]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'x86/spinlocks' into x86/xen
authorIngo Molnar <mingo@elte.hu>
Thu, 31 Jul 2008 10:39:15 +0000 (12:39 +0200)
committerIngo Molnar <mingo@elte.hu>
Thu, 31 Jul 2008 10:39:15 +0000 (12:39 +0200)
3190 files changed:
CREDITS
Documentation/00-INDEX
Documentation/ABI/testing/sysfs-devices-memory [new file with mode: 0644]
Documentation/ABI/testing/sysfs-kernel-mm [new file with mode: 0644]
Documentation/ABI/testing/sysfs-kernel-mm-hugepages [new file with mode: 0644]
Documentation/CodingStyle
Documentation/DMA-API.txt
Documentation/DocBook/kernel-locking.tmpl
Documentation/DocBook/procfs-guide.tmpl
Documentation/Intel-IOMMU.txt
Documentation/SubmittingPatches
Documentation/accounting/delay-accounting.txt
Documentation/accounting/getdelays.c
Documentation/accounting/taskstats-struct.txt
Documentation/arm/Interrupts
Documentation/bt8xxgpio.txt [new file with mode: 0644]
Documentation/controllers/memory.txt
Documentation/cpu-freq/governors.txt
Documentation/edac.txt
Documentation/fb/sh7760fb.txt [new file with mode: 0644]
Documentation/fb/tridentfb.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/Locking
Documentation/filesystems/omfs.txt [new file with mode: 0644]
Documentation/filesystems/proc.txt
Documentation/filesystems/relay.txt
Documentation/filesystems/vfat.txt
Documentation/filesystems/vfs.txt
Documentation/gpio.txt
Documentation/i2c/upgrading-clients [new file with mode: 0644]
Documentation/ia64/kvm.txt
Documentation/input/cs461x.txt
Documentation/ioctl/ioctl-decoding.txt
Documentation/iostats.txt
Documentation/isdn/README.mISDN [new file with mode: 0644]
Documentation/kdump/kdump.txt
Documentation/kernel-parameters.txt
Documentation/keys.txt
Documentation/laptops/thinkpad-acpi.txt
Documentation/leds-class.txt
Documentation/lguest/lguest.c
Documentation/local_ops.txt
Documentation/moxa-smartio
Documentation/networking/bonding.txt
Documentation/networking/can.txt
Documentation/networking/packet_mmap.txt
Documentation/networking/tc-actions-env-rules.txt
Documentation/power/00-INDEX
Documentation/power/apm-acpi.txt [new file with mode: 0644]
Documentation/power/pm.txt [deleted file]
Documentation/powerpc/booting-without-of.txt
Documentation/powerpc/qe_firmware.txt
Documentation/s390/driver-model.txt
Documentation/scsi/ibmmca.txt
Documentation/scsi/lpfc.txt
Documentation/scsi/scsi_fc_transport.txt
Documentation/sh/clk.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/Audiophile-Usb.txt
Documentation/sound/alsa/hda_codec.txt
Documentation/sound/alsa/soc/dapm.txt
Documentation/sparse.txt
Documentation/sysctl/vm.txt
Documentation/timers/highres.txt
Documentation/unaligned-memory-access.txt
Documentation/usb/authorization.txt
Documentation/video4linux/CARDLIST.au0828
Documentation/video4linux/CARDLIST.em28xx
Documentation/video4linux/gspca.txt
Documentation/video4linux/sn9c102.txt
Documentation/vm/hugetlbpage.txt
Documentation/vm/numa_memory_policy.txt
Documentation/volatile-considered-harmful.txt
Kbuild
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/boot/misc.c
arch/alpha/kernel/osf_sys.c
arch/alpha/mm/init.c
arch/alpha/mm/numa.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/compressed/misc.c
arch/arm/common/dmabounce.c
arch/arm/common/locomo.c
arch/arm/common/sa1111.c
arch/arm/configs/eseries_pxa_defconfig
arch/arm/kernel/kprobes.c
arch/arm/kernel/module.c
arch/arm/kernel/process.c
arch/arm/mach-at91/at91cap9_devices.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/board-cam60.c
arch/arm/mach-at91/board-cap9adk.c
arch/arm/mach-at91/board-dk.c
arch/arm/mach-at91/board-kb9202.c
arch/arm/mach-at91/board-sam9-l9260.c
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9rlek.c
arch/arm/mach-at91/board-yl-9200.c [changed mode: 0755->0644]
arch/arm/mach-at91/irq.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-imx/irq.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-ixp23xx/core.c
arch/arm/mach-ixp23xx/roadrunner.c
arch/arm/mach-ixp4xx/avila-pci.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/coyote-pci.c
arch/arm/mach-ixp4xx/dsmg600-pci.c
arch/arm/mach-ixp4xx/fsg-pci.c
arch/arm/mach-ixp4xx/gateway7001-pci.c
arch/arm/mach-ixp4xx/gtwx5715-pci.c
arch/arm/mach-ixp4xx/ixdp425-pci.c
arch/arm/mach-ixp4xx/ixdpg425-pci.c
arch/arm/mach-ixp4xx/nas100d-pci.c
arch/arm/mach-ixp4xx/nslu2-pci.c
arch/arm/mach-ixp4xx/wg302v2-pci.c
arch/arm/mach-ks8695/irq.c
arch/arm/mach-netx/generic.c
arch/arm/mach-ns9xxx/clock.c
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-omap1/board-palmz71.c
arch/arm/mach-omap1/board-voiceblue.c
arch/arm/mach-omap1/fpga.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-orion5x/db88f5281-setup.c
arch/arm/mach-orion5x/irq.c
arch/arm/mach-orion5x/rd88f5182-setup.c
arch/arm/mach-orion5x/ts209-setup.c
arch/arm/mach-pnx4008/irq.c
arch/arm/mach-pxa/cm-x270-pci.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/sharpsl_pm.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-sa1100/cerf.c
arch/arm/mach-sa1100/h3600.c
arch/arm/mach-sa1100/irq.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-sa1100/pleb.c
arch/arm/mm/consistent.c
arch/arm/mm/discontig.c
arch/arm/mm/fault-armv.c
arch/arm/mm/init.c
arch/arm/plat-mxc/gpio.c
arch/arm/plat-omap/fb.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-s3c24xx/Kconfig
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-s3c24xx/irq.c
arch/avr32/Kconfig
arch/avr32/boards/atstk1000/Kconfig
arch/avr32/boards/atstk1000/Makefile
arch/avr32/boards/atstk1000/atstk1002.c
arch/avr32/boards/atstk1000/atstk1003.c
arch/avr32/boards/atstk1000/atstk1004.c
arch/avr32/kernel/process.c
arch/avr32/kernel/stacktrace.c
arch/avr32/kernel/time.c
arch/avr32/mach-at32ap/at32ap700x.c
arch/avr32/mach-at32ap/hsmc.c
arch/avr32/mach-at32ap/pio.c
arch/avr32/mm/init.c
arch/avr32/mm/ioremap.c
arch/blackfin/Kconfig
arch/blackfin/Kconfig.debug
arch/blackfin/Makefile
arch/blackfin/configs/BF527-EZKIT_defconfig
arch/blackfin/configs/BF533-EZKIT_defconfig
arch/blackfin/configs/BF533-STAMP_defconfig
arch/blackfin/configs/BF537-STAMP_defconfig
arch/blackfin/configs/BF548-EZKIT_defconfig
arch/blackfin/configs/BF561-EZKIT_defconfig
arch/blackfin/configs/CM-BF527_defconfig [new file with mode: 0644]
arch/blackfin/configs/CM-BF533_defconfig
arch/blackfin/configs/CM-BF537E_defconfig
arch/blackfin/configs/CM-BF537U_defconfig
arch/blackfin/configs/CM-BF548_defconfig
arch/blackfin/configs/CM-BF561_defconfig
arch/blackfin/configs/H8606_defconfig
arch/blackfin/configs/IP0X_defconfig
arch/blackfin/configs/PNAV-10_defconfig
arch/blackfin/configs/SRV1_defconfig
arch/blackfin/kernel/Makefile
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/kernel/cplb-nompu/cplbhdlr.S
arch/blackfin/kernel/cplb-nompu/cplbinit.c
arch/blackfin/kernel/dualcore_test.c [deleted file]
arch/blackfin/kernel/entry.S
arch/blackfin/kernel/kgdb.c
arch/blackfin/kernel/module.c
arch/blackfin/kernel/process.c
arch/blackfin/kernel/ptrace.c
arch/blackfin/kernel/setup.c
arch/blackfin/kernel/traps.c
arch/blackfin/kernel/vmlinux.lds.S
arch/blackfin/mach-bf527/boards/Kconfig
arch/blackfin/mach-bf527/boards/Makefile
arch/blackfin/mach-bf527/boards/cm_bf527.c [new file with mode: 0644]
arch/blackfin/mach-bf527/head.S
arch/blackfin/mach-bf533/head.S
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/head.S
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/head.S
arch/blackfin/mach-bf561/head.S
arch/blackfin/mach-common/arch_checks.c
arch/blackfin/mach-common/dpmc_modes.S
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/ints-priority.c
arch/blackfin/mach-common/pm.c
arch/blackfin/mm/blackfin_sram.c
arch/blackfin/mm/blackfin_sram.h
arch/blackfin/mm/init.c
arch/cris/arch-v10/boot/compressed/misc.c
arch/cris/arch-v10/kernel/kgdb.c
arch/cris/arch-v10/mm/init.c
arch/cris/arch-v32/boot/compressed/misc.c
arch/cris/arch-v32/drivers/Kconfig
arch/cris/arch-v32/drivers/pci/dma.c
arch/cris/arch-v32/kernel/kgdb.c
arch/cris/arch-v32/mm/init.c
arch/cris/kernel/profile.c
arch/cris/mm/init.c
arch/frv/kernel/gdb-stub.c
arch/frv/kernel/pm.c
arch/frv/mm/init.c
arch/h8300/Kconfig
arch/h8300/boot/compressed/misc.c
arch/h8300/kernel/setup.c
arch/h8300/mm/init.c
arch/ia64/hp/common/hwsw_iommu.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/kprobes.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/sys_ia64.c
arch/ia64/kvm/kvm-ia64.c
arch/ia64/mm/discontig.c
arch/ia64/mm/hugetlbpage.c
arch/ia64/sn/pci/pci_dma.c
arch/m32r/boot/compressed/misc.c
arch/m32r/mm/discontig.c
arch/m32r/mm/init.c
arch/m68k/amiga/chipram.c
arch/m68k/mm/init.c
arch/m68k/mm/motorola.c
arch/m68k/mm/sun3mmu.c
arch/m68knommu/Kconfig
arch/m68knommu/Makefile
arch/m68knommu/configs/m5208evb_defconfig [new file with mode: 0644]
arch/m68knommu/configs/m5249evb_defconfig [new file with mode: 0644]
arch/m68knommu/configs/m5275evb_defconfig [new file with mode: 0644]
arch/m68knommu/configs/m5307c3_defconfig [new file with mode: 0644]
arch/m68knommu/configs/m5407c3_defconfig [new file with mode: 0644]
arch/m68knommu/kernel/setup.c
arch/m68knommu/kernel/time.c
arch/m68knommu/kernel/traps.c
arch/m68knommu/kernel/vmlinux.lds.S
arch/m68knommu/mm/init.c
arch/m68knommu/platform/coldfire/Makefile
arch/m68knommu/platform/coldfire/dma_timer.c [new file with mode: 0644]
arch/m68knommu/platform/coldfire/head.S
arch/m68knommu/platform/coldfire/pit.c
arch/mips/Kconfig
arch/mips/au1000/common/power.c
arch/mips/kernel/linux32.c
arch/mips/kernel/module.c
arch/mips/kernel/process.c
arch/mips/kernel/stacktrace.c
arch/mips/kernel/syscall.c
arch/mips/mm/Makefile
arch/mips/mm/dma-default.c
arch/mips/mm/pgtable.c [deleted file]
arch/mips/sgi-ip27/ip27-klnuma.c
arch/mips/sgi-ip27/ip27-memory.c
arch/mn10300/boot/compressed/misc.c
arch/mn10300/kernel/gdb-stub.c
arch/mn10300/mm/init.c
arch/mn10300/mm/pgtable.c
arch/parisc/hpux/sys_hpux.c
arch/parisc/mm/init.c
arch/powerpc/Kconfig
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/idle.c
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/lparcfg.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/rtas_flash.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/stacktrace.c
arch/powerpc/kernel/suspend.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vio.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/kvm/44x_tlb.c
arch/powerpc/kvm/emulate.c
arch/powerpc/lib/code-patching.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/tlb_64.c
arch/powerpc/platforms/52xx/Kconfig
arch/powerpc/platforms/cell/celleb_scc_pciex.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/spider-pci.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/sputrace.c
arch/powerpc/platforms/iseries/iommu.c
arch/powerpc/platforms/iseries/mf.c
arch/powerpc/platforms/iseries/setup.c
arch/powerpc/platforms/pasemi/iommu.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/udbg_scc.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/Makefile
arch/powerpc/platforms/pseries/cmm.c [new file with mode: 0644]
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/plpar_wrappers.h
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/dart_iommu.c
arch/powerpc/sysdev/qe_lib/Kconfig
arch/s390/Kconfig
arch/s390/kernel/kprobes.c
arch/s390/kernel/process.c
arch/s390/kernel/setup.c
arch/s390/kernel/topology.c
arch/s390/kvm/gaccess.h
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/sigp.c
arch/s390/mm/hugetlbpage.c
arch/s390/mm/init.c
arch/sh/Kconfig
arch/sh/Kconfig.debug
arch/sh/Makefile
arch/sh/boards/dreamcast/rtc.c
arch/sh/boards/renesas/ap325rxa/Makefile [new file with mode: 0644]
arch/sh/boards/renesas/ap325rxa/setup.c [new file with mode: 0644]
arch/sh/boards/renesas/migor/Kconfig [new file with mode: 0644]
arch/sh/boards/renesas/migor/Makefile
arch/sh/boards/renesas/migor/lcd_qvga.c [new file with mode: 0644]
arch/sh/boards/renesas/migor/setup.c
arch/sh/boards/renesas/rsk7203/Makefile [new file with mode: 0644]
arch/sh/boards/renesas/rsk7203/setup.c [new file with mode: 0644]
arch/sh/boards/renesas/sh7763rdp/Makefile [new file with mode: 0644]
arch/sh/boards/renesas/sh7763rdp/irq.c [new file with mode: 0644]
arch/sh/boards/renesas/sh7763rdp/setup.c [new file with mode: 0644]
arch/sh/boards/renesas/sh7785lcr/Makefile [new file with mode: 0644]
arch/sh/boards/renesas/sh7785lcr/setup.c [new file with mode: 0644]
arch/sh/boards/se/7343/irq.c
arch/sh/boards/se/7343/setup.c
arch/sh/boards/se/770x/io.c
arch/sh/boards/se/770x/setup.c
arch/sh/boards/se/7722/setup.c
arch/sh/boot/Makefile
arch/sh/boot/compressed/Makefile_32
arch/sh/boot/compressed/Makefile_64
arch/sh/boot/compressed/misc_32.c
arch/sh/boot/compressed/misc_64.c
arch/sh/boot/compressed/piggy.S [new file with mode: 0644]
arch/sh/boot/compressed/vmlinux.scr [deleted file]
arch/sh/configs/ap325rxa_defconfig [new file with mode: 0644]
arch/sh/configs/se7343_defconfig
arch/sh/configs/se7712_defconfig
arch/sh/configs/sh7763rdp_defconfig [new file with mode: 0644]
arch/sh/configs/sh7785lcr_defconfig [new file with mode: 0644]
arch/sh/drivers/pci/Makefile
arch/sh/drivers/pci/fixups-sh7785lcr.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-dreamcast.c
arch/sh/drivers/pci/ops-sh7785lcr.c [new file with mode: 0644]
arch/sh/drivers/pci/pci-auto.c
arch/sh/drivers/pci/pci.c
arch/sh/kernel/Makefile_32
arch/sh/kernel/cf-enabler.c
arch/sh/kernel/cpu/clock.c
arch/sh/kernel/cpu/irq/intc.c
arch/sh/kernel/cpu/sh2/entry.S
arch/sh/kernel/cpu/sh2/ex.S
arch/sh/kernel/cpu/sh2/setup-sh7619.c
arch/sh/kernel/cpu/sh2a/Makefile
arch/sh/kernel/cpu/sh2a/entry.S [new file with mode: 0644]
arch/sh/kernel/cpu/sh2a/ex.S [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/ex.S
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4a/Makefile
arch/sh/kernel/cpu/sh4a/clock-sh7343.c [deleted file]
arch/sh/kernel/cpu/sh4a/clock-sh7722.c
arch/sh/kernel/cpu/sh4a/setup-sh7343.c
arch/sh/kernel/cpu/sh4a/setup-sh7366.c
arch/sh/kernel/cpu/sh4a/setup-sh7722.c
arch/sh/kernel/cpu/sh4a/setup-sh7723.c
arch/sh/kernel/cpu/sh4a/setup-sh7763.c
arch/sh/kernel/cpu/sh4a/setup-sh7780.c
arch/sh/kernel/cpu/sh4a/setup-sh7785.c
arch/sh/kernel/entry-common.S
arch/sh/kernel/machine_kexec.c
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/setup.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/stacktrace.c
arch/sh/kernel/sys_sh32.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sh/kernel/time_32.c
arch/sh/kernel/timers/timer-tmu.c
arch/sh/kernel/traps_32.c
arch/sh/lib/Makefile
arch/sh/mm/Kconfig
arch/sh/mm/cache-debugfs.c
arch/sh/mm/cache-sh4.c
arch/sh/mm/consistent.c
arch/sh/mm/fault_32.c
arch/sh/mm/hugetlbpage.c
arch/sh/mm/init.c
arch/sh/mm/numa.c
arch/sh/mm/pg-sh4.c
arch/sh/mm/pg-sh7705.c
arch/sh/mm/pmb.c
arch/sh/tools/mach-types
arch/sparc/Kconfig
arch/sparc/include/asm/Kbuild [new file with mode: 0644]
arch/sparc/include/asm/agp.h [moved from include/asm-sparc/agp.h with 100% similarity]
arch/sparc/include/asm/apb.h [moved from include/asm-sparc/apb.h with 100% similarity]
arch/sparc/include/asm/apc.h [moved from include/asm-sparc/apc.h with 100% similarity]
arch/sparc/include/asm/asi.h [moved from include/asm-sparc/asi.h with 100% similarity]
arch/sparc/include/asm/asmmacro.h [moved from include/asm-sparc/asmmacro.h with 100% similarity]
arch/sparc/include/asm/atomic.h [moved from include/asm-sparc/atomic.h with 65% similarity]
arch/sparc/include/asm/atomic_32.h [moved from include/asm-sparc/atomic_32.h with 100% similarity]
arch/sparc/include/asm/atomic_64.h [moved from include/asm-sparc/atomic_64.h with 100% similarity]
arch/sparc/include/asm/auxio.h [moved from include/asm-sparc/auxio.h with 65% similarity]
arch/sparc/include/asm/auxio_32.h [moved from include/asm-sparc/auxio_32.h with 97% similarity]
arch/sparc/include/asm/auxio_64.h [moved from include/asm-sparc/auxio_64.h with 100% similarity]
arch/sparc/include/asm/auxvec.h [moved from include/asm-sparc/auxvec.h with 100% similarity]
arch/sparc/include/asm/backoff.h [moved from include/asm-sparc/backoff.h with 100% similarity]
arch/sparc/include/asm/bbc.h [moved from include/asm-sparc/bbc.h with 100% similarity]
arch/sparc/include/asm/bitext.h [moved from include/asm-sparc/bitext.h with 100% similarity]
arch/sparc/include/asm/bitops.h [moved from include/asm-sparc/bitops.h with 65% similarity]
arch/sparc/include/asm/bitops_32.h [moved from include/asm-sparc/bitops_32.h with 100% similarity]
arch/sparc/include/asm/bitops_64.h [moved from include/asm-sparc/bitops_64.h with 100% similarity]
arch/sparc/include/asm/bpp.h [moved from include/asm-sparc/bpp.h with 100% similarity]
arch/sparc/include/asm/btfixup.h [moved from include/asm-sparc/btfixup.h with 99% similarity]
arch/sparc/include/asm/bug.h [moved from include/asm-sparc/bug.h with 100% similarity]
arch/sparc/include/asm/bugs.h [moved from include/asm-sparc/bugs.h with 87% similarity]
arch/sparc/include/asm/byteorder.h [moved from include/asm-sparc/byteorder.h with 100% similarity]
arch/sparc/include/asm/cache.h [moved from include/asm-sparc/cache.h with 100% similarity]
arch/sparc/include/asm/cacheflush.h [moved from include/asm-sparc/cacheflush.h with 64% similarity]
arch/sparc/include/asm/cacheflush_32.h [moved from include/asm-sparc/cacheflush_32.h with 100% similarity]
arch/sparc/include/asm/cacheflush_64.h [moved from include/asm-sparc/cacheflush_64.h with 100% similarity]
arch/sparc/include/asm/chafsr.h [moved from include/asm-sparc/chafsr.h with 100% similarity]
arch/sparc/include/asm/checksum.h [moved from include/asm-sparc/checksum.h with 65% similarity]
arch/sparc/include/asm/checksum_32.h [moved from include/asm-sparc/checksum_32.h with 100% similarity]
arch/sparc/include/asm/checksum_64.h [moved from include/asm-sparc/checksum_64.h with 100% similarity]
arch/sparc/include/asm/chmctrl.h [moved from include/asm-sparc/chmctrl.h with 100% similarity]
arch/sparc/include/asm/clock.h [moved from include/asm-sparc/clock.h with 100% similarity]
arch/sparc/include/asm/cmt.h [moved from include/asm-sparc/cmt.h with 100% similarity]
arch/sparc/include/asm/compat.h [moved from include/asm-sparc/compat.h with 100% similarity]
arch/sparc/include/asm/compat_signal.h [moved from include/asm-sparc/compat_signal.h with 100% similarity]
arch/sparc/include/asm/contregs.h [moved from include/asm-sparc/contregs.h with 100% similarity]
arch/sparc/include/asm/cpudata.h [moved from include/asm-sparc/cpudata.h with 65% similarity]
arch/sparc/include/asm/cpudata_32.h [moved from include/asm-sparc/cpudata_32.h with 89% similarity]
arch/sparc/include/asm/cpudata_64.h [moved from include/asm-sparc/cpudata_64.h with 100% similarity]
arch/sparc/include/asm/cputime.h [moved from include/asm-sparc/cputime.h with 100% similarity]
arch/sparc/include/asm/current.h [moved from include/asm-sparc/current.h with 96% similarity]
arch/sparc/include/asm/cypress.h [moved from include/asm-sparc/cypress.h with 100% similarity]
arch/sparc/include/asm/dcr.h [moved from include/asm-sparc/dcr.h with 100% similarity]
arch/sparc/include/asm/dcu.h [moved from include/asm-sparc/dcu.h with 100% similarity]
arch/sparc/include/asm/delay.h [moved from include/asm-sparc/delay.h with 65% similarity]
arch/sparc/include/asm/delay_32.h [moved from include/asm-sparc/delay_32.h with 100% similarity]
arch/sparc/include/asm/delay_64.h [moved from include/asm-sparc/delay_64.h with 100% similarity]
arch/sparc/include/asm/device.h [moved from include/asm-sparc/device.h with 100% similarity]
arch/sparc/include/asm/display7seg.h [moved from include/asm-sparc/display7seg.h with 100% similarity]
arch/sparc/include/asm/div64.h [moved from include/asm-sparc/div64.h with 100% similarity]
arch/sparc/include/asm/dma-mapping.h [moved from include/asm-sparc/dma-mapping.h with 64% similarity]
arch/sparc/include/asm/dma-mapping_32.h [moved from include/asm-sparc/dma-mapping_32.h with 100% similarity]
arch/sparc/include/asm/dma-mapping_64.h [moved from include/asm-sparc/dma-mapping_64.h with 98% similarity]
arch/sparc/include/asm/dma.h [moved from include/asm-sparc/dma.h with 66% similarity]
arch/sparc/include/asm/dma_32.h [moved from include/asm-sparc/dma_32.h with 99% similarity]
arch/sparc/include/asm/dma_64.h [moved from include/asm-sparc/dma_64.h with 99% similarity]
arch/sparc/include/asm/ebus.h [moved from include/asm-sparc/ebus.h with 66% similarity]
arch/sparc/include/asm/ebus_32.h [moved from include/asm-sparc/ebus_32.h with 100% similarity]
arch/sparc/include/asm/ebus_64.h [moved from include/asm-sparc/ebus_64.h with 100% similarity]
arch/sparc/include/asm/ecc.h [moved from include/asm-sparc/ecc.h with 100% similarity]
arch/sparc/include/asm/eeprom.h [moved from include/asm-sparc/eeprom.h with 100% similarity]
arch/sparc/include/asm/elf.h [moved from include/asm-sparc/elf.h with 66% similarity]
arch/sparc/include/asm/elf_32.h [moved from include/asm-sparc/elf_32.h with 100% similarity]
arch/sparc/include/asm/elf_64.h [moved from include/asm-sparc/elf_64.h with 100% similarity]
arch/sparc/include/asm/emergency-restart.h [moved from include/asm-sparc/emergency-restart.h with 100% similarity]
arch/sparc/include/asm/envctrl.h [moved from include/asm-sparc/envctrl.h with 100% similarity]
arch/sparc/include/asm/errno.h [moved from include/asm-sparc/errno.h with 100% similarity]
arch/sparc/include/asm/estate.h [moved from include/asm-sparc/estate.h with 100% similarity]
arch/sparc/include/asm/fb.h [moved from include/asm-sparc/fb.h with 100% similarity]
arch/sparc/include/asm/fbio.h [moved from include/asm-sparc/fbio.h with 100% similarity]
arch/sparc/include/asm/fcntl.h [moved from include/asm-sparc/fcntl.h with 100% similarity]
arch/sparc/include/asm/fhc.h [moved from include/asm-sparc/fhc.h with 100% similarity]
arch/sparc/include/asm/fixmap.h [moved from include/asm-sparc/fixmap.h with 100% similarity]
arch/sparc/include/asm/floppy.h [moved from include/asm-sparc/floppy.h with 65% similarity]
arch/sparc/include/asm/floppy_32.h [moved from include/asm-sparc/floppy_32.h with 99% similarity]
arch/sparc/include/asm/floppy_64.h [moved from include/asm-sparc/floppy_64.h with 100% similarity]
arch/sparc/include/asm/fpumacro.h [moved from include/asm-sparc/fpumacro.h with 100% similarity]
arch/sparc/include/asm/ftrace.h [moved from include/asm-sparc64/ftrace.h with 100% similarity]
arch/sparc/include/asm/futex.h [moved from include/asm-sparc/futex.h with 65% similarity]
arch/sparc/include/asm/futex_32.h [moved from include/asm-sparc/futex_32.h with 100% similarity]
arch/sparc/include/asm/futex_64.h [moved from include/asm-sparc/futex_64.h with 100% similarity]
arch/sparc/include/asm/hardirq.h [moved from include/asm-sparc/hardirq.h with 65% similarity]
arch/sparc/include/asm/hardirq_32.h [moved from include/asm-sparc/hardirq_32.h with 100% similarity]
arch/sparc/include/asm/hardirq_64.h [moved from include/asm-sparc/hardirq_64.h with 100% similarity]
arch/sparc/include/asm/head.h [moved from include/asm-sparc/head.h with 66% similarity]
arch/sparc/include/asm/head_32.h [moved from include/asm-sparc/head_32.h with 100% similarity]
arch/sparc/include/asm/head_64.h [moved from include/asm-sparc/head_64.h with 100% similarity]
arch/sparc/include/asm/highmem.h [moved from include/asm-sparc/highmem.h with 100% similarity]
arch/sparc/include/asm/hugetlb.h [moved from include/asm-sparc/hugetlb.h with 91% similarity]
arch/sparc/include/asm/hvtramp.h [moved from include/asm-sparc/hvtramp.h with 100% similarity]
arch/sparc/include/asm/hw_irq.h [moved from include/asm-sparc/hw_irq.h with 100% similarity]
arch/sparc/include/asm/hypervisor.h [moved from include/asm-sparc/hypervisor.h with 100% similarity]
arch/sparc/include/asm/ide.h [moved from include/asm-sparc/ide.h with 98% similarity]
arch/sparc/include/asm/idprom.h [moved from include/asm-sparc/idprom.h with 100% similarity]
arch/sparc/include/asm/intr_queue.h [moved from include/asm-sparc/intr_queue.h with 100% similarity]
arch/sparc/include/asm/io-unit.h [moved from include/asm-sparc/io-unit.h with 100% similarity]
arch/sparc/include/asm/io.h [moved from include/asm-sparc/io.h with 67% similarity]
arch/sparc/include/asm/io_32.h [moved from include/asm-sparc/io_32.h with 100% similarity]
arch/sparc/include/asm/io_64.h [moved from include/asm-sparc/io_64.h with 100% similarity]
arch/sparc/include/asm/ioctl.h [moved from include/asm-sparc/ioctl.h with 100% similarity]
arch/sparc/include/asm/ioctls.h [moved from include/asm-sparc/ioctls.h with 100% similarity]
arch/sparc/include/asm/iommu.h [moved from include/asm-sparc/iommu.h with 65% similarity]
arch/sparc/include/asm/iommu_32.h [moved from include/asm-sparc/iommu_32.h with 100% similarity]
arch/sparc/include/asm/iommu_64.h [moved from include/asm-sparc/iommu_64.h with 100% similarity]
arch/sparc/include/asm/ipcbuf.h [moved from include/asm-sparc/ipcbuf.h with 65% similarity]
arch/sparc/include/asm/ipcbuf_32.h [moved from include/asm-sparc/ipcbuf_32.h with 100% similarity]
arch/sparc/include/asm/ipcbuf_64.h [moved from include/asm-sparc/ipcbuf_64.h with 100% similarity]
arch/sparc/include/asm/irq.h [moved from include/asm-sparc/irq.h with 66% similarity]
arch/sparc/include/asm/irq_32.h [moved from include/asm-sparc/irq_32.h with 100% similarity]
arch/sparc/include/asm/irq_64.h [moved from include/asm-sparc/irq_64.h with 100% similarity]
arch/sparc/include/asm/irq_regs.h [moved from include/asm-sparc/irq_regs.h with 100% similarity]
arch/sparc/include/asm/irqflags.h [moved from include/asm-sparc/irqflags.h with 65% similarity]
arch/sparc/include/asm/irqflags_32.h [moved from include/asm-sparc/irqflags_32.h with 96% similarity]
arch/sparc/include/asm/irqflags_64.h [moved from include/asm-sparc/irqflags_64.h with 97% similarity]
arch/sparc/include/asm/jsflash.h [moved from include/asm-sparc/jsflash.h with 100% similarity]
arch/sparc/include/asm/kdebug.h [moved from include/asm-sparc/kdebug.h with 65% similarity]
arch/sparc/include/asm/kdebug_32.h [moved from include/asm-sparc/kdebug_32.h with 100% similarity]
arch/sparc/include/asm/kdebug_64.h [moved from include/asm-sparc/kdebug_64.h with 100% similarity]
arch/sparc/include/asm/kgdb.h [moved from include/asm-sparc/kgdb.h with 100% similarity]
arch/sparc/include/asm/kmap_types.h [moved from include/asm-sparc/kmap_types.h with 100% similarity]
arch/sparc/include/asm/kprobes.h [moved from include/asm-sparc/kprobes.h with 100% similarity]
arch/sparc/include/asm/ldc.h [moved from include/asm-sparc/ldc.h with 100% similarity]
arch/sparc/include/asm/linkage.h [moved from include/asm-sparc/linkage.h with 100% similarity]
arch/sparc/include/asm/lmb.h [moved from include/asm-sparc/lmb.h with 100% similarity]
arch/sparc/include/asm/local.h [moved from include/asm-sparc/local.h with 100% similarity]
arch/sparc/include/asm/lsu.h [moved from include/asm-sparc/lsu.h with 100% similarity]
arch/sparc/include/asm/machines.h [moved from include/asm-sparc/machines.h with 100% similarity]
arch/sparc/include/asm/mbus.h [moved from include/asm-sparc/mbus.h with 100% similarity]
arch/sparc/include/asm/mc146818rtc.h [moved from include/asm-sparc/mc146818rtc.h with 64% similarity]
arch/sparc/include/asm/mc146818rtc_32.h [moved from include/asm-sparc/mc146818rtc_32.h with 100% similarity]
arch/sparc/include/asm/mc146818rtc_64.h [moved from include/asm-sparc/mc146818rtc_64.h with 100% similarity]
arch/sparc/include/asm/mdesc.h [moved from include/asm-sparc/mdesc.h with 100% similarity]
arch/sparc/include/asm/memreg.h [moved from include/asm-sparc/memreg.h with 100% similarity]
arch/sparc/include/asm/mman.h [moved from include/asm-sparc/mman.h with 100% similarity]
arch/sparc/include/asm/mmu.h [moved from include/asm-sparc/mmu.h with 66% similarity]
arch/sparc/include/asm/mmu_32.h [moved from include/asm-sparc/mmu_32.h with 100% similarity]
arch/sparc/include/asm/mmu_64.h [moved from include/asm-sparc/mmu_64.h with 100% similarity]
arch/sparc/include/asm/mmu_context.h [moved from include/asm-sparc/mmu_context.h with 64% similarity]
arch/sparc/include/asm/mmu_context_32.h [moved from include/asm-sparc/mmu_context_32.h with 100% similarity]
arch/sparc/include/asm/mmu_context_64.h [moved from include/asm-sparc/mmu_context_64.h with 100% similarity]
arch/sparc/include/asm/mmzone.h [moved from include/asm-sparc/mmzone.h with 100% similarity]
arch/sparc/include/asm/module.h [moved from include/asm-sparc/module.h with 65% similarity]
arch/sparc/include/asm/module_32.h [moved from include/asm-sparc/module_32.h with 100% similarity]
arch/sparc/include/asm/module_64.h [moved from include/asm-sparc/module_64.h with 100% similarity]
arch/sparc/include/asm/mostek.h [moved from include/asm-sparc/mostek.h with 65% similarity]
arch/sparc/include/asm/mostek_32.h [moved from include/asm-sparc/mostek_32.h with 100% similarity]
arch/sparc/include/asm/mostek_64.h [moved from include/asm-sparc/mostek_64.h with 100% similarity]
arch/sparc/include/asm/mpmbox.h [moved from include/asm-sparc/mpmbox.h with 100% similarity]
arch/sparc/include/asm/msgbuf.h [moved from include/asm-sparc/msgbuf.h with 100% similarity]
arch/sparc/include/asm/msi.h [moved from include/asm-sparc/msi.h with 100% similarity]
arch/sparc/include/asm/mutex.h [moved from include/asm-sparc/mutex.h with 100% similarity]
arch/sparc/include/asm/mxcc.h [moved from include/asm-sparc/mxcc.h with 100% similarity]
arch/sparc/include/asm/ns87303.h [moved from include/asm-sparc/ns87303.h with 100% similarity]
arch/sparc/include/asm/obio.h [moved from include/asm-sparc/obio.h with 100% similarity]
arch/sparc/include/asm/of_device.h [moved from include/asm-sparc/of_device.h with 100% similarity]
arch/sparc/include/asm/of_platform.h [moved from include/asm-sparc/of_platform.h with 64% similarity]
arch/sparc/include/asm/of_platform_32.h [moved from include/asm-sparc/of_platform_32.h with 91% similarity]
arch/sparc/include/asm/of_platform_64.h [moved from include/asm-sparc/of_platform_64.h with 91% similarity]
arch/sparc/include/asm/openprom.h [moved from include/asm-sparc/openprom.h with 65% similarity]
arch/sparc/include/asm/openprom_32.h [moved from include/asm-sparc/openprom_32.h with 100% similarity]
arch/sparc/include/asm/openprom_64.h [moved from include/asm-sparc/openprom_64.h with 100% similarity]
arch/sparc/include/asm/openpromio.h [moved from include/asm-sparc/openpromio.h with 100% similarity]
arch/sparc/include/asm/oplib.h [moved from include/asm-sparc/oplib.h with 65% similarity]
arch/sparc/include/asm/oplib_32.h [moved from include/asm-sparc/oplib_32.h with 100% similarity]
arch/sparc/include/asm/oplib_64.h [moved from include/asm-sparc/oplib_64.h with 100% similarity]
arch/sparc/include/asm/page.h [moved from include/asm-sparc/page.h with 66% similarity]
arch/sparc/include/asm/page_32.h [moved from include/asm-sparc/page_32.h with 97% similarity]
arch/sparc/include/asm/page_64.h [moved from include/asm-sparc/page_64.h with 97% similarity]
arch/sparc/include/asm/param.h [moved from include/asm-sparc/param.h with 100% similarity]
arch/sparc/include/asm/parport.h [moved from include/asm-sparc/parport.h with 100% similarity]
arch/sparc/include/asm/pbm.h [moved from include/asm-sparc/pbm.h with 100% similarity]
arch/sparc/include/asm/pci.h [moved from include/asm-sparc/pci.h with 66% similarity]
arch/sparc/include/asm/pci_32.h [moved from include/asm-sparc/pci_32.h with 98% similarity]
arch/sparc/include/asm/pci_64.h [moved from include/asm-sparc/pci_64.h with 97% similarity]
arch/sparc/include/asm/pcic.h [moved from include/asm-sparc/pcic.h with 100% similarity]
arch/sparc/include/asm/percpu.h [moved from include/asm-sparc/percpu.h with 65% similarity]
arch/sparc/include/asm/percpu_32.h [moved from include/asm-sparc/percpu_32.h with 100% similarity]
arch/sparc/include/asm/percpu_64.h [moved from include/asm-sparc/percpu_64.h with 100% similarity]
arch/sparc/include/asm/perfctr.h [moved from include/asm-sparc/perfctr.h with 100% similarity]
arch/sparc/include/asm/pgalloc.h [moved from include/asm-sparc/pgalloc.h with 65% similarity]
arch/sparc/include/asm/pgalloc_32.h [moved from include/asm-sparc/pgalloc_32.h with 100% similarity]
arch/sparc/include/asm/pgalloc_64.h [moved from include/asm-sparc/pgalloc_64.h with 100% similarity]
arch/sparc/include/asm/pgtable.h [moved from include/asm-sparc/pgtable.h with 65% similarity]
arch/sparc/include/asm/pgtable_32.h [moved from include/asm-sparc/pgtable_32.h with 99% similarity]
arch/sparc/include/asm/pgtable_64.h [moved from include/asm-sparc/pgtable_64.h with 100% similarity]
arch/sparc/include/asm/pgtsrmmu.h [moved from include/asm-sparc/pgtsrmmu.h with 100% similarity]
arch/sparc/include/asm/pgtsun4.h [moved from include/asm-sparc/pgtsun4.h with 100% similarity]
arch/sparc/include/asm/pgtsun4c.h [moved from include/asm-sparc/pgtsun4c.h with 100% similarity]
arch/sparc/include/asm/pil.h [moved from include/asm-sparc/pil.h with 100% similarity]
arch/sparc/include/asm/poll.h [moved from include/asm-sparc/poll.h with 100% similarity]
arch/sparc/include/asm/posix_types.h [moved from include/asm-sparc/posix_types.h with 64% similarity]
arch/sparc/include/asm/posix_types_32.h [moved from include/asm-sparc/posix_types_32.h with 100% similarity]
arch/sparc/include/asm/posix_types_64.h [moved from include/asm-sparc/posix_types_64.h with 100% similarity]
arch/sparc/include/asm/processor.h [moved from include/asm-sparc/processor.h with 64% similarity]
arch/sparc/include/asm/processor_32.h [moved from include/asm-sparc/processor_32.h with 97% similarity]
arch/sparc/include/asm/processor_64.h [moved from include/asm-sparc/processor_64.h with 99% similarity]
arch/sparc/include/asm/prom.h [moved from include/asm-sparc/prom.h with 100% similarity]
arch/sparc/include/asm/psr.h [moved from include/asm-sparc/psr.h with 100% similarity]
arch/sparc/include/asm/psrcompat.h [moved from include/asm-sparc/psrcompat.h with 100% similarity]
arch/sparc/include/asm/pstate.h [moved from include/asm-sparc/pstate.h with 100% similarity]
arch/sparc/include/asm/ptrace.h [moved from include/asm-sparc/ptrace.h with 65% similarity]
arch/sparc/include/asm/ptrace_32.h [moved from include/asm-sparc/ptrace_32.h with 98% similarity]
arch/sparc/include/asm/ptrace_64.h [moved from include/asm-sparc/ptrace_64.h with 99% similarity]
arch/sparc/include/asm/reboot.h [moved from include/asm-sparc/reboot.h with 100% similarity]
arch/sparc/include/asm/reg.h [moved from include/asm-sparc/reg.h with 66% similarity]
arch/sparc/include/asm/reg_32.h [moved from include/asm-sparc/reg_32.h with 98% similarity]
arch/sparc/include/asm/reg_64.h [moved from include/asm-sparc/reg_64.h with 97% similarity]
arch/sparc/include/asm/resource.h [moved from include/asm-sparc/resource.h with 100% similarity]
arch/sparc/include/asm/ross.h [moved from include/asm-sparc/ross.h with 100% similarity]
arch/sparc/include/asm/rtc.h [moved from include/asm-sparc/rtc.h with 100% similarity]
arch/sparc/include/asm/rwsem-const.h [moved from include/asm-sparc/rwsem-const.h with 100% similarity]
arch/sparc/include/asm/rwsem.h [moved from include/asm-sparc/rwsem.h with 100% similarity]
arch/sparc/include/asm/sbi.h [moved from include/asm-sparc/sbi.h with 100% similarity]
arch/sparc/include/asm/sbus.h [moved from include/asm-sparc/sbus.h with 66% similarity]
arch/sparc/include/asm/sbus_32.h [moved from include/asm-sparc/sbus_32.h with 100% similarity]
arch/sparc/include/asm/sbus_64.h [moved from include/asm-sparc/sbus_64.h with 100% similarity]
arch/sparc/include/asm/scatterlist.h [moved from include/asm-sparc/scatterlist.h with 64% similarity]
arch/sparc/include/asm/scatterlist_32.h [moved from include/asm-sparc/scatterlist_32.h with 100% similarity]
arch/sparc/include/asm/scatterlist_64.h [moved from include/asm-sparc/scatterlist_64.h with 100% similarity]
arch/sparc/include/asm/scratchpad.h [moved from include/asm-sparc/scratchpad.h with 100% similarity]
arch/sparc/include/asm/seccomp.h [moved from include/asm-sparc/seccomp.h with 100% similarity]
arch/sparc/include/asm/sections.h [moved from include/asm-sparc/sections.h with 65% similarity]
arch/sparc/include/asm/sections_32.h [moved from include/asm-sparc/sections_32.h with 100% similarity]
arch/sparc/include/asm/sections_64.h [moved from include/asm-sparc/sections_64.h with 100% similarity]
arch/sparc/include/asm/sembuf.h [moved from include/asm-sparc/sembuf.h with 100% similarity]
arch/sparc/include/asm/setup.h [moved from include/asm-sparc/setup.h with 100% similarity]
arch/sparc/include/asm/sfafsr.h [moved from include/asm-sparc/sfafsr.h with 100% similarity]
arch/sparc/include/asm/sfp-machine.h [moved from include/asm-sparc/sfp-machine.h with 64% similarity]
arch/sparc/include/asm/sfp-machine_32.h [moved from include/asm-sparc/sfp-machine_32.h with 100% similarity]
arch/sparc/include/asm/sfp-machine_64.h [moved from include/asm-sparc/sfp-machine_64.h with 100% similarity]
arch/sparc/include/asm/shmbuf.h [moved from include/asm-sparc/shmbuf.h with 100% similarity]
arch/sparc/include/asm/shmparam.h [moved from include/asm-sparc/shmparam.h with 65% similarity]
arch/sparc/include/asm/shmparam_32.h [moved from include/asm-sparc/shmparam_32.h with 100% similarity]
arch/sparc/include/asm/shmparam_64.h [moved from include/asm-sparc/shmparam_64.h with 100% similarity]
arch/sparc/include/asm/sigcontext.h [moved from include/asm-sparc/sigcontext.h with 64% similarity]
arch/sparc/include/asm/sigcontext_32.h [moved from include/asm-sparc/sigcontext_32.h with 100% similarity]
arch/sparc/include/asm/sigcontext_64.h [moved from include/asm-sparc/sigcontext_64.h with 100% similarity]
arch/sparc/include/asm/siginfo.h [moved from include/asm-sparc/siginfo.h with 65% similarity]
arch/sparc/include/asm/siginfo_32.h [moved from include/asm-sparc/siginfo_32.h with 100% similarity]
arch/sparc/include/asm/siginfo_64.h [moved from include/asm-sparc/siginfo_64.h with 100% similarity]
arch/sparc/include/asm/signal.h [moved from include/asm-sparc/signal.h with 65% similarity]
arch/sparc/include/asm/signal_32.h [moved from include/asm-sparc/signal_32.h with 100% similarity]
arch/sparc/include/asm/signal_64.h [moved from include/asm-sparc/signal_64.h with 100% similarity]
arch/sparc/include/asm/smp.h [moved from include/asm-sparc/smp.h with 66% similarity]
arch/sparc/include/asm/smp_32.h [moved from include/asm-sparc/smp_32.h with 100% similarity]
arch/sparc/include/asm/smp_64.h [moved from include/asm-sparc/smp_64.h with 100% similarity]
arch/sparc/include/asm/smpprim.h [moved from include/asm-sparc/smpprim.h with 100% similarity]
arch/sparc/include/asm/socket.h [moved from include/asm-sparc/socket.h with 100% similarity]
arch/sparc/include/asm/sockios.h [moved from include/asm-sparc/sockios.h with 100% similarity]
arch/sparc/include/asm/sparsemem.h [moved from include/asm-sparc/sparsemem.h with 100% similarity]
arch/sparc/include/asm/spinlock.h [moved from include/asm-sparc/spinlock.h with 65% similarity]
arch/sparc/include/asm/spinlock_32.h [moved from include/asm-sparc/spinlock_32.h with 100% similarity]
arch/sparc/include/asm/spinlock_64.h [moved from include/asm-sparc/spinlock_64.h with 100% similarity]
arch/sparc/include/asm/spinlock_types.h [moved from include/asm-sparc/spinlock_types.h with 100% similarity]
arch/sparc/include/asm/spitfire.h [moved from include/asm-sparc/spitfire.h with 100% similarity]
arch/sparc/include/asm/sstate.h [moved from include/asm-sparc/sstate.h with 100% similarity]
arch/sparc/include/asm/stacktrace.h [moved from include/asm-sparc/stacktrace.h with 100% similarity]
arch/sparc/include/asm/starfire.h [moved from include/asm-sparc/starfire.h with 100% similarity]
arch/sparc/include/asm/stat.h [moved from include/asm-sparc/stat.h with 66% similarity]
arch/sparc/include/asm/stat_32.h [moved from include/asm-sparc/stat_32.h with 100% similarity]
arch/sparc/include/asm/stat_64.h [moved from include/asm-sparc/stat_64.h with 100% similarity]
arch/sparc/include/asm/statfs.h [moved from include/asm-sparc/statfs.h with 65% similarity]
arch/sparc/include/asm/statfs_32.h [moved from include/asm-sparc/statfs_32.h with 100% similarity]
arch/sparc/include/asm/statfs_64.h [moved from include/asm-sparc/statfs_64.h with 100% similarity]
arch/sparc/include/asm/string.h [moved from include/asm-sparc/string.h with 65% similarity]
arch/sparc/include/asm/string_32.h [moved from include/asm-sparc/string_32.h with 100% similarity]
arch/sparc/include/asm/string_64.h [moved from include/asm-sparc/string_64.h with 100% similarity]
arch/sparc/include/asm/sun4paddr.h [moved from include/asm-sparc/sun4paddr.h with 100% similarity]
arch/sparc/include/asm/sun4prom.h [moved from include/asm-sparc/sun4prom.h with 100% similarity]
arch/sparc/include/asm/sunbpp.h [moved from include/asm-sparc/sunbpp.h with 99% similarity]
arch/sparc/include/asm/swift.h [moved from include/asm-sparc/swift.h with 100% similarity]
arch/sparc/include/asm/syscall.h [new file with mode: 0644]
arch/sparc/include/asm/syscalls.h [moved from include/asm-sparc/syscalls.h with 100% similarity]
arch/sparc/include/asm/sysen.h [moved from include/asm-sparc/sysen.h with 100% similarity]
arch/sparc/include/asm/system.h [moved from include/asm-sparc/system.h with 65% similarity]
arch/sparc/include/asm/system_32.h [moved from include/asm-sparc/system_32.h with 100% similarity]
arch/sparc/include/asm/system_64.h [moved from include/asm-sparc/system_64.h with 100% similarity]
arch/sparc/include/asm/termbits.h [moved from include/asm-sparc/termbits.h with 100% similarity]
arch/sparc/include/asm/termios.h [moved from include/asm-sparc/termios.h with 100% similarity]
arch/sparc/include/asm/thread_info.h [moved from include/asm-sparc/thread_info.h with 64% similarity]
arch/sparc/include/asm/thread_info_32.h [moved from include/asm-sparc/thread_info_32.h with 94% similarity]
arch/sparc/include/asm/thread_info_64.h [moved from include/asm-sparc/thread_info_64.h with 96% similarity]
arch/sparc/include/asm/timer.h [moved from include/asm-sparc/timer.h with 65% similarity]
arch/sparc/include/asm/timer_32.h [moved from include/asm-sparc/timer_32.h with 100% similarity]
arch/sparc/include/asm/timer_64.h [moved from include/asm-sparc/timer_64.h with 100% similarity]
arch/sparc/include/asm/timex.h [moved from include/asm-sparc/timex.h with 65% similarity]
arch/sparc/include/asm/timex_32.h [moved from include/asm-sparc/timex_32.h with 89% similarity]
arch/sparc/include/asm/timex_64.h [moved from include/asm-sparc/timex_64.h with 90% similarity]
arch/sparc/include/asm/tlb.h [moved from include/asm-sparc/tlb.h with 66% similarity]
arch/sparc/include/asm/tlb_32.h [moved from include/asm-sparc/tlb_32.h with 100% similarity]
arch/sparc/include/asm/tlb_64.h [moved from include/asm-sparc/tlb_64.h with 100% similarity]
arch/sparc/include/asm/tlbflush.h [moved from include/asm-sparc/tlbflush.h with 65% similarity]
arch/sparc/include/asm/tlbflush_32.h [moved from include/asm-sparc/tlbflush_32.h with 100% similarity]
arch/sparc/include/asm/tlbflush_64.h [moved from include/asm-sparc/tlbflush_64.h with 100% similarity]
arch/sparc/include/asm/topology.h [moved from include/asm-sparc/topology.h with 65% similarity]
arch/sparc/include/asm/topology_32.h [moved from include/asm-sparc/topology_32.h with 100% similarity]
arch/sparc/include/asm/topology_64.h [moved from include/asm-sparc/topology_64.h with 100% similarity]
arch/sparc/include/asm/traps.h [moved from include/asm-sparc/traps.h with 100% similarity]
arch/sparc/include/asm/tsb.h [moved from include/asm-sparc/tsb.h with 100% similarity]
arch/sparc/include/asm/tsunami.h [moved from include/asm-sparc/tsunami.h with 100% similarity]
arch/sparc/include/asm/ttable.h [moved from include/asm-sparc/ttable.h with 100% similarity]
arch/sparc/include/asm/turbosparc.h [moved from include/asm-sparc/turbosparc.h with 100% similarity]
arch/sparc/include/asm/types.h [moved from include/asm-sparc/types.h with 100% similarity]
arch/sparc/include/asm/uaccess.h [moved from include/asm-sparc/uaccess.h with 65% similarity]
arch/sparc/include/asm/uaccess_32.h [moved from include/asm-sparc/uaccess_32.h with 100% similarity]
arch/sparc/include/asm/uaccess_64.h [moved from include/asm-sparc/uaccess_64.h with 100% similarity]
arch/sparc/include/asm/uctx.h [moved from include/asm-sparc/uctx.h with 100% similarity]
arch/sparc/include/asm/unaligned.h [moved from include/asm-sparc/unaligned.h with 100% similarity]
arch/sparc/include/asm/unistd.h [moved from include/asm-sparc/unistd.h with 65% similarity]
arch/sparc/include/asm/unistd_32.h [moved from include/asm-sparc/unistd_32.h with 99% similarity]
arch/sparc/include/asm/unistd_64.h [moved from include/asm-sparc/unistd_64.h with 99% similarity]
arch/sparc/include/asm/upa.h [moved from include/asm-sparc/upa.h with 100% similarity]
arch/sparc/include/asm/user.h [moved from include/asm-sparc/user.h with 100% similarity]
arch/sparc/include/asm/utrap.h [moved from include/asm-sparc/utrap.h with 97% similarity]
arch/sparc/include/asm/vac-ops.h [moved from include/asm-sparc/vac-ops.h with 100% similarity]
arch/sparc/include/asm/vaddrs.h [moved from include/asm-sparc/vaddrs.h with 97% similarity]
arch/sparc/include/asm/vfc_ioctls.h [moved from include/asm-sparc/vfc_ioctls.h with 100% similarity]
arch/sparc/include/asm/vga.h [moved from include/asm-sparc/vga.h with 100% similarity]
arch/sparc/include/asm/viking.h [moved from include/asm-sparc/viking.h with 100% similarity]
arch/sparc/include/asm/vio.h [moved from include/asm-sparc/vio.h with 100% similarity]
arch/sparc/include/asm/visasm.h [moved from include/asm-sparc/visasm.h with 100% similarity]
arch/sparc/include/asm/watchdog.h [moved from include/asm-sparc/watchdog.h with 100% similarity]
arch/sparc/include/asm/winmacro.h [moved from include/asm-sparc/winmacro.h with 100% similarity]
arch/sparc/include/asm/xor.h [moved from include/asm-sparc/xor.h with 66% similarity]
arch/sparc/include/asm/xor_32.h [moved from include/asm-sparc/xor_32.h with 99% similarity]
arch/sparc/include/asm/xor_64.h [moved from include/asm-sparc/xor_64.h with 98% similarity]
arch/sparc/kernel/entry.S
arch/sparc/kernel/ptrace.c
arch/sparc/kernel/rtrap.S
arch/sparc/kernel/signal.c
arch/sparc/kernel/sys_sparc.c
arch/sparc/kernel/systbls.S
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
arch/sparc64/Kconfig
arch/sparc64/kernel/compat_audit.c
arch/sparc64/kernel/entry.h
arch/sparc64/kernel/iommu_common.h
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/kprobes.c
arch/sparc64/kernel/ldc.c
arch/sparc64/kernel/process.c
arch/sparc64/kernel/ptrace.c
arch/sparc64/kernel/rtrap.S
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/sys_sparc.c
arch/sparc64/kernel/syscalls.S
arch/sparc64/kernel/systbls.S
arch/sparc64/kernel/time.c
arch/sparc64/mm/hugetlbpage.c
arch/sparc64/mm/init.c
arch/um/include/irq_kern.h
arch/um/include/irq_user.h
arch/um/include/skas/skas.h
arch/um/include/um_uaccess.h
arch/um/kernel/irq.c
arch/um/kernel/ksyms.c
arch/um/kernel/mem.c
arch/um/kernel/physmem.c
arch/um/kernel/process.c
arch/um/kernel/ptrace.c
arch/um/kernel/time.c
arch/um/kernel/uaccess.c
arch/um/os-Linux/sigio.c
arch/um/os-Linux/signal.c
arch/um/os-Linux/skas/process.c
arch/um/os-Linux/umid.c
arch/um/sys-i386/bugs.c
arch/um/sys-i386/checksum.S
arch/um/sys-i386/ldt.c
arch/v850/Kconfig [deleted file]
arch/v850/Kconfig.debug [deleted file]
arch/v850/Makefile [deleted file]
arch/v850/README [deleted file]
arch/v850/configs/rte-ma1-cb_defconfig [deleted file]
arch/v850/configs/rte-me2-cb_defconfig [deleted file]
arch/v850/configs/sim_defconfig [deleted file]
arch/v850/kernel/Makefile [deleted file]
arch/v850/kernel/anna-rom.ld [deleted file]
arch/v850/kernel/anna.c [deleted file]
arch/v850/kernel/anna.ld [deleted file]
arch/v850/kernel/as85ep1-rom.ld [deleted file]
arch/v850/kernel/as85ep1.c [deleted file]
arch/v850/kernel/as85ep1.ld [deleted file]
arch/v850/kernel/asm-offsets.c [deleted file]
arch/v850/kernel/bug.c [deleted file]
arch/v850/kernel/entry.S [deleted file]
arch/v850/kernel/fpga85e2c.c [deleted file]
arch/v850/kernel/fpga85e2c.ld [deleted file]
arch/v850/kernel/gbus_int.c [deleted file]
arch/v850/kernel/head.S [deleted file]
arch/v850/kernel/highres_timer.c [deleted file]
arch/v850/kernel/init_task.c [deleted file]
arch/v850/kernel/intv.S [deleted file]
arch/v850/kernel/irq.c [deleted file]
arch/v850/kernel/ma.c [deleted file]
arch/v850/kernel/mach.c [deleted file]
arch/v850/kernel/mach.h [deleted file]
arch/v850/kernel/me2.c [deleted file]
arch/v850/kernel/memcons.c [deleted file]
arch/v850/kernel/module.c [deleted file]
arch/v850/kernel/process.c [deleted file]
arch/v850/kernel/procfs.c [deleted file]
arch/v850/kernel/ptrace.c [deleted file]
arch/v850/kernel/rte_cb.c [deleted file]
arch/v850/kernel/rte_cb_leds.c [deleted file]
arch/v850/kernel/rte_cb_multi.c [deleted file]
arch/v850/kernel/rte_ma1_cb-rom.ld [deleted file]
arch/v850/kernel/rte_ma1_cb.c [deleted file]
arch/v850/kernel/rte_ma1_cb.ld [deleted file]
arch/v850/kernel/rte_mb_a_pci.c [deleted file]
arch/v850/kernel/rte_me2_cb.c [deleted file]
arch/v850/kernel/rte_me2_cb.ld [deleted file]
arch/v850/kernel/rte_nb85e_cb-multi.ld [deleted file]
arch/v850/kernel/rte_nb85e_cb.c [deleted file]
arch/v850/kernel/rte_nb85e_cb.ld [deleted file]
arch/v850/kernel/setup.c [deleted file]
arch/v850/kernel/signal.c [deleted file]
arch/v850/kernel/sim.c [deleted file]
arch/v850/kernel/sim.ld [deleted file]
arch/v850/kernel/sim85e2.c [deleted file]
arch/v850/kernel/sim85e2.ld [deleted file]
arch/v850/kernel/simcons.c [deleted file]
arch/v850/kernel/syscalls.c [deleted file]
arch/v850/kernel/teg.c [deleted file]
arch/v850/kernel/time.c [deleted file]
arch/v850/kernel/v850_ksyms.c [deleted file]
arch/v850/kernel/v850e2_cache.c [deleted file]
arch/v850/kernel/v850e_cache.c [deleted file]
arch/v850/kernel/v850e_intc.c [deleted file]
arch/v850/kernel/v850e_timer_d.c [deleted file]
arch/v850/kernel/v850e_utils.c [deleted file]
arch/v850/kernel/vmlinux.lds.S [deleted file]
arch/v850/lib/Makefile [deleted file]
arch/v850/lib/ashldi3.c [deleted file]
arch/v850/lib/ashrdi3.c [deleted file]
arch/v850/lib/checksum.c [deleted file]
arch/v850/lib/lshrdi3.c [deleted file]
arch/v850/lib/memcpy.c [deleted file]
arch/v850/lib/memset.c [deleted file]
arch/v850/lib/muldi3.c [deleted file]
arch/v850/lib/negdi2.c [deleted file]
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/boot/compressed/misc.c
arch/x86/ia32/ia32_aout.c
arch/x86/ia32/ia32entry.S
arch/x86/ia32/sys_ia32.c
arch/x86/kernel/acpi/cstate.c
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/x86/kernel/cpu/cpufreq/powernow-k8.c
arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/head_32.S
arch/x86/kernel/hpet.c
arch/x86/kernel/irqinit_64.c
arch/x86/kernel/kprobes.c
arch/x86/kernel/ldt.c
arch/x86/kernel/machine_kexec_32.c
arch/x86/kernel/machine_kexec_64.c
arch/x86/kernel/microcode.c
arch/x86/kernel/module_64.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/pci-nommu.c
arch/x86/kernel/pci-swiotlb_64.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/relocate_kernel_32.S
arch/x86/kernel/setup.c
arch/x86/kernel/setup_percpu.c
arch/x86/kernel/signal_64.c
arch/x86/kernel/syscall_table_32.S
arch/x86/kvm/Kconfig
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lguest/boot.c
arch/x86/mm/Makefile
arch/x86/mm/discontig_32.c
arch/x86/mm/gup.c [new file with mode: 0644]
arch/x86/mm/hugetlbpage.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/mm/numa_64.c
arch/x86/mm/pgtable_32.c
arch/x86/oprofile/nmi_int.c
arch/x86/pci/fixup.c
arch/x86/pci/i386.c
arch/x86/pci/irq.c
arch/x86/pci/numaq_32.c
arch/x86/xen/enlighten.c
arch/x86/xen/xen-asm_64.S
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/syscall.c
arch/xtensa/mm/init.c
block/as-iosched.c
block/blk-map.c
block/ioctl.c
drivers/Makefile
drivers/acpi/namespace/nsnames.c
drivers/acpi/pci_link.c
drivers/acpi/pci_slot.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_throttling.c
drivers/acpi/sleep/main.c
drivers/acpi/system.c
drivers/acpi/tables/tbfadt.c
drivers/acpi/thermal.c
drivers/acpi/utilities/utalloc.c
drivers/acpi/video.c
drivers/ata/ahci.c
drivers/ata/pata_ixp4xx_cf.c
drivers/atm/fore200e.c
drivers/auxdisplay/cfag12864b.c
drivers/base/core.c
drivers/base/firmware_class.c
drivers/base/isa.c
drivers/base/memory.c
drivers/base/sys.c
drivers/block/aoe/aoechr.c
drivers/block/virtio_blk.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/ds1302.c
drivers/char/dsp56k.c
drivers/char/efirtc.c
drivers/char/hpet.c
drivers/char/hvc_console.c
drivers/char/hvc_console.h
drivers/char/hvc_irq.c [new file with mode: 0644]
drivers/char/hvc_iseries.c
drivers/char/hvc_vio.c
drivers/char/hvc_xen.c
drivers/char/hw_random/intel-rng.c
drivers/char/ip2/ip2main.c
drivers/char/lcd.c [deleted file]
drivers/char/lcd.h [deleted file]
drivers/char/mem.c
drivers/char/mspec.c
drivers/char/mwave/mwavedd.c
drivers/char/mwave/mwavedd.h
drivers/char/mwave/tp3780i.c
drivers/char/mxser.c
drivers/char/nwflash.c
drivers/char/pcmcia/ipwireless/hardware.c
drivers/char/pcmcia/ipwireless/hardware.h
drivers/char/pcmcia/ipwireless/main.c
drivers/char/pcmcia/ipwireless/main.h
drivers/char/pcmcia/ipwireless/network.c
drivers/char/pcmcia/ipwireless/network.h
drivers/char/pcmcia/ipwireless/tty.c
drivers/char/ppdev.c
drivers/char/random.c
drivers/char/rio/rio_linux.c
drivers/char/rtc.c
drivers/char/ser_a2232.c
drivers/char/stallion.c
drivers/char/sx.c
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm_bios.c
drivers/char/tpm/tpm_tis.c
drivers/char/tty_io.c
drivers/char/virtio_console.c
drivers/char/vme_scc.c
drivers/char/vt.c
drivers/char/xilinx_hwicap/xilinx_hwicap.c
drivers/cpuidle/cpuidle.c
drivers/crypto/talitos.c
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/e752x_edac.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/edac_pci_sysfs.c
drivers/edac/i5100_edac.c [new file with mode: 0644]
drivers/edac/mpc85xx_edac.c
drivers/edac/mv64x60_edac.c
drivers/firewire/Kconfig
drivers/firewire/fw-card.c
drivers/firewire/fw-cdev.c
drivers/firewire/fw-iso.c
drivers/firewire/fw-ohci.c
drivers/firewire/fw-sbp2.c
drivers/firewire/fw-topology.c
drivers/firewire/fw-transaction.c
drivers/firmware/dcdbas.c
drivers/firmware/dell_rbu.c
drivers/firmware/memmap.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/bt8xxgpio.c [new file with mode: 0644]
drivers/gpio/gpiolib.c
drivers/gpio/max732x.c [new file with mode: 0644]
drivers/gpio/mcp23s08.c
drivers/gpio/pca953x.c
drivers/gpio/pcf857x.c
drivers/gpu/drm/drm_drv.c
drivers/i2c/busses/i2c-bfin-twi.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/chips/Kconfig
drivers/i2c/chips/tps65010.c
drivers/ide/Kconfig
drivers/ide/Makefile
drivers/ide/arm/icside.c
drivers/ide/arm/palm_bk3710.c
drivers/ide/arm/rapide.c
drivers/ide/ide-cd.c
drivers/ide/ide-disk.c
drivers/ide/ide-dma.c
drivers/ide/ide-floppy.c
drivers/ide/ide-generic.c
drivers/ide/ide-iops.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide-tape.c
drivers/ide/ide-taskfile.c
drivers/ide/ide.c
drivers/ide/legacy/gayle.c
drivers/ide/legacy/ht6560b.c
drivers/ide/pci/aec62xx.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/amd74xx.c
drivers/ide/pci/atiixp.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/cs5520.c
drivers/ide/pci/cs5530.c
drivers/ide/pci/cs5535.c
drivers/ide/pci/cy82c693.c
drivers/ide/pci/generic.c
drivers/ide/pci/hpt34x.c
drivers/ide/pci/hpt366.c
drivers/ide/pci/it8213.c
drivers/ide/pci/it821x.c
drivers/ide/pci/jmicron.c
drivers/ide/pci/ns87415.c
drivers/ide/pci/opti621.c
drivers/ide/pci/pdc202xx_new.c
drivers/ide/pci/pdc202xx_old.c
drivers/ide/pci/piix.c
drivers/ide/pci/rz1000.c
drivers/ide/pci/sc1200.c
drivers/ide/pci/serverworks.c
drivers/ide/pci/siimage.c
drivers/ide/pci/sis5513.c
drivers/ide/pci/sl82c105.c
drivers/ide/pci/slc90e66.c
drivers/ide/pci/tc86c001.c
drivers/ide/pci/triflex.c
drivers/ide/pci/trm290.c
drivers/ide/pci/via82cxxx.c
drivers/ide/setup-pci.c
drivers/ieee1394/iso.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/ucm.c
drivers/infiniband/core/ucma.c
drivers/infiniband/hw/ehca/ehca_classes.h
drivers/infiniband/hw/ehca/ehca_hca.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ehca/ehca_qp.c
drivers/infiniband/hw/ehca/ipz_pt_fn.c
drivers/infiniband/hw/ipath/ipath_sdma.c
drivers/infiniband/hw/ipath/ipath_user_sdma.c
drivers/infiniband/hw/mlx4/cq.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/mr.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mlx4/srq.c
drivers/infiniband/hw/mlx4/user.h
drivers/infiniband/hw/mthca/mthca_dev.h
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/hw/mthca/mthca_mr.c
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_cm.h
drivers/infiniband/hw/nes/nes_hw.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/ulp/ipoib/Kconfig
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/input/keyboard/hil_kbd.c
drivers/input/keyboard/sh_keysc.c
drivers/input/misc/hp_sdc_rtc.c
drivers/input/misc/uinput.c
drivers/input/serio/hp_sdc.c
drivers/input/serio/serio.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/atmel_tsadcc.c [new file with mode: 0644]
drivers/input/touchscreen/corgi_ts.c
drivers/input/touchscreen/mainstone-wm97xx.c
drivers/isdn/Kconfig
drivers/isdn/Makefile
drivers/isdn/gigaset/asyncdata.c
drivers/isdn/gigaset/bas-gigaset.c
drivers/isdn/gigaset/common.c
drivers/isdn/gigaset/gigaset.h
drivers/isdn/gigaset/i4l.c
drivers/isdn/gigaset/interface.c
drivers/isdn/gigaset/usb-gigaset.c
drivers/isdn/hardware/Makefile
drivers/isdn/hardware/mISDN/Kconfig [new file with mode: 0644]
drivers/isdn/hardware/mISDN/Makefile [new file with mode: 0644]
drivers/isdn/hardware/mISDN/hfc_multi.h [new file with mode: 0644]
drivers/isdn/hardware/mISDN/hfc_pci.h [new file with mode: 0644]
drivers/isdn/hardware/mISDN/hfcmulti.c [new file with mode: 0644]
drivers/isdn/hardware/mISDN/hfcpci.c [new file with mode: 0644]
drivers/isdn/hisax/hisax_fcpcipnp.c
drivers/isdn/hisax/st5481.h
drivers/isdn/hisax/st5481_b.c
drivers/isdn/hisax/st5481_d.c
drivers/isdn/hisax/st5481_usb.c
drivers/isdn/mISDN/Kconfig [new file with mode: 0644]
drivers/isdn/mISDN/Makefile [new file with mode: 0644]
drivers/isdn/mISDN/core.c [new file with mode: 0644]
drivers/isdn/mISDN/core.h [new file with mode: 0644]
drivers/isdn/mISDN/dsp.h [new file with mode: 0644]
drivers/isdn/mISDN/dsp_audio.c [new file with mode: 0644]
drivers/isdn/mISDN/dsp_biquad.h [new file with mode: 0644]
drivers/isdn/mISDN/dsp_blowfish.c [new file with mode: 0644]
drivers/isdn/mISDN/dsp_cmx.c [new file with mode: 0644]
drivers/isdn/mISDN/dsp_core.c [new file with mode: 0644]
drivers/isdn/mISDN/dsp_dtmf.c [new file with mode: 0644]
drivers/isdn/mISDN/dsp_ecdis.h [new file with mode: 0644]
drivers/isdn/mISDN/dsp_hwec.c [new file with mode: 0644]
drivers/isdn/mISDN/dsp_hwec.h [new file with mode: 0644]
drivers/isdn/mISDN/dsp_pipeline.c [new file with mode: 0644]
drivers/isdn/mISDN/dsp_tones.c [new file with mode: 0644]
drivers/isdn/mISDN/fsm.c [new file with mode: 0644]
drivers/isdn/mISDN/fsm.h [new file with mode: 0644]
drivers/isdn/mISDN/hwchannel.c [new file with mode: 0644]
drivers/isdn/mISDN/l1oip.h [new file with mode: 0644]
drivers/isdn/mISDN/l1oip_codec.c [new file with mode: 0644]
drivers/isdn/mISDN/l1oip_core.c [new file with mode: 0644]
drivers/isdn/mISDN/layer1.c [new file with mode: 0644]
drivers/isdn/mISDN/layer1.h [new file with mode: 0644]
drivers/isdn/mISDN/layer2.c [new file with mode: 0644]
drivers/isdn/mISDN/layer2.h [new file with mode: 0644]
drivers/isdn/mISDN/socket.c [new file with mode: 0644]
drivers/isdn/mISDN/stack.c [new file with mode: 0644]
drivers/isdn/mISDN/tei.c [new file with mode: 0644]
drivers/isdn/mISDN/timerdev.c [new file with mode: 0644]
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/led-triggers.c
drivers/leds/leds-atmel-pwm.c
drivers/leds/leds-h1940.c
drivers/leds/leds-pca9532.c [new file with mode: 0644]
drivers/leds/leds-pca955x.c [new file with mode: 0644]
drivers/lguest/core.c
drivers/lguest/interrupts_and_traps.c
drivers/lguest/lguest_device.c
drivers/lguest/x86/core.c
drivers/md/dm-mpath.c
drivers/media/common/saa7146_fops.c
drivers/media/common/saa7146_video.c
drivers/media/common/tuners/Kconfig
drivers/media/common/tuners/Makefile
drivers/media/common/tuners/mt20xx.c
drivers/media/common/tuners/mxl5007t.c [new file with mode: 0644]
drivers/media/common/tuners/mxl5007t.h [new file with mode: 0644]
drivers/media/common/tuners/tda9887.c
drivers/media/common/tuners/tuner-simple.c
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/anysee.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dw2102.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/dw2102.h [new file with mode: 0644]
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/drx397xD.c [new file with mode: 0644]
drivers/media/dvb/frontends/drx397xD.h [new file with mode: 0644]
drivers/media/dvb/frontends/drx397xD_fw.h [new file with mode: 0644]
drivers/media/dvb/frontends/z0194a.h [new file with mode: 0644]
drivers/media/dvb/pluto2/pluto2.c
drivers/media/dvb/siano/smscoreapi.c
drivers/media/dvb/siano/smsdvb.c
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttusb-dec/Kconfig
drivers/media/radio/dsbr100.c
drivers/media/radio/miropcm20-radio.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-si470x.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/arv.c
drivers/media/video/au0828/Kconfig
drivers/media/video/au0828/au0828-cards.c
drivers/media/video/au0828/au0828-cards.h
drivers/media/video/au0828/au0828-dvb.c
drivers/media/video/bt8xx/Kconfig
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-risc.c
drivers/media/video/bt8xx/bttv-vbi.c
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/compat_ioctl32.c
drivers/media/video/cpia.c
drivers/media/video/cpia.h
drivers/media/video/cpia2/cpia2_core.c
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cs5345.c
drivers/media/video/cs53l32a.c
drivers/media/video/cx18/Kconfig
drivers/media/video/cx18/cx18-av-audio.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-firmware.c
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx23885/Kconfig
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx25840/Kconfig
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx25840/cx25840-core.h
drivers/media/video/cx88/Kconfig
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-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/gspca/conex.c
drivers/media/video/gspca/etoms.c
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/mars.c
drivers/media/video/gspca/ov519.c
drivers/media/video/gspca/pac207.c
drivers/media/video/gspca/pac7311.c
drivers/media/video/gspca/sonixb.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/gspca/spca500.c
drivers/media/video/gspca/spca501.c
drivers/media/video/gspca/spca505.c
drivers/media/video/gspca/spca506.c
drivers/media/video/gspca/spca508.c
drivers/media/video/gspca/spca561.c
drivers/media/video/gspca/stk014.c
drivers/media/video/gspca/sunplus.c
drivers/media/video/gspca/t613.c
drivers/media/video/gspca/tv8532.c
drivers/media/video/gspca/vc032x.c
drivers/media/video/gspca/zc3xx.c
drivers/media/video/ivtv/Kconfig
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/m52790.c
drivers/media/video/meye.c
drivers/media/video/msp3400-driver.c
drivers/media/video/msp3400-kthreads.c
drivers/media/video/mt9m001.c
drivers/media/video/ov511.c
drivers/media/video/ov511.h
drivers/media/video/planb.c
drivers/media/video/planb.h
drivers/media/video/pms.c
drivers/media/video/pvrusb2/Kconfig
drivers/media/video/pvrusb2/pvrusb2-context.h
drivers/media/video/pvrusb2/pvrusb2-devattr.c
drivers/media/video/pvrusb2/pvrusb2-devattr.h
drivers/media/video/pvrusb2/pvrusb2-dvb.c
drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-ioread.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc.h
drivers/media/video/s2255drv.c
drivers/media/video/saa5246a.c
drivers/media/video/saa5249.c
drivers/media/video/saa7134/Kconfig
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa717x.c
drivers/media/video/saa7196.h
drivers/media/video/se401.c
drivers/media/video/se401.h
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sn9c102/sn9c102.h
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/soc_camera.c
drivers/media/video/stk-webcam.c
drivers/media/video/stradis.c
drivers/media/video/stv680.c
drivers/media/video/tda7432.c
drivers/media/video/tda9875.c
drivers/media/video/tlv320aic23b.c
drivers/media/video/tuner-core.c
drivers/media/video/tveeprom.c
drivers/media/video/tvp5150.c
drivers/media/video/usbvideo/usbvideo.c
drivers/media/video/usbvideo/usbvideo.h
drivers/media/video/usbvideo/vicam.c
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/v4l2-dev.c [new file with mode: 0644]
drivers/media/video/v4l2-ioctl.c [new file with mode: 0644]
drivers/media/video/videobuf-core.c
drivers/media/video/videobuf-dma-contig.c
drivers/media/video/videobuf-vmalloc.c
drivers/media/video/videodev.c
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/vp27smpx.c
drivers/media/video/w9966.c
drivers/media/video/w9968cf.c
drivers/media/video/w9968cf.h
drivers/media/video/wm8739.c
drivers/media/video/wm8775.c
drivers/media/video/zc0301/zc0301.h
drivers/media/video/zc0301/zc0301_core.c
drivers/media/video/zoran_card.c
drivers/media/video/zoran_card.h
drivers/media/video/zoran_driver.c
drivers/media/video/zr364xx.c
drivers/memstick/core/memstick.c
drivers/memstick/core/mspro_block.c
drivers/memstick/host/jmb38x_ms.c
drivers/memstick/host/tifm_ms.c
drivers/message/fusion/lsi/mpi_history.txt
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptlan.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/i2o/device.c
drivers/mfd/Kconfig
drivers/mfd/asic3.c
drivers/mfd/htc-egpio.c
drivers/mfd/htc-pasic3.c
drivers/mfd/mcp-sa11x0.c
drivers/mfd/mfd-core.c
drivers/mfd/sm501.c
drivers/mfd/tc6393xb.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/atmel-ssc.c
drivers/misc/atmel_pwm.c
drivers/misc/hp-wmi.c [new file with mode: 0644]
drivers/misc/phantom.c
drivers/misc/sgi-xp/xpc_main.c
drivers/misc/thinkpad_acpi.c
drivers/mmc/core/Makefile
drivers/mmc/core/bus.c
drivers/mmc/core/core.h
drivers/mmc/core/debugfs.c [new file with mode: 0644]
drivers/mmc/core/host.c
drivers/mmc/host/atmel-mci-regs.h
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/imxmmc.c
drivers/mmc/host/mmc_spi.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mtd/Kconfig
drivers/mtd/afs.c
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/chips/cfi_probe.c
drivers/mtd/chips/cfi_util.c
drivers/mtd/chips/chipreg.c
drivers/mtd/chips/gen_probe.c
drivers/mtd/chips/jedec_probe.c
drivers/mtd/chips/map_absent.c
drivers/mtd/chips/map_ram.c
drivers/mtd/chips/map_rom.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/Kconfig
drivers/mtd/devices/Makefile
drivers/mtd/devices/block2mtd.c
drivers/mtd/devices/doc2000.c
drivers/mtd/devices/doc2001.c
drivers/mtd/devices/doc2001plus.c
drivers/mtd/devices/docecc.c
drivers/mtd/devices/docprobe.c
drivers/mtd/devices/lart.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/ms02-nv.c
drivers/mtd/devices/ms02-nv.h
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/devices/mtdram.c
drivers/mtd/devices/phram.c
drivers/mtd/devices/pmc551.c
drivers/mtd/devices/slram.c
drivers/mtd/ftl.c
drivers/mtd/inftlcore.c
drivers/mtd/inftlmount.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/amd76xrom.c
drivers/mtd/maps/autcpu12-nvram.c
drivers/mtd/maps/bast-flash.c [deleted file]
drivers/mtd/maps/bfin-async-flash.c [new file with mode: 0644]
drivers/mtd/maps/cdb89712.c
drivers/mtd/maps/ceiva.c
drivers/mtd/maps/cfi_flagadm.c
drivers/mtd/maps/dbox2-flash.c
drivers/mtd/maps/dc21285.c
drivers/mtd/maps/dilnetpc.c
drivers/mtd/maps/dmv182.c
drivers/mtd/maps/ebony.c
drivers/mtd/maps/edb7312.c
drivers/mtd/maps/fortunet.c
drivers/mtd/maps/h720x-flash.c
drivers/mtd/maps/ichxrom.c
drivers/mtd/maps/impa7.c
drivers/mtd/maps/integrator-flash.c
drivers/mtd/maps/ipaq-flash.c
drivers/mtd/maps/ixp2000.c
drivers/mtd/maps/ixp4xx.c
drivers/mtd/maps/l440gx.c
drivers/mtd/maps/map_funcs.c
drivers/mtd/maps/mbx860.c
drivers/mtd/maps/netsc520.c
drivers/mtd/maps/nettel.c
drivers/mtd/maps/octagon-5066.c
drivers/mtd/maps/omap-toto-flash.c
drivers/mtd/maps/pci.c
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/maps/physmap.c
drivers/mtd/maps/plat-ram.c
drivers/mtd/maps/redwood.c
drivers/mtd/maps/rpxlite.c
drivers/mtd/maps/sa1100-flash.c
drivers/mtd/maps/sbc8240.c
drivers/mtd/maps/sbc_gxx.c
drivers/mtd/maps/sc520cdp.c
drivers/mtd/maps/scb2_flash.c
drivers/mtd/maps/scx200_docflash.c
drivers/mtd/maps/sharpsl-flash.c
drivers/mtd/maps/solutionengine.c
drivers/mtd/maps/sun_uflash.c
drivers/mtd/maps/tqm8xxl.c
drivers/mtd/maps/ts5500_flash.c
drivers/mtd/maps/tsunami_flash.c
drivers/mtd/maps/uclinux.c
drivers/mtd/maps/vmax301.c
drivers/mtd/maps/walnut.c
drivers/mtd/maps/wr_sbc82xx_flash.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdblock.c
drivers/mtd/mtdblock_ro.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/atmel_nand.c [moved from drivers/mtd/nand/at91_nand.c with 62% similarity]
drivers/mtd/nand/atmel_nand_ecc.h [new file with mode: 0644]
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/autcpu12.c
drivers/mtd/nand/cafe_nand.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/edb7312.c
drivers/mtd/nand/excite_nandflash.c
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/h1910.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_bbt.c
drivers/mtd/nand/nand_ecc.c
drivers/mtd/nand/nand_ids.c
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/ppchameleonevb.c
drivers/mtd/nand/rtc_from4.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sharpsl.c
drivers/mtd/nand/spia.c
drivers/mtd/nand/toto.c
drivers/mtd/nand/ts7250.c
drivers/mtd/nftlcore.c
drivers/mtd/nftlmount.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/redboot.c
drivers/mtd/rfd_ftl.c
drivers/mtd/ubi/build.c
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/debug.c
drivers/mtd/ubi/debug.h
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/gluebi.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/kapi.c
drivers/mtd/ubi/misc.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/scan.h
drivers/mtd/ubi/ubi-media.h
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/upd.c
drivers/mtd/ubi/vmt.c
drivers/mtd/ubi/vtbl.c
drivers/mtd/ubi/wl.c
drivers/net/arm/ep93xx_eth.c
drivers/net/bnx2x_main.c
drivers/net/cassini.c
drivers/net/cxgb3/sge.c
drivers/net/e100.c
drivers/net/e1000e/ethtool.c
drivers/net/e1000e/netdev.c
drivers/net/fec.c
drivers/net/ibmveth.c
drivers/net/ibmveth.h
drivers/net/iseries_veth.c
drivers/net/mlx4/alloc.c
drivers/net/mlx4/catas.c
drivers/net/mlx4/cmd.c
drivers/net/mlx4/cq.c
drivers/net/mlx4/eq.c
drivers/net/mlx4/fw.c
drivers/net/mlx4/fw.h
drivers/net/mlx4/icm.c
drivers/net/mlx4/icm.h
drivers/net/mlx4/intf.c
drivers/net/mlx4/main.c
drivers/net/mlx4/mcg.c
drivers/net/mlx4/mlx4.h
drivers/net/mlx4/mr.c
drivers/net/mlx4/pd.c
drivers/net/mlx4/qp.c
drivers/net/mlx4/reset.c
drivers/net/mlx4/srq.c
drivers/net/pasemi_mac.c
drivers/net/ppp_generic.c
drivers/net/qla3xxx.c
drivers/net/s2io.c
drivers/net/sfc/rx.c
drivers/net/sfc/tx.c
drivers/net/sky2.c
drivers/net/spider_net.c
drivers/net/tc35815.c
drivers/net/virtio_net.c
drivers/net/wireless/ath5k/base.c
drivers/of/Kconfig
drivers/of/Makefile
drivers/of/base.c
drivers/of/of_i2c.c
drivers/of/of_spi.c [new file with mode: 0644]
drivers/parport/ieee1284.c
drivers/parport/parport_ax88796.c
drivers/parport/parport_cs.c
drivers/parport/parport_pc.c
drivers/parport/procfs.c
drivers/pci/dmar.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/msi.c
drivers/pci/pci-acpi.c
drivers/pci/pci.c
drivers/pci/pcie/aspm.c
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pci/quirks.c
drivers/pcmcia/electra_cf.c
drivers/pcmcia/soc_common.c
drivers/pnp/base.h
drivers/pnp/card.c
drivers/pnp/quirks.c
drivers/power/ds2760_battery.c
drivers/power/pda_power.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1305.c [new file with mode: 0644]
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-m41t94.c [new file with mode: 0644]
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pcf8583.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-vr41xx.c
drivers/s390/kvm/Makefile
drivers/s390/kvm/kvm_virtio.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-9xxx.h
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/advansys.c
drivers/scsi/aha152x.c
drivers/scsi/aic94xx/aic94xx.h
drivers/scsi/aic94xx/aic94xx_hwi.c
drivers/scsi/aic94xx/aic94xx_scb.c
drivers/scsi/aic94xx/aic94xx_task.c
drivers/scsi/aic94xx/aic94xx_tmf.c
drivers/scsi/arm/fas216.c
drivers/scsi/ch.c
drivers/scsi/device_handler/Kconfig
drivers/scsi/device_handler/Makefile
drivers/scsi/device_handler/scsi_dh.c
drivers/scsi/device_handler/scsi_dh_alua.c [new file with mode: 0644]
drivers/scsi/device_handler/scsi_dh_emc.c
drivers/scsi/device_handler/scsi_dh_hp_sw.c
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvfc.h
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvscsi.h
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/ibmvscsi/rpa_vscsi.c
drivers/scsi/ide-scsi.c
drivers/scsi/imm.c
drivers/scsi/ipr.h
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/libsas/sas_port.c
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/libsrp.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/megaraid/mega_common.h
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_mm.c
drivers/scsi/nsp32.c
drivers/scsi/nsp32_debug.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pcmcia/nsp_debug.c
drivers/scsi/ppa.c
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_netlink.c
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_tgt_priv.h
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/sd_dif.c [new file with mode: 0644]
drivers/scsi/st.c
drivers/scsi/stex.c
drivers/scsi/sun_esp.c
drivers/scsi/sym53c8xx_2/sym_hipd.c
drivers/scsi/tmscsim.c
drivers/scsi/wd7000.c
drivers/scsi/zalon.c
drivers/serial/8250.c
drivers/serial/8250_gsc.c
drivers/serial/8250_pci.c
drivers/serial/Kconfig
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/dz.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/serial/zs.c
drivers/spi/Kconfig
drivers/spi/atmel_spi.c
drivers/spi/au1550_spi.c
drivers/spi/mpc52xx_psc_spi.c
drivers/spi/omap2_mcspi.c
drivers/spi/pxa2xx_spi.c
drivers/spi/spi.c
drivers/spi/spi_imx.c
drivers/spi/spi_mpc83xx.c
drivers/spi/spi_s3c24xx.c
drivers/spi/spidev.c
drivers/spi/xilinx_spi.c
drivers/telephony/ixj.c
drivers/usb/gadget/at91_udc.h
drivers/usb/gadget/cdc2.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/fsl_usb2_udc.c
drivers/usb/gadget/fsl_usb2_udc.h
drivers/usb/gadget/gmidi.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/goku_udc.h
drivers/usb/gadget/inode.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/net2280.h
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/omap_udc.h
drivers/usb/gadget/printer.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/pxa25x_udc.h
drivers/usb/gadget/u_ether.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/isp116x.h
drivers/usb/host/sl811-hcd.c
drivers/usb/host/sl811.h
drivers/usb/misc/usbtest.c
drivers/usb/mon/mon_text.c
drivers/usb/serial/ipaq.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/acornfb.c
drivers/video/am200epd.c
drivers/video/amifb.c
drivers/video/atafb.c
drivers/video/atmel_lcdfb.c
drivers/video/aty/aty128fb.c
drivers/video/aty/atyfb_base.c
drivers/video/aty/radeon_base.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/atmel-pwm-bl.c [new file with mode: 0644]
drivers/video/backlight/backlight.c
drivers/video/backlight/ili9320.c [new file with mode: 0644]
drivers/video/backlight/ili9320.h [new file with mode: 0644]
drivers/video/backlight/lcd.c
drivers/video/backlight/mbp_nvidia_bl.c [new file with mode: 0644]
drivers/video/backlight/platform_lcd.c [new file with mode: 0644]
drivers/video/backlight/vgg2432a4.c [new file with mode: 0644]
drivers/video/bf54x-lq043fb.c
drivers/video/bfin-t350mcqb-fb.c
drivers/video/carminefb.c [new file with mode: 0644]
drivers/video/carminefb.h [new file with mode: 0644]
drivers/video/carminefb_regs.h [new file with mode: 0644]
drivers/video/cobalt_lcdfb.c [new file with mode: 0644]
drivers/video/console/fbcon.c
drivers/video/console/fbcon.h
drivers/video/console/mdacon.c
drivers/video/console/sticon.c
drivers/video/console/sticore.c
drivers/video/fbmem.c
drivers/video/fbmon.c
drivers/video/fsl-diu-fb.c
drivers/video/geode/lxfb.h
drivers/video/geode/lxfb_ops.c
drivers/video/hgafb.c
drivers/video/imxfb.c
drivers/video/macfb.c
drivers/video/neofb.c
drivers/video/omap/dispc.c
drivers/video/omap/omapfb_main.c
drivers/video/omap/sossi.c
drivers/video/pxafb.c
drivers/video/pxafb.h
drivers/video/sa1100fb.c
drivers/video/sa1100fb.h
drivers/video/sh7760fb.c [new file with mode: 0644]
drivers/video/sh_mobile_lcdcfb.c [new file with mode: 0644]
drivers/video/sis/init.h
drivers/video/sis/init301.h
drivers/video/sis/initextlfb.c
drivers/video/sis/osdef.h
drivers/video/sis/sis.h
drivers/video/sis/sis_accel.c
drivers/video/sis/sis_main.c
drivers/video/sis/sis_main.h
drivers/video/sis/vgatypes.h
drivers/video/skeletonfb.c
drivers/video/sm501fb.c
drivers/video/sticore.h
drivers/video/stifb.c
drivers/video/tdfxfb.c
drivers/video/tridentfb.c
drivers/video/uvesafb.c
drivers/video/vfb.c
drivers/video/vga16fb.c
drivers/virtio/virtio.c
drivers/virtio/virtio_pci.c
drivers/virtio/virtio_ring.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/xen/balloon.c
drivers/zorro/zorro-sysfs.c
fs/Kconfig
fs/Kconfig.binfmt
fs/Makefile
fs/adfs/super.c
fs/affs/affs.h
fs/affs/bitmap.c
fs/affs/file.c
fs/affs/super.c
fs/afs/internal.h
fs/afs/security.c
fs/afs/super.c
fs/aio.c
fs/anon_inodes.c
fs/attr.c
fs/autofs4/autofs_i.h
fs/autofs4/expire.c
fs/autofs4/inode.c
fs/autofs4/root.c
fs/autofs4/waitq.c
fs/bad_inode.c
fs/befs/linuxvfs.c
fs/bfs/bfs.h
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_flat.c
fs/binfmt_misc.c
fs/binfmt_som.c
fs/bio-integrity.c
fs/bio.c
fs/block_dev.c
fs/buffer.c
fs/cifs/asn1.c
fs/cifs/cifs_debug.c
fs/cifs/cifsacl.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/inode.c
fs/cifs/readdir.c
fs/coda/coda_linux.c
fs/coda/dir.c
fs/coda/inode.c
fs/coda/pioctl.c
fs/coda/psdev.c
fs/coda/upcall.c
fs/compat.c
fs/compat_ioctl.c
fs/dcache.c
fs/direct-io.c
fs/dlm/lock.c
fs/dlm/lowcomms.c
fs/dlm/plock.c
fs/dlm/user.c
fs/dquot.c
fs/ecryptfs/Makefile
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/kthread.c [new file with mode: 0644]
fs/ecryptfs/main.c
fs/ecryptfs/miscdev.c
fs/ecryptfs/mmap.c
fs/efs/super.c
fs/eventfd.c
fs/eventpoll.c
fs/exec.c
fs/ext2/acl.c
fs/ext2/acl.h
fs/ext2/inode.c
fs/ext2/super.c
fs/ext2/xattr_security.c
fs/ext2/xattr_trusted.c
fs/ext2/xattr_user.c
fs/ext3/acl.c
fs/ext3/acl.h
fs/ext3/dir.c
fs/ext3/ialloc.c
fs/ext3/inode.c
fs/ext3/namei.c
fs/ext3/super.c
fs/ext3/xattr_security.c
fs/ext3/xattr_trusted.c
fs/ext3/xattr_user.c
fs/ext4/acl.c
fs/ext4/acl.h
fs/ext4/inode.c
fs/ext4/super.c
fs/fat/cache.c
fs/fat/dir.c
fs/fat/file.c
fs/fat/inode.c
fs/fat/misc.c
fs/fcntl.c
fs/fifo.c
fs/file.c
fs/file_table.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/main.c
fs/gfs2/ops_export.c
fs/gfs2/ops_inode.c
fs/gfs2/super.c
fs/hfs/bitmap.c
fs/hfs/btree.c
fs/hfs/extent.c
fs/hfs/hfs_fs.h
fs/hfs/inode.c
fs/hfs/super.c
fs/hfsplus/extents.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/inode.c
fs/hfsplus/super.c
fs/hostfs/hostfs_kern.c
fs/hpfs/namei.c
fs/hpfs/super.c
fs/hppfs/hppfs.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/inotify_user.c
fs/isofs/inode.c
fs/isofs/rock.c
fs/jbd/commit.c
fs/jbd/journal.c
fs/jbd/revoke.c
fs/jbd/transaction.c
fs/jffs2/acl.c
fs/jffs2/acl.h
fs/jffs2/dir.c
fs/jffs2/file.c
fs/jffs2/ioctl.c
fs/jffs2/os-linux.h
fs/jffs2/super.c
fs/jfs/acl.c
fs/jfs/jfs_acl.h
fs/jfs/jfs_metapage.c
fs/jfs/super.c
fs/lockd/clntproc.c
fs/lockd/svclock.c
fs/locks.c
fs/minix/inode.c
fs/minix/minix.h
fs/minix/namei.c
fs/msdos/namei.c
fs/namei.c
fs/namespace.c
fs/ncpfs/dir.c
fs/ncpfs/inode.c
fs/nfs/dir.c
fs/nfs/inode.c
fs/nfs/nfsroot.c
fs/nfs/super.c
fs/nfs/unlink.c
fs/nfsd/lockd.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsfh.c
fs/nfsd/vfs.c
fs/ntfs/file.c
fs/ntfs/super.c
fs/ocfs2/dlm/dlmfs.c
fs/ocfs2/file.c
fs/ocfs2/file.h
fs/ocfs2/super.c
fs/omfs/Makefile [new file with mode: 0644]
fs/omfs/bitmap.c [new file with mode: 0644]
fs/omfs/dir.c [new file with mode: 0644]
fs/omfs/file.c [new file with mode: 0644]
fs/omfs/inode.c [new file with mode: 0644]
fs/omfs/omfs.h [new file with mode: 0644]
fs/omfs/omfs_fs.h [new file with mode: 0644]
fs/open.c
fs/openpromfs/inode.c
fs/partitions/check.c
fs/partitions/efi.c
fs/partitions/ldm.c
fs/partitions/ldm.h
fs/pipe.c
fs/proc/Kconfig [new file with mode: 0644]
fs/proc/array.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/kcore.c
fs/proc/kmsg.c
fs/proc/proc_misc.c
fs/proc/proc_sysctl.c
fs/qnx4/inode.c
fs/quota.c
fs/quota_v1.c
fs/quota_v2.c
fs/reiserfs/journal.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/reiserfs/xattr_security.c
fs/reiserfs/xattr_trusted.c
fs/reiserfs/xattr_user.c
fs/romfs/inode.c
fs/signalfd.c
fs/smbfs/cache.c
fs/smbfs/file.c
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/splice.c
fs/stat.c
fs/super.c
fs/sync.c
fs/sysfs/dir.c
fs/sysfs/file.c
fs/sysfs/group.c
fs/sysv/inode.c
fs/timerfd.c
fs/ubifs/file.c
fs/ubifs/super.c
fs/udf/super.c
fs/ufs/super.c
fs/utimes.c
fs/vfat/namei.c
fs/xattr.c
fs/xfs/linux-2.6/kmem.h
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_super.c
include/Kbuild
include/acpi/actbl.h
include/asm-alpha/dma-mapping.h
include/asm-alpha/ide.h [deleted file]
include/asm-alpha/kvm.h [deleted file]
include/asm-alpha/namei.h [deleted file]
include/asm-alpha/page.h
include/asm-alpha/pci.h
include/asm-alpha/semaphore.h [deleted file]
include/asm-alpha/socket.h
include/asm-alpha/thread_info.h
include/asm-arm/arch-at91/at91_ecc.h [deleted file]
include/asm-arm/arch-at91/board.h
include/asm-arm/arch-pnx4008/irqs.h
include/asm-arm/arch-pxa/idp.h
include/asm-arm/arch-pxa/pcm990_baseboard.h
include/asm-arm/arch-pxa/pxa25x-udc.h
include/asm-arm/arch-s3c2410/spi.h
include/asm-arm/arch-sa1100/h3600.h
include/asm-arm/arch-sa1100/ide.h
include/asm-arm/bitops.h
include/asm-arm/cacheflush.h
include/asm-arm/dma-mapping.h
include/asm-arm/ide.h
include/asm-arm/irq.h
include/asm-arm/kvm.h [deleted file]
include/asm-arm/namei.h [deleted file]
include/asm-arm/page-nommu.h
include/asm-arm/page.h
include/asm-arm/pci.h
include/asm-arm/plat-s3c/iic.h
include/asm-arm/ptrace.h
include/asm-arm/semaphore.h [deleted file]
include/asm-arm/thread_info.h
include/asm-avr32/arch-at32ap/board.h
include/asm-avr32/dma-mapping.h
include/asm-avr32/kvm.h [deleted file]
include/asm-avr32/namei.h [deleted file]
include/asm-avr32/page.h
include/asm-avr32/semaphore.h [deleted file]
include/asm-avr32/thread_info.h
include/asm-blackfin/bfin-global.h
include/asm-blackfin/dma.h
include/asm-blackfin/dpmc.h
include/asm-blackfin/elf.h
include/asm-blackfin/gpio.h
include/asm-blackfin/ide.h [deleted file]
include/asm-blackfin/kvm.h [deleted file]
include/asm-blackfin/mach-bf527/anomaly.h
include/asm-blackfin/mach-bf527/bfin_sir.h
include/asm-blackfin/mach-bf527/defBF527.h
include/asm-blackfin/mach-bf527/mem_init.h
include/asm-blackfin/mach-bf533/bfin_sir.h
include/asm-blackfin/mach-bf533/mem_init.h
include/asm-blackfin/mach-bf537/bfin_sir.h
include/asm-blackfin/mach-bf537/defBF537.h
include/asm-blackfin/mach-bf537/mem_init.h
include/asm-blackfin/mach-bf548/bfin_sir.h
include/asm-blackfin/mach-bf548/gpio.h
include/asm-blackfin/mach-bf561/bfin_sir.h
include/asm-blackfin/mach-bf561/mem_init.h
include/asm-blackfin/module.h
include/asm-blackfin/namei.h [deleted file]
include/asm-blackfin/page.h
include/asm-blackfin/processor.h
include/asm-blackfin/ptrace.h
include/asm-blackfin/semaphore.h [deleted file]
include/asm-blackfin/thread_info.h
include/asm-cris/arch-v10/Kbuild
include/asm-cris/arch-v10/ide.h [deleted file]
include/asm-cris/arch-v10/ptrace.h
include/asm-cris/arch-v32/Kbuild
include/asm-cris/arch-v32/ide.h [deleted file]
include/asm-cris/arch-v32/ptrace.h
include/asm-cris/cacheflush.h
include/asm-cris/dma-mapping.h
include/asm-cris/ide.h [deleted file]
include/asm-cris/kvm.h [deleted file]
include/asm-cris/namei.h [deleted file]
include/asm-cris/page.h
include/asm-cris/ptrace.h
include/asm-cris/semaphore.h [deleted file]
include/asm-cris/thread_info.h
include/asm-frv/Kbuild
include/asm-frv/dma-mapping.h
include/asm-frv/ide.h
include/asm-frv/kvm.h [deleted file]
include/asm-frv/namei.h [deleted file]
include/asm-frv/page.h
include/asm-frv/semaphore.h [deleted file]
include/asm-frv/thread_info.h
include/asm-generic/Kbuild.asm
include/asm-generic/bug.h
include/asm-generic/dma-coherent.h [new file with mode: 0644]
include/asm-generic/dma-mapping-broken.h
include/asm-generic/dma-mapping.h
include/asm-generic/gpio.h
include/asm-generic/int-ll64.h
include/asm-generic/pci-dma-compat.h
include/asm-generic/pgtable-nopmd.h
include/asm-generic/syscall.h [new file with mode: 0644]
include/asm-generic/vmlinux.lds.h
include/asm-h8300/elf.h
include/asm-h8300/ide.h [deleted file]
include/asm-h8300/keyboard.h [deleted file]
include/asm-h8300/kvm.h [deleted file]
include/asm-h8300/namei.h [deleted file]
include/asm-h8300/page.h
include/asm-h8300/semaphore.h [deleted file]
include/asm-h8300/thread_info.h
include/asm-ia64/hugetlb.h
include/asm-ia64/ide.h [deleted file]
include/asm-ia64/machvec.h
include/asm-ia64/namei.h [deleted file]
include/asm-ia64/page.h
include/asm-ia64/semaphore.h [deleted file]
include/asm-ia64/thread_info.h
include/asm-ia64/unistd.h
include/asm-m32r/ide.h [deleted file]
include/asm-m32r/kvm.h [deleted file]
include/asm-m32r/namei.h [deleted file]
include/asm-m32r/page.h
include/asm-m32r/semaphore.h [deleted file]
include/asm-m32r/thread_info.h
include/asm-m68k/dma-mapping.h
include/asm-m68k/dvma.h
include/asm-m68k/ide.h
include/asm-m68k/kvm.h [deleted file]
include/asm-m68k/namei.h [deleted file]
include/asm-m68k/page.h
include/asm-m68k/semaphore.h [deleted file]
include/asm-m68k/thread_info.h
include/asm-m68knommu/bitops.h
include/asm-m68knommu/byteorder.h
include/asm-m68knommu/commproc.h
include/asm-m68knommu/kvm.h [deleted file]
include/asm-m68knommu/namei.h [deleted file]
include/asm-m68knommu/page.h
include/asm-m68knommu/ptrace.h
include/asm-m68knommu/semaphore.h [deleted file]
include/asm-m68knommu/system.h
include/asm-m68knommu/thread_info.h
include/asm-mips/dma-mapping.h
include/asm-mips/kvm.h [deleted file]
include/asm-mips/mach-au1x00/au1550_spi.h
include/asm-mips/mach-generic/gpio.h
include/asm-mips/mach-generic/ide.h
include/asm-mips/namei.h [deleted file]
include/asm-mips/page.h
include/asm-mips/processor.h
include/asm-mips/semaphore.h [deleted file]
include/asm-mips/socket.h
include/asm-mips/thread_info.h
include/asm-mn10300/dma-mapping.h
include/asm-mn10300/ide.h
include/asm-mn10300/kvm.h [deleted file]
include/asm-mn10300/namei.h [deleted file]
include/asm-mn10300/page.h
include/asm-mn10300/pci.h
include/asm-mn10300/ptrace.h
include/asm-mn10300/scatterlist.h
include/asm-mn10300/semaphore.h [deleted file]
include/asm-mn10300/thread_info.h
include/asm-parisc/cacheflush.h
include/asm-parisc/dma-mapping.h
include/asm-parisc/ide.h
include/asm-parisc/kvm.h [deleted file]
include/asm-parisc/namei.h [deleted file]
include/asm-parisc/page.h
include/asm-parisc/ptrace.h
include/asm-parisc/semaphore.h [deleted file]
include/asm-parisc/socket.h
include/asm-parisc/thread_info.h
include/asm-powerpc/Kbuild
include/asm-powerpc/cputable.h
include/asm-powerpc/dma-mapping.h
include/asm-powerpc/elf.h
include/asm-powerpc/firmware.h
include/asm-powerpc/gpio.h
include/asm-powerpc/hugetlb.h
include/asm-powerpc/hvcall.h
include/asm-powerpc/ide.h
include/asm-powerpc/io.h
include/asm-powerpc/kvm_ppc.h
include/asm-powerpc/lppaca.h
include/asm-powerpc/machdep.h
include/asm-powerpc/mmu-hash64.h
include/asm-powerpc/mpc52xx_psc.h
include/asm-powerpc/namei.h [deleted file]
include/asm-powerpc/page.h
include/asm-powerpc/page_64.h
include/asm-powerpc/pgalloc-64.h
include/asm-powerpc/pgtable-4k.h
include/asm-powerpc/pgtable-64k.h
include/asm-powerpc/pgtable-ppc32.h
include/asm-powerpc/pgtable-ppc64.h
include/asm-powerpc/pgtable.h
include/asm-powerpc/ptrace.h
include/asm-powerpc/semaphore.h [deleted file]
include/asm-powerpc/signal.h
include/asm-powerpc/smp.h
include/asm-powerpc/syscall.h [new file with mode: 0644]
include/asm-powerpc/syscalls.h
include/asm-powerpc/systbl.h
include/asm-powerpc/system.h
include/asm-powerpc/thread_info.h
include/asm-powerpc/tlbflush.h
include/asm-powerpc/topology.h
include/asm-powerpc/unistd.h
include/asm-powerpc/vio.h
include/asm-s390/Kbuild
include/asm-s390/hugetlb.h
include/asm-s390/kvm_host.h
include/asm-s390/kvm_virtio.h
include/asm-s390/namei.h [deleted file]
include/asm-s390/page.h
include/asm-s390/semaphore.h [deleted file]
include/asm-s390/thread_info.h
include/asm-sh/clock.h
include/asm-sh/cpu-sh4/cacheflush.h
include/asm-sh/cpu-sh4/freq.h
include/asm-sh/device.h
include/asm-sh/dma-mapping.h
include/asm-sh/elf.h
include/asm-sh/hugetlb.h
include/asm-sh/hw_irq.h
include/asm-sh/ide.h [deleted file]
include/asm-sh/kvm.h [deleted file]
include/asm-sh/migor.h
include/asm-sh/mmu.h
include/asm-sh/mmu_context.h
include/asm-sh/namei.h [deleted file]
include/asm-sh/page.h
include/asm-sh/pgtable_32.h
include/asm-sh/processor.h
include/asm-sh/processor_32.h
include/asm-sh/processor_64.h
include/asm-sh/ptrace.h
include/asm-sh/se.h
include/asm-sh/se7343.h
include/asm-sh/se7722.h
include/asm-sh/segment.h
include/asm-sh/semaphore.h [deleted file]
include/asm-sh/sh7760fb.h [new file with mode: 0644]
include/asm-sh/sh7763rdp.h [new file with mode: 0644]
include/asm-sh/sh7785lcr.h [new file with mode: 0644]
include/asm-sh/sh_mobile_lcdc.h [new file with mode: 0644]
include/asm-sh/system.h
include/asm-sh/thread_info.h
include/asm-sh/timer.h
include/asm-sh/uaccess.h
include/asm-sh/uaccess_32.h
include/asm-sh/uaccess_64.h
include/asm-sh/unistd.h
include/asm-sh/unistd_32.h
include/asm-sh/unistd_64.h
include/asm-sparc/Kbuild [deleted file]
include/asm-sparc/kvm.h [deleted file]
include/asm-sparc/namei.h [deleted file]
include/asm-sparc/namei_32.h [deleted file]
include/asm-sparc/namei_64.h [deleted file]
include/asm-sparc/semaphore.h [deleted file]
include/asm-sparc64/Kbuild [deleted file]
include/asm-sparc64/agp.h [deleted file]
include/asm-sparc64/apb.h [deleted file]
include/asm-sparc64/asi.h [deleted file]
include/asm-sparc64/atomic.h [deleted file]
include/asm-sparc64/auxio.h [deleted file]
include/asm-sparc64/auxvec.h [deleted file]
include/asm-sparc64/backoff.h [deleted file]
include/asm-sparc64/bbc.h [deleted file]
include/asm-sparc64/bitops.h [deleted file]
include/asm-sparc64/bpp.h [deleted file]
include/asm-sparc64/bug.h [deleted file]
include/asm-sparc64/bugs.h [deleted file]
include/asm-sparc64/byteorder.h [deleted file]
include/asm-sparc64/cache.h [deleted file]
include/asm-sparc64/cacheflush.h [deleted file]
include/asm-sparc64/chafsr.h [deleted file]
include/asm-sparc64/checksum.h [deleted file]
include/asm-sparc64/chmctrl.h [deleted file]
include/asm-sparc64/cmt.h [deleted file]
include/asm-sparc64/compat.h [deleted file]
include/asm-sparc64/compat_signal.h [deleted file]
include/asm-sparc64/cpudata.h [deleted file]
include/asm-sparc64/cputime.h [deleted file]
include/asm-sparc64/current.h [deleted file]
include/asm-sparc64/dcr.h [deleted file]
include/asm-sparc64/dcu.h [deleted file]
include/asm-sparc64/delay.h [deleted file]
include/asm-sparc64/device.h [deleted file]
include/asm-sparc64/display7seg.h [deleted file]
include/asm-sparc64/div64.h [deleted file]
include/asm-sparc64/dma-mapping.h [deleted file]
include/asm-sparc64/dma.h [deleted file]
include/asm-sparc64/ebus.h [deleted file]
include/asm-sparc64/elf.h [deleted file]
include/asm-sparc64/emergency-restart.h [deleted file]
include/asm-sparc64/envctrl.h [deleted file]
include/asm-sparc64/errno.h [deleted file]
include/asm-sparc64/estate.h [deleted file]
include/asm-sparc64/fb.h [deleted file]
include/asm-sparc64/fbio.h [deleted file]
include/asm-sparc64/fcntl.h [deleted file]
include/asm-sparc64/fhc.h [deleted file]
include/asm-sparc64/floppy.h [deleted file]
include/asm-sparc64/fpumacro.h [deleted file]
include/asm-sparc64/futex.h [deleted file]
include/asm-sparc64/hardirq.h [deleted file]
include/asm-sparc64/head.h [deleted file]
include/asm-sparc64/hugetlb.h [deleted file]
include/asm-sparc64/hvtramp.h [deleted file]
include/asm-sparc64/hw_irq.h [deleted file]
include/asm-sparc64/hypervisor.h [deleted file]
include/asm-sparc64/ide.h [deleted file]
include/asm-sparc64/idprom.h [deleted file]
include/asm-sparc64/intr_queue.h [deleted file]
include/asm-sparc64/io.h [deleted file]
include/asm-sparc64/ioctl.h [deleted file]
include/asm-sparc64/ioctls.h [deleted file]
include/asm-sparc64/iommu.h [deleted file]
include/asm-sparc64/ipcbuf.h [deleted file]
include/asm-sparc64/irq.h [deleted file]
include/asm-sparc64/irq_regs.h [deleted file]
include/asm-sparc64/irqflags.h [deleted file]
include/asm-sparc64/kdebug.h [deleted file]
include/asm-sparc64/kgdb.h [deleted file]
include/asm-sparc64/kmap_types.h [deleted file]
include/asm-sparc64/kprobes.h [deleted file]
include/asm-sparc64/kvm.h [deleted file]
include/asm-sparc64/ldc.h [deleted file]
include/asm-sparc64/linkage.h [deleted file]
include/asm-sparc64/lmb.h [deleted file]
include/asm-sparc64/local.h [deleted file]
include/asm-sparc64/lsu.h [deleted file]
include/asm-sparc64/mc146818rtc.h [deleted file]
include/asm-sparc64/mdesc.h [deleted file]
include/asm-sparc64/mman.h [deleted file]
include/asm-sparc64/mmu.h [deleted file]
include/asm-sparc64/mmu_context.h [deleted file]
include/asm-sparc64/mmzone.h [deleted file]
include/asm-sparc64/module.h [deleted file]
include/asm-sparc64/mostek.h [deleted file]
include/asm-sparc64/msgbuf.h [deleted file]
include/asm-sparc64/mutex.h [deleted file]
include/asm-sparc64/namei.h [deleted file]
include/asm-sparc64/ns87303.h [deleted file]
include/asm-sparc64/of_device.h [deleted file]
include/asm-sparc64/of_platform.h [deleted file]
include/asm-sparc64/openprom.h [deleted file]
include/asm-sparc64/openpromio.h [deleted file]
include/asm-sparc64/oplib.h [deleted file]
include/asm-sparc64/page.h [deleted file]
include/asm-sparc64/param.h [deleted file]
include/asm-sparc64/parport.h [deleted file]
include/asm-sparc64/pci.h [deleted file]
include/asm-sparc64/percpu.h [deleted file]
include/asm-sparc64/perfctr.h [deleted file]
include/asm-sparc64/pgalloc.h [deleted file]
include/asm-sparc64/pgtable.h [deleted file]
include/asm-sparc64/pil.h [deleted file]
include/asm-sparc64/poll.h [deleted file]
include/asm-sparc64/posix_types.h [deleted file]
include/asm-sparc64/processor.h [deleted file]
include/asm-sparc64/prom.h [deleted file]
include/asm-sparc64/psrcompat.h [deleted file]
include/asm-sparc64/pstate.h [deleted file]
include/asm-sparc64/ptrace.h [deleted file]
include/asm-sparc64/reboot.h [deleted file]
include/asm-sparc64/reg.h [deleted file]
include/asm-sparc64/resource.h [deleted file]
include/asm-sparc64/rtc.h [deleted file]
include/asm-sparc64/rwsem-const.h [deleted file]
include/asm-sparc64/rwsem.h [deleted file]
include/asm-sparc64/sbus.h [deleted file]
include/asm-sparc64/scatterlist.h [deleted file]
include/asm-sparc64/scratchpad.h [deleted file]
include/asm-sparc64/seccomp.h [deleted file]
include/asm-sparc64/sections.h [deleted file]
include/asm-sparc64/semaphore.h [deleted file]
include/asm-sparc64/sembuf.h [deleted file]
include/asm-sparc64/setup.h [deleted file]
include/asm-sparc64/sfafsr.h [deleted file]
include/asm-sparc64/sfp-machine.h [deleted file]
include/asm-sparc64/shmbuf.h [deleted file]
include/asm-sparc64/shmparam.h [deleted file]
include/asm-sparc64/sigcontext.h [deleted file]
include/asm-sparc64/siginfo.h [deleted file]
include/asm-sparc64/signal.h [deleted file]
include/asm-sparc64/smp.h [deleted file]
include/asm-sparc64/socket.h [deleted file]
include/asm-sparc64/sockios.h [deleted file]
include/asm-sparc64/sparsemem.h [deleted file]
include/asm-sparc64/spinlock.h [deleted file]
include/asm-sparc64/spinlock_types.h [deleted file]
include/asm-sparc64/spitfire.h [deleted file]
include/asm-sparc64/sstate.h [deleted file]
include/asm-sparc64/stacktrace.h [deleted file]
include/asm-sparc64/starfire.h [deleted file]
include/asm-sparc64/stat.h [deleted file]
include/asm-sparc64/statfs.h [deleted file]
include/asm-sparc64/string.h [deleted file]
include/asm-sparc64/sunbpp.h [deleted file]
include/asm-sparc64/syscalls.h [deleted file]
include/asm-sparc64/system.h [deleted file]
include/asm-sparc64/termbits.h [deleted file]
include/asm-sparc64/termios.h [deleted file]
include/asm-sparc64/thread_info.h [deleted file]
include/asm-sparc64/timer.h [deleted file]
include/asm-sparc64/timex.h [deleted file]
include/asm-sparc64/tlb.h [deleted file]
include/asm-sparc64/tlbflush.h [deleted file]
include/asm-sparc64/topology.h [deleted file]
include/asm-sparc64/tsb.h [deleted file]
include/asm-sparc64/ttable.h [deleted file]
include/asm-sparc64/types.h [deleted file]
include/asm-sparc64/uaccess.h [deleted file]
include/asm-sparc64/uctx.h [deleted file]
include/asm-sparc64/unaligned.h [deleted file]
include/asm-sparc64/unistd.h [deleted file]
include/asm-sparc64/upa.h [deleted file]
include/asm-sparc64/user.h [deleted file]
include/asm-sparc64/utrap.h [deleted file]
include/asm-sparc64/vga.h [deleted file]
include/asm-sparc64/vio.h [deleted file]
include/asm-sparc64/visasm.h [deleted file]
include/asm-sparc64/watchdog.h [deleted file]
include/asm-sparc64/xor.h [deleted file]
include/asm-um/kvm.h [deleted file]
include/asm-um/namei.h [deleted file]
include/asm-um/page.h
include/asm-um/ptrace-generic.h
include/asm-um/semaphore.h [deleted file]
include/asm-um/thread_info.h
include/asm-v850/Kbuild [deleted file]
include/asm-v850/a.out.h [deleted file]
include/asm-v850/anna.h [deleted file]
include/asm-v850/as85ep1.h [deleted file]
include/asm-v850/asm.h [deleted file]
include/asm-v850/atomic.h [deleted file]
include/asm-v850/auxvec.h [deleted file]
include/asm-v850/bitops.h [deleted file]
include/asm-v850/bug.h [deleted file]
include/asm-v850/bugs.h [deleted file]
include/asm-v850/byteorder.h [deleted file]
include/asm-v850/cache.h [deleted file]
include/asm-v850/cacheflush.h [deleted file]
include/asm-v850/checksum.h [deleted file]
include/asm-v850/clinkage.h [deleted file]
include/asm-v850/cputime.h [deleted file]
include/asm-v850/current.h [deleted file]
include/asm-v850/delay.h [deleted file]
include/asm-v850/device.h [deleted file]
include/asm-v850/div64.h [deleted file]
include/asm-v850/dma-mapping.h [deleted file]
include/asm-v850/dma.h [deleted file]
include/asm-v850/elf.h [deleted file]
include/asm-v850/emergency-restart.h [deleted file]
include/asm-v850/entry.h [deleted file]
include/asm-v850/errno.h [deleted file]
include/asm-v850/fb.h [deleted file]
include/asm-v850/fcntl.h [deleted file]
include/asm-v850/flat.h [deleted file]
include/asm-v850/fpga85e2c.h [deleted file]
include/asm-v850/futex.h [deleted file]
include/asm-v850/gbus_int.h [deleted file]
include/asm-v850/hardirq.h [deleted file]
include/asm-v850/highres_timer.h [deleted file]
include/asm-v850/hw_irq.h [deleted file]
include/asm-v850/io.h [deleted file]
include/asm-v850/ioctl.h [deleted file]
include/asm-v850/ioctls.h [deleted file]
include/asm-v850/ipcbuf.h [deleted file]
include/asm-v850/irq.h [deleted file]
include/asm-v850/irq_regs.h [deleted file]
include/asm-v850/kdebug.h [deleted file]
include/asm-v850/kmap_types.h [deleted file]
include/asm-v850/kvm.h [deleted file]
include/asm-v850/linkage.h [deleted file]
include/asm-v850/local.h [deleted file]
include/asm-v850/ma.h [deleted file]
include/asm-v850/ma1.h [deleted file]
include/asm-v850/machdep.h [deleted file]
include/asm-v850/macrology.h [deleted file]
include/asm-v850/me2.h [deleted file]
include/asm-v850/mman.h [deleted file]
include/asm-v850/mmu.h [deleted file]
include/asm-v850/mmu_context.h [deleted file]
include/asm-v850/module.h [deleted file]
include/asm-v850/msgbuf.h [deleted file]
include/asm-v850/mutex.h [deleted file]
include/asm-v850/namei.h [deleted file]
include/asm-v850/page.h [deleted file]
include/asm-v850/param.h [deleted file]
include/asm-v850/pci.h [deleted file]
include/asm-v850/percpu.h [deleted file]
include/asm-v850/pgalloc.h [deleted file]
include/asm-v850/pgtable.h [deleted file]
include/asm-v850/poll.h [deleted file]
include/asm-v850/posix_types.h [deleted file]
include/asm-v850/processor.h [deleted file]
include/asm-v850/ptrace.h [deleted file]
include/asm-v850/resource.h [deleted file]
include/asm-v850/rte_cb.h [deleted file]
include/asm-v850/rte_ma1_cb.h [deleted file]
include/asm-v850/rte_mb_a_pci.h [deleted file]
include/asm-v850/rte_me2_cb.h [deleted file]
include/asm-v850/rte_nb85e_cb.h [deleted file]
include/asm-v850/scatterlist.h [deleted file]
include/asm-v850/sections.h [deleted file]
include/asm-v850/segment.h [deleted file]
include/asm-v850/semaphore.h [deleted file]
include/asm-v850/sembuf.h [deleted file]
include/asm-v850/serial.h [deleted file]
include/asm-v850/setup.h [deleted file]
include/asm-v850/shmbuf.h [deleted file]
include/asm-v850/shmparam.h [deleted file]
include/asm-v850/sigcontext.h [deleted file]
include/asm-v850/siginfo.h [deleted file]
include/asm-v850/signal.h [deleted file]
include/asm-v850/sim.h [deleted file]
include/asm-v850/sim85e2.h [deleted file]
include/asm-v850/sim85e2c.h [deleted file]
include/asm-v850/sim85e2s.h [deleted file]
include/asm-v850/simsyscall.h [deleted file]
include/asm-v850/socket.h [deleted file]
include/asm-v850/sockios.h [deleted file]
include/asm-v850/stat.h [deleted file]
include/asm-v850/statfs.h [deleted file]
include/asm-v850/string.h [deleted file]
include/asm-v850/system.h [deleted file]
include/asm-v850/teg.h [deleted file]
include/asm-v850/termbits.h [deleted file]
include/asm-v850/termios.h [deleted file]
include/asm-v850/thread_info.h [deleted file]
include/asm-v850/timex.h [deleted file]
include/asm-v850/tlb.h [deleted file]
include/asm-v850/tlbflush.h [deleted file]
include/asm-v850/topology.h [deleted file]
include/asm-v850/types.h [deleted file]
include/asm-v850/uaccess.h [deleted file]
include/asm-v850/ucontext.h [deleted file]
include/asm-v850/unaligned.h [deleted file]
include/asm-v850/unistd.h [deleted file]
include/asm-v850/user.h [deleted file]
include/asm-v850/v850e.h [deleted file]
include/asm-v850/v850e2.h [deleted file]
include/asm-v850/v850e2_cache.h [deleted file]
include/asm-v850/v850e_cache.h [deleted file]
include/asm-v850/v850e_intc.h [deleted file]
include/asm-v850/v850e_timer_c.h [deleted file]
include/asm-v850/v850e_timer_d.h [deleted file]
include/asm-v850/v850e_uart.h [deleted file]
include/asm-v850/v850e_uarta.h [deleted file]
include/asm-v850/v850e_uartb.h [deleted file]
include/asm-v850/v850e_utils.h [deleted file]
include/asm-x86/Kbuild
include/asm-x86/desc.h
include/asm-x86/device.h
include/asm-x86/dma-mapping.h
include/asm-x86/gpio.h
include/asm-x86/hugetlb.h
include/asm-x86/i387.h
include/asm-x86/ide.h [deleted file]
include/asm-x86/io_32.h
include/asm-x86/io_64.h
include/asm-x86/iommu.h
include/asm-x86/kexec.h
include/asm-x86/kvm_host.h
include/asm-x86/mach-summit/mach_apic.h
include/asm-x86/namei.h [deleted file]
include/asm-x86/page.h
include/asm-x86/paravirt.h
include/asm-x86/pgtable.h
include/asm-x86/processor-flags.h
include/asm-x86/semaphore.h [deleted file]
include/asm-x86/swiotlb.h
include/asm-x86/thread_info.h
include/asm-x86/uaccess.h
include/asm-x86/unistd_32.h
include/asm-x86/unistd_64.h
include/asm-xtensa/dma-mapping.h
include/asm-xtensa/ide.h [deleted file]
include/asm-xtensa/kvm.h [deleted file]
include/asm-xtensa/namei.h [deleted file]
include/asm-xtensa/page.h
include/asm-xtensa/ptrace.h
include/asm-xtensa/semaphore.h [deleted file]
include/asm-xtensa/thread_info.h
include/linux/Kbuild
include/linux/acct.h
include/linux/acpi.h
include/linux/aio.h
include/linux/anon_inodes.h
include/linux/atmel-pwm-bl.h [new file with mode: 0644]
include/linux/audit.h
include/linux/auto_fs4.h
include/linux/auxvec.h
include/linux/bcd.h
include/linux/binfmts.h
include/linux/bootmem.h
include/linux/buffer_head.h
include/linux/byteorder/big_endian.h
include/linux/byteorder/little_endian.h
include/linux/cgroup.h
include/linux/coda.h
include/linux/coda_linux.h
include/linux/consolemap.h
include/linux/cpu.h
include/linux/cpumask.h
include/linux/crash_dump.h
include/linux/delayacct.h
include/linux/dirent.h
include/linux/eventfd.h
include/linux/eventpoll.h
include/linux/ext2_fs.h
include/linux/ext3_fs.h
include/linux/fb.h
include/linux/fd1772.h [deleted file]
include/linux/fs.h
include/linux/fs_struct.h
include/linux/fuse.h
include/linux/genhd.h
include/linux/gfp.h
include/linux/gpio.h
include/linux/hugetlb.h
include/linux/i2c/max732x.h [new file with mode: 0644]
include/linux/i2o.h
include/linux/ide.h
include/linux/idr.h
include/linux/init.h
include/linux/init_task.h
include/linux/inotify.h
include/linux/iommu-helper.h
include/linux/ipc_namespace.h
include/linux/irqflags.h
include/linux/jffs2.h
include/linux/kallsyms.h
include/linux/kernel.h
include/linux/kexec.h
include/linux/kmod.h
include/linux/kobject.h
include/linux/kprobes.h
include/linux/kthread.h
include/linux/lcd.h
include/linux/leds-pca9532.h [new file with mode: 0644]
include/linux/leds.h
include/linux/list.h
include/linux/mISDNdsp.h [new file with mode: 0644]
include/linux/mISDNhw.h [new file with mode: 0644]
include/linux/mISDNif.h [new file with mode: 0644]
include/linux/major.h
include/linux/maple.h
include/linux/memcontrol.h
include/linux/memory_hotplug.h
include/linux/mempolicy.h
include/linux/memstick.h
include/linux/mfd/core.h
include/linux/migrate.h
include/linux/mlx4/device.h
include/linux/mlx4/qp.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmc/card.h
include/linux/mmc/host.h
include/linux/mmu_notifier.h [new file with mode: 0644]
include/linux/module.h
include/linux/mount.h
include/linux/msdos_fs.h
include/linux/mtd/blktrans.h
include/linux/mtd/cfi.h
include/linux/mtd/cfi_endian.h
include/linux/mtd/concat.h
include/linux/mtd/doc2000.h
include/linux/mtd/flashchip.h
include/linux/mtd/ftl.h
include/linux/mtd/gen_probe.h
include/linux/mtd/inftl.h
include/linux/mtd/map.h
include/linux/mtd/mtd.h
include/linux/mtd/nand.h
include/linux/mtd/nand_ecc.h
include/linux/mtd/nftl.h
include/linux/mtd/partitions.h
include/linux/mtd/physmap.h
include/linux/mtd/plat-ram.h
include/linux/mtd/pmc551.h
include/linux/mtd/ubi.h
include/linux/mtd/xip.h
include/linux/namei.h
include/linux/net.h
include/linux/nfs_fs.h
include/linux/nfsd/nfsd.h
include/linux/notifier.h
include/linux/nsproxy.h
include/linux/of.h
include/linux/of_spi.h [new file with mode: 0644]
include/linux/page-flags.h
include/linux/pagemap.h
include/linux/parport.h
include/linux/parser.h
include/linux/pci-aspm.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/pci_regs.h
include/linux/percpu.h
include/linux/pid.h
include/linux/pid_namespace.h
include/linux/pm.h
include/linux/pm_legacy.h [deleted file]
include/linux/proc_fs.h
include/linux/profile.h
include/linux/ptrace.h
include/linux/quota.h
include/linux/quotaops.h
include/linux/radix-tree.h
include/linux/ratelimit.h [new file with mode: 0644]
include/linux/rculist.h
include/linux/rcupreempt.h
include/linux/reiserfs_fs.h
include/linux/reiserfs_fs_sb.h
include/linux/reiserfs_xattr.h
include/linux/relay.h
include/linux/res_counter.h
include/linux/rmap.h
include/linux/rtc.h
include/linux/rtnetlink.h
include/linux/sched.h
include/linux/security.h
include/linux/sem.h
include/linux/semaphore.h
include/linux/serial_core.h
include/linux/serio.h
include/linux/shmem_fs.h
include/linux/signalfd.h
include/linux/slab.h
include/linux/slub_def.h
include/linux/sm501.h
include/linux/smb_fs.h
include/linux/smp.h
include/linux/socket.h
include/linux/spi/ds1305.h [new file with mode: 0644]
include/linux/spi/mcp23s08.h
include/linux/spi/spi.h
include/linux/spinlock.h
include/linux/ssb/ssb.h
include/linux/stop_machine.h
include/linux/string.h
include/linux/suspend.h
include/linux/swap.h
include/linux/syscalls.h
include/linux/sysctl.h
include/linux/task_io_accounting.h
include/linux/task_io_accounting_ops.h
include/linux/taskstats.h
include/linux/tick.h
include/linux/timerfd.h
include/linux/tracehook.h [new file with mode: 0644]
include/linux/typecheck.h [new file with mode: 0644]
include/linux/usb/composite.h
include/linux/videodev.h
include/linux/videodev2.h
include/linux/videotext.h
include/linux/virtio_9p.h
include/linux/virtio_balloon.h
include/linux/virtio_blk.h
include/linux/virtio_config.h
include/linux/virtio_console.h
include/linux/virtio_net.h
include/linux/virtio_pci.h
include/linux/virtio_ring.h
include/linux/virtio_rng.h
include/linux/vmstat.h
include/linux/vt_kern.h
include/linux/workqueue.h
include/media/audiochip.h
include/media/saa7146_vv.h
include/media/tveeprom.h
include/media/v4l2-chip-ident.h
include/media/v4l2-common.h
include/media/v4l2-dev.h
include/media/v4l2-ioctl.h [new file with mode: 0644]
include/mtd/inftl-user.h
include/mtd/jffs2-user.h
include/mtd/mtd-abi.h
include/mtd/mtd-user.h
include/mtd/nftl-user.h
include/mtd/ubi-user.h
include/net/af_unix.h
include/net/ieee80211_radiotap.h
include/net/ip.h
include/net/ipcomp.h
include/net/ipv6.h
include/net/net_namespace.h
include/net/request_sock.h
include/net/route.h
include/rdma/ib_verbs.h
include/rdma/rdma_cm.h
include/scsi/scsi.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_device.h
include/scsi/scsi_dh.h
include/scsi/scsi_eh.h
include/scsi/scsi_host.h
include/video/atmel_lcdc.h
include/video/ili9320.h [new file with mode: 0644]
include/video/neomagic.h
include/video/platform_lcd.h [new file with mode: 0644]
include/video/trident.h
init/Kconfig
init/do_mounts.c
init/do_mounts.h
init/do_mounts_rd.c
init/initramfs.c
init/main.c
init/version.c
ipc/ipc_sysctl.c
ipc/ipcns_notifier.c
ipc/mqueue.c
ipc/sem.c
ipc/shm.c
ipc/util.c
ipc/util.h
kernel/Kconfig.hz
kernel/Makefile
kernel/acct.c
kernel/capability.c
kernel/cgroup.c
kernel/cpu.c
kernel/cpuset.c
kernel/delayacct.c
kernel/dma-coherent.c [new file with mode: 0644]
kernel/exec_domain.c
kernel/exit.c
kernel/fork.c
kernel/irq/chip.c
kernel/irq/manage.c
kernel/kallsyms.c
kernel/kexec.c
kernel/kmod.c
kernel/kprobes.c
kernel/kthread.c
kernel/marker.c
kernel/module.c
kernel/ns_cgroup.c
kernel/nsproxy.c
kernel/panic.c
kernel/pid.c
kernel/pid_namespace.c
kernel/posix-timers.c
kernel/power/Kconfig
kernel/power/main.c
kernel/power/power.h
kernel/power/poweroff.c
kernel/power/process.c
kernel/power/snapshot.c
kernel/printk.c
kernel/profile.c
kernel/ptrace.c
kernel/rcuclassic.c
kernel/relay.c
kernel/res_counter.c
kernel/sched.c
kernel/sched_rt.c
kernel/signal.c
kernel/smp.c
kernel/softirq.c
kernel/softlockup.c
kernel/stop_machine.c
kernel/sys.c
kernel/sys_ni.c
kernel/sysctl.c
kernel/sysctl_check.c
kernel/taskstats.c
kernel/time/tick-common.c
kernel/time/tick-sched.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_sched_wakeup.c
kernel/trace/trace_sysprof.c
kernel/tsacct.c
kernel/workqueue.c
lib/Kconfig.debug
lib/Makefile
lib/bcd.c [new file with mode: 0644]
lib/cmdline.c
lib/debugobjects.c
lib/idr.c
lib/inflate.c
lib/iomap.c
lib/iommu-helper.c
lib/kobject.c
lib/kobject_uevent.c
lib/list_debug.c
lib/lzo/lzo1x_decompress.c
lib/plist.c
lib/radix-tree.c
lib/ratelimit.c
lib/show_mem.c [new file with mode: 0644]
lib/smp_processor_id.c
lib/swiotlb.c
lib/syscall.c [new file with mode: 0644]
mm/Kconfig
mm/Makefile
mm/allocpercpu.c
mm/bootmem.c
mm/filemap.c
mm/filemap_xip.c
mm/fremap.c
mm/hugetlb.c
mm/internal.h
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/migrate.c
mm/mm_init.c [new file with mode: 0644]
mm/mmap.c
mm/mmu_notifier.c [new file with mode: 0644]
mm/mprotect.c
mm/mremap.c
mm/nommu.c
mm/page-writeback.c
mm/page_alloc.c
mm/pdflush.c
mm/readahead.c
mm/rmap.c
mm/shmem.c
mm/shmem_acl.c
mm/slab.c
mm/slob.c
mm/slub.c
mm/sparse.c
mm/swap.c
mm/swap_state.c
mm/swapfile.c
mm/truncate.c
mm/util.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/802/psnap.c
net/9p/trans_fd.c
net/appletalk/ddp.c
net/bridge/netfilter/ebtable_filter.c
net/bridge/netfilter/ebtable_nat.c
net/compat.c
net/core/datagram.c
net/core/dev.c
net/core/request_sock.c
net/core/skbuff.c
net/core/sock.c
net/core/stream.c
net/core/sysctl_net_core.c
net/core/user_dma.c
net/core/utils.c
net/dccp/dccp.h
net/dccp/input.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dccp/output.c
net/dccp/proto.c
net/dccp/timer.c
net/ipv4/Kconfig
net/ipv4/af_inet.c
net/ipv4/devinet.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_fragment.c
net/ipv4/inet_hashtables.c
net/ipv4/inet_timewait_sock.c
net/ipv4/ip_fragment.c
net/ipv4/ip_output.c
net/ipv4/ipcomp.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/arptable_filter.c
net/ipv4/netfilter/iptable_security.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_timer.c
net/ipv6/Kconfig
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/inet6_connection_sock.c
net/ipv6/inet6_hashtables.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_output.c
net/ipv6/ipcomp6.c
net/ipv6/mip6.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/ip6table_security.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c
net/ipv6/syncookies.c
net/ipv6/sysctl_net_ipv6.c
net/ipv6/tcp_ipv6.c
net/key/af_key.c
net/netfilter/nf_conntrack_extend.c
net/netlink/af_netlink.c
net/packet/af_packet.c
net/rxrpc/af_rxrpc.c
net/sched/act_api.c
net/sched/act_police.c
net/sched/cls_u32.c
net/sched/sch_atm.c
net/sched/sch_cbq.c
net/sched/sch_generic.c
net/sched/sch_htb.c
net/sctp/associola.c
net/sctp/socket.c
net/socket.c
net/sunrpc/rpc_pipe.c
net/sunrpc/svc.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sysctl_net.c
net/unix/af_unix.c
net/unix/garbage.c
net/xfrm/Kconfig
net/xfrm/Makefile
net/xfrm/xfrm_algo.c
net/xfrm/xfrm_ipcomp.c [new file with mode: 0644]
net/xfrm/xfrm_state.c
scripts/Makefile.fwinst
scripts/Makefile.headersinst
scripts/checkpatch.pl
scripts/checkstack.pl
scripts/diffconfig [new file with mode: 0755]
scripts/genksyms/genksyms.c
scripts/hdrcheck.sh [deleted file]
scripts/headers.sh [new file with mode: 0755]
scripts/headers_check.pl [new file with mode: 0644]
scripts/headers_install.pl [new file with mode: 0644]
scripts/kconfig/conf.c
scripts/kconfig/confdata.c
scripts/kconfig/lkc.h
scripts/kernel-doc
scripts/mod/file2alias.c
scripts/mod/mk_elfconfig.c
scripts/setlocalversion
security/Kconfig
security/capability.c
security/commoncap.c
security/device_cgroup.c
security/security.c
security/selinux/hooks.c
security/smack/smack_lsm.c
sound/core/info.c
sound/i2c/other/tea575x-tuner.c
sound/isa/cs423x/cs4236.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/oss/Kconfig
sound/oss/Makefile
sound/oss/trident.c [deleted file]
sound/oss/trident.h [deleted file]
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_patch.c
sound/pci/azt3328.h
sound/pci/ens1370.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/au1x/psc-i2s.c
sound/soc/codecs/wm9712.c
sound/soc/soc-dapm.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 077b147388bd593c971ec2643e0c8b9ecd194b65..c62dcb3b7e2621d918815a656f2682fda044afcb 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -317,6 +317,14 @@ S: 2322 37th Ave SW
 S: Seattle, Washington 98126-2010
 S: USA
 
+N: Muli Ben-Yehuda
+E: mulix@mulix.org
+E: muli@il.ibm.com
+W: http://www.mulix.org
+D: trident OSS sound driver, x86-64 dma-ops and Calgary IOMMU,
+D: KVM and Xen bits and other misc. hackery.
+S: Haifa, Israel
+
 N: Johannes Berg
 E: johannes@sipsolutions.net
 W: http://johannes.sipsolutions.net/
index 1977fab386566e23f501bea233f8f487d16f5c38..6de71308a9060b1a81c27aedb5b91042ff0b668b 100644 (file)
@@ -361,8 +361,6 @@ telephony/
        - directory with info on telephony (e.g. voice over IP) support.
 time_interpolators.txt
        - info on time interpolators.
-tipar.txt
-       - information about Parallel link cable for Texas Instruments handhelds.
 tty.txt
        - guide to the locking policies of the tty layer.
 uml/
diff --git a/Documentation/ABI/testing/sysfs-devices-memory b/Documentation/ABI/testing/sysfs-devices-memory
new file mode 100644 (file)
index 0000000..7a16fe1
--- /dev/null
@@ -0,0 +1,24 @@
+What:          /sys/devices/system/memory
+Date:          June 2008
+Contact:       Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+               The /sys/devices/system/memory contains a snapshot of the
+               internal state of the kernel memory blocks. Files could be
+               added or removed dynamically to represent hot-add/remove
+               operations.
+
+Users:         hotplug memory add/remove tools
+               https://w3.opensource.ibm.com/projects/powerpc-utils/
+
+What:          /sys/devices/system/memory/memoryX/removable
+Date:          June 2008
+Contact:       Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+               The file /sys/devices/system/memory/memoryX/removable
+               indicates whether this memory block is removable or not.
+               This is useful for a user-level agent to determine
+               identify removable sections of the memory before attempting
+               potentially expensive hot-remove memory operation
+
+Users:         hotplug memory remove tools
+               https://w3.opensource.ibm.com/projects/powerpc-utils/
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm b/Documentation/ABI/testing/sysfs-kernel-mm
new file mode 100644 (file)
index 0000000..190d523
--- /dev/null
@@ -0,0 +1,6 @@
+What:          /sys/kernel/mm
+Date:          July 2008
+Contact:       Nishanth Aravamudan <nacc@us.ibm.com>, VM maintainers
+Description:
+               /sys/kernel/mm/ should contain any and all VM
+               related information in /sys/kernel/.
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-hugepages b/Documentation/ABI/testing/sysfs-kernel-mm-hugepages
new file mode 100644 (file)
index 0000000..e21c005
--- /dev/null
@@ -0,0 +1,15 @@
+What:          /sys/kernel/mm/hugepages/
+Date:          June 2008
+Contact:       Nishanth Aravamudan <nacc@us.ibm.com>, hugetlb maintainers
+Description:
+               /sys/kernel/mm/hugepages/ contains a number of subdirectories
+               of the form hugepages-<size>kB, where <size> is the page size
+               of the hugepages supported by the kernel/CPU combination.
+
+               Under these directories are a number of files:
+                       nr_hugepages
+                       nr_overcommit_hugepages
+                       free_hugepages
+                       surplus_hugepages
+                       resv_hugepages
+               See Documentation/vm/hugetlbpage.txt for details.
index 6caa146155788c8a67fc940c1879f2faf4fac1bb..1875e502f87205a1dcaf268d0af78127ee336144 100644 (file)
@@ -474,25 +474,29 @@ make a good program).
 So, you can either get rid of GNU emacs, or change it to use saner
 values.  To do the latter, you can stick the following in your .emacs file:
 
-(defun linux-c-mode ()
-  "C mode with adjusted defaults for use with the Linux kernel."
-  (interactive)
-  (c-mode)
-  (c-set-style "K&R")
-  (setq tab-width 8)
-  (setq indent-tabs-mode t)
-  (setq c-basic-offset 8))
-
-This will define the M-x linux-c-mode command.  When hacking on a
-module, if you put the string -*- linux-c -*- somewhere on the first
-two lines, this mode will be automatically invoked. Also, you may want
-to add
-
-(setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode)
-                       auto-mode-alist))
-
-to your .emacs file if you want to have linux-c-mode switched on
-automagically when you edit source files under /usr/src/linux.
+(defun c-lineup-arglist-tabs-only (ignored)
+  "Line up argument lists by tabs, not spaces"
+  (let* ((anchor (c-langelem-pos c-syntactic-element))
+        (column (c-langelem-2nd-pos c-syntactic-element))
+        (offset (- (1+ column) anchor))
+        (steps (floor offset c-basic-offset)))
+    (* (max steps 1)
+       c-basic-offset)))
+
+(add-hook 'c-mode-hook
+          (lambda ()
+            (let ((filename (buffer-file-name)))
+              ;; Enable kernel mode for the appropriate files
+              (when (and filename
+                         (string-match "~/src/linux-trees" filename))
+                (setq indent-tabs-mode t)
+                (c-set-style "linux")
+                (c-set-offset 'arglist-cont-nonempty
+                              '(c-lineup-gcc-asm-reg
+                                c-lineup-arglist-tabs-only))))))
+
+This will make emacs go better with the kernel coding style for C
+files below ~/src/linux-trees.
 
 But even if you fail in getting emacs to do sane formatting, not
 everything is lost: use "indent".
index 80d150458c80c5ac7f7f5f75b3e6ff8a602a19ca..d8b63d164e41193927af2c7fb41dcb0893f57878 100644 (file)
@@ -298,10 +298,10 @@ recommended that you never use these unless you really know what the
 cache width is.
 
 int
-dma_mapping_error(dma_addr_t dma_addr)
+dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 
 int
-pci_dma_mapping_error(dma_addr_t dma_addr)
+pci_dma_mapping_error(struct pci_dev *hwdev, dma_addr_t dma_addr)
 
 In some circumstances dma_map_single and dma_map_page will fail to create
 a mapping. A driver can check for these errors by testing the returned
index 2510763295d09dfbd893e288d1948c9b05feda4d..084f6ad7b7a0a4729b85aea3cc5c3e6eb6557689 100644 (file)
    </para>
 
    <sect1 id="lock-intro">
-   <title>Three Main Types of Kernel Locks: Spinlocks, Mutexes and Semaphores</title>
+   <title>Two Main Types of Kernel Locks: Spinlocks and Mutexes</title>
 
    <para>
-     There are three main types of kernel locks.  The fundamental type
+     There are two main types of kernel locks.  The fundamental type
      is the spinlock 
      (<filename class="headerfile">include/asm/spinlock.h</filename>),
      which is a very simple single-holder lock: if you can't get the 
      can't sleep (see <xref linkend="sleeping-things"/>), and so have to
      use a spinlock instead.
    </para>
-   <para>
-     The third type is a semaphore
-     (<filename class="headerfile">include/linux/semaphore.h</filename>): it
-     can have more than one holder at any time (the number decided at
-     initialization time), although it is most commonly used as a
-     single-holder lock (a mutex).  If you can't get a semaphore, your
-     task will be suspended and later on woken up - just like for mutexes.
-   </para>
    <para>
      Neither type of lock is recursive: see
      <xref linkend="deadlock"/>.
     </para>
 
     <para>
-      Semaphores still exist, because they are required for
+      Mutexes still exist, because they are required for
       synchronization between <firstterm linkend="gloss-usercontext">user 
       contexts</firstterm>, as we will see below.
     </para>
 
      <para>
        If you have a data structure which is only ever accessed from
-       user context, then you can use a simple semaphore
-       (<filename>linux/linux/semaphore.h</filename>) to protect it.  This
-       is the most trivial case: you initialize the semaphore to the number 
-       of resources available (usually 1), and call
-       <function>down_interruptible()</function> to grab the semaphore, and 
-       <function>up()</function> to release it.  There is also a 
-       <function>down()</function>, which should be avoided, because it 
+       user context, then you can use a simple mutex
+       (<filename>include/linux/mutex.h</filename>) to protect it.  This
+       is the most trivial case: you initialize the mutex.  Then you can
+       call <function>mutex_lock_interruptible()</function> to grab the mutex,
+       and <function>mutex_unlock()</function> to release it.  There is also a 
+       <function>mutex_lock()</function>, which should be avoided, because it 
        will not return if a signal is received.
      </para>
 
      <para>
-       Example: <filename>linux/net/core/netfilter.c</filename> allows 
+       Example: <filename>net/netfilter/nf_sockopt.c</filename> allows 
        registration of new <function>setsockopt()</function> and 
        <function>getsockopt()</function> calls, with
        <function>nf_register_sockopt()</function>.  Registration and 
       <listitem>
        <para>
           If you are in a process context (any syscall) and want to
-       lock other process out, use a semaphore.  You can take a semaphore
+       lock other process out, use a mutex.  You can take a mutex
        and sleep (<function>copy_from_user*(</function> or
        <function>kmalloc(x,GFP_KERNEL)</function>).
       </para>
 <entry>SLBH</entry>
 <entry>SLBH</entry>
 <entry>SLBH</entry>
-<entry>DI</entry>
+<entry>MLI</entry>
 <entry>None</entry>
 </row>
 
 <entry>spin_lock_bh</entry>
 </row>
 <row>
-<entry>DI</entry>
-<entry>down_interruptible</entry>
+<entry>MLI</entry>
+<entry>mutex_lock_interruptible</entry>
 </row>
 
 </tbody>
@@ -1310,7 +1301,7 @@ as Alan Cox says, <quote>Lock data, not code</quote>.
     <para>
       There is a coding bug where a piece of code tries to grab a
       spinlock twice: it will spin forever, waiting for the lock to
-      be released (spinlocks, rwlocks and semaphores are not
+      be released (spinlocks, rwlocks and mutexes are not
       recursive in Linux).  This is trivial to diagnose: not a
       stay-up-five-nights-talk-to-fluffy-code-bunnies kind of
       problem.
@@ -1335,7 +1326,7 @@ as Alan Cox says, <quote>Lock data, not code</quote>.
 
     <para>
       This complete lockup is easy to diagnose: on SMP boxes the
-      watchdog timer or compiling with <symbol>DEBUG_SPINLOCKS</symbol> set
+      watchdog timer or compiling with <symbol>DEBUG_SPINLOCK</symbol> set
       (<filename>include/linux/spinlock.h</filename>) will show this up 
       immediately when it happens.
     </para>
@@ -1558,7 +1549,7 @@ the amount of locking which needs to be done.
    <title>Read/Write Lock Variants</title>
 
    <para>
-      Both spinlocks and semaphores have read/write variants:
+      Both spinlocks and mutexes have read/write variants:
       <type>rwlock_t</type> and <structname>struct rw_semaphore</structname>.
       These divide users into two classes: the readers and the writers.  If
       you are only reading the data, you can get a read lock, but to write to
@@ -1681,7 +1672,7 @@ the amount of locking which needs to be done.
  #include &lt;linux/slab.h&gt;
  #include &lt;linux/string.h&gt;
 +#include &lt;linux/rcupdate.h&gt;
- #include &lt;linux/semaphore.h&gt;
+ #include &lt;linux/mutex.h&gt;
  #include &lt;asm/errno.h&gt;
 
  struct object
@@ -1913,7 +1904,7 @@ machines due to caching.
        </listitem>
        <listitem>
         <para>
-          <function> put_user()</function>
+          <function>put_user()</function>
         </para>
        </listitem>
       </itemizedlist>
@@ -1927,13 +1918,13 @@ machines due to caching.
 
      <listitem>
       <para>
-      <function>down_interruptible()</function> and
-      <function>down()</function>
+      <function>mutex_lock_interruptible()</function> and
+      <function>mutex_lock()</function>
       </para>
       <para>
-       There is a <function>down_trylock()</function> which can be
+       There is a <function>mutex_trylock()</function> which can be
        used inside interrupt context, as it will not sleep.
-       <function>up()</function> will also never sleep.
+       <function>mutex_unlock()</function> will also never sleep.
       </para>
      </listitem>
     </itemizedlist>
@@ -2023,7 +2014,7 @@ machines due to caching.
       <para>
         Prior to 2.5, or when <symbol>CONFIG_PREEMPT</symbol> is
         unset, processes in user context inside the kernel would not
-        preempt each other (ie. you had that CPU until you have it up,
+        preempt each other (ie. you had that CPU until you gave it up,
         except for interrupts).  With the addition of
         <symbol>CONFIG_PREEMPT</symbol> in 2.5.4, this changed: when
         in user context, higher priority tasks can "cut in": spinlocks
index 1fd6a1ec7591d5f4179cdf2a641f1b055c1f486a..8a5dc6e021ffa8b16b6dc2f997e115e77b1aaf70 100644 (file)
 
     <revhistory>
       <revision>
-       <revnumber>1.0&nbsp;</revnumber>
+       <revnumber>1.0</revnumber>
        <date>May 30, 2001</date>
        <revremark>Initial revision posted to linux-kernel</revremark>
       </revision>
       <revision>
-       <revnumber>1.1&nbsp;</revnumber>
+       <revnumber>1.1</revnumber>
        <date>June 3, 2001</date>
        <revremark>Revised after comments from linux-kernel</revremark>
       </revision>
index c2321903aa09adea7f64c00d300814cc32229d1f..21bc416d887efdfabfe4c03b22639b225d72909c 100644 (file)
@@ -48,7 +48,7 @@ IOVA generation is pretty generic. We used the same technique as vmalloc()
 but these are not global address spaces, but separate for each domain.
 Different DMA engines may support different number of domains.
 
-We also allocate gaurd pages with each mapping, so we can attempt to catch
+We also allocate guard pages with each mapping, so we can attempt to catch
 any overflow that might happen.
 
 
@@ -112,4 +112,4 @@ TBD
 
 - For compatibility testing, could use unity map domain for all devices, just
   provide a 1-1 for all useful memory under a single domain for all devices.
-- API for paravirt ops for abstracting functionlity for VMM folks.
+- API for paravirt ops for abstracting functionality for VMM folks.
index 118ca6e9404f47ded06c7ee3a287003d00377e56..f79ad9ff6031aa4ee622d9f0be3e0c1604e2d14b 100644 (file)
@@ -528,7 +528,33 @@ See more details on the proper patch format in the following
 references.
 
 
+16) Sending "git pull" requests  (from Linus emails)
 
+Please write the git repo address and branch name alone on the same line
+so that I can't even by mistake pull from the wrong branch, and so
+that a triple-click just selects the whole thing.
+
+So the proper format is something along the lines of:
+
+       "Please pull from
+
+               git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+        to get these changes:"
+
+so that I don't have to hunt-and-peck for the address and inevitably
+get it wrong (actually, I've only gotten it wrong a few times, and
+checking against the diffstat tells me when I get it wrong, but I'm
+just a lot more comfortable when I don't have to "look for" the right
+thing to pull, and double-check that I have the right branch-name).
+
+
+Please use "git diff -M --stat --summary" to generate the diffstat:
+the -M enables rename detection, and the summary enables a summary of
+new/deleted or renamed files.
+
+With rename detection, the statistics are rather different [...]
+because git will notice that a fair number of the changes are renames.
 
 -----------------------------------
 SECTION 2 - HINTS, TIPS, AND TRICKS
index 1443cd71d2631241f13286e544296ef286d91c90..8a12f0730c94da018615aebc8e657daf65eadd80 100644 (file)
@@ -11,6 +11,7 @@ the delays experienced by a task while
 a) waiting for a CPU (while being runnable)
 b) completion of synchronous block I/O initiated by the task
 c) swapping in pages
+d) memory reclaim
 
 and makes these statistics available to userspace through
 the taskstats interface.
@@ -41,7 +42,7 @@ this structure. See
      include/linux/taskstats.h
 for a description of the fields pertaining to delay accounting.
 It will generally be in the form of counters returning the cumulative
-delay seen for cpu, sync block I/O, swapin etc.
+delay seen for cpu, sync block I/O, swapin, memory reclaim etc.
 
 Taking the difference of two successive readings of a given
 counter (say cpu_delay_total) for a task will give the delay
@@ -94,7 +95,9 @@ CPU   count   real total      virtual total   delay total
        7876    92005750        100000000       24001500
 IO     count   delay total
        0       0
-MEM    count   delay total
+SWAP   count   delay total
+       0       0
+RECLAIM        count   delay total
        0       0
 
 Get delays seen in executing a given simple command
@@ -108,5 +111,7 @@ CPU count   real total      virtual total   delay total
        6       4000250         4000000         0
 IO     count   delay total
        0       0
-MEM    count   delay total
+SWAP   count   delay total
+       0       0
+RECLAIM        count   delay total
        0       0
index 40121b5cca14cab3993000c53078ef2d8484f001..3f7755f3963f11fd31ba598a8f6199371c87202f 100644 (file)
@@ -196,14 +196,18 @@ void print_delayacct(struct taskstats *t)
               "      %15llu%15llu%15llu%15llu\n"
               "IO    %15s%15s\n"
               "      %15llu%15llu\n"
-              "MEM   %15s%15s\n"
+              "SWAP  %15s%15s\n"
+              "      %15llu%15llu\n"
+              "RECLAIM  %12s%15s\n"
               "      %15llu%15llu\n",
               "count", "real total", "virtual total", "delay total",
               t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
               t->cpu_delay_total,
               "count", "delay total",
               t->blkio_count, t->blkio_delay_total,
-              "count", "delay total", t->swapin_count, t->swapin_delay_total);
+              "count", "delay total", t->swapin_count, t->swapin_delay_total,
+              "count", "delay total",
+              t->freepages_count, t->freepages_delay_total);
 }
 
 void task_context_switch_counts(struct taskstats *t)
index cd784f46bf8abefb9ed24257aaf5fcf4df2ecb00..e7512c061c1572f5127b7bb861ded0f0515bc6af 100644 (file)
@@ -6,7 +6,7 @@ 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
+    If CONFIG_TASKSTATS is set, the taskstats interface is enabled and
     the common fields and basic accounting fields are collected for
     delivery at do_exit() of a task.
 2) Delay accounting fields
@@ -26,6 +26,8 @@ There are three different groups of fields in the struct taskstats:
 
 5) Time accounting for SMT machines
 
+6) Extended delay accounting fields for memory reclaim
+
 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.
 
@@ -170,4 +172,9 @@ struct taskstats {
        __u64   ac_utimescaled;         /* utime scaled on frequency etc */
        __u64   ac_stimescaled;         /* stime scaled on frequency etc */
        __u64   cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
+
+6) Extended delay accounting fields for memory reclaim
+       /* Delay waiting for memory reclaim */
+       __u64   freepages_count;
+       __u64   freepages_delay_total;
 }
index 0d3dbf1099bcc90cae1b364002ef32e15dcdc06a..c202ed35d7d610dd3c399b50fdb65796917f1544 100644 (file)
@@ -138,14 +138,8 @@ So, what's changed?
 
                 Set active the IRQ edge(s)/level.  This replaces the
                 SA1111 INTPOL manipulation, and the set_GPIO_IRQ_edge()
-                function.  Type should be one of the following:
-
-                #define IRQT_NOEDGE     (0)
-                #define IRQT_RISING     (__IRQT_RISEDGE)
-                #define IRQT_FALLING    (__IRQT_FALEDGE)
-                #define IRQT_BOTHEDGE   (__IRQT_RISEDGE|__IRQT_FALEDGE)
-                #define IRQT_LOW        (__IRQT_LOWLVL)
-                #define IRQT_HIGH       (__IRQT_HIGHLVL)
+                function.  Type should be one of IRQ_TYPE_xxx defined in
+               <linux/irq.h>
 
 3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type.
 
diff --git a/Documentation/bt8xxgpio.txt b/Documentation/bt8xxgpio.txt
new file mode 100644 (file)
index 0000000..d8297e4
--- /dev/null
@@ -0,0 +1,67 @@
+===============================================================
+==  BT8XXGPIO driver                                         ==
+==                                                           ==
+==  A driver for a selfmade cheap BT8xx based PCI GPIO-card  ==
+==                                                           ==
+==  For advanced documentation, see                          ==
+==  http://www.bu3sch.de/btgpio.php                          ==
+===============================================================
+
+
+A generic digital 24-port PCI GPIO card can be built out of an ordinary
+Brooktree bt848, bt849, bt878 or bt879 based analog TV tuner card. The
+Brooktree chip is used in old analog Hauppauge WinTV PCI cards. You can easily
+find them used for low prices on the net.
+
+The bt8xx chip does have 24 digital GPIO ports.
+These ports are accessible via 24 pins on the SMD chip package.
+
+
+==============================================
+==  How to physically access the GPIO pins  ==
+==============================================
+
+The are several ways to access these pins. One might unsolder the whole chip
+and put it on a custom PCI board, or one might only unsolder each individual
+GPIO pin and solder that to some tiny wire. As the chip package really is tiny
+there are some advanced soldering skills needed in any case.
+
+The physical pinouts are drawn in the following ASCII art.
+The GPIO pins are marked with G00-G23
+
+                                           G G G G G G G G G G G G     G G G G G G
+                                           0 0 0 0 0 0 0 0 0 0 1 1     1 1 1 1 1 1
+                                           0 1 2 3 4 5 6 7 8 9 0 1     2 3 4 5 6 7
+           | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+           ---------------------------------------------------------------------------
+         --|                               ^                                     ^   |--
+         --|                               pin 86                           pin 67   |--
+         --|                                                                         |--
+         --|                                                               pin 61 >  |-- G18
+         --|                                                                         |-- G19
+         --|                                                                         |-- G20
+         --|                                                                         |-- G21
+         --|                                                                         |-- G22
+         --|                                                               pin 56 >  |-- G23
+         --|                                                                         |--
+         --|                           Brooktree 878/879                             |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|                                                                         |--
+         --|   O                                                                     |--
+         --|                                                                         |--
+           ---------------------------------------------------------------------------
+           | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+           ^
+           This is pin 1
+
index 866b9cd9a9590d6b6b8c3d577038e8d51234082b..9b53d5827361fd647f3388212e648f502defc698 100644 (file)
@@ -242,8 +242,7 @@ rmdir() if there are no tasks.
 1. Add support for accounting huge pages (as a separate controller)
 2. Make per-cgroup scanner reclaim not-shared pages first
 3. Teach controller to account for shared-pages
-4. Start reclamation when the limit is lowered
-5. Start reclamation in the background when the limit is
+4. Start reclamation in the background when the limit is
    not yet hit but the usage is getting closer
 
 Summary
index dcec0564d04075a9751e462968f956385405f283..5b0cfa67aff9c89ebc6d0f9dd4d467e8be8ae71f 100644 (file)
@@ -122,7 +122,7 @@ around '10000' or more.
 show_sampling_rate_(min|max): the minimum and maximum sampling rates
 available that you may set 'sampling_rate' to.
 
-up_threshold: defines what the average CPU usaged between the samplings
+up_threshold: defines what the average CPU usage between the samplings
 of 'sampling_rate' needs to be for the kernel to make a decision on
 whether it should increase the frequency.  For example when it is set
 to its default value of '80' it means that between the checking
index a5c36842ecef4ec103ff7f44b5499ed9963db0c2..8eda3fb664166726163bf59565c9d52c76af6c79 100644 (file)
@@ -222,74 +222,9 @@ both csrow2 and csrow3 are populated, this indicates a dual ranked
 set of DIMMs for channels 0 and 1.
 
 
-Within each of the 'mc','mcX' and 'csrowX' directories are several
+Within each of the 'mcX' and 'csrowX' directories are several
 EDAC control and attribute files.
 
-
-============================================================================
-DIRECTORY 'mc'
-
-In directory 'mc' are EDAC system overall control and attribute files:
-
-
-Panic on UE control file:
-
-       'edac_mc_panic_on_ue'
-
-       An uncorrectable error will cause a machine panic.  This is usually
-       desirable.  It is a bad idea to continue when an uncorrectable error
-       occurs - it is indeterminate what was uncorrected and the operating
-       system context might be so mangled that continuing will lead to further
-       corruption. If the kernel has MCE configured, then EDAC will never
-       notice the UE.
-
-       LOAD TIME: module/kernel parameter: panic_on_ue=[0|1]
-
-       RUN TIME:  echo "1" >/sys/devices/system/edac/mc/edac_mc_panic_on_ue
-
-
-Log UE control file:
-
-       'edac_mc_log_ue'
-
-       Generate kernel messages describing uncorrectable errors.  These errors
-       are reported through the system message log system.  UE statistics
-       will be accumulated even when UE logging is disabled.
-
-       LOAD TIME: module/kernel parameter: log_ue=[0|1]
-
-       RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ue
-
-
-Log CE control file:
-
-       'edac_mc_log_ce'
-
-       Generate kernel messages describing correctable errors.  These
-       errors are reported through the system message log system.
-       CE statistics will be accumulated even when CE logging is disabled.
-
-       LOAD TIME: module/kernel parameter: log_ce=[0|1]
-
-       RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ce
-
-
-Polling period control file:
-
-       'edac_mc_poll_msec'
-
-       The time period, in milliseconds, for polling for error information.
-       Too small a value wastes resources.  Too large a value might delay
-       necessary handling of errors and might loose valuable information for
-       locating the error.  1000 milliseconds (once each second) is the current
-       default. Systems which require all the bandwidth they can get, may
-       increase this.
-
-       LOAD TIME: module/kernel parameter: poll_msec=[0|1]
-
-       RUN TIME: echo "1000" >/sys/devices/system/edac/mc/edac_mc_poll_msec
-
-
 ============================================================================
 'mcX' DIRECTORIES
 
@@ -392,7 +327,7 @@ Sdram memory scrubbing rate:
        'sdram_scrub_rate'
 
        Read/Write attribute file that controls memory scrubbing. The scrubbing
-       rate is set by writing a minimum bandwith in bytes/sec to the attribute
+       rate is set by writing a minimum bandwidth in bytes/sec to the attribute
        file. The rate will be translated to an internal value that gives at
        least the specified rate.
 
@@ -537,7 +472,6 @@ Channel 1 DIMM Label control file:
        motherboard specific and determination of this information
        must occur in userland at this time.
 
-
 ============================================================================
 SYSTEM LOGGING
 
@@ -570,7 +504,6 @@ error type, a notice of "no info" and then an optional,
 driver-specific error message.
 
 
-
 ============================================================================
 PCI Bus Parity Detection
 
@@ -604,6 +537,74 @@ Enable/Disable PCI Parity checking control file:
        echo "0" >/sys/devices/system/edac/pci/check_pci_parity
 
 
+Parity Count:
+
+       'pci_parity_count'
+
+       This attribute file will display the number of parity errors that
+       have been detected.
+
+
+============================================================================
+MODULE PARAMETERS
+
+Panic on UE control file:
+
+       'edac_mc_panic_on_ue'
+
+       An uncorrectable error will cause a machine panic.  This is usually
+       desirable.  It is a bad idea to continue when an uncorrectable error
+       occurs - it is indeterminate what was uncorrected and the operating
+       system context might be so mangled that continuing will lead to further
+       corruption. If the kernel has MCE configured, then EDAC will never
+       notice the UE.
+
+       LOAD TIME: module/kernel parameter: edac_mc_panic_on_ue=[0|1]
+
+       RUN TIME:  echo "1" > /sys/module/edac_core/parameters/edac_mc_panic_on_ue
+
+
+Log UE control file:
+
+       'edac_mc_log_ue'
+
+       Generate kernel messages describing uncorrectable errors.  These errors
+       are reported through the system message log system.  UE statistics
+       will be accumulated even when UE logging is disabled.
+
+       LOAD TIME: module/kernel parameter: edac_mc_log_ue=[0|1]
+
+       RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ue
+
+
+Log CE control file:
+
+       'edac_mc_log_ce'
+
+       Generate kernel messages describing correctable errors.  These
+       errors are reported through the system message log system.
+       CE statistics will be accumulated even when CE logging is disabled.
+
+       LOAD TIME: module/kernel parameter: edac_mc_log_ce=[0|1]
+
+       RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ce
+
+
+Polling period control file:
+
+       'edac_mc_poll_msec'
+
+       The time period, in milliseconds, for polling for error information.
+       Too small a value wastes resources.  Too large a value might delay
+       necessary handling of errors and might loose valuable information for
+       locating the error.  1000 milliseconds (once each second) is the current
+       default. Systems which require all the bandwidth they can get, may
+       increase this.
+
+       LOAD TIME: module/kernel parameter: edac_mc_poll_msec=[0|1]
+
+       RUN TIME: echo "1000" > /sys/module/edac_core/parameters/edac_mc_poll_msec
+
 
 Panic on PCI PARITY Error:
 
@@ -614,21 +615,13 @@ Panic on PCI PARITY Error:
        error has been detected.
 
 
-       module/kernel parameter: panic_on_pci_parity=[0|1]
+       module/kernel parameter: edac_panic_on_pci_pe=[0|1]
 
        Enable:
-       echo "1" >/sys/devices/system/edac/pci/panic_on_pci_parity
+       echo "1" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
 
        Disable:
-       echo "0" >/sys/devices/system/edac/pci/panic_on_pci_parity
-
-
-Parity Count:
-
-       'pci_parity_count'
-
-       This attribute file will display the number of parity errors that
-       have been detected.
+       echo "0" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
 
 
 
diff --git a/Documentation/fb/sh7760fb.txt b/Documentation/fb/sh7760fb.txt
new file mode 100644 (file)
index 0000000..c87bfe5
--- /dev/null
@@ -0,0 +1,131 @@
+SH7760/SH7763 integrated LCDC Framebuffer driver
+================================================
+
+0. Overwiew
+-----------
+The SH7760/SH7763 have an integrated LCD Display controller (LCDC) which
+supports (in theory) resolutions ranging from 1x1 to 1024x1024,
+with color depths ranging from 1 to 16 bits, on STN, DSTN and TFT Panels.
+
+Caveats:
+* Framebuffer memory must be a large chunk allocated at the top
+  of Area3 (HW requirement). Because of this requirement you should NOT
+  make the driver a module since at runtime it may become impossible to
+  get a large enough contiguous chunk of memory.
+
+* The driver does not support changing resolution while loaded
+  (displays aren't hotpluggable anyway)
+
+* Heavy flickering may be observed
+  a) if you're using 15/16bit color modes at >= 640x480 px resolutions,
+  b) during PCMCIA (or any other slow bus) activity.
+
+* Rotation works only 90degress clockwise, and only if horizontal
+  resolution is <= 320 pixels.
+
+files:   drivers/video/sh7760fb.c
+        include/asm-sh/sh7760fb.h
+        Documentation/fb/sh7760fb.txt
+
+1. Platform setup
+-----------------
+SH7760:
+ Video data is fetched via the DMABRG DMA engine, so you have to
+ configure the SH DMAC for DMABRG mode (write 0x94808080 to the
+ DMARSRA register somewhere at boot).
+
+ PFC registers PCCR and PCDR must be set to peripheral mode.
+ (write zeros to both).
+
+The driver does NOT do the above for you since board setup is, well, job
+of the board setup code.
+
+2. Panel definitions
+--------------------
+The LCDC must explicitly be told about the type of LCD panel
+attached.  Data must be wrapped in a "struct sh7760fb_platdata" and
+passed to the driver as platform_data.
+
+Suggest you take a closer look at the SH7760 Manual, Section 30.
+(http://documentation.renesas.com/eng/products/mpumcu/e602291_sh7760.pdf)
+
+The following code illustrates what needs to be done to
+get the framebuffer working on a 640x480 TFT:
+
+====================== cut here ======================================
+
+#include <linux/fb.h>
+#include <asm/sh7760fb.h>
+
+/*
+ * NEC NL6440bc26-01 640x480 TFT
+ * dotclock 25175 kHz
+ * Xres                640     Yres            480
+ * Htotal      800     Vtotal          525
+ * HsynStart   656     VsynStart       490
+ * HsynLenn    30      VsynLenn        2
+ *
+ * The linux framebuffer layer does not use the syncstart/synclen
+ * values but right/left/upper/lower margin values. The comments
+ * for the x_margin explain how to calculate those from given
+ * panel sync timings.
+ */
+static struct fb_videomode nl6448bc26 = {
+       .name           = "NL6448BC26",
+       .refresh        = 60,
+       .xres           = 640,
+       .yres           = 480,
+       .pixclock       = 39683,        /* in picoseconds! */
+       .hsync_len      = 30,
+       .vsync_len      = 2,
+       .left_margin    = 114,  /* HTOT - (HSYNSLEN + HSYNSTART) */
+       .right_margin   = 16,   /* HSYNSTART - XRES */
+       .upper_margin   = 33,   /* VTOT - (VSYNLEN + VSYNSTART) */
+       .lower_margin   = 10,   /* VSYNSTART - YRES */
+       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+       .vmode          = FB_VMODE_NONINTERLACED,
+       .flag           = 0,
+};
+
+static struct sh7760fb_platdata sh7760fb_nl6448 = {
+       .def_mode       = &nl6448bc26,
+       .ldmtr          = LDMTR_TFT_COLOR_16,   /* 16bit TFT panel */
+       .lddfr          = LDDFR_8BPP,           /* we want 8bit output */
+       .ldpmmr         = 0x0070,
+       .ldpspr         = 0x0500,
+       .ldaclnr        = 0,
+       .ldickr         = LDICKR_CLKSRC(LCDC_CLKSRC_EXTERNAL) |
+                         LDICKR_CLKDIV(1),
+       .rotate         = 0,
+       .novsync        = 1,
+       .blank          = NULL,
+};
+
+/* SH7760:
+ * 0xFE300800: 256 * 4byte xRGB palette ram
+ * 0xFE300C00: 42 bytes ctrl registers
+ */
+static struct resource sh7760_lcdc_res[] = {
+       [0] = {
+               .start  = 0xFE300800,
+               .end    = 0xFE300CFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 65,
+               .end    = 65,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device sh7760_lcdc_dev = {
+       .dev    = {
+               .platform_data = &sh7760fb_nl6448,
+       },
+       .name           = "sh7760-lcdc",
+       .id             = -1,
+       .resource       = sh7760_lcdc_res,
+       .num_resources  = ARRAY_SIZE(sh7760_lcdc_res),
+};
+
+====================== cut here ======================================
index 8a6c8a43e6a37803e4fcbd640f1b4578f5a611c6..45d9de5b13a3cb9f8143484d49737ae87254fdf7 100644 (file)
@@ -3,11 +3,25 @@ Tridentfb is a framebuffer driver for some Trident chip based cards.
 The following list of chips is thought to be supported although not all are
 tested:
 
-those from the Image series with Cyber in their names - accelerated
-those with Blade in their names (Blade3D,CyberBlade...) - accelerated
-the newer CyberBladeXP family  - nonaccelerated
-
-Only PCI/AGP based cards are supported, none of the older Tridents.
+those from the TGUI series 9440/96XX and with Cyber in their names
+those from the Image series and with Cyber in their names
+those with Blade in their names (Blade3D,CyberBlade...)
+the newer CyberBladeXP family
+
+All families are accelerated. Only PCI/AGP based cards are supported,
+none of the older Tridents.
+The driver supports 8, 16 and 32 bits per pixel depths.
+The TGUI family requires a line length to be power of 2 if acceleration
+is enabled. This means that range of possible resolutions and bpp is
+limited comparing to the range if acceleration is disabled (see list
+of parameters below).
+
+Known bugs:
+1. The driver randomly locks up on 3DImage975 chip with acceleration
+   enabled. The same happens in X11 (Xorg).
+2. The ramdac speeds require some more fine tuning. It is possible to
+   switch resolution which the chip does not support at some depths for
+   older chips.
 
 How to use it?
 ==============
@@ -17,12 +31,11 @@ video=tridentfb
 
 The parameters for tridentfb are concatenated with a ':' as in this example.
 
-video=tridentfb:800x600,bpp=16,noaccel
+video=tridentfb:800x600-16@75,noaccel
 
 The second level parameters that tridentfb understands are:
 
 noaccel - turns off acceleration (when it doesn't work for your card)
-accel - force text acceleration (for boards which by default are noacceled)
 
 fp     - use flat panel related stuff
 crt    - assume monitor is present instead of fp
@@ -31,21 +44,24 @@ center      - for flat panels and resolutions smaller than native size center the
          image, otherwise use
 stretch
 
-memsize - integer value in Kb, use if your card's memory size is misdetected.
+memsize - integer value in KB, use if your card's memory size is misdetected.
          look at the driver output to see what it says when initializing.
-memdiff - integer value in Kb,should be nonzero if your card reports
-         more memory than it actually has.For instance mine is 192K less than
+
+memdiff - integer value in KB, should be nonzero if your card reports
+         more memory than it actually has. For instance mine is 192K less than
          detection says in all three BIOS selectable situations 2M, 4M, 8M.
          Only use if your video memory is taken from main memory hence of
-         configurable size.Otherwise use memsize.
-         If in some modes which barely fit the memory you see garbage at the bottom
-         this might help by not letting change to that mode anymore.
+         configurable size. Otherwise use memsize.
+         If in some modes which barely fit the memory you see garbage
+         at the bottom this might help by not letting change to that mode
+         anymore.
 
 nativex - the width in pixels of the flat panel.If you know it (usually 1024
          800 or 1280) and it is not what the driver seems to detect use it.
 
-bpp  - bits per pixel (8,16 or 32)
-mode - a mode name like 800x600 (as described in Documentation/fb/modedb.txt)
+bpp    - bits per pixel (8,16 or 32)
+mode   - a mode name like 800x600-8@75 as described in
+         Documentation/fb/modedb.txt
 
 Using insane values for the above parameters will probably result in driver
 misbehaviour so take care(for instance memsize=12345678 or memdiff=23784 or
index 9f73587219e87a601f361b0942530888e56c3303..c23955404bf5d5056f7ddf448ea52415b6d3adfd 100644 (file)
@@ -47,6 +47,30 @@ Who: Mauro Carvalho Chehab <mchehab@infradead.org>
 
 ---------------------------
 
+What:  old tuner-3036 i2c driver
+When:  2.6.28
+Why:   This driver is for VERY old i2c-over-parallel port teletext receiver
+       boxes. Rather then spending effort on converting this driver to V4L2,
+       and since it is extremely unlikely that anyone still uses one of these
+       devices, it was decided to drop it.
+Who:   Hans Verkuil <hverkuil@xs4all.nl>
+       Mauro Carvalho Chehab <mchehab@infradead.org>
+
+ ---------------------------
+
+What:   V4L2 dpc7146 driver
+When:   2.6.28
+Why:    Old driver for the dpc7146 demonstration board that is no longer
+       relevant. The last time this was tested on actual hardware was
+       probably around 2002. Since this is a driver for a demonstration
+       board the decision was made to remove it rather than spending a
+       lot of effort continually updating this driver to stay in sync
+       with the latest internal V4L2 or I2C API.
+Who:    Hans Verkuil <hverkuil@xs4all.nl>
+       Mauro Carvalho Chehab <mchehab@infradead.org>
+
+---------------------------
+
 What:  PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
 When:  November 2005
 Files: drivers/pcmcia/: pcmcia_ioctl.c
@@ -138,24 +162,6 @@ Who:       Kay Sievers <kay.sievers@suse.de>
 
 ---------------------------
 
-What:  find_task_by_pid
-When:  2.6.26
-Why:   With pid namespaces, calling this funciton will return the
-       wrong task when called from inside a namespace.
-
-       The best way to save a task pid and find a task by this
-       pid later, is to find this task's struct pid pointer (or get
-       it directly from the task) and call pid_task() later.
-
-       If someone really needs to get a task by its pid_t, then
-       he most likely needs the find_task_by_vpid() to get the
-       task from the same namespace as the current task is in, but
-       this may be not so in general.
-
-Who:   Pavel Emelyanov <xemul@openvz.org>
-
----------------------------
-
 What:  ACPI procfs interface
 When:  July 2008
 Why:   ACPI sysfs conversion should be finished by January 2008.
@@ -300,14 +306,6 @@ Who:       ocfs2-devel@oss.oracle.com
 
 ---------------------------
 
-What:  asm/semaphore.h
-When:  2.6.26
-Why:   Implementation became generic; users should now include
-       linux/semaphore.h instead.
-Who:   Matthew Wilcox <willy@linux.intel.com>
-
----------------------------
-
 What:  SCTP_GET_PEER_ADDRS_NUM_OLD, SCTP_GET_PEER_ADDRS_OLD,
        SCTP_GET_LOCAL_ADDRS_NUM_OLD, SCTP_GET_LOCAL_ADDRS_OLD
 When:  June 2009
index 8b22d7d8b99166b6db2e037644e9c5d7ff03695e..680fb566b9286bcc71a527c5f75d4b94fc9ac215 100644 (file)
@@ -510,6 +510,7 @@ prototypes:
        void (*close)(struct vm_area_struct*);
        int (*fault)(struct vm_area_struct*, struct vm_fault *);
        int (*page_mkwrite)(struct vm_area_struct *, struct page *);
+       int (*access)(struct vm_area_struct *, unsigned long, void*, int, int);
 
 locking rules:
                BKL     mmap_sem        PageLocked(page)
@@ -517,6 +518,7 @@ open:               no      yes
 close:         no      yes
 fault:         no      yes
 page_mkwrite:  no      yes             no
+access:                no      yes
 
        ->page_mkwrite() is called when a previously read-only page is
 about to become writeable. The file system is responsible for
@@ -525,6 +527,11 @@ taking to lock out truncate, the page range should be verified to be
 within i_size. The page mapping should also be checked that it is not
 NULL.
 
+       ->access() is called when get_user_pages() fails in
+acces_process_vm(), typically used to debug a process through
+/proc/pid/mem or ptrace.  This function is needed only for
+VM_IO | VM_PFNMAP VMAs.
+
 ================================================================================
                        Dubious stuff
 
diff --git a/Documentation/filesystems/omfs.txt b/Documentation/filesystems/omfs.txt
new file mode 100644 (file)
index 0000000..1d0d41f
--- /dev/null
@@ -0,0 +1,106 @@
+Optimized MPEG Filesystem (OMFS)
+
+Overview
+========
+
+OMFS is a filesystem created by SonicBlue for use in the ReplayTV DVR
+and Rio Karma MP3 player.  The filesystem is extent-based, utilizing
+block sizes from 2k to 8k, with hash-based directories.  This
+filesystem driver may be used to read and write disks from these
+devices.
+
+Note, it is not recommended that this FS be used in place of a general
+filesystem for your own streaming media device.  Native Linux filesystems
+will likely perform better.
+
+More information is available at:
+
+    http://linux-karma.sf.net/
+
+Various utilities, including mkomfs and omfsck, are included with
+omfsprogs, available at:
+
+    http://bobcopeland.com/karma/
+
+Instructions are included in its README.
+
+Options
+=======
+
+OMFS supports the following mount-time options:
+
+    uid=n        - make all files owned by specified user
+    gid=n        - make all files owned by specified group
+    umask=xxx    - set permission umask to xxx
+    fmask=xxx    - set umask to xxx for files
+    dmask=xxx    - set umask to xxx for directories
+
+Disk format
+===========
+
+OMFS discriminates between "sysblocks" and normal data blocks.  The sysblock
+group consists of super block information, file metadata, directory structures,
+and extents.  Each sysblock has a header containing CRCs of the entire
+sysblock, and may be mirrored in successive blocks on the disk.  A sysblock may
+have a smaller size than a data block, but since they are both addressed by the
+same 64-bit block number, any remaining space in the smaller sysblock is
+unused.
+
+Sysblock header information:
+
+struct omfs_header {
+        __be64 h_self;                  /* FS block where this is located */
+        __be32 h_body_size;             /* size of useful data after header */
+        __be16 h_crc;                   /* crc-ccitt of body_size bytes */
+        char h_fill1[2];
+        u8 h_version;                   /* version, always 1 */
+        char h_type;                    /* OMFS_INODE_X */
+        u8 h_magic;                     /* OMFS_IMAGIC */
+        u8 h_check_xor;                 /* XOR of header bytes before this */
+        __be32 h_fill2;
+};
+
+Files and directories are both represented by omfs_inode:
+
+struct omfs_inode {
+        struct omfs_header i_head;      /* header */
+        __be64 i_parent;                /* parent containing this inode */
+        __be64 i_sibling;               /* next inode in hash bucket */
+        __be64 i_ctime;                 /* ctime, in milliseconds */
+        char i_fill1[35];
+        char i_type;                    /* OMFS_[DIR,FILE] */
+        __be32 i_fill2;
+        char i_fill3[64];
+        char i_name[OMFS_NAMELEN];      /* filename */
+        __be64 i_size;                  /* size of file, in bytes */
+};
+
+Directories in OMFS are implemented as a large hash table.  Filenames are
+hashed then prepended into the bucket list beginning at OMFS_DIR_START.
+Lookup requires hashing the filename, then seeking across i_sibling pointers
+until a match is found on i_name.  Empty buckets are represented by block
+pointers with all-1s (~0).
+
+A file is an omfs_inode structure followed by an extent table beginning at
+OMFS_EXTENT_START:
+
+struct omfs_extent_entry {
+        __be64 e_cluster;               /* start location of a set of blocks */
+        __be64 e_blocks;                /* number of blocks after e_cluster */
+};
+
+struct omfs_extent {
+        __be64 e_next;                  /* next extent table location */
+        __be32 e_extent_count;          /* total # extents in this table */
+        __be32 e_fill;
+        struct omfs_extent_entry e_entry;       /* start of extent entries */
+};
+
+Each extent holds the block offset followed by number of blocks allocated to
+the extent.  The final extent in each table is a terminator with e_cluster
+being ~0 and e_blocks being ones'-complement of the total number of blocks
+in the table.
+
+If this table overflows, a continuation inode is written and pointed to by
+e_next.  These have a header but lack the rest of the inode structure.
+
index 7f268f327d750e725f1e5ca5ddfe99dcb8014cd5..64557821ee5984f5babe336f701f172b8602a4dc 100644 (file)
@@ -296,6 +296,7 @@ Table 1-4: Kernel info in /proc
  uptime      System uptime                                     
  version     Kernel version                                    
  video      bttv info of video resources                       (2.4)
+ vmallocinfo Show vmalloced areas
 ..............................................................................
 
 You can,  for  example,  check  which interrupts are currently in use and what
@@ -557,6 +558,49 @@ VmallocTotal: total size of vmalloc memory area
  VmallocUsed: amount of vmalloc area which is used
 VmallocChunk: largest contigious block of vmalloc area which is free
 
+..............................................................................
+
+vmallocinfo:
+
+Provides information about vmalloced/vmaped areas. One line per area,
+containing the virtual address range of the area, size in bytes,
+caller information of the creator, and optional information depending
+on the kind of area :
+
+ pages=nr    number of pages
+ phys=addr   if a physical address was specified
+ ioremap     I/O mapping (ioremap() and friends)
+ vmalloc     vmalloc() area
+ vmap        vmap()ed pages
+ user        VM_USERMAP area
+ vpages      buffer for pages pointers was vmalloced (huge area)
+ N<node>=nr  (Only on NUMA kernels)
+             Number of pages allocated on memory node <node>
+
+> cat /proc/vmallocinfo
+0xffffc20000000000-0xffffc20000201000 2101248 alloc_large_system_hash+0x204 ...
+  /0x2c0 pages=512 vmalloc N0=128 N1=128 N2=128 N3=128
+0xffffc20000201000-0xffffc20000302000 1052672 alloc_large_system_hash+0x204 ...
+  /0x2c0 pages=256 vmalloc N0=64 N1=64 N2=64 N3=64
+0xffffc20000302000-0xffffc20000304000    8192 acpi_tb_verify_table+0x21/0x4f...
+  phys=7fee8000 ioremap
+0xffffc20000304000-0xffffc20000307000   12288 acpi_tb_verify_table+0x21/0x4f...
+  phys=7fee7000 ioremap
+0xffffc2000031d000-0xffffc2000031f000    8192 init_vdso_vars+0x112/0x210
+0xffffc2000031f000-0xffffc2000032b000   49152 cramfs_uncompress_init+0x2e ...
+  /0x80 pages=11 vmalloc N0=3 N1=3 N2=2 N3=3
+0xffffc2000033a000-0xffffc2000033d000   12288 sys_swapon+0x640/0xac0      ...
+  pages=2 vmalloc N1=2
+0xffffc20000347000-0xffffc2000034c000   20480 xt_alloc_table_info+0xfe ...
+  /0x130 [x_tables] pages=4 vmalloc N0=4
+0xffffffffa0000000-0xffffffffa000f000   61440 sys_init_module+0xc27/0x1d00 ...
+   pages=14 vmalloc N2=14
+0xffffffffa000f000-0xffffffffa0014000   20480 sys_init_module+0xc27/0x1d00 ...
+   pages=4 vmalloc N1=4
+0xffffffffa0014000-0xffffffffa0017000   12288 sys_init_module+0xc27/0x1d00 ...
+   pages=2 vmalloc N1=2
+0xffffffffa0017000-0xffffffffa0022000   45056 sys_init_module+0xc27/0x1d00 ...
+   pages=10 vmalloc N0=10
 
 1.3 IDE devices in /proc/ide
 ----------------------------
@@ -887,7 +931,7 @@ group_prealloc  max_to_scan  mb_groups  mb_history  min_to_scan  order2_req
 stats  stream_req
 
 mb_groups:
-This file gives the details of mutiblock allocator buddy cache of free blocks
+This file gives the details of multiblock allocator buddy cache of free blocks
 
 mb_history:
 Multiblock allocation history.
@@ -1430,7 +1474,7 @@ used because pages_free(1355) is smaller than watermark + protection[2]
 normal page requirement. If requirement is DMA zone(index=0), protection[0]
 (=0) is used.
 
-zone[i]'s protection[j] is calculated by following exprssion.
+zone[i]'s protection[j] is calculated by following expression.
 
 (i < j):
   zone[i]->protection[j]
index 094f2d2f38b1a5571283ee745aa494c12b12808c..510b722667ac885cf7abed3732961941a5ad1c14 100644 (file)
@@ -294,6 +294,16 @@ user-defined data with a channel, and is immediately available
 (including in create_buf_file()) via chan->private_data or
 buf->chan->private_data.
 
+Buffer-only channels
+--------------------
+
+These channels have no files associated and can be created with
+relay_open(NULL, NULL, ...). Such channels are useful in scenarios such
+as when doing early tracing in the kernel, before the VFS is up. In these
+cases, one may open a buffer-only channel and then call
+relay_late_setup_files() when the kernel is ready to handle files,
+to expose the buffered data to the userspace.
+
 Channel 'modes'
 ---------------
 
index 2d5e1e582e13272bfaef2fbc494a156d829cc289..bbac4f1d90567c3f7ea0f46a869c091160390076 100644 (file)
@@ -96,6 +96,14 @@ shortname=lower|win95|winnt|mixed
                        emulate the Windows 95 rule for create.
                 Default setting is `lower'.
 
+tz=UTC        -- Interpret timestamps as UTC rather than local time.
+                 This option disables the conversion of timestamps
+                 between local time (as used by Windows on FAT) and UTC
+                 (which Linux uses internally).  This is particuluarly
+                 useful when mounting devices (like digital cameras)
+                 that are set to UTC in order to avoid the pitfalls of
+                 local time.
+
 <bool>: 0,1,yes,no,true,false
 
 TODO
index b7522c6cbae3758f77cb12e22b78825e43a3796d..c4d348dabe9499454055ebff41fb88ef71346dda 100644 (file)
@@ -143,7 +143,7 @@ struct file_system_type {
 
 The get_sb() method has the following arguments:
 
-  struct file_system_type *fs_type: decribes the filesystem, partly initialized
+  struct file_system_type *fs_type: describes the filesystem, partly initialized
        by the specific filesystem code
 
   int flags: mount flags
@@ -895,9 +895,9 @@ struct dentry_operations {
        iput() yourself
 
   d_dname: called when the pathname of a dentry should be generated.
-       Usefull for some pseudo filesystems (sockfs, pipefs, ...) to delay
+       Useful for some pseudo filesystems (sockfs, pipefs, ...) to delay
        pathname generation. (Instead of doing it when dentry is created,
-       its done only when the path is needed.). Real filesystems probably
+       it's done only when the path is needed.). Real filesystems probably
        dont want to use it, because their dentries are present in global
        dcache hash, so their hash should be an invariant. As no lock is
        held, d_dname() should not try to modify the dentry itself, unless
index c35ca9e40d4ca8ae0cbf7c06c639d8531ae8d9dd..18022e249c53dc1ad991d74d160551fa32f32070 100644 (file)
@@ -347,15 +347,12 @@ necessarily be nonportable.
 Dynamic definition of GPIOs is not currently standard; for example, as
 a side effect of configuring an add-on board with some GPIO expanders.
 
-These calls are purely for kernel space, but a userspace API could be built
-on top of them.
-
 
 GPIO implementor's framework (OPTIONAL)
 =======================================
 As noted earlier, there is an optional implementation framework making it
 easier for platforms to support different kinds of GPIO controller using
-the same programming interface.
+the same programming interface.  This framework is called "gpiolib".
 
 As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
 will be found there.  That will list all the controllers registered through
@@ -392,11 +389,21 @@ either NULL or the label associated with that GPIO when it was requested.
 
 Platform Support
 ----------------
-To support this framework, a platform's Kconfig will "select HAVE_GPIO_LIB"
+To support this framework, a platform's Kconfig will "select" either
+ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB
 and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
 three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
 They may also want to provide a custom value for ARCH_NR_GPIOS.
 
+ARCH_REQUIRE_GPIOLIB means that the gpio-lib code will always get compiled
+into the kernel on that architecture.
+
+ARCH_WANT_OPTIONAL_GPIOLIB means the gpio-lib code defaults to off and the user
+can enable it and build it into the kernel optionally.
+
+If neither of these options are selected, the platform does not support
+GPIOs through GPIO-lib and the code cannot be enabled by the user.
+
 Trivial implementations of those functions can directly use framework
 code, which always dispatches through the gpio_chip:
 
@@ -439,4 +446,120 @@ becomes available.  That may mean the device should not be registered until
 calls for that GPIO can work.  One way to address such dependencies is for
 such gpio_chip controllers to provide setup() and teardown() callbacks to
 board specific code; those board specific callbacks would register devices
-once all the necessary resources are available.
+once all the necessary resources are available, and remove them later when
+the GPIO controller device becomes unavailable.
+
+
+Sysfs Interface for Userspace (OPTIONAL)
+========================================
+Platforms which use the "gpiolib" implementors framework may choose to
+configure a sysfs user interface to GPIOs.  This is different from the
+debugfs interface, since it provides control over GPIO direction and
+value instead of just showing a gpio state summary.  Plus, it could be
+present on production systems without debugging support.
+
+Given approprate hardware documentation for the system, userspace could
+know for example that GPIO #23 controls the write protect line used to
+protect boot loader segments in flash memory.  System upgrade procedures
+may need to temporarily remove that protection, first importing a GPIO,
+then changing its output state, then updating the code before re-enabling
+the write protection.  In normal use, GPIO #23 would never be touched,
+and the kernel would have no need to know about it.
+
+Again depending on appropriate hardware documentation, on some systems
+userspace GPIO can be used to determine system configuration data that
+standard kernels won't know about.  And for some tasks, simple userspace
+GPIO drivers could be all that the system really needs.
+
+Note that standard kernel drivers exist for common "LEDs and Buttons"
+GPIO tasks:  "leds-gpio" and "gpio_keys", respectively.  Use those
+instead of talking directly to the GPIOs; they integrate with kernel
+frameworks better than your userspace code could.
+
+
+Paths in Sysfs
+--------------
+There are three kinds of entry in /sys/class/gpio:
+
+   -   Control interfaces used to get userspace control over GPIOs;
+
+   -   GPIOs themselves; and
+
+   -   GPIO controllers ("gpio_chip" instances).
+
+That's in addition to standard files including the "device" symlink.
+
+The control interfaces are write-only:
+
+    /sys/class/gpio/
+
+       "export" ... Userspace may ask the kernel to export control of
+               a GPIO to userspace by writing its number to this file.
+
+               Example:  "echo 19 > export" will create a "gpio19" node
+               for GPIO #19, if that's not requested by kernel code.
+
+       "unexport" ... Reverses the effect of exporting to userspace.
+
+               Example:  "echo 19 > unexport" will remove a "gpio19"
+               node exported using the "export" file.
+
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+       "direction" ... reads as either "in" or "out".  This value may
+               normally be written.  Writing as "out" defaults to
+               initializing the value as low.  To ensure glitch free
+               operation, values "low" and "high" may be written to
+               configure the GPIO as an output with that initial value.
+
+               Note that this attribute *will not exist* if the kernel
+               doesn't support changing the direction of a GPIO, or
+               it was exported by kernel code that didn't explicitly
+               allow userspace to reconfigure this GPIO's direction.
+
+       "value" ... reads as either 0 (low) or 1 (high).  If the GPIO
+               is configured as an output, this value may be written;
+               any nonzero value is treated as high.
+
+GPIO controllers have paths like /sys/class/gpio/chipchip42/ (for the
+controller implementing GPIOs starting at #42) and have the following
+read-only attributes:
+
+    /sys/class/gpio/gpiochipN/
+
+       "base" ... same as N, the first GPIO managed by this chip
+
+       "label" ... provided for diagnostics (not always unique)
+
+       "ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
+
+Board documentation should in most cases cover what GPIOs are used for
+what purposes.  However, those numbers are not always stable; GPIOs on
+a daughtercard might be different depending on the base board being used,
+or other cards in the stack.  In such cases, you may need to use the
+gpiochip nodes (possibly in conjunction with schematics) to determine
+the correct GPIO number to use for a given signal.
+
+
+Exporting from Kernel code
+--------------------------
+Kernel code can explicitly manage exports of GPIOs which have already been
+requested using gpio_request():
+
+       /* export the GPIO to userspace */
+       int gpio_export(unsigned gpio, bool direction_may_change);
+
+       /* reverse gpio_export() */
+       void gpio_unexport();
+
+After a kernel driver requests a GPIO, it may only be made available in
+the sysfs interface by gpio_export().  The driver can control whether the
+signal direction may change.  This helps drivers prevent userspace code
+from accidentally clobbering important system state.
+
+This explicit exporting can help with debugging (by making some kinds
+of experiments easier), or can provide an always-there interface that's
+suitable for documenting as part of a board support package.
diff --git a/Documentation/i2c/upgrading-clients b/Documentation/i2c/upgrading-clients
new file mode 100644 (file)
index 0000000..9a45f9b
--- /dev/null
@@ -0,0 +1,281 @@
+Upgrading I2C Drivers to the new 2.6 Driver Model
+=================================================
+
+Ben Dooks <ben-linux@fluff.org>
+
+Introduction
+------------
+
+This guide outlines how to alter existing Linux 2.6 client drivers from
+the old to the new new binding methods.
+
+
+Example old-style driver
+------------------------
+
+
+struct example_state {
+       struct i2c_client       client;
+       ....
+};
+
+static struct i2c_driver example_driver;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static int example_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct example_state *state;
+       struct device *dev = &adap->dev;  /* to use for dev_ reports */
+       int ret;
+
+       state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
+       if (state == NULL) {
+               dev_err(dev, "failed to create our state\n");
+               return -ENOMEM;
+       }
+
+       example->client.addr    = addr;
+       example->client.flags   = 0;
+       example->client.adapter = adap;
+
+       i2c_set_clientdata(&state->i2c_client, state);
+       strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);
+
+       ret = i2c_attach_client(&state->i2c_client);
+       if (ret < 0) {
+               dev_err(dev, "failed to attach client\n");
+               kfree(state);
+               return ret;
+       }
+
+       dev = &state->i2c_client.dev;
+
+       /* rest of the initialisation goes here. */
+
+       dev_info(dev, "example client created\n");
+
+       return 0;
+}
+
+static int __devexit example_detach(struct i2c_client *client)
+{
+       struct example_state *state = i2c_get_clientdata(client);
+
+       i2c_detach_client(client);
+       kfree(state);
+       return 0;
+}
+
+static int example_attach_adapter(struct i2c_adapter *adap)
+{
+       return i2c_probe(adap, &addr_data, example_attach);
+}
+
+static struct i2c_driver example_driver = {
+       .driver         = {
+               .owner          = THIS_MODULE,
+               .name           = "example",
+       },
+       .attach_adapter = example_attach_adapter,
+       .detach_client  = __devexit_p(example_detach),
+       .suspend        = example_suspend,
+       .resume         = example_resume,
+};
+
+
+Updating the client
+-------------------
+
+The new style binding model will check against a list of supported
+devices and their associated address supplied by the code registering
+the busses. This means that the driver .attach_adapter and
+.detach_adapter methods can be removed, along with the addr_data,
+as follows:
+
+- static struct i2c_driver example_driver;
+
+- static unsigned short ignore[] = { I2C_CLIENT_END };
+- static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
+
+- I2C_CLIENT_INSMOD;
+
+- static int example_attach_adapter(struct i2c_adapter *adap)
+- {
+-      return i2c_probe(adap, &addr_data, example_attach);
+- }
+
+ static struct i2c_driver example_driver = {
+-      .attach_adapter = example_attach_adapter,
+-      .detach_client  = __devexit_p(example_detach),
+ }
+
+Add the probe and remove methods to the i2c_driver, as so:
+
+ static struct i2c_driver example_driver = {
++      .probe          = example_probe,
++      .remove         = __devexit_p(example_remove),
+ }
+
+Change the example_attach method to accept the new parameters
+which include the i2c_client that it will be working with:
+
+- static int example_attach(struct i2c_adapter *adap, int addr, int kind)
++ static int example_probe(struct i2c_client *client,
++                         const struct i2c_device_id *id)
+
+Change the name of example_attach to example_probe to align it with the
+i2c_driver entry names. The rest of the probe routine will now need to be
+changed as the i2c_client has already been setup for use.
+
+The necessary client fields have already been setup before
+the probe function is called, so the following client setup
+can be removed:
+
+-      example->client.addr    = addr;
+-      example->client.flags   = 0;
+-      example->client.adapter = adap;
+-
+-      strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);
+
+The i2c_set_clientdata is now:
+
+-      i2c_set_clientdata(&state->client, state);
++      i2c_set_clientdata(client, state);
+
+The call to i2c_attach_client is no longer needed, if the probe
+routine exits successfully, then the driver will be automatically
+attached by the core. Change the probe routine as so:
+
+-      ret = i2c_attach_client(&state->i2c_client);
+-      if (ret < 0) {
+-              dev_err(dev, "failed to attach client\n");
+-              kfree(state);
+-              return ret;
+-      }
+
+
+Remove the storage of 'struct i2c_client' from the 'struct example_state'
+as we are provided with the i2c_client in our example_probe. Instead we
+store a pointer to it for when it is needed.
+
+struct example_state {
+-      struct i2c_client       client;
++      struct i2c_client       *client;
+
+the new i2c client as so:
+
+-      struct device *dev = &adap->dev;  /* to use for dev_ reports */
++      struct device *dev = &i2c_client->dev;  /* to use for dev_ reports */
+
+And remove the change after our client is attached, as the driver no
+longer needs to register a new client structure with the core:
+
+-      dev = &state->i2c_client.dev;
+
+In the probe routine, ensure that the new state has the client stored
+in it:
+
+static int example_probe(struct i2c_client *i2c_client,
+                        const struct i2c_device_id *id)
+{
+       struct example_state *state;
+       struct device *dev = &i2c_client->dev;
+       int ret;
+
+       state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
+       if (state == NULL) {
+               dev_err(dev, "failed to create our state\n");
+               return -ENOMEM;
+       }
+
++      state->client = i2c_client;
+
+Update the detach method, by changing the name to _remove and
+to delete the i2c_detach_client call. It is possible that you
+can also remove the ret variable as it is not not needed for
+any of the core functions.
+
+- static int __devexit example_detach(struct i2c_client *client)
++ static int __devexit example_remove(struct i2c_client *client)
+{
+       struct example_state *state = i2c_get_clientdata(client);
+
+-      i2c_detach_client(client);
+
+And finally ensure that we have the correct ID table for the i2c-core
+and other utilities:
+
++ struct i2c_device_id example_idtable[] = {
++       { "example", 0 },
++       { }
++};
++
++MODULE_DEVICE_TABLE(i2c, example_idtable);
+
+static struct i2c_driver example_driver = {
+       .driver         = {
+               .owner          = THIS_MODULE,
+               .name           = "example",
+       },
++      .id_table       = example_ids,
+
+
+Our driver should now look like this:
+
+struct example_state {
+       struct i2c_client       *client;
+       ....
+};
+
+static int example_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct example_state *state;
+       struct device *dev = &client->dev;
+
+       state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
+       if (state == NULL) {
+               dev_err(dev, "failed to create our state\n");
+               return -ENOMEM;
+       }
+
+       state->client = client;
+       i2c_set_clientdata(client, state);
+
+       /* rest of the initialisation goes here. */
+
+       dev_info(dev, "example client created\n");
+
+       return 0;
+}
+
+static int __devexit example_remove(struct i2c_client *client)
+{
+       struct example_state *state = i2c_get_clientdata(client);
+
+       kfree(state);
+       return 0;
+}
+
+static struct i2c_device_id example_idtable[] = {
+       { "example", 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, example_idtable);
+
+static struct i2c_driver example_driver = {
+       .driver         = {
+               .owner          = THIS_MODULE,
+               .name           = "example",
+       },
+       .id_table       = example_idtable,
+       .probe          = example_probe,
+       .remove         = __devexit_p(example_remove),
+       .suspend        = example_suspend,
+       .resume         = example_resume,
+};
index bec9d815da33a0495c7ea4d2eebecf7f4c1ab2fc..914d07f49268b728ab5c1d8a6e7b23b59cef0128 100644 (file)
@@ -50,9 +50,9 @@ Note: For step 2, please make sure that host page size == TARGET_PAGE_SIZE of qe
                /usr/local/bin/qemu-system-ia64 -smp xx -m 512 -hda $your_image
                (xx is the number of virtual processors for the guest, now the maximum value is 4)
 
-5. Known possibile issue on some platforms with old Firmware.
+5. Known possible issue on some platforms with old Firmware.
 
-If meet strange host crashe issues, try to solve it through either of the following ways:
+In the event of strange host crash issues, try to solve it through either of the following ways:
 
 (1): Upgrade your Firmware to the latest one.
 
@@ -65,8 +65,8 @@ index 0b53344..f02b0f7 100644
        mov ar.pfs = loc1
        mov rp = loc0
        ;;
--      srlz.d                          // seralize restoration of psr.l
-+      srlz.i                  // seralize restoration of psr.l
+-      srlz.d                          // serialize restoration of psr.l
++      srlz.i                  // serialize restoration of psr.l
 +      ;;
        br.ret.sptk.many b0
  END(ia64_pal_call_static)
index afe0d6543e093fa5dfa4758bbb0cbec90ff0bce3..202e9dbacec39a96990c5722c4b1ab832b939b61 100644 (file)
@@ -31,7 +31,7 @@ The driver works with ALSA drivers simultaneously. For example, the xracer
 uses joystick as input device and PCM device as sound output in one time.
 There are no sound or input collisions detected. The source code have
 comments about them; but I've found the joystick can be initialized 
-separately of ALSA modules. So, you canm use only one joystick driver
+separately of ALSA modules. So, you can use only one joystick driver
 without ALSA drivers. The ALSA drivers are not needed to compile or
 run this driver.
 
index bfdf7f3ee4f05e0f52e08c8aee1ad55c248b8af4..e35efb0cec2e64a99538d24c2c7c7b38846abc26 100644 (file)
@@ -1,6 +1,6 @@
 To decode a hex IOCTL code:
 
-Most architecures use this generic format, but check
+Most architectures use this generic format, but check
 include/ARCH/ioctl.h for specifics, e.g. powerpc
 uses 3 bits to encode read/write and 13 bits for size.
 
@@ -18,7 +18,7 @@ uses 3 bits to encode read/write and 13 bits for size.
  7-0   function #
 
 
- So for example 0x82187201 is a read with arg length of 0x218,
+So for example 0x82187201 is a read with arg length of 0x218,
 character 'r' function 1. Grepping the source reveals this is:
 
 #define VFAT_IOCTL_READDIR_BOTH         _IOR('r', 1, struct dirent [2])
index 5925c3cd030d55884b3f962ed40ced5a20709cf4..59a69ec67c408a54ee724df4d4a64a69a8317f68 100644 (file)
@@ -143,7 +143,7 @@ disk and partition statistics are consistent again. Since we still don't
 keep record of the partition-relative address, an operation is attributed to
 the partition which contains the first sector of the request after the
 eventual merges. As requests can be merged across partition, this could lead
-to some (probably insignificant) innacuracy.
+to some (probably insignificant) inaccuracy.
 
 Additional notes
 ----------------
diff --git a/Documentation/isdn/README.mISDN b/Documentation/isdn/README.mISDN
new file mode 100644 (file)
index 0000000..cd8bf92
--- /dev/null
@@ -0,0 +1,6 @@
+mISDN is a new modular ISDN driver, in the long term it should replace
+the old I4L driver architecture for passiv ISDN cards.
+It was designed to allow a broad range of applications and interfaces
+but only have the basic function in kernel, the interface to the user
+space is based on sockets with a own address family AF_ISDN.
+
index 9691c7f5166c1ea60acfbc383799dc5ec4dcbd21..0705040531a534c2c153c1289fe0febf92926a61 100644 (file)
@@ -65,26 +65,26 @@ Install kexec-tools
 
 2) Download the kexec-tools user-space package from the following URL:
 
-http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools-testing.tar.gz
+http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools.tar.gz
 
-This is a symlink to the latest version, which at the time of writing is
-20061214, the only release of kexec-tools-testing so far. As other versions
-are released, the older ones will remain available at
-http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
+This is a symlink to the latest version.
 
-Note: Latest kexec-tools-testing git tree is available at
+The latest kexec-tools git tree is available at:
 
-git://git.kernel.org/pub/scm/linux/kernel/git/horms/kexec-tools-testing.git
+git://git.kernel.org/pub/scm/linux/kernel/git/horms/kexec-tools.git
 or
-http://www.kernel.org/git/?p=linux/kernel/git/horms/kexec-tools-testing.git;a=summary
+http://www.kernel.org/git/?p=linux/kernel/git/horms/kexec-tools.git
+
+More information about kexec-tools can be found at
+http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/README.html
 
 3) Unpack the tarball with the tar command, as follows:
 
-   tar xvpzf kexec-tools-testing.tar.gz
+   tar xvpzf kexec-tools.tar.gz
 
 4) Change to the kexec-tools directory, as follows:
 
-   cd kexec-tools-testing-VERSION
+   cd kexec-tools-VERSION
 
 5) Configure the package, as follows:
 
index 47e7d8794fc6fbad46c37edbc1d9a5bc4f6c3e82..e7bea3e853044e54f3ee863ad3d295b0df84a522 100644 (file)
@@ -87,7 +87,8 @@ parameter is applicable:
        SH      SuperH architecture is enabled.
        SMP     The kernel is an SMP kernel.
        SPARC   Sparc architecture is enabled.
-       SWSUSP  Software suspend is enabled.
+       SWSUSP  Software suspend (hibernation) is enabled.
+       SUSPEND System suspend states are enabled.
        TS      Appropriate touchscreen support is enabled.
        USB     USB support is enabled.
        USBHID  USB Human Interface Device support is enabled.
@@ -147,10 +148,12 @@ and is between 256 and 4096 characters. It is defined in the file
                        default: 0
 
        acpi_sleep=     [HW,ACPI] Sleep options
-                       Format: { s3_bios, s3_mode, s3_beep, old_ordering }
+                       Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, old_ordering }
                        See Documentation/power/video.txt for s3_bios and s3_mode.
                        s3_beep is for debugging; it makes the PC's speaker beep
                        as soon as the kernel's real-mode entry point is called.
+                       s4_nohwsig prevents ACPI hardware signature from being
+                       used during resume from hibernation.
                        old_ordering causes the ACPI 1.0 ordering of the _PTS
                        control method, wrt putting devices into low power
                        states, to be enforced (the ACPI 2.0 ordering of _PTS is
@@ -774,8 +777,22 @@ and is between 256 and 4096 characters. It is defined in the file
        hisax=          [HW,ISDN]
                        See Documentation/isdn/README.HiSax.
 
-       hugepages=      [HW,X86-32,IA-64] Maximal number of HugeTLB pages.
-       hugepagesz=     [HW,IA-64,PPC] The size of the HugeTLB pages.
+       hugepages=      [HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
+       hugepagesz=     [HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
+                       On x86-64 and powerpc, this option can be specified
+                       multiple times interleaved with hugepages= to reserve
+                       huge pages of different sizes. Valid pages sizes on
+                       x86-64 are 2M (when the CPU supports "pse") and 1G
+                       (when the CPU supports the "pdpe1gb" cpuinfo flag)
+                       Note that 1GB pages can only be allocated at boot time
+                       using hugepages= and not freed afterwards.
+       default_hugepagesz=
+                       [same as hugepagesz=] The size of the default
+                       HugeTLB page size. This is the size represented by
+                       the legacy /proc/ hugepages APIs, used for SHM, and
+                       default size when mounting hugetlbfs filesystems.
+                       Defaults to the default architecture's huge page size
+                       if not specified.
 
        i8042.direct    [HW] Put keyboard port into non-translated mode
        i8042.dumbkbd   [HW] Pretend that controller can only read data from
@@ -1225,6 +1242,14 @@ and is between 256 and 4096 characters. It is defined in the file
 
        mga=            [HW,DRM]
 
+       mminit_loglevel=
+                       [KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
+                       parameter allows control of the logging verbosity for
+                       the additional memory initialisation checks. A value
+                       of 0 disables mminit logging and a level of 4 will
+                       log everything. Information is printed at KERN_DEBUG
+                       so loglevel=8 may also need to be specified.
+
        mousedev.tap_time=
                        [MOUSE] Maximum time between finger touching and
                        leaving touchpad surface for touch to be considered
@@ -2101,6 +2126,12 @@ and is between 256 and 4096 characters. It is defined in the file
 
        tdfx=           [HW,DRM]
 
+       test_suspend=   [SUSPEND]
+                       Specify "mem" (for Suspend-to-RAM) or "standby" (for
+                       standby suspend) as the system sleep state to briefly
+                       enter during system startup.  The system is woken from
+                       this state using a wakeup-capable RTC alarm.
+
        thash_entries=  [KNL,NET]
                        Set number of hash buckets for TCP connection
 
@@ -2128,13 +2159,6 @@ and is between 256 and 4096 characters. It is defined in the file
                        <deci-seconds>: poll all this frequency
                        0: no polling (default)
 
-       tipar.timeout=  [HW,PPT]
-                       Set communications timeout in tenths of a second
-                       (default 15).
-
-       tipar.delay=    [HW,PPT]
-                       Set inter-bit delay in microseconds (default 10).
-
        tmscsim=        [HW,SCSI]
                        See comment before function dc390_setup() in
                        drivers/scsi/tmscsim.c.
index d5c7a57d17007fa0f43558b270b0e4c302d5f8aa..b56aacc1fff864022dbdf67aac997d54f0d14f32 100644 (file)
@@ -864,7 +864,7 @@ payload contents" for more information.
     request_key_with_auxdata() respectively.
 
     These two functions return with the key potentially still under
-    construction.  To wait for contruction completion, the following should be
+    construction.  To wait for construction completion, the following should be
     called:
 
        int wait_for_key_construction(struct key *key, bool intr);
index 64b3f146e4b09aa4d2cd312e97689f9eba503347..02dc748b76c4ac861549077392ef1deb3ca9c652 100644 (file)
@@ -1,7 +1,7 @@
                     ThinkPad ACPI Extras Driver
 
-                            Version 0.20
-                          April 09th, 2008
+                            Version 0.21
+                           May 29th, 2008
 
                Borislav Deianov <borislav@users.sf.net>
              Henrique de Moraes Holschuh <hmh@hmh.eng.br>
@@ -621,7 +621,8 @@ Bluetooth
 ---------
 
 procfs: /proc/acpi/ibm/bluetooth
-sysfs device attribute: bluetooth_enable
+sysfs device attribute: bluetooth_enable (deprecated)
+sysfs rfkill class: switch "tpacpi_bluetooth_sw"
 
 This feature shows the presence and current state of a ThinkPad
 Bluetooth device in the internal ThinkPad CDC slot.
@@ -643,8 +644,12 @@ Sysfs notes:
                0: disables Bluetooth / Bluetooth is disabled
                1: enables Bluetooth / Bluetooth is enabled.
 
-       Note: this interface will be probably be superseded by the
-       generic rfkill class, so it is NOT to be considered stable yet.
+       Note: this interface has been superseded by the generic rfkill
+       class.  It has been deprecated, and it will be removed in year
+       2010.
+
+       rfkill controller switch "tpacpi_bluetooth_sw": refer to
+       Documentation/rfkill.txt for details.
 
 Video output control -- /proc/acpi/ibm/video
 --------------------------------------------
@@ -1374,7 +1379,8 @@ EXPERIMENTAL: WAN
 -----------------
 
 procfs: /proc/acpi/ibm/wan
-sysfs device attribute: wwan_enable
+sysfs device attribute: wwan_enable (deprecated)
+sysfs rfkill class: switch "tpacpi_wwan_sw"
 
 This feature is marked EXPERIMENTAL because the implementation
 directly accesses hardware registers and may not work as expected. USE
@@ -1404,8 +1410,12 @@ Sysfs notes:
                0: disables WWAN card / WWAN card is disabled
                1: enables WWAN card / WWAN card is enabled.
 
-       Note: this interface will be probably be superseded by the
-       generic rfkill class, so it is NOT to be considered stable yet.
+       Note: this interface has been superseded by the generic rfkill
+       class.  It has been deprecated, and it will be removed in year
+       2010.
+
+       rfkill controller switch "tpacpi_wwan_sw": refer to
+       Documentation/rfkill.txt for details.
 
 Multiple Commands, Module Parameters
 ------------------------------------
index 18860ad9935a7876746c00660f36b9fd90529499..6399557cdab3d6542a0feea0c0cd2c6b2af5ffad 100644 (file)
@@ -59,7 +59,7 @@ Hardware accelerated blink of LEDs
 
 Some LEDs can be programmed to blink without any CPU interaction. To
 support this feature, a LED driver can optionally implement the
-blink_set() function (see <linux/leds.h>). If implemeted, triggers can
+blink_set() function (see <linux/leds.h>). If implemented, triggers can
 attempt to use it before falling back to software timers. The blink_set()
 function should return 0 if the blink setting is supported, or -EINVAL
 otherwise, which means that LED blinking will be handled by software.
index 82fafe0429fed8dc441411059be52b33154dd8a8..b88b0ea54e90c597896aac6eb478e1b56bab8bd0 100644 (file)
 #include <sched.h>
 #include <limits.h>
 #include <stddef.h>
+#include <signal.h>
 #include "linux/lguest_launcher.h"
 #include "linux/virtio_config.h"
 #include "linux/virtio_net.h"
 #include "linux/virtio_blk.h"
 #include "linux/virtio_console.h"
+#include "linux/virtio_rng.h"
 #include "linux/virtio_ring.h"
 #include "asm-x86/bootparam.h"
 /*L:110 We can ignore the 39 include files we need for this program, but I do
@@ -64,8 +66,8 @@ typedef uint8_t u8;
 #endif
 /* We can have up to 256 pages for devices. */
 #define DEVICE_PAGES 256
-/* This will occupy 2 pages: it must be a power of 2. */
-#define VIRTQUEUE_NUM 128
+/* This will occupy 3 pages: it must be a power of 2. */
+#define VIRTQUEUE_NUM 256
 
 /*L:120 verbose is both a global flag and a macro.  The C preprocessor allows
  * this, and although I wouldn't recommend it, it works quite nicely here. */
@@ -74,12 +76,19 @@ static bool verbose;
        do { if (verbose) printf(args); } while(0)
 /*:*/
 
-/* The pipe to send commands to the waker process */
-static int waker_fd;
+/* File descriptors for the Waker. */
+struct {
+       int pipe[2];
+       int lguest_fd;
+} waker_fds;
+
 /* The pointer to the start of guest memory. */
 static void *guest_base;
 /* The maximum guest physical address allowed, and maximum possible. */
 static unsigned long guest_limit, guest_max;
+/* The pipe for signal hander to write to. */
+static int timeoutpipe[2];
+static unsigned int timeout_usec = 500;
 
 /* a per-cpu variable indicating whose vcpu is currently running */
 static unsigned int __thread cpu_id;
@@ -155,11 +164,14 @@ struct virtqueue
        /* Last available index we saw. */
        u16 last_avail_idx;
 
-       /* The routine to call when the Guest pings us. */
-       void (*handle_output)(int fd, struct virtqueue *me);
+       /* The routine to call when the Guest pings us, or timeout. */
+       void (*handle_output)(int fd, struct virtqueue *me, bool timeout);
 
        /* Outstanding buffers */
        unsigned int inflight;
+
+       /* Is this blocked awaiting a timer? */
+       bool blocked;
 };
 
 /* Remember the arguments to the program so we can "reboot" */
@@ -190,6 +202,9 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
        return iov->iov_base;
 }
 
+/* Wrapper for the last available index.  Makes it easier to change. */
+#define lg_last_avail(vq)      ((vq)->last_avail_idx)
+
 /* The virtio configuration space is defined to be little-endian.  x86 is
  * little-endian too, but it's nice to be explicit so we have these helpers. */
 #define cpu_to_le16(v16) (v16)
@@ -199,6 +214,33 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
 #define le32_to_cpu(v32) (v32)
 #define le64_to_cpu(v64) (v64)
 
+/* Is this iovec empty? */
+static bool iov_empty(const struct iovec iov[], unsigned int num_iov)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_iov; i++)
+               if (iov[i].iov_len)
+                       return false;
+       return true;
+}
+
+/* Take len bytes from the front of this iovec. */
+static void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_iov; i++) {
+               unsigned int used;
+
+               used = iov[i].iov_len < len ? iov[i].iov_len : len;
+               iov[i].iov_base += used;
+               iov[i].iov_len -= used;
+               len -= used;
+       }
+       assert(len == 0);
+}
+
 /* The device virtqueue descriptors are followed by feature bitmasks. */
 static u8 *get_feature_bits(struct device *dev)
 {
@@ -254,6 +296,7 @@ static void *map_zeroed_pages(unsigned int num)
                    PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
        if (addr == MAP_FAILED)
                err(1, "Mmaping %u pages of /dev/zero", num);
+       close(fd);
 
        return addr;
 }
@@ -540,69 +583,64 @@ static void add_device_fd(int fd)
  * watch, but handing a file descriptor mask through to the kernel is fairly
  * icky.
  *
- * Instead, we fork off a process which watches the file descriptors and writes
+ * Instead, we clone off a thread which watches the file descriptors and writes
  * the LHREQ_BREAK command to the /dev/lguest file descriptor to tell the Host
  * stop running the Guest.  This causes the Launcher to return from the
  * /dev/lguest read with -EAGAIN, where it will write to /dev/lguest to reset
  * the LHREQ_BREAK and wake us up again.
  *
  * This, of course, is merely a different *kind* of icky.
+ *
+ * Given my well-known antipathy to threads, I'd prefer to use processes.  But
+ * it's easier to share Guest memory with threads, and trivial to share the
+ * devices.infds as the Launcher changes it.
  */
-static void wake_parent(int pipefd, int lguest_fd)
+static int waker(void *unused)
 {
-       /* Add the pipe from the Launcher to the fdset in the device_list, so
-        * we watch it, too. */
-       add_device_fd(pipefd);
+       /* Close the write end of the pipe: only the Launcher has it open. */
+       close(waker_fds.pipe[1]);
 
        for (;;) {
                fd_set rfds = devices.infds;
                unsigned long args[] = { LHREQ_BREAK, 1 };
+               unsigned int maxfd = devices.max_infd;
+
+               /* We also listen to the pipe from the Launcher. */
+               FD_SET(waker_fds.pipe[0], &rfds);
+               if (waker_fds.pipe[0] > maxfd)
+                       maxfd = waker_fds.pipe[0];
 
                /* Wait until input is ready from one of the devices. */
-               select(devices.max_infd+1, &rfds, NULL, NULL, NULL);
-               /* Is it a message from the Launcher? */
-               if (FD_ISSET(pipefd, &rfds)) {
-                       int fd;
-                       /* If read() returns 0, it means the Launcher has
-                        * exited.  We silently follow. */
-                       if (read(pipefd, &fd, sizeof(fd)) == 0)
-                               exit(0);
-                       /* Otherwise it's telling us to change what file
-                        * descriptors we're to listen to.  Positive means
-                        * listen to a new one, negative means stop
-                        * listening. */
-                       if (fd >= 0)
-                               FD_SET(fd, &devices.infds);
-                       else
-                               FD_CLR(-fd - 1, &devices.infds);
-               } else /* Send LHREQ_BREAK command. */
-                       pwrite(lguest_fd, args, sizeof(args), cpu_id);
+               select(maxfd+1, &rfds, NULL, NULL, NULL);
+
+               /* Message from Launcher? */
+               if (FD_ISSET(waker_fds.pipe[0], &rfds)) {
+                       char c;
+                       /* If this fails, then assume Launcher has exited.
+                        * Don't do anything on exit: we're just a thread! */
+                       if (read(waker_fds.pipe[0], &c, 1) != 1)
+                               _exit(0);
+                       continue;
+               }
+
+               /* Send LHREQ_BREAK command to snap the Launcher out of it. */
+               pwrite(waker_fds.lguest_fd, args, sizeof(args), cpu_id);
        }
+       return 0;
 }
 
 /* This routine just sets up a pipe to the Waker process. */
-static int setup_waker(int lguest_fd)
-{
-       int pipefd[2], child;
-
-       /* We create a pipe to talk to the Waker, and also so it knows when the
-        * Launcher dies (and closes pipe). */
-       pipe(pipefd);
-       child = fork();
-       if (child == -1)
-               err(1, "forking");
-
-       if (child == 0) {
-               /* We are the Waker: close the "writing" end of our copy of the
-                * pipe and start waiting for input. */
-               close(pipefd[1]);
-               wake_parent(pipefd[0], lguest_fd);
-       }
-       /* Close the reading end of our copy of the pipe. */
-       close(pipefd[0]);
+static void setup_waker(int lguest_fd)
+{
+       /* This pipe is closed when Launcher dies, telling Waker. */
+       if (pipe(waker_fds.pipe) != 0)
+               err(1, "Creating pipe for Waker");
 
-       /* Here is the fd used to talk to the waker. */
-       return pipefd[1];
+       /* Waker also needs to know the lguest fd */
+       waker_fds.lguest_fd = lguest_fd;
+
+       if (clone(waker, malloc(4096) + 4096, CLONE_VM | SIGCHLD, NULL) == -1)
+               err(1, "Creating Waker");
 }
 
 /*
@@ -661,19 +699,22 @@ static unsigned get_vq_desc(struct virtqueue *vq,
                            unsigned int *out_num, unsigned int *in_num)
 {
        unsigned int i, head;
+       u16 last_avail;
 
        /* Check it isn't doing very strange things with descriptor numbers. */
-       if ((u16)(vq->vring.avail->idx - vq->last_avail_idx) > vq->vring.num)
+       last_avail = lg_last_avail(vq);
+       if ((u16)(vq->vring.avail->idx - last_avail) > vq->vring.num)
                errx(1, "Guest moved used index from %u to %u",
-                    vq->last_avail_idx, vq->vring.avail->idx);
+                    last_avail, vq->vring.avail->idx);
 
        /* If there's nothing new since last we looked, return invalid. */
-       if (vq->vring.avail->idx == vq->last_avail_idx)
+       if (vq->vring.avail->idx == last_avail)
                return vq->vring.num;
 
        /* Grab the next descriptor number they're advertising, and increment
         * the index we've seen. */
-       head = vq->vring.avail->ring[vq->last_avail_idx++ % vq->vring.num];
+       head = vq->vring.avail->ring[last_avail % vq->vring.num];
+       lg_last_avail(vq)++;
 
        /* If their number is silly, that's a fatal mistake. */
        if (head >= vq->vring.num)
@@ -821,8 +862,8 @@ static bool handle_console_input(int fd, struct device *dev)
                                unsigned long args[] = { LHREQ_BREAK, 0 };
                                /* Close the fd so Waker will know it has to
                                 * exit. */
-                               close(waker_fd);
-                               /* Just in case waker is blocked in BREAK, send
+                               close(waker_fds.pipe[1]);
+                               /* Just in case Waker is blocked in BREAK, send
                                 * unbreak now. */
                                write(fd, args, sizeof(args));
                                exit(2);
@@ -839,7 +880,7 @@ static bool handle_console_input(int fd, struct device *dev)
 
 /* Handling output for console is simple: we just get all the output buffers
  * and write them to stdout. */
-static void handle_console_output(int fd, struct virtqueue *vq)
+static void handle_console_output(int fd, struct virtqueue *vq, bool timeout)
 {
        unsigned int head, out, in;
        int len;
@@ -854,6 +895,21 @@ static void handle_console_output(int fd, struct virtqueue *vq)
        }
 }
 
+static void block_vq(struct virtqueue *vq)
+{
+       struct itimerval itm;
+
+       vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+       vq->blocked = true;
+
+       itm.it_interval.tv_sec = 0;
+       itm.it_interval.tv_usec = 0;
+       itm.it_value.tv_sec = 0;
+       itm.it_value.tv_usec = timeout_usec;
+
+       setitimer(ITIMER_REAL, &itm, NULL);
+}
+
 /*
  * The Network
  *
@@ -861,22 +917,34 @@ static void handle_console_output(int fd, struct virtqueue *vq)
  * and write them (ignoring the first element) to this device's file descriptor
  * (/dev/net/tun).
  */
-static void handle_net_output(int fd, struct virtqueue *vq)
+static void handle_net_output(int fd, struct virtqueue *vq, bool timeout)
 {
-       unsigned int head, out, in;
+       unsigned int head, out, in, num = 0;
        int len;
        struct iovec iov[vq->vring.num];
+       static int last_timeout_num;
 
        /* Keep getting output buffers from the Guest until we run out. */
        while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
                if (in)
                        errx(1, "Input buffers in output queue?");
-               /* Check header, but otherwise ignore it (we told the Guest we
-                * supported no features, so it shouldn't have anything
-                * interesting). */
-               (void)convert(&iov[0], struct virtio_net_hdr);
-               len = writev(vq->dev->fd, iov+1, out-1);
+               len = writev(vq->dev->fd, iov, out);
+               if (len < 0)
+                       err(1, "Writing network packet to tun");
                add_used_and_trigger(fd, vq, head, len);
+               num++;
+       }
+
+       /* Block further kicks and set up a timer if we saw anything. */
+       if (!timeout && num)
+               block_vq(vq);
+
+       if (timeout) {
+               if (num < last_timeout_num)
+                       timeout_usec += 10;
+               else if (timeout_usec > 1)
+                       timeout_usec--;
+               last_timeout_num = num;
        }
 }
 
@@ -887,7 +955,6 @@ static bool handle_tun_input(int fd, struct device *dev)
        unsigned int head, in_num, out_num;
        int len;
        struct iovec iov[dev->vq->vring.num];
-       struct virtio_net_hdr *hdr;
 
        /* First we need a network buffer from the Guests's recv virtqueue. */
        head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
@@ -896,25 +963,23 @@ static bool handle_tun_input(int fd, struct device *dev)
                 * early, the Guest won't be ready yet.  Wait until the device
                 * status says it's ready. */
                /* FIXME: Actually want DRIVER_ACTIVE here. */
-               if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK)
-                       warn("network: no dma buffer!");
+
+               /* Now tell it we want to know if new things appear. */
+               dev->vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+               wmb();
+
                /* We'll turn this back on if input buffers are registered. */
                return false;
        } else if (out_num)
                errx(1, "Output buffers in network recv queue?");
 
-       /* First element is the header: we set it to 0 (no features). */
-       hdr = convert(&iov[0], struct virtio_net_hdr);
-       hdr->flags = 0;
-       hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
-
        /* Read the packet from the device directly into the Guest's buffer. */
-       len = readv(dev->fd, iov+1, in_num-1);
+       len = readv(dev->fd, iov, in_num);
        if (len <= 0)
                err(1, "reading network");
 
        /* Tell the Guest about the new packet. */
-       add_used_and_trigger(fd, dev->vq, head, sizeof(*hdr) + len);
+       add_used_and_trigger(fd, dev->vq, head, len);
 
        verbose("tun input packet len %i [%02x %02x] (%s)\n", len,
                ((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1],
@@ -927,11 +992,18 @@ static bool handle_tun_input(int fd, struct device *dev)
 /*L:215 This is the callback attached to the network and console input
  * virtqueues: it ensures we try again, in case we stopped console or net
  * delivery because Guest didn't have any buffers. */
-static void enable_fd(int fd, struct virtqueue *vq)
+static void enable_fd(int fd, struct virtqueue *vq, bool timeout)
 {
        add_device_fd(vq->dev->fd);
-       /* Tell waker to listen to it again */
-       write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd));
+       /* Snap the Waker out of its select loop. */
+       write(waker_fds.pipe[1], "", 1);
+}
+
+static void net_enable_fd(int fd, struct virtqueue *vq, bool timeout)
+{
+       /* We don't need to know again when Guest refills receive buffer. */
+       vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+       enable_fd(fd, vq, timeout);
 }
 
 /* When the Guest tells us they updated the status field, we handle it. */
@@ -951,7 +1023,7 @@ static void update_device_status(struct device *dev)
                for (vq = dev->vq; vq; vq = vq->next) {
                        memset(vq->vring.desc, 0,
                               vring_size(vq->config.num, getpagesize()));
-                       vq->last_avail_idx = 0;
+                       lg_last_avail(vq) = 0;
                }
        } else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
                warnx("Device %s configuration FAILED", dev->name);
@@ -960,10 +1032,10 @@ static void update_device_status(struct device *dev)
 
                verbose("Device %s OK: offered", dev->name);
                for (i = 0; i < dev->desc->feature_len; i++)
-                       verbose(" %08x", get_feature_bits(dev)[i]);
+                       verbose(" %02x", get_feature_bits(dev)[i]);
                verbose(", accepted");
                for (i = 0; i < dev->desc->feature_len; i++)
-                       verbose(" %08x", get_feature_bits(dev)
+                       verbose(" %02x", get_feature_bits(dev)
                                [dev->desc->feature_len+i]);
 
                if (dev->ready)
@@ -1000,7 +1072,7 @@ static void handle_output(int fd, unsigned long addr)
                        if (strcmp(vq->dev->name, "console") != 0)
                                verbose("Output to %s\n", vq->dev->name);
                        if (vq->handle_output)
-                               vq->handle_output(fd, vq);
+                               vq->handle_output(fd, vq, false);
                        return;
                }
        }
@@ -1014,6 +1086,29 @@ static void handle_output(int fd, unsigned long addr)
              strnlen(from_guest_phys(addr), guest_limit - addr));
 }
 
+static void handle_timeout(int fd)
+{
+       char buf[32];
+       struct device *i;
+       struct virtqueue *vq;
+
+       /* Clear the pipe */
+       read(timeoutpipe[0], buf, sizeof(buf));
+
+       /* Check each device and virtqueue: flush blocked ones. */
+       for (i = devices.dev; i; i = i->next) {
+               for (vq = i->vq; vq; vq = vq->next) {
+                       if (!vq->blocked)
+                               continue;
+
+                       vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+                       vq->blocked = false;
+                       if (vq->handle_output)
+                               vq->handle_output(fd, vq, true);
+               }
+       }
+}
+
 /* This is called when the Waker wakes us up: check for incoming file
  * descriptors. */
 static void handle_input(int fd)
@@ -1024,16 +1119,20 @@ static void handle_input(int fd)
        for (;;) {
                struct device *i;
                fd_set fds = devices.infds;
+               int num;
 
+               num = select(devices.max_infd+1, &fds, NULL, NULL, &poll);
+               /* Could get interrupted */
+               if (num < 0)
+                       continue;
                /* If nothing is ready, we're done. */
-               if (select(devices.max_infd+1, &fds, NULL, NULL, &poll) == 0)
+               if (num == 0)
                        break;
 
                /* Otherwise, call the device(s) which have readable file
                 * descriptors and a method of handling them.  */
                for (i = devices.dev; i; i = i->next) {
                        if (i->handle_input && FD_ISSET(i->fd, &fds)) {
-                               int dev_fd;
                                if (i->handle_input(fd, i))
                                        continue;
 
@@ -1043,13 +1142,12 @@ static void handle_input(int fd)
                                 * buffers to deliver into.  Console also uses
                                 * it when it discovers that stdin is closed. */
                                FD_CLR(i->fd, &devices.infds);
-                               /* Tell waker to ignore it too, by sending a
-                                * negative fd number (-1, since 0 is a valid
-                                * FD number). */
-                               dev_fd = -i->fd - 1;
-                               write(waker_fd, &dev_fd, sizeof(dev_fd));
                        }
                }
+
+               /* Is this the timeout fd? */
+               if (FD_ISSET(timeoutpipe[0], &fds))
+                       handle_timeout(fd);
        }
 }
 
@@ -1098,7 +1196,7 @@ static struct lguest_device_desc *new_dev_desc(u16 type)
 /* Each device descriptor is followed by the description of its virtqueues.  We
  * specify how many descriptors the virtqueue is to have. */
 static void add_virtqueue(struct device *dev, unsigned int num_descs,
-                         void (*handle_output)(int fd, struct virtqueue *me))
+                         void (*handle_output)(int, struct virtqueue *, bool))
 {
        unsigned int pages;
        struct virtqueue **i, *vq = malloc(sizeof(*vq));
@@ -1114,6 +1212,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
        vq->last_avail_idx = 0;
        vq->dev = dev;
        vq->inflight = 0;
+       vq->blocked = false;
 
        /* Initialize the configuration. */
        vq->config.num = num_descs;
@@ -1246,6 +1345,24 @@ static void setup_console(void)
 }
 /*:*/
 
+static void timeout_alarm(int sig)
+{
+       write(timeoutpipe[1], "", 1);
+}
+
+static void setup_timeout(void)
+{
+       if (pipe(timeoutpipe) != 0)
+               err(1, "Creating timeout pipe");
+
+       if (fcntl(timeoutpipe[1], F_SETFL,
+                 fcntl(timeoutpipe[1], F_GETFL) | O_NONBLOCK) != 0)
+               err(1, "Making timeout pipe nonblocking");
+
+       add_device_fd(timeoutpipe[0]);
+       signal(SIGALRM, timeout_alarm);
+}
+
 /*M:010 Inter-guest networking is an interesting area.  Simplest is to have a
  * --sharenet=<name> option which opens or creates a named pipe.  This can be
  * used to send packets to another guest in a 1:1 manner.
@@ -1264,10 +1381,25 @@ static void setup_console(void)
 
 static u32 str2ip(const char *ipaddr)
 {
-       unsigned int byte[4];
+       unsigned int b[4];
 
-       sscanf(ipaddr, "%u.%u.%u.%u", &byte[0], &byte[1], &byte[2], &byte[3]);
-       return (byte[0] << 24) | (byte[1] << 16) | (byte[2] << 8) | byte[3];
+       if (sscanf(ipaddr, "%u.%u.%u.%u", &b[0], &b[1], &b[2], &b[3]) != 4)
+               errx(1, "Failed to parse IP address '%s'", ipaddr);
+       return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
+}
+
+static void str2mac(const char *macaddr, unsigned char mac[6])
+{
+       unsigned int m[6];
+       if (sscanf(macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
+                  &m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) != 6)
+               errx(1, "Failed to parse mac address '%s'", macaddr);
+       mac[0] = m[0];
+       mac[1] = m[1];
+       mac[2] = m[2];
+       mac[3] = m[3];
+       mac[4] = m[4];
+       mac[5] = m[5];
 }
 
 /* This code is "adapted" from libbridge: it attaches the Host end of the
@@ -1288,6 +1420,7 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
                errx(1, "interface %s does not exist!", if_name);
 
        strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
+       ifr.ifr_name[IFNAMSIZ-1] = '\0';
        ifr.ifr_ifindex = ifidx;
        if (ioctl(fd, SIOCBRADDIF, &ifr) < 0)
                err(1, "can't add %s to bridge %s", if_name, br_name);
@@ -1296,64 +1429,90 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
 /* This sets up the Host end of the network device with an IP address, brings
  * it up so packets will flow, the copies the MAC address into the hwaddr
  * pointer. */
-static void configure_device(int fd, const char *devname, u32 ipaddr,
-                            unsigned char hwaddr[6])
+static void configure_device(int fd, const char *tapif, u32 ipaddr)
 {
        struct ifreq ifr;
        struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
 
-       /* Don't read these incantations.  Just cut & paste them like I did! */
        memset(&ifr, 0, sizeof(ifr));
-       strcpy(ifr.ifr_name, devname);
+       strcpy(ifr.ifr_name, tapif);
+
+       /* Don't read these incantations.  Just cut & paste them like I did! */
        sin->sin_family = AF_INET;
        sin->sin_addr.s_addr = htonl(ipaddr);
        if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
-               err(1, "Setting %s interface address", devname);
+               err(1, "Setting %s interface address", tapif);
        ifr.ifr_flags = IFF_UP;
        if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
-               err(1, "Bringing interface %s up", devname);
+               err(1, "Bringing interface %s up", tapif);
+}
+
+static void get_mac(int fd, const char *tapif, unsigned char hwaddr[6])
+{
+       struct ifreq ifr;
+
+       memset(&ifr, 0, sizeof(ifr));
+       strcpy(ifr.ifr_name, tapif);
 
        /* SIOC stands for Socket I/O Control.  G means Get (vs S for Set
         * above).  IF means Interface, and HWADDR is hardware address.
         * Simple! */
        if (ioctl(fd, SIOCGIFHWADDR, &ifr) != 0)
-               err(1, "getting hw address for %s", devname);
+               err(1, "getting hw address for %s", tapif);
        memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, 6);
 }
 
-/*L:195 Our network is a Host<->Guest network.  This can either use bridging or
- * routing, but the principle is the same: it uses the "tun" device to inject
- * packets into the Host as if they came in from a normal network card.  We
- * just shunt packets between the Guest and the tun device. */
-static void setup_tun_net(const char *arg)
+static int get_tun_device(char tapif[IFNAMSIZ])
 {
-       struct device *dev;
        struct ifreq ifr;
-       int netfd, ipfd;
-       u32 ip;
-       const char *br_name = NULL;
-       struct virtio_net_config conf;
+       int netfd;
+
+       /* Start with this zeroed.  Messy but sure. */
+       memset(&ifr, 0, sizeof(ifr));
 
        /* We open the /dev/net/tun device and tell it we want a tap device.  A
         * tap device is like a tun device, only somehow different.  To tell
         * the truth, I completely blundered my way through this code, but it
         * works now! */
        netfd = open_or_die("/dev/net/tun", O_RDWR);
-       memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+       ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
        strcpy(ifr.ifr_name, "tap%d");
        if (ioctl(netfd, TUNSETIFF, &ifr) != 0)
                err(1, "configuring /dev/net/tun");
+
+       if (ioctl(netfd, TUNSETOFFLOAD,
+                 TUN_F_CSUM|TUN_F_TSO4|TUN_F_TSO6|TUN_F_TSO_ECN) != 0)
+               err(1, "Could not set features for tun device");
+
        /* We don't need checksums calculated for packets coming in this
         * device: trust us! */
        ioctl(netfd, TUNSETNOCSUM, 1);
 
+       memcpy(tapif, ifr.ifr_name, IFNAMSIZ);
+       return netfd;
+}
+
+/*L:195 Our network is a Host<->Guest network.  This can either use bridging or
+ * routing, but the principle is the same: it uses the "tun" device to inject
+ * packets into the Host as if they came in from a normal network card.  We
+ * just shunt packets between the Guest and the tun device. */
+static void setup_tun_net(char *arg)
+{
+       struct device *dev;
+       int netfd, ipfd;
+       u32 ip = INADDR_ANY;
+       bool bridging = false;
+       char tapif[IFNAMSIZ], *p;
+       struct virtio_net_config conf;
+
+       netfd = get_tun_device(tapif);
+
        /* First we create a new network device. */
        dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input);
 
        /* Network devices need a receive and a send queue, just like
         * console. */
-       add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
+       add_virtqueue(dev, VIRTQUEUE_NUM, net_enable_fd);
        add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output);
 
        /* We need a socket to perform the magic network ioctls to bring up the
@@ -1364,28 +1523,56 @@ static void setup_tun_net(const char *arg)
 
        /* If the command line was --tunnet=bridge:<name> do bridging. */
        if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) {
-               ip = INADDR_ANY;
-               br_name = arg + strlen(BRIDGE_PFX);
-               add_to_bridge(ipfd, ifr.ifr_name, br_name);
-       } else /* It is an IP address to set up the device with */
+               arg += strlen(BRIDGE_PFX);
+               bridging = true;
+       }
+
+       /* A mac address may follow the bridge name or IP address */
+       p = strchr(arg, ':');
+       if (p) {
+               str2mac(p+1, conf.mac);
+               *p = '\0';
+       } else {
+               p = arg + strlen(arg);
+               /* None supplied; query the randomly assigned mac. */
+               get_mac(ipfd, tapif, conf.mac);
+       }
+
+       /* arg is now either an IP address or a bridge name */
+       if (bridging)
+               add_to_bridge(ipfd, tapif, arg);
+       else
                ip = str2ip(arg);
 
-       /* Set up the tun device, and get the mac address for the interface. */
-       configure_device(ipfd, ifr.ifr_name, ip, conf.mac);
+       /* Set up the tun device. */
+       configure_device(ipfd, tapif, ip);
 
        /* Tell Guest what MAC address to use. */
        add_feature(dev, VIRTIO_NET_F_MAC);
        add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
+       /* Expect Guest to handle everything except UFO */
+       add_feature(dev, VIRTIO_NET_F_CSUM);
+       add_feature(dev, VIRTIO_NET_F_GUEST_CSUM);
+       add_feature(dev, VIRTIO_NET_F_MAC);
+       add_feature(dev, VIRTIO_NET_F_GUEST_TSO4);
+       add_feature(dev, VIRTIO_NET_F_GUEST_TSO6);
+       add_feature(dev, VIRTIO_NET_F_GUEST_ECN);
+       add_feature(dev, VIRTIO_NET_F_HOST_TSO4);
+       add_feature(dev, VIRTIO_NET_F_HOST_TSO6);
+       add_feature(dev, VIRTIO_NET_F_HOST_ECN);
        set_config(dev, sizeof(conf), &conf);
 
        /* We don't need the socket any more; setup is done. */
        close(ipfd);
 
-       verbose("device %u: tun net %u.%u.%u.%u\n",
-               devices.device_num++,
-               (u8)(ip>>24),(u8)(ip>>16),(u8)(ip>>8),(u8)ip);
-       if (br_name)
-               verbose("attached to bridge: %s\n", br_name);
+       devices.device_num++;
+
+       if (bridging)
+               verbose("device %u: tun %s attached to bridge: %s\n",
+                       devices.device_num, tapif, arg);
+       else
+               verbose("device %u: tun %s: %s\n",
+                       devices.device_num, tapif, arg);
 }
 
 /* Our block (disk) device should be really simple: the Guest asks for a block
@@ -1550,7 +1737,7 @@ static bool handle_io_finish(int fd, struct device *dev)
 }
 
 /* When the Guest submits some I/O, we just need to wake the I/O thread. */
-static void handle_virtblk_output(int fd, struct virtqueue *vq)
+static void handle_virtblk_output(int fd, struct virtqueue *vq, bool timeout)
 {
        struct vblk_info *vblk = vq->dev->priv;
        char c = 0;
@@ -1621,6 +1808,64 @@ static void setup_block_file(const char *filename)
        verbose("device %u: virtblock %llu sectors\n",
                devices.device_num, le64_to_cpu(conf.capacity));
 }
+
+/* Our random number generator device reads from /dev/random into the Guest's
+ * input buffers.  The usual case is that the Guest doesn't want random numbers
+ * and so has no buffers although /dev/random is still readable, whereas
+ * console is the reverse.
+ *
+ * The same logic applies, however. */
+static bool handle_rng_input(int fd, struct device *dev)
+{
+       int len;
+       unsigned int head, in_num, out_num, totlen = 0;
+       struct iovec iov[dev->vq->vring.num];
+
+       /* First we need a buffer from the Guests's virtqueue. */
+       head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
+
+       /* If they're not ready for input, stop listening to this file
+        * descriptor.  We'll start again once they add an input buffer. */
+       if (head == dev->vq->vring.num)
+               return false;
+
+       if (out_num)
+               errx(1, "Output buffers in rng?");
+
+       /* This is why we convert to iovecs: the readv() call uses them, and so
+        * it reads straight into the Guest's buffer.  We loop to make sure we
+        * fill it. */
+       while (!iov_empty(iov, in_num)) {
+               len = readv(dev->fd, iov, in_num);
+               if (len <= 0)
+                       err(1, "Read from /dev/random gave %i", len);
+               iov_consume(iov, in_num, len);
+               totlen += len;
+       }
+
+       /* Tell the Guest about the new input. */
+       add_used_and_trigger(fd, dev->vq, head, totlen);
+
+       /* Everything went OK! */
+       return true;
+}
+
+/* And this creates a "hardware" random number device for the Guest. */
+static void setup_rng(void)
+{
+       struct device *dev;
+       int fd;
+
+       fd = open_or_die("/dev/random", O_RDONLY);
+
+       /* The device responds to return from I/O thread. */
+       dev = new_device("rng", VIRTIO_ID_RNG, fd, handle_rng_input);
+
+       /* The device has one virtqueue, where the Guest places inbufs. */
+       add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
+
+       verbose("device %u: rng\n", devices.device_num++);
+}
 /* That's the end of device setup. */
 
 /*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */
@@ -1628,11 +1873,12 @@ static void __attribute__((noreturn)) restart_guest(void)
 {
        unsigned int i;
 
-       /* Closing pipes causes the Waker thread and io_threads to die, and
-        * closing /dev/lguest cleans up the Guest.  Since we don't track all
-        * open fds, we simply close everything beyond stderr. */
+       /* Since we don't track all open fds, we simply close everything beyond
+        * stderr. */
        for (i = 3; i < FD_SETSIZE; i++)
                close(i);
+
+       /* The exec automatically gets rid of the I/O and Waker threads. */
        execv(main_args[0], main_args);
        err(1, "Could not exec %s", main_args[0]);
 }
@@ -1663,7 +1909,7 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
                /* ERESTART means that we need to reboot the guest */
                } else if (errno == ERESTART) {
                        restart_guest();
-               /* EAGAIN means the Waker wanted us to look at some input.
+               /* EAGAIN means a signal (timeout).
                 * Anything else means a bug or incompatible change. */
                } else if (errno != EAGAIN)
                        err(1, "Running guest failed");
@@ -1691,13 +1937,14 @@ static struct option opts[] = {
        { "verbose", 0, NULL, 'v' },
        { "tunnet", 1, NULL, 't' },
        { "block", 1, NULL, 'b' },
+       { "rng", 0, NULL, 'r' },
        { "initrd", 1, NULL, 'i' },
        { NULL },
 };
 static void usage(void)
 {
        errx(1, "Usage: lguest [--verbose] "
-            "[--tunnet=(<ipaddr>|bridge:<bridgename>)\n"
+            "[--tunnet=(<ipaddr>:<macaddr>|bridge:<bridgename>:<macaddr>)\n"
             "|--block=<filename>|--initrd=<filename>]...\n"
             "<mem-in-mb> vmlinux [args...]");
 }
@@ -1765,6 +2012,9 @@ int main(int argc, char *argv[])
                case 'b':
                        setup_block_file(optarg);
                        break;
+               case 'r':
+                       setup_rng();
+                       break;
                case 'i':
                        initrd_name = optarg;
                        break;
@@ -1783,6 +2033,9 @@ int main(int argc, char *argv[])
        /* We always have a console device */
        setup_console();
 
+       /* We can timeout waiting for Guest network transmit. */
+       setup_timeout();
+
        /* Now we load the kernel */
        start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));
 
@@ -1826,10 +2079,10 @@ int main(int argc, char *argv[])
         * /dev/lguest file descriptor. */
        lguest_fd = tell_kernel(pgdir, start);
 
-       /* We fork off a child process, which wakes the Launcher whenever one
-        * of the input file descriptors needs attention.  We call this the
-        * Waker, and we'll cover it in a moment. */
-       waker_fd = setup_waker(lguest_fd);
+       /* We clone off a thread, which wakes the Launcher whenever one of the
+        * input file descriptors needs attention.  We call this the Waker, and
+        * we'll cover it in a moment. */
+       setup_waker(lguest_fd);
 
        /* Finally, run the Guest.  This doesn't return. */
        run_guest(lguest_fd);
index 4269a1105b378fafcc689435a2531b9d9d4287db..f4f8b1c6c8ba45ba6ec351aa92c40e798024983c 100644 (file)
@@ -36,7 +36,7 @@ It can be done by slightly modifying the standard atomic operations : only
 their UP variant must be kept. It typically means removing LOCK prefix (on
 i386 and x86_64) and any SMP sychronization barrier. If the architecture does
 not have a different behavior between SMP and UP, including asm-generic/local.h
-in your archtecture's local.h is sufficient.
+in your architecture's local.h is sufficient.
 
 The local_t type is defined as an opaque signed long by embedding an
 atomic_long_t inside a structure. This is made so a cast from this type to a
index fe24ecc6372e6b3482c3f39972ab9f70077d7b70..5337e80a5b96c6341e523394be6fedc58b87f6ed 100644 (file)
@@ -1,14 +1,22 @@
 =============================================================================
-
-       MOXA Smartio Family Device Driver Ver 1.1 Installation Guide
-                   for Linux Kernel 2.2.x and 2.0.3x
-              Copyright (C) 1999, Moxa Technologies Co, Ltd.
+          MOXA Smartio/Industio Family Device Driver Installation Guide
+                   for Linux Kernel 2.4.x, 2.6.x
+              Copyright (C) 2008, Moxa Inc.
 =============================================================================
+Date: 01/21/2008
+
 Content
 
 1. Introduction
 2. System Requirement
 3. Installation
+   3.1 Hardware installation
+   3.2 Driver files
+   3.3 Device naming convention
+   3.4 Module driver configuration
+   3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x.
+   3.6 Custom configuration
+   3.7 Verify driver installation
 4. Utilities
 5. Setserial
 6. Troubleshooting
@@ -16,27 +24,48 @@ Content
 -----------------------------------------------------------------------------
 1. Introduction
 
-   The Smartio family Linux driver, Ver. 1.1, supports following multiport
+   The Smartio/Industio/UPCI family Linux driver supports following multiport
    boards.
 
-    -C104P/H/HS, C104H/PCI, C104HS/PCI, CI-104J 4 port multiport board.
-    -C168P/H/HS, C168H/PCI 8 port multiport board.
-
-   This driver has been modified a little and cleaned up from the Moxa
-   contributed driver code and merged into Linux 2.2.14pre. In particular
-   official major/minor numbers have been assigned which are different to
-   those the original Moxa supplied driver used.
+    - 2 ports multiport board
+       CP-102U, CP-102UL, CP-102UF
+       CP-132U-I, CP-132UL,
+       CP-132, CP-132I, CP132S, CP-132IS,
+       CI-132, CI-132I, CI-132IS,
+       (C102H, C102HI, C102HIS, C102P, CP-102, CP-102S)
+
+    - 4 ports multiport board
+       CP-104EL,
+       CP-104UL, CP-104JU,
+       CP-134U, CP-134U-I,
+       C104H/PCI, C104HS/PCI,
+       CP-114, CP-114I, CP-114S, CP-114IS, CP-114UL,
+       C104H, C104HS,
+       CI-104J, CI-104JS,
+       CI-134, CI-134I, CI-134IS,
+       (C114HI, CT-114I, C104P)
+       POS-104UL,
+       CB-114,
+       CB-134I
+
+    - 8 ports multiport board
+       CP-118EL, CP-168EL,
+       CP-118U, CP-168U,
+       C168H/PCI,
+       C168H, C168HS,
+       (C168P),
+       CB-108
 
    This driver and installation procedure have been developed upon Linux Kernel
-   2.2.5 and backward compatible to 2.0.3x. This driver supports Intel x86 and
-   Alpha hardware platform. In order to maintain compatibility, this version
-   has also been properly tested with RedHat, OpenLinux, TurboLinux and
-   S.u.S.E Linux. However, if compatibility problem occurs, please contact
-   Moxa at support@moxa.com.tw.
+   2.4.x and 2.6.x. This driver supports Intel x86 hardware platform. In order
+   to maintain compatibility, this version has also been properly tested with
+   RedHat, Mandrake, Fedora and S.u.S.E Linux. However, if compatibility problem
+   occurs, please contact Moxa at support@moxa.com.tw.
 
    In addition to device driver, useful utilities are also provided in this
    version. They are
-    - msdiag     Diagnostic program for detecting installed Moxa Smartio boards.
+    - msdiag     Diagnostic program for displaying installed Moxa
+                 Smartio/Industio boards.
     - msmon      Monitor program to observe data count and line status signals.
     - msterm     A simple terminal program which is useful in testing serial
                 ports.
@@ -47,8 +76,7 @@ Content
    GNU General Public License in this version. Please refer to GNU General
    Public License announcement in each source code file for more detail.
 
-   In Moxa's ftp sites, you may always find latest driver at
-   ftp://ftp.moxa.com  or ftp://ftp.moxa.com.tw.
+   In Moxa's Web sites, you may always find latest driver at http://web.moxa.com.
 
    This version of driver can be installed as Loadable Module (Module driver)
    or built-in into kernel (Static driver). You may refer to following
@@ -61,18 +89,27 @@ Content
 
 -----------------------------------------------------------------------------
 2. System Requirement
-   - Hardware platform: Intel x86 or Alpha machine
-   - Kernel version: 2.0.3x or 2.2.x
+   - Hardware platform: Intel x86 machine
+   - Kernel version: 2.4.x or 2.6.x
    - gcc version 2.72 or later
    - Maximum 4 boards can be installed in combination
 
 -----------------------------------------------------------------------------
 3. Installation
 
+   3.1 Hardware installation
+   3.2 Driver files
+   3.3 Device naming convention
+   3.4 Module driver configuration
+   3.5 Static driver configuration for Linux kernel 2.4.x, 2.6.x.
+   3.6 Custom configuration
+   3.7 Verify driver installation
+
+
    3.1 Hardware installation
 
-       There are two types of buses, ISA and PCI, for Smartio family multiport
-       board.
+       There are two types of buses, ISA and PCI, for Smartio/Industio
+       family multiport board.
 
        ISA board
        ---------
@@ -81,47 +118,57 @@ Content
        installation procedure in User's Manual before proceed any further.
        Please make sure the JP1 is open after the ISA board is set properly.
 
-       PCI board
-       ---------
+       PCI/UPCI board
+       --------------
        You may need to adjust IRQ usage in BIOS to avoid from IRQ conflict
        with other ISA devices. Please refer to hardware installation
        procedure in User's Manual in advance.
 
-       IRQ Sharing
+       PCI IRQ Sharing
        -----------
        Each port within the same multiport board shares the same IRQ. Up to
-       4 Moxa Smartio Family multiport boards can be installed together on
-       one system and they can share the same IRQ.
+       4 Moxa Smartio/Industio PCI Family multiport boards can be installed
+       together on one system and they can share the same IRQ.
+
 
-   3.2 Driver files and device naming convention
+   3.2 Driver files
 
        The driver file may be obtained from ftp, CD-ROM or floppy disk. The
        first step, anyway, is to copy driver file "mxser.tgz" into specified
        directory. e.g. /moxa. The execute commands as below.
 
+       # cd /
+       # mkdir moxa
        # cd /moxa
-       # tar xvf /dev/fd0 
+       # tar xvf /dev/fd0
+
        or
+
+       # cd /
+       # mkdir moxa
        # cd /moxa
        # cp /mnt/cdrom/<driver directory>/mxser.tgz .
        # tar xvfz mxser.tgz
 
+
+   3.3 Device naming convention
+
        You may find all the driver and utilities files in /moxa/mxser.
        Following installation procedure depends on the model you'd like to
-       run the driver. If you prefer module driver, please refer to 3.3.
-       If static driver is required, please refer to 3.4.
+       run the driver. If you prefer module driver, please refer to 3.4.
+       If static driver is required, please refer to 3.5.
 
        Dialin and callout port
        -----------------------
-       This driver remains traditional serial device properties. There're
+       This driver remains traditional serial device properties. There are
        two special file name for each serial port. One is dial-in port
        which is named "ttyMxx". For callout port, the naming convention
        is "cumxx".
 
        Device naming when more than 2 boards installed
        -----------------------------------------------
-       Naming convention for each Smartio multiport board is pre-defined
-       as below.
+       Naming convention for each Smartio/Industio multiport board is
+       pre-defined as below.
 
        Board Num.       Dial-in Port         Callout port
        1st board       ttyM0  - ttyM7        cum0  - cum7
@@ -129,6 +176,12 @@ Content
        3rd board       ttyM16 - ttyM23       cum16 - cum23
        4th board       ttyM24 - ttym31       cum24 - cum31
 
+
+       !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+       Under Kernel 2.6 the cum Device is Obsolete. So use ttyM*
+       device instead.
+       !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
        Board sequence
        --------------
        This driver will activate ISA boards according to the parameter set
@@ -138,69 +191,131 @@ Content
        For PCI boards, their sequence will be after ISA boards and C168H/PCI
        has higher priority than C104H/PCI boards.
 
-   3.3 Module driver configuration
+   3.4 Module driver configuration
        Module driver is easiest way to install. If you prefer static driver
        installation, please skip this paragraph.
-       1. Find "Makefile" in /moxa/mxser, then run
 
-         # make install
+
+       ------------- Prepare to use the MOXA driver--------------------
+       3.4.1 Create tty device with correct major number
+          Before using MOXA driver, your system must have the tty devices
+          which are created with driver's major number. We offer one shell
+          script "msmknod" to simplify the procedure.
+          This step is only needed to be executed once. But you still
+          need to do this procedure when:
+          a. You change the driver's major number. Please refer the "3.7"
+             section.
+          b. Your total installed MOXA boards number is changed. Maybe you
+             add/delete one MOXA board.
+          c. You want to change the tty name. This needs to modify the
+             shell script "msmknod"
+
+          The procedure is:
+         # cd /moxa/mxser/driver
+         # ./msmknod
+
+          This shell script will require the major number for dial-in
+          device and callout device to create tty device. You also need
+          to specify the total installed MOXA board number. Default major
+          numbers for dial-in device and callout device are 30, 35. If
+          you need to change to other number, please refer section "3.7"
+          for more detailed procedure.
+          Msmknod will delete any special files occupying the same device
+          naming.
+
+       3.4.2 Build the MOXA driver and utilities
+          Before using the MOXA driver and utilities, you need compile the
+          all the source code. This step is only need to be executed once.
+          But you still re-compile the source code if you modify the source
+          code. For example, if you change the driver's major number (see
+          "3.7" section), then you need to do this step again.
+
+          Find "Makefile" in /moxa/mxser, then run
+
+         # make clean; make install
+
+          !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
+         For Red Hat 9, Red Hat Enterprise Linux AS3/ES3/WS3 & Fedora Core1:
+         # make clean; make installsp1
+
+         For Red Hat Enterprise Linux AS4/ES4/WS4:
+         # make clean; make installsp2
+          !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
 
          The driver files "mxser.o" and utilities will be properly compiled
-         and copied to system directories respectively.Then run
+         and copied to system directories respectively.
 
-         # insmod mxser
+       ------------- Load MOXA driver--------------------
+       3.4.3 Load the MOXA driver
 
-         to activate the modular driver. You may run "lsmod" to check
-         if "mxser.o" is activated.
+         # modprobe mxser <argument>
 
-       2. Create special files by executing "msmknod".
-         # cd /moxa/mxser/driver
-         # ./msmknod
+         will activate the module driver. You may run "lsmod" to check
+         if "mxser" is activated. If the MOXA board is ISA board, the
+          <argument> is needed. Please refer to section "3.4.5" for more
+          information.
+
+
+       ------------- Load MOXA driver on boot --------------------
+       3.4.4 For the above description, you may manually execute
+          "modprobe mxser" to activate this driver and run
+         "rmmod mxser" to remove it.
+          However, it's better to have a boot time configuration to
+          eliminate manual operation. Boot time configuration can be
+          achieved by rc file. We offer one "rc.mxser" file to simplify
+          the procedure under "moxa/mxser/driver".
 
-         Default major numbers for dial-in device and callout device are
-         174, 175. Msmknod will delete any special files occupying the same
-         device naming.
+          But if you use ISA board, please modify the "modprobe ..." command
+          to add the argument (see "3.4.5" section). After modifying the
+          rc.mxser, please try to execute "/moxa/mxser/driver/rc.mxser"
+          manually to make sure the modification is ok. If any error
+          encountered, please try to modify again. If the modification is
+          completed, follow the below step.
 
-       3. Up to now, you may manually execute "insmod mxser" to activate
-         this driver and run "rmmod mxser" to remove it. However, it's
-         better to have a boot time configuration to eliminate manual
-         operation.
-         Boot time configuration can be achieved by rc file. Run following
-         command for setting rc files.
+         Run following command for setting rc files.
 
          # cd /moxa/mxser/driver
          # cp ./rc.mxser /etc/rc.d
          # cd /etc/rc.d
 
-         You may have to modify part of the content in rc.mxser to specify
-          parameters for ISA board. Please refer to rc.mxser for more detail.
-          Find "rc.serial". If "rc.serial" doesn't exist, create it by vi.
-         Add "rc.mxser" in last line. Next, open rc.local by vi
-         and append following content.
+         Check "rc.serial" is existed or not. If "rc.serial" doesn't exist,
+         create it by vi, run "chmod 755 rc.serial" to change the permission.
+         Add "/etc/rc.d/rc.mxser" in last line,
 
-         if [ -f /etc/rc.d/rc.serial ]; then
-            sh /etc/rc.d/rc.serial
-         fi
+          Reboot and check if moxa.o activated by "lsmod" command.
 
-       4. Reboot and check if mxser.o activated by "lsmod" command.
-       5. If you'd like to drive Smartio ISA boards in the system, you'll
-         have to add parameter to specify CAP address of given board while
-          activating "mxser.o". The format for parameters are as follows.
+       3.4.5. If you'd like to drive Smartio/Industio ISA boards in the system,
+          you'll have to add parameter to specify CAP address of given
+         board while activating "mxser.o". The format for parameters are
+         as follows.
 
-         insmod mxser ioaddr=0x???,0x???,0x???,0x???
+         modprobe mxser ioaddr=0x???,0x???,0x???,0x???
                                |      |     |    |
                                |      |     |    +- 4th ISA board
                                |      |     +------ 3rd ISA board
                                |      +------------ 2nd ISA board
                                +------------------- 1st ISA board
 
-   3.4 Static driver configuration
+   3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x
+
+       Note: To use static driver, you must install the linux kernel
+             source package.
+
+       3.5.1 Backup the built-in driver in the kernel.
+          # cd /usr/src/linux/drivers/char
+          # mv mxser.c mxser.c.old
+
+          For Red Hat 7.x user, you need to create link:
+          # cd /usr/src
+          # ln -s linux-2.4 linux
 
-       1. Create link
+       3.5.2 Create link
          # cd /usr/src/linux/drivers/char
          # ln -s /moxa/mxser/driver/mxser.c mxser.c
 
-       2. Add CAP address list for ISA boards
+       3.5.3 Add CAP address list for ISA boards. For PCI boards user,
+          please skip this step.
+
          In module mode, the CAP address for ISA board is given by
          parameter. In static driver configuration, you'll have to
          assign it within driver's source code. If you will not
@@ -222,73 +337,55 @@ Content
             static int mxserBoardCAP[]
             = {0x280, 0x180, 0x00, 0x00};
 
-       3. Modify tty_io.c
-         # cd /usr/src/linux/drivers/char/
-         # vi tty_io.c
-           Find pty_init(), insert "mxser_init()" as
+       3.5.4 Setup kernel configuration
 
-           pty_init();
-           mxser_init();
+          Configure the kernel:
 
-       4. Modify tty.h
-         # cd /usr/src/linux/include/linux
-         # vi tty.h
-           Find extern int tty_init(void), insert "mxser_init()" as
+            # cd /usr/src/linux
+            # make menuconfig
 
-           extern int tty_init(void);
-           extern int mxser_init(void);
-     
-       5. Modify Makefile
-         # cd /usr/src/linux/drivers/char
-         # vi Makefile
-           Find L_OBJS := tty_io.o ...... random.o, add
-           "mxser.o" at last of this line as
-           L_OBJS := tty_io.o ....... mxser.o
+          You will go into a menu-driven system. Please select [Character
+          devices][Non-standard serial port support], enable the [Moxa
+          SmartIO support] driver with "[*]" for built-in (not "[M]"), then
+          select [Exit] to exit this program.
 
-       6. Rebuild kernel
-         The following are for Linux kernel rebuilding,for your reference only.
+       3.5.5 Rebuild kernel
+         The following are for Linux kernel rebuilding, for your
+          reference only.
          For appropriate details, please refer to the Linux document.
 
-         If 'lilo' utility is installed, please use 'make zlilo' to rebuild
-         kernel. If 'lilo' is not installed, please follow the following steps.
-
           a. cd /usr/src/linux
-          b. make clean                             /* take a few minutes */
-          c. make bzImage                 /* take probably 10-20 minutes */
-          d. Backup original boot kernel.                /* optional step */
-          e. cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz
+          b. make clean             /* take a few minutes */
+          c. make dep               /* take a few minutes */
+          d. make bzImage           /* take probably 10-20 minutes */
+          e. make install           /* copy boot image to correct position */
           f. Please make sure the boot kernel (vmlinuz) is in the
-             correct position. If you use 'lilo' utility, you should
-             check /etc/lilo.conf 'image' item specified the path
-             which is the 'vmlinuz' path, or you will load wrong
-             (or old) boot kernel image (vmlinuz).
-          g. chmod 400 /vmlinuz
-          h. lilo
-          i. rdev -R /vmlinuz 1
-          j. sync
-
-         Note that if the result of "make zImage" is ERROR, then you have to
-         go back to Linux configuration Setup. Type "make config" in directory
-         /usr/src/linux or "setup".
-
-         Since system include file, /usr/src/linux/include/linux/interrupt.h,
-         is modified each time the MOXA driver is installed, kernel rebuilding
-         is inevitable. And it takes about 10 to 20 minutes depends on the
-         machine.
-
-       7. Make utility
-         # cd /moxa/mxser/utility
-         # make install
-       
-       8. Make special file
+             correct position.
+          g. If you use 'lilo' utility, you should check /etc/lilo.conf
+             'image' item specified the path which is the 'vmlinuz' path,
+             or you will load wrong (or old) boot kernel image (vmlinuz).
+             After checking /etc/lilo.conf, please run "lilo".
+
+         Note that if the result of "make bzImage" is ERROR, then you have to
+         go back to Linux configuration Setup. Type "make menuconfig" in
+          directory /usr/src/linux.
+
+
+       3.5.6 Make tty device and special file
           # cd /moxa/mxser/driver
           # ./msmknod
 
-       9. Reboot
+       3.5.7 Make utility
+         # cd /moxa/mxser/utility
+         # make clean; make install
+
+       3.5.8 Reboot
 
-   3.5 Custom configuration
+
+
+   3.6 Custom configuration
        Although this driver already provides you default configuration, you
-       still can change the device name and major number.The instruction to
+       still can change the device name and major number. The instruction to
        change these parameters are shown as below.
 
        Change Device name
@@ -306,33 +403,37 @@ Content
        2 free major numbers for this driver. There are 3 steps to change
        major numbers.
 
-       1. Find free major numbers
+       3.6.1 Find free major numbers
          In /proc/devices, you may find all the major numbers occupied
          in the system. Please select 2 major numbers that are available.
          e.g. 40, 45.
-       2. Create special files
+       3.6.2 Create special files
          Run /moxa/mxser/driver/msmknod to create special files with
          specified major numbers.
-       3. Modify driver with new major number
+       3.6.3 Modify driver with new major number
          Run vi to open /moxa/mxser/driver/mxser.c. Locate the line
          contains "MXSERMAJOR". Change the content as below.
          #define         MXSERMAJOR              40
          #define         MXSERCUMAJOR            45
-       4. Run # make install in /moxa/mxser/driver.
+       3.6.4 Run "make clean; make install" in /moxa/mxser/driver.
 
-   3.6 Verify driver installation
+   3.7 Verify driver installation
        You may refer to /var/log/messages to check the latest status
        log reported by this driver whenever it's activated.
+
 -----------------------------------------------------------------------------
 4. Utilities
    There are 3 utilities contained in this driver. They are msdiag, msmon and
    msterm. These 3 utilities are released in form of source code. They should
    be compiled into executable file and copied into /usr/bin.
 
+   Before using these utilities, please load driver (refer 3.4 & 3.5) and
+   make sure you had run the "msmknod" utility.
+
    msdiag - Diagnostic
    --------------------
-   This utility provides the function to detect what Moxa Smartio multiport
-   board exists in the system.
+   This utility provides the function to display what Moxa Smartio/Industio
+   board found by driver in the system.
 
    msmon - Port Monitoring
    -----------------------
@@ -353,12 +454,13 @@ Content
    application, for example, sending AT command to a modem connected to the
    port or used as a terminal for login purpose. Note that this is only a
    dumb terminal emulation without handling full screen operation.
+
 -----------------------------------------------------------------------------
 5. Setserial
 
    Supported Setserial parameters are listed as below.
 
-   uart          set UART type(16450-->disable FIFO, 16550A-->enable FIFO)
+   uart                  set UART type(16450-->disable FIFO, 16550A-->enable FIFO)
    close_delay   set the amount of time(in 1/100 of a second) that DTR
                  should be kept low while being closed.
    closing_wait   set the amount of time(in 1/100 of a second) that the
@@ -366,7 +468,13 @@ Content
                  being closed, before the receiver is disable.
    spd_hi        Use  57.6kb  when  the application requests 38.4kb.
    spd_vhi       Use  115.2kb  when  the application requests 38.4kb.
+   spd_shi       Use  230.4kb  when  the application requests 38.4kb.
+   spd_warp      Use  460.8kb  when  the application requests 38.4kb.
    spd_normal    Use  38.4kb  when  the application requests 38.4kb.
+   spd_cust      Use  the custom divisor to set the speed when  the
+                 application requests 38.4kb.
+   divisor       This option set the custom divison.
+   baud_base     This option set the base baud rate.
 
 -----------------------------------------------------------------------------
 6. Troubleshooting
@@ -375,8 +483,9 @@ Content
    possible. If all the possible solutions fail, please contact our technical
    support team to get more help.
 
-   Error msg: More than 4 Moxa Smartio family boards found. Fifth board and
-             after are ignored.
+
+   Error msg: More than 4 Moxa Smartio/Industio family boards found. Fifth board
+              and after are ignored.
    Solution:
    To avoid this problem, please unplug fifth and after board, because Moxa
    driver supports up to 4 boards.
@@ -384,7 +493,7 @@ Content
    Error msg: Request_irq fail, IRQ(?) may be conflict with another device.
    Solution:
    Other PCI or ISA devices occupy the assigned IRQ. If you are not sure
-   which device causes the situation,please check /proc/interrupts to find
+   which device causes the situation, please check /proc/interrupts to find
    free IRQ and simply change another free IRQ for Moxa board.
 
    Error msg: Board #: C1xx Series(CAP=xxx) interrupt number invalid.
@@ -397,15 +506,18 @@ Content
    Moxa ISA board needs an interrupt vector.Please refer to user's manual
    "Hardware Installation" chapter to set interrupt vector.
 
-   Error msg: Couldn't install MOXA Smartio family driver!
+   Error msg: Couldn't install MOXA Smartio/Industio family driver!
    Solution:
    Load Moxa driver fail, the major number may conflict with other devices.
-   Please refer to previous section 3.5 to change a free major number for
+   Please refer to previous section 3.7 to change a free major number for
    Moxa driver.
 
-   Error msg: Couldn't install MOXA Smartio family callout driver!
+   Error msg: Couldn't install MOXA Smartio/Industio family callout driver!
    Solution:
    Load Moxa callout driver fail, the callout device major number may
-   conflict with other devices. Please refer to previous section 3.5 to
+   conflict with other devices. Please refer to previous section 3.7 to
    change a free callout device major number for Moxa driver.
+
+
 -----------------------------------------------------------------------------
+
index 7fa7fe71d7a8310c00c8cade78688ece2d5250c4..688dfe1e6b70f75a36d84f30dda2234c53664be0 100644 (file)
@@ -631,7 +631,7 @@ xmit_hash_policy
                in environments where a layer3 gateway device is
                required to reach most destinations.
 
-               This algorithm is 802.3ad complient.
+               This algorithm is 802.3ad compliant.
 
        layer3+4
 
index 641d2afacffa33094a5ee7a52e6646ec7c089220..297ba7b1ccaf953ff85e486baa0a7547450db31c 100644 (file)
@@ -186,7 +186,7 @@ solution for a couple of reasons:
 
   The Linux network devices (by default) just can handle the
   transmission and reception of media dependent frames. Due to the
-  arbritration on the CAN bus the transmission of a low prio CAN-ID
+  arbitration on the CAN bus the transmission of a low prio CAN-ID
   may be delayed by the reception of a high prio CAN frame. To
   reflect the correct* traffic on the node the loopback of the sent
   data has to be performed right after a successful transmission. If
@@ -481,7 +481,7 @@ solution for a couple of reasons:
   - stats_timer: To calculate the Socket CAN core statistics
     (e.g. current/maximum frames per second) this 1 second timer is
     invoked at can.ko module start time by default. This timer can be
-    disabled by using stattimer=0 on the module comandline.
+    disabled by using stattimer=0 on the module commandline.
 
   - debug: (removed since SocketCAN SVN r546)
 
index db0cd51695812cfe2c8850bb80471b422f994e25..07c53d5960353fa571e99a73b67910d7b10d6125 100644 (file)
@@ -326,7 +326,7 @@ just one call to mmap is needed:
     mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
 
 If tp_frame_size is a divisor of tp_block_size frames will be 
-contiguosly spaced by tp_frame_size bytes. If not, each 
+contiguously spaced by tp_frame_size bytes. If not, each
 tp_block_size/tp_frame_size frames there will be a gap between 
 the frames. This is because a frame cannot be spawn across two
 blocks. 
index 01e716d185f4253af3a262bdbfb4bde3dbdbb561..dcadf6f88e34222ef430d9423b34604c4ff37edd 100644 (file)
@@ -4,26 +4,27 @@ The "enviromental" rules for authors of any new tc actions are:
 1) If you stealeth or borroweth any packet thou shalt be branching
 from the righteous path and thou shalt cloneth.
 
-For example if your action queues a packet to be processed later
-or intentionaly branches by redirecting a packet then you need to
+For example if your action queues a packet to be processed later,
+or intentionally branches by redirecting a packet, then you need to
 clone the packet.
+
 There are certain fields in the skb tc_verd that need to be reset so we
-avoid loops etc. A few are generic enough so much so that skb_act_clone()
-resets them for you. So invoke skb_act_clone() rather than skb_clone()
+avoid loops, etc.  A few are generic enough that skb_act_clone()
+resets them for you, so invoke skb_act_clone() rather than skb_clone().
 
 2) If you munge any packet thou shalt call pskb_expand_head in the case
 someone else is referencing the skb. After that you "own" the skb.
 You must also tell us if it is ok to munge the packet (TC_OK2MUNGE),
 this way any action downstream can stomp on the packet.
 
-3) dropping packets you dont own is a nono. You simply return
+3) Dropping packets you don't own is a no-no. You simply return
 TC_ACT_SHOT to the caller and they will drop it.
 
 The "enviromental" rules for callers of actions (qdiscs etc) are:
 
-*) thou art responsible for freeing anything returned as being
+*) Thou art responsible for freeing anything returned as being
 TC_ACT_SHOT/STOLEN/QUEUED. If none of TC_ACT_SHOT/STOLEN/QUEUED is
-returned then all is great and you dont need to do anything.
+returned, then all is great and you don't need to do anything.
 
 Post on netdev if something is unclear.
 
index a55d7f1c836d7de2ad0b09b9ea2c138562db01a6..fb742c213c9eb37b9e8216c96f029bebed6a86e9 100644 (file)
@@ -1,5 +1,7 @@
 00-INDEX
        - This file
+apm-acpi.txt
+       - basic info about the APM and ACPI support.
 basic-pm-debugging.txt
        - Debugging suspend and resume
 devices.txt
@@ -14,8 +16,6 @@ notifiers.txt
        - Registering suspend notifiers in device drivers
 pci.txt
        - How the PCI Subsystem Does Power Management
-pm.txt
-       - info on Linux power management support.
 pm_qos_interface.txt
        - info on Linux PM Quality of Service interface
 power_supply_class.txt
diff --git a/Documentation/power/apm-acpi.txt b/Documentation/power/apm-acpi.txt
new file mode 100644 (file)
index 0000000..1bd799d
--- /dev/null
@@ -0,0 +1,32 @@
+APM or ACPI?
+------------
+If you have a relatively recent x86 mobile, desktop, or server system,
+odds are it supports either Advanced Power Management (APM) or
+Advanced Configuration and Power Interface (ACPI).  ACPI is the newer
+of the two technologies and puts power management in the hands of the
+operating system, allowing for more intelligent power management than
+is possible with BIOS controlled APM.
+
+The best way to determine which, if either, your system supports is to
+build a kernel with both ACPI and APM enabled (as of 2.3.x ACPI is
+enabled by default).  If a working ACPI implementation is found, the
+ACPI driver will override and disable APM, otherwise the APM driver
+will be used.
+
+No, sorry, you cannot have both ACPI and APM enabled and running at
+once.  Some people with broken ACPI or broken APM implementations
+would like to use both to get a full set of working features, but you
+simply cannot mix and match the two.  Only one power management
+interface can be in control of the machine at once.  Think about it..
+
+User-space Daemons
+------------------
+Both APM and ACPI rely on user-space daemons, apmd and acpid
+respectively, to be completely functional.  Obtain both of these
+daemons from your Linux distribution or from the Internet (see below)
+and be sure that they are started sometime in the system boot process.
+Go ahead and start both.  If ACPI or APM is not available on your
+system the associated daemon will exit gracefully.
+
+  apmd:   http://worldvisions.ca/~apenwarr/apmd/
+  acpid:  http://acpid.sf.net/
diff --git a/Documentation/power/pm.txt b/Documentation/power/pm.txt
deleted file mode 100644 (file)
index be84150..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-               Linux Power Management Support
-
-This document briefly describes how to use power management with your
-Linux system and how to add power management support to Linux drivers.
-
-APM or ACPI?
-------------
-If you have a relatively recent x86 mobile, desktop, or server system,
-odds are it supports either Advanced Power Management (APM) or
-Advanced Configuration and Power Interface (ACPI).  ACPI is the newer
-of the two technologies and puts power management in the hands of the
-operating system, allowing for more intelligent power management than
-is possible with BIOS controlled APM.
-
-The best way to determine which, if either, your system supports is to
-build a kernel with both ACPI and APM enabled (as of 2.3.x ACPI is
-enabled by default).  If a working ACPI implementation is found, the
-ACPI driver will override and disable APM, otherwise the APM driver
-will be used.
-
-No, sorry, you cannot have both ACPI and APM enabled and running at
-once.  Some people with broken ACPI or broken APM implementations
-would like to use both to get a full set of working features, but you
-simply cannot mix and match the two.  Only one power management
-interface can be in control of the machine at once.  Think about it..
-
-User-space Daemons
-------------------
-Both APM and ACPI rely on user-space daemons, apmd and acpid
-respectively, to be completely functional.  Obtain both of these
-daemons from your Linux distribution or from the Internet (see below)
-and be sure that they are started sometime in the system boot process.
-Go ahead and start both.  If ACPI or APM is not available on your
-system the associated daemon will exit gracefully.
-
-  apmd:   http://worldvisions.ca/~apenwarr/apmd/
-  acpid:  http://acpid.sf.net/
-
-Driver Interface -- OBSOLETE, DO NOT USE!
-----------------*************************
-
-Note: pm_register(), pm_access(), pm_dev_idle() and friends are
-obsolete. Please do not use them. Instead you should properly hook
-your driver into the driver model, and use its suspend()/resume()
-callbacks to do this kind of stuff.
-
-If you are writing a new driver or maintaining an old driver, it
-should include power management support.  Without power management
-support, a single driver may prevent a system with power management
-capabilities from ever being able to suspend (safely).
-
-Overview:
-1) Register each instance of a device with "pm_register"
-2) Call "pm_access" before accessing the hardware.
-   (this will ensure that the hardware is awake and ready)
-3) Your "pm_callback" is called before going into a
-   suspend state (ACPI D1-D3) or after resuming (ACPI D0)
-   from a suspend.
-4) Call "pm_dev_idle" when the device is not being used
-   (optional but will improve device idle detection)
-5) When unloaded, unregister the device with "pm_unregister"
-
-/*
- * Description: Register a device with the power-management subsystem
- *
- * Parameters:
- *   type - device type (PCI device, system device, ...)
- *   id - instance number or unique identifier
- *   cback - request handler callback (suspend, resume, ...)
- *
- * Returns: Registered PM device or NULL on error
- *
- * Examples:
- *   dev = pm_register(PM_SYS_DEV, PM_SYS_VGA, vga_callback);
- *
- *   struct pci_dev *pci_dev = pci_find_dev(...);
- *   dev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), callback);
- */
-struct pm_dev *pm_register(pm_dev_t type, unsigned long id, pm_callback cback);
-
-/*
- * Description: Unregister a device with the power management subsystem
- *
- * Parameters:
- *   dev - PM device previously returned from pm_register
- */
-void pm_unregister(struct pm_dev *dev);
-
-/*
- * Description: Unregister all devices with a matching callback function
- *
- * Parameters:
- *   cback - previously registered request callback
- *
- * Notes: Provided for easier porting from old APM interface
- */
-void pm_unregister_all(pm_callback cback);
-
-/*
- * Power management request callback
- *
- * Parameters:
- *   dev - PM device previously returned from pm_register
- *   rqst - request type
- *   data - data, if any, associated with the request
- *
- * Returns: 0 if the request is successful
- *          EINVAL if the request is not supported
- *          EBUSY if the device is now busy and cannot handle the request
- *          ENOMEM if the device was unable to handle the request due to memory
- *
- * Details: The device request callback will be called before the
- *          device/system enters a suspend state (ACPI D1-D3) or
- *          or after the device/system resumes from suspend (ACPI D0).
- *          For PM_SUSPEND, the ACPI D-state being entered is passed
- *          as the "data" argument to the callback.  The device
- *          driver should save (PM_SUSPEND) or restore (PM_RESUME)
- *          device context when the request callback is called.
- *
- *          Once a driver returns 0 (success) from a suspend
- *          request, it should not process any further requests or
- *          access the device hardware until a call to "pm_access" is made.
- */
-typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data);
-
-Driver Details
---------------
-This is just a quick Q&A as a stopgap until a real driver writers'
-power management guide is available.
-
-Q: When is a device suspended?
-
-Devices can be suspended based on direct user request (eg. laptop lid
-closes), system power policy (eg.  sleep after 30 minutes of console
-inactivity), or device power policy (eg. power down device after 5
-minutes of inactivity)
-
-Q: Must a driver honor a suspend request?
-
-No, a driver can return -EBUSY from a suspend request and this
-will stop the system from suspending.  When a suspend request
-fails, all suspended devices are resumed and the system continues
-to run.  Suspend can be retried at a later time.
-
-Q: Can the driver block suspend/resume requests?
-
-Yes, a driver can delay its return from a suspend or resume
-request until the device is ready to handle requests.  It
-is advantageous to return as quickly as possible from a
-request as suspend/resume are done serially.
-
-Q: What context is a suspend/resume initiated from?
-
-A suspend or resume is initiated from a kernel thread context.
-It is safe to block, allocate memory, initiate requests
-or anything else you can do within the kernel.
-
-Q: Will requests continue to arrive after a suspend?
-
-Possibly.  It is the driver's responsibility to queue(*),
-fail, or drop any requests that arrive after returning
-success to a suspend request.  It is important that the
-driver not access its device until after it receives
-a resume request as the device's bus may no longer
-be active.
-
-(*) If a driver queues requests for processing after
-    resume be aware that the device, network, etc.
-    might be in a different state than at suspend time.
-    It's probably better to drop requests unless
-    the driver is a storage device.
-
-Q: Do I have to manage bus-specific power management registers
-
-No.  It is the responsibility of the bus driver to manage
-PCI, USB, etc. power management registers.  The bus driver
-or the power management subsystem will also enable any
-wake-on functionality that the device has.
-
-Q: So, really, what do I need to do to support suspend/resume?
-
-You need to save any device context that would
-be lost if the device was powered off and then restore
-it at resume time.  When ACPI is active, there are
-three levels of device suspend states; D1, D2, and D3.
-(The suspend state is passed as the "data" argument
-to the device callback.)  With D3, the device is powered
-off and loses all context, D1 and D2 are shallower power
-states and require less device context to be saved.  To
-play it safe, just save everything at suspend and restore
-everything at resume.
-
-Q: Where do I store device context for suspend?
-
-Anywhere in memory, kmalloc a buffer or store it
-in the device descriptor.  You are guaranteed that the
-contents of memory will be restored and accessible
-before resume, even when the system suspends to disk.
-
-Q: What do I need to do for ACPI vs. APM vs. etc?
-
-Drivers need not be aware of the specific power management
-technology that is active.  They just need to be aware
-of when the overlying power management system requests
-that they suspend or resume.
-
-Q: What about device dependencies?
-
-When a driver registers a device, the power management
-subsystem uses the information provided to build a
-tree of device dependencies (eg. USB device X is on
-USB controller Y which is on PCI bus Z)  When power
-management wants to suspend a device, it first sends
-a suspend request to its driver, then the bus driver,
-and so on up to the system bus.  Device resumes
-proceed in the opposite direction.
-
-Q: Who do I contact for additional information about
-   enabling power management for my specific driver/device?
-
-ACPI Development mailing list: linux-acpi@vger.kernel.org
-
-System Interface -- OBSOLETE, DO NOT USE!
-----------------*************************
-If you are providing new power management support to Linux (ie.
-adding support for something like APM or ACPI), you should
-communicate with drivers through the existing generic power
-management interface.
-
-/*
- * Send a request to all devices
- *
- * Parameters:
- *   rqst - request type
- *   data - data, if any, associated with the request
- *
- * Returns: 0 if the request is successful
- *          See "pm_callback" return for errors
- *
- * Details: Walk list of registered devices and call pm_send
- *          for each until complete or an error is encountered.
- *          If an error is encountered for a suspend request,
- *          return all devices to the state they were in before
- *          the suspend request.
- */
-int pm_send_all(pm_request_t rqst, void *data);
-
-/*
- * Find a matching device
- *
- * Parameters:
- *   type - device type (PCI device, system device, or 0 to match all devices)
- *   from - previous match or NULL to start from the beginning
- *
- * Returns: Matching device or NULL if none found
- */
-struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from);
index ea1b70b357936b6e32ebfb8e3c7ae180f45f9209..928a79ceb7aaeb9515fbee4141cd18f06c6f37c5 100644 (file)
@@ -59,6 +59,7 @@ Table of Contents
       p) Freescale Synchronous Serial Interface
          q) USB EHCI controllers
       r) MDIO on GPIOs
+      s) SPI busses
 
   VII - Marvell Discovery mv64[345]6x System Controller chips
     1) The /system-controller node
@@ -707,7 +708,7 @@ device or bus to be described by the device tree.
 In general, the format of an address for a device is defined by the
 parent bus type, based on the #address-cells and #size-cells
 properties.  Note that the parent's parent definitions of #address-cells
-and #size-cells are not inhereted so every node with children must specify
+and #size-cells are not inherited so every node with children must specify
 them.  The kernel requires the root node to have those properties defining
 addresses format for devices directly mapped on the processor bus.
 
@@ -1776,7 +1777,7 @@ platforms are moved over to use the flattened-device-tree model.
 
       Xilinx uartlite devices are simple fixed speed serial ports.
 
-      Requred properties:
+      Required properties:
        - current-speed : Baud rate of uartlite
 
       v) Xilinx hwicap
@@ -1798,7 +1799,7 @@ platforms are moved over to use the flattened-device-tree model.
       Xilinx UART 16550 devices are very similar to the NS16550 but with
       different register spacing and an offset from the base address.
 
-      Requred properties:
+      Required properties:
        - clock-frequency : Frequency of the clock input
        - reg-offset : A value of 3 is required
        - reg-shift : A value of 2 is required
@@ -1883,6 +1884,62 @@ platforms are moved over to use the flattened-device-tree model.
                         &qe_pio_c 6>;
        };
 
+    s) SPI (Serial Peripheral Interface) busses
+
+    SPI busses can be described with a node for the SPI master device
+    and a set of child nodes for each SPI slave on the bus.  For this
+    discussion, it is assumed that the system's SPI controller is in
+    SPI master mode.  This binding does not describe SPI controllers
+    in slave mode.
+
+    The SPI master node requires the following properties:
+    - #address-cells  - number of cells required to define a chip select
+                       address on the SPI bus.
+    - #size-cells     - should be zero.
+    - compatible      - name of SPI bus controller following generic names
+                       recommended practice.
+    No other properties are required in the SPI bus node.  It is assumed
+    that a driver for an SPI bus device will understand that it is an SPI bus.
+    However, the binding does not attempt to define the specific method for
+    assigning chip select numbers.  Since SPI chip select configuration is
+    flexible and non-standardized, it is left out of this binding with the
+    assumption that board specific platform code will be used to manage
+    chip selects.  Individual drivers can define additional properties to
+    support describing the chip select layout.
+
+    SPI slave nodes must be children of the SPI master node and can
+    contain the following properties.
+    - reg             - (required) chip select address of device.
+    - compatible      - (required) name of SPI device following generic names
+                       recommended practice
+    - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
+    - spi-cpol        - (optional) Empty property indicating device requires
+                       inverse clock polarity (CPOL) mode
+    - spi-cpha        - (optional) Empty property indicating device requires
+                       shifted clock phase (CPHA) mode
+
+    SPI example for an MPC5200 SPI bus:
+               spi@f00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+                       reg = <0xf00 0x20>;
+                       interrupts = <2 13 0 2 14 0>;
+                       interrupt-parent = <&mpc5200_pic>;
+
+                       ethernet-switch@0 {
+                               compatible = "micrel,ks8995m";
+                               spi-max-frequency = <1000000>;
+                               reg = <0>;
+                       };
+
+                       codec@1 {
+                               compatible = "ti,tlv320aic26";
+                               spi-max-frequency = <100000>;
+                               reg = <1>;
+                       };
+               };
+
 VII - Marvell Discovery mv64[345]6x System Controller chips
 ===========================================================
 
@@ -1896,7 +1953,7 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd.
 1) The /system-controller node
 
   This node is used to represent the system-controller and must be
-  present when the system uses a system contller chip. The top-level
+  present when the system uses a system controller chip. The top-level
   system-controller node contains information that is global to all
   devices within the system controller chip. The node name begins
   with "system-controller" followed by the unit address, which is
index 896266432d3363e23ce874600293504e6c396f6a..06da4d4b44f9c0d3f81bcbddb01ccc5c76ae01d8 100644 (file)
@@ -217,7 +217,7 @@ Although it is not recommended, you can specify '0' in the soc.model
 field to skip matching SOCs altogether.
 
 The 'model' field is a 16-bit number that matches the actual SOC. The
-'major' and 'minor' fields are the major and minor revision numbrs,
+'major' and 'minor' fields are the major and minor revision numbers,
 respectively, of the SOC.
 
 For example, to match the 8323, revision 1.0:
index e938c442277dc0ecd1b05002ba9167abbedd914c..bde473df748dc95ca903bcadd2155a7def8ed4c4 100644 (file)
@@ -25,7 +25,7 @@ device 4711 via subchannel 1 in subchannel set 0, and subchannel 2 is a non-I/O
 subchannel. Device 1234 is accessed via subchannel 0 in subchannel set 1.
 
 The subchannel named 'defunct' does not represent any real subchannel on the
-system; it is a pseudo subchannel where disconnnected ccw devices are moved to
+system; it is a pseudo subchannel where disconnected ccw devices are moved to
 if they are displaced by another ccw device becoming operational on their
 former subchannel. The ccw devices will be moved again to a proper subchannel
 if they become operational again on that subchannel.
index a810421f1fb3dfab2e256bcb097db6b1fbc484d9..3920f28710c4fcd224fee28bc6959dc192346829 100644 (file)
    - Michael Lang
  
    June 25 1997: (v1.8b)
-   1) Some cosmetical changes for the handling of SCSI-device-types.
+   1) Some cosmetic changes for the handling of SCSI-device-types.
       Now, also CD-Burners / WORMs and SCSI-scanners should work. For
       MO-drives I have no experience, therefore not yet supported.
       In logical_devices I changed from different type-variables to one
       in version 4.0. This was never really necessary, as all troubles were
       based on non-command related reasons up to now, so bypassing commands
       did not help to avoid any bugs. It is kept in 3.2X for debugging reasons.
-   5) Dynamical reassignment of ldns was again verified and analyzed to be
+   5) Dynamic reassignment of ldns was again verified and analyzed to be
       completely inoperational. This is corrected and should work now.
    6) All commands that get sent to the SCSI adapter were verified and
       completed in such a way, that they are now completely conform to the
    concerning the Linux-kernel in special, this SCSI-driver comes without any
    warranty. Its functionality is tested as good as possible on certain 
    machines and combinations of computer hardware, which does not exclude,
-   that dataloss or severe damage of hardware is possible while using this
+   that data loss or severe damage of hardware is possible while using this
    part of software on some arbitrary computer hardware or in combination 
    with other software packages. It is highly recommended to make backup
    copies of your data before using this software. Furthermore, personal
index 4dbe41370a6d6056657da648d20dd7d18576d15d..5741ea8aa88a9e23b495819249fddad5e6c3def0 100644 (file)
@@ -36,7 +36,7 @@ Cable pull and temporary device Loss:
   being removed, a switch rebooting, or a device reboot), the driver could
   hide the disappearance of the device from the midlayer. I/O's issued to
   the LLDD would simply be queued for a short duration, allowing the device
-  to reappear or link come back alive, with no inadvertant side effects
+  to reappear or link come back alive, with no inadvertent side effects
   to the system. If the driver did not hide these conditions, i/o would be
   errored by the driver, the mid-layer would exhaust its retries, and the
   device would be taken offline. Manual intervention would be required to
index d403e46d8463e14fecfd6fc105a119608692d207..75143f0c23b685f95292c2764172350adacafcc8 100644 (file)
@@ -65,7 +65,7 @@ Overview:
     discussion will concentrate on NPIV.
 
   Note: World Wide Name assignment (and uniqueness guarantees) are left
-    up to an administrative entity controling the vport. For example,
+    up to an administrative entity controlling the vport. For example,
     if vports are to be associated with virtual machines, a XEN mgmt
     utility would be responsible for creating wwpn/wwnn's for the vport,
     using it's own naming authority and OUI. (Note: it already does this
@@ -91,7 +91,7 @@ Device Trees and Vport Objects:
   Here's what to expect in the device tree :
    The typical Physical Port's Scsi_Host:
      /sys/devices/.../host17/
-   and it has the typical decendent tree:
+   and it has the typical descendant tree:
      /sys/devices/.../host17/rport-17:0-0/target17:0:0/17:0:0:0:
    and then the vport is created on the Physical Port:
      /sys/devices/.../host17/vport-17:0-0
@@ -192,7 +192,7 @@ Vport States:
       independent of the adapter's link state.
     - Instantiation of the vport on the FC link via ELS traffic, etc.
       This is equivalent to a "link up" and successfull link initialization.
-  Futher information can be found in the interfaces section below for
+  Further information can be found in the interfaces section below for
   Vport Creation.
 
   Once a vport has been instantiated with the kernel/LLDD, a vport state
index 9aef710e9a4b5aa881fa6574ee3fcf9c2406c79f..114b595cfa978a2d17c1cced940043732d7fe333 100644 (file)
@@ -12,7 +12,7 @@ means no changes to adjanced clock
 Internally, the clk_set_rate_ex forwards request to clk->ops->set_rate method,
 if it is present in ops structure. The method should set the clock rate and adjust
 all needed clocks according to the passed algo_id.
-Exact values for algo_id are machine-dependend. For the sh7722, the following
+Exact values for algo_id are machine-dependent. For the sh7722, the following
 values are defined:
 
        NO_CHANGE       = 0,
index 72aff61e731509d7c87f3a3913aa3b4e965ab9c5..6f6d117ac7e22cd2d9fc981f0fc8542d824d1db8 100644 (file)
@@ -1024,6 +1024,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          intel-mac-v3  Intel Mac Type 3
          intel-mac-v4  Intel Mac Type 4
          intel-mac-v5  Intel Mac Type 5
+         intel-mac-auto Intel Mac (detect type according to subsystem id)
          macmini       Intel Mac Mini (equivalent with type 3)
          macbook       Intel Mac Book (eq. type 5)
          macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)
index 2ad5e6306c445bd369bb5346bf18da6156382bca..a4c53d8961e1ca1c57686ac9560bece125fed03a 100644 (file)
@@ -236,15 +236,15 @@ The parameter can be given:
        alias snd-card-1 snd-usb-audio
        options snd-usb-audio index=1 device_setup=0x09
 
-CAUTION when initializaing the device
+CAUTION when initializing the device
 -------------------------------------
 
  * Correct initialization on the device requires that device_setup is given to
    the module BEFORE the device is turned on. So, if you use the "manual probing"
    method described above, take care to power-on the device AFTER this initialization.
 
- * Failing to respect this will lead in a misconfiguration of the device. In this case
-   turn off the device, unproble the snd-usb-audio module, then probe it again with 
+ * Failing to respect this will lead to a misconfiguration of the device. In this case
+   turn off the device, unprobe the snd-usb-audio module, then probe it again with
    correct device_setup parameter and then (and only then) turn on the device again.
 
  * If you've correctly initialized the device in a valid mode and then want to switch
@@ -388,9 +388,9 @@ There are 2 main potential issues when using Jackd with the device:
 
 Jack supports big endian devices only in recent versions (thanks to
 Andreas Steinmetz for his first big-endian patch). I can't remember 
-extacly when this support was released into jackd, let's just say that 
+exactly when this support was released into jackd, let's just say that
 with jackd version 0.103.0 it's almost ok (just a small bug is affecting 
-16bits Big-Endian devices, but since you've read  carefully the above 
+16bits Big-Endian devices, but since you've read carefully the above
 paragraphs, you're now using kernel >= 2.6.23 and your 16bits devices 
 are now Little Endians ;-) ).
 
index 8e1b02526698c55da2c8da8964f480a108a53cb2..34e87ec1379c8e6af81d90608125628535ad107a 100644 (file)
@@ -67,7 +67,7 @@ CONFIG_SND_HDA_POWER_SAVE kconfig.  It's called when the codec needs
 to power up or may power down.  The controller should check the all
 belonging codecs on the bus whether they are actually powered off
 (check codec->power_on), and optionally the driver may power down the
-contoller side, too.
+controller side, too.
 
 The bus instance is created via snd_hda_bus_new().  You need to pass
 the card instance, the template, and the pointer to store the
index c784a18b94dce93bdcb064b2ef6670d450846bd5..b2ed6983f40d21483cfcbbd1e634533ca64e4115 100644 (file)
@@ -68,7 +68,7 @@ Audio DAPM widgets fall into a number of types:-
 (Widgets are defined in include/sound/soc-dapm.h)
 
 Widgets are usually added in the codec driver and the machine driver. There are
-convience macros defined in soc-dapm.h that can be used to quickly build a
+convenience macros defined in soc-dapm.h that can be used to quickly build a
 list of widgets of the codecs and machines DAPM widgets.
 
 Most widgets have a name, register, shift and invert. Some widgets have extra
index 1a3bdc27d95e98ce49c07791b02515e38ef678a5..42f43fa59f24c75c1f553dc5078f88b949302fd9 100644 (file)
@@ -73,10 +73,10 @@ recompiled, or use "make C=2" to run sparse on the files whether they need to
 be recompiled or not.  The latter is a fast way to check the whole tree if you
 have already built it.
 
-The optional make variable CHECKFLAGS can be used to pass arguments to sparse.
-The build system passes -Wbitwise to sparse automatically.  To perform
-endianness checks, you may define __CHECK_ENDIAN__:
+The optional make variable CF can be used to pass arguments to sparse.  The
+build system passes -Wbitwise to sparse automatically.  To perform endianness
+checks, you may define __CHECK_ENDIAN__:
 
-        make C=2 CHECKFLAGS="-D__CHECK_ENDIAN__"
+        make C=2 CF="-D__CHECK_ENDIAN__"
 
 These checks are disabled by default as they generate a host of warnings.
index 8a4863c4edd4c2463ac7fe5a5a492ac5156c9932..d79eeda7a699cbeb72ad0a03332388f8d8a68eeb 100644 (file)
@@ -116,7 +116,7 @@ of kilobytes free.  The VM uses this number to compute a pages_min
 value for each lowmem zone in the system.  Each lowmem zone gets 
 a number of reserved free pages based proportionally on its size.
 
-Some minimal ammount of memory is needed to satisfy PF_MEMALLOC
+Some minimal amount of memory is needed to satisfy PF_MEMALLOC
 allocations; if you set this to lower than 1024KB, your system will
 become subtly broken, and prone to deadlock under high loads.
 
index a73ecf5b4bdb80c6b9977332d89b3eebc479e5c0..21332233cef16a157b95519640e356beadf2eeee 100644 (file)
@@ -125,7 +125,7 @@ increase of flexibility and the avoidance of duplicated code across
 architectures justifies the slight increase of the binary size.
 
 The conversion of an architecture has no functional impact, but allows to
-utilize the high resolution and dynamic tick functionalites without any change
+utilize the high resolution and dynamic tick functionalities without any change
 to the clock event device and timer interrupt code. After the conversion the
 enabling of high resolution timers and dynamic ticks is simply provided by
 adding the kernel/time/Kconfig file to the architecture specific Kconfig and
index b0472ac5226a38ff2f740c185dcfdd5676dbcf97..f866c72291bf4ce2e29a9a6ffd1c40ac740d4bb7 100644 (file)
@@ -218,9 +218,35 @@ If use of such macros is not convenient, another option is to use memcpy(),
 where the source or destination (or both) are of type u8* or unsigned char*.
 Due to the byte-wise nature of this operation, unaligned accesses are avoided.
 
+
+Alignment vs. Networking
+========================
+
+On architectures that require aligned loads, networking requires that the IP
+header is aligned on a four-byte boundary to optimise the IP stack. For
+regular ethernet hardware, the constant NET_IP_ALIGN is used. On most
+architectures this constant has the value 2 because the normal ethernet
+header is 14 bytes long, so in order to get proper alignment one needs to
+DMA to an address which can be expressed as 4*n + 2. One notable exception
+here is powerpc which defines NET_IP_ALIGN to 0 because DMA to unaligned
+addresses can be very expensive and dwarf the cost of unaligned loads.
+
+For some ethernet hardware that cannot DMA to unaligned addresses like
+4*n+2 or non-ethernet hardware, this can be a problem, and it is then
+required to copy the incoming frame into an aligned buffer. Because this is
+unnecessary on architectures that can do unaligned accesses, the code can be
+made dependent on CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS like so:
+
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+       skb = original skb
+#else
+       skb = copy skb
+#endif
+
 --
-Author: Daniel Drake <dsd@gentoo.org>
+Authors: Daniel Drake <dsd@gentoo.org>,
+         Johannes Berg <johannes@sipsolutions.net>
 With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt,
-Johannes Berg, Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock,
-Uli Kunitz, Vadim Lobanov
+Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz,
+Vadim Lobanov
 
index 2af400609498d7c3d4bb33ad7c4a253973af3a4a..381b22ee7834bd2d7b0485570ea9a6caa0a5c587 100644 (file)
@@ -8,7 +8,7 @@ not) in a system. This feature will allow you to implement a lock-down
 of USB devices, fully controlled by user space.
 
 As of now, when a USB device is connected it is configured and
-it's interfaces inmediately made available to the users. With this
+its interfaces are immediately made available to the users.  With this
 modification, only if root authorizes the device to be configured will
 then it be possible to use it.
 
index 86d1c8e7b18f3c31b39dca8176acc3e9bdfdf96a..eedc399e8debd741fc8fb33e25f5a0d55393030f 100644 (file)
@@ -2,3 +2,4 @@
   1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200,2040:7210,2040:7217,2040:721b,2040:721f,2040:7280,0fd9:0008]
   2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
   3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
+  4 -> Hauppauge HVR950Q rev xxF8               (au0828)        [2040:7201,2040:7211,2040:7281]
index 10591467ef166aef609c2b527de16c9d17ca1ff1..89c7f32abf9f2d8a43f98dc892b8ca9b8bad9a24 100644 (file)
@@ -1,11 +1,11 @@
   0 -> Unknown EM2800 video grabber             (em2800)        [eb1a:2800]
-  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2750,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
+  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
   2 -> Terratec Cinergy 250 USB                 (em2820/em2840) [0ccd:0036]
   3 -> Pinnacle PCTV USB 2                      (em2820/em2840) [2304:0208]
   4 -> Hauppauge WinTV USB 2                    (em2820/em2840) [2040:4200,2040:4201]
   5 -> MSI VOX USB 2.0                          (em2820/em2840)
   6 -> Terratec Cinergy 200 USB                 (em2800)
-  7 -> Leadtek Winfast USB II                   (em2800)
+  7 -> Leadtek Winfast USB II                   (em2800)        [0413:6023]
   8 -> Kworld USB2800                           (em2800)
   9 -> Pinnacle Dazzle DVC 90/DVC 100           (em2820/em2840) [2304:0207,2304:021a]
  10 -> Hauppauge WinTV HVR 900                  (em2880)        [2040:6500]
  13 -> Terratec Prodigy XS                      (em2880)        [0ccd:0047]
  14 -> Pixelview Prolink PlayTV USB 2.0         (em2820/em2840)
  15 -> V-Gear PocketTV                          (em2800)
- 16 -> Hauppauge WinTV HVR 950                  (em2880)        [2040:6513,2040:6517,2040:651b,2040:651f]
+ 16 -> Hauppauge WinTV HVR 950                  (em2883)        [2040:6513,2040:6517,2040:651b,2040:651f]
  17 -> Pinnacle PCTV HD Pro Stick               (em2880)        [2304:0227]
  18 -> Hauppauge WinTV HVR 900 (R2)             (em2880)        [2040:6502]
  19 -> PointNix Intra-Oral Camera               (em2860)
+ 20 -> AMD ATI TV Wonder HD 600                 (em2880)        [0438:b002]
+ 21 -> eMPIA Technology, Inc. GrabBeeX+ Video Encoder (em2800)        [eb1a:2801]
+ 22 -> Unknown EM2750/EM2751 webcam grabber     (em2750)        [eb1a:2750,eb1a:2751]
+ 23 -> Huaqi DLCW-130                           (em2750)
+ 24 -> D-Link DUB-T210 TV Tuner                 (em2820/em2840) [2001:f112]
+ 25 -> Gadmei UTV310                            (em2820/em2840)
+ 26 -> Hercules Smart TV USB 2.0                (em2820/em2840)
+ 27 -> Pinnacle PCTV USB 2 (Philips FM1216ME)   (em2820/em2840)
+ 28 -> Leadtek Winfast USB II Deluxe            (em2820/em2840)
+ 29 -> Pinnacle Dazzle DVC 100                  (em2820/em2840)
+ 30 -> Videology 20K14XUSB USB2.0               (em2820/em2840)
+ 31 -> Usbgear VD204v9                          (em2821)
+ 32 -> Supercomp USB 2.0 TV                     (em2821)
+ 33 -> SIIG AVTuner-PVR/Prolink PlayTV USB 2.0  (em2821)
+ 34 -> Terratec Cinergy A Hybrid XS             (em2860)        [0ccd:004f]
+ 35 -> Typhoon DVD Maker                        (em2860)
+ 36 -> NetGMBH Cam                              (em2860)
+ 37 -> Gadmei UTV330                            (em2860)
+ 38 -> Yakumo MovieMixer                        (em2861)
+ 39 -> KWorld PVRTV 300U                        (em2861)        [eb1a:e300]
+ 40 -> Plextor ConvertX PX-TV100U               (em2861)        [093b:a005]
+ 41 -> Kworld 350 U DVB-T                       (em2870)        [eb1a:e350]
+ 42 -> Kworld 355 U DVB-T                       (em2870)        [eb1a:e355,eb1a:e357]
+ 43 -> Terratec Cinergy T XS                    (em2870)        [0ccd:0043]
+ 44 -> Terratec Cinergy T XS (MT2060)           (em2870)
+ 45 -> Pinnacle PCTV DVB-T                      (em2870)
+ 46 -> Compro, VideoMate U3                     (em2870)        [185b:2870]
+ 47 -> KWorld DVB-T 305U                        (em2880)        [eb1a:e305]
+ 48 -> KWorld DVB-T 310U                        (em2880)
+ 49 -> MSI DigiVox A/D                          (em2880)        [eb1a:e310]
+ 50 -> MSI DigiVox A/D II                       (em2880)        [eb1a:e320]
+ 51 -> Terratec Hybrid XS Secam                 (em2880)        [0ccd:004c]
+ 52 -> DNT DA2 Hybrid                           (em2881)
+ 53 -> Pinnacle Hybrid Pro                      (em2881)
+ 54 -> Kworld VS-DVB-T 323UR                    (em2882)        [eb1a:e323]
+ 55 -> Terratec Hybrid XS (em2882)              (em2882)        [0ccd:005e]
+ 56 -> Pinnacle Hybrid Pro (2)                  (em2882)        [2304:0226]
+ 57 -> Kworld PlusTV HD Hybrid 330              (em2883)        [eb1a:a316]
+ 58 -> Compro VideoMate ForYou/Stereo           (em2820/em2840) [185b:2041]
index 0c4880af57a337d597baf871cb4926f48bfffd76..bcaf4ab383be001214f33d5abfbd2adbf954575a 100644 (file)
@@ -1,4 +1,4 @@
-List of the webcams know by gspca.
+List of the webcams known by gspca.
 
 The modules are:
        gspca_main      main driver
index b26f5195af51f58db1d4a04f2826e044b29bc8a2..73de4050d63738dd15c4d3872e3ca49d5e5e089d 100644 (file)
@@ -157,7 +157,7 @@ Loading can be done as shown below:
 
        [root@localhost home]# modprobe sn9c102
 
-Note that the module is called "sn9c102" for historic reasons, althought it
+Note that the module is called "sn9c102" for historic reasons, although it
 does not just support the SN9C102.
 
 At this point all the devices supported by the driver and connected to the USB
index 3102b81bef88d86b753449e86f1d65f6d04c7ea8..ea8714fcc3ad4882dba62d625d22e61ac0a3079f 100644 (file)
@@ -77,7 +77,7 @@ memory that is preset in system at this time.  System administrators may want
 to put this command in one of the local rc init files.  This will enable the
 kernel to request huge pages early in the boot process (when the possibility
 of getting physical contiguous pages is still very high). In either
-case, adminstrators will want to verify the number of hugepages actually
+case, administrators will want to verify the number of hugepages actually
 allocated by checking the sysctl or meminfo.
 
 /proc/sys/vm/nr_overcommit_hugepages indicates how large the pool of
@@ -95,6 +95,29 @@ this condition holds, however, no more surplus huge pages will be
 allowed on the system until one of the two sysctls are increased
 sufficiently, or the surplus huge pages go out of use and are freed.
 
+With support for multiple hugepage pools at run-time available, much of
+the hugepage userspace interface has been duplicated in sysfs. The above
+information applies to the default hugepage size (which will be
+controlled by the proc interfaces for backwards compatibility). The root
+hugepage control directory is
+
+       /sys/kernel/mm/hugepages
+
+For each hugepage size supported by the running kernel, a subdirectory
+will exist, of the form
+
+       hugepages-${size}kB
+
+Inside each of these directories, the same set of files will exist:
+
+       nr_hugepages
+       nr_overcommit_hugepages
+       free_hugepages
+       resv_hugepages
+       surplus_hugepages
+
+which function as described above for the default hugepage-sized case.
+
 If the user applications are going to request hugepages using mmap system
 call, then it is required that system administrator mount a file system of
 type hugetlbfs:
index bad16d3f6a473afe913b0be76e783bcb946bc937..6aaaeb38730cf0ff1d5389cd73a6a8d2fb6bd413 100644 (file)
@@ -58,7 +58,7 @@ most general to most specific:
        the policy at the time they were allocated.
 
     VMA Policy:  A "VMA" or "Virtual Memory Area" refers to a range of a task's
-    virtual adddress space.  A task may define a specific policy for a range
+    virtual address space.  A task may define a specific policy for a range
     of its virtual address space.   See the MEMORY POLICIES APIS section,
     below, for an overview of the mbind() system call used to set a VMA
     policy.
@@ -353,7 +353,7 @@ follows:
 
    Because of this extra reference counting, and because we must lookup
    shared policies in a tree structure under spinlock, shared policies are
-   more expensive to use in the page allocation path.  This is expecially
+   more expensive to use in the page allocation path.  This is especially
    true for shared policies on shared memory regions shared by tasks running
    on different NUMA nodes.  This extra overhead can be avoided by always
    falling back to task or system default policy for shared memory regions,
index 10c2e411cca899558b998e8bed0d3239d4cc92a6..991c26a6ef64fcfdef0fc870d3ed404f55751407 100644 (file)
@@ -114,6 +114,6 @@ CREDITS
 
 Original impetus and research by Randy Dunlap
 Written by Jonathan Corbet
-Improvements via coments from Satyam Sharma, Johannes Stezenbach, Jesper
+Improvements via comments from Satyam Sharma, Johannes Stezenbach, Jesper
        Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, and Stefan
        Richter.
diff --git a/Kbuild b/Kbuild
index e750e9c3fe59862e377a568e0758ca838e11c6f1..f056b4feee519748ae6ef22fde3df1da532e177b 100644 (file)
--- a/Kbuild
+++ b/Kbuild
@@ -43,7 +43,7 @@ $(obj)/$(bounds-file): kernel/bounds.s Kbuild
 # 2) Generate asm-offsets.h
 #
 
-offsets-file := include/asm-$(SRCARCH)/asm-offsets.h
+offsets-file := include/asm/asm-offsets.h
 
 always  += $(offsets-file)
 targets += $(offsets-file)
@@ -81,7 +81,6 @@ arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c \
        $(call if_changed_dep,cc_s_c)
 
 $(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild
-       $(Q)mkdir -p $(dir $@)
        $(call cmd,offsets)
 
 #####
index 5d8971c76a7f31df8bda0ad2071f5738de610c93..deedc0d827b534af5f9d660f47162449da4bdb4f 100644 (file)
@@ -1043,6 +1043,12 @@ M:       fujita.tomonori@lab.ntt.co.jp
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 
+BT8XXGPIO DRIVER
+P:     Michael Buesch
+M:     mb@bu3sch.de
+W:     http://bu3sch.de/btgpio.php
+S:     Maintained
+
 BTTV VIDEO4LINUX DRIVER
 P:     Mauro Carvalho Chehab
 M:     mchehab@infradead.org
@@ -1984,7 +1990,7 @@ P:        Carlos Corbacho
 M:     carlos@strangeworlds.co.uk
 S:     Odd Fixes
 
-HPET:  High Precision Event Timers driver (hpet.c)
+HPET:  High Precision Event Timers driver (drivers/char/hpet.c)
 P:     Clemens Ladisch
 M:     clemens@ladisch.de
 S:     Maintained
@@ -2937,8 +2943,6 @@ P:        Faisal Latif
 M:     flatif@neteffect.com
 P:     Chien Tung
 M:     ctung@neteffect.com
-P:     Glenn Streiff
-M:     gstreiff@neteffect.com
 L:     general@lists.openfabrics.org
 W:     http://www.neteffect.com
 S:     Supported
@@ -3119,6 +3123,12 @@ W:       http://oss.oracle.com/projects/ocfs2/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git
 S:     Supported
 
+OMFS FILESYSTEM
+P:     Bob Copeland
+M:     me@bobcopeland.com
+L:     linux-karma-devel@lists.sourceforge.net
+S:     Maintained
+
 OMNIKEY CARDMAN 4000 DRIVER
 P:     Harald Welte
 M:     laforge@gnumonks.org
@@ -3786,6 +3796,12 @@ P:       Ben Nizette
 M:     bn@niasdigital.com
 S:     Maintained
 
+SOC-CAMERA V4L2 SUBSYSTEM
+P:     Guennadi Liakhovetski
+M:     g.liakhovetski@gmx.de
+L:     video4linux-list@redhat.com
+S:     Maintained
+
 SOFTWARE RAID (Multiple Disks) SUPPORT
 P:     Ingo Molnar
 M:     mingo@redhat.com
@@ -4080,12 +4096,6 @@ W:       http://www.prosec.rub.de/tpm/
 L:     tpmdd-devel@lists.sourceforge.net
 S:     Maintained
 
-TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
-P:     Muli Ben-Yehuda
-M:     mulix@mulix.org
-L:     linux-kernel@vger.kernel.org
-S:     Maintained
-
 TRIVIAL PATCHES
 P:     Jesper Juhl
 M:     trivial@kernel.org
@@ -4131,9 +4141,6 @@ W:        http://www.uclinux.org/
 L:     uclinux-dev@uclinux.org  (subscribers-only)
 S:     Maintained
 
-UCLINUX FOR NEC V850
-P:     Miles Bader
-
 UCLINUX FOR RENESAS H8/300
 P:     Yoshinori Sato
 M:     ysato@users.sourceforge.jp
index 4bcd1cf90cb103e8578b4692ea7e75470f8cbe77..aa527a46c8070f77582671b71b6e5470c0f87aae 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 26
-EXTRAVERSION =
+SUBLEVEL = 27
+EXTRAVERSION = -rc1
 NAME = Rotary Wombat
 
 # *DOCUMENTATION*
@@ -205,6 +205,13 @@ ifeq ($(ARCH),x86_64)
         SRCARCH := x86
 endif
 
+# Where to locate arch specific headers
+ifeq ($(ARCH),sparc64)
+       hdr-arch  := sparc
+else
+       hdr-arch  := $(SRCARCH)
+endif
+
 KCONFIG_CONFIG ?= .config
 
 # SHELL used by kbuild
@@ -326,7 +333,8 @@ AFLAGS_KERNEL       =
 # Needed to be compatible with the O= option
 LINUXINCLUDE    := -Iinclude \
                    $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
-                  -include include/linux/autoconf.h
+                   -I$(srctree)/arch/$(hdr-arch)/include               \
+                   -include include/linux/autoconf.h
 
 KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
 
@@ -922,7 +930,9 @@ ifneq ($(KBUILD_SRC),)
                /bin/false; \
        fi;
        $(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
-       $(Q)ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm
+       $(Q)if [ -e $(srctree)/include/asm-$(SRCARCH)/system.h ]; then  \
+           ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm;     \
+           fi
 endif
 
 # prepare2 creates a makefile if using a separate output directory
@@ -948,22 +958,34 @@ export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
 
 # The asm symlink changes when $(ARCH) changes.
 # Detect this and ask user to run make mrproper
-
-include/asm: FORCE
-       $(Q)set -e; asmlink=`readlink include/asm | cut -d '-' -f 2`;   \
-       if [ -L include/asm ]; then                                     \
-               if [ "$$asmlink" != "$(SRCARCH)" ]; then                \
+define check-symlink
+       set -e;                                                            \
+       if [ -L include/asm ]; then                                        \
+               asmlink=`readlink include/asm | cut -d '-' -f 2`;          \
+               if [ "$$asmlink" != "$(SRCARCH)" ]; then                   \
                        echo "ERROR: the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) was expected"; \
                        echo "       set ARCH or save .config and run 'make mrproper' to fix it";             \
-                       exit 1;                                         \
-               fi;                                                     \
-       else                                                            \
-               echo '  SYMLINK $@ -> include/asm-$(SRCARCH)';          \
-               if [ ! -d include ]; then                               \
-                       mkdir -p include;                               \
-               fi;                                                     \
-               ln -fsn asm-$(SRCARCH) $@;                              \
+                       exit 1;                                            \
+               fi;                                                        \
        fi
+endef
+
+# We create the target directory of the symlink if it does
+# not exist so the test in chack-symlink works and we have a
+# directory for generated filesas used by some architectures.
+define create-symlink
+       if [ ! -L include/asm ]; then                                      \
+                       echo '  SYMLINK $@ -> include/asm-$(SRCARCH)';     \
+                       if [ ! -d include/asm-$(SRCARCH) ]; then           \
+                               mkdir -p include/asm-$(SRCARCH);           \
+                       fi;                                                \
+                       ln -fsn asm-$(SRCARCH) $@;                         \
+       fi
+endef
+
+include/asm: FORCE
+       $(Q)$(check-symlink)
+       $(Q)$(create-symlink)
 
 # Generate some files
 # ---------------------------------------------------------------------------
@@ -1010,36 +1032,43 @@ firmware_install: FORCE
 
 # ---------------------------------------------------------------------------
 # Kernel headers
-INSTALL_HDR_PATH=$(objtree)/usr
-export INSTALL_HDR_PATH
 
-HDRFILTER=generic i386 x86_64
-HDRARCHES=$(filter-out $(HDRFILTER),$(patsubst $(srctree)/include/asm-%/Kbuild,%,$(wildcard $(srctree)/include/asm-*/Kbuild)))
+#Default location for installed headers
+export INSTALL_HDR_PATH = $(objtree)/usr
 
-PHONY += headers_install_all
-headers_install_all: include/linux/version.h scripts_basic FORCE
+hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
+# Find out where the Kbuild file is located to support
+# arch/$(ARCH)/include/asm
+hdr-dir = $(strip                                                         \
+          $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild), \
+               arch/$(hdr-arch)/include/asm, include/asm-$(hdr-arch)))
+
+# If we do an all arch process set dst to asm-$(hdr-arch)
+hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
+
+PHONY += __headers
+__headers: include/linux/version.h scripts_basic FORCE
        $(Q)$(MAKE) $(build)=scripts scripts/unifdef
-       $(Q)for arch in $(HDRARCHES); do \
-        $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch ;\
-        done
+
+PHONY += headers_install_all
+headers_install_all:
+       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh install
 
 PHONY += headers_install
-headers_install: include/linux/version.h scripts_basic FORCE
-       @if [ ! -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
-         echo '*** Error: Headers not exportable for this architecture ($(SRCARCH))'; \
-         exit 1 ; fi
-       $(Q)$(MAKE) $(build)=scripts scripts/unifdef
-       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include
+headers_install: __headers
+       $(if $(wildcard $(srctree)/$(hdr-dir)/Kbuild),, \
+       $(error Headers not exportable for the $(SRCARCH) architecture))
+       $(Q)$(MAKE) $(hdr-inst)=include
+       $(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst)
 
 PHONY += headers_check_all
 headers_check_all: headers_install_all
-       $(Q)for arch in $(HDRARCHES); do \
-        $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
-        done
+       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh check
 
 PHONY += headers_check
 headers_check: headers_install
-       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst) HDRCHECK=1
 
 # ---------------------------------------------------------------------------
 # Modules
@@ -1061,6 +1090,7 @@ modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
        $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
        @echo '  Building modules, stage 2.';
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
 
 
 # Target to prepare building external modules
@@ -1130,7 +1160,7 @@ MRPROPER_FILES += .config .config.old include/asm .version .old_version \
                   include/linux/autoconf.h include/linux/version.h      \
                   include/linux/utsrelease.h                            \
                   include/linux/bounds.h include/asm*/asm-offsets.h     \
-                 Module.symvers tags TAGS cscope*
+                 Module.symvers Module.markers tags TAGS cscope*
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1149,7 +1179,7 @@ clean: archclean $(clean-dirs)
                \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
                -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
                -o -name '*.symtypes' -o -name 'modules.order' \
-               -o -name 'Module.markers' \) \
+               -o -name 'Module.markers' -o -name '.tmp_*.o.*' \) \
                -type f -print | xargs rm -f
 
 # mrproper - Delete all generated files, including .config
@@ -1223,21 +1253,17 @@ help:
        @echo  '  cscope          - Generate cscope index'
        @echo  '  kernelrelease   - Output the release version string'
        @echo  '  kernelversion   - Output the version stored in Makefile'
-       @if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
-        echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
+       @echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
         echo  '                    (default: $(INSTALL_HDR_PATH))'; \
-        fi
-       @echo  ''
+        echo  ''
        @echo  'Static analysers'
        @echo  '  checkstack      - Generate a list of stack hogs'
        @echo  '  namespacecheck  - Name space analysis on compiled kernel'
        @echo  '  versioncheck    - Sanity check on version.h usage'
        @echo  '  includecheck    - Check for duplicate included header files'
        @echo  '  export_report   - List the usages of all exported symbols'
-       @if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
-        echo  '  headers_check   - Sanity check on exported headers'; \
-        fi
-       @echo  ''
+       @echo  '  headers_check   - Sanity check on exported headers'; \
+        echo  ''
        @echo  'Kernel packaging:'
        @$(MAKE) $(build)=$(package-dir) help
        @echo  ''
@@ -1410,7 +1436,11 @@ define find-sources
               \( -name config -o -name 'asm-*' \) -prune \
               -o -name $1 -print; \
          for arch in $(ALLINCLUDE_ARCHS) ; do \
-              find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
+              test -e $(__srctree)include/asm-$${arch} && \
+                 find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
+                   -name $1 -print; \
+              test -e $(__srctree)arch/$${arch}/include/asm && \
+                find $(__srctree)arch/$${arch}/include/asm $(RCS_FIND_IGNORE) \
                    -name $1 -print; \
          done ; \
          find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
index ad89a33d8c6ef66acb166e49fa423659e18afc9c..364c6dadde0a6b6ed988f15294f799240b292a68 100644 (file)
@@ -27,18 +27,65 @@ config KPROBES
          for kernel debugging, non-intrusive instrumentation and testing.
          If in doubt, say "N".
 
+config HAVE_EFFICIENT_UNALIGNED_ACCESS
+       def_bool n
+       help
+         Some architectures are unable to perform unaligned accesses
+         without the use of get_unaligned/put_unaligned. Others are
+         unable to perform such accesses efficiently (e.g. trap on
+         unaligned access and require fixing it up in the exception
+         handler.)
+
+         This symbol should be selected by an architecture if it can
+         perform unaligned accesses efficiently to allow different
+         code paths to be selected for these cases. Some network
+         drivers, for example, could opt to not fix up alignment
+         problems with received packets if doing so would not help
+         much.
+
+         See Documentation/unaligned-memory-access.txt for more
+         information on the topic of unaligned memory accesses.
+
 config KRETPROBES
        def_bool y
        depends on KPROBES && HAVE_KRETPROBES
 
+config HAVE_IOREMAP_PROT
+       def_bool n
+
 config HAVE_KPROBES
        def_bool n
 
 config HAVE_KRETPROBES
        def_bool n
 
+#
+# An arch should select this if it provides all these things:
+#
+#      task_pt_regs()          in asm/processor.h or asm/ptrace.h
+#      arch_has_single_step()  if there is hardware single-step support
+#      arch_has_block_step()   if there is hardware block-step support
+#      arch_ptrace()           and not #define __ARCH_SYS_PTRACE
+#      compat_arch_ptrace()    and #define __ARCH_WANT_COMPAT_SYS_PTRACE
+#      asm/syscall.h           supplying asm-generic/syscall.h interface
+#      linux/regset.h          user_regset interfaces
+#      CORE_DUMP_USE_REGSET    #define'd in linux/elf.h
+#      TIF_SYSCALL_TRACE       calls tracehook_report_syscall_{entry,exit}
+#      TIF_NOTIFY_RESUME       calls tracehook_notify_resume()
+#      signal delivery         calls tracehook_signal_handler()
+#
+config HAVE_ARCH_TRACEHOOK
+       def_bool n
+
 config HAVE_DMA_ATTRS
        def_bool n
 
 config USE_GENERIC_SMP_HELPERS
        def_bool n
+
+config HAVE_CLK
+       def_bool n
+       help
+         The <linux/clk.h> calls support software clock gating and
+         thus are a key power management tool on many systems.
+
index dbe8c280fea9bba26736a5ad7341dfcc9bcaa62d..1bec55d63ef6241fb9451c821a09960657503acb 100644 (file)
@@ -333,11 +333,6 @@ config PCI_SYSCALL
 config IOMMU_HELPER
        def_bool PCI
 
-config ALPHA_CORE_AGP
-       bool
-       depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL
-       default y
-
 config ALPHA_NONAME
        bool
        depends on ALPHA_BOOK1 || ALPHA_NONAME_CH
index c00646b25f6e961862900c8e13bd69cb31a89823..3047a1b3a517160f4c016c032f30549e3c20ca19 100644 (file)
@@ -78,8 +78,6 @@ static unsigned outcnt;               /* bytes in output buffer */
 static int  fill_inbuf(void);
 static void flush_window(void);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 static char *input_data;
 static int  input_data_size;
@@ -88,51 +86,18 @@ static uch *output_data;
 static ulg output_ptr;
 static ulg bytes_out;
 
-static void *malloc(int size);
-static void free(void *where);
 static void error(char *m);
 static void gzip_mark(void **);
 static void gzip_release(void **);
 
 extern int end;
 static ulg free_mem_ptr;
-static ulg free_mem_ptr_end;
+static ulg free_mem_end_ptr;
 
 #define HEAP_SIZE 0x3000
 
 #include "../../../lib/inflate.c"
 
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size <0) error("Malloc error");
-       if (free_mem_ptr <= 0) error("Memory error");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *)free_mem_ptr;
-       free_mem_ptr += size;
-
-       if (free_mem_ptr >= free_mem_ptr_end)
-               error("Out of memory");
-       return p;
-}
-
-static void free(void *where)
-{ /* gzip_mark & gzip_release do the free */
-}
-
-static void gzip_mark(void **ptr)
-{
-       *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
-       free_mem_ptr = (long) *ptr;
-}
-
 /* ===========================================================================
  * Fill the input buffer. This is called only when the buffer is empty
  * and at least one byte is really needed.
@@ -193,7 +158,7 @@ decompress_kernel(void *output_start,
 
        /* FIXME FIXME FIXME */
        free_mem_ptr            = (ulg)output_start + ksize;
-       free_mem_ptr_end        = (ulg)output_start + ksize + 0x200000;
+       free_mem_end_ptr        = (ulg)output_start + ksize + 0x200000;
        /* FIXME FIXME FIXME */
 
        /* put in temp area to reduce initial footprint */
index 32ca1b9273078d7025466075e677a59e34938b33..6e943135f0e041346e63348a18fb33239113b9c1 100644 (file)
@@ -253,15 +253,15 @@ do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,
 }
 
 asmlinkage int
-osf_statfs(char __user *path, struct osf_statfs __user *buffer, unsigned long bufsiz)
+osf_statfs(char __user *pathname, struct osf_statfs __user *buffer, unsigned long bufsiz)
 {
-       struct nameidata nd;
+       struct path path;
        int retval;
 
-       retval = user_path_walk(path, &nd);
+       retval = user_path(pathname, &path);
        if (!retval) {
-               retval = do_osf_statfs(nd.path.dentry, buffer, bufsiz);
-               path_put(&nd.path);
+               retval = do_osf_statfs(path.dentry, buffer, bufsiz);
+               path_put(&path);
        }
        return retval;
 }
index 40c15e7301ded438baa46d83e67fcac06062efd6..234e42b8ee7436cb61455c3eabe8f3d8f61ea183 100644 (file)
@@ -94,36 +94,6 @@ __bad_page(void)
        return pte_mkdirty(mk_pte(virt_to_page(EMPTY_PGE), PAGE_SHARED));
 }
 
-#ifndef CONFIG_DISCONTIGMEM
-void
-show_mem(void)
-{
-       long i,free = 0,total = 0,reserved = 0;
-       long shared = 0, cached = 0;
-
-       printk("\nMem-info:\n");
-       show_free_areas();
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-       i = max_mapnr;
-       while (i-- > 0) {
-               total++;
-               if (PageReserved(mem_map+i))
-                       reserved++;
-               else if (PageSwapCache(mem_map+i))
-                       cached++;
-               else if (!page_count(mem_map+i))
-                       free++;
-               else
-                       shared += page_count(mem_map + i) - 1;
-       }
-       printk("%ld pages of RAM\n",total);
-       printk("%ld free pages\n",free);
-       printk("%ld reserved pages\n",reserved);
-       printk("%ld pages shared\n",shared);
-       printk("%ld pages swap cached\n",cached);
-}
-#endif
-
 static inline unsigned long
 load_PCB(struct pcb_struct *pcb)
 {
index 10ab7833e83ca660c7292869e501434251e4bdba..a13de49d126579c58f2b4d3131dd861741628d59 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/pgalloc.h>
 
 pg_data_t node_data[MAX_NUMNODES];
-bootmem_data_t node_bdata[MAX_NUMNODES];
 EXPORT_SYMBOL(node_data);
 
 #undef DEBUG_DISCONTIG
@@ -141,7 +140,7 @@ setup_memory_node(int nid, void *kernel_end)
                printk(" not enough mem to reserve NODE_DATA");
                return;
        }
-       NODE_DATA(nid)->bdata = &node_bdata[nid];
+       NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
 
        printk(" Detected node memory:   start %8lu, end %8lu\n",
               node_min_pfn, node_max_pfn);
@@ -304,8 +303,9 @@ void __init paging_init(void)
        dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
        for_each_online_node(nid) {
-               unsigned long start_pfn = node_bdata[nid].node_boot_start >> PAGE_SHIFT;
-               unsigned long end_pfn = node_bdata[nid].node_low_pfn;
+               bootmem_data_t *bdata = &bootmem_node_data[nid];
+               unsigned long start_pfn = bdata->node_min_pfn;
+               unsigned long end_pfn = bdata->node_low_pfn;
 
                if (dma_local_pfn >= end_pfn - start_pfn)
                        zones_size[ZONE_DMA] = end_pfn - start_pfn;
@@ -313,7 +313,7 @@ void __init paging_init(void)
                        zones_size[ZONE_DMA] = dma_local_pfn;
                        zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
                }
-               free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, NULL);
+               free_area_init_node(nid, zones_size, start_pfn, NULL);
        }
 
        /* Initialize the kernel's ZERO_PGE. */
@@ -359,38 +359,3 @@ void __init mem_init(void)
        mem_stress();
 #endif
 }
-
-void
-show_mem(void)
-{
-       long i,free = 0,total = 0,reserved = 0;
-       long shared = 0, cached = 0;
-       int nid;
-
-       printk("\nMem-info:\n");
-       show_free_areas();
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-       for_each_online_node(nid) {
-               unsigned long flags;
-               pgdat_resize_lock(NODE_DATA(nid), &flags);
-               i = node_spanned_pages(nid);
-               while (i-- > 0) {
-                       struct page *page = nid_page_nr(nid, i);
-                       total++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (!page_count(page))
-                               free++;
-                       else
-                               shared += page_count(page) - 1;
-               }
-               pgdat_resize_unlock(NODE_DATA(nid), &flags);
-       }
-       printk("%ld pages of RAM\n",total);
-       printk("%ld free pages\n",free);
-       printk("%ld reserved pages\n",reserved);
-       printk("%ld pages shared\n",shared);
-       printk("%ld pages swap cached\n",cached);
-}
index d048f6887d0b0aff8e882283923c9a3640a6a816..257033c691f2618adf9c6103d9e1e9090b470fcb 100644 (file)
@@ -17,6 +17,7 @@ config ARM
        select HAVE_KRETPROBES if (HAVE_KPROBES)
        select HAVE_FTRACE if (!XIP_KERNEL)
        select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE)
+       select HAVE_GENERIC_DMA_COHERENT
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@ -198,12 +199,14 @@ choice
 config ARCH_AAEC2000
        bool "Agilent AAEC-2000 based"
        select ARM_AMBA
+       select HAVE_CLK
        help
          This enables support for systems based on the Agilent AAEC-2000
 
 config ARCH_INTEGRATOR
        bool "ARM Ltd. Integrator family"
        select ARM_AMBA
+       select HAVE_CLK
        select ICST525
        help
          Support for ARM's Integrator platform.
@@ -211,6 +214,7 @@ config ARCH_INTEGRATOR
 config ARCH_REALVIEW
        bool "ARM Ltd. RealView family"
        select ARM_AMBA
+       select HAVE_CLK
        select ICST307
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
@@ -221,6 +225,7 @@ config ARCH_VERSATILE
        bool "ARM Ltd. Versatile family"
        select ARM_AMBA
        select ARM_VIC
+       select HAVE_CLK
        select ICST307
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
@@ -230,6 +235,7 @@ config ARCH_VERSATILE
 config ARCH_AT91
        bool "Atmel AT91"
        select GENERIC_GPIO
+       select HAVE_CLK
        help
          This enables support for systems based on the Atmel AT91RM9200,
          AT91SAM9 and AT91CAP9 processors.
@@ -262,7 +268,8 @@ config ARCH_EP93XX
        select ARM_AMBA
        select ARM_VIC
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select HAVE_CLK
+       select ARCH_REQUIRE_GPIOLIB
        help
          This enables support for the Cirrus EP93xx series of CPUs.
 
@@ -308,7 +315,7 @@ config ARCH_IOP32X
        select PLAT_IOP
        select PCI
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
        help
          Support for Intel's 80219 and IOP32X (XScale) family of
          processors.
@@ -319,7 +326,7 @@ config ARCH_IOP33X
        select PLAT_IOP
        select PCI
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
        help
          Support for Intel's IOP33X (XScale) family of processors.
 
@@ -381,6 +388,7 @@ config ARCH_NS9XXX
        select GENERIC_GPIO
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
+       select HAVE_CLK
        help
          Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
          System.
@@ -411,7 +419,7 @@ config ARCH_MXC
        select GENERIC_CLOCKEVENTS
        select ARCH_MTD_XIP
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
        help
          Support for Freescale MXC/iMX-based family of processors
 
@@ -430,6 +438,7 @@ config ARCH_ORION5X
 
 config ARCH_PNX4008
        bool "Philips Nexperia PNX4008 Mobile"
+       select HAVE_CLK
        help
          This enables support for Philips PNX4008 mobile platform.
 
@@ -438,7 +447,8 @@ config ARCH_PXA
        depends on MMU
        select ARCH_MTD_XIP
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select HAVE_CLK
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select TICK_ONESHOT
@@ -468,14 +478,16 @@ config ARCH_SA1100
        select GENERIC_GPIO
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
+       select HAVE_CLK
        select TICK_ONESHOT
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
        help
          Support for StrongARM 11x0 based boards.
 
 config ARCH_S3C2410
        bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
        select GENERIC_GPIO
+       select HAVE_CLK
        help
          Samsung S3C2410X CPU based systems, such as the Simtec Electronics
          BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -503,13 +515,15 @@ config ARCH_DAVINCI
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
+       select HAVE_CLK
        help
          Support for TI's DaVinci platform.
 
 config ARCH_OMAP
        bool "TI OMAP"
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select HAVE_CLK
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        help
index b20995a82e046b380210d56956fd8a851ca7356b..2f07477442369ee44b88cbd7fe3a57bcea8ec774 100644 (file)
@@ -67,7 +67,7 @@ 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_ARM946E)     :=$(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
index 9b444022cb9bc76933f1fdba6dffb294723fd7ac..7145cc7c04f0b8e36fb4b86205602fa7e0618bac 100644 (file)
@@ -217,8 +217,6 @@ static unsigned outcnt;             /* bytes in output buffer */
 static int  fill_inbuf(void);
 static void flush_window(void);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 extern char input_data[];
 extern char input_data_end[];
@@ -227,64 +225,21 @@ static uch *output_data;
 static ulg output_ptr;
 static ulg bytes_out;
 
-static void *malloc(int size);
-static void free(void *where);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 static void putstr(const char *);
 
 extern int end;
 static ulg free_mem_ptr;
-static ulg free_mem_ptr_end;
+static ulg free_mem_end_ptr;
 
-#define HEAP_SIZE 0x3000
-
-#include "../../../../lib/inflate.c"
-
-#ifndef STANDALONE_DEBUG
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size <0) error("Malloc error");
-       if (free_mem_ptr <= 0) error("Memory error");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *)free_mem_ptr;
-       free_mem_ptr += size;
-
-       if (free_mem_ptr >= free_mem_ptr_end)
-               error("Out of memory");
-       return p;
-}
-
-static void free(void *where)
-{ /* gzip_mark & gzip_release do the free */
-}
-
-static void gzip_mark(void **ptr)
-{
-       arch_decomp_wdog();
-       *ptr = (void *) free_mem_ptr;
-}
+#ifdef STANDALONE_DEBUG
+#define NO_INFLATE_MALLOC
+#endif
 
-static void gzip_release(void **ptr)
-{
-       arch_decomp_wdog();
-       free_mem_ptr = (long) *ptr;
-}
-#else
-static void gzip_mark(void **ptr)
-{
-}
+#define ARCH_HAS_DECOMP_WDOG
 
-static void gzip_release(void **ptr)
-{
-}
-#endif
+#include "../../../../lib/inflate.c"
 
 /* ===========================================================================
  * Fill the input buffer. This is called only when the buffer is empty
@@ -348,7 +303,7 @@ decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
 {
        output_data             = (uch *)output_start;  /* Points to kernel start */
        free_mem_ptr            = free_mem_ptr_p;
-       free_mem_ptr_end        = free_mem_ptr_end_p;
+       free_mem_end_ptr        = free_mem_ptr_end_p;
        __machine_arch_type     = arch_id;
 
        arch_decomp_setup();
index dd2947342604b2ea43bdfa409dcc32b4b2609cf2..69130f365904bc0889e3f99d75af10834c9a9f8d 100644 (file)
@@ -280,7 +280,7 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
        /*
         * Trying to unmap an invalid mapping
         */
-       if (dma_mapping_error(dma_addr)) {
+       if (dma_mapping_error(dev, dma_addr)) {
                dev_err(dev, "Trying to unmap invalid mapping\n");
                return;
        }
index c3c3a333904995273e5f7af7c68890c8baee361d..85579654d3b778761e912ae22b7eaea14f8b4ca9 100644 (file)
@@ -331,17 +331,17 @@ static int locomo_gpio_type(unsigned int irq, unsigned int type)
 
        mask = 1 << (irq - LOCOMO_IRQ_GPIO_START);
 
-       if (type == IRQT_PROBE) {
+       if (type == IRQ_TYPE_PROBE) {
                if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
                        return 0;
-               type = __IRQT_RISEDGE | __IRQT_FALEDGE;
+               type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
        }
 
-       if (type & __IRQT_RISEDGE)
+       if (type & IRQ_TYPE_EDGE_RISING)
                GPIO_IRQ_rising_edge |= mask;
        else
                GPIO_IRQ_rising_edge &= ~mask;
-       if (type & __IRQT_FALEDGE)
+       if (type & IRQ_TYPE_EDGE_FALLING)
                GPIO_IRQ_falling_edge |= mask;
        else
                GPIO_IRQ_falling_edge &= ~mask;
@@ -473,7 +473,7 @@ static void locomo_setup_irq(struct locomo *lchip)
        /*
         * Install handler for IRQ_LOCOMO_HW.
         */
-       set_irq_type(lchip->irq, IRQT_FALLING);
+       set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
        set_irq_chip_data(lchip->irq, irqbase);
        set_irq_chained_handler(lchip->irq, locomo_handler);
 
index 0a8e1ff2af8a99255b0f419d6b7b82f7fe5721a9..f6d3fdda7067caafff09011a6b587b1e982f6d4a 100644 (file)
@@ -241,14 +241,14 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
        void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ip0;
 
-       if (flags == IRQT_PROBE)
+       if (flags == IRQ_TYPE_PROBE)
                return 0;
 
-       if ((!(flags & __IRQT_RISEDGE) ^ !(flags & __IRQT_FALEDGE)) == 0)
+       if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
                return -EINVAL;
 
        ip0 = sa1111_readl(mapbase + SA1111_INTPOL0);
-       if (flags & __IRQT_RISEDGE)
+       if (flags & IRQ_TYPE_EDGE_RISING)
                ip0 &= ~mask;
        else
                ip0 |= mask;
@@ -338,14 +338,14 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
        void __iomem *mapbase = get_irq_chip_data(irq);
        unsigned long ip1;
 
-       if (flags == IRQT_PROBE)
+       if (flags == IRQ_TYPE_PROBE)
                return 0;
 
-       if ((!(flags & __IRQT_RISEDGE) ^ !(flags & __IRQT_FALEDGE)) == 0)
+       if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
                return -EINVAL;
 
        ip1 = sa1111_readl(mapbase + SA1111_INTPOL1);
-       if (flags & __IRQT_RISEDGE)
+       if (flags & IRQ_TYPE_EDGE_RISING)
                ip1 &= ~mask;
        else
                ip1 |= mask;
@@ -427,7 +427,7 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
        /*
         * Register SA1111 interrupt
         */
-       set_irq_type(sachip->irq, IRQT_RISING);
+       set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
        set_irq_data(sachip->irq, irqbase);
        set_irq_chained_handler(sachip->irq, sa1111_irq_handler);
 }
index 493ecee24f94c5c4c7e268c00fe8c48bb2481341..2307587a38a9ec89ca60251429c62cced8281053 100644 (file)
@@ -1,15 +1,19 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-hh17
-# Fri Nov  9 20:23:03 2007
+# Linux kernel version: 2.6.26
+# Sat Jul 26 22:28:46 2008
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
 # CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -18,75 +22,90 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
 CONFIG_ZONE_DMA=y
 CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
 CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_KALLSYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
+# CONFIG_HAVE_IOREMAP_PROT is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_ARCH_TRACEHOOK is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+CONFIG_HAVE_CLK=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
-
-#
-# Block layer
-#
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -100,6 +119,7 @@ CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
 
 #
 # System Type
@@ -111,21 +131,26 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 # 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_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
-# CONFIG_ARCH_IOP13XX is not set
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
 # CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
 # CONFIG_ARCH_PNX4008 is not set
 CONFIG_ARCH_PXA=y
 # CONFIG_ARCH_RPC is not set
@@ -133,80 +158,48 @@ CONFIG_ARCH_PXA=y
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_BOARD_IRQ_MAP_SMALL is not set
-CONFIG_BOARD_IRQ_MAP_BIG=y
-CONFIG_DMABOUNCE=y
+# CONFIG_ARCH_MSM7X00A is not set
 
 #
-# Intel PXA2xx Implementations
+# Intel PXA2xx/PXA3xx Implementations
 #
+# CONFIG_ARCH_GUMSTIX is not set
 # CONFIG_ARCH_LUBBOCK is not set
 # CONFIG_MACH_LOGICPD_PXA270 is not set
 # CONFIG_MACH_MAINSTONE is not set
 # CONFIG_ARCH_PXA_IDP is not set
-CONFIG_TOSHIBA_TMIO_OHCI=y
-CONFIG_ARCH_ESERIES=y
+# CONFIG_PXA_SHARPSL is not set
+CONFIG_ARCH_PXA_ESERIES=y
 CONFIG_MACH_E330=y
+CONFIG_MACH_E350=y
 CONFIG_MACH_E740=y
 CONFIG_MACH_E750=y
 CONFIG_MACH_E400=y
 CONFIG_MACH_E800=y
-CONFIG_E330_LCD=y
-CONFIG_E740_LCD=y
-CONFIG_E750_LCD=y
-CONFIG_E400_LCD=y
-CONFIG_E800_LCD=y
-CONFIG_ESERIES_UDC=y
-CONFIG_E330_TC6387XB=y
-CONFIG_E740_T7L66XB=y
-CONFIG_E400_T7L66XB=y
-CONFIG_E750_E800_TC6393XB=y
-CONFIG_E740_PCMCIA=m
-CONFIG_E750_PCMCIA=m
-CONFIG_E800_PCMCIA=m
-# CONFIG_MACH_A620 is not set
-# CONFIG_MACH_A716 is not set
-# CONFIG_MACH_A730 is not set
-# CONFIG_ARCH_H1900 is not set
-# CONFIG_ARCH_H2200 is not set
-# CONFIG_MACH_H3900 is not set
-# CONFIG_MACH_H4000 is not set
-# CONFIG_MACH_H4700 is not set
-# CONFIG_MACH_HX2750 is not set
-# CONFIG_ARCH_H5400 is not set
-# CONFIG_MACH_HIMALAYA is not set
-# CONFIG_MACH_HTCUNIVERSAL is not set
-# CONFIG_MACH_HTCALPINE is not set
-# CONFIG_MACH_MAGICIAN is not set
-# CONFIG_MACH_HTCAPACHE is not set
-# CONFIG_MACH_BLUEANGEL is not set
-
-#
-# HTC_HW6X00
-#
-# CONFIG_MACH_HTCBEETLES is not set
-# CONFIG_MACH_HW6900 is not set
-# CONFIG_MACH_HTCATHENA is not set
-# CONFIG_ARCH_AXIMX3 is not set
-# CONFIG_ARCH_AXIMX5 is not set
-# CONFIG_MACH_X50 is not set
-# CONFIG_ARCH_ROVERP1 is not set
-# CONFIG_ARCH_ROVERP5P is not set
-# CONFIG_MACH_XSCALE_PALMLD is not set
-# CONFIG_MACH_T3XSCALE is not set
-# CONFIG_MACH_RECON is not set
-# CONFIG_MACH_GHI270HG is not set
-# CONFIG_MACH_GHI270 is not set
-# CONFIG_MACH_LOOXC550 is not set
-# CONFIG_PXA_SHARPSL is not set
 # CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_ZYLONITE is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_TAVOREVB is not set
+# CONFIG_MACH_SAAR is not set
+# CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_PCM027 is not set
+# CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_PXA_EZX is not set
 CONFIG_PXA25x=y
+# CONFIG_PXA_PWM is not set
+
+#
+# Boot options
+#
 
 #
-# Linux As Bootloader
+# Power management
 #
-# CONFIG_LAB is not set
 
 #
 # Processor Type
@@ -215,6 +208,7 @@ CONFIG_CPU_32=y
 CONFIG_CPU_XSCALE=y
 CONFIG_CPU_32v5=y
 CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_NOIFAR=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
 CONFIG_CPU_CP15=y
@@ -232,11 +226,9 @@ CONFIG_XSCALE_PMU=y
 #
 # Bus support
 #
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-CONFIG_PCCARD=m
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCCARD=y
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
 CONFIG_PCMCIA_LOAD_CIS=y
@@ -245,11 +237,14 @@ CONFIG_PCMCIA_IOCTL=y
 #
 # PC-card bridges
 #
-CONFIG_PCMCIA_PXA2XX=m
 
 #
 # Kernel Features
 #
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 # CONFIG_PREEMPT is not set
 CONFIG_HZ=100
 CONFIG_AEABI=y
@@ -262,9 +257,13 @@ CONFIG_FLATMEM_MANUAL=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -275,7 +274,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE=""
 # CONFIG_XIP_KERNEL is not set
 CONFIG_KEXEC=y
-# CONFIG_TXTOFFSET_DELTA is not set
+CONFIG_ATAGS_PROC=y
 
 #
 # CPU Frequency scaling
@@ -304,11 +303,12 @@ CONFIG_BINFMT_MISC=y
 # Power management options
 #
 CONFIG_PM=y
-CONFIG_PM_LEGACY=y
 # CONFIG_PM_DEBUG is not set
-# CONFIG_DPM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
 # CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 
 #
 # Networking
@@ -318,13 +318,13 @@ CONFIG_NET=y
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -339,35 +339,40 @@ CONFIG_IP_FIB_HASH=y
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE 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
@@ -380,10 +385,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 # CONFIG_NET_SCHED is not set
 
 #
@@ -391,15 +392,74 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
+# CONFIG_CAN is not set
+CONFIG_IRDA=y
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_KINGSUN_DONGLE is not set
+# CONFIG_KSDAZZLE_DONGLE is not set
+# CONFIG_KS959_DONGLE is not set
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_PXA_FICP=y
+# CONFIG_MCS_FIR is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+CONFIG_CFG80211=m
+CONFIG_NL80211=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_MAC80211=m
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
 CONFIG_IEEE80211=m
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
-# CONFIG_IEEE80211_CRYPT_CCMP is not set
-# CONFIG_IEEE80211_CRYPT_TKIP is not set
-# CONFIG_IEEE80211_SOFTMAC is not set
-CONFIG_WIRELESS_EXT=y
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -408,38 +468,32 @@ CONFIG_WIRELESS_EXT=y
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_STANDALONE is not set
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=m
 # 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_AFS_PARTS is not set
+# CONFIG_MTD_PARTITIONS is not set
 
 #
 # User Modules And Translation Layers
 #
-CONFIG_MTD_CHAR=m
-CONFIG_MTD_BLKDEVS=m
-CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_CHAR is not set
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
 # CONFIG_MTD_BLOCK_RO is not set
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -459,7 +513,6 @@ CONFIG_MTD_CFI_I2=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
@@ -482,82 +535,43 @@ CONFIG_MTD_CFI_I2=y
 # 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=m
-CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
 # CONFIG_MTD_NAND_ECC_SMC is not set
-# CONFIG_MTD_NAND_H1900 is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
 CONFIG_MTD_NAND_IDS=m
 # CONFIG_MTD_NAND_DISKONCHIP is not set
 # CONFIG_MTD_NAND_SHARPSL is not set
-# CONFIG_MTD_NAND_NANDSIM is not set
-
-#
-# OneNAND Flash Device Drivers
-#
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
 # CONFIG_MTD_ONENAND is not set
 
 #
-# Parallel port support
+# UBI - Unsorted block images
 #
+# CONFIG_MTD_UBI is not set
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # 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_UB is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=6144
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_RAM 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 is not set
-CONFIG_BLK_DEV_IDEDISK=m
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECS is not set
-# 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 is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_IDE_GENERIC is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
 # CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_SCSI_PROC_FS is not set
@@ -565,7 +579,7 @@ CONFIG_SCSI=m
 #
 # SCSI support type (disk, tape, CD-ROM)
 #
-# CONFIG_BLK_DEV_SD is not set
+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
@@ -579,6 +593,7 @@ CONFIG_SCSI=m
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -586,132 +601,78 @@ CONFIG_SCSI=m
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
 # CONFIG_SCSI_SAS_LIBSAS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_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
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_PMP is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_MV is not set
+CONFIG_PATA_PCMCIA=m
+# CONFIG_PATA_PLATFORM is not set
 # 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_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_VETH is not set
 # CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-
-#
-# Wireless 802.11 Frequency Hopping cards support
+# Wireless LAN
 #
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
 # CONFIG_PCMCIA_RAYCS is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_HERMES is not set
+# CONFIG_LIBERTAS is not set
+CONFIG_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
 # CONFIG_ATMEL is not set
-
-#
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
 # CONFIG_AIRO_CS is not set
 # CONFIG_PCMCIA_WL3501 is not set
 # CONFIG_USB_ZD1201 is not set
-CONFIG_HOSTAP=m
-# CONFIG_HOSTAP_FIRMWARE is not set
-# CONFIG_HOSTAP_CS is not set
-# CONFIG_ACX is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_RT2X00 is not set
 
 #
-# Wan interfaces
+# 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_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
 # 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
 
 #
@@ -719,38 +680,48 @@ CONFIG_NET_WIRELESS=y
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
 #
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
-CONFIG_INPUT_TSDEV=m
-CONFIG_INPUT_TSDEV_SCREEN_X=240
-CONFIG_INPUT_TSDEV_SCREEN_Y=320
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_EVBUG is not set
-# CONFIG_INPUT_LED_TRIGGER is not set
 
 #
 # Input Device Drivers
 #
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# 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_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_GPIO=m
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
 # CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
 # CONFIG_TOUCHSCREEN_MK712 is not set
-CONFIG_TOUCHSCREEN_WM97XX=m
-CONFIG_TOUCHSCREEN_WM9705=y
-CONFIG_TOUCHSCREEN_WM9712=y
-CONFIG_TOUCHSCREEN_WM9713=y
 # CONFIG_TOUCHSCREEN_PENMOUNT is not set
 # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
 # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
 # CONFIG_TOUCHSCREEN_UCB1400 is not set
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+# CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -763,9 +734,11 @@ CONFIG_TOUCHSCREEN_WM9713=y
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -777,25 +750,12 @@ CONFIG_HW_CONSOLE=y
 # Non-8250 serial port support
 #
 # CONFIG_SERIAL_PXA is not set
-# CONFIG_RS232_SERIAL is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=m
 # CONFIG_NVRAM is not set
-# CONFIG_SA1100_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-# CONFIG_TIHTC is not set
 
 #
 # PCMCIA character devices
@@ -803,117 +763,79 @@ CONFIG_HW_RANDOM=m
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_CARDMAN_4000 is not set
 # CONFIG_CARDMAN_4040 is not set
+# CONFIG_IPWIRELESS is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
-
-#
-# SPI support
-#
 # CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
 
 #
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-# CONFIG_POWER_SUPPLY is not set
-
-#
-# L3 serial bus support
-#
-# CONFIG_L3 is not set
-
-#
-# Misc devices
+# I2C GPIO expanders:
 #
 
 #
-# Multimedia Capabilities Port drivers
+# PCI GPIO expanders:
 #
-# CONFIG_ADC is not set
 
 #
-# Compaq/iPAQ Drivers
+# SPI GPIO expanders:
 #
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_WATCHDOG is not set
 
 #
-# Compaq/HP iPAQ Drivers
+# Sonics Silicon Backplane
 #
-# CONFIG_IPAQ_SLEEVE is not set
-# CONFIG_SLEEVE_DEBUG is not set
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+CONFIG_MFD_CORE=y
 # CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_ASIC2 is not set
-# CONFIG_HTC_ASIC3 is not set
-# CONFIG_HTC_PASIC3 is not set
 # CONFIG_HTC_EGPIO is not set
-# CONFIG_HTC_BBKEYS is not set
-# CONFIG_HTC_ASIC3_DS1WM is not set
-# CONFIG_SOC_SAMCOP is not set
-# CONFIG_SOC_HAMCOP is not set
-# CONFIG_SOC_MQ11XX is not set
-CONFIG_SOC_T7L66XB=y
-# CONFIG_SOC_TC6387XB is not set
-CONFIG_SOC_TC6393XB=y
-# CONFIG_SOC_TSC2101 is not set
-# CONFIG_SOC_TSC2200 is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
+# CONFIG_HTC_PASIC3 is not set
+CONFIG_MFD_TC6393XB=y
 
 #
-# LED Triggers
+# Multimedia devices
 #
-# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
 
 #
-# Multimedia devices
+# Multimedia core support
 #
 # CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
 
 #
-# Digital Video Broadcasting Devices
+# Multimedia drivers
 #
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CORGI=y
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -923,14 +845,25 @@ CONFIG_FB_CFB_IMAGEBLIT=y
 #
 # Frame buffer hardware drivers
 #
-# CONFIG_FB_IMAGEON is not set
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_SMARTPANEL is not set
 # CONFIG_FB_PXA_PARAMETERS is not set
 # CONFIG_FB_MBX is not set
 CONFIG_FB_W100=y
+# CONFIG_FB_AM200EPD is not set
 # CONFIG_FB_VIRTUAL is not set
-# CONFIG_FB_VSFB is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
 # Console display driver support
@@ -938,6 +871,7 @@ CONFIG_FB_W100=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
 # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 CONFIG_FONTS=y
 # CONFIG_FONT_8x8 is not set
@@ -945,28 +879,13 @@ CONFIG_FONTS=y
 # CONFIG_FONT_6x11 is not set
 # CONFIG_FONT_7x14 is not set
 # CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
-# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
 # CONFIG_FONT_SUN8x16 is not set
 # CONFIG_FONT_SUN12x22 is not set
 # CONFIG_FONT_10x18 is not set
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
+# CONFIG_LOGO is not set
 CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
@@ -980,125 +899,75 @@ CONFIG_SND_SUPPORT_OLD_API=y
 CONFIG_SND_VERBOSE_PROCFS=y
 CONFIG_SND_VERBOSE_PRINTK=y
 # CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
-
-#
-# ALSA ARM devices
-#
+CONFIG_SND_ARM=y
 # CONFIG_SND_PXA2XX_AC97 is not set
-# CONFIG_SND_RECON is not set
-
-#
-# USB devices
-#
-# CONFIG_SND_USB_AUDIO is not set
-
-#
-# PCMCIA devices
-#
-# CONFIG_SND_VXPOCKET is not set
-# CONFIG_SND_PDAUDIOCF is not set
-
-#
-# SoC audio support
-#
-CONFIG_SND_SOC_AC97_BUS=y
+# CONFIG_SND_USB is not set
+# CONFIG_SND_PCMCIA is not set
 CONFIG_SND_SOC=m
-
-#
-# SoC Platforms
-#
-
-#
-# SoC Audio for the Atmel AT91
-#
-
-#
-# SoC Audio for the Intel PXA2xx
-#
+CONFIG_SND_SOC_AC97_BUS=y
 CONFIG_SND_PXA2XX_SOC=m
 CONFIG_SND_PXA2XX_SOC_AC97=m
-CONFIG_SND_PXA2XX_SOC_E740_WM9705=m
-CONFIG_SND_PXA2XX_SOC_E750_WM9705=m
-CONFIG_SND_PXA2XX_SOC_E800_WM9712=m
-# CONFIG_SND_PXA2XX_SOC_MAGICIAN is not set
-# CONFIG_SND_PXA2XX_SOC_BLUEANGEL is not set
-# CONFIG_SND_PXA2XX_SOC_H5000 is not set
-
-#
-# SoC Audio for the Freescale i.MX
-#
-
-#
-# SoC Audio for the Samsung S3C24XX
-#
-# CONFIG_SND_SOC_AC97_CODEC is not set
-# CONFIG_SND_SOC_WM8711 is not set
-# CONFIG_SND_SOC_WM8510 is not set
-# CONFIG_SND_SOC_WM8731 is not set
-# CONFIG_SND_SOC_WM8750 is not set
-# CONFIG_SND_SOC_WM8753 is not set
-# CONFIG_SND_SOC_WM8772 is not set
-# CONFIG_SND_SOC_WM8971 is not set
-# CONFIG_SND_SOC_WM8956 is not set
-# CONFIG_SND_SOC_WM8960 is not set
-# CONFIG_SND_SOC_WM8976 is not set
-# CONFIG_SND_SOC_WM8974 is not set
-# CONFIG_SND_SOC_WM8980 is not set
-CONFIG_SND_SOC_WM9705=m
-# CONFIG_SND_SOC_WM9713 is not set
+CONFIG_SND_PXA2XX_SOC_E800=m
 CONFIG_SND_SOC_WM9712=m
-# CONFIG_SND_SOC_UDA1380 is not set
-# CONFIG_SND_SOC_AK4535 is not set
-
-#
-# Open Sound System
-#
 # CONFIG_SOUND_PRIME is not set
 CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
 
 #
-# HID Devices
+# USB Input Devices
 #
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
 
 #
-# USB support
+# USB HID Boot Protocol drivers
 #
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
 # CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=m
-CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
 
 #
 # Miscellaneous USB options
 #
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -1107,68 +976,19 @@ CONFIG_USB_DYNAMIC_MINORS=y
 #
 # 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_ISD200 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_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE 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
-# CONFIG_USB_GTCO 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_MII is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_MON is not set
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
 #
-
-#
-# USB Serial Converter support
-#
 # CONFIG_USB_SERIAL is not set
 
 #
@@ -1192,56 +1012,57 @@ CONFIG_USB_STORAGE=m
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+# CONFIG_USB_ISIGHTFW is not set
 CONFIG_USB_GADGET=y
 # CONFIG_USB_GADGET_DEBUG_FILES is not set
 CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
 # CONFIG_USB_GADGET_NET2280 is not set
-CONFIG_USB_GADGET_PXA2XX=y
-CONFIG_USB_PXA2XX=y
-# CONFIG_USB_PXA2XX_SMALL is not set
+CONFIG_USB_GADGET_PXA25X=y
+CONFIG_USB_PXA25X=y
+CONFIG_USB_PXA25X_SMALL=y
+# CONFIG_USB_GADGET_M66592 is not set
 # CONFIG_USB_GADGET_PXA27X is not set
 # CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_MQ11XX is not set
 # CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_AT91 is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 # CONFIG_USB_GADGET_DUALSPEED is not set
 # CONFIG_USB_ZERO is not set
-CONFIG_USB_ETH=y
+CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 # CONFIG_USB_GADGETFS is not set
 # CONFIG_USB_FILE_STORAGE is not set
 # CONFIG_USB_G_SERIAL is not set
 # CONFIG_USB_MIDI_GADGET is not set
-# CONFIG_USB_G_CHAR is not set
-# CONFIG_USB_PXA2XX_GPIO is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
 
 #
-# MMC/SD Card support
+# MMC/SD Card Drivers
 #
-CONFIG_MMC=y
-# CONFIG_MMC_DEBUG is not set
 CONFIG_MMC_BLOCK=y
-# CONFIG_MMC_PXA is not set
-CONFIG_MMC_TMIO=y
-# CONFIG_MMC_SAMCOP is not set
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
 
 #
-# Real Time Clock
+# MMC/SD Host Controller Drivers
 #
+# CONFIG_MMC_PXA is not set
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_NEW_LEDS is not set
 CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
 
 #
 # File systems
@@ -1255,14 +1076,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+CONFIG_DNOTIFY=y
 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
@@ -1292,7 +1110,6 @@ CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1305,30 +1122,21 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_JFFS2_FS=m
-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_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
 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_LOCKD=y
 CONFIG_LOCKD_V4=y
@@ -1341,7 +1149,6 @@ CONFIG_SUNRPC=y
 # 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
@@ -1363,10 +1170,7 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
+# CONFIG_SYSV68_PARTITION is not set
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=y
@@ -1407,30 +1211,32 @@ CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
 
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_DEBUG_USER is not set
 
 #
@@ -1438,61 +1244,102 @@ CONFIG_FRAME_POINTER=y
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
 
 #
-# Cryptographic options
+# Crypto core or helper
 #
-CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=m
 CONFIG_CRYPTO_BLKCIPHER=m
 CONFIG_CRYPTO_MANAGER=m
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_MD4 is not set
 # CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 # CONFIG_CRYPTO_SHA1 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
 # 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_CAMELLIA is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
 
 #
-# Hardware crypto devices
+# Compression
 #
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 5ee39e10c8d18a37eb8004e91b0e5c046bd2eff7..d28513f14d05906cec08a849128f76edaaf5ad16 100644 (file)
@@ -296,8 +296,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
        unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
 
        INIT_HLIST_HEAD(&empty_rp);
-       spin_lock_irqsave(&kretprobe_lock, flags);
-       head = kretprobe_inst_table_head(current);
+       kretprobe_hash_lock(current, &head, &flags);
 
        /*
         * It is possible to have multiple instances associated with a given
@@ -337,7 +336,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
        }
 
        kretprobe_assert(ri, orig_ret_address, trampoline_address);
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
+       kretprobe_hash_unlock(current, &flags);
 
        hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
                hlist_del(&ri->hlist);
@@ -347,7 +346,6 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
        return (void *)orig_ret_address;
 }
 
-/* Called with kretprobe_lock held. */
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                      struct pt_regs *regs)
 {
index 79b7e5cf5416cff90059fd145ca6a2c76d253011..a68259a0cccdb54ac3dd06cb3e5248b9b0904cd8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/moduleloader.h>
 #include <linux/kernel.h>
+#include <linux/mm.h>
 #include <linux/elf.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
index 199b3680118bc4c5f09c4ee300a41627830d587a..89bfded70a1f480ced698568a9d5fd685c48a17b 100644 (file)
@@ -162,7 +162,7 @@ void cpu_idle(void)
                if (!idle)
                        idle = default_idle;
                leds_event(led_idle_start);
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        idle();
                leds_event(led_idle_end);
index 747b9dedab88a8e51d75be21b5c9799f34e38b53..dc8b40783d94243565a1e7963941f35fdf267c13 100644 (file)
@@ -377,7 +377,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
  * -------------------------------------------------------------------- */
 
 #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;
 
 #define NAND_BASE      AT91_CHIPSELECT_3
 
@@ -395,7 +395,7 @@ static struct resource nand_resources[] = {
 };
 
 static struct platform_device at91cap9_nand_device = {
-       .name           = "at91_nand",
+       .name           = "atmel_nand",
        .id             = -1,
        .dev            = {
                                .platform_data  = &nand_data,
@@ -404,7 +404,7 @@ static struct platform_device at91cap9_nand_device = {
        .num_resources  = ARRAY_SIZE(nand_resources),
 };
 
-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
 {
        unsigned long csa, mode;
 
@@ -445,7 +445,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
        platform_device_register(&at91cap9_nand_device);
 }
 #else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
 #endif
 
 
index de19bee83f758c55c4b092428b31cfdc573048ce..8ced9bc82099911445a0d459169a185455554e09 100644 (file)
@@ -369,7 +369,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
  * -------------------------------------------------------------------- */
 
 #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;
 
 #define NAND_BASE      AT91_CHIPSELECT_3
 
@@ -382,7 +382,7 @@ static struct resource nand_resources[] = {
 };
 
 static struct platform_device at91rm9200_nand_device = {
-       .name           = "at91_nand",
+       .name           = "atmel_nand",
        .id             = -1,
        .dev            = {
                                .platform_data  = &nand_data,
@@ -391,7 +391,7 @@ static struct platform_device at91rm9200_nand_device = {
        .num_resources  = ARRAY_SIZE(nand_resources),
 };
 
-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
 {
        unsigned int csa;
 
@@ -429,7 +429,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
        platform_device_register(&at91rm9200_nand_device);
 }
 #else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
 #endif
 
 
index 86cba4ac29b1672ffba1cf182b8d08af923a2744..cae5f52f1278e1311baa90e5fe4da69880a02c8c 100644 (file)
@@ -284,7 +284,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
  * -------------------------------------------------------------------- */
 
 #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;
 
 #define NAND_BASE      AT91_CHIPSELECT_3
 
@@ -302,7 +302,7 @@ static struct resource nand_resources[] = {
 };
 
 static struct platform_device at91sam9260_nand_device = {
-       .name           = "at91_nand",
+       .name           = "atmel_nand",
        .id             = -1,
        .dev            = {
                                .platform_data  = &nand_data,
@@ -311,7 +311,7 @@ static struct platform_device at91sam9260_nand_device = {
        .num_resources  = ARRAY_SIZE(nand_resources),
 };
 
-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
 {
        unsigned long csa, mode;
 
@@ -373,7 +373,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
        platform_device_register(&at91sam9260_nand_device);
 }
 #else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
 #endif
 
 
index ec1891375dfbefb9a9090a9ee17e6212c10a3128..483d436af22d84610b84b9a916748b222c35c263 100644 (file)
@@ -199,7 +199,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
  * -------------------------------------------------------------------- */
 
 #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;
 
 #define NAND_BASE      AT91_CHIPSELECT_3
 
@@ -211,8 +211,8 @@ static struct resource nand_resources[] = {
        }
 };
 
-static struct platform_device at91_nand_device = {
-       .name           = "at91_nand",
+static struct platform_device atmel_nand_device = {
+       .name           = "atmel_nand",
        .id             = -1,
        .dev            = {
                                .platform_data  = &nand_data,
@@ -221,7 +221,7 @@ static struct platform_device at91_nand_device = {
        .num_resources  = ARRAY_SIZE(nand_resources),
 };
 
-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
 {
        unsigned long csa, mode;
 
@@ -262,11 +262,11 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
        at91_set_A_periph(AT91_PIN_PC1, 0);             /* NANDWE */
 
        nand_data = *data;
-       platform_device_register(&at91_nand_device);
+       platform_device_register(&atmel_nand_device);
 }
 
 #else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
 #endif
 
 
index 8a81f76f02000e270641f2f77a2853000e92221f..9762b15f658ac0238bed885ab511e43c8aed83d7 100644 (file)
@@ -353,7 +353,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
  * -------------------------------------------------------------------- */
 
 #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;
 
 #define NAND_BASE      AT91_CHIPSELECT_3
 
@@ -371,7 +371,7 @@ static struct resource nand_resources[] = {
 };
 
 static struct platform_device at91sam9263_nand_device = {
-       .name           = "at91_nand",
+       .name           = "atmel_nand",
        .id             = -1,
        .dev            = {
                                .platform_data  = &nand_data,
@@ -380,7 +380,7 @@ static struct platform_device at91sam9263_nand_device = {
        .num_resources  = ARRAY_SIZE(nand_resources),
 };
 
-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
 {
        unsigned long csa, mode;
 
@@ -421,7 +421,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
        platform_device_register(&at91sam9263_nand_device);
 }
 #else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
 #endif
 
 
index ae28101e75422a5376ff03037a8e6e987adf365c..5f3094870cadcbaa5e92579cbd451b3e9ab89943 100644 (file)
@@ -195,7 +195,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
  * -------------------------------------------------------------------- */
 
 #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
-static struct at91_nand_data nand_data;
+static struct atmel_nand_data nand_data;
 
 #define NAND_BASE      AT91_CHIPSELECT_3
 
@@ -212,8 +212,8 @@ static struct resource nand_resources[] = {
        }
 };
 
-static struct platform_device at91_nand_device = {
-       .name           = "at91_nand",
+static struct platform_device atmel_nand_device = {
+       .name           = "atmel_nand",
        .id             = -1,
        .dev            = {
                                .platform_data  = &nand_data,
@@ -222,7 +222,7 @@ static struct platform_device at91_nand_device = {
        .num_resources  = ARRAY_SIZE(nand_resources),
 };
 
-void __init at91_add_device_nand(struct at91_nand_data *data)
+void __init at91_add_device_nand(struct atmel_nand_data *data)
 {
        unsigned long csa;
 
@@ -259,11 +259,11 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
        at91_set_A_periph(AT91_PIN_PB5, 0);             /* NANDWE */
 
        nand_data = *data;
-       platform_device_register(&at91_nand_device);
+       platform_device_register(&atmel_nand_device);
 }
 
 #else
-void __init at91_add_device_nand(struct at91_nand_data *data) {}
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
 #endif
 
 
index b22a1a00405547cf7be13f22371dd510a5677f33..af2c33aff1a8c9aafa194429248f74bf028eab07 100644 (file)
@@ -142,7 +142,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return cam60_nand_partition;
 }
 
-static struct at91_nand_data __initdata cam60_nand_data = {
+static struct atmel_nand_data __initdata cam60_nand_data = {
        .ale            = 21,
        .cle            = 22,
        // .det_pin     = ... not there
index 8a2a958639db5e9256188ae9de763b73de9f40af..117cf6c9afce3534b8c904bb4915974728456dbb 100644 (file)
@@ -181,7 +181,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return cap9adk_nand_partitions;
 }
 
-static struct at91_nand_data __initdata cap9adk_nand_data = {
+static struct atmel_nand_data __initdata cap9adk_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
@@ -330,10 +330,10 @@ static void __init cap9adk_board_init(void)
        /* Serial */
        at91_add_device_serial();
        /* USB Host */
-       set_irq_type(AT91CAP9_ID_UHP, IRQT_HIGH);
+       set_irq_type(AT91CAP9_ID_UHP, IRQ_TYPE_LEVEL_HIGH);
        at91_add_device_usbh(&cap9adk_usbh_data);
        /* USB HS */
-       set_irq_type(AT91CAP9_ID_UDPHS, IRQT_HIGH);
+       set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH);
        at91_add_device_usba(&cap9adk_usba_udc_data);
        /* SPI */
        at91_add_device_spi(cap9adk_spi_devices, ARRAY_SIZE(cap9adk_spi_devices));
@@ -350,7 +350,7 @@ static void __init cap9adk_board_init(void)
        /* I2C */
        at91_add_device_i2c(NULL, 0);
        /* LCD Controller */
-       set_irq_type(AT91CAP9_ID_LCDC, IRQT_HIGH);
+       set_irq_type(AT91CAP9_ID_LCDC, IRQ_TYPE_LEVEL_HIGH);
        at91_add_device_lcdc(&cap9adk_lcdc_data);
        /* AC97 */
        at91_add_device_ac97(&cap9adk_ac97_data);
index dab958d2592658d7e9b0bb242bb628b3bfd0102c..02a70b2f355bd07e3551e82fa60d96be266cde8b 100644 (file)
@@ -147,7 +147,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return dk_nand_partition;
 }
 
-static struct at91_nand_data __initdata dk_nand_data = {
+static struct atmel_nand_data __initdata dk_nand_data = {
        .ale            = 22,
        .cle            = 21,
        .det_pin        = AT91_PIN_PB1,
index cb065febd95e6e35bf9145accdf72b4946ec9284..082ed59365a4a4f90a13e6ab19897cad6df30f9f 100644 (file)
@@ -105,7 +105,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return kb9202_nand_partition;
 }
 
-static struct at91_nand_data __initdata kb9202_nand_data = {
+static struct atmel_nand_data __initdata kb9202_nand_data = {
        .ale            = 22,
        .cle            = 21,
        // .det_pin     = ... not there
index 8f76af5e219aea79278bff8085243966a7b53b3e..57a6221943ed3b82f57e69d6db53994aaf7fc9f7 100644 (file)
@@ -141,7 +141,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return ek_nand_partition;
 }
 
-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
index 4d1d9c777084dfb3f695bebcffc1b1ab8b11d2ae..6a680795c3c83d80cea369cd85d4fee0269201d4 100644 (file)
@@ -178,7 +178,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return ek_nand_partition;
 }
 
-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
index 08382c0df2211401c1ccb04887a45a938901f4de..43dfbd0d543a07c7aeb7689354e3ea506bff60b1 100644 (file)
@@ -183,7 +183,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return ek_nand_partition;
 }
 
-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 22,
        .cle            = 21,
 //     .det_pin        = ... not connected
index b4cd5d0ed597ed57bbd90460b1e8b8b7797f3d2f..6605a098011761bb32cc85b58077cfac6f866cbb 100644 (file)
@@ -187,7 +187,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return ek_nand_partition;
 }
 
-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
index b6a70fc735c38b602d47556e1d9d41ea0ce5140c..66e77bb2e079c4ad9592ed1d6dc347159fa079e8 100644 (file)
@@ -96,7 +96,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return ek_nand_partition;
 }
 
-static struct at91_nand_data __initdata ek_nand_data = {
+static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
old mode 100755 (executable)
new mode 100644 (file)
index 7079050..bbbfd06
@@ -180,7 +180,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio
        return yl9200_nand_partition;
 }
 
-static struct at91_nand_data __initdata yl9200_nand_data = {
+static struct atmel_nand_data __initdata yl9200_nand_data = {
        .ale            = 6,
        .cle            = 7,
        // .det_pin     = ... not connected
index 78a5cdb746dc851170a7a583e1d6016575939be6..ca87587b2b4b0f28ef70ecfade042f30b4e26fde 100644 (file)
@@ -56,19 +56,19 @@ static int at91_aic_set_type(unsigned irq, unsigned type)
        unsigned int smr, srctype;
 
        switch (type) {
-       case IRQT_HIGH:
+       case IRQ_TYPE_LEVEL_HIGH:
                srctype = AT91_AIC_SRCTYPE_HIGH;
                break;
-       case IRQT_RISING:
+       case IRQ_TYPE_EDGE_RISING:
                srctype = AT91_AIC_SRCTYPE_RISING;
                break;
-       case IRQT_LOW:
+       case IRQ_TYPE_LEVEL_LOW:
                if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))         /* only supported on external interrupts */
                        srctype = AT91_AIC_SRCTYPE_LOW;
                else
                        return -EINVAL;
                break;
-       case IRQT_FALLING:
+       case IRQ_TYPE_EDGE_FALLING:
                if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))         /* only supported on external interrupts */
                        srctype = AT91_AIC_SRCTYPE_FALLING;
                else
index 1d7bca6aa441e3a092a87933a3d87e9c9a2f245f..5fed57608507f8647c8aad81675906e284d2adad 100644 (file)
@@ -226,7 +226,7 @@ static void ep93xx_gpio_irq_ack(unsigned int irq)
        int port = line >> 3;
        int port_mask = 1 << (line & 7);
 
-       if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
+       if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
                gpio_int_type2[port] ^= port_mask; /* switch edge direction */
                ep93xx_gpio_update_int_params(port);
        }
@@ -240,7 +240,7 @@ static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
        int port = line >> 3;
        int port_mask = 1 << (line & 7);
 
-       if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE)
+       if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
                gpio_int_type2[port] ^= port_mask; /* switch edge direction */
 
        gpio_int_unmasked[port] &= ~port_mask;
@@ -283,27 +283,27 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
        gpio_direction_input(gpio);
 
        switch (type) {
-       case IRQT_RISING:
+       case IRQ_TYPE_EDGE_RISING:
                gpio_int_type1[port] |= port_mask;
                gpio_int_type2[port] |= port_mask;
                desc->handle_irq = handle_edge_irq;
                break;
-       case IRQT_FALLING:
+       case IRQ_TYPE_EDGE_FALLING:
                gpio_int_type1[port] |= port_mask;
                gpio_int_type2[port] &= ~port_mask;
                desc->handle_irq = handle_edge_irq;
                break;
-       case IRQT_HIGH:
+       case IRQ_TYPE_LEVEL_HIGH:
                gpio_int_type1[port] &= ~port_mask;
                gpio_int_type2[port] |= port_mask;
                desc->handle_irq = handle_level_irq;
                break;
-       case IRQT_LOW:
+       case IRQ_TYPE_LEVEL_LOW:
                gpio_int_type1[port] &= ~port_mask;
                gpio_int_type2[port] &= ~port_mask;
                desc->handle_irq = handle_level_irq;
                break;
-       case IRQT_BOTHEDGE:
+       case IRQ_TYPE_EDGE_BOTH:
                gpio_int_type1[port] |= port_mask;
                /* set initial polarity based on current input level */
                if (gpio_get_value(gpio))
index e6695c4e623b80facd70a60feb7244466a09cedc..e1b1f028b93061e1b34acf64ae580149fc16b991 100644 (file)
@@ -111,7 +111,7 @@ imx_gpio_irq_type(unsigned int _irq, unsigned int type)
        reg = irq >> 5;
        bit = 1 << (irq % 32);
 
-       if (type == IRQT_PROBE) {
+       if (type == IRQ_TYPE_PROBE) {
                /* Don't mess with enabled GPIOs using preconfigured edges or
                   GPIOs set to alternate function during probe */
                /* TODO: support probe */
@@ -120,7 +120,7 @@ imx_gpio_irq_type(unsigned int _irq, unsigned int type)
 //                      return 0;
 //              if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
 //                      return 0;
-//              type = __IRQT_RISEDGE | __IRQT_FALEDGE;
+//              type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
        }
 
        GIUS(reg) |= bit;
@@ -128,19 +128,19 @@ imx_gpio_irq_type(unsigned int _irq, unsigned int type)
 
        DEBUG_IRQ("setting type of irq %d to ", _irq);
 
-       if (type & __IRQT_RISEDGE) {
+       if (type & IRQ_TYPE_EDGE_RISING) {
                DEBUG_IRQ("rising edges\n");
                irq_type = 0x0;
        }
-       if (type & __IRQT_FALEDGE) {
+       if (type & IRQ_TYPE_EDGE_FALLING) {
                DEBUG_IRQ("falling edges\n");
                irq_type = 0x1;
        }
-       if (type & __IRQT_LOWLVL) {
+       if (type & IRQ_TYPE_LEVEL_LOW) {
                DEBUG_IRQ("low level\n");
                irq_type = 0x3;
        }
-       if (type & __IRQT_HIGHLVL) {
+       if (type & IRQ_TYPE_LEVEL_HIGH) {
                DEBUG_IRQ("high level\n");
                irq_type = 0x2;
        }
index 2741063bf361e34abca66f96f648c1f6a7843ea8..28f164ea47268d77ce0401e2969ad506942bd8b1 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/f75375s.h>
+#include <linux/leds-pca9532.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -206,6 +207,53 @@ static struct f75375s_platform_data n2100_f75375s = {
        .pwm_enable = { 0, 0 },
 };
 
+static struct pca9532_platform_data n2100_leds = {
+       .leds = {
+       {       .name = "n2100:red:satafail0",
+               .state = PCA9532_OFF,
+               .type = PCA9532_TYPE_LED,
+       },
+       {       .name = "n2100:red:satafail1",
+               .state = PCA9532_OFF,
+               .type = PCA9532_TYPE_LED,
+       },
+       {       .name = "n2100:blue:usb",
+               .state = PCA9532_OFF,
+               .type = PCA9532_TYPE_LED,
+       },
+       {       .type = PCA9532_TYPE_NONE },
+
+       {       .type = PCA9532_TYPE_NONE },
+       {       .type = PCA9532_TYPE_NONE },
+       {       .type = PCA9532_TYPE_NONE },
+       {       .name = "n2100:red:usb",
+               .state = PCA9532_OFF,
+               .type = PCA9532_TYPE_LED,
+       },
+
+       {       .type = PCA9532_TYPE_NONE }, /* power OFF gpio */
+       {       .type = PCA9532_TYPE_NONE }, /* reset gpio */
+       {       .type = PCA9532_TYPE_NONE },
+       {       .type = PCA9532_TYPE_NONE },
+
+       {       .type = PCA9532_TYPE_NONE },
+       {       .name = "n2100:orange:system",
+               .state = PCA9532_OFF,
+               .type = PCA9532_TYPE_LED,
+       },
+       {       .name = "n2100:red:system",
+               .state = PCA9532_OFF,
+               .type = PCA9532_TYPE_LED,
+       },
+       {       .name = "N2100 beeper"  ,
+               .state =  PCA9532_OFF,
+               .type = PCA9532_TYPE_N2100_BEEP,
+       },
+       },
+       .psc = { 0, 0 },
+       .pwm = { 0, 0 },
+};
+
 static struct i2c_board_info __initdata n2100_i2c_devices[] = {
        {
                I2C_BOARD_INFO("rs5c372b", 0x32),
@@ -214,6 +262,10 @@ static struct i2c_board_info __initdata n2100_i2c_devices[] = {
                I2C_BOARD_INFO("f75375", 0x2e),
                .platform_data = &n2100_f75375s,
        },
+       {
+               I2C_BOARD_INFO("pca9532", 0x60),
+               .platform_data = &n2100_leds,
+       },
 };
 
 /*
index 81cdc826720663722f574605d58cc9b99833cbd5..daf28074134b1391f716392f4effdd7934299559 100644 (file)
@@ -329,19 +329,19 @@ static int ixp2000_GPIO_irq_type(unsigned int irq, unsigned int type)
        /*
         * Then, set the proper trigger type.
         */
-       if (type & IRQT_FALLING)
+       if (type & IRQ_TYPE_EDGE_FALLING)
                GPIO_IRQ_falling_edge |= 1 << line;
        else
                GPIO_IRQ_falling_edge &= ~(1 << line);
-       if (type & IRQT_RISING)
+       if (type & IRQ_TYPE_EDGE_RISING)
                GPIO_IRQ_rising_edge |= 1 << line;
        else
                GPIO_IRQ_rising_edge &= ~(1 << line);
-       if (type & IRQT_LOW)
+       if (type & IRQ_TYPE_LEVEL_LOW)
                GPIO_IRQ_level_low |= 1 << line;
        else
                GPIO_IRQ_level_low &= ~(1 << line);
-       if (type & IRQT_HIGH)
+       if (type & IRQ_TYPE_LEVEL_HIGH)
                GPIO_IRQ_level_high |= 1 << line;
        else
                GPIO_IRQ_level_high &= ~(1 << line);
index 5fea5a132939abc1c608bec1a04940b7ae7612d6..df16a4eac4907ecb03862fbbe636750724da350a 100644 (file)
@@ -126,23 +126,23 @@ static int ixp23xx_irq_set_type(unsigned int irq, unsigned int type)
                return -EINVAL;
 
        switch (type) {
-       case IRQT_BOTHEDGE:
+       case IRQ_TYPE_EDGE_BOTH:
                int_style = IXP23XX_GPIO_STYLE_TRANSITIONAL;
                irq_type = IXP23XX_IRQ_EDGE;
                break;
-       case IRQT_RISING:
+       case IRQ_TYPE_EDGE_RISING:
                int_style = IXP23XX_GPIO_STYLE_RISING_EDGE;
                irq_type = IXP23XX_IRQ_EDGE;
                break;
-       case IRQT_FALLING:
+       case IRQ_TYPE_EDGE_FALLING:
                int_style = IXP23XX_GPIO_STYLE_FALLING_EDGE;
                irq_type = IXP23XX_IRQ_EDGE;
                break;
-       case IRQT_HIGH:
+       case IRQ_TYPE_LEVEL_HIGH:
                int_style = IXP23XX_GPIO_STYLE_ACTIVE_HIGH;
                irq_type = IXP23XX_IRQ_LEVEL;
                break;
-       case IRQT_LOW:
+       case IRQ_TYPE_LEVEL_LOW:
                int_style = IXP23XX_GPIO_STYLE_ACTIVE_LOW;
                irq_type = IXP23XX_IRQ_LEVEL;
                break;
index f0f70ba1e46d7c6a14d6b0ccb8ca10ede4777e5e..896ff9f840d9af4565291dc5aa295b6d16be5864 100644 (file)
@@ -110,8 +110,8 @@ static int __init roadrunner_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
 
 static void __init roadrunner_pci_preinit(void)
 {
-       set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQT_LOW);
-       set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQT_LOW);
+       set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
 
        ixp23xx_pci_preinit();
 }
index 3f867691d9f2fd41fa6eab25aa415d0ac04754ef..c6e044befccb17a0cdf911fa7798039cb13e8b47 100644 (file)
 
 void __init avila_pci_preinit(void)
 {
-       set_irq_type(IRQ_AVILA_PCI_INTA, IRQT_LOW);
-       set_irq_type(IRQ_AVILA_PCI_INTB, IRQT_LOW);
-       set_irq_type(IRQ_AVILA_PCI_INTC, IRQT_LOW);
-       set_irq_type(IRQ_AVILA_PCI_INTD, IRQT_LOW);
+       set_irq_type(IRQ_AVILA_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_AVILA_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_AVILA_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_AVILA_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index 3781b3db9f497dc83aab3512ab350d44d9a3d07c..3947c506b4f30cf50b20b821cafb526b6c93187d 100644 (file)
@@ -142,23 +142,23 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
                return -EINVAL;
 
        switch (type){
-       case IRQT_BOTHEDGE:
+       case IRQ_TYPE_EDGE_BOTH:
                int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
                irq_type = IXP4XX_IRQ_EDGE;
                break;
-       case IRQT_RISING:
+       case IRQ_TYPE_EDGE_RISING:
                int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
                irq_type = IXP4XX_IRQ_EDGE;
                break;
-       case IRQT_FALLING:
+       case IRQ_TYPE_EDGE_FALLING:
                int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
                irq_type = IXP4XX_IRQ_EDGE;
                break;
-       case IRQT_HIGH:
+       case IRQ_TYPE_LEVEL_HIGH:
                int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
                irq_type = IXP4XX_IRQ_LEVEL;
                break;
-       case IRQT_LOW:
+       case IRQ_TYPE_LEVEL_LOW:
                int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
                irq_type = IXP4XX_IRQ_LEVEL;
                break;
index ad2e5b97966ecfbb221d6260489f320c5e64e087..be4f4a208b907c18641163bf474a4a11a5b78d27 100644 (file)
@@ -27,8 +27,8 @@
 
 void __init coyote_pci_preinit(void)
 {
-       set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
-       set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW);
+       set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index 9db7e1f4201174af8969ed3e9d96b22e50a01f06..926d15f885fb7a77dedf3727c9dc96d747e81f29 100644 (file)
 
 void __init dsmg600_pci_preinit(void)
 {
-       set_irq_type(IRQ_DSMG600_PCI_INTA, IRQT_LOW);
-       set_irq_type(IRQ_DSMG600_PCI_INTB, IRQT_LOW);
-       set_irq_type(IRQ_DSMG600_PCI_INTC, IRQT_LOW);
-       set_irq_type(IRQ_DSMG600_PCI_INTD, IRQT_LOW);
-       set_irq_type(IRQ_DSMG600_PCI_INTE, IRQT_LOW);
-       set_irq_type(IRQ_DSMG600_PCI_INTF, IRQT_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTE, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_DSMG600_PCI_INTF, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index f19f3f6feda11079cb1f1db2db2dd5ddb373fc35..ca12a9ca083045f479409d0a5172a88ab5eb529e 100644 (file)
@@ -25,9 +25,9 @@
 
 void __init fsg_pci_preinit(void)
 {
-       set_irq_type(IRQ_FSG_PCI_INTA, IRQT_LOW);
-       set_irq_type(IRQ_FSG_PCI_INTB, IRQT_LOW);
-       set_irq_type(IRQ_FSG_PCI_INTC, IRQT_LOW);
+       set_irq_type(IRQ_FSG_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_FSG_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_FSG_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index 6abf568322d3dda0a7bc4e0dafc8ef5041442db8..afd1dc14e597db844c01827d7cb0ebe1e988203c 100644 (file)
@@ -29,8 +29,8 @@
 
 void __init gateway7001_pci_preinit(void)
 {
-       set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW);
-       set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index 49dec78688078f3bcc387af331b33ddb88be2895..20960704183be269ead5a5baf9ff17db5e76e344 100644 (file)
  */
 void __init gtwx5715_pci_preinit(void)
 {
-       set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW);
-       set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQT_LOW);
-       set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQT_LOW);
-       set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQT_LOW);
+       set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index 4087960048123541411cc472e3413f99f3100398..7d9bb4d2310441f12c3dac01140d524fe628ba35 100644 (file)
 
 void __init ixdp425_pci_preinit(void)
 {
-       set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW);
-       set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW);
-       set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW);
-       set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_LOW);
+       set_irq_type(IRQ_IXDP425_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_IXDP425_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_IXDP425_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_IXDP425_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index d1e75b7dc3b1a1263ed545c3f3a43dace8037a60..37d9f2e8f602d825e076a171fc791953b7e8a351 100644 (file)
@@ -25,8 +25,8 @@
 
 void __init ixdpg425_pci_preinit(void)
 {
-       set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
-       set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index b8ebaf4a9c8e5db0dfba464bc70803aa7d04952c..1088426fdcee3054a1907fc6506573cff4adf687 100644 (file)
 
 void __init nas100d_pci_preinit(void)
 {
-       set_irq_type(IRQ_NAS100D_PCI_INTA, IRQT_LOW);
-       set_irq_type(IRQ_NAS100D_PCI_INTB, IRQT_LOW);
-       set_irq_type(IRQ_NAS100D_PCI_INTC, IRQT_LOW);
-       set_irq_type(IRQ_NAS100D_PCI_INTD, IRQT_LOW);
-       set_irq_type(IRQ_NAS100D_PCI_INTE, IRQT_LOW);
+       set_irq_type(IRQ_NAS100D_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_NAS100D_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_NAS100D_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_NAS100D_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_NAS100D_PCI_INTE, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index 04661fef97f5a09a6116fde0ca6d58361b6454ab..4429b8448b61caa0d9a106738caa920f5f70c755 100644 (file)
@@ -24,9 +24,9 @@
 
 void __init nslu2_pci_preinit(void)
 {
-       set_irq_type(IRQ_NSLU2_PCI_INTA, IRQT_LOW);
-       set_irq_type(IRQ_NSLU2_PCI_INTB, IRQT_LOW);
-       set_irq_type(IRQ_NSLU2_PCI_INTC, IRQT_LOW);
+       set_irq_type(IRQ_NSLU2_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_NSLU2_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_NSLU2_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index 6588f2c758e22c5dc01103ebb6e257a4f6862bb2..0f00feab67f8a3985cbecc03682d18d840520c44 100644 (file)
@@ -29,8 +29,8 @@
 
 void __init wg302v2_pci_preinit(void)
 {
-       set_irq_type(IRQ_IXP4XX_GPIO8, IRQT_LOW);
-       set_irq_type(IRQ_IXP4XX_GPIO9, IRQT_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
 
        ixp4xx_pci_preinit();
 }
index 4c3ab43e1046b5f36ecd9c27447b31d33e05003a..0b06941a1eed2bdb0423afd269e7e9a5aac11801 100644 (file)
@@ -72,21 +72,21 @@ static int ks8695_irq_set_type(unsigned int irqno, unsigned int type)
        ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
 
        switch (type) {
-               case IRQT_HIGH:
+               case IRQ_TYPE_LEVEL_HIGH:
                        mode = IOPC_TM_HIGH;
                        level_triggered = 1;
                        break;
-               case IRQT_LOW:
+               case IRQ_TYPE_LEVEL_LOW:
                        mode = IOPC_TM_LOW;
                        level_triggered = 1;
                        break;
-               case IRQT_RISING:
+               case IRQ_TYPE_EDGE_RISING:
                        mode = IOPC_TM_RISING;
                        break;
-               case IRQT_FALLING:
+               case IRQ_TYPE_EDGE_FALLING:
                        mode = IOPC_TM_FALLING;
                        break;
-               case IRQT_BOTHEDGE:
+               case IRQ_TYPE_EDGE_BOTH:
                        mode = IOPC_TM_EDGE;
                        break;
                default:
index fd7537f7d11e798c3257ba46a5b21211b45a5b1c..99d4fb19a08a4af010ffd1661204f72ac1ee538a 100644 (file)
@@ -99,19 +99,19 @@ netx_hif_irq_type(unsigned int _irq, unsigned int type)
 
        irq = _irq - NETX_IRQ_HIF_CHAINED(0);
 
-       if (type & __IRQT_RISEDGE) {
+       if (type & IRQ_TYPE_EDGE_RISING) {
                DEBUG_IRQ("rising edges\n");
                val |= (1 << 26) << irq;
        }
-       if (type & __IRQT_FALEDGE) {
+       if (type & IRQ_TYPE_EDGE_FALLING) {
                DEBUG_IRQ("falling edges\n");
                val &= ~((1 << 26) << irq);
        }
-       if (type & __IRQT_LOWLVL) {
+       if (type & IRQ_TYPE_LEVEL_LOW) {
                DEBUG_IRQ("low level\n");
                val &= ~((1 << 26) << irq);
        }
-       if (type & __IRQT_HIGHLVL) {
+       if (type & IRQ_TYPE_LEVEL_HIGH) {
                DEBUG_IRQ("high level\n");
                val |= (1 << 26) << irq;
        }
index f8639161068f264b764f3bcf593b00f8ddb3bb06..44ed20d4a388a718bad140aeeabbfaeb70a1a04e 100644 (file)
@@ -14,8 +14,8 @@
 #include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
+#include <linux/semaphore.h>
 
-#include <asm/semaphore.h>
 #include "clock.h"
 
 static LIST_HEAD(clocks);
index 845c66371ca3a7eee5f47757fec16401d219896b..41f94f6fc15c4c7119536accffbb3a540b41558c 100644 (file)
@@ -288,7 +288,7 @@ static void __init osk_init_cf(void)
                return;
        }
        /* the CF I/O IRQ is really active-low */
-       set_irq_type(OMAP_GPIO_IRQ(62), IRQT_FALLING);
+       set_irq_type(OMAP_GPIO_IRQ(62), IRQ_TYPE_EDGE_FALLING);
 }
 
 static void __init osk_init_irq(void)
@@ -483,7 +483,7 @@ static void __init osk_mistral_init(void)
        omap_cfg_reg(P20_1610_GPIO4);   /* PENIRQ */
        gpio_request(4, "ts_int");
        gpio_direction_input(4);
-       set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
+       set_irq_type(OMAP_GPIO_IRQ(4), IRQ_TYPE_EDGE_FALLING);
 
        spi_register_board_info(mistral_boardinfo,
                        ARRAY_SIZE(mistral_boardinfo));
@@ -494,7 +494,7 @@ static void __init osk_mistral_init(void)
                int ret = 0;
 
                gpio_direction_input(OMAP_MPUIO(2));
-               set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING);
+               set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQ_TYPE_EDGE_RISING);
 #ifdef CONFIG_PM
                /* share the IRQ in case someone wants to use the
                 * button for more than wakeup from system sleep.
index e020c2774606884e1dfcfa8f5dbd76f94887ca6e..34389b63b0ecc9f1c61a4cf931e8759aaed9021a 100644 (file)
@@ -298,11 +298,11 @@ palmz71_powercable(int irq, void *dev_id)
        if (omap_get_gpio_datain(PALMZ71_USBDETECT_GPIO)) {
                printk(KERN_INFO "PM: Power cable connected\n");
                set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO),
-                               IRQT_FALLING);
+                               IRQ_TYPE_EDGE_FALLING);
        } else {
                printk(KERN_INFO "PM: Power cable disconnected\n");
                set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO),
-                               IRQT_RISING);
+                               IRQ_TYPE_EDGE_RISING);
        }
        return IRQ_HANDLED;
 }
index 5c00b3f39cdd5d44cc1d75b9060d7fe78addb6f5..8948d45a27695c64db1e228ed2f1e7be7518880f 100644 (file)
@@ -186,10 +186,10 @@ static void __init voiceblue_init(void)
        omap_request_gpio(13);
        omap_request_gpio(14);
        omap_request_gpio(15);
-       set_irq_type(OMAP_GPIO_IRQ(12), IRQT_RISING);
-       set_irq_type(OMAP_GPIO_IRQ(13), IRQT_RISING);
-       set_irq_type(OMAP_GPIO_IRQ(14), IRQT_RISING);
-       set_irq_type(OMAP_GPIO_IRQ(15), IRQT_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(12), IRQ_TYPE_EDGE_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(13), IRQ_TYPE_EDGE_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(14), IRQ_TYPE_EDGE_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(15), IRQ_TYPE_EDGE_RISING);
 
        platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
        omap_board_config = voiceblue_config;
index 0cf62ef5ecb7dea02740f7c5746cc280410df897..d963125ed755815345e08c0c781a95e277923729 100644 (file)
@@ -181,7 +181,7 @@ void omap1510_fpga_init_irq(void)
         */
        omap_request_gpio(13);
        omap_set_gpio_direction(13, 1);
-       set_irq_type(OMAP_GPIO_IRQ(13), IRQT_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(13), IRQ_TYPE_EDGE_RISING);
        set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
 }
 
index 620fa0f120ee8a67df40fe95b5f5e2b569127f11..870b34972d3b15a7bdee22222dfe801bf9d1bbfd 100644 (file)
@@ -337,17 +337,17 @@ static void __init apollon_sw_init(void)
        omap_request_gpio(SW_DOWN_GPIO58);
        omap_set_gpio_direction(SW_DOWN_GPIO58, 1);
 
-       set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQ_TYPE_EDGE_RISING);
        if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt,
                                IRQF_SHARED, "enter sw",
                                &apollon_sw_interrupt))
                return;
-       set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQ_TYPE_EDGE_RISING);
        if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt,
                                IRQF_SHARED, "up sw",
                                &apollon_sw_interrupt))
                return;
-       set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQ_TYPE_EDGE_RISING);
        if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt,
                                IRQF_SHARED, "down sw",
                                &apollon_sw_interrupt))
index 88405e74e5e306a4a6384151c5827d908c80d303..40a0bee4fbb3da6159625ff5c34e7b4236710b30 100644 (file)
@@ -213,7 +213,7 @@ void __init db88f5281_pci_preinit(void)
        pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
        if (gpio_request(pin, "PCI Int1") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "db88f5281_pci_preinit faield to "
                                        "set_irq_type pin %d\n", pin);
@@ -226,7 +226,7 @@ void __init db88f5281_pci_preinit(void)
        pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
        if (gpio_request(pin, "PCI Int2") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "db88f5281_pci_preinit faield "
                                        "to set_irq_type pin %d\n", pin);
index e2a0084ab4a3845d72ea5e98b802641ded09d600..9ae3f6dc7839cb9f1285f5990dbd133e97b73f68 100644 (file)
@@ -91,27 +91,27 @@ static int orion5x_gpio_set_irq_type(u32 irq, u32 type)
        desc = irq_desc + irq;
 
        switch (type) {
-       case IRQT_HIGH:
+       case IRQ_TYPE_LEVEL_HIGH:
                desc->handle_irq = handle_level_irq;
                desc->status |= IRQ_LEVEL;
                orion5x_clrbits(GPIO_IN_POL, (1 << pin));
                break;
-       case IRQT_LOW:
+       case IRQ_TYPE_LEVEL_LOW:
                desc->handle_irq = handle_level_irq;
                desc->status |= IRQ_LEVEL;
                orion5x_setbits(GPIO_IN_POL, (1 << pin));
                break;
-       case IRQT_RISING:
+       case IRQ_TYPE_EDGE_RISING:
                desc->handle_irq = handle_edge_irq;
                desc->status &= ~IRQ_LEVEL;
                orion5x_clrbits(GPIO_IN_POL, (1 << pin));
                break;
-       case IRQT_FALLING:
+       case IRQ_TYPE_EDGE_FALLING:
                desc->handle_irq = handle_edge_irq;
                desc->status &= ~IRQ_LEVEL;
                orion5x_setbits(GPIO_IN_POL, (1 << pin));
                break;
-       case IRQT_BOTHEDGE:
+       case IRQ_TYPE_EDGE_BOTH:
                desc->handle_irq = handle_edge_irq;
                desc->status &= ~IRQ_LEVEL;
                /*
@@ -156,7 +156,7 @@ static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                if (cause & (1 << pin)) {
                        irq = gpio_to_irq(pin);
                        desc = irq_desc + irq;
-                       if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
+                       if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
                                /* Swap polarity (race with GPIO line) */
                                u32 polarity = readl(GPIO_IN_POL);
                                polarity ^= 1 << pin;
index 10ae62864269371af277850bcbed7048612e0319..2a46d27209c198ad472a62c2aafb220bfbaa97d1 100644 (file)
@@ -148,7 +148,7 @@ void __init rd88f5182_pci_preinit(void)
        pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
        if (gpio_request(pin, "PCI IntA") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "rd88f5182_pci_preinit faield to "
                                        "set_irq_type pin %d\n", pin);
@@ -161,7 +161,7 @@ void __init rd88f5182_pci_preinit(void)
        pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
        if (gpio_request(pin, "PCI IntB") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "rd88f5182_pci_preinit faield to "
                                        "set_irq_type pin %d\n", pin);
index a9cef9703d5b37bdd4e38b56974875b32caec9cc..f270ada2def93b1b4ad5e308c4c641a534986b39 100644 (file)
@@ -117,7 +117,7 @@ void __init qnap_ts209_pci_preinit(void)
        pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
        if (gpio_request(pin, "PCI Int1") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
                                        "set_irq_type pin %d\n", pin);
@@ -131,7 +131,7 @@ void __init qnap_ts209_pci_preinit(void)
        pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
        if (gpio_request(pin, "PCI Int2") == 0) {
                if (gpio_direction_input(pin) == 0) {
-                       set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+                       set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
                } else {
                        printk(KERN_ERR "qnap_ts209_pci_preinit failed "
                                        "to set_irq_type pin %d\n", pin);
index 968d0b027597399fa88d3d627756dddb1abc7316..5ed67e1947a8bda3ca268b10af7617cb32d66677 100644 (file)
@@ -56,28 +56,28 @@ static void pnx4008_mask_ack_irq(unsigned int irq)
 static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
 {
        switch (type) {
-       case IRQT_RISING:
+       case IRQ_TYPE_EDGE_RISING:
                __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));        /*edge sensitive */
                __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));        /*rising edge */
                set_irq_handler(irq, handle_edge_irq);
                break;
-       case IRQT_FALLING:
+       case IRQ_TYPE_EDGE_FALLING:
                __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));        /*edge sensitive */
                __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));       /*falling edge */
                set_irq_handler(irq, handle_edge_irq);
                break;
-       case IRQT_LOW:
+       case IRQ_TYPE_LEVEL_LOW:
                __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));       /*level sensitive */
                __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));       /*low level */
                set_irq_handler(irq, handle_level_irq);
                break;
-       case IRQT_HIGH:
+       case IRQ_TYPE_LEVEL_HIGH:
                __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));       /*level sensitive */
                __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));        /* high level */
                set_irq_handler(irq, handle_level_irq);
                break;
 
-       /* IRQT_BOTHEDGE is not supported */
+       /* IRQ_TYPE_EDGE_BOTH is not supported */
        default:
                printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
                return -1;
index bcf0cde6ccc965ce2a3ba925ff868596f0d8c185..31f5bd411cedd89aa554b9899f2de336064c0a96 100644 (file)
@@ -71,7 +71,7 @@ void __cmx270_pci_init_irq(int irq_gpio)
 
        cmx270_it8152_irq_gpio = irq_gpio;
 
-       set_irq_type(gpio_to_irq(irq_gpio), IRQT_RISING);
+       set_irq_type(gpio_to_irq(irq_gpio), IRQ_TYPE_EDGE_RISING);
 
        set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx270_it8152_irq_demux);
 }
index cc1c4fa061451cc26e15c9250b545773adf9072a..8d1ab54e7b20e5d3eed4a3fa403e6a4f4a32af77 100644 (file)
@@ -113,7 +113,7 @@ static void __init lpd270_init_irq(void)
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
        set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
-       set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
+       set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
 }
 
 
index ac26423cd20cbda2ce8db0667887625c4ef466da..af7375bb46a47f0556d6e502d270e0c6684ee870 100644 (file)
@@ -152,7 +152,7 @@ static void __init lubbock_init_irq(void)
        }
 
        set_irq_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
-       set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
+       set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
 }
 
 #ifdef CONFIG_PM
index 851ec2d9b699c178fe36aa723269150d67f409f4..c8e38b5ff1c4a2a50fe92afc645df9da680f2dff 100644 (file)
@@ -191,7 +191,7 @@ static void __init mainstone_init_irq(void)
        MST_INTSETCLR = 0;
 
        set_irq_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
-       set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
+       set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
 }
 
 #ifdef CONFIG_PM
index 34cd585075b076c76e517558d45f226588c9fa20..23e9b9283301d1ce7f59b9ea10f91eda989b1f89 100644 (file)
@@ -146,18 +146,18 @@ void sharpsl_pm_pxa_init(void)
        if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) {
                dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin));
        }
-       else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQT_BOTHEDGE);
+       else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQ_TYPE_EDGE_BOTH);
 
        if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) {
                dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock));
        }
-       else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQT_FALLING);
+       else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQ_TYPE_EDGE_FALLING);
 
        if (sharpsl_pm.machinfo->gpio_fatal) {
                if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) {
                        dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal));
                }
-               else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQT_FALLING);
+               else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQ_TYPE_EDGE_FALLING);
        }
 
        if (sharpsl_pm.machinfo->batfull_irq)
@@ -166,7 +166,7 @@ void sharpsl_pm_pxa_init(void)
                if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) {
                        dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull));
                }
-               else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING);
+               else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQ_TYPE_EDGE_RISING);
        }
 }
 
index dee7bf36f013f76af3950eed48ecf299ec010fac..12811b7aea0706347b032b6686dc43b7c5a0f33f 100644 (file)
@@ -122,7 +122,7 @@ static struct resource dm9000_resources[] = {
        [2] = {
                .start  = TRIZEPS4_ETH_IRQ,
                .end    = TRIZEPS4_ETH_IRQ,
-               .flags  = (IORESOURCE_IRQ | IRQT_RISING),
+               .flags  = (IORESOURCE_IRQ | IRQ_TYPE_EDGE_RISING),
        },
 };
 
index 31afe50d7cd59746360d0dbbb642c7f87197bdcb..56d3ee01baae09298a9006bd9e773373d29c9a14 100644 (file)
@@ -96,7 +96,7 @@ static struct resource cerf_flash_resource = {
 static void __init cerf_init_irq(void)
 {
        sa1100_init_irq();
-       set_irq_type(CERF_ETH_IRQ, IRQT_RISING);
+       set_irq_type(CERF_ETH_IRQ, IRQ_TYPE_EDGE_RISING);
 }
 
 static struct map_desc cerf_io_desc[] __initdata = {
index 8473c37b77d6e1bf4f5c7d6ce06109793c4275c4..b34ff42bbd75a137aeea778f6d1c4f4ff6d77a6e 100644 (file)
@@ -834,7 +834,7 @@ static void __init h3800_init_irq(void)
                set_irq_chip(irq, &h3800_gpio_irqchip);
        }
 #endif
-       set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING);
+       set_irq_type(IRQ_GPIO_H3800_ASIC, IRQ_TYPE_EDGE_RISING);
        set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, h3800_IRQ_demux);
 }
 
index fa0403af7eecf3f078a18225f6f8ab485bcf8811..c5e438b12ec75ae3a5588e16e3ee22a70df5579f 100644 (file)
@@ -46,17 +46,17 @@ static int sa1100_gpio_type(unsigned int irq, unsigned int type)
        else
                mask = GPIO11_27_MASK(irq);
 
-       if (type == IRQT_PROBE) {
+       if (type == IRQ_TYPE_PROBE) {
                if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
                        return 0;
-               type = __IRQT_RISEDGE | __IRQT_FALEDGE;
+               type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
        }
 
-       if (type & __IRQT_RISEDGE) {
+       if (type & IRQ_TYPE_EDGE_RISING) {
                GPIO_IRQ_rising_edge |= mask;
        } else
                GPIO_IRQ_rising_edge &= ~mask;
-       if (type & __IRQT_FALEDGE) {
+       if (type & IRQ_TYPE_EDGE_FALLING) {
                GPIO_IRQ_falling_edge |= mask;
        } else
                GPIO_IRQ_falling_edge &= ~mask;
index 9f1ed15093016b3ebd88a204795efca7d026946b..967a48454f6bd34e33507de11aa4fabd30065214 100644 (file)
@@ -151,7 +151,7 @@ static int __devinit neponset_probe(struct platform_device *dev)
        /*
         * Install handler for GPIO25.
         */
-       set_irq_type(IRQ_GPIO25, IRQT_RISING);
+       set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING);
        set_irq_chained_handler(IRQ_GPIO25, neponset_irq_handler);
 
        /*
index c7bf7e0038f07922bb294860ed75c284fbb1a811..69a71f11625eb74c01ceea24c9b0b5a6f808af06 100644 (file)
@@ -143,7 +143,7 @@ static void __init pleb_map_io(void)
 
        GPDR &= ~GPIO_ETH0_IRQ;
 
-       set_irq_type(GPIO_ETH0_IRQ, IRQT_FALLING);
+       set_irq_type(GPIO_ETH0_IRQ, IRQ_TYPE_EDGE_FALLING);
 }
 
 MACHINE_START(PLEB, "PLEB")
index 333a82a3717e07daa8979986480579b943507e53..db7b3e38ef1d1410287f8ca7a84cd435e73f5c2c 100644 (file)
@@ -274,6 +274,11 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
 void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
+       void *memory;
+
+       if (dma_alloc_from_coherent(dev, size, handle, &memory))
+               return memory;
+
        if (arch_is_coherent()) {
                void *virt;
 
@@ -362,6 +367,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
 
        WARN_ON(irqs_disabled());
 
+       if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
+               return;
+
        if (arch_is_coherent()) {
                kfree(cpu_addr);
                return;
index 1e56021895072b69777ddebc3d18b54fd2baba0e..c8c0c4b0f0a33e67a26b80829d9cfc03ede7a141 100644 (file)
  * Our node_data structure for discontiguous memory.
  */
 
-static bootmem_data_t node_bootmem_data[MAX_NUMNODES];
-
 pg_data_t discontig_node_data[MAX_NUMNODES] = {
-  { .bdata = &node_bootmem_data[0] },
-  { .bdata = &node_bootmem_data[1] },
-  { .bdata = &node_bootmem_data[2] },
-  { .bdata = &node_bootmem_data[3] },
+  { .bdata = &bootmem_node_data[0] },
+  { .bdata = &bootmem_node_data[1] },
+  { .bdata = &bootmem_node_data[2] },
+  { .bdata = &bootmem_node_data[3] },
 #if MAX_NUMNODES == 16
-  { .bdata = &node_bootmem_data[4] },
-  { .bdata = &node_bootmem_data[5] },
-  { .bdata = &node_bootmem_data[6] },
-  { .bdata = &node_bootmem_data[7] },
-  { .bdata = &node_bootmem_data[8] },
-  { .bdata = &node_bootmem_data[9] },
-  { .bdata = &node_bootmem_data[10] },
-  { .bdata = &node_bootmem_data[11] },
-  { .bdata = &node_bootmem_data[12] },
-  { .bdata = &node_bootmem_data[13] },
-  { .bdata = &node_bootmem_data[14] },
-  { .bdata = &node_bootmem_data[15] },
+  { .bdata = &bootmem_node_data[4] },
+  { .bdata = &bootmem_node_data[5] },
+  { .bdata = &bootmem_node_data[6] },
+  { .bdata = &bootmem_node_data[7] },
+  { .bdata = &bootmem_node_data[8] },
+  { .bdata = &bootmem_node_data[9] },
+  { .bdata = &bootmem_node_data[10] },
+  { .bdata = &bootmem_node_data[11] },
+  { .bdata = &bootmem_node_data[12] },
+  { .bdata = &bootmem_node_data[13] },
+  { .bdata = &bootmem_node_data[14] },
+  { .bdata = &bootmem_node_data[15] },
 #endif
 };
 
index fbfa26058442ccf5fb8dc0225b306f404eea2b6e..a8ec97b4752e129afcecbded471388af85d6ccb8 100644 (file)
@@ -37,7 +37,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
        pgd_t *pgd;
        pmd_t *pmd;
        pte_t *pte, entry;
-       int ret = 0;
+       int ret;
 
        pgd = pgd_offset(vma->vm_mm, address);
        if (pgd_none(*pgd))
@@ -54,16 +54,20 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
        pte = pte_offset_map(pmd, address);
        entry = *pte;
 
+       /*
+        * If this page is present, it's actually being shared.
+        */
+       ret = pte_present(entry);
+
        /*
         * If this page isn't present, or is already setup to
         * fault (ie, is old), we can safely ignore any issues.
         */
-       if (pte_present(entry) && pte_val(entry) & shared_pte_mask) {
+       if (ret && pte_val(entry) & shared_pte_mask) {
                flush_cache_page(vma, address, pte_pfn(entry));
                pte_val(entry) &= ~shared_pte_mask;
                set_pte_at(vma->vm_mm, address, pte, entry);
                flush_tlb_page(vma, address);
-               ret = 1;
        }
        pte_unmap(pte);
        return ret;
index b657f1719af0e0f50a2498566d981acb616e967f..e6352946dde020e04c3461b2f074972592b74710 100644 (file)
@@ -284,7 +284,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
         */
        arch_adjust_zones(node, zone_size, zhole_size);
 
-       free_area_init_node(node, pgdat, zone_size, start_pfn, zhole_size);
+       free_area_init_node(node, zone_size, start_pfn, zhole_size);
 
        return end_pfn;
 }
index 4a7736717d860b7f32422993960cf00aca61a695..318b268f938e524dbd342f258a2b26699bfa89b9 100644 (file)
@@ -73,19 +73,19 @@ static int gpio_set_irq_type(u32 irq, u32 type)
        void __iomem *reg = port->base;
 
        switch (type) {
-       case IRQT_RISING:
+       case IRQ_TYPE_EDGE_RISING:
                edge = GPIO_INT_RISE_EDGE;
                break;
-       case IRQT_FALLING:
+       case IRQ_TYPE_EDGE_FALLING:
                edge = GPIO_INT_FALL_EDGE;
                break;
-       case IRQT_LOW:
+       case IRQ_TYPE_LEVEL_LOW:
                edge = GPIO_INT_LOW_LEV;
                break;
-       case IRQT_HIGH:
+       case IRQ_TYPE_LEVEL_HIGH:
                edge = GPIO_INT_HIGH_LEV;
                break;
-       default:        /* this includes IRQT_BOTHEDGE */
+       default:        /* this includes IRQ_TYPE_EDGE_BOTH */
                return -EINVAL;
        }
 
index 7854f19b77cf6588b23762632c4c3efddd9b0ac4..5d107520e6b90348a5d168c25da557613d41d04f 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/bootmem.h>
@@ -182,7 +183,7 @@ void __init omapfb_reserve_sdram(void)
                return;
 
        bdata = NODE_DATA(0)->bdata;
-       sdram_start = bdata->node_boot_start;
+       sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
        sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
        reserved = 0;
        for (i = 0; ; i++) {
@@ -340,5 +341,3 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
 
 
 #endif
-
-
index 1903a3491ee9ff7f330e90a3c9a7df5cd4897d22..63e094342ef6b7e38ddba9df5c2585b21aaad22d 100644 (file)
@@ -517,13 +517,13 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
        u32 gpio_bit = 1 << gpio;
 
        MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
-               trigger & __IRQT_LOWLVL);
+               trigger & IRQ_TYPE_LEVEL_LOW);
        MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
-               trigger & __IRQT_HIGHLVL);
+               trigger & IRQ_TYPE_LEVEL_HIGH);
        MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
-               trigger & __IRQT_RISEDGE);
+               trigger & IRQ_TYPE_EDGE_RISING);
        MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
-               trigger & __IRQT_FALEDGE);
+               trigger & IRQ_TYPE_EDGE_FALLING);
 
        if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
                if (trigger != 0)
@@ -555,9 +555,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
        case METHOD_MPUIO:
                reg += OMAP_MPUIO_GPIO_INT_EDGE;
                l = __raw_readl(reg);
-               if (trigger & __IRQT_RISEDGE)
+               if (trigger & IRQ_TYPE_EDGE_RISING)
                        l |= 1 << gpio;
-               else if (trigger & __IRQT_FALEDGE)
+               else if (trigger & IRQ_TYPE_EDGE_FALLING)
                        l &= ~(1 << gpio);
                else
                        goto bad;
@@ -567,9 +567,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
        case METHOD_GPIO_1510:
                reg += OMAP1510_GPIO_INT_CONTROL;
                l = __raw_readl(reg);
-               if (trigger & __IRQT_RISEDGE)
+               if (trigger & IRQ_TYPE_EDGE_RISING)
                        l |= 1 << gpio;
-               else if (trigger & __IRQT_FALEDGE)
+               else if (trigger & IRQ_TYPE_EDGE_FALLING)
                        l &= ~(1 << gpio);
                else
                        goto bad;
@@ -584,9 +584,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
                gpio &= 0x07;
                l = __raw_readl(reg);
                l &= ~(3 << (gpio << 1));
-               if (trigger & __IRQT_RISEDGE)
+               if (trigger & IRQ_TYPE_EDGE_RISING)
                        l |= 2 << (gpio << 1);
-               if (trigger & __IRQT_FALEDGE)
+               if (trigger & IRQ_TYPE_EDGE_FALLING)
                        l |= 1 << (gpio << 1);
                if (trigger)
                        /* Enable wake-up during idle for dynamic tick */
@@ -599,9 +599,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
        case METHOD_GPIO_730:
                reg += OMAP730_GPIO_INT_CONTROL;
                l = __raw_readl(reg);
-               if (trigger & __IRQT_RISEDGE)
+               if (trigger & IRQ_TYPE_EDGE_RISING)
                        l |= 1 << gpio;
-               else if (trigger & __IRQT_FALEDGE)
+               else if (trigger & IRQ_TYPE_EDGE_FALLING)
                        l &= ~(1 << gpio);
                else
                        goto bad;
@@ -887,7 +887,7 @@ 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);
+       _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
 }
 
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
@@ -924,7 +924,7 @@ int omap_request_gpio(int gpio)
        /* 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);
+       _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
 
 #ifdef CONFIG_ARCH_OMAP15XX
        if (bank->method == METHOD_GPIO_1510) {
@@ -1488,6 +1488,9 @@ static int __init _omap_gpio_init(void)
                bank->chip.set = gpio_set;
                if (bank_is_mpuio(bank)) {
                        bank->chip.label = "mpuio";
+#ifdef CONFIG_ARCH_OMAP1
+                       bank->chip.dev = &omap_mpuio_device.dev;
+#endif
                        bank->chip.base = OMAP_MPUIO(0);
                } else {
                        bank->chip.label = "gpio";
index 5e28c217b8c28217bfed9c6a7094211b6602b6bd..0af3872fb76306fa6b6119dcf12ad124c9463189 100644 (file)
@@ -9,7 +9,7 @@ config PLAT_S3C24XX
        depends on ARCH_S3C2410
        default y if ARCH_S3C2410
        select NO_IOPORT
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
        help
          Base platform code for any Samsung S3C24XX device
 
index 60f162dc4fad5d1617f074c5256dc5c8b8227e03..8c5e656d5d8c8c346dd5f2d3c7740886a977f235 100644 (file)
@@ -1304,7 +1304,7 @@ struct sysdev_class dma_sysclass = {
 
 /* kmem cache implementation */
 
-static void s3c2410_dma_cache_ctor(struct kmem_cache *c, void *p)
+static void s3c2410_dma_cache_ctor(void *p)
 {
        memset(p, 0, sizeof(struct s3c2410_dma_buf));
 }
index ae2c5d7efc9dc411cc1488840bee40d8b648a456..001436c04b13b53e697c328929467667acf19dc2 100644 (file)
@@ -292,27 +292,27 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
        /* Set the external interrupt to pointed trigger type */
        switch (type)
        {
-               case IRQT_NOEDGE:
+               case IRQ_TYPE_NONE:
                        printk(KERN_WARNING "No edge setting!\n");
                        break;
 
-               case IRQT_RISING:
+               case IRQ_TYPE_EDGE_RISING:
                        newvalue = S3C2410_EXTINT_RISEEDGE;
                        break;
 
-               case IRQT_FALLING:
+               case IRQ_TYPE_EDGE_FALLING:
                        newvalue = S3C2410_EXTINT_FALLEDGE;
                        break;
 
-               case IRQT_BOTHEDGE:
+               case IRQ_TYPE_EDGE_BOTH:
                        newvalue = S3C2410_EXTINT_BOTHEDGE;
                        break;
 
-               case IRQT_LOW:
+               case IRQ_TYPE_LEVEL_LOW:
                        newvalue = S3C2410_EXTINT_LOWLEV;
                        break;
 
-               case IRQT_HIGH:
+               case IRQ_TYPE_LEVEL_HIGH:
                        newvalue = S3C2410_EXTINT_HILEV;
                        break;
 
index 45d63c9860150fd70d566b8a032ccebda568f954..7c239a916275b6b66b326e7fc93c6207bdbaf270 100644 (file)
@@ -10,6 +10,7 @@ config AVR32
        # With EMBEDDED=n, we get lots of stuff automatically selected
        # that we usually don't need on AVR32.
        select EMBEDDED
+       select HAVE_CLK
        select HAVE_OPROFILE
        select HAVE_KPROBES
        help
@@ -87,7 +88,7 @@ config PLATFORM_AT32AP
        select SUBARCH_AVR32B
        select MMU
        select PERFORMANCE_COUNTERS
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_ALLOCATOR
 
 #
index af90b00100fd0d96f58df404411e00affce02bcd..8dc48214f0b76ffe44c15e2ca5f74a52641a2086 100644 (file)
@@ -18,6 +18,10 @@ config BOARD_ATSTK1004
        bool "ATSTK1004"
        select CPU_AT32AP7002
 
+config BOARD_ATSTK1006
+       bool "ATSTK1006"
+       select CPU_AT32AP7000
+
 endchoice
 
 
index beead86462e8a6a7f8f7797e746be176268394ba..edecee03742d4a935df734e4e86f9d755c7eb8ad 100644 (file)
@@ -2,3 +2,4 @@ obj-y                           += setup.o flash.o
 obj-$(CONFIG_BOARD_ATSTK1002)  += atstk1002.o
 obj-$(CONFIG_BOARD_ATSTK1003)  += atstk1003.o
 obj-$(CONFIG_BOARD_ATSTK1004)  += atstk1004.o
+obj-$(CONFIG_BOARD_ATSTK1006)  += atstk1002.o
index e11659b732fab61d743f5e72b3487b298c5f9646..8538ba75ef92c8a1def6ee96caea4557618ae061 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * ATSTK1002 daughterboard-specific init code
+ * ATSTK1002/ATSTK1006 daughterboard-specific init code
  *
- * Copyright (C) 2005-2006 Atmel Corporation
+ * Copyright (C) 2005-2007 Atmel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -21,6 +21,8 @@
 
 #include <asm/io.h>
 #include <asm/setup.h>
+#include <asm/atmel-mci.h>
+
 #include <asm/arch/at32ap700x.h>
 #include <asm/arch/board.h>
 #include <asm/arch/init.h>
@@ -35,6 +37,74 @@ unsigned long at32_board_osc_rates[3] = {
        [2] = 12000000, /* 12 MHz on osc1 */
 };
 
+/*
+ * The ATSTK1006 daughterboard is very similar to the ATSTK1002. Both
+ * have the AT32AP7000 chip on board; the difference is that the
+ * STK1006 has 128 MB SDRAM (the STK1002 uses the 8 MB SDRAM chip on
+ * the STK1000 motherboard) and 256 MB NAND flash (the STK1002 has
+ * none.)
+ *
+ * The RAM difference is handled by the boot loader, so the only
+ * difference we end up handling here is the NAND flash.
+ */
+#ifdef CONFIG_BOARD_ATSTK1006
+#include <linux/mtd/partitions.h>
+#include <asm/arch/smc.h>
+
+static struct smc_timing nand_timing __initdata = {
+       .ncs_read_setup         = 0,
+       .nrd_setup              = 10,
+       .ncs_write_setup        = 0,
+       .nwe_setup              = 10,
+
+       .ncs_read_pulse         = 30,
+       .nrd_pulse              = 15,
+       .ncs_write_pulse        = 30,
+       .nwe_pulse              = 15,
+
+       .read_cycle             = 30,
+       .write_cycle            = 30,
+
+       .ncs_read_recover       = 0,
+       .nrd_recover            = 15,
+       .ncs_write_recover      = 0,
+       /* WE# high -> RE# low min 60 ns */
+       .nwe_recover            = 50,
+};
+
+static struct smc_config nand_config __initdata = {
+       .bus_width              = 1,
+       .nrd_controlled         = 1,
+       .nwe_controlled         = 1,
+       .nwait_mode             = 0,
+       .byte_write             = 0,
+       .tdf_cycles             = 2,
+       .tdf_mode               = 0,
+};
+
+static struct mtd_partition nand_partitions[] = {
+       {
+               .name           = "main",
+               .offset         = 0x00000000,
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct mtd_partition *nand_part_info(int size, int *num_partitions)
+{
+       *num_partitions = ARRAY_SIZE(nand_partitions);
+       return nand_partitions;
+}
+
+struct atmel_nand_data atstk1006_nand_data __initdata = {
+       .cle            = 21,
+       .ale            = 22,
+       .rdy_pin        = GPIO_PIN_PB(30),
+       .enable_pin     = GPIO_PIN_PB(29),
+       .partition_info = nand_part_info,
+};
+#endif
+
 struct eth_addr {
        u8 addr[6];
 };
@@ -192,6 +262,21 @@ void __init setup_board(void)
        at32_setup_serial_console(0);
 }
 
+#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
+
+/* MMC card detect requires MACB0 *NOT* be used */
+#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
+static struct mci_platform_data __initdata mci0_data = {
+       .detect_pin     = GPIO_PIN_PC(14),      /* gpio30/sdcd */
+       .wp_pin         = GPIO_PIN_PC(15),      /* gpio31/sdwp */
+};
+#define MCI_PDATA      &mci0_data
+#else
+#define MCI_PDATA      NULL
+#endif /* SW6 for sd{cd,wp} routing */
+
+#endif /* SW2 for MMC signal routing */
+
 static int __init atstk1002_init(void)
 {
        /*
@@ -218,6 +303,12 @@ static int __init atstk1002_init(void)
 
        at32_add_system_devices();
 
+#ifdef CONFIG_BOARD_ATSTK1006
+       smc_set_timing(&nand_config, &nand_timing);
+       smc_set_configuration(3, &nand_config);
+       at32_add_device_nand(0, &atstk1006_nand_data);
+#endif
+
 #ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
        at32_add_device_usart(1);
 #else
@@ -235,7 +326,7 @@ static int __init atstk1002_init(void)
        at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 #endif
 #ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
-       at32_add_device_mci(0, NULL);
+       at32_add_device_mci(0, MCI_PDATA);
 #endif
 #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
        set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
index ea109f435a83adc6ffb67cd8264d8a84552f52c9..591fc73b554a58dc5c71e56fdd5471030dd32c32 100644 (file)
@@ -154,7 +154,7 @@ static int __init atstk1003_init(void)
        at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 #endif
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
-       at32_add_device_mci(0);
+       at32_add_device_mci(0, NULL);
 #endif
        at32_add_device_usba(0, NULL);
 #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
index c7236df74d7422125d6048c33804f8d167c1c91c..d9c5e0a21256cf30cd7c9a031b27753ddd2f67d6 100644 (file)
@@ -137,7 +137,7 @@ static int __init atstk1004_init(void)
        at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 #endif
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
-       at32_add_device_mci(0);
+       at32_add_device_mci(0, NULL);
 #endif
        at32_add_device_lcdc(0, &atstk1000_lcdc_data,
                             fbmem_start, fbmem_size, 0);
index 6cf9df1762743a29813db51b5d82d5ba8f6acedf..ff820a9e743a01c3d5fdd7bd61649fec474bdad3 100644 (file)
@@ -31,7 +31,7 @@ void cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        cpu_idle_sleep();
                tick_nohz_restart_sched_tick();
index f4bdb448049c309b7363d7889d272d5c15ab33ed..c09f0d8dd679462481d926cedfcc28f8ca97f6eb 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 #include <linux/thread_info.h>
+#include <linux/module.h>
 
 register unsigned long current_frame_pointer asm("r7");
 
index abd954fb7ba0ccbf37b1494b93c1600045fd1a88..7e7f32771ae1aa9d0a25b38739cebc81352173a4 100644 (file)
@@ -43,6 +43,9 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
        struct clock_event_device *evdev = dev_id;
 
+       if (unlikely(!(intc_get_pending(0) & 1)))
+               return IRQ_NONE;
+
        /*
         * Disable the interrupt until the clockevent subsystem
         * reprograms it.
@@ -55,7 +58,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction timer_irqaction = {
        .handler        = timer_interrupt,
-       .flags          = IRQF_TIMER | IRQF_DISABLED,
+       /* Oprofile uses the same irq as the timer, so allow it to be shared */
+       .flags          = IRQF_TIMER | IRQF_DISABLED | IRQF_SHARED,
        .name           = "avr32_comparator",
 };
 
index 604f44f5dd164833a9bfdb075a7d65a713617fff..1617048c86c5955bb549d84be9d1bf77ca90c6af 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/usb/atmel_usba_udc.h>
 
@@ -1285,7 +1286,6 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
 {
        struct mci_platform_data        _data;
        struct platform_device          *pdev;
-       struct dw_dma_slave             *dws;
 
        if (id != 0)
                return NULL;
@@ -1300,7 +1300,9 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
 
        if (!data) {
                data = &_data;
-               memset(data, 0, sizeof(struct mci_platform_data));
+               memset(data, -1, sizeof(struct mci_platform_data));
+               data->detect_pin = GPIO_PIN_NONE;
+               data->wp_pin = GPIO_PIN_NONE;
        }
 
        if (platform_device_add_data(pdev, data,
@@ -1314,12 +1316,10 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
        select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
        select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
 
-       if (data) {
-               if (data->detect_pin != GPIO_PIN_NONE)
-                       at32_select_gpio(data->detect_pin, 0);
-               if (data->wp_pin != GPIO_PIN_NONE)
-                       at32_select_gpio(data->wp_pin, 0);
-       }
+       if (gpio_is_valid(data->detect_pin))
+               at32_select_gpio(data->detect_pin, 0);
+       if (gpio_is_valid(data->wp_pin))
+               at32_select_gpio(data->wp_pin, 0);
 
        atmel_mci0_pclk.dev = &pdev->dev;
 
@@ -1853,11 +1853,11 @@ at32_add_device_cf(unsigned int id, unsigned int extint,
        if (at32_init_ide_or_cf(pdev, data->cs, extint))
                goto fail;
 
-       if (data->detect_pin != GPIO_PIN_NONE)
+       if (gpio_is_valid(data->detect_pin))
                at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH);
-       if (data->reset_pin != GPIO_PIN_NONE)
+       if (gpio_is_valid(data->reset_pin))
                at32_select_gpio(data->reset_pin, 0);
-       if (data->vcc_pin != GPIO_PIN_NONE)
+       if (gpio_is_valid(data->vcc_pin))
                at32_select_gpio(data->vcc_pin, 0);
        /* READY is used as extint, so we can't select it as gpio */
 
@@ -1870,6 +1870,58 @@ fail:
 }
 #endif
 
+/* --------------------------------------------------------------------
+ * NAND Flash / SmartMedia
+ * -------------------------------------------------------------------- */
+static struct resource smc_cs3_resource[] __initdata = {
+       {
+               .start  = 0x0c000000,
+               .end    = 0x0fffffff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = 0xfff03c00,
+               .end    = 0xfff03fff,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+struct platform_device *__init
+at32_add_device_nand(unsigned int id, struct atmel_nand_data *data)
+{
+       struct platform_device *pdev;
+
+       if (id != 0 || !data)
+               return NULL;
+
+       pdev = platform_device_alloc("atmel_nand", id);
+       if (!pdev)
+               goto fail;
+
+       if (platform_device_add_resources(pdev, smc_cs3_resource,
+                               ARRAY_SIZE(smc_cs3_resource)))
+               goto fail;
+
+       if (platform_device_add_data(pdev, data,
+                               sizeof(struct atmel_nand_data)))
+               goto fail;
+
+       set_ebi_sfr_bits(HMATRIX_BIT(CS3A));
+       if (data->enable_pin)
+               at32_select_gpio(data->enable_pin,
+                               AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
+       if (data->rdy_pin)
+               at32_select_gpio(data->rdy_pin, 0);
+       if (data->det_pin)
+               at32_select_gpio(data->det_pin, 0);
+
+       platform_device_add(pdev);
+       return pdev;
+
+fail:
+       platform_device_put(pdev);
+       return NULL;
+}
+
 /* --------------------------------------------------------------------
  * AC97C
  * -------------------------------------------------------------------- */
@@ -1885,9 +1937,11 @@ static struct clk atmel_ac97c0_pclk = {
        .index          = 10,
 };
 
-struct platform_device *__init at32_add_device_ac97c(unsigned int id)
+struct platform_device *__init
+at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data)
 {
        struct platform_device *pdev;
+       struct ac97c_platform_data _data;
 
        if (id != 0)
                return NULL;
@@ -1898,19 +1952,37 @@ struct platform_device *__init at32_add_device_ac97c(unsigned int id)
 
        if (platform_device_add_resources(pdev, atmel_ac97c0_resource,
                                ARRAY_SIZE(atmel_ac97c0_resource)))
-               goto err_add_resources;
+               goto fail;
 
-       select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */
-       select_peripheral(PB(21), PERIPH_B, 0); /* SDO  */
-       select_peripheral(PB(22), PERIPH_B, 0); /* SDI  */
-       select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */
+       if (!data) {
+               data = &_data;
+               memset(data, 0, sizeof(struct ac97c_platform_data));
+               data->reset_pin = GPIO_PIN_NONE;
+       }
+
+       data->dma_rx_periph_id = 3;
+       data->dma_tx_periph_id = 4;
+       data->dma_controller_id = 0;
+
+       if (platform_device_add_data(pdev, data,
+                               sizeof(struct ac97c_platform_data)))
+               goto fail;
+
+       select_peripheral(PB(20), PERIPH_B, 0); /* SDO  */
+       select_peripheral(PB(21), PERIPH_B, 0); /* SYNC */
+       select_peripheral(PB(22), PERIPH_B, 0); /* SCLK */
+       select_peripheral(PB(23), PERIPH_B, 0); /* SDI  */
+
+       /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */
+       if (data->reset_pin != GPIO_PIN_NONE)
+               at32_select_gpio(data->reset_pin, 0);
 
        atmel_ac97c0_pclk.dev = &pdev->dev;
 
        platform_device_add(pdev);
        return pdev;
 
-err_add_resources:
+fail:
        platform_device_put(pdev);
        return NULL;
 }
index fa427ed427874843ea523c30c2c69b46089914be..b2d9bc61a35ca1ca55572bf8aa6636ecde50f9cc 100644 (file)
@@ -278,4 +278,4 @@ static int __init hsmc_init(void)
 {
        return platform_driver_register(&hsmc_driver);
 }
-arch_initcall(hsmc_init);
+core_initcall(hsmc_init);
index 60da03ba7117e0c9a62ad4756ac5fa0aecf7d756..296294f8ed81c42a92963c7794f3a39897e9fa81 100644 (file)
@@ -360,6 +360,8 @@ static int __init pio_probe(struct platform_device *pdev)
        pio->chip.label = pio->name;
        pio->chip.base = pdev->id * 32;
        pio->chip.ngpio = 32;
+       pio->chip.dev = &pdev->dev;
+       pio->chip.owner = THIS_MODULE;
 
        pio->chip.direction_input = direction_input;
        pio->chip.get = gpio_get;
index 3f90a87527bb27fe6ce997c0881a1ecfcbbdcc87..fa92ff6d95f751f341d1ec4b3c1b5f643e2b2e82 100644 (file)
@@ -38,45 +38,6 @@ EXPORT_SYMBOL(empty_zero_page);
  */
 unsigned long mmu_context_cache = NO_CONTEXT;
 
-void show_mem(void)
-{
-       int total = 0, reserved = 0, cached = 0;
-       int slab = 0, free = 0, shared = 0;
-       pg_data_t *pgdat;
-
-       printk("Mem-info:\n");
-       show_free_areas();
-
-       for_each_online_pgdat(pgdat) {
-               struct page *page, *end;
-
-               page = pgdat->node_mem_map;
-               end = page + pgdat->node_spanned_pages;
-
-               do {
-                       total++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (PageSlab(page))
-                               slab++;
-                       else if (!page_count(page))
-                               free++;
-                       else
-                               shared += page_count(page) - 1;
-                       page++;
-               } while (page < end);
-       }
-
-       printk ("%d pages of RAM\n", total);
-       printk ("%d free pages\n", free);
-       printk ("%d reserved pages\n", reserved);
-       printk ("%d slab pages\n", slab);
-       printk ("%d pages shared\n", shared);
-       printk ("%d pages swap cached\n", cached);
-}
-
 /*
  * paging_init() sets up the page tables
  *
@@ -119,8 +80,7 @@ void __init paging_init(void)
                unsigned long zones_size[MAX_NR_ZONES];
                unsigned long low, start_pfn;
 
-               start_pfn = pgdat->bdata->node_boot_start;
-               start_pfn >>= PAGE_SHIFT;
+               start_pfn = pgdat->bdata->node_min_pfn;
                low = pgdat->bdata->node_low_pfn;
 
                memset(zones_size, 0, sizeof(zones_size));
@@ -129,7 +89,7 @@ void __init paging_init(void)
                printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
                       nid, start_pfn, low);
 
-               free_area_init_node(nid, pgdat, zones_size, start_pfn, NULL);
+               free_area_init_node(nid, zones_size, start_pfn, NULL);
 
                printk("Node %u: mem_map starts at %p\n",
                       pgdat->node_id, pgdat->node_mem_map);
index 3437c82434ac9ec189742862d1ce996223feabf4..f03b79f0e0ab0a75f631e7886ad41a7a855c518d 100644 (file)
@@ -6,6 +6,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/vmalloc.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/io.h>
 
index b83b8ef84e91d3f6836f986570ca912e52f6ba77..5a097c46bc4613e6857640cb3bdea0c417ec4ba2 100644 (file)
@@ -234,7 +234,7 @@ config MEM_MT48LC16M16A2TG_75
        bool
        depends on (BFIN533_EZKIT || BFIN561_EZKIT \
                || BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM \
-               || H8606_HVSISTEMAS)
+               || H8606_HVSISTEMAS || BFIN527_BLUETECHNIX_CM)
        default y
 
 config MEM_MT48LC32M8A2_75
@@ -310,25 +310,6 @@ config BFIN_KERNEL_CLOCK
          are also not changed, and the Bootloader does 100% of the hardware
          configuration.
 
-config MEM_SIZE
-       int "SDRAM Memory Size in MBytes"
-       depends on BFIN_KERNEL_CLOCK
-       default 64
-
-config MEM_ADD_WIDTH
-       int "Memory Address Width"
-       depends on BFIN_KERNEL_CLOCK
-       depends on (!BF54x)
-       range 8 11
-       default  9 if BFIN533_EZKIT
-       default  9 if BFIN561_EZKIT
-       default  9 if H8606_HVSISTEMAS
-       default 10 if BFIN527_EZKIT
-       default 10 if BFIN537_STAMP
-       default 11 if BFIN533_STAMP
-       default 10 if PNAV10
-       default 10 if BFIN532_IP0X
-
 config PLL_BYPASS
        bool "Bypass PLL"
        depends on BFIN_KERNEL_CLOCK
@@ -349,8 +330,7 @@ config VCO_MULT
        default "45" if BFIN533_STAMP
        default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM)
        default "22" if BFIN533_BLUETECHNIX_CM
-       default "20" if BFIN537_BLUETECHNIX_CM
-       default "20" if BFIN561_BLUETECHNIX_CM
+       default "20" if (BFIN537_BLUETECHNIX_CM || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
        default "20" if BFIN561_EZKIT
        default "16" if H8606_HVSISTEMAS
        help
@@ -390,7 +370,7 @@ config SCLK_DIV
 
 config MAX_MEM_SIZE
        int "Max SDRAM Memory Size in MBytes"
-       depends on !BFIN_KERNEL_CLOCK && !MPU
+       depends on !MPU
        default 512
        help
          This is the max memory size that the kernel will create CPLB
@@ -748,14 +728,6 @@ config BFIN_WT
 
 endchoice
 
-config L1_MAX_PIECE
-       int "Set the max L1 SRAM pieces"
-       default 16
-       help
-         Set the max memory pieces for the L1 SRAM allocation algorithm.
-         Min value is 16. Max value is 1024.
-
-
 config MPU
        bool "Enable the memory protection unit (EXPERIMENTAL)"
        default n
@@ -899,7 +871,7 @@ config ARCH_SUSPEND_POSSIBLE
        depends on !SMP
 
 choice
-       prompt "Default Power Saving Mode"
+       prompt "Standby Power Saving Mode"
        depends on PM
        default PM_BFIN_SLEEP_DEEPER
 config  PM_BFIN_SLEEP_DEEPER
@@ -918,6 +890,8 @@ config  PM_BFIN_SLEEP_DEEPER
          normal during Sleep Deeper, due to the reduced SCLK frequency.
          When in the sleep mode, system DMA access to L1 memory is not supported.
 
+         If unsure, select "Sleep Deeper".
+
 config  PM_BFIN_SLEEP
        bool "Sleep"
        help
@@ -925,15 +899,17 @@ config  PM_BFIN_SLEEP
          dissipation by disabling the clock to the processor core (CCLK).
          The PLL and system clock (SCLK), however, continue to operate in
          this mode. Typically an external event or RTC activity will wake
-         up the processor. When in the sleep mode,
-         system DMA access to L1 memory is not supported.
+         up the processor. When in the sleep mode, system DMA access to L1
+         memory is not supported.
+
+         If unsure, select "Sleep Deeper".
 endchoice
 
 config PM_WAKEUP_BY_GPIO
-       bool "Cause Wakeup Event by GPIO"
+       bool "Allow Wakeup from Standby by GPIO"
 
 config PM_WAKEUP_GPIO_NUMBER
-       int "Wakeup GPIO number"
+       int "GPIO number"
        range 0 47
        depends on PM_WAKEUP_BY_GPIO
        default 2 if BFIN537_STAMP
@@ -954,6 +930,58 @@ config  PM_WAKEUP_GPIO_POLAR_EDGE_B
        bool "Both EDGE"
 endchoice
 
+comment "Possible Suspend Mem / Hibernate Wake-Up Sources"
+       depends on PM
+
+config PM_BFIN_WAKE_RTC
+       bool "Allow Wake-Up from RESET and on-chip RTC"
+       depends on PM
+       default n
+       help
+         Enable RTC Wake-Up (Voltage Regulator Power-Up)
+
+config PM_BFIN_WAKE_PH6
+       bool "Allow Wake-Up from on-chip PHY or PH6 GP"
+       depends on PM && (BF52x || BF534 || BF536 || BF537)
+       default n
+       help
+         Enable PHY and PH6 GP Wake-Up (Voltage Regulator Power-Up)
+
+config PM_BFIN_WAKE_CAN
+       bool "Allow Wake-Up from on-chip CAN0/1"
+       depends on PM && (BF54x || BF534 || BF536 || BF537)
+       default n
+       help
+         Enable CAN0/1 Wake-Up (Voltage Regulator Power-Up)
+
+config PM_BFIN_WAKE_GP
+       bool "Allow Wake-Up from GPIOs"
+       depends on PM && BF54x
+       default n
+       help
+         Enable General-Purpose Wake-Up (Voltage Regulator Power-Up)
+
+config PM_BFIN_WAKE_USB
+       bool "Allow Wake-Up from on-chip USB"
+       depends on PM && (BF54x || BF52x)
+       default n
+       help
+         Enable USB Wake-Up (Voltage Regulator Power-Up)
+
+config PM_BFIN_WAKE_KEYPAD
+       bool "Allow Wake-Up from on-chip Keypad"
+       depends on PM && BF54x
+       default n
+       help
+         Enable Keypad Wake-Up (Voltage Regulator Power-Up)
+
+config PM_BFIN_WAKE_ROTARY
+       bool "Allow Wake-Up from on-chip Rotary"
+       depends on PM && BF54x
+       default n
+       help
+         Enable Rotary Wake-Up (Voltage Regulator Power-Up)
+
 endmenu
 
 menu "CPU Frequency scaling"
index c61bdebb9974e63a4bf73fcc8f1104588f28b8d9..c468624d55f00614f627814f72e609a3565b34df 100644 (file)
@@ -154,13 +154,6 @@ config EARLY_PRINTK
          all of this lives in the init section and is thrown away after the
          kernel boots completely.
 
-config DUAL_CORE_TEST_MODULE
-       tristate "Dual Core Test Module"
-       depends on (BF561)
-       default n
-       help
-         Say Y here to build-in dual core test module for dual core test.
-
 config CPLB_INFO
        bool "Display the CPLB information"
        help
index 3cbe16caad4b98c8e0b2f376c4e954fe4903cc29..9564731ad3a8788c7690a23fd0a6ca36cfa50cd6 100644 (file)
@@ -6,8 +6,9 @@
 # for more details.
 #
 
-
-CROSS_COMPILE    ?= bfin-uclinux-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE    := bfin-uclinux-
+endif
 LDFLAGS_vmlinux  := -X
 OBJCOPYFLAGS     := -O binary -R .note -R .comment -S
 GZFLAGS          := -9
index 5e6fb9d8e50fb4d9bf4378821f8fb29ab763647c..66854a83c0de648c8b7ad6cf6a36801d9f38d666 100644 (file)
@@ -1,7 +1,6 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.24.7
-# Fri May 16 10:02:29 2008
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -290,7 +289,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_GPTIMERS=y
 CONFIG_BFIN_DMA_5XX=y
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
@@ -430,7 +429,58 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+CONFIG_BFIN_SIR=m
+CONFIG_BFIN_SIR0=y
+CONFIG_SIR_BFIN_DMA=y
+# CONFIG_SIR_BFIN_PIO is not set
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+# CONFIG_KINGSUN_DONGLE is not set
+# CONFIG_KSDAZZLE_DONGLE is not set
+# CONFIG_KS959_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_MCS_FIR is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
 
@@ -689,8 +739,11 @@ CONFIG_BFIN_OTP=y
 # CONFIG_BFIN_SPORT is not set
 # CONFIG_BFIN_TIMER_LATENCY is not set
 # CONFIG_TWI_LCD is not set
-# CONFIG_SIMPLE_GPIO is not set
-# CONFIG_VT is not set
+CONFIG_SIMPLE_GPIO=m
+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
 
 #
@@ -872,18 +925,136 @@ CONFIG_SSB_POSSIBLE=y
 #
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_BFIN_T350MCQB=y
+# CONFIG_FB_BFIN_7393 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_LTV350QV=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+# CONFIG_BACKLIGHT_CORGI is not set
 
 #
 # Display device support
 #
 # CONFIG_DISPLAY_SUPPORT is not set
 
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_BLACKFIN_VGA16 is not set
+CONFIG_LOGO_BLACKFIN_CLUT224=y
+
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# SPI devices
+#
+
+#
+# ALSA Blackfin devices
+#
+# CONFIG_SND_BLACKFIN_AD1836 is not set
+# CONFIG_SND_BLACKFIN_AD1836_TDM is not set
+# CONFIG_SND_BLACKFIN_AD1836_I2S is not set
+# CONFIG_SND_BLACKFIN_AD1836_MULSUB is not set
+# CONFIG_SND_BLACKFIN_AD1836_5P1 is not set
+# CONFIG_SND_BFIN_AD73311 is not set
+# CONFIG_SND_BFIN_AD73322 is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_SOC=m
+CONFIG_SND_BF5XX_SOC=m
+CONFIG_SND_MMAP_SUPPORT=y
+CONFIG_SND_BF5XX_SOC_I2S=m
+CONFIG_SND_BF5XX_SOC_AC97=m
+# CONFIG_SND_BF5XX_SOC_WM8750 is not set
+# CONFIG_SND_BF5XX_SOC_WM8731 is not set
+CONFIG_SND_BF5XX_SOC_SSM2602=m
+CONFIG_SND_BF5XX_SOC_BF5xx=m
+CONFIG_SND_BF5XX_SPORT_NUM=0
+# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set
+
+#
+# SoC Audio support for SuperH
+#
+CONFIG_SND_SOC_SSM2602=m
+# CONFIG_SND_SOC_SSM2602_SPI is not set
+CONFIG_SND_SOC_AD1980=m
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
index 8d817ba01945dc67f2c4400e342419dcfebaa234..6bc11db12690b49077dc5b359dbd99d528494263 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.16
+# Linux kernel version: 2.6.24.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -13,35 +13,34 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -64,32 +63,24 @@ CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_EVENTFD=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_NP2 is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
-
-#
-# Block layer
-#
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
 
 #
 # IO Schedulers
@@ -141,12 +132,12 @@ CONFIG_BF_REV_0_3=y
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
 CONFIG_BF53x=y
-CONFIG_BFIN_SINGLE_CORE=y
 CONFIG_MEM_MT48LC16M16A2TG_75=y
 CONFIG_BFIN533_EZKIT=y
 # CONFIG_BFIN533_STAMP is not set
 # CONFIG_BFIN533_BLUETECHNIX_CM is not set
 # CONFIG_H8606_HVSISTEMAS is not set
+# CONFIG_BFIN532_IP0X is not set
 # CONFIG_GENERIC_BF533_BOARD is not set
 
 #
@@ -189,12 +180,14 @@ CONFIG_WDTIMER=13
 # Board customizations
 #
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
 
 #
 # Clock/PLL Setup
 #
 CONFIG_CLKIN_HZ=27000000
 # CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_MEM_SIZE=512
 CONFIG_MAX_VCO_HZ=750000000
 CONFIG_MIN_VCO_HZ=50000000
 CONFIG_MAX_SCLK_HZ=133333333
@@ -208,13 +201,17 @@ CONFIG_HZ_250=y
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
-# Memory Setup
+# Misc
 #
-CONFIG_MAX_MEM_SIZE=512
-CONFIG_MEM_ADD_WIDTH=9
-CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
 # CONFIG_BFIN_SCRATCH_REG_RETE is not set
 # CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -250,12 +247,14 @@ CONFIG_FLATMEM_MANUAL=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
-CONFIG_LARGE_ALLOCS=y
+CONFIG_VIRT_TO_BUS=y
 # CONFIG_BFIN_GPTIMERS is not set
 CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -293,17 +292,13 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x7BB0
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0xAAC3
+CONFIG_BANK_3=0xAAC2
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
 # CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
 # CONFIG_PCCARD is not set
 
 #
@@ -321,7 +316,9 @@ CONFIG_BINFMT_ZFLAT=y
 CONFIG_PM=y
 # CONFIG_PM_LEGACY is not set
 # CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
 CONFIG_PM_BFIN_SLEEP_DEEPER=y
 # CONFIG_PM_BFIN_SLEEP is not set
 # CONFIG_PM_WAKEUP_BY_GPIO is not set
@@ -367,6 +364,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -393,10 +391,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 # CONFIG_NET_SCHED is not set
 
 #
@@ -428,6 +422,7 @@ CONFIG_IRDA_CACHE_LAST_LSAP=y
 # SIR device drivers
 #
 CONFIG_IRTTY_SIR=m
+# CONFIG_BFIN_SIR is not set
 
 #
 # Dongle support
@@ -457,6 +452,7 @@ CONFIG_IRTTY_SIR=m
 # CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
 # CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -465,14 +461,11 @@ CONFIG_IRTTY_SIR=m
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 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 is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
@@ -492,6 +485,7 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -548,20 +542,8 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
-
-#
-# Parallel port support
-#
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -571,10 +553,8 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_IDE is not set
 
 #
@@ -582,32 +562,29 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
 # CONFIG_MD is not set
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_VETH is not set
 # CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_SMC91X=y
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -624,15 +601,7 @@ CONFIG_NETDEV_10000=y
 # 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
 
 #
@@ -647,7 +616,6 @@ CONFIG_INPUT=m
 #
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_EVBUG is not set
 
@@ -672,13 +640,12 @@ CONFIG_INPUT_EVDEV=m
 #
 # CONFIG_AD9960 is not set
 # CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PFLAGS is not set
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
 # CONFIG_BF5xx_PPI is not set
 CONFIG_BFIN_SPORT=y
 # CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_AD5304 is not set
+CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
@@ -706,28 +673,11 @@ CONFIG_UNIX98_PTYS=y
 # CAN, the car bus and industrial fieldbus
 #
 # CONFIG_CAN4LINUX is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_BFIN_WDT=y
 CONFIG_HW_RANDOM=y
 # CONFIG_GEN_RTC is not set
-CONFIG_BLACKFIN_DPMC=y
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 
@@ -748,22 +698,37 @@ CONFIG_SPI_BFIN=y
 #
 # CONFIG_SPI_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
-
-#
-# Dallas's 1-wire bus
-#
+# CONFIG_SPI_TLE62X0 is not set
 # CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -780,72 +745,27 @@ CONFIG_DAB=y
 #
 # Graphics support
 #
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Display device support
 #
 # CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-# CONFIG_FB is not set
 
 #
 # Sound
 #
 # CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
+CONFIG_HID_SUPPORT=y
 CONFIG_HID=m
 # CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-# CONFIG_USB is not set
-
-#
-# Enable Host or Gadget support to see Inventra options
-#
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
 # 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_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -861,10 +781,6 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
 # CONFIG_RTC_DRV_TEST is not set
 
-#
-# I2C RTC drivers
-#
-
 #
 # SPI RTC drivers
 #
@@ -875,8 +791,10 @@ CONFIG_RTC_INTF_DEV=y
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
@@ -885,22 +803,9 @@ CONFIG_RTC_INTF_DEV=y
 CONFIG_RTC_DRV_BFIN=y
 
 #
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
+# Userspace I/O
 #
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_UIO is not set
 
 #
 # File systems
@@ -945,7 +850,6 @@ CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -971,10 +875,12 @@ CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
 # 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_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
@@ -983,10 +889,7 @@ CONFIG_JFFS2_RTIME=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
@@ -1006,17 +909,12 @@ CONFIG_SMB_FS=m
 # 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=m
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
@@ -1057,21 +955,16 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -1079,6 +972,7 @@ CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
@@ -1098,11 +992,7 @@ CONFIG_ACCESS_CHECK=y
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=m
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITY_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
 
 #
@@ -1113,6 +1003,7 @@ CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
index 20d598d17bd14b8f6d0401ff217163848aae4bd0..d77d991a1f619877e1ea25ddf32ebad9f10fcf8e 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.16
+# Linux kernel version: 2.6.24.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -13,35 +13,34 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -64,32 +63,24 @@ CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_EVENTFD=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_NP2 is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
-
-#
-# Block layer
-#
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
 
 #
 # IO Schedulers
@@ -141,12 +132,12 @@ CONFIG_BF_REV_0_3=y
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
 CONFIG_BF53x=y
-CONFIG_BFIN_SINGLE_CORE=y
 CONFIG_MEM_MT48LC64M4A2FB_7E=y
 # CONFIG_BFIN533_EZKIT is not set
 CONFIG_BFIN533_STAMP=y
 # CONFIG_BFIN533_BLUETECHNIX_CM is not set
 # CONFIG_H8606_HVSISTEMAS is not set
+# CONFIG_BFIN532_IP0X is not set
 # CONFIG_GENERIC_BF533_BOARD is not set
 
 #
@@ -189,12 +180,14 @@ CONFIG_WDTIMER=13
 # Board customizations
 #
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
 
 #
 # Clock/PLL Setup
 #
 CONFIG_CLKIN_HZ=11059200
 # CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_MEM_SIZE=512
 CONFIG_MAX_VCO_HZ=750000000
 CONFIG_MIN_VCO_HZ=50000000
 CONFIG_MAX_SCLK_HZ=133333333
@@ -208,14 +201,17 @@ CONFIG_HZ_250=y
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
-# Memory Setup
+# Misc
 #
-CONFIG_MAX_MEM_SIZE=512
-CONFIG_MEM_ADD_WIDTH=11
-CONFIG_ENET_FLASH_PIN=0
-CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
 # CONFIG_BFIN_SCRATCH_REG_RETE is not set
 # CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -251,12 +247,14 @@ CONFIG_FLATMEM_MANUAL=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
-CONFIG_LARGE_ALLOCS=y
+CONFIG_VIRT_TO_BUS=y
 # CONFIG_BFIN_GPTIMERS is not set
 CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -294,17 +292,13 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x7BB0
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0xAAC3
+CONFIG_BANK_3=0xAAC2
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
 # CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
 # CONFIG_PCCARD is not set
 
 #
@@ -322,7 +316,9 @@ CONFIG_BINFMT_ZFLAT=y
 CONFIG_PM=y
 # CONFIG_PM_LEGACY is not set
 # CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
 CONFIG_PM_BFIN_SLEEP_DEEPER=y
 # CONFIG_PM_BFIN_SLEEP is not set
 # CONFIG_PM_WAKEUP_BY_GPIO is not set
@@ -368,6 +364,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -394,10 +391,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 # CONFIG_NET_SCHED is not set
 
 #
@@ -429,6 +422,9 @@ CONFIG_IRDA_CACHE_LAST_LSAP=y
 # SIR device drivers
 #
 CONFIG_IRTTY_SIR=m
+CONFIG_BFIN_SIR=m
+CONFIG_SIR_BFIN_DMA=y
+# CONFIG_SIR_BFIN_PIO is not set
 
 #
 # Dongle support
@@ -458,6 +454,7 @@ CONFIG_IRTTY_SIR=m
 # CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
 # CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -466,14 +463,11 @@ CONFIG_IRTTY_SIR=m
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 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 is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
@@ -493,6 +487,7 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -524,11 +519,7 @@ CONFIG_MTD_ROM=m
 #
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 # CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_BF5xx=m
-CONFIG_BFIN_FLASH_BANK_0=0x7BB0
-CONFIG_BFIN_FLASH_BANK_1=0x7BB0
-CONFIG_BFIN_FLASH_BANK_2=0x7BB0
-CONFIG_BFIN_FLASH_BANK_3=0x7BB0
+CONFIG_MTD_BFIN_ASYNC=m
 # CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
@@ -555,20 +546,8 @@ CONFIG_BFIN_FLASH_BANK_3=0x7BB0
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
-
-#
-# Parallel port support
-#
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -578,10 +557,8 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_IDE is not set
 
 #
@@ -589,32 +566,29 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
 # CONFIG_MD is not set
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_VETH is not set
 # CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_SMC91X=y
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -631,15 +605,7 @@ CONFIG_NETDEV_10000=y
 # 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
 
 #
@@ -654,7 +620,6 @@ CONFIG_INPUT=y
 #
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_EVBUG is not set
 
@@ -667,14 +632,8 @@ CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_ATI_REMOTE is not set
-# CONFIG_INPUT_ATI_REMOTE2 is not set
-# CONFIG_INPUT_KEYSPAN_REMOTE is not set
-# CONFIG_INPUT_POWERMATE is not set
-# CONFIG_INPUT_YEALINK is not set
 # CONFIG_INPUT_UINPUT is not set
 CONFIG_TWI_KEYPAD=m
-CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=39
 
 #
 # Hardware I/O ports
@@ -687,15 +646,13 @@ CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=39
 #
 # CONFIG_AD9960 is not set
 # CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PFLAGS is not set
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
 # CONFIG_BF5xx_PPI is not set
 CONFIG_BFIN_SPORT=y
 # CONFIG_BFIN_TIMER_LATENCY is not set
 CONFIG_TWI_LCD=m
-CONFIG_TWI_LCD_SLAVE_ADDR=34
-# CONFIG_AD5304 is not set
+CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
@@ -723,28 +680,11 @@ CONFIG_UNIX98_PTYS=y
 # CAN, the car bus and industrial fieldbus
 #
 # CONFIG_CAN4LINUX is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_BFIN_WDT=y
 CONFIG_HW_RANDOM=y
 # CONFIG_GEN_RTC is not set
-CONFIG_BLACKFIN_DPMC=y
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=m
 CONFIG_I2C_BOARDINFO=y
@@ -764,6 +704,7 @@ CONFIG_I2C_ALGOBIT=m
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
 # CONFIG_I2C_STUB is not set
 
 #
@@ -771,14 +712,15 @@ CONFIG_I2C_ALGOBIT=m
 #
 # CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
 # CONFIG_SENSORS_AD5252 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8575 is not set
-# CONFIG_SENSORS_PCA9543 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -801,14 +743,11 @@ CONFIG_SPI_BFIN=y
 #
 # CONFIG_SPI_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
-
-#
-# Dallas's 1-wire bus
-#
+# CONFIG_SPI_TLE62X0 is not set
 # CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
@@ -816,12 +755,12 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ADT7470 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_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -836,13 +775,16 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
@@ -852,6 +794,20 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -863,24 +819,20 @@ CONFIG_HWMON=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=m
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB_DDC is not set
 CONFIG_FB_CFB_FILLRECT=m
 CONFIG_FB_CFB_COPYAREA=m
 CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
 # CONFIG_FB_SYS_FILLRECT is not set
 # CONFIG_FB_SYS_COPYAREA is not set
 # CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -895,7 +847,7 @@ CONFIG_FB_DEFERRED_IO=y
 #
 # Frame buffer hardware drivers
 #
-CONFIG_FB_BFIN_7171=m
+# CONFIG_FB_BFIN_T350MCQB is not set
 CONFIG_FB_BFIN_7393=m
 CONFIG_NTSC=y
 # CONFIG_PAL is not set
@@ -905,9 +857,14 @@ CONFIG_NTSC=y
 # CONFIG_PAL_YCBCR is not set
 CONFIG_ADV7393_1XMEM=y
 # CONFIG_ADV7393_2XMEM is not set
-# CONFIG_FB_BFIN_T350MCQB is not set
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_LOGO is not set
 
 #
@@ -940,6 +897,10 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
 
+#
+# SPI devices
+#
+
 #
 # ALSA Blackfin devices
 #
@@ -953,69 +914,43 @@ CONFIG_SND_BLACKFIN_SPI_PFBIT=4
 CONFIG_SND_BFIN_AD73311=m
 CONFIG_SND_BFIN_SPORT=0
 CONFIG_SND_BFIN_AD73311_SE=4
+CONFIG_SND_BFIN_AD73322=m
+CONFIG_SND_BFIN_AD73322_SPORT0_SE=10
+CONFIG_SND_BFIN_AD73322_SPORT1_SE=14
+CONFIG_SND_BFIN_AD73322_RESET=12
 
 #
 # System on Chip audio support
 #
-# CONFIG_SND_SOC is not set
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_SOC=m
+CONFIG_SND_BF5XX_SOC=m
+CONFIG_SND_MMAP_SUPPORT=y
+CONFIG_SND_BF5XX_SOC_AC97=m
+# CONFIG_SND_BF5XX_SOC_WM8750 is not set
+# CONFIG_SND_BF5XX_SOC_WM8731 is not set
+# CONFIG_SND_BF5XX_SOC_SSM2602 is not set
+CONFIG_SND_BF5XX_SOC_BF5xx=m
+CONFIG_SND_BF5XX_SPORT_NUM=0
+# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set
 
 #
-# Open Sound System
+# SoC Audio support for SuperH
 #
-# CONFIG_SOUND_PRIME is not set
+CONFIG_SND_SOC_AD1980=m
 
 #
-# HID Devices
+# Open Sound System
 #
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-# CONFIG_USB is not set
-
-#
-# Enable Host or Gadget support to see Inventra options
-#
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
 # 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_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1035,6 +970,7 @@ CONFIG_RTC_INTF_DEV=y
 # I2C RTC drivers
 #
 # CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
 # CONFIG_RTC_DRV_MAX6900 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
@@ -1042,6 +978,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
 
 #
 # SPI RTC drivers
@@ -1053,8 +990,10 @@ CONFIG_RTC_INTF_DEV=y
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
@@ -1063,22 +1002,9 @@ CONFIG_RTC_INTF_DEV=y
 CONFIG_RTC_DRV_BFIN=y
 
 #
-# DMA Engine support
+# Userspace I/O
 #
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_UIO is not set
 
 #
 # File systems
@@ -1123,7 +1049,6 @@ CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1149,10 +1074,12 @@ CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
 # 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_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
@@ -1161,10 +1088,7 @@ CONFIG_JFFS2_RTIME=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
@@ -1184,17 +1108,12 @@ CONFIG_SMB_FS=m
 # 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=m
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
@@ -1235,21 +1154,16 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -1257,6 +1171,7 @@ CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
@@ -1276,11 +1191,7 @@ CONFIG_ACCESS_CHECK=y
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=m
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITY_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
 
 #
@@ -1291,6 +1202,7 @@ CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
index b5189c8ba263a3755ce725445727b230ec4a195c..5fd7c4b143df56bfd3f7bb8b3fed4a75e025ab1c 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.16
+# Linux kernel version: 2.6.24.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -13,35 +13,34 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -64,32 +63,24 @@ CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_EVENTFD=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_NP2 is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
-
-#
-# Block layer
-#
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
 
 #
 # IO Schedulers
@@ -141,7 +132,6 @@ CONFIG_BF_REV_0_2=y
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
 CONFIG_BF53x=y
-CONFIG_BFIN_SINGLE_CORE=y
 CONFIG_MEM_MT48LC32M8A2_75=y
 CONFIG_IRQ_PLL_WAKEUP=7
 CONFIG_IRQ_RTC=8
@@ -197,12 +187,14 @@ CONFIG_IRQ_PROG_INTA=12
 # Board customizations
 #
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
 
 #
 # Clock/PLL Setup
 #
 CONFIG_CLKIN_HZ=25000000
 # CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_MEM_SIZE=512
 CONFIG_MAX_VCO_HZ=600000000
 CONFIG_MIN_VCO_HZ=50000000
 CONFIG_MAX_SCLK_HZ=133333333
@@ -216,13 +208,17 @@ CONFIG_HZ_250=y
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
-# Memory Setup
+# Misc
 #
-CONFIG_MAX_MEM_SIZE=512
-CONFIG_MEM_ADD_WIDTH=10
-CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
 # CONFIG_BFIN_SCRATCH_REG_RETE is not set
 # CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -258,12 +254,14 @@ CONFIG_FLATMEM_MANUAL=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
-CONFIG_LARGE_ALLOCS=y
+CONFIG_VIRT_TO_BUS=y
 # CONFIG_BFIN_GPTIMERS is not set
 CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -301,17 +299,13 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x7BB0
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0x99B3
+CONFIG_BANK_3=0x99B2
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
 # CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
 # CONFIG_PCCARD is not set
 
 #
@@ -329,7 +323,9 @@ CONFIG_BINFMT_ZFLAT=y
 CONFIG_PM=y
 # CONFIG_PM_LEGACY is not set
 # CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
 CONFIG_PM_BFIN_SLEEP_DEEPER=y
 # CONFIG_PM_BFIN_SLEEP is not set
 # CONFIG_PM_WAKEUP_BY_GPIO is not set
@@ -375,6 +371,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -401,10 +398,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 # CONFIG_NET_SCHED is not set
 
 #
@@ -436,6 +429,10 @@ CONFIG_IRDA_CACHE_LAST_LSAP=y
 # SIR device drivers
 #
 CONFIG_IRTTY_SIR=m
+CONFIG_BFIN_SIR=m
+CONFIG_BFIN_SIR1=y
+CONFIG_SIR_BFIN_DMA=y
+# CONFIG_SIR_BFIN_PIO is not set
 
 #
 # Dongle support
@@ -465,6 +462,7 @@ CONFIG_IRTTY_SIR=m
 # CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
 # CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -473,14 +471,11 @@ CONFIG_IRTTY_SIR=m
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 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 is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
@@ -500,6 +495,7 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -572,20 +568,8 @@ CONFIG_MTD_NAND_IDS=m
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
-
-#
-# Parallel port support
-#
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -595,10 +579,8 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_IDE is not set
 
 #
@@ -606,22 +588,18 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
 # CONFIG_MD is not set
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_VETH is not set
 CONFIG_PHYLIB=y
 
 #
@@ -635,21 +613,24 @@ CONFIG_PHYLIB=y
 # CONFIG_VITESSE_PHY is not set
 CONFIG_SMSC_PHY=y
 # CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
 # CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_SMC91X is not set
 CONFIG_BFIN_MAC=y
 CONFIG_BFIN_MAC_USE_L1=y
 CONFIG_BFIN_TX_DESC_NUM=10
 CONFIG_BFIN_RX_DESC_NUM=20
 # CONFIG_BFIN_MAC_RMII is not set
+# CONFIG_SMC91X is not set
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -666,15 +647,7 @@ CONFIG_NETDEV_10000=y
 # 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
 
 #
@@ -689,7 +662,6 @@ CONFIG_INPUT=y
 #
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_EVBUG is not set
 
@@ -702,14 +674,8 @@ CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_ATI_REMOTE is not set
-# CONFIG_INPUT_ATI_REMOTE2 is not set
-# CONFIG_INPUT_KEYSPAN_REMOTE is not set
-# CONFIG_INPUT_POWERMATE is not set
-# CONFIG_INPUT_YEALINK is not set
 # CONFIG_INPUT_UINPUT is not set
 CONFIG_TWI_KEYPAD=m
-CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72
 
 #
 # Hardware I/O ports
@@ -722,15 +688,13 @@ CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72
 #
 # CONFIG_AD9960 is not set
 # CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PFLAGS is not set
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
 # CONFIG_BF5xx_PPI is not set
 CONFIG_BFIN_SPORT=y
 # CONFIG_BFIN_TIMER_LATENCY is not set
 CONFIG_TWI_LCD=m
-CONFIG_TWI_LCD_SLAVE_ADDR=34
-# CONFIG_AD5304 is not set
+CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
@@ -766,28 +730,11 @@ CONFIG_CAN4LINUX=y
 # CONFIG_CAN_MCF5282 is not set
 # CONFIG_CAN_UNCTWINCAN is not set
 CONFIG_CAN_BLACKFIN=m
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_BFIN_WDT=y
 CONFIG_HW_RANDOM=y
 # CONFIG_GEN_RTC is not set
-CONFIG_BLACKFIN_DPMC=y
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=m
 CONFIG_I2C_BOARDINFO=y
@@ -809,6 +756,7 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
 # CONFIG_I2C_STUB is not set
 
 #
@@ -816,14 +764,15 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
 #
 # CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
 CONFIG_SENSORS_AD5252=m
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8575 is not set
-# CONFIG_SENSORS_PCA9543 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -846,14 +795,11 @@ CONFIG_SPI_BFIN=y
 #
 # CONFIG_SPI_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
-
-#
-# Dallas's 1-wire bus
-#
+# CONFIG_SPI_TLE62X0 is not set
 # CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
@@ -861,12 +807,12 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ADT7470 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_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -881,13 +827,16 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
@@ -897,6 +846,20 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -913,21 +876,15 @@ CONFIG_DAB=y
 #
 # Graphics support
 #
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=m
-CONFIG_LCD_CLASS_DEVICE=m
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=m
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB_DDC is not set
 CONFIG_FB_CFB_FILLRECT=m
 CONFIG_FB_CFB_COPYAREA=m
 CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
 # CONFIG_FB_SYS_FILLRECT is not set
 # CONFIG_FB_SYS_COPYAREA is not set
 # CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -942,7 +899,8 @@ CONFIG_FB_DEFERRED_IO=y
 #
 # Frame buffer hardware drivers
 #
-CONFIG_FB_BFIN_7171=m
+# CONFIG_FB_HITACHI_TX09 is not set
+# CONFIG_FB_BFIN_T350MCQB is not set
 CONFIG_FB_BFIN_7393=m
 CONFIG_NTSC=y
 # CONFIG_PAL is not set
@@ -956,10 +914,18 @@ CONFIG_FB_BF537_LQ035=m
 CONFIG_LQ035_SLAVE_ADDR=0x58
 # CONFIG_FB_BFIN_LANDSCAPE is not set
 # CONFIG_FB_BFIN_BGR is not set
-# CONFIG_FB_BFIN_T350MCQB is not set
-# CONFIG_FB_HITACHI_TX09 is not set
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_LTV350QV is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_CORGI=m
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_LOGO is not set
 
 #
@@ -992,6 +958,10 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
 
+#
+# SPI devices
+#
+
 #
 # ALSA Blackfin devices
 #
@@ -1005,6 +975,10 @@ CONFIG_SND_BLACKFIN_SPI_PFBIT=4
 CONFIG_SND_BFIN_AD73311=m
 CONFIG_SND_BFIN_SPORT=0
 CONFIG_SND_BFIN_AD73311_SE=4
+CONFIG_SND_BFIN_AD73322=m
+CONFIG_SND_BFIN_AD73322_SPORT0_SE=10
+CONFIG_SND_BFIN_AD73322_SPORT1_SE=14
+CONFIG_SND_BFIN_AD73322_RESET=12
 
 #
 # System on Chip audio support
@@ -1016,9 +990,14 @@ CONFIG_SND_MMAP_SUPPORT=y
 CONFIG_SND_BF5XX_SOC_AC97=m
 # CONFIG_SND_BF5XX_SOC_WM8750 is not set
 # CONFIG_SND_BF5XX_SOC_WM8731 is not set
+# CONFIG_SND_BF5XX_SOC_SSM2602 is not set
 CONFIG_SND_BF5XX_SOC_BF5xx=m
 CONFIG_SND_BF5XX_SPORT_NUM=0
 # CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set
+
+#
+# SoC Audio support for SuperH
+#
 CONFIG_SND_SOC_AD1980=m
 
 #
@@ -1026,59 +1005,18 @@ CONFIG_SND_SOC_AD1980=m
 #
 # CONFIG_SOUND_PRIME is not set
 CONFIG_AC97_BUS=m
-
-#
-# HID Devices
-#
+CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-# CONFIG_USB is not set
-
-#
-# Enable Host or Gadget support to see Inventra options
-#
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_NO_DUMMY_DELAY is not set
+# CONFIG_DUMMY_DELAY_BANK0 is not set
+# CONFIG_DUMMY_DELAY_BANK1 is not set
+# CONFIG_DUMMY_DELAY_BANK2 is not set
+# CONFIG_DUMMY_DELAY_BANK3 is not set
 # 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_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1098,6 +1036,7 @@ CONFIG_RTC_INTF_DEV=y
 # I2C RTC drivers
 #
 # CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
 # CONFIG_RTC_DRV_MAX6900 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
@@ -1105,6 +1044,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
 
 #
 # SPI RTC drivers
@@ -1116,8 +1056,10 @@ CONFIG_RTC_INTF_DEV=y
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
@@ -1126,22 +1068,9 @@ CONFIG_RTC_INTF_DEV=y
 CONFIG_RTC_DRV_BFIN=y
 
 #
-# DMA Engine support
+# Userspace I/O
 #
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_UIO is not set
 
 #
 # File systems
@@ -1186,7 +1115,6 @@ CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1212,10 +1140,12 @@ CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
 # 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_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
@@ -1224,10 +1154,7 @@ CONFIG_JFFS2_RTIME=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
@@ -1247,17 +1174,12 @@ CONFIG_SMB_FS=m
 # 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=m
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
@@ -1298,21 +1220,16 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -1320,6 +1237,7 @@ CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
@@ -1339,11 +1257,7 @@ CONFIG_ACCESS_CHECK=y
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=m
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITY_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
 
 #
@@ -1354,6 +1268,7 @@ CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
index 1ff2ff4b49aa14aa6fc536eb00f1d8836385b10b..390669e8668e0695fb41da67baf77bcbe205410d 100644 (file)
@@ -365,7 +365,7 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x5554
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0x99B3
+CONFIG_BANK_3=0x99B2
 CONFIG_EBIU_MBSCTLVAL=0x0
 CONFIG_EBIU_MODEVAL=0x1
 CONFIG_EBIU_FCTLVAL=0x6
@@ -468,7 +468,60 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+CONFIG_BFIN_SIR=m
+# CONFIG_BFIN_SIR0 is not set
+# CONFIG_BFIN_SIR2 is not set
+CONFIG_BFIN_SIR3=y
+CONFIG_SIR_BFIN_DMA=y
+# CONFIG_SIR_BFIN_PIO is not set
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+# CONFIG_KINGSUN_DONGLE is not set
+# CONFIG_KSDAZZLE_DONGLE is not set
+# CONFIG_KS959_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_MCS_FIR is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
 
@@ -575,6 +628,7 @@ CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_BF5XX=y
 CONFIG_MTD_NAND_BF5XX_HWECC=y
+# CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC is not set
 # CONFIG_MTD_NAND_DISKONCHIP is not set
 # CONFIG_MTD_NAND_NANDSIM is not set
 # CONFIG_MTD_NAND_PLATFORM is not set
@@ -766,7 +820,7 @@ CONFIG_BFIN_OTP=y
 # CONFIG_BFIN_SPORT is not set
 # CONFIG_BFIN_TIMER_LATENCY is not set
 # CONFIG_TWI_LCD is not set
-# CONFIG_SIMPLE_GPIO is not set
+CONFIG_SIMPLE_GPIO=m
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
@@ -1071,6 +1125,7 @@ CONFIG_SND_BF5XX_SOC_AC97=y
 CONFIG_SND_BF5XX_SOC_BF548_EZKIT=y
 # CONFIG_SND_BF5XX_SOC_WM8750 is not set
 # CONFIG_SND_BF5XX_SOC_WM8731 is not set
+# CONFIG_SND_BF5XX_SOC_SSM2602 is not set
 CONFIG_SND_BF5XX_SPORT_NUM=0
 CONFIG_SND_BF5XX_HAVE_COLD_RESET=y
 CONFIG_SND_BF5XX_RESET_GPIO_NUM=19
@@ -1133,7 +1188,7 @@ CONFIG_USB_MUSB_HOST=y
 # CONFIG_USB_MUSB_OTG is not set
 CONFIG_USB_MUSB_HDRC_HCD=y
 # CONFIG_MUSB_PIO_ONLY is not set
-# CONFIG_USB_INVENTRA_DMA is not set
+CONFIG_USB_INVENTRA_DMA=y
 # CONFIG_USB_TI_CPPI_DMA is not set
 CONFIG_USB_MUSB_LOGLEVEL=0
 
@@ -1312,7 +1367,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
index b4a20c8908165000f8375c97214dc67b1c260daa..976a4d7ba175ee955270d9170023d02525d3a19b 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.16
+# Linux kernel version: 2.6.24.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -13,35 +13,34 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -64,32 +63,24 @@ CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_EVENTFD=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_NP2 is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
-
-#
-# Block layer
-#
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
 
 #
 # IO Schedulers
@@ -140,7 +131,6 @@ CONFIG_BF_REV_0_3=y
 # CONFIG_BF_REV_0_5 is not set
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
-CONFIG_BFIN_DUAL_CORE=y
 CONFIG_MEM_MT48LC16M16A2TG_75=y
 CONFIG_IRQ_PLL_WAKEUP=7
 CONFIG_IRQ_SPORT0_ERROR=7
@@ -233,12 +223,14 @@ CONFIG_IRQ_WDTIMER=13
 # Board customizations
 #
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
 
 #
 # Clock/PLL Setup
 #
 CONFIG_CLKIN_HZ=30000000
 # CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_MEM_SIZE=512
 CONFIG_MAX_VCO_HZ=600000000
 CONFIG_MIN_VCO_HZ=50000000
 CONFIG_MAX_SCLK_HZ=133333333
@@ -252,13 +244,17 @@ CONFIG_HZ_250=y
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
-# Memory Setup
+# Misc
 #
-CONFIG_MAX_MEM_SIZE=512
-CONFIG_MEM_ADD_WIDTH=9
-CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
 # CONFIG_BFIN_SCRATCH_REG_RETE is not set
 # CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -294,12 +290,14 @@ CONFIG_FLATMEM_MANUAL=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
-CONFIG_LARGE_ALLOCS=y
+CONFIG_VIRT_TO_BUS=y
 # CONFIG_BFIN_GPTIMERS is not set
 CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -341,17 +339,13 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x7BB0
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0xAAC3
+CONFIG_BANK_3=0xAAC2
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
 # CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
 # CONFIG_PCCARD is not set
 
 #
@@ -367,8 +361,14 @@ CONFIG_BINFMT_ZFLAT=y
 # Power management options
 #
 # CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
 # CONFIG_PM_WAKEUP_BY_GPIO is not set
 
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
 #
 # Networking
 #
@@ -405,6 +405,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -431,10 +432,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 # CONFIG_NET_SCHED is not set
 
 #
@@ -466,6 +463,7 @@ CONFIG_IRDA_CACHE_LAST_LSAP=y
 # SIR device drivers
 #
 CONFIG_IRTTY_SIR=m
+# CONFIG_BFIN_SIR is not set
 
 #
 # Dongle support
@@ -495,6 +493,7 @@ CONFIG_IRTTY_SIR=m
 # CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
 # CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -503,14 +502,11 @@ CONFIG_IRTTY_SIR=m
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 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 is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
@@ -530,6 +526,7 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -590,20 +587,8 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
-
-#
-# Parallel port support
-#
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -613,10 +598,8 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_IDE is not set
 
 #
@@ -624,32 +607,29 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
 # CONFIG_MD is not set
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_VETH is not set
 # CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_SMC91X=y
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -666,15 +646,7 @@ CONFIG_NETDEV_10000=y
 # 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
 
 #
@@ -689,7 +661,6 @@ CONFIG_INPUT=m
 #
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_EVBUG is not set
 
@@ -714,13 +685,12 @@ CONFIG_INPUT_EVDEV=m
 #
 # CONFIG_AD9960 is not set
 # CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PFLAGS is not set
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
 # CONFIG_BF5xx_PPI is not set
 # CONFIG_BFIN_SPORT is not set
 # CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_AD5304 is not set
+CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
@@ -748,27 +718,11 @@ CONFIG_UNIX98_PTYS=y
 # CAN, the car bus and industrial fieldbus
 #
 # CONFIG_CAN4LINUX is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_BFIN_WDT=y
 CONFIG_HW_RANDOM=y
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 
@@ -789,22 +743,37 @@ CONFIG_SPI_BFIN=y
 #
 # CONFIG_SPI_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
-
-#
-# Dallas's 1-wire bus
-#
+# CONFIG_SPI_TLE62X0 is not set
 # CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -821,91 +790,33 @@ CONFIG_DAB=y
 #
 # Graphics support
 #
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Display device support
 #
 # CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-# CONFIG_FB is not set
 
 #
 # Sound
 #
 # CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
+CONFIG_HID_SUPPORT=y
 CONFIG_HID=m
 # CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-# CONFIG_USB is not set
-
-#
-# Enable Host or Gadget support to see Inventra options
-#
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
 # 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
+# Userspace I/O
 #
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_UIO is not set
 
 #
 # File systems
@@ -950,7 +861,6 @@ CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -976,10 +886,12 @@ CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
 # 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_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
@@ -988,10 +900,7 @@ CONFIG_JFFS2_RTIME=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
@@ -1011,17 +920,12 @@ CONFIG_SMB_FS=m
 # 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=m
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
@@ -1062,21 +966,16 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -1084,6 +983,7 @@ CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
@@ -1104,11 +1004,7 @@ CONFIG_ACCESS_CHECK=y
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=m
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITY_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
 
 #
@@ -1119,6 +1015,7 @@ CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
new file mode 100644 (file)
index 0000000..0799aa9
--- /dev/null
@@ -0,0 +1,1185 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.24.7
+# Fri Jul 18 18:00:41 2008
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=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=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+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
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+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"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+CONFIG_BF527=y
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+CONFIG_BF_REV_0_1=y
+# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF52x=y
+CONFIG_MEM_MT48LC16M16A2TG_75=y
+# CONFIG_BFIN527_EZKIT is not set
+CONFIG_BFIN527_BLUETECHNIX_CM=y
+
+#
+# BF527 Specific Configuration
+#
+
+#
+# Alternative Multiplexing Scheme
+#
+# CONFIG_BF527_SPORT0_PORTF is not set
+CONFIG_BF527_SPORT0_PORTG=y
+CONFIG_BF527_SPORT0_TSCLK_PG10=y
+# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
+CONFIG_BF527_UART1_PORTF=y
+# CONFIG_BF527_UART1_PORTG is not set
+# CONFIG_BF527_NAND_D_PORTF is not set
+CONFIG_BF527_NAND_D_PORTH=y
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_DMA0_ERROR=7
+CONFIG_IRQ_DMAR0_BLK=7
+CONFIG_IRQ_DMAR1_BLK=7
+CONFIG_IRQ_DMAR0_OVR=7
+CONFIG_IRQ_DMAR1_OVR=7
+CONFIG_IRQ_PPI_ERROR=7
+CONFIG_IRQ_MAC_ERROR=7
+CONFIG_IRQ_SPORT0_ERROR=7
+CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_UART0_ERROR=7
+CONFIG_IRQ_UART1_ERROR=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_OPTSEC=11
+CONFIG_IRQ_CNT=11
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_PORTH_INTA=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_PORTH_INTB=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PORTG_INTA=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_PORTF_INTA=13
+CONFIG_IRQ_PORTF_INTB=13
+CONFIG_IRQ_SPI_ERROR=7
+CONFIG_IRQ_NFC_ERROR=7
+CONFIG_IRQ_HDMA_ERROR=7
+CONFIG_IRQ_HDMA=7
+CONFIG_IRQ_USB_EINT=10
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=25000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_MEM_SIZE=512
+CONFIG_MAX_VCO_HZ=600000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Misc
+#
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+# CONFIG_SCHEDULE_L1 is not set
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+# CONFIG_MEMSET_L1 is not set
+# CONFIG_MEMCPY_L1 is not set
+# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL 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_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_BFIN_GPTIMERS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_4M is not set
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+# CONFIG_BFIN_WB is not set
+CONFIG_BFIN_WT=y
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x5554
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0xFFC0
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
+# CONFIG_PM_BFIN_SLEEP_DEEPER is not set
+# CONFIG_PM_BFIN_SLEEP is not set
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+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=m
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# 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 is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 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
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_MAC_USE_L1=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+CONFIG_BFIN_MAC_RMII=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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_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
+# CONFIG_ISDN is not set
+# 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_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_OTP=y
+# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_TWI_LCD is not set
+CONFIG_SIMPLE_GPIO=m
+# 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_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# 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_BLACKFIN_TWI=m
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_AD5252 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 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=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S 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_LM70 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_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 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
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+CONFIG_USB_OTG_BLACKLIST_HUB=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# Blackfin high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+CONFIG_MUSB_PIO_ONLY=y
+CONFIG_USB_MUSB_LOGLEVEL=0
+
+#
+# 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_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 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_ADUTUX 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_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY 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_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# 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_YAFFS_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
+CONFIG_NETWORK_FILESYSTEMS=y
+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 is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_BIND34 is not set
+# 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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# 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 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
+# CONFIG_DLM is not set
+# CONFIG_INSTRUMENTATION is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_DEBUG_MMRS=y
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CPLB_INFO is not set
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_CAPABILITIES is not set
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 560890fe0d30010c35769ea90cce9852ebd89ee7..09deea44480b43d6d830d19d2c8c317625a7b40f 100644 (file)
@@ -39,7 +39,8 @@ CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
@@ -291,7 +292,7 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x7BB0
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0xFFC3
+CONFIG_BANK_3=0xFFC2
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -617,8 +618,7 @@ CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
 
 #
 # CAN, the car bus and industrial fieldbus
@@ -778,7 +778,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -866,11 +866,11 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_MMRS is not set
+CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
index 9f66d2de1007d020a8292e6b2aaa13cd9e38854b..219fc345a5f5bdc7f2a25273cc4ace45c25e29c9 100644 (file)
@@ -39,7 +39,8 @@ CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
@@ -299,7 +300,7 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x7BB0
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0xFFC3
+CONFIG_BANK_3=0xFFC2
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -351,7 +352,10 @@ 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_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
@@ -645,8 +649,7 @@ CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
 
 #
 # CAN, the car bus and industrial fieldbus
@@ -806,7 +809,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -894,12 +897,12 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_MMRS is not set
-# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
+CONFIG_DEBUG_MMRS=y
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
index 2694d06c5bde841a350bf40026af08f596694d5d..9873d586fc7753240a01d774b9d9e165f9a3b146 100644 (file)
@@ -39,7 +39,8 @@ CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
@@ -298,8 +299,8 @@ CONFIG_C_AMBEN_ALL=y
 #
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x7BB0
-CONFIG_BANK_2=0xFFC3
-CONFIG_BANK_3=0xFFC3
+CONFIG_BANK_2=0xFFC2
+CONFIG_BANK_3=0xFFC2
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -628,8 +629,7 @@ CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
 
 #
 # CAN, the car bus and industrial fieldbus
@@ -806,7 +806,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -894,12 +894,12 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_MMRS is not set
-# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
+CONFIG_DEBUG_MMRS=y
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
index 90207251c5336770c887149402ba13650beb55dd..0e3605fdb7b040f8c8be5038fa43a3d5ade884f5 100644 (file)
@@ -363,7 +363,7 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x5554
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0x99B3
+CONFIG_BANK_3=0x99B2
 CONFIG_EBIU_MBSCTLVAL=0x0
 CONFIG_EBIU_MODEVAL=0x1
 CONFIG_EBIU_FCTLVAL=0x6
@@ -744,8 +744,8 @@ CONFIG_BFIN_OTP=y
 #
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
-# CONFIG_SERIAL_BFIN_DMA is not set
-CONFIG_SERIAL_BFIN_PIO=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
 # CONFIG_SERIAL_BFIN_UART0 is not set
 CONFIG_SERIAL_BFIN_UART1=y
 # CONFIG_BFIN_UART1_CTSRTS is not set
@@ -1149,7 +1149,7 @@ CONFIG_RTC_DRV_BFIN=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -1332,7 +1332,7 @@ CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_SAMPLES is not set
-# CONFIG_DEBUG_MMRS is not set
+CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
index daf00906c1ef42696e37743486dbe45d4e67da15..59c7cdbee904f0206755731174193799d1130ef2 100644 (file)
@@ -35,7 +35,8 @@ CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_USER_NS is not set
 # CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
 CONFIG_FAIR_GROUP_SCHED=y
@@ -341,7 +342,7 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x7BB0
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0xFFC3
+CONFIG_BANK_3=0xFFC2
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -631,8 +632,7 @@ CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
 
 #
 # CAN, the car bus and industrial fieldbus
@@ -756,7 +756,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -830,12 +830,12 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_SAMPLES is not set
-# CONFIG_DEBUG_MMRS is not set
+CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
index 679c7483ea714361c67c2589e5c6ebcaf9506c1f..ba0bee90b7e1e46965a145d975c0ce4242b3b0be 100644 (file)
@@ -967,7 +967,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
index 4384a670a8b8e2f97ed0cd294d41a127e8cde537..285d2241df260e106e201b71c05ab8114536af24 100644 (file)
@@ -1066,7 +1066,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
index 87622ad9df479e545bb7b8d9c9dc834b7e122494..bffca7de65d4b44419bf39bab94f565464f91406 100644 (file)
@@ -294,7 +294,7 @@ CONFIG_C_AMBEN_ALL=y
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x33B0
 CONFIG_BANK_2=0x33B0
-CONFIG_BANK_3=0x99B3
+CONFIG_BANK_3=0x99B2
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -1080,7 +1080,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
index 951ea041257654a90c2b2aa03dacca4e076f2075..b1309f878fcd0c4f31b102e1b0de63eef335a211 100644 (file)
@@ -1067,7 +1067,7 @@ CONFIG_FS_MBCACHE=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
index 6140cd69c782455e225b66eec7d4494366ebd819..606adc78aa85cdec05b0d45fe0e9a239eda17609 100644 (file)
@@ -18,6 +18,5 @@ endif
 obj-$(CONFIG_BFIN_GPTIMERS)          += gptimers.o
 obj-$(CONFIG_MODULES)                += module.o
 obj-$(CONFIG_BFIN_DMA_5XX)           += bfin_dma_5xx.o
-obj-$(CONFIG_DUAL_CORE_TEST_MODULE)  += dualcore_test.o
 obj-$(CONFIG_KGDB)                   += kgdb.o
 obj-$(CONFIG_EARLY_PRINTK)           += early_printk.o
index d54f19085f37a13d5b7798f387bd65aa83373ce0..93229b3d6e3e30da6bc17dd760bd48ddbacda0af 100644 (file)
@@ -472,6 +472,40 @@ unsigned long get_dma_curr_addr(unsigned int channel)
 }
 EXPORT_SYMBOL(get_dma_curr_addr);
 
+#ifdef CONFIG_PM
+int blackfin_dma_suspend(void)
+{
+       int i;
+
+#ifdef CONFIG_BF561    /* IMDMA channels doesn't have a PERIPHERAL_MAP */
+       for (i = 0; i <= CH_MEM_STREAM3_SRC; i++) {
+#else
+       for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
+#endif
+               if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) {
+                       printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
+                       return -EBUSY;
+               }
+
+               dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
+       }
+
+       return 0;
+}
+
+void blackfin_dma_resume(void)
+{
+       int i;
+
+#ifdef CONFIG_BF561    /* IMDMA channels doesn't have a PERIPHERAL_MAP */
+       for (i = 0; i <= CH_MEM_STREAM3_SRC; i++)
+#else
+       for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++)
+#endif
+               dma_ch[i].regs->peripheral_map = dma_ch[i].saved_peripheral_map;
+}
+#endif
+
 static void *__dma_memcpy(void *dest, const void *src, size_t size)
 {
        int direction;  /* 1 - address decrease, 0 - address increase */
index b6d89d1644cc8515c1909865e01fdf83e9ede39f..ecbd141e0ef2b1d60a4ae71af6655aabd16019b3 100644 (file)
@@ -186,7 +186,10 @@ static struct str_ident {
        char name[RESOURCE_LABEL_SIZE];
 } str_ident[MAX_RESOURCES];
 
-#if defined(CONFIG_PM) && !defined(CONFIG_BF54x)
+#if defined(CONFIG_PM)
+#if defined(CONFIG_BF54x)
+static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
+#else
 static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
 static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
 static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -206,7 +209,7 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PORTF_INT
 #ifdef BF561_FAMILY
 static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB};
 #endif
-
+#endif
 #endif /* CONFIG_PM */
 
 #if defined(BF548_FAMILY)
@@ -667,7 +670,7 @@ static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type)
        return 0;
 }
 
-u32 bfin_pm_setup(void)
+u32 bfin_pm_standby_setup(void)
 {
        u16 bank, mask, i, gpio;
 
@@ -679,7 +682,7 @@ u32 bfin_pm_setup(void)
                gpio_bankb[bank]->maskb = 0;
 
                if (mask) {
-#ifdef BF537_FAMILY
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
                        gpio_bank_saved[bank].fer   = *port_fer[bank];
 #endif
                        gpio_bank_saved[bank].inen  = gpio_bankb[bank]->inen;
@@ -715,7 +718,7 @@ u32 bfin_pm_setup(void)
        return 0;
 }
 
-void bfin_pm_restore(void)
+void bfin_pm_standby_restore(void)
 {
        u16 bank, mask, i;
 
@@ -724,7 +727,7 @@ void bfin_pm_restore(void)
                bank = gpio_bank(i);
 
                if (mask) {
-#ifdef BF537_FAMILY
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
                        *port_fer[bank]         = gpio_bank_saved[bank].fer;
 #endif
                        gpio_bankb[bank]->inen  = gpio_bank_saved[bank].inen;
@@ -743,8 +746,111 @@ void bfin_pm_restore(void)
        AWA_DUMMY_READ(maskb);
 }
 
+void bfin_gpio_pm_hibernate_suspend(void)
+{
+       int i, bank;
+
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
+               bank = gpio_bank(i);
+
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
+                       gpio_bank_saved[bank].fer   = *port_fer[bank];
+#ifdef BF527_FAMILY
+                       gpio_bank_saved[bank].mux   = *port_mux[bank];
+#else
+                       if (bank == 0)
+                               gpio_bank_saved[bank].mux   = bfin_read_PORT_MUX();
+#endif
+#endif
+                       gpio_bank_saved[bank].data  = gpio_bankb[bank]->data;
+                       gpio_bank_saved[bank].inen  = gpio_bankb[bank]->inen;
+                       gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
+                       gpio_bank_saved[bank].dir   = gpio_bankb[bank]->dir;
+                       gpio_bank_saved[bank].edge  = gpio_bankb[bank]->edge;
+                       gpio_bank_saved[bank].both  = gpio_bankb[bank]->both;
+                       gpio_bank_saved[bank].maska  = gpio_bankb[bank]->maska;
+       }
+
+       AWA_DUMMY_READ(maska);
+}
+
+void bfin_gpio_pm_hibernate_restore(void)
+{
+       int i, bank;
+
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
+                       bank = gpio_bank(i);
+
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
+#ifdef BF527_FAMILY
+                       *port_mux[bank] = gpio_bank_saved[bank].mux;
+#else
+                       if (bank == 0)
+                               bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
+#endif
+                       *port_fer[bank]         = gpio_bank_saved[bank].fer;
+#endif
+                       gpio_bankb[bank]->inen  = gpio_bank_saved[bank].inen;
+                       gpio_bankb[bank]->dir   = gpio_bank_saved[bank].dir;
+                       gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
+                       gpio_bankb[bank]->edge  = gpio_bank_saved[bank].edge;
+                       gpio_bankb[bank]->both  = gpio_bank_saved[bank].both;
+
+                       gpio_bankb[bank]->data_set = gpio_bank_saved[bank].data
+                                                       | gpio_bank_saved[bank].dir;
+
+                       gpio_bankb[bank]->maska = gpio_bank_saved[bank].maska;
+       }
+       AWA_DUMMY_READ(maska);
+}
+
+
 #endif
 #else /* BF548_FAMILY */
+#ifdef CONFIG_PM
+
+u32 bfin_pm_standby_setup(void)
+{
+       return 0;
+}
+
+void bfin_pm_standby_restore(void)
+{
+
+}
+
+void bfin_gpio_pm_hibernate_suspend(void)
+{
+       int i, bank;
+
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
+               bank = gpio_bank(i);
+
+                       gpio_bank_saved[bank].fer  = gpio_array[bank]->port_fer;
+                       gpio_bank_saved[bank].mux  = gpio_array[bank]->port_mux;
+                       gpio_bank_saved[bank].data  = gpio_array[bank]->port_data;
+                       gpio_bank_saved[bank].data  = gpio_array[bank]->port_data;
+                       gpio_bank_saved[bank].inen  = gpio_array[bank]->port_inen;
+                       gpio_bank_saved[bank].dir   = gpio_array[bank]->port_dir_set;
+       }
+}
+
+void bfin_gpio_pm_hibernate_restore(void)
+{
+       int i, bank;
+
+       for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
+                       bank = gpio_bank(i);
+
+                       gpio_array[bank]->port_mux  = gpio_bank_saved[bank].mux;
+                       gpio_array[bank]->port_fer  = gpio_bank_saved[bank].fer;
+                       gpio_array[bank]->port_inen  = gpio_bank_saved[bank].inen;
+                       gpio_array[bank]->port_dir_set   = gpio_bank_saved[bank].dir;
+                       gpio_array[bank]->port_set = gpio_bank_saved[bank].data
+                                                       | gpio_bank_saved[bank].dir;
+       }
+}
+#endif
 
 unsigned short get_gpio_dir(unsigned gpio)
 {
index 2788532de72be3176bd9503fd5894ec45dbb13a4..ecbabc0a1fedd71b936ba9d812b0e836028a6206 100644 (file)
@@ -125,6 +125,6 @@ ENTRY(__cplb_hdr)
        SP += -12;
        call _panic_cplb_error;
        SP += 12;
-       JUMP _handle_bad_cplb;
+       JUMP.L _handle_bad_cplb;
 
 ENDPROC(__cplb_hdr)
index 6be0c50122e8c627102fbcbe5692cc26013b0135..224e7cc30bc599f23d4d8f73f2d161e0e85f004f 100644 (file)
 #include <asm/cplb.h>
 #include <asm/cplbinit.h>
 
-#ifdef CONFIG_MAX_MEM_SIZE
-# define CPLB_MEM CONFIG_MAX_MEM_SIZE
-#else
-# define CPLB_MEM CONFIG_MEM_SIZE
-#endif
+#define CPLB_MEM CONFIG_MAX_MEM_SIZE
 
 /*
 * Number of required data CPLB switchtable entries
diff --git a/arch/blackfin/kernel/dualcore_test.c b/arch/blackfin/kernel/dualcore_test.c
deleted file mode 100644 (file)
index 0fcba74..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * File:         arch/blackfin/kernel/dualcore_test.c
- * Based on:
- * Author:
- *
- * Created:
- * Description:  Small test code for CoreB on a BF561
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-static int *testarg = (int *)0xfeb00000;
-
-static int test_init(void)
-{
-       *testarg = 1;
-       printk(KERN_INFO "Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
-              *testarg, testarg);
-       return 0;
-}
-
-static void test_exit(void)
-{
-       printk(KERN_INFO "Dual core test module removed: testarg = [%d]\n", *testarg);
-}
-
-module_init(test_init);
-module_exit(test_exit);
index 65f4e67a65c4c0c3f0a8d2ad31ca12bee231e6ea..31bd9bf3efae267fd6101ba9569929272070b7cc 100644 (file)
@@ -64,6 +64,11 @@ ENDPROC(_ret_from_fork)
 
 ENTRY(_sys_fork)
        r0 = -EINVAL;
+#if (ANOMALY_05000371)
+       nop;
+       nop;
+       nop;
+#endif
        rts;
 ENDPROC(_sys_fork)
 
index a9c15515bfd7347dd62fcc536c8b2194fe5a4c25..a1f9641a6425d6158ebf21f4a71f4df867fd44ea 100644 (file)
@@ -203,6 +203,8 @@ struct hw_breakpoint {
 
 int kgdb_arch_init(void)
 {
+       debugger_step = 0;
+
        kgdb_remove_all_hw_break();
        return 0;
 }
@@ -368,6 +370,7 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
        char *ptr;
        int newPC;
        int wp_status;
+       int i;
 
        switch (remcom_in_buffer[0]) {
        case 'c':
@@ -392,7 +395,18 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
                /* set the trace bit if we're stepping */
                if (remcom_in_buffer[0] == 's') {
                        linux_regs->syscfg |= 0x1;
-                       debugger_step = 1;
+                       debugger_step = linux_regs->ipend;
+                       debugger_step >>= 6;
+                       for (i = 10; i > 0; i--, debugger_step >>= 1)
+                               if (debugger_step & 1)
+                                       break;
+                       /* i indicate event priority of current stopped instruction
+                        * user space instruction is 0, IVG15 is 1, IVTMR is 10.
+                        * debugger_step > 0 means in single step mode
+                        */
+                       debugger_step = i + 1;
+               } else {
+                       debugger_step = 0;
                }
 
                wp_status = bfin_read_WPSTAT();
index 14a42848f37f70d453807bf3cbe7b1a3346e98e1..e1bebc80a5bf18471ad0160c9bcc4cb59fbeb777 100644 (file)
@@ -173,7 +173,7 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
        for (s = sechdrs; s < sechdrs_end; ++s) {
                if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) ||
                    ((strcmp(".text", secstrings + s->sh_name) == 0) &&
-                    (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) {
+                    (hdr->e_flags & EF_BFIN_CODE_IN_L1) && (s->sh_size > 0))) {
                        dest = l1_inst_sram_alloc(s->sh_size);
                        mod->arch.text_l1 = dest;
                        if (dest == NULL) {
@@ -188,7 +188,7 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
                }
                if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) ||
                    ((strcmp(".data", secstrings + s->sh_name) == 0) &&
-                    (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+                    (hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
                        dest = l1_data_sram_alloc(s->sh_size);
                        mod->arch.data_a_l1 = dest;
                        if (dest == NULL) {
@@ -203,7 +203,7 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
                }
                if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 ||
                    ((strcmp(".bss", secstrings + s->sh_name) == 0) &&
-                    (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+                    (hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
                        dest = l1_data_sram_alloc(s->sh_size);
                        mod->arch.bss_a_l1 = dest;
                        if (dest == NULL) {
@@ -242,6 +242,51 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
                        s->sh_flags &= ~SHF_ALLOC;
                        s->sh_addr = (unsigned long)dest;
                }
+               if ((strcmp(".l2.text", secstrings + s->sh_name) == 0) ||
+                   ((strcmp(".text", secstrings + s->sh_name) == 0) &&
+                    (hdr->e_flags & EF_BFIN_CODE_IN_L2) && (s->sh_size > 0))) {
+                       dest = l2_sram_alloc(s->sh_size);
+                       mod->arch.text_l2 = dest;
+                       if (dest == NULL) {
+                               printk(KERN_ERR
+                                      "module %s: L2 SRAM allocation failed\n",
+                                      mod->name);
+                               return -1;
+                       }
+                       memcpy(dest, (void *)s->sh_addr, s->sh_size);
+                       s->sh_flags &= ~SHF_ALLOC;
+                       s->sh_addr = (unsigned long)dest;
+               }
+               if ((strcmp(".l2.data", secstrings + s->sh_name) == 0) ||
+                   ((strcmp(".data", secstrings + s->sh_name) == 0) &&
+                    (hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
+                       dest = l2_sram_alloc(s->sh_size);
+                       mod->arch.data_l2 = dest;
+                       if (dest == NULL) {
+                               printk(KERN_ERR
+                                       "module %s: L2 SRAM allocation failed\n",
+                                       mod->name);
+                               return -1;
+                       }
+                       memcpy(dest, (void *)s->sh_addr, s->sh_size);
+                       s->sh_flags &= ~SHF_ALLOC;
+                       s->sh_addr = (unsigned long)dest;
+               }
+               if (strcmp(".l2.bss", secstrings + s->sh_name) == 0 ||
+                   ((strcmp(".bss", secstrings + s->sh_name) == 0) &&
+                    (hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
+                       dest = l2_sram_alloc(s->sh_size);
+                       mod->arch.bss_l2 = dest;
+                       if (dest == NULL) {
+                               printk(KERN_ERR
+                                       "module %s: L2 SRAM allocation failed\n",
+                                       mod->name);
+                               return -1;
+                       }
+                       memset(dest, 0, s->sh_size);
+                       s->sh_flags &= ~SHF_ALLOC;
+                       s->sh_addr = (unsigned long)dest;
+               }
        }
        return 0;
 }
@@ -411,9 +456,10 @@ module_finalize(const Elf_Ehdr * hdr,
                        continue;
 
                if ((sechdrs[i].sh_type == SHT_RELA) &&
-                   ((strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
+                   ((strcmp(".rela.l2.text", secstrings + sechdrs[i].sh_name) == 0) ||
+                   (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
                    ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
-                        (hdr->e_flags & FLG_CODE_IN_L1)))) {
+                       (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) {
                        apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
                                           symindex, i, mod);
                }
@@ -423,14 +469,12 @@ module_finalize(const Elf_Ehdr * hdr,
 
 void module_arch_cleanup(struct module *mod)
 {
-       if (mod->arch.text_l1)
-               l1_inst_sram_free((void *)mod->arch.text_l1);
-       if (mod->arch.data_a_l1)
-               l1_data_sram_free((void *)mod->arch.data_a_l1);
-       if (mod->arch.bss_a_l1)
-               l1_data_sram_free((void *)mod->arch.bss_a_l1);
-       if (mod->arch.data_b_l1)
-               l1_data_B_sram_free((void *)mod->arch.data_b_l1);
-       if (mod->arch.bss_b_l1)
-               l1_data_B_sram_free((void *)mod->arch.bss_b_l1);
+       l1_inst_sram_free(mod->arch.text_l1);
+       l1_data_A_sram_free(mod->arch.data_a_l1);
+       l1_data_A_sram_free(mod->arch.bss_a_l1);
+       l1_data_B_sram_free(mod->arch.data_b_l1);
+       l1_data_B_sram_free(mod->arch.bss_b_l1);
+       l2_sram_free(mod->arch.text_l2);
+       l2_sram_free(mod->arch.data_l2);
+       l2_sram_free(mod->arch.bss_l2);
 }
index 53c2cd255441ff5a23a55ce9cc8e5702ef1ec966..77800dd83e578d49844edaceaec7fc4f3bcfe728 100644 (file)
@@ -105,7 +105,7 @@ void cpu_idle(void)
 #endif
                if (!idle)
                        idle = default_idle;
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        idle();
                tick_nohz_restart_sched_tick();
index f51ab088098ec1e16162c2c4a62c4c20a42b4b17..bf1a51d8e608a39305ef8d03295060bec5416138 100644 (file)
@@ -219,6 +219,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                                safe_dma_memcpy (&tmp, (const void *)(addr + add), sizeof(tmp));
                                copied = sizeof(tmp);
                        } else
+#endif
+#if L1_DATA_A_LENGTH != 0
+                       if (addr + add >= L1_DATA_A_START
+                           && addr + add + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
+                               memcpy(&tmp, (const void *)(addr + add), sizeof(tmp));
+                               copied = sizeof(tmp);
+                       } else
+#endif
+#if L1_DATA_B_LENGTH != 0
+                       if (addr + add >= L1_DATA_B_START
+                           && addr + add + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
+                               memcpy(&tmp, (const void *)(addr + add), sizeof(tmp));
+                               copied = sizeof(tmp);
+                       } else
 #endif
                        if (addr + add >= FIXED_CODE_START
                            && addr + add + sizeof(tmp) <= FIXED_CODE_END) {
@@ -289,6 +303,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                                safe_dma_memcpy ((void *)(addr + add), &data, sizeof(data));
                                copied = sizeof(data);
                        } else
+#endif
+#if L1_DATA_A_LENGTH != 0
+                       if (addr + add >= L1_DATA_A_START
+                           && addr + add + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
+                               memcpy((void *)(addr + add), &data, sizeof(data));
+                               copied = sizeof(data);
+                       } else
+#endif
+#if L1_DATA_B_LENGTH != 0
+                       if (addr + add >= L1_DATA_B_START
+                           && addr + add + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
+                               memcpy((void *)(addr + add), &data, sizeof(data));
+                               copied = sizeof(data);
+                       } else
 #endif
                        if (addr + add >= FIXED_CODE_START
                            && addr + add + sizeof(data) <= FIXED_CODE_END) {
index 8efea004aecb46cdcd01c5899cf3aa52d97f9613..23e637eb78da8e7daab447c4b2f4ac849099f565 100644 (file)
@@ -104,6 +104,7 @@ void __init bf53x_relocate_l1_mem(void)
        unsigned long l1_code_length;
        unsigned long l1_data_a_length;
        unsigned long l1_data_b_length;
+       unsigned long l2_length;
 
        l1_code_length = _etext_l1 - _stext_l1;
        if (l1_code_length > L1_CODE_LENGTH)
@@ -129,6 +130,15 @@ void __init bf53x_relocate_l1_mem(void)
        /* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */
        dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
                        l1_data_a_length, l1_data_b_length);
+
+#ifdef L2_LENGTH
+       l2_length = _ebss_l2 - _stext_l2;
+       if (l2_length > L2_LENGTH)
+               panic("L2 SRAM Overflow\n");
+
+       /* Copy _stext_l2 to _edata_l2 to L2 SRAM */
+       dma_memcpy(_stext_l2, _l2_lma_start, l2_length);
+#endif
 }
 
 /* add_memory_region to memmap */
@@ -664,11 +674,8 @@ static __init void setup_bootmem_allocator(void)
 })
 static inline int __init get_mem_size(void)
 {
-#ifdef CONFIG_MEM_SIZE
-       return CONFIG_MEM_SIZE;
-#else
-# if defined(EBIU_SDBCTL)
-#  if defined(BF561_FAMILY)
+#if defined(EBIU_SDBCTL)
+# if defined(BF561_FAMILY)
        int ret = 0;
        u32 sdbctl = bfin_read_EBIU_SDBCTL();
        ret += EBSZ_TO_MEG(sdbctl >>  0);
@@ -676,10 +683,10 @@ static inline int __init get_mem_size(void)
        ret += EBSZ_TO_MEG(sdbctl >> 16);
        ret += EBSZ_TO_MEG(sdbctl >> 24);
        return ret;
-#  else
+# else
        return EBSZ_TO_MEG(bfin_read_EBIU_SDBCTL());
-#  endif
-# elif defined(EBIU_DDRCTL1)
+# endif
+#elif defined(EBIU_DDRCTL1)
        u32 ddrctl = bfin_read_EBIU_DDRCTL1();
        int ret = 0;
        switch (ddrctl & 0xc0000) {
@@ -693,8 +700,9 @@ static inline int __init get_mem_size(void)
                case DEVWD_8:  ret *= 2;
                case DEVWD_16: break;
        }
+       if ((ddrctl & 0xc000) == 0x4000)
+               ret *= 2;
        return ret;
-# endif
 #endif
        BUG();
 }
@@ -763,6 +771,9 @@ void __init setup_arch(char **cmdline_p)
 
        _bfin_swrst = bfin_read_SWRST();
 
+       /* If we double fault, reset the system - otherwise we hang forever */
+       bfin_write_SWRST(DOUBLE_FAULT);
+
        if (_bfin_swrst & RESET_DOUBLE)
                printk(KERN_INFO "Recovering from Double Fault event\n");
        else if (_bfin_swrst & RESET_WDOG)
@@ -842,38 +853,55 @@ static int __init topology_init(void)
 
 subsys_initcall(topology_init);
 
+/* Get the voltage input multiplier */
+static u_long cached_vco_pll_ctl, cached_vco;
 static u_long get_vco(void)
 {
        u_long msel;
-       u_long vco;
 
-       msel = (bfin_read_PLL_CTL() >> 9) & 0x3F;
+       u_long pll_ctl = bfin_read_PLL_CTL();
+       if (pll_ctl == cached_vco_pll_ctl)
+               return cached_vco;
+       else
+               cached_vco_pll_ctl = pll_ctl;
+
+       msel = (pll_ctl >> 9) & 0x3F;
        if (0 == msel)
                msel = 64;
 
-       vco = CONFIG_CLKIN_HZ;
-       vco >>= (1 & bfin_read_PLL_CTL());      /* DF bit */
-       vco = msel * vco;
-       return vco;
+       cached_vco = CONFIG_CLKIN_HZ;
+       cached_vco >>= (1 & pll_ctl);   /* DF bit */
+       cached_vco *= msel;
+       return cached_vco;
 }
 
 /* Get the Core clock */
+static u_long cached_cclk_pll_div, cached_cclk;
 u_long get_cclk(void)
 {
        u_long csel, ssel;
+
        if (bfin_read_PLL_STAT() & 0x1)
                return CONFIG_CLKIN_HZ;
 
        ssel = bfin_read_PLL_DIV();
+       if (ssel == cached_cclk_pll_div)
+               return cached_cclk;
+       else
+               cached_cclk_pll_div = ssel;
+
        csel = ((ssel >> 4) & 0x03);
        ssel &= 0xf;
        if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */
-               return get_vco() / ssel;
-       return get_vco() >> csel;
+               cached_cclk = get_vco() / ssel;
+       else
+               cached_cclk = get_vco() >> csel;
+       return cached_cclk;
 }
 EXPORT_SYMBOL(get_cclk);
 
 /* Get the System clock */
+static u_long cached_sclk_pll_div, cached_sclk;
 u_long get_sclk(void)
 {
        u_long ssel;
@@ -881,13 +909,20 @@ u_long get_sclk(void)
        if (bfin_read_PLL_STAT() & 0x1)
                return CONFIG_CLKIN_HZ;
 
-       ssel = (bfin_read_PLL_DIV() & 0xf);
+       ssel = bfin_read_PLL_DIV();
+       if (ssel == cached_sclk_pll_div)
+               return cached_sclk;
+       else
+               cached_sclk_pll_div = ssel;
+
+       ssel &= 0xf;
        if (0 == ssel) {
                printk(KERN_WARNING "Invalid System Clock\n");
                ssel = 1;
        }
 
-       return get_vco() / ssel;
+       cached_sclk = get_vco() / ssel;
+       return cached_sclk;
 }
 EXPORT_SYMBOL(get_sclk);
 
@@ -916,7 +951,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        uint32_t revid;
 
        u_long cclk = 0, sclk = 0;
-       u_int dcache_size = 0, dsup_banks = 0;
+       u_int icache_size = BFIN_ICACHESIZE / 1024, dcache_size = 0, dsup_banks = 0;
 
        cpu = CPU;
        mmu = "none";
@@ -985,12 +1020,15 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        }
 
        /* Is it turned on? */
-       if (!((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE)))
+       if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE))
                dcache_size = 0;
 
+       if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) == (IMC | ENICPLB))
+               icache_size = 0;
+
        seq_printf(m, "cache size\t: %d KB(L1 icache) "
                "%d KB(L1 dcache-%s) %d KB(L2 cache)\n",
-               BFIN_ICACHESIZE / 1024, dcache_size,
+               icache_size, dcache_size,
 #if defined CONFIG_BFIN_WB
                "wb"
 #elif defined CONFIG_BFIN_WT
@@ -1000,8 +1038,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
        seq_printf(m, "%s\n", cache);
 
-       seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n",
-                  BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES);
+       if (icache_size)
+               seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n",
+                          BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES);
+       else
+               seq_printf(m, "icache setup\t: off\n");
+
        seq_printf(m,
                   "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n",
                   dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS,
index f061f5181623e4214e6e606642c83a79c15ae1fc..ad922ab915438ef3d66820809285e1f9a8477deb 100644 (file)
@@ -69,8 +69,6 @@ void __init trap_init(void)
 
 unsigned long saved_icplb_fault_addr, saved_dcplb_fault_addr;
 
-int kstack_depth_to_print = 48;
-
 static void decode_address(char *buf, unsigned long address)
 {
        struct vm_list_struct *vml;
@@ -163,6 +161,9 @@ static void decode_address(char *buf, unsigned long address)
                                if (!in_atomic)
                                        mmput(mm);
 
+                               if (!strlen(buf))
+                                       sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name);
+
                                goto done;
                        }
 
@@ -173,7 +174,7 @@ static void decode_address(char *buf, unsigned long address)
        }
 
        /* we were unable to find this address anywhere */
-       sprintf(buf, "<0x%p> /* unknown address */", (void *)address);
+       sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
 
 done:
        write_unlock_irqrestore(&tasklist_lock, flags);
@@ -494,7 +495,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
        BUG_ON(sig == 0);
 
        if (sig != SIGTRAP) {
-               unsigned long stack;
+               unsigned long *stack;
                dump_bfin_process(fp);
                dump_bfin_mem(fp);
                show_regs(fp);
@@ -508,14 +509,23 @@ asmlinkage void trap_c(struct pt_regs *fp)
                else
 #endif
                        dump_bfin_trace_buffer();
-               show_stack(current, &stack);
+
                if (oops_in_progress) {
+                       /* Dump the current kernel stack */
+                       printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
+                       show_stack(current, NULL);
+
                        print_modules();
 #ifndef CONFIG_ACCESS_CHECK
                        printk(KERN_EMERG "Please turn on "
                               "CONFIG_ACCESS_CHECK\n");
 #endif
                        panic("Kernel exception");
+               } else {
+                       /* Dump the user space stack */
+                       stack = (unsigned long *)rdusp();
+                       printk(KERN_NOTICE "Userspace Stack\n");
+                       show_stack(NULL, stack);
                }
        }
 
@@ -532,11 +542,71 @@ asmlinkage void trap_c(struct pt_regs *fp)
 
 #define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)
 
+/*
+ * Similar to get_user, do some address checking, then dereference
+ * Return true on sucess, false on bad address
+ */
+bool get_instruction(unsigned short *val, unsigned short *address)
+{
+
+       unsigned long addr;
+
+       addr = (unsigned long)address;
+
+       /* Check for odd addresses */
+       if (addr & 0x1)
+               return false;
+
+       /* Check that things do not wrap around */
+       if (addr > (addr + 2))
+               return false;
+
+       /*
+        * Since we are in exception context, we need to do a little address checking
+        * We need to make sure we are only accessing valid memory, and
+        * we don't read something in the async space that can hang forever
+        */
+       if ((addr >= FIXED_CODE_START && (addr + 2) <= physical_mem_end) ||
+#ifdef L2_START
+           (addr >= L2_START && (addr + 2) <= (L2_START + L2_LENGTH)) ||
+#endif
+           (addr >= BOOT_ROM_START && (addr + 2) <= (BOOT_ROM_START + BOOT_ROM_LENGTH)) ||
+#if L1_DATA_A_LENGTH != 0
+           (addr >= L1_DATA_A_START && (addr + 2) <= (L1_DATA_A_START + L1_DATA_A_LENGTH)) ||
+#endif
+#if L1_DATA_B_LENGTH != 0
+           (addr >= L1_DATA_B_START && (addr + 2) <= (L1_DATA_B_START + L1_DATA_B_LENGTH)) ||
+#endif
+           (addr >= L1_SCRATCH_START && (addr + 2) <= (L1_SCRATCH_START + L1_SCRATCH_LENGTH)) ||
+           (!(bfin_read_EBIU_AMBCTL0() & B0RDYEN) &&
+              addr >= ASYNC_BANK0_BASE && (addr + 2) <= (ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)) ||
+           (!(bfin_read_EBIU_AMBCTL0() & B1RDYEN) &&
+              addr >= ASYNC_BANK1_BASE && (addr + 2) <= (ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)) ||
+           (!(bfin_read_EBIU_AMBCTL1() & B2RDYEN) &&
+              addr >= ASYNC_BANK2_BASE && (addr + 2) <= (ASYNC_BANK2_BASE + ASYNC_BANK1_SIZE)) ||
+           (!(bfin_read_EBIU_AMBCTL1() & B3RDYEN) &&
+             addr >= ASYNC_BANK3_BASE && (addr + 2) <= (ASYNC_BANK3_BASE + ASYNC_BANK1_SIZE))) {
+               *val = *address;
+               return true;
+       }
+
+#if L1_CODE_LENGTH != 0
+       if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) {
+               dma_memcpy(val, address, 2);
+               return true;
+       }
+#endif
+
+
+       return false;
+}
+
 void dump_bfin_trace_buffer(void)
 {
 #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
        int tflags, i = 0;
        char buf[150];
+       unsigned short val = 0, *addr;
 #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
        int j, index;
 #endif
@@ -549,8 +619,42 @@ void dump_bfin_trace_buffer(void)
                for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
                        decode_address(buf, (unsigned long)bfin_read_TBUF());
                        printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
-                       decode_address(buf, (unsigned long)bfin_read_TBUF());
-                       printk(KERN_NOTICE "     Source : %s\n", buf);
+                       addr = (unsigned short *)bfin_read_TBUF();
+                       decode_address(buf, (unsigned long)addr);
+                       printk(KERN_NOTICE "     Source : %s ", buf);
+                       if (get_instruction(&val, addr)) {
+                               if (val == 0x0010)
+                                       printk("RTS");
+                               else if (val == 0x0011)
+                                       printk("RTI");
+                               else if (val == 0x0012)
+                                       printk("RTX");
+                               else if (val >= 0x0050 && val <= 0x0057)
+                                       printk("JUMP (P%i)", val & 7);
+                               else if (val >= 0x0060 && val <= 0x0067)
+                                       printk("CALL (P%i)", val & 7);
+                               else if (val >= 0x0070 && val <= 0x0077)
+                                       printk("CALL (PC+P%i)", val & 7);
+                               else if (val >= 0x0080 && val <= 0x0087)
+                                       printk("JUMP (PC+P%i)", val & 7);
+                               else if ((val >= 0x1000 && val <= 0x13FF) ||
+                                   (val >= 0x1800 && val <= 0x1BFF))
+                                       printk("IF !CC JUMP");
+                               else if ((val >= 0x1400 && val <= 0x17ff) ||
+                                   (val >= 0x1c00 && val <= 0x1fff))
+                                       printk("IF CC JUMP");
+                               else if (val >= 0x2000 && val <= 0x2fff)
+                                       printk("JUMP.S");
+                               else if (val >= 0xe080 && val <= 0xe0ff)
+                                       printk("LSETUP");
+                               else if (val >= 0xe200 && val <= 0xe2ff)
+                                       printk("JUMP.L");
+                               else if (val >= 0xe300 && val <= 0xe3ff)
+                                       printk("CALL pcrel");
+                               else
+                                       printk("0x%04x", val);
+                       }
+                       printk("\n");
                }
        }
 
@@ -582,59 +686,151 @@ void dump_bfin_trace_buffer(void)
 }
 EXPORT_SYMBOL(dump_bfin_trace_buffer);
 
-static void show_trace(struct task_struct *tsk, unsigned long *sp)
+/*
+ * Checks to see if the address pointed to is either a
+ * 16-bit CALL instruction, or a 32-bit CALL instruction
+ */
+bool is_bfin_call(unsigned short *addr)
 {
-       unsigned long addr;
+       unsigned short opcode = 0, *ins_addr;
+       ins_addr = (unsigned short *)addr;
 
-       printk(KERN_NOTICE "\n" KERN_NOTICE "Call Trace:\n");
-
-       while (!kstack_end(sp)) {
-               addr = *sp++;
-               /*
-                * If the address is either in the text segment of the
-                * kernel, or in the region which contains vmalloc'ed
-                * memory, it *may* be the address of a calling
-                * routine; if so, print it so that someone tracing
-                * down the cause of the crash will be able to figure
-                * out the call path that was taken.
-                */
-               if (kernel_text_address(addr))
-                       print_ip_sym(addr);
-       }
+       if (!get_instruction(&opcode, ins_addr))
+               return false;
 
-       printk(KERN_NOTICE "\n");
-}
+       if ((opcode >= 0x0060 && opcode <= 0x0067) ||
+           (opcode >= 0x0070 && opcode <= 0x0077))
+               return true;
+
+       ins_addr--;
+       if (!get_instruction(&opcode, ins_addr))
+               return false;
 
+       if (opcode >= 0xE300 && opcode <= 0xE3FF)
+               return true;
+
+       return false;
+
+}
 void show_stack(struct task_struct *task, unsigned long *stack)
 {
-       unsigned long *endstack, addr;
-       int i;
+       unsigned int *addr, *endstack, *fp = 0, *frame;
+       unsigned short *ins_addr;
+       char buf[150];
+       unsigned int i, j, ret_addr, frame_no = 0;
 
-       /* Cannot call dump_bfin_trace_buffer() here as show_stack() is
-        * called externally in some places in the kernel.
+       /*
+        * If we have been passed a specific stack, use that one otherwise
+        *    if we have been passed a task structure, use that, otherwise
+        *    use the stack of where the variable "stack" exists
         */
 
-       if (!stack) {
-               if (task)
+       if (stack == NULL) {
+               if (task) {
+                       /* We know this is a kernel stack, so this is the start/end */
                        stack = (unsigned long *)task->thread.ksp;
-               else
+                       endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
+               } else {
+                       /* print out the existing stack info */
                        stack = (unsigned long *)&stack;
+                       endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
+               }
+       } else
+               endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
+
+       decode_address(buf, (unsigned int)stack);
+       printk(KERN_NOTICE "Stack info:\n" KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
+       addr = (unsigned int *)((unsigned int)stack & ~0x3F);
+
+       /* First thing is to look for a frame pointer */
+       for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
+               addr < endstack; addr++, i++) {
+               if (*addr & 0x1)
+                       continue;
+               ins_addr = (unsigned short *)*addr;
+               ins_addr--;
+               if (is_bfin_call(ins_addr))
+                       fp = addr - 1;
+
+               if (fp) {
+                       /* Let's check to see if it is a frame pointer */
+                       while (fp >= (addr - 1) && fp < endstack && fp)
+                               fp = (unsigned int *)*fp;
+                       if (fp == 0 || fp == endstack) {
+                               fp = addr - 1;
+                               break;
+                       }
+                       fp = 0;
+               }
        }
+       if (fp) {
+               frame = fp;
+               printk(" FP: (0x%p)\n", fp);
+       } else
+               frame = 0;
 
-       addr = (unsigned long)stack;
-       endstack = (unsigned long *)PAGE_ALIGN(addr);
+       /*
+        * Now that we think we know where things are, we
+        * walk the stack again, this time printing things out
+        * incase there is no frame pointer, we still look for
+        * valid return addresses
+        */
 
-       printk(KERN_NOTICE "Stack from %08lx:", (unsigned long)stack);
-       for (i = 0; i < kstack_depth_to_print; i++) {
-               if (stack + 1 > endstack)
-                       break;
-               if (i % 8 == 0)
-                       printk("\n" KERN_NOTICE "       ");
-               printk(" %08lx", *stack++);
+       /* First time print out data, next time, print out symbols */
+       for (j = 0; j <= 1; j++) {
+               if (j)
+                       printk(KERN_NOTICE "Return addresses in stack:\n");
+               else
+                       printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);
+
+               fp = frame;
+               frame_no = 0;
+
+               for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
+                    addr <= endstack; addr++, i++) {
+
+                       ret_addr = 0;
+                       if (!j && i % 8 == 0)
+                               printk("\n" KERN_NOTICE "%p:",addr);
+
+                       /* if it is an odd address, or zero, just skip it */
+                       if (*addr & 0x1 || !*addr)
+                               goto print;
+
+                       ins_addr = (unsigned short *)*addr;
+
+                       /* Go back one instruction, and see if it is a CALL */
+                       ins_addr--;
+                       ret_addr = is_bfin_call(ins_addr);
+ print:
+                       if (!j && stack == (unsigned long *)addr)
+                               printk("[%08x]", *addr);
+                       else if (ret_addr)
+                               if (j) {
+                                       decode_address(buf, (unsigned int)*addr);
+                                       if (frame == addr) {
+                                               printk(KERN_NOTICE "   frame %2i : %s\n", frame_no, buf);
+                                               continue;
+                                       }
+                                       printk(KERN_NOTICE "    address : %s\n", buf);
+                               } else
+                                       printk("<%08x>", *addr);
+                       else if (fp == addr) {
+                               if (j)
+                                       frame = addr+1;
+                               else
+                                       printk("(%08x)", *addr);
+
+                               fp = (unsigned int *)*addr;
+                               frame_no++;
+
+                       } else if (!j)
+                               printk(" %08x ", *addr);
+               }
+               if (!j)
+                       printk("\n");
        }
-       printk("\n");
 
-       show_trace(task, stack);
 }
 
 void dump_stack(void)
@@ -715,19 +911,9 @@ void dump_bfin_mem(struct pt_regs *fp)
                if (!((unsigned long)addr & 0xF))
                        printk("\n" KERN_NOTICE "0x%p: ", addr);
 
-               if (get_user(val, addr)) {
-                       if (addr >= (unsigned short *)L1_CODE_START &&
-                           addr < (unsigned short *)(L1_CODE_START + L1_CODE_LENGTH)) {
-                               dma_memcpy(&val, addr, sizeof(val));
-                               sprintf(buf, "%04x", val);
-                       } else if (addr >= (unsigned short *)FIXED_CODE_START &&
-                               addr <= (unsigned short *)memory_start) {
-                               val = bfin_read16(addr);
-                               sprintf(buf, "%04x", val);
-                       } else {
+               if (get_instruction(&val, addr)) {
                                val = 0;
                                sprintf(buf, "????");
-                       }
                } else
                        sprintf(buf, "%04x", val);
 
index 3ecc64cab3be03231484f907ddfc20fd784be6df..0896e38d61087f1398a096cb6790d96afc4febc6 100644 (file)
@@ -101,6 +101,11 @@ SECTIONS
 #if !L1_DATA_B_LENGTH
                *(.l1.data.B)
 #endif
+#ifndef L2_LENGTH
+               . = ALIGN(32);
+               *(.data_l2.cacheline_aligned)
+               *(.l2.data)
+#endif
 
                DATA_DATA
                *(.data.*)
@@ -182,13 +187,12 @@ SECTIONS
                *(.l1.data)
                __edata_l1 = .;
 
-               . = ALIGN(4);
-               __sbss_l1 = .;
-               *(.l1.bss)
-
                . = ALIGN(32);
                *(.data_l1.cacheline_aligned)
 
+               . = ALIGN(4);
+               __sbss_l1 = .;
+               *(.l1.bss)
                . = ALIGN(4);
                __ebss_l1 = .;
        }
@@ -203,11 +207,37 @@ SECTIONS
                . = ALIGN(4);
                __sbss_b_l1 = .;
                *(.l1.bss.B)
-
                . = ALIGN(4);
                __ebss_b_l1 = .;
        }
 
+#ifdef L2_LENGTH
+       __l2_lma_start = .;
+
+       .text_data_l2 L2_START : AT(LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1))
+       {
+               . = ALIGN(4);
+               __stext_l2 = .;
+               *(.l1.text)
+               . = ALIGN(4);
+               __etext_l2 = .;
+
+               . = ALIGN(4);
+               __sdata_l2 = .;
+               *(.l1.data)
+               __edata_l2 = .;
+
+               . = ALIGN(32);
+               *(.data_l2.cacheline_aligned)
+
+               . = ALIGN(4);
+               __sbss_l2 = .;
+               *(.l1.bss)
+               . = ALIGN(4);
+               __ebss_l2 = .;
+       }
+#endif
+
        /* Force trailing alignment of our init section so that when we
         * free our init memory, we don't leave behind a partial page.
         */
index 6a570ad03746f2372dca7f5a67868396e6d44f36..8bf9e58f01480f3ae1530550933f36cdf3b33dc4 100644 (file)
@@ -9,4 +9,9 @@ config BFIN527_EZKIT
        help
          BF527-EZKIT-LITE board support.
 
+config BFIN527_BLUETECHNIX_CM
+       bool "Bluetechnix CM-BF527"
+       help
+         CM-BF527 support for EVAL- and DEV-Board.
+
 endchoice
index 7277d35ef11174e91803f74bf81cd7b88e2b92af..7ba7d256bbb8601b6cf5da9136ff21e435753a81 100644 (file)
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_BFIN527_EZKIT)            += ezkit.o
+obj-$(CONFIG_BFIN527_BLUETECHNIX_CM)   += cm_bf527.o
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
new file mode 100644 (file)
index 0000000..0b26ae2
--- /dev/null
@@ -0,0 +1,1011 @@
+/*
+ * File:         arch/blackfin/mach-bf527/boards/cm-bf527.c
+ * Based on:     arch/blackfin/mach-bf537/boards/stamp.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/etherdevice.h>
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+#include <linux/usb/isp1362.h>
+#endif
+#include <linux/pata_platform.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb/sl811.h>
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+#include <linux/usb/musb.h>
+#endif
+#include <asm/cplb.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+#include <asm/nand.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+#include <linux/spi/ad7877.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "Bluetechnix CM-BF527";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#define ISP1761_BASE       0x203C0000
+#define ISP1761_IRQ        IRQ_PF7
+
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+static struct resource bfin_isp1761_resources[] = {
+       [0] = {
+               .name   = "isp1761-regs",
+               .start  = ISP1761_BASE + 0x00000000,
+               .end    = ISP1761_BASE + 0x000fffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = ISP1761_IRQ,
+               .end    = ISP1761_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_isp1761_device = {
+       .name           = "isp1761",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(bfin_isp1761_resources),
+       .resource       = bfin_isp1761_resources,
+};
+
+static struct platform_device *bfin_isp1761_devices[] = {
+       &bfin_isp1761_device,
+};
+
+int __init bfin_isp1761_init(void)
+{
+       unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
+       set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+
+       return platform_add_devices(bfin_isp1761_devices, num_devices);
+}
+
+void __exit bfin_isp1761_exit(void)
+{
+       platform_device_unregister(&bfin_isp1761_device);
+}
+
+arch_initcall(bfin_isp1761_init);
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+static struct resource musb_resources[] = {
+       [0] = {
+               .start  = 0xffc03800,
+               .end    = 0xffc03cff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = { /* general IRQ */
+               .start  = IRQ_USB_INT0,
+               .end    = IRQ_USB_INT0,
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+       [2] = { /* DMA IRQ */
+               .start  = IRQ_USB_DMA,
+               .end    = IRQ_USB_DMA,
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_USB_MUSB_OTG)
+       .mode           = MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+       .mode           = MUSB_HOST,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+       .mode           = MUSB_PERIPHERAL,
+#endif
+       .multipoint     = 0,
+};
+
+static u64 musb_dmamask = ~(u32)0;
+
+static struct platform_device musb_device = {
+       .name           = "musb_hdrc",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = &musb_dmamask,
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &musb_plat,
+       },
+       .num_resources  = ARRAY_SIZE(musb_resources),
+       .resource       = musb_resources,
+};
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition ezkit_partitions[] = {
+       {
+               .name       = "Bootloader",
+               .size       = 0x40000,
+               .offset     = 0,
+       }, {
+               .name       = "Kernel",
+               .size       = 0x1C0000,
+               .offset     = MTDPART_OFS_APPEND,
+       }, {
+               .name       = "RootFS",
+               .size       = MTDPART_SIZ_FULL,
+               .offset     = MTDPART_OFS_APPEND,
+       }
+};
+
+static struct physmap_flash_data ezkit_flash_data = {
+       .width      = 2,
+       .parts      = ezkit_partitions,
+       .nr_parts   = ARRAY_SIZE(ezkit_partitions),
+};
+
+static struct resource ezkit_flash_resource = {
+       .start = 0x20000000,
+       .end   = 0x201fffff,
+       .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ezkit_flash_device = {
+       .name          = "physmap-flash",
+       .id            = 0,
+       .dev = {
+               .platform_data = &ezkit_flash_data,
+       },
+       .num_resources = 1,
+       .resource      = &ezkit_flash_resource,
+};
+#endif
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+static struct mtd_partition partition_info[] = {
+       {
+               .name = "Linux Kernel",
+               .offset = 0,
+               .size = 4 * SIZE_1M,
+       },
+       {
+               .name = "File System",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct bf5xx_nand_platform bf5xx_nand_platform = {
+       .page_size = NFC_PG_SIZE_256,
+       .data_width = NFC_NWIDTH_8,
+       .partitions = partition_info,
+       .nr_partitions = ARRAY_SIZE(partition_info),
+       .rd_dly = 3,
+       .wr_dly = 3,
+};
+
+static struct resource bf5xx_nand_resources[] = {
+       {
+               .start = NFC_CTL,
+               .end = NFC_DATA_RD + 2,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = CH_NFC,
+               .end = CH_NFC,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bf5xx_nand_device = {
+       .name = "bf5xx-nand",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bf5xx_nand_resources),
+       .resource = bf5xx_nand_resources,
+       .dev = {
+               .platform_data = &bf5xx_nand_platform,
+       },
+};
+#endif
+
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+static struct resource bfin_pcmcia_cf_resources[] = {
+       {
+               .start = 0x20310000, /* IO PORT */
+               .end = 0x20312000,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = 0x20311000, /* Attribute Memory */
+               .end = 0x20311FFF,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = IRQ_PF4,
+               .end = IRQ_PF4,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+       }, {
+               .start = 6, /* Card Detect PF6 */
+               .end = 6,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_pcmcia_cf_device = {
+       .name = "bfin_cf_pcmcia",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(bfin_pcmcia_cf_resources),
+       .resource = bfin_pcmcia_cf_resources,
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+       {
+               .name = "smc91x-regs",
+               .start = 0x20300300,
+               .end = 0x20300300 + 16,
+               .flags = IORESOURCE_MEM,
+       }, {
+
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+static struct platform_device smc91x_device = {
+       .name = "smc91x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smc91x_resources),
+       .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+static struct resource dm9000_resources[] = {
+       [0] = {
+               .start  = 0x203FB800,
+               .end    = 0x203FB800 + 8,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_PF9,
+               .end    = IRQ_PF9,
+               .flags  = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
+       },
+};
+
+static struct platform_device dm9000_device = {
+       .name           = "dm9000",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(dm9000_resources),
+       .resource       = dm9000_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+static struct resource sl811_hcd_resources[] = {
+       {
+               .start = 0x20340000,
+               .end = 0x20340000,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = 0x20340004,
+               .end = 0x20340004,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = CONFIG_USB_SL811_BFIN_IRQ,
+               .end = CONFIG_USB_SL811_BFIN_IRQ,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+void sl811_port_power(struct device *dev, int is_on)
+{
+       gpio_request(CONFIG_USB_SL811_BFIN_GPIO_VBUS, "usb:SL811_VBUS");
+       gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS, is_on);
+}
+#endif
+
+static struct sl811_platform_data sl811_priv = {
+       .potpg = 10,
+       .power = 250,       /* == 500mA */
+#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS)
+       .port_power = &sl811_port_power,
+#endif
+};
+
+static struct platform_device sl811_hcd_device = {
+       .name = "sl811-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &sl811_priv,
+       },
+       .num_resources = ARRAY_SIZE(sl811_hcd_resources),
+       .resource = sl811_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+static struct resource isp1362_hcd_resources[] = {
+       {
+               .start = 0x20360000,
+               .end = 0x20360000,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = 0x20360004,
+               .end = 0x20360004,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
+               .end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+       .sel15Kres = 1,
+       .clknotstop = 0,
+       .oc_enable = 0,
+       .int_act_high = 0,
+       .int_edge_triggered = 0,
+       .remote_wakeup_connected = 0,
+       .no_power_switching = 1,
+       .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+       .name = "isp1362-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &isp1362_priv,
+       },
+       .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+       .resource = isp1362_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mac_device = {
+       .name = "bfin_mac",
+};
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+static struct resource net2272_bfin_resources[] = {
+       {
+               .start = 0x20300000,
+               .end = 0x20300000 + 0x100,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = IRQ_PF7,
+               .end = IRQ_PF7,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct platform_device net2272_bfin_device = {
+       .name = "net2272",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(net2272_bfin_resources),
+       .resource = net2272_bfin_resources,
+};
+#endif
+
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00040000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       }, {
+               .name = "linux kernel",
+               .size = MTDPART_SIZ_FULL,
+               .offset = MTDPART_OFS_APPEND,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p16",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+       || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+       .enable_dma = 1,
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_PBX)
+static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
+       .ctl_reg        = 0x4, /* send zero */
+       .enable_dma     = 0,
+       .bits_per_word  = 8,
+       .cs_change_per_word = 1,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+
+static const struct ad7877_platform_data bfin_ad7877_ts_info = {
+       .model                  = 7877,
+       .vref_delay_usecs       = 50,   /* internal, no capacitor */
+       .x_plate_ohms           = 419,
+       .y_plate_ohms           = 486,
+       .pressure_max           = 1000,
+       .pressure_min           = 0,
+       .stopacq_polarity       = 1,
+       .first_conversion_delay = 3,
+       .acquisition_time       = 1,
+       .averaging              = 1,
+       .pen_down_acc_interval  = 1,
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
+        && defined(CONFIG_SND_SOC_WM8731_SPI)
+static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 8,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+       || defined(CONFIG_SPI_ADC_BF533_MODULE)
+       {
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. */
+               .platform_data = NULL, /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
+#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE)
+       {
+               .modalias = "ad9960-spi",
+               .max_speed_hz = 10000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 1,
+               .controller_data = &ad9960_spi_chip_info,
+       },
+#endif
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+       {
+               .modalias = "spi_mmc_dummy",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 0,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias = "spi_mmc",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+#if defined(CONFIG_PBX)
+       {
+               .modalias = "fxs-spi",
+               .max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 8 - CONFIG_J11_JUMPER,
+               .controller_data = &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias = "fxo-spi",
+               .max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 8 - CONFIG_J19_JUMPER,
+               .controller_data = &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+       {
+               .modalias               = "ad7877",
+               .platform_data          = &bfin_ad7877_ts_info,
+               .irq                    = IRQ_PF8,
+               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 0,
+               .chip_select  = 2,
+               .controller_data = &spi_ad7877_chip_info,
+       },
+#endif
+#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
+        && defined(CONFIG_SND_SOC_WM8731_SPI)
+       {
+               .modalias       = "wm8731",
+               .max_speed_hz   = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 0,
+               .chip_select    = 5,
+               .controller_data = &spi_wm8731_chip_info,
+               .mode = SPI_MODE_0,
+       },
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+       {
+               .modalias = "spidev",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 1,
+               .controller_data = &spidev_chip_info,
+       },
+#endif
+};
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* SPI controller data */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+       .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+       [0] = {
+               .start = SPI0_REGBASE,
+               .end   = SPI0_REGBASE + 0xFF,
+               .flags = IORESOURCE_MEM,
+               },
+       [1] = {
+               .start = CH_SPI,
+               .end   = CH_SPI,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_spi0_device = {
+       .name = "bfin-spi",
+       .id = 0, /* Bus number */
+       .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+       .resource = bfin_spi0_resource,
+       .dev = {
+               .platform_data = &bfin_spi0_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+static struct platform_device bfin_fb_adv7393_device = {
+       .name = "bfin-adv7393",
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+       [0] = {
+               .start = TWI0_REGBASE,
+               .end   = TWI0_REGBASE,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TWI,
+               .end   = IRQ_TWI,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+       .name = "i2c-bfin-twi",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+       .resource = bfin_twi0_resource,
+};
+#endif
+
+#ifdef CONFIG_I2C_BOARDINFO
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_lcd", 0x22),
+               .type = "pcf8574_lcd",
+       },
+#endif
+#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_keypad", 0x27),
+               .type = "pcf8574_keypad",
+               .irq = IRQ_PF8,
+       },
+#endif
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+static struct platform_device bfin_sport0_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 0,
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 1,
+};
+#endif
+
+#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+#define PATA_INT       55
+
+static struct pata_platform_info bfin_pata_platform_data = {
+       .ioport_shift = 1,
+       .irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+};
+
+static struct resource bfin_pata_resources[] = {
+       {
+               .start = 0x20314020,
+               .end = 0x2031403F,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = 0x2031401C,
+               .end = 0x2031401F,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = PATA_INT,
+               .end = PATA_INT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_pata_device = {
+       .name = "pata_platform",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(bfin_pata_resources),
+       .resource = bfin_pata_resources,
+       .dev = {
+               .platform_data = &bfin_pata_platform_data,
+       }
+};
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+static struct gpio_keys_button bfin_gpio_keys_table[] = {
+       {BTN_0, GPIO_PF14, 1, "gpio-keys: BTN0"},
+};
+
+static struct gpio_keys_platform_data bfin_gpio_keys_data = {
+       .buttons        = bfin_gpio_keys_table,
+       .nbuttons       = ARRAY_SIZE(bfin_gpio_keys_table),
+};
+
+static struct platform_device bfin_device_gpiokeys = {
+       .name      = "gpio-keys",
+       .dev = {
+               .platform_data = &bfin_gpio_keys_data,
+       },
+};
+#endif
+
+static struct resource bfin_gpios_resources = {
+       .start = 0,
+       .end   = MAX_BLACKFIN_GPIOS - 1,
+       .flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+       .name = "simple-gpio",
+       .id = -1,
+       .num_resources = 1,
+       .resource = &bfin_gpios_resources,
+};
+
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_100, 400000000),
+       VRPAIR(VLEV_105, 426000000),
+       VRPAIR(VLEV_110, 500000000),
+       VRPAIR(VLEV_115, 533000000),
+       VRPAIR(VLEV_120, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
+static struct platform_device *stamp_devices[] __initdata = {
+
+       &bfin_dpmc,
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+       &bf5xx_nand_device,
+#endif
+
+#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+       &bfin_pcmcia_cf_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
+       &sl811_hcd_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+       &isp1362_hcd_device,
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+       &musb_device,
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+       &smc91x_device,
+#endif
+
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+       &dm9000_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+       &net2272_bfin_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &bfin_spi0_device,
+#endif
+
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+       &bfin_fb_adv7393_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+       &i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+       &bfin_sport0_uart_device,
+       &bfin_sport1_uart_device,
+#endif
+
+#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+       &bfin_pata_device,
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+       &bfin_device_gpiokeys,
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+       &ezkit_flash_device,
+#endif
+
+       &bfin_gpios_device,
+};
+
+static int __init stamp_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
+
+#ifdef CONFIG_I2C_BOARDINFO
+       i2c_register_board_info(0, bfin_i2c_board_info,
+                               ARRAY_SIZE(bfin_i2c_board_info));
+#endif
+
+       platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+       spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+
+#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+       irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+#endif
+       return 0;
+}
+
+arch_initcall(stamp_init);
+
+void native_machine_restart(char *cmd)
+{
+       /* workaround reboot hang when booting from SPI */
+       if ((bfin_read_SYSCR() & 0x7) == 0x3)
+               bfin_gpio_reset_spi0_ssel1();
+}
+
+void bfin_get_ether_addr(char *addr)
+{
+       random_ether_addr(addr);
+       printk(KERN_WARNING "%s:%s: Setting Ethernet MAC to a random one\n", __FILE__, __func__);
+}
+EXPORT_SYMBOL(bfin_get_ether_addr);
index 57bdb3ba2fede26bf63b3ad4ee9cab714d87f1fe..fe05cc1ef1746629971057f7a2e2eed5d250112f 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/blackfin.h>
 #include <asm/trace.h>
 
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach-common/clocks.h>
 #include <asm/mach/mem_init.h>
 #endif
@@ -185,7 +185,7 @@ ENTRY(__start)
 
        /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
        call _bf53x_relocate_l1_mem;
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
        call _start_dma_code;
 #endif
 
@@ -318,7 +318,7 @@ ENDPROC(_real_start)
 __FINIT
 
 .section .l1.text
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
 ENTRY(_start_dma_code)
 
        /* Enable PHY CLK buffer output */
@@ -398,12 +398,6 @@ ENTRY(_start_dma_code)
        w[p0] = r0.l;
        ssync;
 
-       p0.l = LO(EBIU_SDBCTL);
-       p0.h = HI(EBIU_SDBCTL);     /* SDRAM Memory Bank Control Register */
-       r0 = mem_SDBCTL;
-       w[p0] = r0.l;
-       ssync;
-
        P2.H = hi(EBIU_SDGCTL);
        P2.L = lo(EBIU_SDGCTL);
        R0 = [P2];
index 1295deac00a48379c0bdd2bfb951c56cde463f69..c671e8549b17fd5d95da3fa5117f7fb476c70f7e 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/init.h>
 #include <asm/blackfin.h>
 #include <asm/trace.h>
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach-common/clocks.h>
 #include <asm/mach/mem_init.h>
 #endif
@@ -186,7 +186,7 @@ ENTRY(__start)
 
        /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
        call _bf53x_relocate_l1_mem;
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
        call _start_dma_code;
 #endif
 
@@ -319,7 +319,7 @@ ENDPROC(_real_start)
 __FINIT
 
 .section .l1.text
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
 ENTRY(_start_dma_code)
        p0.h = hi(SIC_IWR);
        p0.l = lo(SIC_IWR);
@@ -390,12 +390,6 @@ ENTRY(_start_dma_code)
        w[p0] = r0.l;
        ssync;
 
-       p0.l = LO(EBIU_SDBCTL);
-       p0.h = HI(EBIU_SDBCTL);     /* SDRAM Memory Bank Control Register */
-       r0 = mem_SDBCTL;
-       w[p0] = r0.l;
-       ssync;
-
        P2.H = hi(EBIU_SDGCTL);
        P2.L = lo(EBIU_SDGCTL);
        R0 = [P2];
index 671f9d67f23a33b34207c965cce9ec53f386345a..6dbc76fb080b55f8428742ea2fd74de4cb5e24e2 100644 (file)
  */
 
 #include <linux/device.h>
+#include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mtd/plat-ram.h>
 #include <linux/mtd/physmap.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
@@ -355,6 +358,84 @@ static struct platform_device net2272_bfin_device = {
 };
 #endif
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
+
+static struct mtd_partition bfin_plat_nand_partitions[] = {
+       {
+               .name   = "linux kernel",
+               .size   = 0x400000,
+               .offset = 0,
+       }, {
+               .name   = "file system",
+               .size   = MTDPART_SIZ_FULL,
+               .offset = MTDPART_OFS_APPEND,
+       },
+};
+#endif
+
+#define BFIN_NAND_PLAT_CLE 2
+#define BFIN_NAND_PLAT_ALE 1
+static void bfin_plat_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct nand_chip *this = mtd->priv;
+
+       if (cmd == NAND_CMD_NONE)
+               return;
+
+       if (ctrl & NAND_CLE)
+               writeb(cmd, this->IO_ADDR_W + (1 << BFIN_NAND_PLAT_CLE));
+       else
+               writeb(cmd, this->IO_ADDR_W + (1 << BFIN_NAND_PLAT_ALE));
+}
+
+#define BFIN_NAND_PLAT_READY GPIO_PF3
+static int bfin_plat_nand_dev_ready(struct mtd_info *mtd)
+{
+       return gpio_get_value(BFIN_NAND_PLAT_READY);
+}
+
+static struct platform_nand_data bfin_plat_nand_data = {
+       .chip = {
+               .chip_delay = 30,
+#ifdef CONFIG_MTD_PARTITIONS
+               .part_probe_types = part_probes,
+               .partitions = bfin_plat_nand_partitions,
+               .nr_partitions = ARRAY_SIZE(bfin_plat_nand_partitions),
+#endif
+       },
+       .ctrl = {
+               .cmd_ctrl  = bfin_plat_nand_cmd_ctrl,
+               .dev_ready = bfin_plat_nand_dev_ready,
+       },
+};
+
+#define MAX(x, y) (x > y ? x : y)
+static struct resource bfin_plat_nand_resources = {
+       .start = 0x20212000,
+       .end   = 0x20212000 + (1 << MAX(BFIN_NAND_PLAT_CLE, BFIN_NAND_PLAT_ALE)),
+       .flags = IORESOURCE_IO,
+};
+
+static struct platform_device bfin_async_nand_device = {
+       .name = "gen_nand",
+       .id = -1,
+       .num_resources = 1,
+       .resource = &bfin_plat_nand_resources,
+       .dev = {
+               .platform_data = &bfin_plat_nand_data,
+       },
+};
+
+static void bfin_plat_nand_init(void)
+{
+       gpio_request(BFIN_NAND_PLAT_READY, "bfin_nand_plat");
+}
+#else
+static void bfin_plat_nand_init(void) {}
+#endif
+
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 static struct mtd_partition stamp_partitions[] = {
        {
@@ -780,7 +861,7 @@ static struct platform_device bfin_sport1_uart_device = {
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-#define PATA_INT       55
+#define PATA_INT       IRQ_PF5
 
 static struct pata_platform_info bfin_pata_platform_data = {
        .ioport_shift = 1,
@@ -922,6 +1003,10 @@ static struct platform_device *stamp_devices[] __initdata = {
 
        &bfin_gpios_device,
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+       &bfin_async_nand_device,
+#endif
+
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &stamp_flash_device,
 #endif
@@ -936,6 +1021,7 @@ static int __init stamp_init(void)
                                ARRAY_SIZE(bfin_i2c_board_info));
 #endif
 
+       bfin_plat_nand_init();
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 
index 48cd58a410a0b75e8a55b02e0a87b2566701bdc8..6b019eaee0b61e7847043ebee2503bae4493900f 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/blackfin.h>
 #include <asm/trace.h>
 
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach-common/clocks.h>
 #include <asm/mach/mem_init.h>
 #endif
@@ -217,7 +217,7 @@ ENTRY(__start)
 
        /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
        call _bf53x_relocate_l1_mem;
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
        call _start_dma_code;
 #endif
 
@@ -350,7 +350,7 @@ ENDPROC(_real_start)
 __FINIT
 
 .section .l1.text
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
 ENTRY(_start_dma_code)
 
        /* Enable PHY CLK buffer output */
@@ -430,12 +430,6 @@ ENTRY(_start_dma_code)
        w[p0] = r0.l;
        ssync;
 
-       p0.l = LO(EBIU_SDBCTL);
-       p0.h = HI(EBIU_SDBCTL);     /* SDRAM Memory Bank Control Register */
-       r0 = mem_SDBCTL;
-       w[p0] = r0.l;
-       ssync;
-
        P2.H = hi(EBIU_SDGCTL);
        P2.L = lo(EBIU_SDGCTL);
        R0 = [P2];
index af7c211a580eaf0763f3765d0882d15f932f00dd..166fa2201ee7a0827e03cbfc8493d9cbd99d3662 100644 (file)
@@ -61,6 +61,49 @@ const char bfin_board_name[] = "ADSP-BF548-EZKIT";
  *  Driver needs to know address, irq and flag pin.
  */
 
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+static struct resource bfin_isp1761_resources[] = {
+       [0] = {
+               .name   = "isp1761-regs",
+               .start  = 0x2C0C0000,
+               .end    = 0x2C0C0000 + 0xfffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_PG7,
+               .end    = IRQ_PG7,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_isp1761_device = {
+       .name           = "isp1761",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(bfin_isp1761_resources),
+       .resource       = bfin_isp1761_resources,
+};
+
+static struct platform_device *bfin_isp1761_devices[] = {
+       &bfin_isp1761_device,
+};
+
+int __init bfin_isp1761_init(void)
+{
+       unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
+       set_irq_type(bfin_isp1761_resources[1].start, IRQF_TRIGGER_FALLING);
+
+       return platform_add_devices(bfin_isp1761_devices, num_devices);
+}
+
+void __exit bfin_isp1761_exit(void)
+{
+       platform_device_unregister(&bfin_isp1761_device);
+}
+arch_initcall(bfin_isp1761_init);
+#endif
+
 #if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
 
 #include <asm/mach/bf54x-lq043.h>
@@ -177,6 +220,7 @@ static struct resource bfin_uart_resources[] = {
        {
                .start = 0xFFC03100,
                .end = 0xFFC031FF,
+               .flags = IORESOURCE_MEM,
        },
 #endif
 };
index f7191141a3ce104fafe7a312703ce51b28171175..06b9178cfcfe4a571b1fdded8396f53e11e355cf 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/init.h>
 #include <asm/blackfin.h>
 #include <asm/trace.h>
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach-common/clocks.h>
 #include <asm/mach/mem_init.h>
 #endif
@@ -130,7 +130,7 @@ ENTRY(__start)
 
        /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
        call _bf53x_relocate_l1_mem;
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
        call _start_dma_code;
 #endif
        /* Code for initializing Async memory banks */
@@ -288,7 +288,7 @@ ENDPROC(_real_start)
 __FINIT
 
 .section .l1.text
-#if CONFIG_BFIN_KERNEL_CLOCK
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
 ENTRY(_start_dma_code)
 
        /* Enable PHY CLK buffer output */
index 5b8bd40851dd5cdd596a62040a1d51a5adea78bc..cf1a2dff01e71b9fab72a90aa8a3e42cf937c2a0 100644 (file)
@@ -377,12 +377,6 @@ ENTRY(_start_dma_code)
        w[p0] = r0.l;
        ssync;
 
-       p0.l = LO(EBIU_SDBCTL);
-       p0.h = HI(EBIU_SDBCTL);     /* SDRAM Memory Bank Control Register */
-       r0 = mem_SDBCTL;
-       w[p0] = r0.l;
-       ssync;
-
        P2.H = hi(EBIU_SDGCTL);
        P2.L = lo(EBIU_SDGCTL);
        R0 = [P2];
index caaab49e9cfa18800c52d08a44b13fd820daaca2..f9160d83b91f5ecd632d011f71c6f29e9f7746f3 100644 (file)
@@ -53,9 +53,3 @@
 # endif
 
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
-
-#ifdef CONFIG_MEM_SIZE
-#if (CONFIG_MEM_SIZE % 4)
-#error "SDRAM mem size must be multible of 4MB"
-#endif
-#endif
index b7981d31c39212b42ea0d1ce56017e9a1867cb43..5e3f1d8a4fb881138f63a56fa8ea6bf0c9b8c144 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/linkage.h>
 #include <asm/blackfin.h>
 #include <asm/mach/irq.h>
-
+#include <asm/dpmc.h>
 
 .section .l1.text
 
@@ -51,31 +51,32 @@ ENTRY(_sleep_mode)
        RETS = [SP++];
        ( R7:0, P5:0 ) = [SP++];
        RTS;
+ENDPROC(_sleep_mode)
 
 ENTRY(_hibernate_mode)
        [--SP] = ( R7:0, P5:0 );
        [--SP] =  RETS;
 
+       R3 = R0;
+       R0 = IWR_DISABLE_ALL;
+       R1 = IWR_DISABLE_ALL;
+       R2 = IWR_DISABLE_ALL;
        call _set_sic_iwr;
+       call _set_dram_srfs;
+       SSYNC;
 
        R0 = 0xFFFF (Z);
        call _set_rtc_istat;
 
        P0.H = hi(VR_CTL);
        P0.L = lo(VR_CTL);
-       R1 = W[P0](z);
-       BITSET (R1, 8);
-       BITCLR (R1, 0);
-       BITCLR (R1, 1);
-       W[P0] = R1.L;
-       SSYNC;
 
+       W[P0] = R3.L;
        CLI R2;
        IDLE;
-
-       /* Actually, adding anything may not be necessary...SDRAM contents
-        * are lost
-        */
+.Lforever:
+       jump .Lforever;
+ENDPROC(_hibernate_mode)
 
 ENTRY(_deep_sleep)
        [--SP] = ( R7:0, P5:0 );
@@ -131,6 +132,7 @@ ENTRY(_deep_sleep)
        RETS = [SP++];
        ( R7:0, P5:0 ) = [SP++];
        RTS;
+ENDPROC(_deep_sleep)
 
 ENTRY(_sleep_deeper)
        [--SP] = ( R7:0, P5:0 );
@@ -232,53 +234,73 @@ ENTRY(_sleep_deeper)
        RETS = [SP++];
        ( R7:0, P5:0 ) = [SP++];
        RTS;
+ENDPROC(_sleep_deeper)
 
 ENTRY(_set_dram_srfs)
        /*  set the dram to self refresh mode */
-#if defined(CONFIG_BF54x)
+       SSYNC;
+#if defined(EBIU_RSTCTL)       /* DDR */
        P0.H = hi(EBIU_RSTCTL);
        P0.L = lo(EBIU_RSTCTL);
        R2 = [P0];
-       R3.H = hi(SRREQ);
-       R3.L = lo(SRREQ);
-#else
-       P0.H = hi(EBIU_SDGCTL);
+       BITSET(R2, 3); /* SRREQ enter self-refresh mode */
+       [P0] = R2;
+       SSYNC;
+1:
+       R2 = [P0];
+       CC = BITTST(R2, 4);
+       if !CC JUMP 1b;
+#else                          /* SDRAM */
        P0.L = lo(EBIU_SDGCTL);
+       P0.H = hi(EBIU_SDGCTL);
        R2 = [P0];
-       R3.H = hi(SRFS);
-       R3.L = lo(SRFS);
-#endif
-       R2 = R2|R3;
+       BITSET(R2, 24); /* SRFS enter self-refresh mode */
        [P0] = R2;
-       ssync;
-#if defined(CONFIG_BF54x)
-.LSRR_MODE:
+       SSYNC;
+
+       P0.L = lo(EBIU_SDSTAT);
+       P0.H = hi(EBIU_SDSTAT);
+1:
+       R2 = w[P0];
+       SSYNC;
+       cc = BITTST(R2, 1); /* SDSRA poll self-refresh status */
+       if !cc jump 1b;
+
+       P0.L = lo(EBIU_SDGCTL);
+       P0.H = hi(EBIU_SDGCTL);
        R2 = [P0];
-       CC = BITTST(R2, 4);
-       if !CC JUMP .LSRR_MODE;
+       BITCLR(R2, 0); /* SCTLE disable CLKOUT */
+       [P0] = R2;
 #endif
        RTS;
+ENDPROC(_set_dram_srfs)
 
 ENTRY(_unset_dram_srfs)
        /*  set the dram out of self refresh mode */
-#if defined(CONFIG_BF54x)
+#if defined(EBIU_RSTCTL)       /* DDR */
        P0.H = hi(EBIU_RSTCTL);
        P0.L = lo(EBIU_RSTCTL);
        R2 = [P0];
-       R3.H = hi(SRREQ);
-       R3.L = lo(SRREQ);
-#else
+       BITCLR(R2, 3); /* clear SRREQ bit */
+       [P0] = R2;
+#elif defined(EBIU_SDGCTL)     /* SDRAM */
+
+       P0.L = lo(EBIU_SDGCTL); /* release CLKOUT from self-refresh */
+       P0.H = hi(EBIU_SDGCTL);
+       R2 = [P0];
+       BITSET(R2, 0); /* SCTLE enable CLKOUT */
+       [P0] = R2
+       SSYNC;
+
+       P0.L = lo(EBIU_SDGCTL); /* release SDRAM from self-refresh */
        P0.H = hi(EBIU_SDGCTL);
-       P0.L = lo(EBIU_SDGCTL);
        R2 = [P0];
-       R3.H = hi(SRFS);
-       R3.L = lo(SRFS);
+       BITCLR(R2, 24); /* clear SRFS bit */
+       [P0] = R2
 #endif
-       R3 = ~R3;
-       R2 = R2&R3;
-       [P0] = R2;
-       ssync;
+       SSYNC;
        RTS;
+ENDPROC(_unset_dram_srfs)
 
 ENTRY(_set_sic_iwr)
 #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)  || defined(CONFIG_BF561)
@@ -300,6 +322,7 @@ ENTRY(_set_sic_iwr)
 
        SSYNC;
        RTS;
+ENDPROC(_set_sic_iwr)
 
 ENTRY(_set_rtc_istat)
 #ifndef CONFIG_BF561
@@ -307,8 +330,14 @@ ENTRY(_set_rtc_istat)
        P0.L = lo(RTC_ISTAT);
        w[P0] = R0.L;
        SSYNC;
+#elif (ANOMALY_05000371)
+       nop;
+       nop;
+       nop;
+       nop;
 #endif
        RTS;
+ENDPROC(_set_rtc_istat)
 
 ENTRY(_test_pll_locked)
        P0.H = hi(PLL_STAT);
@@ -318,3 +347,509 @@ ENTRY(_test_pll_locked)
        CC = BITTST(R0,5);
        IF !CC JUMP 1b;
        RTS;
+ENDPROC(_test_pll_locked)
+
+.section .text
+
+ENTRY(_do_hibernate)
+       [--SP] = ( R7:0, P5:0 );
+       [--SP] =  RETS;
+       /* Save System MMRs */
+       R2 = R0;
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+
+#ifdef SIC_IMASK0
+       PM_SYS_PUSH(SIC_IMASK0)
+#endif
+#ifdef SIC_IMASK1
+       PM_SYS_PUSH(SIC_IMASK1)
+#endif
+#ifdef SIC_IMASK2
+       PM_SYS_PUSH(SIC_IMASK2)
+#endif
+#ifdef SIC_IMASK
+       PM_SYS_PUSH(SIC_IMASK)
+#endif
+#ifdef SICA_IMASK0
+       PM_SYS_PUSH(SICA_IMASK0)
+#endif
+#ifdef SICA_IMASK1
+       PM_SYS_PUSH(SICA_IMASK1)
+#endif
+#ifdef SIC_IAR2
+       PM_SYS_PUSH(SIC_IAR0)
+       PM_SYS_PUSH(SIC_IAR1)
+       PM_SYS_PUSH(SIC_IAR2)
+#endif
+#ifdef SIC_IAR3
+       PM_SYS_PUSH(SIC_IAR3)
+#endif
+#ifdef SIC_IAR4
+       PM_SYS_PUSH(SIC_IAR4)
+       PM_SYS_PUSH(SIC_IAR5)
+       PM_SYS_PUSH(SIC_IAR6)
+#endif
+#ifdef SIC_IAR7
+       PM_SYS_PUSH(SIC_IAR7)
+#endif
+#ifdef SIC_IAR8
+       PM_SYS_PUSH(SIC_IAR8)
+       PM_SYS_PUSH(SIC_IAR9)
+       PM_SYS_PUSH(SIC_IAR10)
+       PM_SYS_PUSH(SIC_IAR11)
+#endif
+
+#ifdef SICA_IAR0
+       PM_SYS_PUSH(SICA_IAR0)
+       PM_SYS_PUSH(SICA_IAR1)
+       PM_SYS_PUSH(SICA_IAR2)
+       PM_SYS_PUSH(SICA_IAR3)
+       PM_SYS_PUSH(SICA_IAR4)
+       PM_SYS_PUSH(SICA_IAR5)
+       PM_SYS_PUSH(SICA_IAR6)
+       PM_SYS_PUSH(SICA_IAR7)
+#endif
+
+#ifdef SIC_IWR
+       PM_SYS_PUSH(SIC_IWR)
+#endif
+#ifdef SIC_IWR0
+       PM_SYS_PUSH(SIC_IWR0)
+#endif
+#ifdef SIC_IWR1
+       PM_SYS_PUSH(SIC_IWR1)
+#endif
+#ifdef SIC_IWR2
+       PM_SYS_PUSH(SIC_IWR2)
+#endif
+#ifdef SICA_IWR0
+       PM_SYS_PUSH(SICA_IWR0)
+#endif
+#ifdef SICA_IWR1
+       PM_SYS_PUSH(SICA_IWR1)
+#endif
+
+#ifdef PINT0_ASSIGN
+       PM_SYS_PUSH(PINT0_ASSIGN)
+       PM_SYS_PUSH(PINT1_ASSIGN)
+       PM_SYS_PUSH(PINT2_ASSIGN)
+       PM_SYS_PUSH(PINT3_ASSIGN)
+#endif
+
+       PM_SYS_PUSH(EBIU_AMBCTL0)
+       PM_SYS_PUSH(EBIU_AMBCTL1)
+       PM_SYS_PUSH16(EBIU_AMGCTL)
+
+#ifdef EBIU_FCTL
+       PM_SYS_PUSH(EBIU_MBSCTL)
+       PM_SYS_PUSH(EBIU_MODE)
+       PM_SYS_PUSH(EBIU_FCTL)
+#endif
+
+       PM_SYS_PUSH16(SYSCR)
+
+       /* Save Core MMRs */
+       P0.H = hi(SRAM_BASE_ADDRESS);
+       P0.L = lo(SRAM_BASE_ADDRESS);
+
+       PM_PUSH(DMEM_CONTROL)
+       PM_PUSH(DCPLB_ADDR0)
+       PM_PUSH(DCPLB_ADDR1)
+       PM_PUSH(DCPLB_ADDR2)
+       PM_PUSH(DCPLB_ADDR3)
+       PM_PUSH(DCPLB_ADDR4)
+       PM_PUSH(DCPLB_ADDR5)
+       PM_PUSH(DCPLB_ADDR6)
+       PM_PUSH(DCPLB_ADDR7)
+       PM_PUSH(DCPLB_ADDR8)
+       PM_PUSH(DCPLB_ADDR9)
+       PM_PUSH(DCPLB_ADDR10)
+       PM_PUSH(DCPLB_ADDR11)
+       PM_PUSH(DCPLB_ADDR12)
+       PM_PUSH(DCPLB_ADDR13)
+       PM_PUSH(DCPLB_ADDR14)
+       PM_PUSH(DCPLB_ADDR15)
+       PM_PUSH(DCPLB_DATA0)
+       PM_PUSH(DCPLB_DATA1)
+       PM_PUSH(DCPLB_DATA2)
+       PM_PUSH(DCPLB_DATA3)
+       PM_PUSH(DCPLB_DATA4)
+       PM_PUSH(DCPLB_DATA5)
+       PM_PUSH(DCPLB_DATA6)
+       PM_PUSH(DCPLB_DATA7)
+       PM_PUSH(DCPLB_DATA8)
+       PM_PUSH(DCPLB_DATA9)
+       PM_PUSH(DCPLB_DATA10)
+       PM_PUSH(DCPLB_DATA11)
+       PM_PUSH(DCPLB_DATA12)
+       PM_PUSH(DCPLB_DATA13)
+       PM_PUSH(DCPLB_DATA14)
+       PM_PUSH(DCPLB_DATA15)
+       PM_PUSH(IMEM_CONTROL)
+       PM_PUSH(ICPLB_ADDR0)
+       PM_PUSH(ICPLB_ADDR1)
+       PM_PUSH(ICPLB_ADDR2)
+       PM_PUSH(ICPLB_ADDR3)
+       PM_PUSH(ICPLB_ADDR4)
+       PM_PUSH(ICPLB_ADDR5)
+       PM_PUSH(ICPLB_ADDR6)
+       PM_PUSH(ICPLB_ADDR7)
+       PM_PUSH(ICPLB_ADDR8)
+       PM_PUSH(ICPLB_ADDR9)
+       PM_PUSH(ICPLB_ADDR10)
+       PM_PUSH(ICPLB_ADDR11)
+       PM_PUSH(ICPLB_ADDR12)
+       PM_PUSH(ICPLB_ADDR13)
+       PM_PUSH(ICPLB_ADDR14)
+       PM_PUSH(ICPLB_ADDR15)
+       PM_PUSH(ICPLB_DATA0)
+       PM_PUSH(ICPLB_DATA1)
+       PM_PUSH(ICPLB_DATA2)
+       PM_PUSH(ICPLB_DATA3)
+       PM_PUSH(ICPLB_DATA4)
+       PM_PUSH(ICPLB_DATA5)
+       PM_PUSH(ICPLB_DATA6)
+       PM_PUSH(ICPLB_DATA7)
+       PM_PUSH(ICPLB_DATA8)
+       PM_PUSH(ICPLB_DATA9)
+       PM_PUSH(ICPLB_DATA10)
+       PM_PUSH(ICPLB_DATA11)
+       PM_PUSH(ICPLB_DATA12)
+       PM_PUSH(ICPLB_DATA13)
+       PM_PUSH(ICPLB_DATA14)
+       PM_PUSH(ICPLB_DATA15)
+       PM_PUSH(EVT0)
+       PM_PUSH(EVT1)
+       PM_PUSH(EVT2)
+       PM_PUSH(EVT3)
+       PM_PUSH(EVT4)
+       PM_PUSH(EVT5)
+       PM_PUSH(EVT6)
+       PM_PUSH(EVT7)
+       PM_PUSH(EVT8)
+       PM_PUSH(EVT9)
+       PM_PUSH(EVT10)
+       PM_PUSH(EVT11)
+       PM_PUSH(EVT12)
+       PM_PUSH(EVT13)
+       PM_PUSH(EVT14)
+       PM_PUSH(EVT15)
+       PM_PUSH(IMASK)
+       PM_PUSH(ILAT)
+       PM_PUSH(IPRIO)
+       PM_PUSH(TCNTL)
+       PM_PUSH(TPERIOD)
+       PM_PUSH(TSCALE)
+       PM_PUSH(TCOUNT)
+       PM_PUSH(TBUFCTL)
+
+       /* Save Core Registers */
+       [--sp] = SYSCFG;
+       [--sp] = ( R7:0, P5:0 );
+       [--sp] = fp;
+       [--sp] = usp;
+
+       [--sp] = i0;
+       [--sp] = i1;
+       [--sp] = i2;
+       [--sp] = i3;
+
+       [--sp] = m0;
+       [--sp] = m1;
+       [--sp] = m2;
+       [--sp] = m3;
+
+       [--sp] = l0;
+       [--sp] = l1;
+       [--sp] = l2;
+       [--sp] = l3;
+
+       [--sp] = b0;
+       [--sp] = b1;
+       [--sp] = b2;
+       [--sp] = b3;
+       [--sp] = a0.x;
+       [--sp] = a0.w;
+       [--sp] = a1.x;
+       [--sp] = a1.w;
+
+       [--sp] = LC0;
+       [--sp] = LC1;
+       [--sp] = LT0;
+       [--sp] = LT1;
+       [--sp] = LB0;
+       [--sp] = LB1;
+
+       [--sp] = ASTAT;
+       [--sp] = CYCLES;
+       [--sp] = CYCLES2;
+
+       [--sp] = RETS;
+       r0 = RETI;
+       [--sp] = r0;
+       [--sp] = RETX;
+       [--sp] = RETN;
+       [--sp] = RETE;
+       [--sp] = SEQSTAT;
+
+       /* Save Magic, return address and Stack Pointer */
+       P0.H = 0;
+       P0.L = 0;
+       R0.H = 0xDEAD;  /* Hibernate Magic */
+       R0.L = 0xBEEF;
+       [P0++] = R0;    /* Store Hibernate Magic */
+       R0.H = .Lpm_resume_here;
+       R0.L = .Lpm_resume_here;
+       [P0++] = R0;    /* Save Return Address */
+       [P0++] = SP;    /* Save Stack Pointer */
+       P0.H = _hibernate_mode;
+       P0.L = _hibernate_mode;
+       R0 = R2;
+       call (P0); /* Goodbye */
+
+.Lpm_resume_here:
+
+       /* Restore Core Registers */
+       SEQSTAT = [sp++];
+       RETE = [sp++];
+       RETN = [sp++];
+       RETX = [sp++];
+       r0 = [sp++];
+       RETI = r0;
+       RETS = [sp++];
+
+       CYCLES2 = [sp++];
+       CYCLES = [sp++];
+       ASTAT = [sp++];
+
+       LB1 = [sp++];
+       LB0 = [sp++];
+       LT1 = [sp++];
+       LT0 = [sp++];
+       LC1 = [sp++];
+       LC0 = [sp++];
+
+       a1.w = [sp++];
+       a1.x = [sp++];
+       a0.w = [sp++];
+       a0.x = [sp++];
+       b3 = [sp++];
+       b2 = [sp++];
+       b1 = [sp++];
+       b0 = [sp++];
+
+       l3 = [sp++];
+       l2 = [sp++];
+       l1 = [sp++];
+       l0 = [sp++];
+
+       m3 = [sp++];
+       m2 = [sp++];
+       m1 = [sp++];
+       m0 = [sp++];
+
+       i3 = [sp++];
+       i2 = [sp++];
+       i1 = [sp++];
+       i0 = [sp++];
+
+       usp = [sp++];
+       fp = [sp++];
+
+       ( R7 : 0, P5 : 0) = [ SP ++ ];
+       SYSCFG = [sp++];
+
+       /* Restore Core MMRs */
+
+       PM_POP(TBUFCTL)
+       PM_POP(TCOUNT)
+       PM_POP(TSCALE)
+       PM_POP(TPERIOD)
+       PM_POP(TCNTL)
+       PM_POP(IPRIO)
+       PM_POP(ILAT)
+       PM_POP(IMASK)
+       PM_POP(EVT15)
+       PM_POP(EVT14)
+       PM_POP(EVT13)
+       PM_POP(EVT12)
+       PM_POP(EVT11)
+       PM_POP(EVT10)
+       PM_POP(EVT9)
+       PM_POP(EVT8)
+       PM_POP(EVT7)
+       PM_POP(EVT6)
+       PM_POP(EVT5)
+       PM_POP(EVT4)
+       PM_POP(EVT3)
+       PM_POP(EVT2)
+       PM_POP(EVT1)
+       PM_POP(EVT0)
+       PM_POP(ICPLB_DATA15)
+       PM_POP(ICPLB_DATA14)
+       PM_POP(ICPLB_DATA13)
+       PM_POP(ICPLB_DATA12)
+       PM_POP(ICPLB_DATA11)
+       PM_POP(ICPLB_DATA10)
+       PM_POP(ICPLB_DATA9)
+       PM_POP(ICPLB_DATA8)
+       PM_POP(ICPLB_DATA7)
+       PM_POP(ICPLB_DATA6)
+       PM_POP(ICPLB_DATA5)
+       PM_POP(ICPLB_DATA4)
+       PM_POP(ICPLB_DATA3)
+       PM_POP(ICPLB_DATA2)
+       PM_POP(ICPLB_DATA1)
+       PM_POP(ICPLB_DATA0)
+       PM_POP(ICPLB_ADDR15)
+       PM_POP(ICPLB_ADDR14)
+       PM_POP(ICPLB_ADDR13)
+       PM_POP(ICPLB_ADDR12)
+       PM_POP(ICPLB_ADDR11)
+       PM_POP(ICPLB_ADDR10)
+       PM_POP(ICPLB_ADDR9)
+       PM_POP(ICPLB_ADDR8)
+       PM_POP(ICPLB_ADDR7)
+       PM_POP(ICPLB_ADDR6)
+       PM_POP(ICPLB_ADDR5)
+       PM_POP(ICPLB_ADDR4)
+       PM_POP(ICPLB_ADDR3)
+       PM_POP(ICPLB_ADDR2)
+       PM_POP(ICPLB_ADDR1)
+       PM_POP(ICPLB_ADDR0)
+       PM_POP(IMEM_CONTROL)
+       PM_POP(DCPLB_DATA15)
+       PM_POP(DCPLB_DATA14)
+       PM_POP(DCPLB_DATA13)
+       PM_POP(DCPLB_DATA12)
+       PM_POP(DCPLB_DATA11)
+       PM_POP(DCPLB_DATA10)
+       PM_POP(DCPLB_DATA9)
+       PM_POP(DCPLB_DATA8)
+       PM_POP(DCPLB_DATA7)
+       PM_POP(DCPLB_DATA6)
+       PM_POP(DCPLB_DATA5)
+       PM_POP(DCPLB_DATA4)
+       PM_POP(DCPLB_DATA3)
+       PM_POP(DCPLB_DATA2)
+       PM_POP(DCPLB_DATA1)
+       PM_POP(DCPLB_DATA0)
+       PM_POP(DCPLB_ADDR15)
+       PM_POP(DCPLB_ADDR14)
+       PM_POP(DCPLB_ADDR13)
+       PM_POP(DCPLB_ADDR12)
+       PM_POP(DCPLB_ADDR11)
+       PM_POP(DCPLB_ADDR10)
+       PM_POP(DCPLB_ADDR9)
+       PM_POP(DCPLB_ADDR8)
+       PM_POP(DCPLB_ADDR7)
+       PM_POP(DCPLB_ADDR6)
+       PM_POP(DCPLB_ADDR5)
+       PM_POP(DCPLB_ADDR4)
+       PM_POP(DCPLB_ADDR3)
+       PM_POP(DCPLB_ADDR2)
+       PM_POP(DCPLB_ADDR1)
+       PM_POP(DCPLB_ADDR0)
+       PM_POP(DMEM_CONTROL)
+
+       /* Restore System MMRs */
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       PM_SYS_POP16(SYSCR)
+
+#ifdef EBIU_FCTL
+       PM_SYS_POP(EBIU_FCTL)
+       PM_SYS_POP(EBIU_MODE)
+       PM_SYS_POP(EBIU_MBSCTL)
+#endif
+       PM_SYS_POP16(EBIU_AMGCTL)
+       PM_SYS_POP(EBIU_AMBCTL1)
+       PM_SYS_POP(EBIU_AMBCTL0)
+
+#ifdef PINT0_ASSIGN
+       PM_SYS_POP(PINT3_ASSIGN)
+       PM_SYS_POP(PINT2_ASSIGN)
+       PM_SYS_POP(PINT1_ASSIGN)
+       PM_SYS_POP(PINT0_ASSIGN)
+#endif
+
+#ifdef SICA_IWR1
+       PM_SYS_POP(SICA_IWR1)
+#endif
+#ifdef SICA_IWR0
+       PM_SYS_POP(SICA_IWR0)
+#endif
+#ifdef SIC_IWR2
+       PM_SYS_POP(SIC_IWR2)
+#endif
+#ifdef SIC_IWR1
+       PM_SYS_POP(SIC_IWR1)
+#endif
+#ifdef SIC_IWR0
+       PM_SYS_POP(SIC_IWR0)
+#endif
+#ifdef SIC_IWR
+       PM_SYS_POP(SIC_IWR)
+#endif
+
+#ifdef SICA_IAR0
+       PM_SYS_POP(SICA_IAR7)
+       PM_SYS_POP(SICA_IAR6)
+       PM_SYS_POP(SICA_IAR5)
+       PM_SYS_POP(SICA_IAR4)
+       PM_SYS_POP(SICA_IAR3)
+       PM_SYS_POP(SICA_IAR2)
+       PM_SYS_POP(SICA_IAR1)
+       PM_SYS_POP(SICA_IAR0)
+#endif
+
+#ifdef SIC_IAR8
+       PM_SYS_POP(SIC_IAR11)
+       PM_SYS_POP(SIC_IAR10)
+       PM_SYS_POP(SIC_IAR9)
+       PM_SYS_POP(SIC_IAR8)
+#endif
+#ifdef SIC_IAR7
+       PM_SYS_POP(SIC_IAR7)
+#endif
+#ifdef SIC_IAR6
+       PM_SYS_POP(SIC_IAR6)
+       PM_SYS_POP(SIC_IAR5)
+       PM_SYS_POP(SIC_IAR4)
+#endif
+#ifdef SIC_IAR3
+       PM_SYS_POP(SIC_IAR3)
+#endif
+#ifdef SIC_IAR2
+       PM_SYS_POP(SIC_IAR2)
+       PM_SYS_POP(SIC_IAR1)
+       PM_SYS_POP(SIC_IAR0)
+#endif
+#ifdef SICA_IMASK1
+       PM_SYS_POP(SICA_IMASK1)
+#endif
+#ifdef SICA_IMASK0
+       PM_SYS_POP(SICA_IMASK0)
+#endif
+#ifdef SIC_IMASK
+       PM_SYS_POP(SIC_IMASK)
+#endif
+#ifdef SIC_IMASK2
+       PM_SYS_POP(SIC_IMASK2)
+#endif
+#ifdef SIC_IMASK1
+       PM_SYS_POP(SIC_IMASK1)
+#endif
+#ifdef SIC_IMASK0
+       PM_SYS_POP(SIC_IMASK0)
+#endif
+
+       [--sp] = RETI;  /* Clear Global Interrupt Disable */
+       SP += 4;
+
+       RETS = [SP++];
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+ENDPROC(_do_hibernate)
index 038f70e0be65cb4adcb1ada19b07f6d75eba7d8b..eceb484d90f9da1144a1c1afca1e019f29a3f672 100644 (file)
@@ -158,23 +158,45 @@ ENTRY(_ex_single_step)
        cc = r7 == r6;
        if cc jump _bfin_return_from_exception;
 
+       /* Don't do single step in hardware exception handler */
+        p5.l = lo(IPEND);
+        p5.h = hi(IPEND);
+       r6 = [p5];
+       cc = bittst(r6, 5);
+       if cc jump _bfin_return_from_exception;
+
+#ifdef CONFIG_KGDB
+       /* skip single step if current interrupt priority is higher than
+        * that of the first instruction, from which gdb starts single step */
+       r6 >>= 6;
+       r7 = 10;
+.Lfind_priority_start:
+       cc = bittst(r6, 0);
+       if cc jump .Lfind_priority_done;
+       r6 >>= 1;
+       r7 += -1;
+       cc = r7 == 0;
+       if cc jump .Lfind_priority_done;
+       jump.s .Lfind_priority_start;
+.Lfind_priority_done:
+       p4.l = _debugger_step;
+       p4.h = _debugger_step;
+       r6 = [p4];
+       cc = r6 == 0;
+       if cc jump .Ldo_single_step;
+       r6 += -1;
+       cc = r6 < r7;
+       if cc jump _bfin_return_from_exception;
+.Ldo_single_step:
+#endif
+
        /* If we were in user mode, do the single step normally.  */
-       p5.l = lo(IPEND);
-       p5.h = hi(IPEND);
        r6 = [p5];
        r7 = 0xffe0 (z);
        r7 = r7 & r6;
        cc = r7 == 0;
-       if !cc jump 1f;
-
-       /* Single stepping only a single instruction, so clear the trace
-        * bit here.  */
-       r7 = syscfg;
-       bitclr (r7, 0);
-       syscfg = R7;
-       jump _ex_trap_c;
+       if cc jump 1f;
 
-1:
        /*
         * We were in an interrupt handler.  By convention, all of them save
         * SYSCFG with their first instruction, so by checking whether our
@@ -202,11 +224,15 @@ ENTRY(_ex_single_step)
        cc = R7 == R6;
        if !cc jump _bfin_return_from_exception;
 
+1:
+       /* Single stepping only a single instruction, so clear the trace
+        * bit here.  */
        r7 = syscfg;
        bitclr (r7, 0);
        syscfg = R7;
 
-       /* Fall through to _bfin_return_from_exception.  */
+       jump _ex_trap_c;
+
 ENDPROC(_ex_single_step)
 
 ENTRY(_bfin_return_from_exception)
index f5fd768022eaeb13cab7d7be9dd24b8e86c6d5e7..64d746114e4b2897ee28cc6c4a4d0091d0b5a6b3 100644 (file)
@@ -459,6 +459,8 @@ static struct irq_chip bfin_gpio_irqchip = {
        .mask = bfin_gpio_mask_irq,
        .mask_ack = bfin_gpio_mask_ack_irq,
        .unmask = bfin_gpio_unmask_irq,
+       .disable = bfin_gpio_mask_irq,
+       .enable = bfin_gpio_unmask_irq,
        .set_type = bfin_gpio_irq_type,
        .startup = bfin_gpio_irq_startup,
        .shutdown = bfin_gpio_irq_shutdown,
@@ -846,6 +848,8 @@ static struct irq_chip bfin_gpio_irqchip = {
        .mask = bfin_gpio_mask_irq,
        .mask_ack = bfin_gpio_mask_ack_irq,
        .unmask = bfin_gpio_unmask_irq,
+       .disable = bfin_gpio_mask_irq,
+       .enable = bfin_gpio_unmask_irq,
        .set_type = bfin_gpio_irq_type,
        .startup = bfin_gpio_irq_startup,
        .shutdown = bfin_gpio_irq_shutdown,
index 0be805ca423f06f604099cfb2c2a8e7f2d0a4e80..4fe6a2366b133e2a9e0a5101d9728f3394335e73 100644 (file)
@@ -38,8 +38,9 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 
-#include <asm/dpmc.h>
 #include <asm/gpio.h>
+#include <asm/dma.h>
+#include <asm/dpmc.h>
 
 #ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H
 #define WAKEUP_TYPE    PM_WAKE_HIGH
 #define WAKEUP_TYPE    PM_WAKE_BOTH_EDGES
 #endif
 
+
 void bfin_pm_suspend_standby_enter(void)
 {
+       unsigned long flags;
+
 #ifdef CONFIG_PM_WAKEUP_BY_GPIO
        gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE);
 #endif
 
-       u32 flags;
-
        local_irq_save(flags);
-       bfin_pm_setup();
+       bfin_pm_standby_setup();
 
 #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
        sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
@@ -78,7 +80,7 @@ void bfin_pm_suspend_standby_enter(void)
        sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
 #endif
 
-       bfin_pm_restore();
+       bfin_pm_standby_restore();
 
 #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)  || defined(CONFIG_BF561)
        bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
@@ -93,6 +95,195 @@ void bfin_pm_suspend_standby_enter(void)
        local_irq_restore(flags);
 }
 
+int bf53x_suspend_l1_mem(unsigned char *memptr)
+{
+       dma_memcpy(memptr, (const void *) L1_CODE_START, L1_CODE_LENGTH);
+       dma_memcpy(memptr + L1_CODE_LENGTH, (const void *) L1_DATA_A_START,
+                       L1_DATA_A_LENGTH);
+       dma_memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH,
+                       (const void *) L1_DATA_B_START, L1_DATA_B_LENGTH);
+       memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH +
+                       L1_DATA_B_LENGTH, (const void *) L1_SCRATCH_START,
+                       L1_SCRATCH_LENGTH);
+
+       return 0;
+}
+
+int bf53x_resume_l1_mem(unsigned char *memptr)
+{
+       dma_memcpy((void *) L1_CODE_START, memptr, L1_CODE_LENGTH);
+       dma_memcpy((void *) L1_DATA_A_START, memptr + L1_CODE_LENGTH,
+                       L1_DATA_A_LENGTH);
+       dma_memcpy((void *) L1_DATA_B_START, memptr + L1_CODE_LENGTH +
+                       L1_DATA_A_LENGTH, L1_DATA_B_LENGTH);
+       memcpy((void *) L1_SCRATCH_START, memptr + L1_CODE_LENGTH +
+                       L1_DATA_A_LENGTH + L1_DATA_B_LENGTH, L1_SCRATCH_LENGTH);
+
+       return 0;
+}
+
+#ifdef CONFIG_BFIN_WB
+static void flushinv_all_dcache(void)
+{
+       u32 way, bank, subbank, set;
+       u32 status, addr;
+       u32 dmem_ctl = bfin_read_DMEM_CONTROL();
+
+       for (bank = 0; bank < 2; ++bank) {
+               if (!(dmem_ctl & (1 << (DMC1_P - bank))))
+                       continue;
+
+               for (way = 0; way < 2; ++way)
+                       for (subbank = 0; subbank < 4; ++subbank)
+                               for (set = 0; set < 64; ++set) {
+
+                                       bfin_write_DTEST_COMMAND(
+                                               way << 26 |
+                                               bank << 23 |
+                                               subbank << 16 |
+                                               set << 5
+                                       );
+                                       CSYNC();
+                                       status = bfin_read_DTEST_DATA0();
+
+                                       /* only worry about valid/dirty entries */
+                                       if ((status & 0x3) != 0x3)
+                                               continue;
+
+                                       /* construct the address using the tag */
+                                       addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
+
+                                       /* flush it */
+                                       __asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr));
+                               }
+       }
+}
+#endif
+
+static inline void dcache_disable(void)
+{
+#ifdef CONFIG_BFIN_DCACHE
+       unsigned long ctrl;
+
+#ifdef CONFIG_BFIN_WB
+       flushinv_all_dcache();
+#endif
+       SSYNC();
+       ctrl = bfin_read_DMEM_CONTROL();
+       ctrl &= ~ENDCPLB;
+       bfin_write_DMEM_CONTROL(ctrl);
+       SSYNC();
+#endif
+}
+
+static inline void dcache_enable(void)
+{
+#ifdef CONFIG_BFIN_DCACHE
+       unsigned long ctrl;
+       SSYNC();
+       ctrl = bfin_read_DMEM_CONTROL();
+       ctrl |= ENDCPLB;
+       bfin_write_DMEM_CONTROL(ctrl);
+       SSYNC();
+#endif
+}
+
+static inline void icache_disable(void)
+{
+#ifdef CONFIG_BFIN_ICACHE
+       unsigned long ctrl;
+       SSYNC();
+       ctrl = bfin_read_IMEM_CONTROL();
+       ctrl &= ~ENICPLB;
+       bfin_write_IMEM_CONTROL(ctrl);
+       SSYNC();
+#endif
+}
+
+static inline void icache_enable(void)
+{
+#ifdef CONFIG_BFIN_ICACHE
+       unsigned long ctrl;
+       SSYNC();
+       ctrl = bfin_read_IMEM_CONTROL();
+       ctrl |= ENICPLB;
+       bfin_write_IMEM_CONTROL(ctrl);
+       SSYNC();
+#endif
+}
+
+int bfin_pm_suspend_mem_enter(void)
+{
+       unsigned long flags;
+       int wakeup, ret;
+
+       unsigned char *memptr = kmalloc(L1_CODE_LENGTH + L1_DATA_A_LENGTH
+                                        + L1_DATA_B_LENGTH + L1_SCRATCH_LENGTH,
+                                         GFP_KERNEL);
+
+       if (memptr == NULL) {
+               panic("bf53x_suspend_l1_mem malloc failed");
+               return -ENOMEM;
+       }
+
+       wakeup = bfin_read_VR_CTL() & ~FREQ;
+       wakeup |= SCKELOW;
+
+       /* FIXME: merge this somehow with set_irq_wake */
+#ifdef CONFIG_PM_BFIN_WAKE_RTC
+       wakeup |= WAKE;
+#endif
+#ifdef CONFIG_PM_BFIN_WAKE_PH6
+       wakeup |= PHYWE;
+#endif
+#ifdef CONFIG_PM_BFIN_WAKE_CAN
+       wakeup |= CANWE;
+#endif
+#ifdef CONFIG_PM_BFIN_WAKE_GP
+       wakeup |= GPWE;
+#endif
+#ifdef CONFIG_PM_BFIN_WAKE_USB
+       wakeup |= USBWE;
+#endif
+#ifdef CONFIG_PM_BFIN_WAKE_KEYPAD
+       wakeup |= KPADWE;
+#endif
+#ifdef CONFIG_PM_BFIN_WAKE_ROTARY
+       wakeup |= ROTWE;
+#endif
+
+       local_irq_save(flags);
+
+       ret = blackfin_dma_suspend();
+
+       if (ret) {
+               local_irq_restore(flags);
+               kfree(memptr);
+               return ret;
+       }
+
+       bfin_gpio_pm_hibernate_suspend();
+
+       dcache_disable();
+       icache_disable();
+       bf53x_suspend_l1_mem(memptr);
+
+       do_hibernate(wakeup);   /* Goodbye */
+
+       bf53x_resume_l1_mem(memptr);
+
+       icache_enable();
+       dcache_enable();
+
+       bfin_gpio_pm_hibernate_restore();
+       blackfin_dma_resume();
+
+       local_irq_restore(flags);
+       kfree(memptr);
+
+       return 0;
+}
+
 /*
  *     bfin_pm_valid - Tell the PM core that we only support the standby sleep
  *                     state
@@ -101,7 +292,24 @@ void bfin_pm_suspend_standby_enter(void)
  */
 static int bfin_pm_valid(suspend_state_t state)
 {
-       return (state == PM_SUSPEND_STANDBY);
+       return (state == PM_SUSPEND_STANDBY
+#ifndef BF533_FAMILY
+       /*
+        * On BF533/2/1:
+        * If we enter Hibernate the SCKE Pin is driven Low,
+        * so that the SDRAM enters Self Refresh Mode.
+        * However when the reset sequence that follows hibernate
+        * state is executed, SCKE is driven High, taking the
+        * SDRAM out of Self Refresh.
+        *
+        * If you reconfigure and access the SDRAM "very quickly",
+        * you are likely to avoid errors, otherwise the SDRAM
+        * start losing its contents.
+        * An external HW workaround is possible using logic gates.
+        */
+       || state == PM_SUSPEND_MEM
+#endif
+       );
 }
 
 /*
@@ -115,10 +323,9 @@ static int bfin_pm_enter(suspend_state_t state)
        case PM_SUSPEND_STANDBY:
                bfin_pm_suspend_standby_enter();
                break;
-
        case PM_SUSPEND_MEM:
-               return -ENOTSUPP;
-
+               bfin_pm_suspend_mem_enter();
+               break;
        default:
                return -EINVAL;
        }
index 3246f91c7baa40bc87fc30436b9ec7022092b356..5af3c31c9365a8962d1d8d89a081f8764c16fa0f 100644 (file)
 #include <asm/blackfin.h>
 #include "blackfin_sram.h"
 
-spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock;
-
-#if CONFIG_L1_MAX_PIECE < 16
-#undef CONFIG_L1_MAX_PIECE
-#define CONFIG_L1_MAX_PIECE        16
-#endif
-
-#if CONFIG_L1_MAX_PIECE > 1024
-#undef CONFIG_L1_MAX_PIECE
-#define CONFIG_L1_MAX_PIECE        1024
-#endif
-
-#define SRAM_SLT_NULL      0
-#define SRAM_SLT_FREE      1
-#define SRAM_SLT_ALLOCATED 2
+static spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock;
+static spinlock_t l2_sram_lock;
 
 /* the data structure for L1 scratchpad and DATA SRAM */
-struct l1_sram_piece {
+struct sram_piece {
        void *paddr;
        int size;
-       int flag;
        pid_t pid;
+       struct sram_piece *next;
 };
 
-static struct l1_sram_piece l1_ssram[CONFIG_L1_MAX_PIECE];
+static struct sram_piece free_l1_ssram_head, used_l1_ssram_head;
 
 #if L1_DATA_A_LENGTH != 0
-static struct l1_sram_piece l1_data_A_sram[CONFIG_L1_MAX_PIECE];
+static struct sram_piece free_l1_data_A_sram_head, used_l1_data_A_sram_head;
 #endif
 
 #if L1_DATA_B_LENGTH != 0
-static struct l1_sram_piece l1_data_B_sram[CONFIG_L1_MAX_PIECE];
+static struct sram_piece free_l1_data_B_sram_head, used_l1_data_B_sram_head;
 #endif
 
 #if L1_CODE_LENGTH != 0
-static struct l1_sram_piece l1_inst_sram[CONFIG_L1_MAX_PIECE];
+static struct sram_piece free_l1_inst_sram_head, used_l1_inst_sram_head;
+#endif
+
+#ifdef L2_LENGTH
+static struct sram_piece free_l2_sram_head, used_l2_sram_head;
 #endif
 
+static struct kmem_cache *sram_piece_cache;
+
 /* L1 Scratchpad SRAM initialization function */
-void __init l1sram_init(void)
+static void __init l1sram_init(void)
 {
-       printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
-              L1_SCRATCH_LENGTH >> 10);
+       free_l1_ssram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l1_ssram_head.next) {
+               printk(KERN_INFO"Fail to initialize Scratchpad data SRAM.\n");
+               return;
+       }
+
+       free_l1_ssram_head.next->paddr = (void *)L1_SCRATCH_START;
+       free_l1_ssram_head.next->size = L1_SCRATCH_LENGTH;
+       free_l1_ssram_head.next->pid = 0;
+       free_l1_ssram_head.next->next = NULL;
 
-       memset(&l1_ssram, 0x00, sizeof(l1_ssram));
-       l1_ssram[0].paddr = (void *)L1_SCRATCH_START;
-       l1_ssram[0].size = L1_SCRATCH_LENGTH;
-       l1_ssram[0].flag = SRAM_SLT_FREE;
+       used_l1_ssram_head.next = NULL;
 
        /* mutex initialize */
        spin_lock_init(&l1sram_lock);
+
+       printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
+              L1_SCRATCH_LENGTH >> 10);
 }
 
-void __init l1_data_sram_init(void)
+static void __init l1_data_sram_init(void)
 {
 #if L1_DATA_A_LENGTH != 0
-       memset(&l1_data_A_sram, 0x00, sizeof(l1_data_A_sram));
-       l1_data_A_sram[0].paddr = (void *)L1_DATA_A_START +
-                                       (_ebss_l1 - _sdata_l1);
-       l1_data_A_sram[0].size = L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
-       l1_data_A_sram[0].flag = SRAM_SLT_FREE;
-
-       printk(KERN_INFO "Blackfin Data A SRAM: %d KB (%d KB free)\n",
-              L1_DATA_A_LENGTH >> 10, l1_data_A_sram[0].size >> 10);
+       free_l1_data_A_sram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l1_data_A_sram_head.next) {
+               printk(KERN_INFO"Fail to initialize L1 Data A SRAM.\n");
+               return;
+       }
+
+       free_l1_data_A_sram_head.next->paddr =
+               (void *)L1_DATA_A_START + (_ebss_l1 - _sdata_l1);
+       free_l1_data_A_sram_head.next->size =
+               L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
+       free_l1_data_A_sram_head.next->pid = 0;
+       free_l1_data_A_sram_head.next->next = NULL;
+
+       used_l1_data_A_sram_head.next = NULL;
+
+       printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n",
+               L1_DATA_A_LENGTH >> 10,
+               free_l1_data_A_sram_head.next->size >> 10);
 #endif
 #if L1_DATA_B_LENGTH != 0
-       memset(&l1_data_B_sram, 0x00, sizeof(l1_data_B_sram));
-       l1_data_B_sram[0].paddr = (void *)L1_DATA_B_START +
-                               (_ebss_b_l1 - _sdata_b_l1);
-       l1_data_B_sram[0].size = L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
-       l1_data_B_sram[0].flag = SRAM_SLT_FREE;
-
-       printk(KERN_INFO "Blackfin Data B SRAM: %d KB (%d KB free)\n",
-              L1_DATA_B_LENGTH >> 10, l1_data_B_sram[0].size >> 10);
+       free_l1_data_B_sram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l1_data_B_sram_head.next) {
+               printk(KERN_INFO"Fail to initialize L1 Data B SRAM.\n");
+               return;
+       }
+
+       free_l1_data_B_sram_head.next->paddr =
+               (void *)L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1);
+       free_l1_data_B_sram_head.next->size =
+               L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
+       free_l1_data_B_sram_head.next->pid = 0;
+       free_l1_data_B_sram_head.next->next = NULL;
+
+       used_l1_data_B_sram_head.next = NULL;
+
+       printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n",
+               L1_DATA_B_LENGTH >> 10,
+               free_l1_data_B_sram_head.next->size >> 10);
 #endif
 
        /* mutex initialize */
        spin_lock_init(&l1_data_sram_lock);
 }
 
-void __init l1_inst_sram_init(void)
+static void __init l1_inst_sram_init(void)
 {
 #if L1_CODE_LENGTH != 0
-       memset(&l1_inst_sram, 0x00, sizeof(l1_inst_sram));
-       l1_inst_sram[0].paddr = (void *)L1_CODE_START + (_etext_l1 - _stext_l1);
-       l1_inst_sram[0].size = L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
-       l1_inst_sram[0].flag = SRAM_SLT_FREE;
+       free_l1_inst_sram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l1_inst_sram_head.next) {
+               printk(KERN_INFO"Fail to initialize L1 Instruction SRAM.\n");
+               return;
+       }
 
-       printk(KERN_INFO "Blackfin Instruction SRAM: %d KB (%d KB free)\n",
-              L1_CODE_LENGTH >> 10, l1_inst_sram[0].size >> 10);
+       free_l1_inst_sram_head.next->paddr =
+               (void *)L1_CODE_START + (_etext_l1 - _stext_l1);
+       free_l1_inst_sram_head.next->size =
+               L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
+       free_l1_inst_sram_head.next->pid = 0;
+       free_l1_inst_sram_head.next->next = NULL;
+
+       used_l1_inst_sram_head.next = NULL;
+
+       printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n",
+               L1_CODE_LENGTH >> 10,
+               free_l1_inst_sram_head.next->size >> 10);
 #endif
 
        /* mutex initialize */
        spin_lock_init(&l1_inst_sram_lock);
 }
 
-/* L1 memory allocate function */
-static void *_l1_sram_alloc(size_t size, struct l1_sram_piece *pfree, int count)
+static void __init l2_sram_init(void)
 {
-       int i, index = 0;
-       void *addr = NULL;
+#ifdef L2_LENGTH
+       free_l2_sram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l2_sram_head.next) {
+               printk(KERN_INFO"Fail to initialize L2 SRAM.\n");
+               return;
+       }
 
-       if (size <= 0)
+       free_l2_sram_head.next->paddr = (void *)L2_START +
+               (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
+       free_l2_sram_head.next->size = L2_LENGTH -
+               (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
+       free_l2_sram_head.next->pid = 0;
+       free_l2_sram_head.next->next = NULL;
+
+       used_l2_sram_head.next = NULL;
+
+       printk(KERN_INFO "Blackfin L2 SRAM: %d KB (%d KB free)\n",
+               L2_LENGTH >> 10,
+               free_l2_sram_head.next->size >> 10);
+#endif
+
+       /* mutex initialize */
+       spin_lock_init(&l2_sram_lock);
+}
+void __init bfin_sram_init(void)
+{
+       sram_piece_cache = kmem_cache_create("sram_piece_cache",
+                               sizeof(struct sram_piece),
+                               0, SLAB_PANIC, NULL);
+
+       l1sram_init();
+       l1_data_sram_init();
+       l1_inst_sram_init();
+       l2_sram_init();
+}
+
+/* SRAM allocate function */
+static void *_sram_alloc(size_t size, struct sram_piece *pfree_head,
+               struct sram_piece *pused_head)
+{
+       struct sram_piece *pslot, *plast, *pavail;
+
+       if (size <= 0 || !pfree_head || !pused_head)
                return NULL;
 
        /* Align the size */
        size = (size + 3) & ~3;
 
-       /* not use the good method to match the best slot !!! */
-       /* search an available memory slot */
-       for (i = 0; i < count; i++) {
-               if ((pfree[i].flag == SRAM_SLT_FREE)
-                   && (pfree[i].size >= size)) {
-                       addr = pfree[i].paddr;
-                       pfree[i].flag = SRAM_SLT_ALLOCATED;
-                       pfree[i].pid = current->pid;
-                       index = i;
-                       break;
-               }
+       pslot = pfree_head->next;
+       plast = pfree_head;
+
+       /* search an available piece slot */
+       while (pslot != NULL && size > pslot->size) {
+               plast = pslot;
+               pslot = pslot->next;
        }
-       if (i >= count)
+
+       if (!pslot)
                return NULL;
 
-       /* updated the NULL memory slot !!! */
-       if (pfree[i].size > size) {
-               for (i = 0; i < count; i++) {
-                       if (pfree[i].flag == SRAM_SLT_NULL) {
-                               pfree[i].pid = 0;
-                               pfree[i].flag = SRAM_SLT_FREE;
-                               pfree[i].paddr = addr + size;
-                               pfree[i].size = pfree[index].size - size;
-                               pfree[index].size = size;
-                               break;
-                       }
-               }
+       if (pslot->size == size) {
+               plast->next = pslot->next;
+               pavail = pslot;
+       } else {
+               pavail = kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+
+               if (!pavail)
+                       return NULL;
+
+               pavail->paddr = pslot->paddr;
+               pavail->size = size;
+               pslot->paddr += size;
+               pslot->size -= size;
        }
 
-       return addr;
+       pavail->pid = current->pid;
+
+       pslot = pused_head->next;
+       plast = pused_head;
+
+       /* insert new piece into used piece list !!! */
+       while (pslot != NULL && pavail->paddr < pslot->paddr) {
+               plast = pslot;
+               pslot = pslot->next;
+       }
+
+       pavail->next = pslot;
+       plast->next = pavail;
+
+       return pavail->paddr;
 }
 
 /* Allocate the largest available block.  */
-static void *_l1_sram_alloc_max(struct l1_sram_piece *pfree, int count,
+static void *_sram_alloc_max(struct sram_piece *pfree_head,
+                               struct sram_piece *pused_head,
                                unsigned long *psize)
 {
-       unsigned long best = 0;
-       int i, index = -1;
-       void *addr = NULL;
+       struct sram_piece *pslot, *pmax;
 
-       /* search an available memory slot */
-       for (i = 0; i < count; i++) {
-               if (pfree[i].flag == SRAM_SLT_FREE && pfree[i].size > best) {
-                       addr = pfree[i].paddr;
-                       index = i;
-                       best = pfree[i].size;
-               }
+       if (!pfree_head || !pused_head)
+               return NULL;
+
+       pmax = pslot = pfree_head->next;
+
+       /* search an available piece slot */
+       while (pslot != NULL) {
+               if (pslot->size > pmax->size)
+                       pmax = pslot;
+               pslot = pslot->next;
        }
-       if (index < 0)
+
+       if (!pmax)
                return NULL;
-       *psize = best;
 
-       pfree[index].pid = current->pid;
-       pfree[index].flag = SRAM_SLT_ALLOCATED;
-       return addr;
+       *psize = pmax->size;
+
+       return _sram_alloc(*psize, pfree_head, pused_head);
 }
 
-/* L1 memory free function */
-static int _l1_sram_free(const void *addr,
-                       struct l1_sram_piece *pfree,
-                       int count)
+/* SRAM free function */
+static int _sram_free(const void *addr,
+                       struct sram_piece *pfree_head,
+                       struct sram_piece *pused_head)
 {
-       int i, index = 0;
+       struct sram_piece *pslot, *plast, *pavail;
+
+       if (!pfree_head || !pused_head)
+               return -1;
 
        /* search the relevant memory slot */
-       for (i = 0; i < count; i++) {
-               if (pfree[i].paddr == addr) {
-                       if (pfree[i].flag != SRAM_SLT_ALLOCATED) {
-                               /* error log */
-                               return -1;
-                       }
-                       index = i;
-                       break;
-               }
+       pslot = pused_head->next;
+       plast = pused_head;
+
+       /* search an available piece slot */
+       while (pslot != NULL && pslot->paddr != addr) {
+               plast = pslot;
+               pslot = pslot->next;
        }
-       if (i >= count)
+
+       if (!pslot)
                return -1;
 
-       pfree[index].pid = 0;
-       pfree[index].flag = SRAM_SLT_FREE;
-
-       /* link the next address slot */
-       for (i = 0; i < count; i++) {
-               if (((pfree[index].paddr + pfree[index].size) == pfree[i].paddr)
-                   && (pfree[i].flag == SRAM_SLT_FREE)) {
-                       pfree[i].pid = 0;
-                       pfree[i].flag = SRAM_SLT_NULL;
-                       pfree[index].size += pfree[i].size;
-                       pfree[index].flag = SRAM_SLT_FREE;
-                       break;
-               }
+       plast->next = pslot->next;
+       pavail = pslot;
+       pavail->pid = 0;
+
+       /* insert free pieces back to the free list */
+       pslot = pfree_head->next;
+       plast = pfree_head;
+
+       while (pslot != NULL && addr > pslot->paddr) {
+               plast = pslot;
+               pslot = pslot->next;
+       }
+
+       if (plast != pfree_head && plast->paddr + plast->size == pavail->paddr) {
+               plast->size += pavail->size;
+               kmem_cache_free(sram_piece_cache, pavail);
+       } else {
+               pavail->next = plast;
+               plast->next = pavail;
+               plast = pavail;
        }
 
-       /* link the last address slot */
-       for (i = 0; i < count; i++) {
-               if (((pfree[i].paddr + pfree[i].size) == pfree[index].paddr) &&
-                   (pfree[i].flag == SRAM_SLT_FREE)) {
-                       pfree[index].flag = SRAM_SLT_NULL;
-                       pfree[i].size += pfree[index].size;
-                       break;
-               }
+       if (pslot && plast->paddr + plast->size == pslot->paddr) {
+               plast->size += pslot->size;
+               plast->next = pslot->next;
+               kmem_cache_free(sram_piece_cache, pslot);
        }
 
        return 0;
@@ -272,6 +366,11 @@ int sram_free(const void *addr)
        else if (addr >= (void *)L1_DATA_B_START
                 && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH))
                return l1_data_B_sram_free(addr);
+#endif
+#ifdef L2_LENGTH
+       else if (addr >= (void *)L2_START
+                && addr < (void *)(L2_START + L2_LENGTH))
+               return l2_sram_free(addr);
 #endif
        else
                return -1;
@@ -287,7 +386,8 @@ void *l1_data_A_sram_alloc(size_t size)
        spin_lock_irqsave(&l1_data_sram_lock, flags);
 
 #if L1_DATA_A_LENGTH != 0
-       addr = _l1_sram_alloc(size, l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
+       addr = _sram_alloc(size, &free_l1_data_A_sram_head,
+                       &used_l1_data_A_sram_head);
 #endif
 
        /* add mutex operation */
@@ -309,8 +409,8 @@ int l1_data_A_sram_free(const void *addr)
        spin_lock_irqsave(&l1_data_sram_lock, flags);
 
 #if L1_DATA_A_LENGTH != 0
-       ret = _l1_sram_free(addr,
-                          l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
+       ret = _sram_free(addr, &free_l1_data_A_sram_head,
+                       &used_l1_data_A_sram_head);
 #else
        ret = -1;
 #endif
@@ -331,7 +431,8 @@ void *l1_data_B_sram_alloc(size_t size)
        /* add mutex operation */
        spin_lock_irqsave(&l1_data_sram_lock, flags);
 
-       addr = _l1_sram_alloc(size, l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
+       addr = _sram_alloc(size, &free_l1_data_B_sram_head,
+                       &used_l1_data_B_sram_head);
 
        /* add mutex operation */
        spin_unlock_irqrestore(&l1_data_sram_lock, flags);
@@ -355,7 +456,8 @@ int l1_data_B_sram_free(const void *addr)
        /* add mutex operation */
        spin_lock_irqsave(&l1_data_sram_lock, flags);
 
-       ret = _l1_sram_free(addr, l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
+       ret = _sram_free(addr, &free_l1_data_B_sram_head,
+                       &used_l1_data_B_sram_head);
 
        /* add mutex operation */
        spin_unlock_irqrestore(&l1_data_sram_lock, flags);
@@ -408,7 +510,8 @@ void *l1_inst_sram_alloc(size_t size)
        /* add mutex operation */
        spin_lock_irqsave(&l1_inst_sram_lock, flags);
 
-       addr = _l1_sram_alloc(size, l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
+       addr = _sram_alloc(size, &free_l1_inst_sram_head,
+                       &used_l1_inst_sram_head);
 
        /* add mutex operation */
        spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
@@ -432,7 +535,8 @@ int l1_inst_sram_free(const void *addr)
        /* add mutex operation */
        spin_lock_irqsave(&l1_inst_sram_lock, flags);
 
-       ret = _l1_sram_free(addr, l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
+       ret = _sram_free(addr, &free_l1_inst_sram_head,
+                       &used_l1_inst_sram_head);
 
        /* add mutex operation */
        spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
@@ -453,7 +557,8 @@ void *l1sram_alloc(size_t size)
        /* add mutex operation */
        spin_lock_irqsave(&l1sram_lock, flags);
 
-       addr = _l1_sram_alloc(size, l1_ssram, ARRAY_SIZE(l1_ssram));
+       addr = _sram_alloc(size, &free_l1_ssram_head,
+                       &used_l1_ssram_head);
 
        /* add mutex operation */
        spin_unlock_irqrestore(&l1sram_lock, flags);
@@ -470,7 +575,8 @@ void *l1sram_alloc_max(size_t *psize)
        /* add mutex operation */
        spin_lock_irqsave(&l1sram_lock, flags);
 
-       addr = _l1_sram_alloc_max(l1_ssram, ARRAY_SIZE(l1_ssram), psize);
+       addr = _sram_alloc_max(&free_l1_ssram_head,
+                       &used_l1_ssram_head, psize);
 
        /* add mutex operation */
        spin_unlock_irqrestore(&l1sram_lock, flags);
@@ -487,7 +593,8 @@ int l1sram_free(const void *addr)
        /* add mutex operation */
        spin_lock_irqsave(&l1sram_lock, flags);
 
-       ret = _l1_sram_free(addr, l1_ssram, ARRAY_SIZE(l1_ssram));
+       ret = _sram_free(addr, &free_l1_ssram_head,
+                       &used_l1_ssram_head);
 
        /* add mutex operation */
        spin_unlock_irqrestore(&l1sram_lock, flags);
@@ -495,6 +602,64 @@ int l1sram_free(const void *addr)
        return ret;
 }
 
+void *l2_sram_alloc(size_t size)
+{
+#ifdef L2_LENGTH
+       unsigned flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l2_sram_lock, flags);
+
+       addr = _sram_alloc(size, &free_l2_sram_head,
+                       &used_l2_sram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l2_sram_lock, flags);
+
+       pr_debug("Allocated address in l2_sram_alloc is 0x%lx+0x%lx\n",
+                (long unsigned int)addr, size);
+
+       return addr;
+#else
+       return NULL;
+#endif
+}
+EXPORT_SYMBOL(l2_sram_alloc);
+
+void *l2_sram_zalloc(size_t size)
+{
+       void *addr = l2_sram_alloc(size);
+
+       if (addr)
+               memset(addr, 0x00, size);
+
+       return addr;
+}
+EXPORT_SYMBOL(l2_sram_zalloc);
+
+int l2_sram_free(const void *addr)
+{
+#ifdef L2_LENGTH
+       unsigned flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l2_sram_lock, flags);
+
+       ret = _sram_free(addr, &free_l2_sram_head,
+                       &used_l2_sram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l2_sram_lock, flags);
+
+       return ret;
+#else
+       return -1;
+#endif
+}
+EXPORT_SYMBOL(l2_sram_free);
+
 int sram_free_with_lsl(const void *addr)
 {
        struct sram_list_struct *lsl, **tmp;
@@ -533,6 +698,9 @@ void *sram_alloc_with_lsl(size_t size, unsigned long flags)
        if (addr == NULL && (flags & L1_DATA_B_SRAM))
                addr = l1_data_B_sram_alloc(size);
 
+       if (addr == NULL && (flags & L2_SRAM))
+               addr = l2_sram_alloc(size);
+
        if (addr == NULL) {
                kfree(lsl);
                return NULL;
@@ -549,49 +717,80 @@ EXPORT_SYMBOL(sram_alloc_with_lsl);
 /* Once we get a real allocator, we'll throw all of this away.
  * Until then, we need some sort of visibility into the L1 alloc.
  */
-static void _l1sram_proc_read(char *buf, int *len, const char *desc,
-               struct l1_sram_piece *pfree, const int array_size)
+/* Need to keep line of output the same.  Currently, that is 44 bytes
+ * (including newline).
+ */
+static int _sram_proc_read(char *buf, int *len, int count, const char *desc,
+               struct sram_piece *pfree_head,
+               struct sram_piece *pused_head)
 {
-       int i;
-
-       *len += sprintf(&buf[*len], "--- L1 %-14s Size  PID State\n", desc);
-       for (i = 0; i < array_size; ++i) {
-               const char *alloc_type;
-               switch (pfree[i].flag) {
-               case SRAM_SLT_NULL:      alloc_type = "NULL"; break;
-               case SRAM_SLT_FREE:      alloc_type = "FREE"; break;
-               case SRAM_SLT_ALLOCATED: alloc_type = "ALLOCATED"; break;
-               default:                 alloc_type = "????"; break;
-               }
-               *len += sprintf(&buf[*len], "%p-%p %8i %4i %s\n",
-                       pfree[i].paddr, pfree[i].paddr + pfree[i].size,
-                       pfree[i].size, pfree[i].pid, alloc_type);
+       struct sram_piece *pslot;
+
+       if (!pfree_head || !pused_head)
+               return -1;
+
+       *len += sprintf(&buf[*len], "--- SRAM %-14s Size   PID State     \n", desc);
+
+       /* search the relevant memory slot */
+       pslot = pused_head->next;
+
+       while (pslot != NULL) {
+               *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
+                       pslot->paddr, pslot->paddr + pslot->size,
+                       pslot->size, pslot->pid, "ALLOCATED");
+
+               pslot = pslot->next;
        }
+
+       pslot = pfree_head->next;
+
+       while (pslot != NULL) {
+               *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
+                       pslot->paddr, pslot->paddr + pslot->size,
+                       pslot->size, pslot->pid, "FREE");
+
+               pslot = pslot->next;
+       }
+
+       return 0;
 }
-static int l1sram_proc_read(char *buf, char **start, off_t offset, int count,
+static int sram_proc_read(char *buf, char **start, off_t offset, int count,
                int *eof, void *data)
 {
        int len = 0;
 
-       _l1sram_proc_read(buf, &len, "Scratchpad",
-                       l1_ssram, ARRAY_SIZE(l1_ssram));
+       if (_sram_proc_read(buf, &len, count, "Scratchpad",
+                       &free_l1_ssram_head, &used_l1_ssram_head))
+               goto not_done;
 #if L1_DATA_A_LENGTH != 0
-       _l1sram_proc_read(buf, &len, "Data A",
-                       l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
+       if (_sram_proc_read(buf, &len, count, "L1 Data A",
+                       &free_l1_data_A_sram_head,
+                       &used_l1_data_A_sram_head))
+               goto not_done;
 #endif
 #if L1_DATA_B_LENGTH != 0
-       _l1sram_proc_read(buf, &len, "Data B",
-                       l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
+       if (_sram_proc_read(buf, &len, count, "L1 Data B",
+                       &free_l1_data_B_sram_head,
+                       &used_l1_data_B_sram_head))
+               goto not_done;
 #endif
 #if L1_CODE_LENGTH != 0
-       _l1sram_proc_read(buf, &len, "Instruction",
-                       l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
+       if (_sram_proc_read(buf, &len, count, "L1 Instruction",
+                       &free_l1_inst_sram_head, &used_l1_inst_sram_head))
+               goto not_done;
+#endif
+#ifdef L2_LENGTH
+       if (_sram_proc_read(buf, &len, count, "L2",
+                       &free_l2_sram_head, &used_l2_sram_head))
+               goto not_done;
 #endif
 
+       *eof = 1;
+ not_done:
        return len;
 }
 
-static int __init l1sram_proc_init(void)
+static int __init sram_proc_init(void)
 {
        struct proc_dir_entry *ptr;
        ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL);
@@ -600,8 +799,8 @@ static int __init l1sram_proc_init(void)
                return -1;
        }
        ptr->owner = THIS_MODULE;
-       ptr->read_proc = l1sram_proc_read;
+       ptr->read_proc = sram_proc_read;
        return 0;
 }
-late_initcall(l1sram_proc_init);
+late_initcall(sram_proc_init);
 #endif
index 0fb73b78dd605e5d5427f4fd8fed8c93161191dd..8cb0945563f9eda946c5ac274af431c58786c921 100644 (file)
@@ -30,9 +30,7 @@
 #ifndef __BLACKFIN_SRAM_H__
 #define __BLACKFIN_SRAM_H__
 
-extern void l1sram_init(void);
-extern void l1_inst_sram_init(void);
-extern void l1_data_sram_init(void);
+extern void bfin_sram_init(void);
 extern void *l1sram_alloc(size_t);
 
 #endif
index ec3141fefd20da1554e08d745a8a34f175a04b72..bc240abb8745cf01f854549b863976cca73cd73d 100644 (file)
@@ -53,33 +53,6 @@ static unsigned long empty_bad_page;
 
 unsigned long empty_zero_page;
 
-void show_mem(void)
-{
-       unsigned long i;
-       int free = 0, total = 0, reserved = 0, shared = 0;
-
-       int cached = 0;
-       printk(KERN_INFO "Mem-info:\n");
-       show_free_areas();
-       i = max_mapnr;
-       while (i-- > 0) {
-               total++;
-               if (PageReserved(mem_map + i))
-                       reserved++;
-               else if (PageSwapCache(mem_map + i))
-                       cached++;
-               else if (!page_count(mem_map + i))
-                       free++;
-               else
-                       shared += page_count(mem_map + i) - 1;
-       }
-       printk(KERN_INFO "%d pages of RAM\n", total);
-       printk(KERN_INFO "%d free pages\n", free);
-       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);
-}
-
 /*
  * paging_init() continues the virtual memory environment setup which
  * was begun by the code in arch/head.S.
@@ -164,11 +137,14 @@ void __init mem_init(void)
                "(%uk init code, %uk kernel code, %uk data, %uk dma, %uk reserved)\n",
                (unsigned long) freepages << (PAGE_SHIFT-10), _ramend >> 10,
                initk, codek, datak, DMA_UNCACHED_REGION >> 10, (reservedpages << (PAGE_SHIFT-10)));
+}
+
+static int __init sram_init(void)
+{
+       unsigned long tmp;
 
        /* Initialize the blackfin L1 Memory. */
-       l1sram_init();
-       l1_data_sram_init();
-       l1_inst_sram_init();
+       bfin_sram_init();
 
        /* Allocate this once; never free it.  We assume this gives us a
           pointer to the start of L1 scratchpad memory; panic if it
@@ -179,7 +155,10 @@ void __init mem_init(void)
                        tmp, (unsigned long)L1_SCRATCH_TASK_INFO);
                panic("No L1, time to give up\n");
        }
+
+       return 0;
 }
+pure_initcall(sram_init);
 
 static void __init free_init_pages(const char *what, unsigned long begin, unsigned long end)
 {
index 18e13bce140009a43efa0011393e349ee435a700..d933c89889dbfbcfae9699ea0f1179575de4099c 100644 (file)
@@ -102,50 +102,16 @@ extern char *input_data;  /* lives in head.S */
 static long bytes_out = 0;
 static uch *output_data;
 static unsigned long output_ptr = 0;
-
-static void *malloc(int size);
-static void free(void *where);
-static void gzip_mark(void **);
-static void gzip_release(void **);
-
 static void puts(const char *);
 
 /* the "heap" is put directly after the BSS ends, at end */
 
 extern int _end;
 static long free_mem_ptr = (long)&_end;
+static long free_mem_end_ptr;
 
 #include "../../../../../lib/inflate.c"
 
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size < 0)
-               error("Malloc error");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *)free_mem_ptr;
-       free_mem_ptr += size;
-
-       return p;
-}
-
-static void free(void *where)
-{      /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
-       *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
-       free_mem_ptr = (long) *ptr;
-}
-
 /* decompressor info and error messages to serial console */
 
 static void
index a3ca55150745976d0fcc263f382db56f1f61c14b..6fea45f2e40ca52b670b898afa4787fcefadffa3 100644 (file)
@@ -278,14 +278,6 @@ void putDebugChar (int val);
 
 void enableDebugIRQ (void);
 
-/* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte,
-   represented by int x. */
-static char highhex (int x);
-
-/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte,
-   represented by int x. */
-static char lowhex (int x);
-
 /* Returns the integer equivalent of a hexadecimal character. */
 static int hex (char ch);
 
@@ -356,9 +348,6 @@ extern unsigned char executing_task;
 /* Run-length encoding maximum length. Send 64 at most. */
 #define RUNLENMAX 64
 
-/* Definition of all valid hexadecimal characters */
-static const char hexchars[] = "0123456789abcdef";
-
 /* The inbound/outbound buffers used in packet I/O */
 static char remcomInBuffer[BUFMAX];
 static char remcomOutBuffer[BUFMAX];
@@ -499,8 +488,8 @@ gdb_cris_strtol (const char *s, char **endptr, int base)
        char *sd;
        int x = 0;
        
-       for (s1 = (char*)s; (sd = gdb_cris_memchr(hexchars, *s1, base)) != NULL; ++s1)
-               x = x * base + (sd - hexchars);
+       for (s1 = (char*)s; (sd = gdb_cris_memchr(hex_asc, *s1, base)) != NULL; ++s1)
+               x = x * base + (sd - hex_asc);
         
         if (endptr)
         {
@@ -670,22 +659,6 @@ read_register (char regno, unsigned int *valptr)
 }
 
 /********************************** Packet I/O ******************************/
-/* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte,
-   represented by int x. */
-static inline char
-highhex(int x)
-{
-       return hexchars[(x >> 4) & 0xf];
-}
-
-/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte,
-   represented by int x. */
-static inline char
-lowhex(int x)
-{
-       return hexchars[x & 0xf];
-}
-
 /* Returns the integer equivalent of a hexadecimal character. */
 static int
 hex (char ch)
@@ -721,8 +694,7 @@ mem2hex(char *buf, unsigned char *mem, int count)
                 /* Valid mem address. */
                 for (i = 0; i < count; i++) {
                         ch = *mem++;
-                        *buf++ = highhex (ch);
-                        *buf++ = lowhex (ch);
+                       buf = pack_hex_byte(buf, ch);
                 }
         }
         
@@ -857,9 +829,9 @@ putpacket(char *buffer)
                                src++;
                        }
                }
-               putDebugChar ('#');
-               putDebugChar (highhex (checksum));
-               putDebugChar (lowhex (checksum));
+               putDebugChar('#');
+               putDebugChar(hex_asc_hi(checksum));
+               putDebugChar(hex_asc_lo(checksum));
        } while(kgdb_started && (getDebugChar() != '+'));
 }
 
@@ -895,9 +867,8 @@ stub_is_stopped(int sigval)
         
        /* Send trap type (converted to signal) */
 
-       *ptr++ = 'T';   
-       *ptr++ = highhex (sigval);
-       *ptr++ = lowhex (sigval);
+       *ptr++ = 'T';
+       ptr = pack_hex_byte(ptr, sigval);
 
        /* Send register contents. We probably only need to send the
         * PC, frame pointer and stack pointer here. Other registers will be
@@ -910,9 +881,7 @@ stub_is_stopped(int sigval)
                 status = read_register (regno, &reg_cont);
                 
                if (status == SUCCESS) {
-                        
-                        *ptr++ = highhex (regno);
-                        *ptr++ = lowhex (regno);
+                       ptr = pack_hex_byte(ptr, regno);
                         *ptr++ = ':';
 
                         ptr = mem2hex(ptr, (unsigned char *)&reg_cont,
@@ -937,8 +906,8 @@ stub_is_stopped(int sigval)
        /* Store thread:r...; with the executing task TID. */
        gdb_cris_strcpy (&remcomOutBuffer[pos], "thread:");
        pos += gdb_cris_strlen ("thread:");
-       remcomOutBuffer[pos++] = highhex (executing_task);
-       remcomOutBuffer[pos++] = lowhex (executing_task);
+       remcomOutBuffer[pos++] = hex_asc_hi(executing_task);
+       remcomOutBuffer[pos++] = hex_asc_lo(executing_task);
        gdb_cris_strcpy (&remcomOutBuffer[pos], ";");
 #endif
 
@@ -1126,8 +1095,8 @@ handle_exception (int sigval)
                                   Success: SAA, where AA is the signal number.
                                   Failure: void. */
                                remcomOutBuffer[0] = 'S';
-                               remcomOutBuffer[1] = highhex (sigval);
-                               remcomOutBuffer[2] = lowhex (sigval);
+                               remcomOutBuffer[1] = hex_asc_hi(sigval);
+                               remcomOutBuffer[2] = hex_asc_lo(sigval);
                                remcomOutBuffer[3] = 0;
                                break;
                                
@@ -1224,23 +1193,23 @@ handle_exception (int sigval)
                                                case 'C':
                                                        /* Identify the remote current thread. */
                                                        gdb_cris_strcpy (&remcomOutBuffer[0], "QC");
-                                                       remcomOutBuffer[2] = highhex (current_thread_c);
-                                                       remcomOutBuffer[3] = lowhex (current_thread_c);
+                                                       remcomOutBuffer[2] = hex_asc_hi(current_thread_c);
+                                                       remcomOutBuffer[3] = hex_asc_lo(current_thread_c);
                                                        remcomOutBuffer[4] = '\0';
                                                        break;
                                                case 'L':
                                                        gdb_cris_strcpy (&remcomOutBuffer[0], "QM");
                                                        /* Reply with number of threads. */
                                                        if (os_is_started()) {
-                                                               remcomOutBuffer[2] = highhex (number_of_tasks);
-                                                               remcomOutBuffer[3] = lowhex (number_of_tasks);
+                                                               remcomOutBuffer[2] = hex_asc_hi(number_of_tasks);
+                                                               remcomOutBuffer[3] = hex_asc_lo(number_of_tasks);
                                                        }
                                                        else {
-                                                               remcomOutBuffer[2] = highhex (0);
-                                                               remcomOutBuffer[3] = lowhex (1);
+                                                               remcomOutBuffer[2] = hex_asc_hi(0);
+                                                               remcomOutBuffer[3] = hex_asc_lo(1);
                                                        }
                                                        /* Done with the reply. */
-                                                       remcomOutBuffer[4] = lowhex (1);
+                                                       remcomOutBuffer[4] = hex_asc_lo(1);
                                                        pos = 5;
                                                        /* Expects the argument thread id. */
                                                        for (; pos < (5 + HEXCHARS_IN_THREAD_ID); pos++)
@@ -1251,16 +1220,16 @@ handle_exception (int sigval)
                                                                for (thread_id = 0; thread_id < number_of_tasks; thread_id++) {
                                                                        nextpos = pos + HEXCHARS_IN_THREAD_ID - 1;
                                                                        for (; pos < nextpos; pos ++)
-                                                                               remcomOutBuffer[pos] = lowhex (0);
-                                                                       remcomOutBuffer[pos++] = lowhex (thread_id);
+                                                                               remcomOutBuffer[pos] = hex_asc_lo(0);
+                                                                       remcomOutBuffer[pos++] = hex_asc_lo(thread_id);
                                                                }
                                                        }
                                                        else {
                                                                /* Store the thread identifier of the boot task. */
                                                                nextpos = pos + HEXCHARS_IN_THREAD_ID - 1;
                                                                for (; pos < nextpos; pos ++)
-                                                                       remcomOutBuffer[pos] = lowhex (0);
-                                                               remcomOutBuffer[pos++] = lowhex (current_thread_c);
+                                                                       remcomOutBuffer[pos] = hex_asc_lo(0);
+                                                               remcomOutBuffer[pos++] = hex_asc_lo(current_thread_c);
                                                        }
                                                        remcomOutBuffer[pos] = '\0';
                                                        break;
index e0fcd1a9bfd5f766ecbd952b1170c6e6c2da1e75..742fd1974c2e590a1121b98cf770e913504676ff 100644 (file)
@@ -182,7 +182,7 @@ paging_init(void)
         * mem_map page array.
         */
 
-       free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
+       free_area_init_node(0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
 }
 
 /* Initialize remaps of some I/O-ports. It is important that this
index 55b2695c5d70b70528ba2cbc2e94b6e8323860ee..3595e16e82bcf10ffff7dfcdab26c30a95d4f141 100644 (file)
@@ -89,20 +89,14 @@ static unsigned outcnt = 0;  /* bytes in output buffer */
 
 static void flush_window(void);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 extern char *input_data;  /* lives in head.S */
 
-static long bytes_out = 0;
+static long bytes_out;
 static uch *output_data;
-static unsigned long output_ptr = 0;
+static unsigned long output_ptr;
 
-static void *malloc(int size);
-static void free(void *where);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 static void puts(const char *);
 
@@ -110,37 +104,10 @@ static void puts(const char *);
 
 extern int _end;
 static long free_mem_ptr = (long)&_end;
+static long free_mem_end_ptr;
 
 #include "../../../../../lib/inflate.c"
 
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size <0) error("Malloc error");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *)free_mem_ptr;
-       free_mem_ptr += size;
-
-       return p;
-}
-
-static void free(void *where)
-{      /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
-       *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
-       free_mem_ptr = (long) *ptr;
-}
-
 /* decompressor info and error messages to serial console */
 
 static inline void
index 2a92cb1886ca298fa15e1af1160d067f910064b2..7a64fcef9d07edc354721d70f30af651c2ff7738 100644 (file)
@@ -641,6 +641,7 @@ config PCI
        bool
        depends on ETRAX_CARDBUS
        default y
+       select HAVE_GENERIC_DMA_COHERENT
 
 config ETRAX_IOP_FW_LOAD
        tristate "IO-processor hotplug firmware loading support"
index e0364654fc447f2a4eae7756a28d84775b7654a0..fbe65954ee6c32ab895cbfae568b1613b918b0ee 100644 (file)
 #include <linux/pci.h>
 #include <asm/io.h>
 
-struct dma_coherent_mem {
-       void            *virt_base;
-       u32             device_base;
-       int             size;
-       int             flags;
-       unsigned long   *bitmap;
-};
-
 void *dma_alloc_coherent(struct device *dev, size_t size,
                           dma_addr_t *dma_handle, gfp_t gfp)
 {
        void *ret;
-       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
        int order = get_order(size);
        /* ignore region specifiers */
        gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
-       if (mem) {
-               int page = bitmap_find_free_region(mem->bitmap, mem->size,
-                                                    order);
-               if (page >= 0) {
-                       *dma_handle = mem->device_base + (page << PAGE_SHIFT);
-                       ret = mem->virt_base + (page << PAGE_SHIFT);
-                       memset(ret, 0, size);
-                       return ret;
-               }
-               if (mem->flags & DMA_MEMORY_EXCLUSIVE)
-                       return NULL;
-       }
+       if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
+               return ret;
 
        if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
                gfp |= GFP_DMA;
@@ -60,90 +41,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
 void dma_free_coherent(struct device *dev, size_t size,
                         void *vaddr, dma_addr_t dma_handle)
 {
-       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
        int order = get_order(size);
 
-       if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
-               int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
-
-               bitmap_release_region(mem->bitmap, page, order);
-       } else
+       if (!dma_release_from_coherent(dev, order, vaddr))
                free_pages((unsigned long)vaddr, order);
 }
 
-int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
-                               dma_addr_t device_addr, size_t size, int flags)
-{
-       void __iomem *mem_base;
-       int pages = size >> PAGE_SHIFT;
-       int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
-
-       if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
-               goto out;
-       if (!size)
-               goto out;
-       if (dev->dma_mem)
-               goto out;
-
-       /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
-
-       mem_base = ioremap(bus_addr, size);
-       if (!mem_base)
-               goto out;
-
-       dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
-       if (!dev->dma_mem)
-               goto iounmap_out;
-       dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-       if (!dev->dma_mem->bitmap)
-               goto free1_out;
-
-       dev->dma_mem->virt_base = mem_base;
-       dev->dma_mem->device_base = device_addr;
-       dev->dma_mem->size = pages;
-       dev->dma_mem->flags = flags;
-
-       if (flags & DMA_MEMORY_MAP)
-               return DMA_MEMORY_MAP;
-
-       return DMA_MEMORY_IO;
-
- free1_out:
-       kfree(dev->dma_mem);
- iounmap_out:
-       iounmap(mem_base);
- out:
-       return 0;
-}
-EXPORT_SYMBOL(dma_declare_coherent_memory);
-
-void dma_release_declared_memory(struct device *dev)
-{
-       struct dma_coherent_mem *mem = dev->dma_mem;
-
-       if(!mem)
-               return;
-       dev->dma_mem = NULL;
-       iounmap(mem->virt_base);
-       kfree(mem->bitmap);
-       kfree(mem);
-}
-EXPORT_SYMBOL(dma_release_declared_memory);
-
-void *dma_mark_declared_memory_occupied(struct device *dev,
-                                       dma_addr_t device_addr, size_t size)
-{
-       struct dma_coherent_mem *mem = dev->dma_mem;
-       int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       int pos, err;
-
-       if (!mem)
-               return ERR_PTR(-EINVAL);
-
-       pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
-       err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
-       if (err != 0)
-               return ERR_PTR(err);
-       return mem->virt_base + (pos << PAGE_SHIFT);
-}
-EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
index 4e2e2e271efbd5b042d1660b14392fff42d4cdfe..8bd5a5bc0dc7351a3921ab577465a4d1852ec888 100644 (file)
@@ -398,14 +398,6 @@ void putDebugChar(int val)
 }
 #endif
 
-/* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte,
-   represented by int x. */
-static char highhex(int x);
-
-/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte,
-   represented by int x. */
-static char lowhex(int x);
-
 /* Returns the integer equivalent of a hexadecimal character. */
 static int hex(char ch);
 
@@ -464,9 +456,6 @@ void breakpoint(void);
 /* Run-length encoding maximum length. Send 64 at most. */
 #define RUNLENMAX 64
 
-/* Definition of all valid hexadecimal characters */
-static const char hexchars[] = "0123456789abcdef";
-
 /* The inbound/outbound buffers used in packet I/O */
 static char input_buffer[BUFMAX];
 static char output_buffer[BUFMAX];
@@ -550,8 +539,8 @@ gdb_cris_strtol(const char *s, char **endptr, int base)
        char *sd;
        int x = 0;
 
-       for (s1 = (char*)s; (sd = gdb_cris_memchr(hexchars, *s1, base)) != NULL; ++s1)
-               x = x * base + (sd - hexchars);
+       for (s1 = (char*)s; (sd = gdb_cris_memchr(hex_asc, *s1, base)) != NULL; ++s1)
+               x = x * base + (sd - hex_asc);
 
         if (endptr) {
                 /* Unconverted suffix is stored in endptr unless endptr is NULL. */
@@ -655,22 +644,6 @@ read_register(char regno, unsigned int *valptr)
 }
 
 /********************************** Packet I/O ******************************/
-/* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte,
-   represented by int x. */
-static inline char
-highhex(int x)
-{
-       return hexchars[(x >> 4) & 0xf];
-}
-
-/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte,
-   represented by int x. */
-static inline char
-lowhex(int x)
-{
-       return hexchars[x & 0xf];
-}
-
 /* Returns the integer equivalent of a hexadecimal character. */
 static int
 hex(char ch)
@@ -704,8 +677,7 @@ mem2hex(char *buf, unsigned char *mem, int count)
                 /* Valid mem address. */
                for (i = 0; i < count; i++) {
                        ch = *mem++;
-                       *buf++ = highhex (ch);
-                       *buf++ = lowhex (ch);
+                       buf = pack_hex_byte(buf, ch);
                }
         }
         /* Terminate properly. */
@@ -723,8 +695,7 @@ mem2hex_nbo(char *buf, unsigned char *mem, int count)
        mem += count - 1;
        for (i = 0; i < count; i++) {
                ch = *mem--;
-               *buf++ = highhex (ch);
-               *buf++ = lowhex (ch);
+               buf = pack_hex_byte(buf, ch);
         }
 
         /* Terminate properly. */
@@ -862,8 +833,8 @@ putpacket(char *buffer)
                        }
                }
                putDebugChar('#');
-               putDebugChar(highhex (checksum));
-               putDebugChar(lowhex (checksum));
+               putDebugChar(hex_asc_hi(checksum));
+               putDebugChar(hex_asc_lo(checksum));
        } while(kgdb_started && (getDebugChar() != '+'));
 }
 
@@ -909,8 +880,7 @@ stub_is_stopped(int sigval)
        /* Send trap type (converted to signal) */
 
        *ptr++ = 'T';
-       *ptr++ = highhex(sigval);
-       *ptr++ = lowhex(sigval);
+       ptr = pack_hex_byte(ptr, sigval);
 
        if (((reg.exs & 0xff00) >> 8) == 0xc) {
 
@@ -1018,30 +988,26 @@ stub_is_stopped(int sigval)
        }
        /* Only send PC, frame and stack pointer. */
        read_register(PC, &reg_cont);
-       *ptr++ = highhex(PC);
-       *ptr++ = lowhex(PC);
+       ptr = pack_hex_byte(PC);
        *ptr++ = ':';
        ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[PC]);
        *ptr++ = ';';
 
        read_register(R8, &reg_cont);
-       *ptr++ = highhex(R8);
-       *ptr++ = lowhex(R8);
+       ptr = pack_hex_byte(R8);
        *ptr++ = ':';
        ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[R8]);
        *ptr++ = ';';
 
        read_register(SP, &reg_cont);
-       *ptr++ = highhex(SP);
-       *ptr++ = lowhex(SP);
+       ptr = pack_hex_byte(SP);
        *ptr++ = ':';
        ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[SP]);
        *ptr++ = ';';
 
        /* Send ERP as well; this will save us an entire register fetch in some cases. */
         read_register(ERP, &reg_cont);
-        *ptr++ = highhex(ERP);
-        *ptr++ = lowhex(ERP);
+       ptr = pack_hex_byte(ERP);
         *ptr++ = ':';
         ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[ERP]);
         *ptr++ = ';';
@@ -1533,8 +1499,8 @@ handle_exception(int sigval)
                                   Success: SAA, where AA is the signal number.
                                   Failure: void. */
                                output_buffer[0] = 'S';
-                               output_buffer[1] = highhex(sigval);
-                               output_buffer[2] = lowhex(sigval);
+                               output_buffer[1] = hex_asc_hi(sigval);
+                               output_buffer[2] = hex_asc_lo(sigval);
                                output_buffer[3] = 0;
                                break;
 
index 5a9ac5834647b222094a19ee83dd74ce1260807f..8a34b8b74293716b953149536a7fbe129a01df73 100644 (file)
@@ -162,7 +162,7 @@ paging_init(void)
         * substantially higher than 0, like us (we start at PAGE_OFFSET). This
         * saves space in the mem_map page array.
         */
-       free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
+       free_area_init_node(0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
 
        mem_map = contig_page_data.node_mem_map;
 }
index 44f7b4f794760dcaebf8cae38f114a39739e4d6f..9aa571169bcc5ea1f9847ab8bea143ccadfc6f14 100644 (file)
@@ -35,19 +35,16 @@ read_cris_profile(struct file *file, char __user *buf,
                  size_t count, loff_t *ppos)
 {
        unsigned long p = *ppos;
+       ssize_t ret;
 
-       if (p > SAMPLE_BUFFER_SIZE)
-               return 0;
+       ret = simple_read_from_buffer(buf, count, ppos, sample_buffer,
+                                               SAMPLE_BUFFER_SIZE);
+       if (ret < 0)
+               return ret;
 
-       if (p + count > SAMPLE_BUFFER_SIZE)
-               count = SAMPLE_BUFFER_SIZE - p;
-       if (copy_to_user(buf, sample_buffer + p,count))
-               return -EFAULT;
+       memset(sample_buffer + p, 0, ret);
 
-       memset(sample_buffer + p, 0, count);
-       *ppos += count;
-
-       return count;
+       return ret;
 }
 
 static ssize_t
index 5b06ffa15e347868c8ddfa5c796744b42fa4db3e..2fdd212eb250002cf5bfd53bb513c86bea15a8f4 100644 (file)
@@ -19,36 +19,6 @@ unsigned long empty_zero_page;
 extern char _stext, _edata, _etext; /* From linkerscript */
 extern char __init_begin, __init_end;
 
-void 
-show_mem(void)
-{
-       int i,free = 0,total = 0,cached = 0, reserved = 0, nonshared = 0;
-       int shared = 0;
-
-       printk("\nMem-info:\n");
-       show_free_areas();
-       i = max_mapnr;
-       while (i-- > 0) {
-               total++;
-               if (PageReserved(mem_map+i))
-                       reserved++;
-               else if (PageSwapCache(mem_map+i))
-                       cached++;
-               else if (!page_count(mem_map+i))
-                       free++;
-               else if (page_count(mem_map+i) == 1)
-                       nonshared++;
-               else
-                       shared += page_count(mem_map+i) - 1;
-       }
-       printk("%d pages of RAM\n",total);
-       printk("%d free pages\n",free);
-       printk("%d reserved pages\n",reserved);
-       printk("%d pages nonshared\n",nonshared);
-       printk("%d pages shared\n",shared);
-       printk("%d pages swap cached\n",cached);
-}
-
 void __init
 mem_init(void)
 {
index 48a0393e7cee1cd0e14fb15a7c20bbee9008fde3..7ca8a6b19ac97c3d74d1f6bbab44d23b45697fd9 100644 (file)
@@ -182,8 +182,6 @@ extern volatile u32 __attribute__((section(".bss"))) gdbstub_trace_through_excep
 static char    input_buffer[BUFMAX];
 static char    output_buffer[BUFMAX];
 
-static const char hexchars[] = "0123456789abcdef";
-
 static const char *regnames[] = {
        "PSR ", "ISR ", "CCR ", "CCCR",
        "LR  ", "LCR ", "PC  ", "_stt",
@@ -383,8 +381,8 @@ static int gdbstub_send_packet(char *buffer)
                }
 
                gdbstub_tx_char('#');
-               gdbstub_tx_char(hexchars[checksum >> 4]);
-               gdbstub_tx_char(hexchars[checksum & 0xf]);
+               gdbstub_tx_char(hex_asc_hi(checksum));
+               gdbstub_tx_char(hex_asc_lo(checksum));
 
        } while (gdbstub_rx_char(&ch,0),
 #ifdef GDBSTUB_DEBUG_PROTOCOL
@@ -674,8 +672,7 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
        if ((uint32_t)mem&1 && count>=1) {
                if (!gdbstub_read_byte(mem,ch))
                        return NULL;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
                mem++;
                count--;
        }
@@ -683,10 +680,8 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
        if ((uint32_t)mem&3 && count>=2) {
                if (!gdbstub_read_word(mem,(uint16_t *)ch))
                        return NULL;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
-               *buf++ = hexchars[ch[1] >> 4];
-               *buf++ = hexchars[ch[1] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
+               buf = pack_hex_byte(buf, ch[1]);
                mem += 2;
                count -= 2;
        }
@@ -694,14 +689,10 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
        while (count>=4) {
                if (!gdbstub_read_dword(mem,(uint32_t *)ch))
                        return NULL;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
-               *buf++ = hexchars[ch[1] >> 4];
-               *buf++ = hexchars[ch[1] & 0xf];
-               *buf++ = hexchars[ch[2] >> 4];
-               *buf++ = hexchars[ch[2] & 0xf];
-               *buf++ = hexchars[ch[3] >> 4];
-               *buf++ = hexchars[ch[3] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
+               buf = pack_hex_byte(buf, ch[1]);
+               buf = pack_hex_byte(buf, ch[2]);
+               buf = pack_hex_byte(buf, ch[3]);
                mem += 4;
                count -= 4;
        }
@@ -709,10 +700,8 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
        if (count>=2) {
                if (!gdbstub_read_word(mem,(uint16_t *)ch))
                        return NULL;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
-               *buf++ = hexchars[ch[1] >> 4];
-               *buf++ = hexchars[ch[1] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
+               buf = pack_hex_byte(buf, ch[1]);
                mem += 2;
                count -= 2;
        }
@@ -720,8 +709,7 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
        if (count>=1) {
                if (!gdbstub_read_byte(mem,ch))
                        return NULL;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
        }
 
        *buf = 0;
@@ -1471,22 +1459,22 @@ void gdbstub(int sigval)
                *ptr++ = 'O';
                ptr = mem2hex(title, ptr, sizeof(title) - 1,0);
 
-               hx = hexchars[(brr & 0xf0000000) >> 28];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(brr & 0x0f000000) >> 24];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(brr & 0x00f00000) >> 20];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(brr & 0x000f0000) >> 16];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(brr & 0x0000f000) >> 12];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(brr & 0x00000f00) >> 8];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(brr & 0x000000f0) >> 4];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(brr & 0x0000000f)];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
+               hx = hex_asc_hi(brr >> 24);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(brr >> 24);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_hi(brr >> 16);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(brr >> 16);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_hi(brr >> 8);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(brr >> 8);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_hi(brr);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(brr);
+               ptr = pack_hex_byte(ptr, hx);
 
                ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
                *ptr = 0;
@@ -1500,12 +1488,10 @@ void gdbstub(int sigval)
 
        /* Send trap type (converted to signal) */
        *ptr++ = 'T';
-       *ptr++ = hexchars[sigval >> 4];
-       *ptr++ = hexchars[sigval & 0xf];
+       ptr = pack_hex_byte(ptr, sigval);
 
        /* Send Error PC */
-       *ptr++ = hexchars[GDB_REG_PC >> 4];
-       *ptr++ = hexchars[GDB_REG_PC & 0xf];
+       ptr = pack_hex_byte(ptr, GDB_REG_PC);
        *ptr++ = ':';
        ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0);
        *ptr++ = ';';
@@ -1513,8 +1499,7 @@ void gdbstub(int sigval)
        /*
         * Send frame pointer
         */
-       *ptr++ = hexchars[GDB_REG_FP >> 4];
-       *ptr++ = hexchars[GDB_REG_FP & 0xf];
+       ptr = pack_hex_byte(ptr, GDB_REG_FP);
        *ptr++ = ':';
        ptr = mem2hex(&__debug_frame->fp, ptr, 4, 0);
        *ptr++ = ';';
@@ -1522,8 +1507,7 @@ void gdbstub(int sigval)
        /*
         * Send stack pointer
         */
-       *ptr++ = hexchars[GDB_REG_SP >> 4];
-       *ptr++ = hexchars[GDB_REG_SP & 0xf];
+       ptr = pack_hex_byte(ptr, GDB_REG_SP);
        *ptr++ = ':';
        ptr = mem2hex(&__debug_frame->sp, ptr, 4, 0);
        *ptr++ = ';';
@@ -1548,8 +1532,8 @@ void gdbstub(int sigval)
                        /* request repeat of last signal number */
                case '?':
                        output_buffer[0] = 'S';
-                       output_buffer[1] = hexchars[sigval >> 4];
-                       output_buffer[2] = hexchars[sigval & 0xf];
+                       output_buffer[1] = hex_asc_hi(sigval);
+                       output_buffer[2] = hex_asc_lo(sigval);
                        output_buffer[3] = 0;
                        break;
 
@@ -2059,8 +2043,8 @@ void gdbstub_exit(int status)
        }
 
        gdbstub_tx_char('#');
-       gdbstub_tx_char(hexchars[checksum >> 4]);
-       gdbstub_tx_char(hexchars[checksum & 0xf]);
+       gdbstub_tx_char(hex_asc_hi(checksum));
+       gdbstub_tx_char(hex_asc_lo(checksum));
 
        /* make sure the output is flushed, or else RedBoot might clobber it */
        gdbstub_tx_char('-');
index 73f3aeefd2034ac0b0f35d8268ad7adac631d314..d1113c5031f5f4f19a16314378e63ab3a9889301 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <linux/pm_legacy.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
index 9af7740f32fb348a1cecf13a8e5292627e53ecf0..1b851db341865420257f388a9fc9e31828a1d0e8 100644 (file)
@@ -61,37 +61,6 @@ static unsigned long empty_bad_page;
 unsigned long empty_zero_page;
 EXPORT_SYMBOL(empty_zero_page);
 
-/*****************************************************************************/
-/*
- *
- */
-void show_mem(void)
-{
-       unsigned long i;
-       int free = 0, total = 0, reserved = 0, shared = 0;
-
-       printk("\nMem-info:\n");
-       show_free_areas();
-       i = max_mapnr;
-       while (i-- > 0) {
-               struct page *page = &mem_map[i];
-
-               total++;
-               if (PageReserved(page))
-                       reserved++;
-               else if (!page_count(page))
-                       free++;
-               else
-                       shared += page_count(page) - 1;
-       }
-
-       printk("%d pages of RAM\n",total);
-       printk("%d free pages\n",free);
-       printk("%d reserved pages\n",reserved);
-       printk("%d pages shared\n",shared);
-
-} /* end show_mem() */
-
 /*****************************************************************************/
 /*
  * paging_init() continues the virtual memory environment setup which
index 085dc6ec152b057b6da23c2742a39d0a0012c327..396ab059efa35a9fa1d2e8258aff56cd0f8f0ab4 100644 (file)
@@ -203,20 +203,6 @@ config UNIX98_PTYS
          Read the instructions in <file:Documentation/Changes> pertaining to
          pseudo terminals. It's safe to say N.
 
-config UNIX98_PTY_COUNT
-       int "Maximum number of Unix98 PTYs in use (0-2048)"
-       depends on UNIX98_PTYS
-       default "256"
-       help
-         The maximum number of Unix98 PTYs that can be used at any one time.
-         The default is 256, and should be enough for desktop systems. Server
-         machines which support incoming telnet/rlogin/ssh connections and/or
-         serve several X terminals may want to increase this: every incoming
-         connection and every xterm uses up one PTY.
-
-         When not in use, each additional set of 256 PTYs occupy
-         approximately 8 KB of kernel memory on 32-bit architectures.
-
 source "drivers/char/pcmcia/Kconfig"
 
 source "drivers/serial/Kconfig"
index 845074588af0aacf98d9b16d2d63590669c65b04..51ab6cbd030f58a9c439e9bc65849fd460d7b749 100644 (file)
@@ -67,8 +67,6 @@ static unsigned outcnt = 0;  /* bytes in output buffer */
 static int  fill_inbuf(void);
 static void flush_window(void);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 extern char input_data[];
 extern int input_len;
@@ -77,11 +75,7 @@ static long bytes_out = 0;
 static uch *output_data;
 static unsigned long output_ptr = 0;
 
-static void *malloc(int size);
-static void free(void *where);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 int puts(const char *);
 
@@ -98,38 +92,6 @@ static unsigned long free_mem_end_ptr;
 #define TDR *((volatile unsigned char *)0xffff8b)
 #define SSR *((volatile unsigned char *)0xffff8c)
 
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size <0) error("Malloc error");
-       if (free_mem_ptr == 0) error("Memory error");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *)free_mem_ptr;
-       free_mem_ptr += size;
-
-       if (free_mem_ptr >= free_mem_end_ptr)
-               error("Out of memory");
-
-       return p;
-}
-
-static void free(void *where)
-{      /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
-       *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
-       free_mem_ptr = (long) *ptr;
-}
-
 int puts(const char *s)
 {
        return 0;
index b1f25c20a5dbdb8f6c1a2c4a29e61546499ce3e7..7fda657110eb3d7a7cab104dd3d81f1693506526 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/fb.h>
 #include <linux/console.h>
index e4f4199f97abc874cbf98fd1f5e73559919e4f62..a1d228f5e4e6b4282ac10558ad6fc801a209e4cf 100644 (file)
@@ -64,33 +64,6 @@ unsigned long empty_zero_page;
 
 extern unsigned long rom_length;
 
-void show_mem(void)
-{
-    unsigned long i;
-    int free = 0, total = 0, reserved = 0, shared = 0;
-    int cached = 0;
-
-    printk("\nMem-info:\n");
-    show_free_areas();
-    i = max_mapnr;
-    while (i-- > 0) {
-       total++;
-       if (PageReserved(mem_map+i))
-           reserved++;
-       else if (PageSwapCache(mem_map+i))
-           cached++;
-       else if (!page_count(mem_map+i))
-           free++;
-       else
-           shared += page_count(mem_map+i) - 1;
-    }
-    printk("%d pages of RAM\n",total);
-    printk("%d free pages\n",free);
-    printk("%d reserved pages\n",reserved);
-    printk("%d pages shared\n",shared);
-    printk("%d pages swap cached\n",cached);
-}
-
 extern unsigned long memory_start;
 extern unsigned long memory_end;
 
index 1c44ec2a1d58e2495cb21f41759dcee218471ffc..88b6e6f3fd88b6245079c966b1a721fbee65f89d 100644 (file)
@@ -186,9 +186,10 @@ hwsw_dma_supported (struct device *dev, u64 mask)
 }
 
 int
-hwsw_dma_mapping_error (dma_addr_t dma_addr)
+hwsw_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-       return hwiommu_dma_mapping_error (dma_addr) || swiotlb_dma_mapping_error(dma_addr);
+       return hwiommu_dma_mapping_error(dev, dma_addr) ||
+               swiotlb_dma_mapping_error(dev, dma_addr);
 }
 
 EXPORT_SYMBOL(hwsw_dma_mapping_error);
index 34421aed1e2ab95ff0d4f4d4e458003b409fd1a2..4956be40d7b56d9c03a3224e45f743e8f6e34d39 100644 (file)
@@ -2147,7 +2147,7 @@ sba_dma_supported (struct device *dev, u64 mask)
 }
 
 int
-sba_dma_mapping_error (dma_addr_t dma_addr)
+sba_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return 0;
 }
index 7e028ceb93ba6272abfaa9635bec1fc4ef6e6d6a..465116aecb85adf03880caf8285abeecc8c300e3 100644 (file)
@@ -1139,7 +1139,7 @@ sys32_pipe (int __user *fd)
        int retval;
        int fds[2];
 
-       retval = do_pipe(fds);
+       retval = do_pipe_flags(fds, 0);
        if (retval)
                goto out;
        if (copy_to_user(fd, fds, sizeof(fds)))
index 56ab156c48aed88303ddde98d6b085dd7e9ac6ea..0dd6c1419d8dfa6be2a9996a54c714f8f3488423 100644 (file)
@@ -1691,6 +1691,12 @@ sys_call_table:
        data8 sys_timerfd_create                // 1310
        data8 sys_timerfd_settime
        data8 sys_timerfd_gettime
+       data8 sys_signalfd4
+       data8 sys_eventfd2
+       data8 sys_epoll_create1                 // 1315
+       data8 sys_dup3
+       data8 sys_pipe2
+       data8 sys_inotify_init1
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
index 233434f4f88f21cc58da0e0f2c7c726268db4f72..f07688da947c352217246d706435d09256d8894e 100644 (file)
@@ -429,8 +429,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
                ((struct fnptr *)kretprobe_trampoline)->ip;
 
        INIT_HLIST_HEAD(&empty_rp);
-       spin_lock_irqsave(&kretprobe_lock, flags);
-       head = kretprobe_inst_table_head(current);
+       kretprobe_hash_lock(current, &head, &flags);
 
        /*
         * It is possible to have multiple instances associated with a given
@@ -485,7 +484,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
        kretprobe_assert(ri, orig_ret_address, trampoline_address);
 
        reset_current_kprobe();
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
+       kretprobe_hash_unlock(current, &flags);
        preempt_enable_no_resched();
 
        hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
@@ -500,7 +499,6 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
        return 1;
 }
 
-/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                      struct pt_regs *regs)
 {
index 19d4493c619323d3f91acffeff43a08bf45aec6b..fc8f3509df270ba010ec4e2ce9765d0459d6f77e 100644 (file)
@@ -2626,7 +2626,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task)
        /*
         * make sure the task is off any CPU
         */
-       wait_task_inactive(task);
+       wait_task_inactive(task, 0);
 
        /* more to come... */
 
@@ -4774,7 +4774,7 @@ recheck:
 
                UNPROTECT_CTX(ctx, flags);
 
-               wait_task_inactive(task);
+               wait_task_inactive(task, 0);
 
                PROTECT_CTX(ctx, flags);
 
index 1eda194b95595110497adb009e457f8fe5c9d116..bcbb6d8792d3344352d226cb6e4fdda7c7d4182e 100644 (file)
@@ -160,7 +160,7 @@ sys_pipe (void)
        int fd[2];
        int retval;
 
-       retval = do_pipe(fd);
+       retval = do_pipe_flags(fd, 0);
        if (retval)
                goto out;
        retval = fd[0];
index 2672f4d278ac52695592f23f6ddc501fcce3b7a8..7a37d06376be893799fa2bfdb30311251a3edbeb 100644 (file)
@@ -125,9 +125,9 @@ void kvm_arch_hardware_enable(void *garbage)
                                PAGE_KERNEL));
        local_irq_save(saved_psr);
        slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
+       local_irq_restore(saved_psr);
        if (slot < 0)
                return;
-       local_irq_restore(saved_psr);
 
        spin_lock(&vp_lock);
        status = ia64_pal_vp_init_env(kvm_vsa_base ?
@@ -160,9 +160,9 @@ void kvm_arch_hardware_disable(void *garbage)
 
        local_irq_save(saved_psr);
        slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
+       local_irq_restore(saved_psr);
        if (slot < 0)
                return;
-       local_irq_restore(saved_psr);
 
        status = ia64_pal_vp_exit_env(host_iva);
        if (status)
@@ -1253,6 +1253,7 @@ static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id)
 uninit:
        kvm_vcpu_uninit(vcpu);
 fail:
+       local_irq_restore(psr);
        return r;
 }
 
index 544dc420c65ed06cf00f043c10f041c70ea87633..d83125e1ed27b33a1e7ef04794324380dc97f862 100644 (file)
@@ -36,7 +36,6 @@ struct early_node_data {
        struct ia64_node_data *node_data;
        unsigned long pernode_addr;
        unsigned long pernode_size;
-       struct bootmem_data bootmem_data;
        unsigned long num_physpages;
 #ifdef CONFIG_ZONE_DMA
        unsigned long num_dma_physpages;
@@ -75,17 +74,17 @@ pg_data_t *pgdat_list[MAX_NUMNODES];
 static int __init build_node_maps(unsigned long start, unsigned long len,
                                  int node)
 {
-       unsigned long cstart, epfn, end = start + len;
-       struct bootmem_data *bdp = &mem_data[node].bootmem_data;
+       unsigned long spfn, epfn, end = start + len;
+       struct bootmem_data *bdp = &bootmem_node_data[node];
 
        epfn = GRANULEROUNDUP(end) >> PAGE_SHIFT;
-       cstart = GRANULEROUNDDOWN(start);
+       spfn = GRANULEROUNDDOWN(start) >> PAGE_SHIFT;
 
        if (!bdp->node_low_pfn) {
-               bdp->node_boot_start = cstart;
+               bdp->node_min_pfn = spfn;
                bdp->node_low_pfn = epfn;
        } else {
-               bdp->node_boot_start = min(cstart, bdp->node_boot_start);
+               bdp->node_min_pfn = min(spfn, bdp->node_min_pfn);
                bdp->node_low_pfn = max(epfn, bdp->node_low_pfn);
        }
 
@@ -167,7 +166,7 @@ static void __init fill_pernode(int node, unsigned long pernode,
 {
        void *cpu_data;
        int cpus = early_nr_cpus_node(node);
-       struct bootmem_data *bdp = &mem_data[node].bootmem_data;
+       struct bootmem_data *bdp = &bootmem_node_data[node];
 
        mem_data[node].pernode_addr = pernode;
        mem_data[node].pernode_size = pernodesize;
@@ -222,20 +221,21 @@ static void __init fill_pernode(int node, unsigned long pernode,
 static int __init find_pernode_space(unsigned long start, unsigned long len,
                                     int node)
 {
-       unsigned long epfn;
+       unsigned long spfn, epfn;
        unsigned long pernodesize = 0, pernode, pages, mapsize;
-       struct bootmem_data *bdp = &mem_data[node].bootmem_data;
+       struct bootmem_data *bdp = &bootmem_node_data[node];
 
+       spfn = start >> PAGE_SHIFT;
        epfn = (start + len) >> PAGE_SHIFT;
 
-       pages = bdp->node_low_pfn - (bdp->node_boot_start >> PAGE_SHIFT);
+       pages = bdp->node_low_pfn - bdp->node_min_pfn;
        mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
 
        /*
         * Make sure this memory falls within this node's usable memory
         * since we may have thrown some away in build_maps().
         */
-       if (start < bdp->node_boot_start || epfn > bdp->node_low_pfn)
+       if (spfn < bdp->node_min_pfn || epfn > bdp->node_low_pfn)
                return 0;
 
        /* Don't setup this node's local space twice... */
@@ -297,7 +297,7 @@ static void __init reserve_pernode_space(void)
                bdp = pdp->bdata;
 
                /* First the bootmem_map itself */
-               pages = bdp->node_low_pfn - (bdp->node_boot_start>>PAGE_SHIFT);
+               pages = bdp->node_low_pfn - bdp->node_min_pfn;
                size = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
                base = __pa(bdp->node_bootmem_map);
                reserve_bootmem_node(pdp, base, size, BOOTMEM_DEFAULT);
@@ -440,7 +440,7 @@ void __init find_memory(void)
        efi_memmap_walk(find_max_min_low_pfn, NULL);
 
        for_each_online_node(node)
-               if (mem_data[node].bootmem_data.node_low_pfn) {
+               if (bootmem_node_data[node].node_low_pfn) {
                        node_clear(node, memory_less_mask);
                        mem_data[node].min_pfn = ~0UL;
                }
@@ -460,14 +460,14 @@ void __init find_memory(void)
                else if (node_isset(node, memory_less_mask))
                        continue;
 
-               bdp = &mem_data[node].bootmem_data;
+               bdp = &bootmem_node_data[node];
                pernode = mem_data[node].pernode_addr;
                pernodesize = mem_data[node].pernode_size;
                map = pernode + pernodesize;
 
                init_bootmem_node(pgdat_list[node],
                                  map>>PAGE_SHIFT,
-                                 bdp->node_boot_start>>PAGE_SHIFT,
+                                 bdp->node_min_pfn,
                                  bdp->node_low_pfn);
        }
 
index d3ce8f3bcaa694070c8ccefb2ef4f03fac2fe6d0..c45fc7f5a979b6064b7e8a403de1922b21adf6df 100644 (file)
@@ -24,7 +24,7 @@
 unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT;
 
 pte_t *
-huge_pte_alloc (struct mm_struct *mm, unsigned long addr)
+huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz)
 {
        unsigned long taddr = htlbpage_to_page(addr);
        pgd_t *pgd;
@@ -75,7 +75,8 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
  * Don't actually need to do any preparation, but need to make sure
  * the address is in the right region.
  */
-int prepare_hugepage_range(unsigned long addr, unsigned long len)
+int prepare_hugepage_range(struct file *file,
+                       unsigned long addr, unsigned long len)
 {
        if (len & ~HPAGE_MASK)
                return -EINVAL;
@@ -106,13 +107,19 @@ int pmd_huge(pmd_t pmd)
 {
        return 0;
 }
+
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *
 follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write)
 {
        return NULL;
 }
 
-void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+void hugetlb_free_pgd_range(struct mmu_gather *tlb,
                        unsigned long addr, unsigned long end,
                        unsigned long floor, unsigned long ceiling)
 {
@@ -149,7 +156,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u
 
        /* Handle MAP_FIXED */
        if (flags & MAP_FIXED) {
-               if (prepare_hugepage_range(addr, len))
+               if (prepare_hugepage_range(file, addr, len))
                        return -EINVAL;
                return addr;
        }
index 52175af299a0424516fc3299c8509487581956dc..53ebb6484495545550e3f07e149bea575db07981 100644 (file)
@@ -350,7 +350,7 @@ void sn_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 }
 EXPORT_SYMBOL(sn_dma_sync_sg_for_device);
 
-int sn_dma_mapping_error(dma_addr_t dma_addr)
+int sn_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return 0;
 }
index 600d40e33495dcb4b8419d70ebbac051407d189c..d394292498c0eb245161cd93c17c16b4b8ccca7b 100644 (file)
@@ -70,8 +70,6 @@ static unsigned outcnt = 0;  /* bytes in output buffer */
 static int  fill_inbuf(void);
 static void flush_window(void);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 static unsigned char *input_data;
 static int input_len;
@@ -82,9 +80,6 @@ static unsigned long output_ptr = 0;
 
 #include "m32r_sio.c"
 
-static void *malloc(int size);
-static void free(void *where);
-
 static unsigned long free_mem_ptr;
 static unsigned long free_mem_end_ptr;
 
@@ -92,38 +87,6 @@ static unsigned long free_mem_end_ptr;
 
 #include "../../../../lib/inflate.c"
 
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size <0) error("Malloc error");
-       if (free_mem_ptr == 0) error("Memory error");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *)free_mem_ptr;
-       free_mem_ptr += size;
-
-       if (free_mem_ptr >= free_mem_end_ptr)
-               error("Out of memory");
-
-       return p;
-}
-
-static void free(void *where)
-{      /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
-       *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
-       free_mem_ptr = (long) *ptr;
-}
-
 void* memset(void* s, int c, size_t n)
 {
        int i;
index 07c1af7dc0e2a3bffec2474e22fab8a17fee0dce..cbc3c4c54566bbfb3f7fb418968e5798798ec740 100644 (file)
@@ -20,7 +20,6 @@ extern char _end[];
 
 struct pglist_data *node_data[MAX_NUMNODES];
 EXPORT_SYMBOL(node_data);
-static bootmem_data_t node_bdata[MAX_NUMNODES] __initdata;
 
 pg_data_t m32r_node_data[MAX_NUMNODES];
 
@@ -81,7 +80,7 @@ unsigned long __init setup_memory(void)
        for_each_online_node(nid) {
                mp = &mem_prof[nid];
                NODE_DATA(nid)=(pg_data_t *)&m32r_node_data[nid];
-               NODE_DATA(nid)->bdata = &node_bdata[nid];
+               NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
                min_pfn = mp->start_pfn;
                max_pfn = mp->start_pfn + mp->pages;
                bootmap_size = init_bootmem_node(NODE_DATA(nid), mp->free_pfn,
@@ -124,8 +123,7 @@ unsigned long __init setup_memory(void)
        return max_low_pfn;
 }
 
-#define START_PFN(nid) \
-       (NODE_DATA(nid)->bdata->node_boot_start >> PAGE_SHIFT)
+#define START_PFN(nid)         (NODE_DATA(nid)->bdata->node_min_pfn)
 #define MAX_LOW_PFN(nid)       (NODE_DATA(nid)->bdata->node_low_pfn)
 
 unsigned long __init zone_sizes_init(void)
@@ -148,8 +146,7 @@ unsigned long __init zone_sizes_init(void)
                zholes_size[ZONE_DMA] = mp->holes;
                holes += zholes_size[ZONE_DMA];
 
-               free_area_init_node(nid, NODE_DATA(nid), zones_size,
-                       start_pfn, zholes_size);
+               free_area_init_node(nid, zones_size, start_pfn, zholes_size);
        }
 
        /*
@@ -163,4 +160,3 @@ unsigned long __init zone_sizes_init(void)
 
        return holes;
 }
-
index bbd97c85bc5d8c1222477bb8b9a0786b26d14268..24d429f9358a5d96dd2c79f04332ccee40a67ae4 100644 (file)
@@ -36,42 +36,6 @@ pgd_t swapper_pg_dir[1024];
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-void show_mem(void)
-{
-       int total = 0, reserved = 0;
-       int shared = 0, cached = 0;
-       int highmem = 0;
-       struct page *page;
-       pg_data_t *pgdat;
-       unsigned long i;
-
-       printk("Mem-info:\n");
-       show_free_areas();
-       printk("Free swap:       %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-       for_each_online_pgdat(pgdat) {
-               unsigned long flags;
-               pgdat_resize_lock(pgdat, &flags);
-               for (i = 0; i < pgdat->node_spanned_pages; ++i) {
-                       page = pgdat_page_nr(pgdat, i);
-                       total++;
-                       if (PageHighMem(page))
-                               highmem++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
-               }
-               pgdat_resize_unlock(pgdat, &flags);
-       }
-       printk("%d pages of RAM\n", total);
-       printk("%d pages of HIGHMEM\n",highmem);
-       printk("%d reserved pages\n",reserved);
-       printk("%d pages shared\n",shared);
-       printk("%d pages swap cached\n",cached);
-}
-
 /*
  * Cache of MMU context last used.
  */
@@ -93,8 +57,7 @@ void free_initrd_mem(unsigned long, unsigned long);
 #endif
 
 /* It'd be good if these lines were in the standard header file. */
-#define START_PFN(nid) \
-       (NODE_DATA(nid)->bdata->node_boot_start >> PAGE_SHIFT)
+#define START_PFN(nid)         (NODE_DATA(nid)->bdata->node_min_pfn)
 #define MAX_LOW_PFN(nid)       (NODE_DATA(nid)->bdata->node_low_pfn)
 
 #ifndef CONFIG_DISCONTIGMEM
@@ -123,7 +86,7 @@ unsigned long __init zone_sizes_init(void)
        start_pfn = __MEMORY_START >> PAGE_SHIFT;
 #endif /* CONFIG_MMU */
 
-       free_area_init_node(0, NODE_DATA(0), zones_size, start_pfn, 0);
+       free_area_init_node(0, zones_size, start_pfn, 0);
 
        return 0;
 }
@@ -252,4 +215,3 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 }
 #endif
-
index cbe36538af47be5cd2914fe7172ad2ea0f96c026..61df1d33c0500c514cb520cb3cbef58f5f3622d9 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
index d8fb9c5303ccf931bca250fa61e410849e886492..81bb08ceec18372e16110a86fe38b7ca441ba383 100644 (file)
@@ -32,8 +32,6 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-static bootmem_data_t __initdata bootmem_data[MAX_NUMNODES];
-
 pg_data_t pg_data_map[MAX_NUMNODES];
 EXPORT_SYMBOL(pg_data_map);
 
@@ -58,7 +56,7 @@ void __init m68k_setup_node(int node)
                pg_data_table[i] = pg_data_map + node;
        }
 #endif
-       pg_data_map[node].bdata = bootmem_data + node;
+       pg_data_map[node].bdata = bootmem_node_data + node;
        node_set_online(node);
 }
 
@@ -71,36 +69,6 @@ void __init m68k_setup_node(int node)
 void *empty_zero_page;
 EXPORT_SYMBOL(empty_zero_page);
 
-void show_mem(void)
-{
-       pg_data_t *pgdat;
-       int free = 0, total = 0, reserved = 0, shared = 0;
-       int cached = 0;
-       int i;
-
-       printk("\nMem-info:\n");
-       show_free_areas();
-       for_each_online_pgdat(pgdat) {
-               for (i = 0; i < pgdat->node_spanned_pages; i++) {
-                       struct page *page = pgdat->node_mem_map + i;
-                       total++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (!page_count(page))
-                               free++;
-                       else
-                               shared += page_count(page) - 1;
-               }
-       }
-       printk("%d pages of RAM\n",total);
-       printk("%d free pages\n",free);
-       printk("%d reserved pages\n",reserved);
-       printk("%d pages shared\n",shared);
-       printk("%d pages swap cached\n",cached);
-}
-
 extern void init_pointer_table(unsigned long ptable);
 
 /* References to section boundaries */
index 226795bdf3550d5aeee4cc30b4d1f2d6af269ba2..c5dbb9bdb32283c7978736a3b695907e1c076615 100644 (file)
@@ -296,7 +296,7 @@ void __init paging_init(void)
 #endif
        for (i = 0; i < m68k_num_memory; i++) {
                zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
-               free_area_init_node(i, pg_data_map + i, zones_size,
+               free_area_init_node(i, zones_size,
                                    m68k_memory[i].addr >> PAGE_SHIFT, NULL);
        }
 }
index edceefc18870732c1bf906ec0475c56b4c252050..1b902dbd4376d7bb4a5e6882edba77bb5384515f 100644 (file)
@@ -94,7 +94,7 @@ void __init paging_init(void)
 
        /* I really wish I knew why the following change made things better...  -- Sam */
 /*     free_area_init(zones_size); */
-       free_area_init_node(0, NODE_DATA(0), zones_size,
+       free_area_init_node(0, zones_size,
                            (__pa(PAGE_OFFSET) >> PAGE_SHIFT) + 1, NULL);
 
 
index 8e8441587c22bcb566976360ec34e53d6145fcd8..2e7515e8db985a9f4b50820edae74a643cf0f325 100644 (file)
@@ -58,10 +58,18 @@ config GENERIC_TIME
        bool
        default y
 
+config GENERIC_CMOS_UPDATE
+       bool
+       default y
+
 config TIME_LOW_RES
        bool
        default y
 
+config GENERIC_CLOCKEVENTS
+       bool
+       default n
+
 config NO_IOPORT
        def_bool y
 
@@ -108,11 +116,13 @@ config M5206e
 
 config M520x
        bool "MCF520x"
+       select GENERIC_CLOCKEVENTS
        help
           Freescale Coldfire 5207/5208 processor support.
 
 config M523x
        bool "MCF523x"
+       select GENERIC_CLOCKEVENTS
        help
          Freescale Coldfire 5230/1/2/4/5 processor support
 
@@ -138,6 +148,7 @@ config M5275
 
 config M528x
        bool "MCF528x"
+       select GENERIC_CLOCKEVENTS
        help
          Motorola ColdFire 5280/5282 processor support.
 
@@ -161,6 +172,7 @@ endchoice
 config M527x
        bool
        depends on (M5271 || M5275)
+       select GENERIC_CLOCKEVENTS
        default y
 
 config COLDFIRE
@@ -674,6 +686,9 @@ endchoice
 if COLDFIRE
 source "kernel/Kconfig.preempt"
 endif
+
+source "kernel/time/Kconfig"
+
 source "mm/Kconfig"
 
 endmenu
index e0b5f62e395caff7ee475a660482e2cdd8b24883..b63bbcf874ffa95799d4a93c2f1602f1175c4b10 100644 (file)
@@ -8,6 +8,8 @@
 # (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com>
 #
 
+KBUILD_DEFCONFIG := m5208evb_defconfig
+
 platform-$(CONFIG_M68328)      := 68328
 platform-$(CONFIG_M68EZ328)    := 68EZ328
 platform-$(CONFIG_M68VZ328)    := 68VZ328
@@ -90,13 +92,14 @@ export PLATFORM BOARD MODEL CPUCLASS
 cflags-$(CONFIG_M5206)         := -m5200
 cflags-$(CONFIG_M5206e)                := -m5200
 cflags-$(CONFIG_M520x)         := -m5307
-cflags-$(CONFIG_M523x)         := -m5307
+cflags-$(CONFIG_M523x)         := $(call cc-option,-mcpu=523x,-m5307)
 cflags-$(CONFIG_M5249)         := -m5200
-cflags-$(CONFIG_M527x)         := -m5307
+cflags-$(CONFIG_M5271)         := $(call cc-option,-mcpu=5271,-m5307)
 cflags-$(CONFIG_M5272)         := -m5307
-cflags-$(CONFIG_M528x)         := -m5307
+cflags-$(CONFIG_M5275)         := $(call cc-option,-mcpu=5275,-m5307)
+cflags-$(CONFIG_M528x)         := $(call cc-option,-m528x,-m5307)
 cflags-$(CONFIG_M5307)         := -m5307
-cflags-$(CONFIG_M532x)         := -m5307
+cflags-$(CONFIG_M532x)         := $(call cc-option,-mcpu=532x,-m5307)
 cflags-$(CONFIG_M5407)         := -m5200
 cflags-$(CONFIG_M68328)                := -m68000
 cflags-$(CONFIG_M68EZ328)      := -m68000
diff --git a/arch/m68knommu/configs/m5208evb_defconfig b/arch/m68knommu/configs/m5208evb_defconfig
new file mode 100644 (file)
index 0000000..6fae33a
--- /dev/null
@@ -0,0 +1,610 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+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 is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG 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"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+CONFIG_M520x=y
+# CONFIG_M523x is not set
+# CONFIG_M5249 is not set
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+# CONFIG_M5275 is not set
+# CONFIG_M528x is not set
+# CONFIG_M5307 is not set
+# CONFIG_M532x is not set
+# CONFIG_M5407 is not set
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=166666666
+CONFIG_CLOCK_DIV=2
+
+#
+# Platform
+#
+CONFIG_M5208EVB=y
+CONFIG_FREESCALE=y
+# CONFIG_4KSTACKS is not set
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x40000000
+CONFIG_RAMSIZE=0x2000000
+CONFIG_VECTORBASE=0x40000000
+CONFIG_KERNELBASE=0x40020000
+# CONFIG_RAMAUTOBIT is not set
+# CONFIG_RAM8BIT is not set
+CONFIG_RAM16BIT=y
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL 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_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM 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 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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+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
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_UCLINUX=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
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+CONFIG_FEC=y
+# CONFIG_FEC2 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# 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_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=115200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA 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_SYSCTL=y
+# CONFIG_SYSFS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_FULLDEBUG=y
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/configs/m5249evb_defconfig b/arch/m68knommu/configs/m5249evb_defconfig
new file mode 100644 (file)
index 0000000..cc64583
--- /dev/null
@@ -0,0 +1,497 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+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 is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG 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"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+# CONFIG_M520x is not set
+# CONFIG_M523x is not set
+CONFIG_M5249=y
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+# CONFIG_M5275 is not set
+# CONFIG_M528x is not set
+# CONFIG_M5307 is not set
+# CONFIG_M532x is not set
+# CONFIG_M5407 is not set
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=140000000
+CONFIG_CLOCK_DIV=2
+
+#
+# Platform
+#
+CONFIG_M5249C3=y
+CONFIG_FREESCALE=y
+CONFIG_4KSTACKS=y
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00800000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_RAMAUTOBIT=y
+# CONFIG_RAM8BIT is not set
+# CONFIG_RAM16BIT is not set
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL 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_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+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
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE 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_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=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
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+# 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_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=19200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA 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_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_FULLDEBUG is not set
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/configs/m5275evb_defconfig b/arch/m68knommu/configs/m5275evb_defconfig
new file mode 100644 (file)
index 0000000..0d1256f
--- /dev/null
@@ -0,0 +1,627 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+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 is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG 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"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+# CONFIG_M520x is not set
+# CONFIG_M523x is not set
+# CONFIG_M5249 is not set
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+CONFIG_M5275=y
+# CONFIG_M528x is not set
+# CONFIG_M5307 is not set
+# CONFIG_M532x is not set
+# CONFIG_M5407 is not set
+CONFIG_M527x=y
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=150000000
+CONFIG_CLOCK_DIV=2
+
+#
+# Platform
+#
+CONFIG_M5275EVB=y
+CONFIG_FREESCALE=y
+# CONFIG_4KSTACKS is not set
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00000000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_RAMAUTOBIT=y
+# CONFIG_RAM8BIT is not set
+# CONFIG_RAM16BIT is not set
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL 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_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM 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 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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+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
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE 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_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=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
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+CONFIG_FEC=y
+CONFIG_FEC2=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# 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_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=19200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA 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_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# 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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_FULLDEBUG is not set
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/configs/m5307c3_defconfig b/arch/m68knommu/configs/m5307c3_defconfig
new file mode 100644 (file)
index 0000000..fe2acdf
--- /dev/null
@@ -0,0 +1,580 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+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 is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG 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"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+# CONFIG_M520x is not set
+# CONFIG_M523x is not set
+# CONFIG_M5249 is not set
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+# CONFIG_M5275 is not set
+# CONFIG_M528x is not set
+CONFIG_M5307=y
+# CONFIG_M532x is not set
+# CONFIG_M5407 is not set
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=90000000
+CONFIG_CLOCK_DIV=2
+# CONFIG_OLDMASK is not set
+
+#
+# Platform
+#
+# CONFIG_ARN5307 is not set
+CONFIG_M5307C3=y
+# CONFIG_eLIA is not set
+# CONFIG_SECUREEDGEMP3 is not set
+# CONFIG_CLEOPATRA is not set
+# CONFIG_NETtel is not set
+CONFIG_FREESCALE=y
+# CONFIG_4KSTACKS is not set
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00800000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_RAMAUTOBIT=y
+# CONFIG_RAM8BIT is not set
+# CONFIG_RAM16BIT is not set
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL 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_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_COMEMPCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM 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 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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=y
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV 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_TABLET 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_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=19200
+CONFIG_SERIAL_MCF_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA 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_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# 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_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_FULLDEBUG=y
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/configs/m5407c3_defconfig b/arch/m68knommu/configs/m5407c3_defconfig
new file mode 100644 (file)
index 0000000..1118936
--- /dev/null
@@ -0,0 +1,641 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+# Wed May  7 10:25:16 2008
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+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 is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG 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"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+# CONFIG_M520x is not set
+# CONFIG_M523x is not set
+# CONFIG_M5249 is not set
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+# CONFIG_M5275 is not set
+# CONFIG_M528x is not set
+# CONFIG_M5307 is not set
+# CONFIG_M532x is not set
+CONFIG_M5407=y
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=50000000
+CONFIG_CLOCK_DIV=1
+
+#
+# Platform
+#
+CONFIG_M5407C3=y
+# CONFIG_CLEOPATRA is not set
+CONFIG_FREESCALE=y
+CONFIG_4KSTACKS=y
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00000000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_RAMAUTOBIT=y
+# CONFIG_RAM8BIT is not set
+# CONFIG_RAM16BIT is not set
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL 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_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_COMEMPCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM 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 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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+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
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE 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_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=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
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV 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_TABLET 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_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=19200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA 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_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_FULLDEBUG is not set
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
index 03f4fe6a2fc0e20e6e28f233cb8718a4799dd9b6..5985f198902113d6ce971e975983fa09019db051 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/fb.h>
 #include <linux/module.h>
+#include <linux/mm.h>
 #include <linux/console.h>
 #include <linux/errno.h>
 #include <linux/string.h>
index 0ccfb2ad63800ee44e449847840885d02760a011..d182b2f722110d098d5e380179b0618298e4b3b4 100644 (file)
@@ -33,14 +33,13 @@ static inline int set_rtc_mmss(unsigned long nowtime)
        return -1;
 }
 
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
 irqreturn_t arch_timer_interrupt(int irq, void *dummy)
 {
-       /* last time the cmos clock got updated */
-       static long last_rtc_update=0;
 
        if (current->pid)
                profile_tick(CPU_PROFILING);
@@ -49,21 +48,6 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy)
 
        do_timer(1);
 
-       /*
-        * If we have an externally synchronized Linux clock, then update
-        * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-        * called as close as possible to 500 ms before the new second starts.
-        */
-       if (ntp_synced() &&
-           xtime.tv_sec > last_rtc_update + 660 &&
-           (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
-           (xtime.tv_nsec  / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
-         if (set_rtc_mmss(xtime.tv_sec) == 0)
-           last_rtc_update = xtime.tv_sec;
-         else
-           last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-       }
-
        write_sequnlock(&xtime_lock);
 
 #ifndef CONFIG_SMP
@@ -71,8 +55,9 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy)
 #endif
        return(IRQ_HANDLED);
 }
+#endif
 
-void time_init(void)
+static unsigned long read_rtc_mmss(void)
 {
        unsigned int year, mon, day, hour, min, sec;
 
@@ -83,10 +68,21 @@ void time_init(void)
 
        if ((year += 1900) < 1970)
                year += 100;
-       xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
-       xtime.tv_nsec = 0;
-       wall_to_monotonic.tv_sec = -xtime.tv_sec;
 
-       hw_timer_init();
+       return  mktime(year, mon, day, hour, min, sec);;
+}
+
+unsigned long read_persistent_clock(void)
+{
+       return read_rtc_mmss();
 }
 
+int update_persistent_clock(struct timespec now)
+{
+       return set_rtc_mmss(now.tv_sec);
+}
+
+void time_init(void)
+{
+       hw_timer_init();
+}
index ec9aea652e79d0665adcb36fe5e9cd49d9625a51..46f8f9d0c4089085c2c3888e0c63afa2cbbb0e09 100644 (file)
@@ -103,12 +103,28 @@ asmlinkage void buserr_c(struct frame *fp)
        force_sig(SIGSEGV, current);
 }
 
+static void print_this_address(unsigned long addr, int i)
+{
+#ifdef CONFIG_KALLSYMS
+       printk(KERN_EMERG " [%08lx] ", addr);
+       print_symbol(KERN_CONT "%s\n", addr);
+#else
+       if (i % 5)
+               printk(KERN_CONT " [%08lx] ", addr);
+       else
+               printk(KERN_CONT "\n" KERN_EMERG " [%08lx] ", addr);
+       i++;
+#endif
+}
+
 int kstack_depth_to_print = 48;
 
 static void __show_stack(struct task_struct *task, unsigned long *stack)
 {
        unsigned long *endstack, addr;
+#ifdef CONFIG_FRAME_POINTER
        unsigned long *last_stack;
+#endif
        int i;
 
        if (!stack)
@@ -126,6 +142,7 @@ static void __show_stack(struct task_struct *task, unsigned long *stack)
                printk(" %08lx", *(stack + i));
        }
        printk("\n");
+       i = 0;
 
 #ifdef CONFIG_FRAME_POINTER
        printk(KERN_EMERG "Call Trace:\n");
@@ -134,15 +151,30 @@ static void __show_stack(struct task_struct *task, unsigned long *stack)
        while (stack <= endstack && stack > last_stack) {
 
                addr = *(stack + 1);
-               printk(KERN_EMERG " [%08lx] ", addr);
-               print_symbol(KERN_CONT "%s\n", addr);
+               print_this_address(addr, i);
+               i++;
 
                last_stack = stack;
                stack = (unsigned long *)*stack;
        }
        printk("\n");
 #else
-       printk(KERN_EMERG "CONFIG_FRAME_POINTER disabled, no symbolic call trace\n");
+       printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
+       while (stack <= endstack) {
+               addr = *stack++;
+               /*
+                * If the address is either in the text segment of the kernel,
+                * or in a region which is occupied by a module then it *may*
+                * be the address of a calling routine; if so, print it so that
+                * someone tracing down the cause of the crash will be able to
+                * figure out the call path that was taken.
+                */
+               if (__kernel_text_address(addr)) {
+                       print_this_address(addr, i);
+                       i++;
+               }
+       }
+       printk(KERN_CONT "\n");
 #endif
 }
 
index 93e69236ed6f8bfd1b6b38408aa380fc43d247de..69ba9b10767abaa49948ea060dfd1c1609908448 100644 (file)
@@ -62,6 +62,7 @@ SECTIONS {
        .text : {
                _text = .;
                _stext = . ;
+               HEAD_TEXT
                TEXT_TEXT
                SCHED_TEXT
                LOCK_TEXT
index 22e2a0d02b81958ab078a874baa9d07c680142b2..3bf249c53e414834114bc845dde4b63afe8e2add 100644 (file)
@@ -62,33 +62,6 @@ static unsigned long empty_bad_page;
 
 unsigned long empty_zero_page;
 
-void show_mem(void)
-{
-    unsigned long i;
-    int free = 0, total = 0, reserved = 0, shared = 0;
-    int cached = 0;
-
-    printk(KERN_INFO "\nMem-info:\n");
-    show_free_areas();
-    i = max_mapnr;
-    while (i-- > 0) {
-       total++;
-       if (PageReserved(mem_map+i))
-           reserved++;
-       else if (PageSwapCache(mem_map+i))
-           cached++;
-       else if (!page_count(mem_map+i))
-           free++;
-       else
-           shared += page_count(mem_map+i) - 1;
-    }
-    printk(KERN_INFO "%d pages of RAM\n",total);
-    printk(KERN_INFO "%d free pages\n",free);
-    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);
-}
-
 extern unsigned long memory_start;
 extern unsigned long memory_end;
 
index 40cf20be1b906fd26e0d5a191be56dbe5bfdc522..4f416a91a829b38c9f130ecad667307ea0ef98f6 100644 (file)
@@ -18,7 +18,7 @@ obj-$(CONFIG_COLDFIRE)        += dma.o entry.o vectors.o
 obj-$(CONFIG_M5206)    += timers.o
 obj-$(CONFIG_M5206e)   += timers.o
 obj-$(CONFIG_M520x)    += pit.o
-obj-$(CONFIG_M523x)    += pit.o
+obj-$(CONFIG_M523x)    += pit.o dma_timer.o
 obj-$(CONFIG_M5249)    += timers.o
 obj-$(CONFIG_M527x)    += pit.o
 obj-$(CONFIG_M5272)    += timers.o
diff --git a/arch/m68knommu/platform/coldfire/dma_timer.c b/arch/m68knommu/platform/coldfire/dma_timer.c
new file mode 100644 (file)
index 0000000..772578b
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * dma_timer.c -- Freescale ColdFire DMA Timer.
+ *
+ * Copyright (C) 2007, Benedikt Spranger <b.spranger@linutronix.de>
+ * Copyright (C) 2008. Sebastian Siewior, Linutronix
+ *
+ */
+
+#include <linux/clocksource.h>
+#include <linux/io.h>
+
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfpit.h>
+#include <asm/mcfsim.h>
+
+#define DMA_TIMER_0    (0x00)
+#define DMA_TIMER_1    (0x40)
+#define DMA_TIMER_2    (0x80)
+#define DMA_TIMER_3    (0xc0)
+
+#define DTMR0  (MCF_IPSBAR + DMA_TIMER_0 + 0x400)
+#define DTXMR0 (MCF_IPSBAR + DMA_TIMER_0 + 0x402)
+#define DTER0  (MCF_IPSBAR + DMA_TIMER_0 + 0x403)
+#define DTRR0  (MCF_IPSBAR + DMA_TIMER_0 + 0x404)
+#define DTCR0  (MCF_IPSBAR + DMA_TIMER_0 + 0x408)
+#define DTCN0  (MCF_IPSBAR + DMA_TIMER_0 + 0x40c)
+
+#define DMA_FREQ    ((MCF_CLK / 2) / 16)
+
+/* DTMR */
+#define DMA_DTMR_RESTART       (1 << 3)
+#define DMA_DTMR_CLK_DIV_1     (1 << 1)
+#define DMA_DTMR_CLK_DIV_16    (2 << 1)
+#define DMA_DTMR_ENABLE                (1 << 0)
+
+static cycle_t cf_dt_get_cycles(void)
+{
+       return __raw_readl(DTCN0);
+}
+
+static struct clocksource clocksource_cf_dt = {
+       .name           = "coldfire_dma_timer",
+       .rating         = 200,
+       .read           = cf_dt_get_cycles,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .shift          = 20,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init  init_cf_dt_clocksource(void)
+{
+       /*
+        * We setup DMA timer 0 in free run mode. This incrementing counter is
+        * used as a highly precious clock source. With MCF_CLOCK = 150 MHz we
+        * get a ~213 ns resolution and the 32bit register will overflow almost
+        * every 15 minutes.
+        */
+       __raw_writeb(0x00, DTXMR0);
+       __raw_writeb(0x00, DTER0);
+       __raw_writel(0x00000000, DTRR0);
+       __raw_writew(DMA_DTMR_CLK_DIV_16 | DMA_DTMR_ENABLE, DTMR0);
+       clocksource_cf_dt.mult = clocksource_hz2mult(DMA_FREQ,
+                                                    clocksource_cf_dt.shift);
+       return clocksource_register(&clocksource_cf_dt);
+}
+
+arch_initcall(init_cf_dt_clocksource);
+
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+#define CYC2NS_SCALE   ((1000000 << CYC2NS_SCALE_FACTOR) / (DMA_FREQ / 1000))
+
+static unsigned long long cycles2ns(unsigned long cycl)
+{
+       return (unsigned long long) ((unsigned long long)cycl *
+                       CYC2NS_SCALE) >> CYC2NS_SCALE_FACTOR;
+}
+
+unsigned long long sched_clock(void)
+{
+       unsigned long cycl = __raw_readl(DTCN0);
+
+       return cycles2ns(cycl);
+}
index b9aa0ca29bfba45ca1bf74e917ec243a67aa666d..2b0d73c0cc328c6bb975a9204c731d6b311b4c9d 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/sys.h>
 #include <linux/linkage.h>
+#include <linux/init.h>
 #include <asm/asm-offsets.h>
 #include <asm/coldfire.h>
 #include <asm/mcfcache.h>
@@ -126,7 +127,7 @@ _ramend:
 
 /*****************************************************************************/
 
-.text
+__HEAD
 
 /*
  *     This is the codes first entry point. This is where it all
index 4290638012e0ee3dfee426848fb8624bb8cb77e5..c5b916700b222194e68e148d3ad13115bd41625e 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/clocksource.h>
+#include <linux/clockchips.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/coldfire.h>
 #define        FREQ    ((MCF_CLK / 2) / 64)
 #define        TA(a)   (MCF_IPSBAR + MCFPIT_BASE1 + (a))
 #define        INTC0   (MCF_IPSBAR + MCFICM_INTC0)
+#define PIT_CYCLES_PER_JIFFY (FREQ / HZ)
 
-static u32 pit_cycles_per_jiffy;
 static u32 pit_cnt;
 
+/*
+ * Initialize the PIT timer.
+ *
+ * This is also called after resume to bring the PIT into operation again.
+ */
+
+static void init_cf_pit_timer(enum clock_event_mode mode,
+                             struct clock_event_device *evt)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+
+               __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+               __raw_writew(PIT_CYCLES_PER_JIFFY, TA(MCFPIT_PMR));
+               __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
+                               MCFPIT_PCSR_OVW | MCFPIT_PCSR_RLD | \
+                               MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
+               break;
+
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+
+               __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+               break;
+
+       case CLOCK_EVT_MODE_ONESHOT:
+
+               __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+               __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
+                               MCFPIT_PCSR_OVW | MCFPIT_PCSR_CLK64, \
+                               TA(MCFPIT_PCSR));
+               break;
+
+       case CLOCK_EVT_MODE_RESUME:
+               /* Nothing to do here */
+               break;
+       }
+}
+
+/*
+ * Program the next event in oneshot mode
+ *
+ * Delta is given in PIT ticks
+ */
+static int cf_pit_next_event(unsigned long delta,
+               struct clock_event_device *evt)
+{
+       __raw_writew(delta, TA(MCFPIT_PMR));
+       return 0;
+}
+
+struct clock_event_device cf_pit_clockevent = {
+       .name           = "pit",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode       = init_cf_pit_timer,
+       .set_next_event = cf_pit_next_event,
+       .shift          = 32,
+       .irq            = MCFINT_VECBASE + MCFINT_PIT1,
+};
+
+
+
 /***************************************************************************/
 
 static irqreturn_t pit_tick(int irq, void *dummy)
 {
+       struct clock_event_device *evt = &cf_pit_clockevent;
        u16 pcsr;
 
        /* Reset the ColdFire timer */
        pcsr = __raw_readw(TA(MCFPIT_PCSR));
        __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
 
-       pit_cnt += pit_cycles_per_jiffy;
-       return arch_timer_interrupt(irq, dummy);
+       pit_cnt += PIT_CYCLES_PER_JIFFY;
+       evt->event_handler(evt);
+       return IRQ_HANDLED;
 }
 
 /***************************************************************************/
@@ -72,14 +136,14 @@ static cycle_t pit_read_clk(void)
        cycles = pit_cnt;
        local_irq_restore(flags);
 
-       return cycles + pit_cycles_per_jiffy - pcntr;
+       return cycles + PIT_CYCLES_PER_JIFFY - pcntr;
 }
 
 /***************************************************************************/
 
 static struct clocksource pit_clk = {
        .name   = "pit",
-       .rating = 250,
+       .rating = 100,
        .read   = pit_read_clk,
        .shift  = 20,
        .mask   = CLOCKSOURCE_MASK(32),
@@ -92,6 +156,14 @@ void hw_timer_init(void)
 {
        u32 imr;
 
+       cf_pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
+       cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32);
+       cf_pit_clockevent.max_delta_ns =
+               clockevent_delta2ns(0xFFFF, &cf_pit_clockevent);
+       cf_pit_clockevent.min_delta_ns =
+               clockevent_delta2ns(0x3f, &cf_pit_clockevent);
+       clockevents_register_device(&cf_pit_clockevent);
+
        setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq);
 
        __raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1);
@@ -99,13 +171,6 @@ void hw_timer_init(void)
        imr &= ~MCFPIT_IMR_IBIT;
        __raw_writel(imr, INTC0 + MCFPIT_IMR);
 
-       /* Set up PIT timer 1 as poll clock */
-       pit_cycles_per_jiffy = FREQ / HZ;
-       __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
-       __raw_writew(pit_cycles_per_jiffy, TA(MCFPIT_PMR));
-       __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
-               MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
-
        pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift);
        clocksource_register(&pit_clk);
 }
index b9c754f4070cc131d0420fea6af9570106eb7978..b4c4eaa5dd265bbdd4646898a99f63e86e01e315 100644 (file)
@@ -713,7 +713,7 @@ config CSRC_SB1250
 
 config GPIO_TXX9
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
        bool
 
 config CFE
index 2166b9e1e80cf4fe1fe3452a4db5f8f852662005..bd854a6d1d89d0d5cd6fd5ff4369d74ee4cc079c 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <linux/init.h>
 #include <linux/pm.h>
-#include <linux/pm_legacy.h>
 #include <linux/sysctl.h>
 #include <linux/jiffies.h>
 
index c266211ed653d728c83e150215d8325be35f346f..2fefb14414b7db6db1dbfd4b58719082197439ba 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/file.h>
 #include <linux/smp_lock.h>
 #include <linux/highuid.h>
-#include <linux/dirent.h>
 #include <linux/resource.h>
 #include <linux/highmem.h>
 #include <linux/time.h>
index e7ed0ac485375744bf8b78be07d2ef595357d644..1f60e27523d9e65ad43289462ee269e4c696ba30 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/moduleloader.h>
 #include <linux/elf.h>
+#include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
index c06f5b5d764cdb6779ad93aa453732c8218397b4..b16facd9ea8ecae7b27116952090beca25450c78 100644 (file)
@@ -53,7 +53,7 @@ void __noreturn cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched()) {
 #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
                        extern void smtc_idle_loop_hook(void);
index 5eb4681a73d2fe7c29ee02010abe5287a5411ad0..0632e2a849c0a50e19ad18c147d6be11a99945ff 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
+#include <linux/module.h>
 #include <asm/stacktrace.h>
 
 /*
index 3523c8d12eda8707af06e8054320374626635852..343015a2f418fd9fb741ef6ae7b8821008e1af19 100644 (file)
@@ -52,7 +52,7 @@ asmlinkage int sysm_pipe(nabi_no_regargs volatile struct pt_regs regs)
        int fd[2];
        int error, res;
 
-       error = do_pipe(fd);
+       error = do_pipe_flags(fd, 0);
        if (error) {
                res = error;
                goto out;
index 48731020ca0e9bb61fc31cef45f80c4bee2ca289..44e8dd8106bf47c774e239e8f550ed4ac6216801 100644 (file)
@@ -3,8 +3,7 @@
 #
 
 obj-y                          += cache.o dma-default.o extable.o fault.o \
-                                  init.o pgtable.o tlbex.o tlbex-fault.o \
-                                  uasm.o page.o
+                                  init.o tlbex.o tlbex-fault.o uasm.o page.o
 
 obj-$(CONFIG_32BIT)            += ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)            += pgtable-64.o
index ae39dd88b9aa0eb97cb63b4c56bbe41c1811ad94..891312f8e5a6b19d01b6485cda535821520e346c 100644 (file)
@@ -348,7 +348,7 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nele
 
 EXPORT_SYMBOL(dma_sync_sg_for_device);
 
-int dma_mapping_error(dma_addr_t dma_addr)
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return 0;
 }
diff --git a/arch/mips/mm/pgtable.c b/arch/mips/mm/pgtable.c
deleted file mode 100644 (file)
index 7dfa579..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-
-void show_mem(void)
-{
-#ifndef CONFIG_NEED_MULTIPLE_NODES  /* XXX(hch): later.. */
-       int pfn, total = 0, reserved = 0;
-       int shared = 0, cached = 0;
-       int highmem = 0;
-       struct page *page;
-
-       printk("Mem-info:\n");
-       show_free_areas();
-       pfn = max_mapnr;
-       while (pfn-- > 0) {
-               if (!pfn_valid(pfn))
-                       continue;
-               page = pfn_to_page(pfn);
-               total++;
-               if (PageHighMem(page))
-                       highmem++;
-               if (PageReserved(page))
-                       reserved++;
-               else if (PageSwapCache(page))
-                       cached++;
-               else if (page_count(page))
-                       shared += page_count(page) - 1;
-       }
-       printk("%d pages of RAM\n", total);
-       printk("%d pages of HIGHMEM\n", highmem);
-       printk("%d reserved pages\n", reserved);
-       printk("%d pages shared\n", shared);
-       printk("%d pages swap cached\n", cached);
-#endif
-}
index 48932ce1d7302bc7972a29be1d620273e83f3136..d9c79d8be81d1b65745e2454b12e56db05ea75c5 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2000 - 2001 Kanoj Sarcar (kanoj@sgi.com)
  */
 #include <linux/init.h>
+#include <linux/mm.h>
 #include <linux/mmzone.h>
 #include <linux/kernel.h>
 #include <linux/nodemask.h>
index 42cd109563064e2a818b8def35419829a2611f93..060d853d7b35126a01287d64467e82997bea1107 100644 (file)
@@ -33,8 +33,6 @@
 #define SLOT_PFNSHIFT           (SLOT_SHIFT - PAGE_SHIFT)
 #define PFN_NASIDSHFT           (NASID_SHFT - PAGE_SHIFT)
 
-static struct bootmem_data __initdata plat_node_bdata[MAX_COMPACT_NODES];
-
 struct node_data *__node_data[MAX_COMPACT_NODES];
 
 EXPORT_SYMBOL(__node_data);
@@ -403,7 +401,7 @@ static void __init node_mem_init(cnodeid_t node)
         */
        __node_data[node] = __va(slot_freepfn << PAGE_SHIFT);
 
-       NODE_DATA(node)->bdata = &plat_node_bdata[node];
+       NODE_DATA(node)->bdata = &bootmem_node_data[node];
        NODE_DATA(node)->node_start_pfn = start_pfn;
        NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
 
index ded207efc97a540425746506bcdffd7964eb7d9d..f673383518e4cf26e42b42a6389a6b40b2e29440 100644 (file)
@@ -153,26 +153,9 @@ static uch *output_data;
 static unsigned long output_ptr;
 
 
-static void *malloc(int size);
-
-static inline void free(void *where)
-{      /* Don't care */
-}
-
 static unsigned long free_mem_ptr = (unsigned long) &end;
 static unsigned long free_mem_end_ptr = (unsigned long) &end + 0x90000;
 
-static inline void gzip_mark(void **ptr)
-{
-       kputs(".");
-       *ptr = (void *) free_mem_ptr;
-}
-
-static inline void gzip_release(void **ptr)
-{
-       free_mem_ptr = (unsigned long) *ptr;
-}
-
 #define INPLACE_MOVE_ROUTINE   0x1000
 #define LOW_BUFFER_START       0x2000
 #define LOW_BUFFER_END         0x90000
@@ -186,26 +169,6 @@ static int lines, cols;
 
 #include "../../../../lib/inflate.c"
 
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size < 0)
-               error("Malloc error\n");
-       if (!free_mem_ptr)
-               error("Memory error\n");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *) free_mem_ptr;
-       free_mem_ptr += size;
-
-       if (free_mem_ptr >= free_mem_end_ptr)
-               error("\nOut of memory\n");
-
-       return p;
-}
-
 static inline void scroll(void)
 {
        int i;
index 21891c71d54965ccb770391df6e5a4522658400e..54be6afb5555c3ae194df237b56c9ff2a387f551 100644 (file)
@@ -163,8 +163,6 @@ static char input_buffer[BUFMAX];
 static char    output_buffer[BUFMAX];
 static char    trans_buffer[BUFMAX];
 
-static const char hexchars[] = "0123456789abcdef";
-
 struct gdbstub_bkpt {
        u8      *addr;          /* address of breakpoint */
        u8      len;            /* size of breakpoint */
@@ -363,8 +361,8 @@ static int putpacket(char *buffer)
                }
 
                gdbstub_io_tx_char('#');
-               gdbstub_io_tx_char(hexchars[checksum >> 4]);
-               gdbstub_io_tx_char(hexchars[checksum & 0xf]);
+               gdbstub_io_tx_char(hex_asc_hi(checksum));
+               gdbstub_io_tx_char(hex_asc_lo(checksum));
 
        } while (gdbstub_io_rx_char(&ch, 0),
                 ch == '-' && (gdbstub_io("### GDB Rx NAK\n"), 0),
@@ -822,8 +820,7 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
        if ((u32) mem & 1 && count >= 1) {
                if (gdbstub_read_byte(mem, ch) != 0)
                        return 0;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
                mem++;
                count--;
        }
@@ -831,10 +828,8 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
        if ((u32) mem & 3 && count >= 2) {
                if (gdbstub_read_word(mem, ch) != 0)
                        return 0;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
-               *buf++ = hexchars[ch[1] >> 4];
-               *buf++ = hexchars[ch[1] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
+               buf = pack_hex_byte(buf, ch[1]);
                mem += 2;
                count -= 2;
        }
@@ -842,14 +837,10 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
        while (count >= 4) {
                if (gdbstub_read_dword(mem, ch) != 0)
                        return 0;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
-               *buf++ = hexchars[ch[1] >> 4];
-               *buf++ = hexchars[ch[1] & 0xf];
-               *buf++ = hexchars[ch[2] >> 4];
-               *buf++ = hexchars[ch[2] & 0xf];
-               *buf++ = hexchars[ch[3] >> 4];
-               *buf++ = hexchars[ch[3] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
+               buf = pack_hex_byte(buf, ch[1]);
+               buf = pack_hex_byte(buf, ch[2]);
+               buf = pack_hex_byte(buf, ch[3]);
                mem += 4;
                count -= 4;
        }
@@ -857,10 +848,8 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
        if (count >= 2) {
                if (gdbstub_read_word(mem, ch) != 0)
                        return 0;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
-               *buf++ = hexchars[ch[1] >> 4];
-               *buf++ = hexchars[ch[1] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
+               buf = pack_hex_byte(buf, ch[1]);
                mem += 2;
                count -= 2;
        }
@@ -868,8 +857,7 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
        if (count >= 1) {
                if (gdbstub_read_byte(mem, ch) != 0)
                        return 0;
-               *buf++ = hexchars[ch[0] >> 4];
-               *buf++ = hexchars[ch[0] & 0xf];
+               buf = pack_hex_byte(buf, ch[0]);
        }
 
        *buf = 0;
@@ -1304,14 +1292,14 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
                *ptr++ = 'O';
                ptr = mem2hex(title, ptr, sizeof(title) - 1, 0);
 
-               hx = hexchars[(excep & 0xf000) >> 12];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(excep & 0x0f00) >> 8];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(excep & 0x00f0) >> 4];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(excep & 0x000f)];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
+               hx = hex_asc_hi(excep >> 8);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(excep >> 8);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_hi(excep);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(excep);
+               ptr = pack_hex_byte(ptr, hx);
 
                ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
                *ptr = 0;
@@ -1322,22 +1310,22 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
                *ptr++ = 'O';
                ptr = mem2hex(tbcberr, ptr, sizeof(tbcberr) - 1, 0);
 
-               hx = hexchars[(bcberr & 0xf0000000) >> 28];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(bcberr & 0x0f000000) >> 24];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(bcberr & 0x00f00000) >> 20];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(bcberr & 0x000f0000) >> 16];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(bcberr & 0x0000f000) >> 12];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(bcberr & 0x00000f00) >> 8];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(bcberr & 0x000000f0) >> 4];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
-               hx = hexchars[(bcberr & 0x0000000f)];
-               *ptr++ = hexchars[hx >> 4];     *ptr++ = hexchars[hx & 0xf];
+               hx = hex_asc_hi(bcberr >> 24);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(bcberr >> 24);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_hi(bcberr >> 16);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(bcberr >> 16);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_hi(bcberr >> 8);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(bcberr >> 8);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_hi(bcberr);
+               ptr = pack_hex_byte(ptr, hx);
+               hx = hex_asc_lo(bcberr);
+               ptr = pack_hex_byte(ptr, hx);
 
                ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
                *ptr = 0;
@@ -1353,14 +1341,12 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
         * Send trap type (converted to signal)
         */
        *ptr++ = 'T';
-       *ptr++ = hexchars[sigval >> 4];
-       *ptr++ = hexchars[sigval & 0xf];
+       ptr = pack_hex_byte(ptr, sigval);
 
        /*
         * Send Error PC
         */
-       *ptr++ = hexchars[GDB_REGID_PC >> 4];
-       *ptr++ = hexchars[GDB_REGID_PC & 0xf];
+       ptr = pack_hex_byte(ptr, GDB_REGID_PC);
        *ptr++ = ':';
        ptr = mem2hex(&regs->pc, ptr, 4, 0);
        *ptr++ = ';';
@@ -1368,8 +1354,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
        /*
         * Send frame pointer
         */
-       *ptr++ = hexchars[GDB_REGID_FP >> 4];
-       *ptr++ = hexchars[GDB_REGID_FP & 0xf];
+       ptr = pack_hex_byte(ptr, GDB_REGID_FP);
        *ptr++ = ':';
        ptr = mem2hex(&regs->a3, ptr, 4, 0);
        *ptr++ = ';';
@@ -1378,8 +1363,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
         * Send stack pointer
         */
        ssp = (unsigned long) (regs + 1);
-       *ptr++ = hexchars[GDB_REGID_SP >> 4];
-       *ptr++ = hexchars[GDB_REGID_SP & 0xf];
+       ptr = pack_hex_byte(ptr, GDB_REGID_SP);
        *ptr++ = ':';
        ptr = mem2hex(&ssp, ptr, 4, 0);
        *ptr++ = ';';
@@ -1399,8 +1383,8 @@ packet_waiting:
                        /* request repeat of last signal number */
                case '?':
                        output_buffer[0] = 'S';
-                       output_buffer[1] = hexchars[sigval >> 4];
-                       output_buffer[2] = hexchars[sigval & 0xf];
+                       output_buffer[1] = hex_asc_hi(sigval);
+                       output_buffer[2] = hex_asc_lo(sigval);
                        output_buffer[3] = 0;
                        break;
 
@@ -1838,8 +1822,8 @@ void gdbstub_exit(int status)
 
        gdbstub_busy = 1;
        output_buffer[0] = 'W';
-       output_buffer[1] = hexchars[(status >> 4) & 0x0F];
-       output_buffer[2] = hexchars[status & 0x0F];
+       output_buffer[1] = hex_asc_hi(status);
+       output_buffer[2] = hex_asc_lo(status);
        output_buffer[3] = 0;
 
        gdbstub_io_tx_char('$');
@@ -1853,8 +1837,8 @@ void gdbstub_exit(int status)
        }
 
        gdbstub_io_tx_char('#');
-       gdbstub_io_tx_char(hexchars[checksum >> 4]);
-       gdbstub_io_tx_char(hexchars[checksum & 0xf]);
+       gdbstub_io_tx_char(hex_asc_hi(checksum));
+       gdbstub_io_tx_char(hex_asc_lo(checksum));
 
        /* make sure the output is flushed, or else RedBoot might clobber it */
        gdbstub_io_tx_flush();
index 8c5d88c7b90ae3cc42d0452171885f6fc3aad0b4..8cee387a24fd95ab9a3d65ab0bd0f9f0fdbb5dc1 100644 (file)
@@ -67,8 +67,8 @@ void __init paging_init(void)
 
        /* declare the sizes of the RAM zones (only use the normal zone) */
        zones_size[ZONE_NORMAL] =
-               (contig_page_data.bdata->node_low_pfn) -
-               (contig_page_data.bdata->node_boot_start >> PAGE_SHIFT);
+               contig_page_data.bdata->node_low_pfn -
+               contig_page_data.bdata->node_min_pfn;
 
        /* pass the memory from the bootmem allocator to the main allocator */
        free_area_init(zones_size);
@@ -87,7 +87,7 @@ void __init mem_init(void)
        if (!mem_map)
                BUG();
 
-#define START_PFN      (contig_page_data.bdata->node_boot_start >> PAGE_SHIFT)
+#define START_PFN      (contig_page_data.bdata->node_min_pfn)
 #define MAX_LOW_PFN    (contig_page_data.bdata->node_low_pfn)
 
        max_mapnr = num_physpages = MAX_LOW_PFN - START_PFN;
index a477038752bab6e1a7653c2b13adbcb7791bb4b0..baffc581e031d6cb3389f4e15d2268fbd38d945d 100644 (file)
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
-void show_mem(void)
-{
-       unsigned long i;
-       int free = 0, total = 0, reserved = 0, shared = 0;
-
-       int cached = 0;
-       printk(KERN_INFO "Mem-info:\n");
-       show_free_areas();
-       i = max_mapnr;
-       while (i-- > 0) {
-               total++;
-               if (PageReserved(mem_map + i))
-                       reserved++;
-               else if (PageSwapCache(mem_map + i))
-                       cached++;
-               else if (!page_count(mem_map + i))
-                       free++;
-               else
-                       shared += page_count(mem_map + i) - 1;
-       }
-       printk(KERN_INFO "%d pages of RAM\n", total);
-       printk(KERN_INFO "%d free pages\n", free);
-       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);
-}
-
 /*
  * Associate a large virtual page frame with a given physical page frame
  * and protection flags for that frame. pfn is for the base of the page,
index 0c5b9dabb4754b350d3763f1ae31b1b3f706e64a..18072e03a019e1411b88a5e0b3fa1ee48e2b6458 100644 (file)
@@ -210,19 +210,19 @@ static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf)
 }
 
 /* hpux statfs */
-asmlinkage long hpux_statfs(const char __user *path,
+asmlinkage long hpux_statfs(const char __user *pathname,
                                                struct hpux_statfs __user *buf)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (!error) {
                struct hpux_statfs tmp;
-               error = vfs_statfs_hpux(nd.path.dentry, &tmp);
+               error = vfs_statfs_hpux(path.dentry, &tmp);
                if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
                        error = -EFAULT;
-               path_put(&nd.path);
+               path_put(&path);
        }
        return error;
 }
@@ -448,7 +448,7 @@ int hpux_pipe(int *kstack_fildes)
        int error;
 
        lock_kernel();
-       error = do_pipe(kstack_fildes);
+       error = do_pipe_flags(kstack_fildes, 0);
        unlock_kernel();
        return error;
 }
index b4d6c8777ed0c1479bbd2231f5232a290b71bc33..7c155c254e72f82cf0dee7d54012de286441fa0b 100644 (file)
@@ -36,7 +36,6 @@ extern int  data_start;
 
 #ifdef CONFIG_DISCONTIGMEM
 struct node_map_data node_data[MAX_NUMNODES] __read_mostly;
-bootmem_data_t bmem_data[MAX_NUMNODES] __read_mostly;
 unsigned char pfnnid_map[PFNNID_MAP_MAX] __read_mostly;
 #endif
 
@@ -262,7 +261,7 @@ static void __init setup_bootmem(void)
 #ifdef CONFIG_DISCONTIGMEM
        for (i = 0; i < MAX_PHYSMEM_RANGES; i++) {
                memset(NODE_DATA(i), 0, sizeof(pg_data_t));
-               NODE_DATA(i)->bdata = &bmem_data[i];
+               NODE_DATA(i)->bdata = &bootmem_node_data[i];
        }
        memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
 
@@ -888,7 +887,7 @@ void __init paging_init(void)
                }
 #endif
 
-               free_area_init_node(i, NODE_DATA(i), zones_size,
+               free_area_init_node(i, zones_size,
                                pmem_ranges[i].start_pfn, NULL);
        }
 }
index 737ebf9d12bb9aca170de68098c758f796d46b0f..587da5e0990f9504979f9357b2783305e6a23d02 100644 (file)
@@ -110,10 +110,14 @@ config PPC
        default y
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FTRACE
+       select ARCH_WANT_OPTIONAL_GPIOLIB
        select HAVE_IDE
+       select HAVE_IOREMAP_PROT
+       select HAVE_EFFICIENT_UNALIGNED_ACCESS
        select HAVE_KPROBES
        select HAVE_ARCH_KGDB
        select HAVE_KRETPROBES
+       select HAVE_ARCH_TRACEHOOK
        select HAVE_LMB
        select HAVE_DMA_ATTRS if PPC64
        select USE_GENERIC_SMP_HELPERS if SMP
@@ -843,6 +847,7 @@ source "crypto/Kconfig"
 config PPC_CLOCK
        bool
        default n
+       select HAVE_CLK
 
 config PPC_LIB_RHEAP
        bool
index b936a1dd0a500adcf63f40a24538b57b32bd2609..25c273c761d19855f2d8861720c24f7cb095bb2f 100644 (file)
@@ -23,6 +23,9 @@
 struct cpu_spec* cur_cpu_spec = NULL;
 EXPORT_SYMBOL(cur_cpu_spec);
 
+/* The platform string corresponding to the real PVR */
+const char *powerpc_base_platform;
+
 /* NOTE:
  * Unlike ppc32, ppc64 will only call this once for the boot CPU, it's
  * the responsibility of the appropriate CPU save/restore functions to
@@ -1652,6 +1655,14 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
                        } else
                                *t = *s;
                        *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
+
+                       /*
+                        * Set the base platform string once; assumes
+                        * we're called with real pvr first.
+                        */
+                       if (*PTRRELOC(&powerpc_base_platform) == NULL)
+                               *PTRRELOC(&powerpc_base_platform) = t->platform;
+
 #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
                        /* ppc64 and booke expect identify_cpu to also call
                         * setup_cpu for that processor. I will consolidate
index da52269aec1e86fc05a2e1fb79d46dcc0b846a88..1cbbf70336415d37c5d14a1f1bd76f8fd1158a30 100644 (file)
@@ -343,7 +343,12 @@ syscall_dotrace:
        stw     r0,_TRAP(r1)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      do_syscall_trace_enter
-       lwz     r0,GPR0(r1)     /* Restore original registers */
+       /*
+        * Restore argument registers possibly just changed.
+        * We use the return value of do_syscall_trace_enter
+        * for call number to look up in the table (r0).
+        */
+       mr      r0,r3
        lwz     r3,GPR3(r1)
        lwz     r4,GPR4(r1)
        lwz     r5,GPR5(r1)
@@ -1055,8 +1060,8 @@ do_user_signal:                   /* r10 contains MSR_KERNEL here */
        SAVE_NVGPRS(r1)
        rlwinm  r3,r3,0,0,30
        stw     r3,_TRAP(r1)
-2:     li      r3,0
-       addi    r4,r1,STACK_FRAME_OVERHEAD
+2:     addi    r3,r1,STACK_FRAME_OVERHEAD
+       mr      r4,r9
        bl      do_signal
        REST_NVGPRS(r1)
        b       recheck
index d7369243ae44ab3aa0e12fcec3db30ae717677c2..2d802e97097c55056757fab95a86aa400f352d99 100644 (file)
@@ -214,7 +214,12 @@ syscall_dotrace:
        bl      .save_nvgprs
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .do_syscall_trace_enter
-       ld      r0,GPR0(r1)     /* Restore original registers */
+       /*
+        * Restore argument registers possibly just changed.
+        * We use the return value of do_syscall_trace_enter
+        * for the call number to look up in the table (r0).
+        */
+       mr      r0,r3
        ld      r3,GPR3(r1)
        ld      r4,GPR4(r1)
        ld      r5,GPR5(r1)
@@ -638,8 +643,7 @@ user_work:
        b       .ret_from_except_lite
 
 1:     bl      .save_nvgprs
-       li      r3,0
-       addi    r4,r1,STACK_FRAME_OVERHEAD
+       addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .do_signal
        b       .ret_from_except
 
index c3cf0e8f3ac173332a01148946ace8c43f45a5a5..d308a9f70f1b81b970ef0f13df10454f0deee3d9 100644 (file)
@@ -60,7 +60,7 @@ void cpu_idle(void)
 
        set_thread_flag(TIF_POLLING_NRFLAG);
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched() && !cpu_should_die()) {
                        ppc64_runlatch_off();
 
index 2385f68c1751d17774df413d44a30468cf8f5c5e..550a19399bfaac81bceabfbeb60f4a29e0e0752f 100644 (file)
@@ -49,6 +49,8 @@ static int novmerge = 1;
 
 static int protect4gb = 1;
 
+static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned int);
+
 static inline unsigned long iommu_num_pages(unsigned long vaddr,
                                            unsigned long slen)
 {
@@ -191,6 +193,7 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
 {
        unsigned long entry, flags;
        dma_addr_t ret = DMA_ERROR_CODE;
+       int build_fail;
 
        spin_lock_irqsave(&(tbl->it_lock), flags);
 
@@ -205,9 +208,21 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
        ret = entry << IOMMU_PAGE_SHIFT;        /* Set the return dma address */
 
        /* Put the TCEs in the HW table */
-       ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & IOMMU_PAGE_MASK,
-                        direction, attrs);
+       build_fail = ppc_md.tce_build(tbl, entry, npages,
+                                     (unsigned long)page & IOMMU_PAGE_MASK,
+                                     direction, attrs);
+
+       /* ppc_md.tce_build() only returns non-zero for transient errors.
+        * Clean up the table bitmap in this case and return
+        * DMA_ERROR_CODE. For all other errors the functionality is
+        * not altered.
+        */
+       if (unlikely(build_fail)) {
+               __iommu_free(tbl, ret, npages);
 
+               spin_unlock_irqrestore(&(tbl->it_lock), flags);
+               return DMA_ERROR_CODE;
+       }
 
        /* Flush/invalidate TLB caches if necessary */
        if (ppc_md.tce_flush)
@@ -276,7 +291,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
        dma_addr_t dma_next = 0, dma_addr;
        unsigned long flags;
        struct scatterlist *s, *outs, *segstart;
-       int outcount, incount, i;
+       int outcount, incount, i, build_fail = 0;
        unsigned int align;
        unsigned long handle;
        unsigned int max_seg_size;
@@ -337,8 +352,11 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                            npages, entry, dma_addr);
 
                /* Insert into HW table */
-               ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK,
-                                direction, attrs);
+               build_fail = ppc_md.tce_build(tbl, entry, npages,
+                                             vaddr & IOMMU_PAGE_MASK,
+                                             direction, attrs);
+               if(unlikely(build_fail))
+                       goto failure;
 
                /* If we are in an open segment, try merging */
                if (segstart != s) {
index 4ba2af125450ea895583efc086a5ea4c5d5724cf..de79915452c87d917728acbeefbd70a2b738d242 100644 (file)
@@ -144,7 +144,6 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
        kcb->kprobe_saved_msr = regs->msr;
 }
 
-/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                      struct pt_regs *regs)
 {
@@ -312,8 +311,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
        unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
 
        INIT_HLIST_HEAD(&empty_rp);
-       spin_lock_irqsave(&kretprobe_lock, flags);
-       head = kretprobe_inst_table_head(current);
+       kretprobe_hash_lock(current, &head, &flags);
 
        /*
         * It is possible to have multiple instances associated with a given
@@ -352,7 +350,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
        regs->nip = orig_ret_address;
 
        reset_current_kprobe();
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
+       kretprobe_hash_unlock(current, &flags);
        preempt_enable_no_resched();
 
        hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
index 4d96e1db55ee276c6c7a1e5e7b063c38d926b338..9ddfaef1a184564fb85f2919220fe4d99c33aad9 100644 (file)
@@ -493,18 +493,18 @@ static int __init serial_dev_init(void)
 device_initcall(serial_dev_init);
 
 
+#ifdef CONFIG_SERIAL_8250_CONSOLE
 /*
  * This is called very early, as part of console_init() (typically just after
  * time_init()). This function is respondible for trying to find a good
  * default console on serial ports. It tries to match the open firmware
- * default output with one of the available serial console drivers, either
- * one of the platform serial ports that have been probed earlier by
- * find_legacy_serial_ports() or some more platform specific ones.
+ * default output with one of the available serial console drivers that have
+ * been probed earlier by find_legacy_serial_ports()
  */
 static int __init check_legacy_serial_console(void)
 {
        struct device_node *prom_stdout = NULL;
-       int speed = 0, offset = 0;
+       int i, speed = 0, offset = 0;
        const char *name;
        const u32 *spd;
 
@@ -548,31 +548,20 @@ static int __init check_legacy_serial_console(void)
        if (spd)
                speed = *spd;
 
-       if (0)
-               ;
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-       else if (strcmp(name, "serial") == 0) {
-               int i;
-               /* Look for it in probed array */
-               for (i = 0; i < legacy_serial_count; i++) {
-                       if (prom_stdout != legacy_serial_infos[i].np)
-                               continue;
-                       offset = i;
-                       speed = legacy_serial_infos[i].speed;
-                       break;
-               }
-               if (i >= legacy_serial_count)
-                       goto not_found;
+       if (strcmp(name, "serial") != 0)
+               goto not_found;
+
+       /* Look for it in probed array */
+       for (i = 0; i < legacy_serial_count; i++) {
+               if (prom_stdout != legacy_serial_infos[i].np)
+                       continue;
+               offset = i;
+               speed = legacy_serial_infos[i].speed;
+               break;
        }
-#endif /* CONFIG_SERIAL_8250_CONSOLE */
-#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
-       else if (strcmp(name, "ch-a") == 0)
-               offset = 0;
-       else if (strcmp(name, "ch-b") == 0)
-               offset = 1;
-#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
-       else
+       if (i >= legacy_serial_count)
                goto not_found;
+
        of_node_put(prom_stdout);
 
        DBG("Found serial console at ttyS%d\n", offset);
@@ -591,3 +580,4 @@ static int __init check_legacy_serial_console(void)
 }
 console_initcall(check_legacy_serial_console);
 
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
index 827a5726a035c9a11d5a182b59b5c2c33f2ab618..9f856a0c3e3876eb1bd6bbe1e2e2b41dba70bf16 100644 (file)
@@ -34,8 +34,9 @@
 #include <asm/time.h>
 #include <asm/prom.h>
 #include <asm/vdso_datapage.h>
+#include <asm/vio.h>
 
-#define MODULE_VERS "1.7"
+#define MODULE_VERS "1.8"
 #define MODULE_NAME "lparcfg"
 
 /* #define LPARCFG_DEBUG */
@@ -129,32 +130,46 @@ static int iseries_lparcfg_data(struct seq_file *m, void *v)
 /*
  * Methods used to fetch LPAR data when running on a pSeries platform.
  */
-static void log_plpar_hcall_return(unsigned long rc, char *tag)
+/**
+ * h_get_mpp
+ * H_GET_MPP hcall returns info in 7 parms
+ */
+int h_get_mpp(struct hvcall_mpp_data *mpp_data)
 {
-       switch(rc) {
-       case 0:
-               return;
-       case H_HARDWARE:
-               printk(KERN_INFO "plpar-hcall (%s) "
-                               "Hardware fault\n", tag);
-               return;
-       case H_FUNCTION:
-               printk(KERN_INFO "plpar-hcall (%s) "
-                               "Function not allowed\n", tag);
-               return;
-       case H_AUTHORITY:
-               printk(KERN_INFO "plpar-hcall (%s) "
-                               "Not authorized to this function\n", tag);
-               return;
-       case H_PARAMETER:
-               printk(KERN_INFO "plpar-hcall (%s) "
-                               "Bad parameter(s)\n",tag);
-               return;
-       default:
-               printk(KERN_INFO "plpar-hcall (%s) "
-                               "Unexpected rc(0x%lx)\n", tag, rc);
-       }
+       int rc;
+       unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+
+       rc = plpar_hcall9(H_GET_MPP, retbuf);
+
+       mpp_data->entitled_mem = retbuf[0];
+       mpp_data->mapped_mem = retbuf[1];
+
+       mpp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff;
+       mpp_data->pool_num = retbuf[2] & 0xffff;
+
+       mpp_data->mem_weight = (retbuf[3] >> 7 * 8) & 0xff;
+       mpp_data->unallocated_mem_weight = (retbuf[3] >> 6 * 8) & 0xff;
+       mpp_data->unallocated_entitlement = retbuf[3] & 0xffffffffffff;
+
+       mpp_data->pool_size = retbuf[4];
+       mpp_data->loan_request = retbuf[5];
+       mpp_data->backing_mem = retbuf[6];
+
+       return rc;
 }
+EXPORT_SYMBOL(h_get_mpp);
+
+struct hvcall_ppp_data {
+       u64     entitlement;
+       u64     unallocated_entitlement;
+       u16     group_num;
+       u16     pool_num;
+       u8      capped;
+       u8      weight;
+       u8      unallocated_weight;
+       u16     active_procs_in_pool;
+       u16     active_system_procs;
+};
 
 /*
  * H_GET_PPP hcall returns info in 4 parms.
@@ -176,27 +191,30 @@ static void log_plpar_hcall_return(unsigned long rc, char *tag)
  *              XXXX - Active processors in Physical Processor Pool.
  *                  XXXX  - Processors active on platform.
  */
-static unsigned int h_get_ppp(unsigned long *entitled,
-                             unsigned long *unallocated,
-                             unsigned long *aggregation,
-                             unsigned long *resource)
+static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data)
 {
        unsigned long rc;
        unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
 
        rc = plpar_hcall(H_GET_PPP, retbuf);
 
-       *entitled = retbuf[0];
-       *unallocated = retbuf[1];
-       *aggregation = retbuf[2];
-       *resource = retbuf[3];
+       ppp_data->entitlement = retbuf[0];
+       ppp_data->unallocated_entitlement = retbuf[1];
+
+       ppp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff;
+       ppp_data->pool_num = retbuf[2] & 0xffff;
 
-       log_plpar_hcall_return(rc, "H_GET_PPP");
+       ppp_data->capped = (retbuf[3] >> 6 * 8) & 0x01;
+       ppp_data->weight = (retbuf[3] >> 5 * 8) & 0xff;
+       ppp_data->unallocated_weight = (retbuf[3] >> 4 * 8) & 0xff;
+       ppp_data->active_procs_in_pool = (retbuf[3] >> 2 * 8) & 0xffff;
+       ppp_data->active_system_procs = retbuf[3] & 0xffff;
 
        return rc;
 }
 
-static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
+static unsigned h_pic(unsigned long *pool_idle_time,
+                     unsigned long *num_procs)
 {
        unsigned long rc;
        unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
@@ -206,8 +224,87 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
        *pool_idle_time = retbuf[0];
        *num_procs = retbuf[1];
 
-       if (rc != H_AUTHORITY)
-               log_plpar_hcall_return(rc, "H_PIC");
+       return rc;
+}
+
+/*
+ * parse_ppp_data
+ * Parse out the data returned from h_get_ppp and h_pic
+ */
+static void parse_ppp_data(struct seq_file *m)
+{
+       struct hvcall_ppp_data ppp_data;
+       int rc;
+
+       rc = h_get_ppp(&ppp_data);
+       if (rc)
+               return;
+
+       seq_printf(m, "partition_entitled_capacity=%ld\n",
+                  ppp_data.entitlement);
+       seq_printf(m, "group=%d\n", ppp_data.group_num);
+       seq_printf(m, "system_active_processors=%d\n",
+                  ppp_data.active_system_procs);
+
+       /* pool related entries are apropriate for shared configs */
+       if (lppaca[0].shared_proc) {
+               unsigned long pool_idle_time, pool_procs;
+
+               seq_printf(m, "pool=%d\n", ppp_data.pool_num);
+
+               /* report pool_capacity in percentage */
+               seq_printf(m, "pool_capacity=%d\n",
+                          ppp_data.active_procs_in_pool * 100);
+
+               h_pic(&pool_idle_time, &pool_procs);
+               seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time);
+               seq_printf(m, "pool_num_procs=%ld\n", pool_procs);
+       }
+
+       seq_printf(m, "unallocated_capacity_weight=%d\n",
+                  ppp_data.unallocated_weight);
+       seq_printf(m, "capacity_weight=%d\n", ppp_data.weight);
+       seq_printf(m, "capped=%d\n", ppp_data.capped);
+       seq_printf(m, "unallocated_capacity=%ld\n",
+                  ppp_data.unallocated_entitlement);
+}
+
+/**
+ * parse_mpp_data
+ * Parse out data returned from h_get_mpp
+ */
+static void parse_mpp_data(struct seq_file *m)
+{
+       struct hvcall_mpp_data mpp_data;
+       int rc;
+
+       rc = h_get_mpp(&mpp_data);
+       if (rc)
+               return;
+
+       seq_printf(m, "entitled_memory=%ld\n", mpp_data.entitled_mem);
+
+       if (mpp_data.mapped_mem != -1)
+               seq_printf(m, "mapped_entitled_memory=%ld\n",
+                          mpp_data.mapped_mem);
+
+       seq_printf(m, "entitled_memory_group_number=%d\n", mpp_data.group_num);
+       seq_printf(m, "entitled_memory_pool_number=%d\n", mpp_data.pool_num);
+
+       seq_printf(m, "entitled_memory_weight=%d\n", mpp_data.mem_weight);
+       seq_printf(m, "unallocated_entitled_memory_weight=%d\n",
+                  mpp_data.unallocated_mem_weight);
+       seq_printf(m, "unallocated_io_mapping_entitlement=%ld\n",
+                  mpp_data.unallocated_entitlement);
+
+       if (mpp_data.pool_size != -1)
+               seq_printf(m, "entitled_memory_pool_size=%ld bytes\n",
+                          mpp_data.pool_size);
+
+       seq_printf(m, "entitled_memory_loan_request=%ld\n",
+                  mpp_data.loan_request);
+
+       seq_printf(m, "backing_memory=%ld bytes\n", mpp_data.backing_mem);
 }
 
 #define SPLPAR_CHARACTERISTICS_TOKEN 20
@@ -313,6 +410,25 @@ static int lparcfg_count_active_processors(void)
        return count;
 }
 
+static void pseries_cmo_data(struct seq_file *m)
+{
+       int cpu;
+       unsigned long cmo_faults = 0;
+       unsigned long cmo_fault_time = 0;
+
+       if (!firmware_has_feature(FW_FEATURE_CMO))
+               return;
+
+       for_each_possible_cpu(cpu) {
+               cmo_faults += lppaca[cpu].cmo_faults;
+               cmo_fault_time += lppaca[cpu].cmo_fault_time;
+       }
+
+       seq_printf(m, "cmo_faults=%lu\n", cmo_faults);
+       seq_printf(m, "cmo_fault_time_usec=%lu\n",
+                  cmo_fault_time / tb_ticks_per_usec);
+}
+
 static int pseries_lparcfg_data(struct seq_file *m, void *v)
 {
        int partition_potential_processors;
@@ -334,60 +450,13 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
        partition_active_processors = lparcfg_count_active_processors();
 
        if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
-               unsigned long h_entitled, h_unallocated;
-               unsigned long h_aggregation, h_resource;
-               unsigned long pool_idle_time, pool_procs;
-               unsigned long purr;
-
-               h_get_ppp(&h_entitled, &h_unallocated, &h_aggregation,
-                         &h_resource);
-
-               seq_printf(m, "R4=0x%lx\n", h_entitled);
-               seq_printf(m, "R5=0x%lx\n", h_unallocated);
-               seq_printf(m, "R6=0x%lx\n", h_aggregation);
-               seq_printf(m, "R7=0x%lx\n", h_resource);
-
-               purr = get_purr();
-
                /* this call handles the ibm,get-system-parameter contents */
                parse_system_parameter_string(m);
+               parse_ppp_data(m);
+               parse_mpp_data(m);
+               pseries_cmo_data(m);
 
-               seq_printf(m, "partition_entitled_capacity=%ld\n", h_entitled);
-
-               seq_printf(m, "group=%ld\n", (h_aggregation >> 2 * 8) & 0xffff);
-
-               seq_printf(m, "system_active_processors=%ld\n",
-                          (h_resource >> 0 * 8) & 0xffff);
-
-               /* pool related entries are apropriate for shared configs */
-               if (lppaca[0].shared_proc) {
-
-                       h_pic(&pool_idle_time, &pool_procs);
-
-                       seq_printf(m, "pool=%ld\n",
-                                  (h_aggregation >> 0 * 8) & 0xffff);
-
-                       /* report pool_capacity in percentage */
-                       seq_printf(m, "pool_capacity=%ld\n",
-                                  ((h_resource >> 2 * 8) & 0xffff) * 100);
-
-                       seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time);
-
-                       seq_printf(m, "pool_num_procs=%ld\n", pool_procs);
-               }
-
-               seq_printf(m, "unallocated_capacity_weight=%ld\n",
-                          (h_resource >> 4 * 8) & 0xFF);
-
-               seq_printf(m, "capacity_weight=%ld\n",
-                          (h_resource >> 5 * 8) & 0xFF);
-
-               seq_printf(m, "capped=%ld\n", (h_resource >> 6 * 8) & 0x01);
-
-               seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated);
-
-               seq_printf(m, "purr=%ld\n", purr);
-
+               seq_printf(m, "purr=%ld\n", get_purr());
        } else {                /* non SPLPAR case */
 
                seq_printf(m, "system_active_processors=%d\n",
@@ -414,6 +483,83 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
        return 0;
 }
 
+static ssize_t update_ppp(u64 *entitlement, u8 *weight)
+{
+       struct hvcall_ppp_data ppp_data;
+       u8 new_weight;
+       u64 new_entitled;
+       ssize_t retval;
+
+       /* Get our current parameters */
+       retval = h_get_ppp(&ppp_data);
+       if (retval)
+               return retval;
+
+       if (entitlement) {
+               new_weight = ppp_data.weight;
+               new_entitled = *entitlement;
+       } else if (weight) {
+               new_weight = *weight;
+               new_entitled = ppp_data.entitlement;
+       } else
+               return -EINVAL;
+
+       pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
+                __FUNCTION__, ppp_data.entitlement, ppp_data.weight);
+
+       pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
+                __FUNCTION__, new_entitled, new_weight);
+
+       retval = plpar_hcall_norets(H_SET_PPP, new_entitled, new_weight);
+       return retval;
+}
+
+/**
+ * update_mpp
+ *
+ * Update the memory entitlement and weight for the partition.  Caller must
+ * specify either a new entitlement or weight, not both, to be updated
+ * since the h_set_mpp call takes both entitlement and weight as parameters.
+ */
+static ssize_t update_mpp(u64 *entitlement, u8 *weight)
+{
+       struct hvcall_mpp_data mpp_data;
+       u64 new_entitled;
+       u8 new_weight;
+       ssize_t rc;
+
+       if (entitlement) {
+               /* Check with vio to ensure the new memory entitlement
+                * can be handled.
+                */
+               rc = vio_cmo_entitlement_update(*entitlement);
+               if (rc)
+                       return rc;
+       }
+
+       rc = h_get_mpp(&mpp_data);
+       if (rc)
+               return rc;
+
+       if (entitlement) {
+               new_weight = mpp_data.mem_weight;
+               new_entitled = *entitlement;
+       } else if (weight) {
+               new_weight = *weight;
+               new_entitled = mpp_data.entitled_mem;
+       } else
+               return -EINVAL;
+
+       pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
+                __FUNCTION__, mpp_data.entitled_mem, mpp_data.mem_weight);
+
+       pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
+                __FUNCTION__, new_entitled, new_weight);
+
+       rc = plpar_hcall_norets(H_SET_MPP, new_entitled, new_weight);
+       return rc;
+}
+
 /*
  * Interface for changing system parameters (variable capacity weight
  * and entitled capacity).  Format of input is "param_name=value";
@@ -427,35 +573,27 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
 static ssize_t lparcfg_write(struct file *file, const char __user * buf,
                             size_t count, loff_t * off)
 {
-       char *kbuf;
+       int kbuf_sz = 64;
+       char kbuf[kbuf_sz];
        char *tmp;
        u64 new_entitled, *new_entitled_ptr = &new_entitled;
        u8 new_weight, *new_weight_ptr = &new_weight;
-
-       unsigned long current_entitled; /* parameters for h_get_ppp */
-       unsigned long dummy;
-       unsigned long resource;
-       u8 current_weight;
-
-       ssize_t retval = -ENOMEM;
+       ssize_t retval;
 
        if (!firmware_has_feature(FW_FEATURE_SPLPAR) ||
                        firmware_has_feature(FW_FEATURE_ISERIES))
                return -EINVAL;
 
-       kbuf = kmalloc(count, GFP_KERNEL);
-       if (!kbuf)
-               goto out;
+       if (count > kbuf_sz)
+               return -EINVAL;
 
-       retval = -EFAULT;
        if (copy_from_user(kbuf, buf, count))
-               goto out;
+               return -EFAULT;
 
-       retval = -EINVAL;
        kbuf[count - 1] = '\0';
        tmp = strchr(kbuf, '=');
        if (!tmp)
-               goto out;
+               return -EINVAL;
 
        *tmp++ = '\0';
 
@@ -463,34 +601,32 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
                char *endp;
                *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10);
                if (endp == tmp)
-                       goto out;
-               new_weight_ptr = &current_weight;
+                       return -EINVAL;
+
+               retval = update_ppp(new_entitled_ptr, NULL);
        } else if (!strcmp(kbuf, "capacity_weight")) {
                char *endp;
                *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10);
                if (endp == tmp)
-                       goto out;
-               new_entitled_ptr = &current_entitled;
-       } else
-               goto out;
-
-       /* Get our current parameters */
-       retval = h_get_ppp(&current_entitled, &dummy, &dummy, &resource);
-       if (retval) {
-               retval = -EIO;
-               goto out;
-       }
-
-       current_weight = (resource >> 5 * 8) & 0xFF;
+                       return -EINVAL;
 
-       pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
-                __func__, current_entitled, current_weight);
+               retval = update_ppp(NULL, new_weight_ptr);
+       } else if (!strcmp(kbuf, "entitled_memory")) {
+               char *endp;
+               *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10);
+               if (endp == tmp)
+                       return -EINVAL;
 
-       pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
-                __func__, *new_entitled_ptr, *new_weight_ptr);
+               retval = update_mpp(new_entitled_ptr, NULL);
+       } else if (!strcmp(kbuf, "entitled_memory_weight")) {
+               char *endp;
+               *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10);
+               if (endp == tmp)
+                       return -EINVAL;
 
-       retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
-                                   *new_weight_ptr);
+               retval = update_mpp(NULL, new_weight_ptr);
+       } else
+               return -EINVAL;
 
        if (retval == H_SUCCESS || retval == H_CONSTRAINED) {
                retval = count;
@@ -506,8 +642,6 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
                retval = -EIO;
        }
 
-out:
-       kfree(kbuf);
        return retval;
 }
 
index 29a0e039d436011b61f2f97b96e8b3237e992977..aab76887a842c7dfa667141fe9467551338cf0ca 100644 (file)
@@ -48,7 +48,7 @@ void machine_kexec_cleanup(struct kimage *image)
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
  */
-NORET_TYPE void machine_kexec(struct kimage *image)
+void machine_kexec(struct kimage *image)
 {
        if (ppc_md.machine_kexec)
                ppc_md.machine_kexec(image);
index 219f3634115e46a05d0c1426d115aa95d58fef48..e030f3bd50248c2a85aae15e704f27bc1bd2dbe5 100644 (file)
@@ -47,6 +47,8 @@
 #ifdef CONFIG_PPC64
 #include <asm/firmware.h>
 #endif
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
 
 extern unsigned long _get_SP(void);
 
@@ -239,6 +241,35 @@ void discard_lazy_cpu_state(void)
 }
 #endif /* CONFIG_SMP */
 
+void do_dabr(struct pt_regs *regs, unsigned long address,
+                   unsigned long error_code)
+{
+       siginfo_t info;
+
+       if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+                       11, SIGSEGV) == NOTIFY_STOP)
+               return;
+
+       if (debugger_dabr_match(regs))
+               return;
+
+       /* Clear the DAC and struct entries.  One shot trigger */
+#if defined(CONFIG_BOOKE)
+       mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
+                                                       | DBCR0_IDM));
+#endif
+
+       /* Clear the DABR */
+       set_dabr(0);
+
+       /* Deliver the signal to userspace */
+       info.si_signo = SIGTRAP;
+       info.si_errno = 0;
+       info.si_code = TRAP_HWBKPT;
+       info.si_addr = (void __user *)address;
+       force_sig_info(SIGTRAP, &info, current);
+}
+
 static DEFINE_PER_CPU(unsigned long, current_dabr);
 
 int set_dabr(unsigned long dabr)
@@ -254,6 +285,11 @@ int set_dabr(unsigned long dabr)
 #if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
        mtspr(SPRN_DABR, dabr);
 #endif
+
+#if defined(CONFIG_BOOKE)
+       mtspr(SPRN_DAC1, dabr);
+#endif
+
        return 0;
 }
 
@@ -337,6 +373,12 @@ struct task_struct *__switch_to(struct task_struct *prev,
        if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
                set_dabr(new->thread.dabr);
 
+#if defined(CONFIG_BOOKE)
+       /* If new thread DAC (HW breakpoint) is the same then leave it */
+       if (new->thread.dabr)
+               set_dabr(new->thread.dabr);
+#endif
+
        new_thread = &new->thread;
        old_thread = &current->thread;
 
@@ -525,6 +567,10 @@ void flush_thread(void)
        if (current->thread.dabr) {
                current->thread.dabr = 0;
                set_dabr(0);
+
+#if defined(CONFIG_BOOKE)
+               current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
+#endif
        }
 }
 
index 1ea8c8d3ce89af4eb230a5a3332d8a020dee20cf..b72849ac7db39af14fe1547571da83066cdc3d77 100644 (file)
@@ -205,8 +205,6 @@ static int __initdata mem_reserve_cnt;
 static cell_t __initdata regbuf[1024];
 
 
-#define MAX_CPU_THREADS 2
-
 /*
  * Error results ... some OF calls will return "-1" on error, some
  * will return 0, some will return either. To simplify, here are
@@ -643,6 +641,11 @@ static void __init early_cmdline_parse(void)
 #else
 #define OV5_MSI                        0x00
 #endif /* CONFIG_PCI_MSI */
+#ifdef CONFIG_PPC_SMLPAR
+#define OV5_CMO                        0x80    /* Cooperative Memory Overcommitment */
+#else
+#define OV5_CMO                        0x00
+#endif
 
 /*
  * The architecture vector has an array of PVR mask/value pairs,
@@ -687,10 +690,12 @@ static unsigned char ibm_architecture_vec[] = {
        0,                              /* don't halt */
 
        /* option vector 5: PAPR/OF options */
-       3 - 2,                          /* length */
+       5 - 2,                          /* length */
        0,                              /* don't ignore, don't halt */
        OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
        OV5_DONATE_DEDICATE_CPU | OV5_MSI,
+       0,
+       OV5_CMO,
 };
 
 /* Old method - ELF header with PT_NOTE sections */
@@ -1332,10 +1337,6 @@ static void __init prom_hold_cpus(void)
        unsigned int reg;
        phandle node;
        char type[64];
-       int cpuid = 0;
-       unsigned int interrupt_server[MAX_CPU_THREADS];
-       unsigned int cpu_threads, hw_cpu_num;
-       int propsize;
        struct prom_t *_prom = &RELOC(prom);
        unsigned long *spinloop
                = (void *) LOW_ADDR(__secondary_hold_spinloop);
@@ -1379,7 +1380,6 @@ static void __init prom_hold_cpus(void)
                reg = -1;
                prom_getprop(node, "reg", &reg, sizeof(reg));
 
-               prom_debug("\ncpuid        = 0x%x\n", cpuid);
                prom_debug("cpu hw idx   = 0x%x\n", reg);
 
                /* Init the acknowledge var which will be reset by
@@ -1388,28 +1388,9 @@ static void __init prom_hold_cpus(void)
                 */
                *acknowledge = (unsigned long)-1;
 
-               propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",
-                                       &interrupt_server,
-                                       sizeof(interrupt_server));
-               if (propsize < 0) {
-                       /* no property.  old hardware has no SMT */
-                       cpu_threads = 1;
-                       interrupt_server[0] = reg; /* fake it with phys id */
-               } else {
-                       /* We have a threaded processor */
-                       cpu_threads = propsize / sizeof(u32);
-                       if (cpu_threads > MAX_CPU_THREADS) {
-                               prom_printf("SMT: too many threads!\n"
-                                           "SMT: found %x, max is %x\n",
-                                           cpu_threads, MAX_CPU_THREADS);
-                               cpu_threads = 1; /* ToDo: panic? */
-                       }
-               }
-
-               hw_cpu_num = interrupt_server[0];
-               if (hw_cpu_num != _prom->cpu) {
+               if (reg != _prom->cpu) {
                        /* Primary Thread of non-boot cpu */
-                       prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg);
+                       prom_printf("starting cpu hw idx %x... ", reg);
                        call_prom("start-cpu", 3, 0, node,
                                  secondary_hold, reg);
 
@@ -1424,17 +1405,10 @@ static void __init prom_hold_cpus(void)
                }
 #ifdef CONFIG_SMP
                else
-                       prom_printf("%x : boot cpu     %x\n", cpuid, reg);
+                       prom_printf("boot cpu hw idx %x\n", reg);
 #endif /* CONFIG_SMP */
-
-               /* Reserve cpu #s for secondary threads.   They start later. */
-               cpuid += cpu_threads;
        }
 
-       if (cpuid > NR_CPUS)
-               prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
-                           ") exceeded: ignoring extras\n");
-
        prom_debug("prom_hold_cpus: end...\n");
 }
 
index 8feb93e7890c74174de4a8161509f47735b3201c..6b66cd85b433ce8c296848f42e77ae5e18bcca87 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/regset.h>
+#include <linux/tracehook.h>
 #include <linux/elf.h>
 #include <linux/user.h>
 #include <linux/security.h>
@@ -703,7 +704,7 @@ void user_enable_single_step(struct task_struct *task)
 
        if (regs != NULL) {
 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
-               task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
+               task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
                regs->msr |= MSR_DE;
 #else
                regs->msr |= MSR_SE;
@@ -716,9 +717,16 @@ void user_disable_single_step(struct task_struct *task)
 {
        struct pt_regs *regs = task->thread.regs;
 
+
+#if defined(CONFIG_BOOKE)
+       /* If DAC then do not single step, skip */
+       if (task->thread.dabr)
+               return;
+#endif
+
        if (regs != NULL) {
 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
-               task->thread.dbcr0 = 0;
+               task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_IDM);
                regs->msr &= ~MSR_DE;
 #else
                regs->msr &= ~MSR_SE;
@@ -727,22 +735,76 @@ void user_disable_single_step(struct task_struct *task)
        clear_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
 
-static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
+int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
                               unsigned long data)
 {
-       /* We only support one DABR and no IABRS at the moment */
+       /* For ppc64 we support one DABR and no IABR's at the moment (ppc64).
+        *  For embedded processors we support one DAC and no IAC's at the
+        *  moment.
+        */
        if (addr > 0)
                return -EINVAL;
 
-       /* The bottom 3 bits are flags */
+       /* The bottom 3 bits in dabr are flags */
        if ((data & ~0x7UL) >= TASK_SIZE)
                return -EIO;
 
-       /* Ensure translation is on */
+#ifndef CONFIG_BOOKE
+
+       /* For processors using DABR (i.e. 970), the bottom 3 bits are flags.
+        *  It was assumed, on previous implementations, that 3 bits were
+        *  passed together with the data address, fitting the design of the
+        *  DABR register, as follows:
+        *
+        *  bit 0: Read flag
+        *  bit 1: Write flag
+        *  bit 2: Breakpoint translation
+        *
+        *  Thus, we use them here as so.
+        */
+
+       /* Ensure breakpoint translation bit is set */
        if (data && !(data & DABR_TRANSLATION))
                return -EIO;
 
+       /* Move contents to the DABR register */
        task->thread.dabr = data;
+
+#endif
+#if defined(CONFIG_BOOKE)
+
+       /* As described above, it was assumed 3 bits were passed with the data
+        *  address, but we will assume only the mode bits will be passed
+        *  as to not cause alignment restrictions for DAC-based processors.
+        */
+
+       /* DAC's hold the whole address without any mode flags */
+       task->thread.dabr = data & ~0x3UL;
+
+       if (task->thread.dabr == 0) {
+               task->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM);
+               task->thread.regs->msr &= ~MSR_DE;
+               return 0;
+       }
+
+       /* Read or Write bits must be set */
+
+       if (!(data & 0x3UL))
+               return -EINVAL;
+
+       /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0
+          register */
+       task->thread.dbcr0 = DBCR0_IDM;
+
+       /* Check for write and read flags and set DBCR0
+          accordingly */
+       if (data & 0x1UL)
+               task->thread.dbcr0 |= DBSR_DAC1R;
+       if (data & 0x2UL)
+               task->thread.dbcr0 |= DBSR_DAC1W;
+
+       task->thread.regs->msr |= MSR_DE;
+#endif
        return 0;
 }
 
@@ -953,31 +1015,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        return ret;
 }
 
-static void do_syscall_trace(void)
+/*
+ * We must return the syscall number to actually look up in the table.
+ * This can be -1L to skip running any syscall at all.
+ */
+long do_syscall_trace_enter(struct pt_regs *regs)
 {
-       /* the 0x80 provides a way for the tracing parent to distinguish
-          between a syscall stop and SIGTRAP delivery */
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                ? 0x80 : 0));
-
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
-       }
-}
+       long ret = 0;
 
-void do_syscall_trace_enter(struct pt_regs *regs)
-{
        secure_computing(regs->gpr[0]);
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE)
-           && (current->ptrace & PT_PTRACED))
-               do_syscall_trace();
+       if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+           tracehook_report_syscall_entry(regs))
+               /*
+                * Tracing decided this syscall should not happen.
+                * We'll return a bogus call number to get an ENOSYS
+                * error, but leave the original number in regs->gpr[0].
+                */
+               ret = -1L;
 
        if (unlikely(current->audit_context)) {
 #ifdef CONFIG_PPC64
@@ -995,16 +1050,19 @@ void do_syscall_trace_enter(struct pt_regs *regs)
                                            regs->gpr[5] & 0xffffffff,
                                            regs->gpr[6] & 0xffffffff);
        }
+
+       return ret ?: regs->gpr[0];
 }
 
 void do_syscall_trace_leave(struct pt_regs *regs)
 {
+       int step;
+
        if (unlikely(current->audit_context))
                audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
                                   regs->result);
 
-       if ((test_thread_flag(TIF_SYSCALL_TRACE)
-            || test_thread_flag(TIF_SINGLESTEP))
-           && (current->ptrace & PT_PTRACED))
-               do_syscall_trace();
+       step = test_thread_flag(TIF_SINGLESTEP);
+       if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall_exit(regs, step);
 }
index 09ded5c424a967cdaa0c1f5817bd7e301b971f60..149cb112cd1ad398357d33ae766e3add6c6cfc01 100644 (file)
@@ -286,7 +286,7 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf,
 }
 
 /* constructor for flash_block_cache */
-void rtas_block_ctor(struct kmem_cache *cache, void *ptr)
+void rtas_block_ctor(void *ptr)
 {
        memset(ptr, 0, RTAS_BLK_SIZE);
 }
index 61a3f4132087d88868c0240d0de2f0a74d378f18..9cc5a52711e5b585bf78ee2e3934e94405508707 100644 (file)
@@ -367,7 +367,6 @@ static void __init cpu_init_thread_core_maps(int tpc)
  * setup_cpu_maps - initialize the following cpu maps:
  *                  cpu_possible_map
  *                  cpu_present_map
- *                  cpu_sibling_map
  *
  * Having the possible map set up early allows us to restrict allocations
  * of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
@@ -475,29 +474,6 @@ void __init smp_setup_cpu_maps(void)
         */
        cpu_init_thread_core_maps(nthreads);
 }
-
-/*
- * Being that cpu_sibling_map is now a per_cpu array, then it cannot
- * be initialized until the per_cpu areas have been created.  This
- * function is now called from setup_per_cpu_areas().
- */
-void __init smp_setup_cpu_sibling_map(void)
-{
-#ifdef CONFIG_PPC64
-       int i, cpu, base;
-
-       for_each_possible_cpu(cpu) {
-               DBG("Sibling map for CPU %d:", cpu);
-               base = cpu_first_thread_in_core(cpu);
-               for (i = 0; i < threads_per_core; i++) {
-                       cpu_set(base + i, per_cpu(cpu_sibling_map, cpu));
-                       DBG(" %d", base + i);
-               }
-               DBG("\n");
-       }
-
-#endif /* CONFIG_PPC64 */
-}
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PCSPKR_PLATFORM
index 04d8de9f0fc6bc80a58cae801010e3489b8e142a..8b25f51f03bf9b8fc78da61015859a4ce9585fd0 100644 (file)
@@ -611,9 +611,6 @@ void __init setup_per_cpu_areas(void)
                paca[i].data_offset = ptr - __per_cpu_start;
                memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
        }
-
-       /* Now that per_cpu is setup, initialize cpu_sibling_map */
-       smp_setup_cpu_sibling_map();
 }
 #endif
 
index ad55488939c376f7073b0770ca79ad1f5954ca1e..a54405ebd7b0c35236cafedb3edee13bcfb67fb3 100644 (file)
@@ -9,7 +9,7 @@
  * this archive for more details.
  */
 
-#include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/signal.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -112,7 +112,7 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
        }
 }
 
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
+static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
 {
        siginfo_t info;
        int signr;
@@ -145,8 +145,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
         * user space. The DABR will have been cleared if it
         * triggered inside the kernel.
         */
-       if (current->thread.dabr)
+       if (current->thread.dabr) {
                set_dabr(current->thread.dabr);
+#if defined(CONFIG_BOOKE)
+               mtspr(SPRN_DBCR0, current->thread.dbcr0);
+#endif
+       }
 
        if (is32) {
                if (ka.sa.sa_flags & SA_SIGINFO)
@@ -173,11 +177,28 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
                 * its frame, and we can clear the TLF_RESTORE_SIGMASK flag.
                 */
                current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
+
+               /*
+                * Let tracing know that we've done the handler setup.
+                */
+               tracehook_signal_handler(signr, &info, &ka, regs,
+                                        test_thread_flag(TIF_SINGLESTEP));
        }
 
        return ret;
 }
 
+void do_signal(struct pt_regs *regs, unsigned long thread_info_flags)
+{
+       if (thread_info_flags & _TIF_SIGPENDING)
+               do_signal_pending(NULL, regs);
+
+       if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+               clear_thread_flag(TIF_NOTIFY_RESUME);
+               tracehook_notify_resume(regs);
+       }
+}
+
 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                unsigned long r5, unsigned long r6, unsigned long r7,
                unsigned long r8, struct pt_regs *regs)
index f5ae9fa222ea01e65a4847897e8b412f3653531e..5337ca7bb649b02999258143947751109fe6c585 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/smp.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
+#include <asm/cputhreads.h>
 #include <asm/cputable.h>
 #include <asm/system.h>
 #include <asm/mpic.h>
@@ -62,10 +63,12 @@ struct thread_info *secondary_ti;
 cpumask_t cpu_possible_map = CPU_MASK_NONE;
 cpumask_t cpu_online_map = CPU_MASK_NONE;
 DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
+DEFINE_PER_CPU(cpumask_t, cpu_core_map) = CPU_MASK_NONE;
 
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_possible_map);
 EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
+EXPORT_PER_CPU_SYMBOL(cpu_core_map);
 
 /* SMP operations for this machine */
 struct smp_ops_t *smp_ops;
@@ -228,6 +231,8 @@ void __devinit smp_prepare_boot_cpu(void)
        BUG_ON(smp_processor_id() != boot_cpuid);
 
        cpu_set(boot_cpuid, cpu_online_map);
+       cpu_set(boot_cpuid, per_cpu(cpu_sibling_map, boot_cpuid));
+       cpu_set(boot_cpuid, per_cpu(cpu_core_map, boot_cpuid));
 #ifdef CONFIG_PPC64
        paca[boot_cpuid].__current = current;
 #endif
@@ -375,11 +380,60 @@ int __cpuinit __cpu_up(unsigned int cpu)
        return 0;
 }
 
+/* Return the value of the reg property corresponding to the given
+ * logical cpu.
+ */
+int cpu_to_core_id(int cpu)
+{
+       struct device_node *np;
+       const int *reg;
+       int id = -1;
+
+       np = of_get_cpu_node(cpu, NULL);
+       if (!np)
+               goto out;
+
+       reg = of_get_property(np, "reg", NULL);
+       if (!reg)
+               goto out;
+
+       id = *reg;
+out:
+       of_node_put(np);
+       return id;
+}
+
+/* Must be called when no change can occur to cpu_present_map,
+ * i.e. during cpu online or offline.
+ */
+static struct device_node *cpu_to_l2cache(int cpu)
+{
+       struct device_node *np;
+       const phandle *php;
+       phandle ph;
+
+       if (!cpu_present(cpu))
+               return NULL;
+
+       np = of_get_cpu_node(cpu, NULL);
+       if (np == NULL)
+               return NULL;
+
+       php = of_get_property(np, "l2-cache", NULL);
+       if (php == NULL)
+               return NULL;
+       ph = *php;
+       of_node_put(np);
+
+       return of_find_node_by_phandle(ph);
+}
 
 /* Activate a secondary processor. */
 int __devinit start_secondary(void *unused)
 {
        unsigned int cpu = smp_processor_id();
+       struct device_node *l2_cache;
+       int i, base;
 
        atomic_inc(&init_mm.mm_count);
        current->active_mm = &init_mm;
@@ -400,6 +454,33 @@ int __devinit start_secondary(void *unused)
 
        ipi_call_lock();
        cpu_set(cpu, cpu_online_map);
+       /* Update sibling maps */
+       base = cpu_first_thread_in_core(cpu);
+       for (i = 0; i < threads_per_core; i++) {
+               if (cpu_is_offline(base + i))
+                       continue;
+               cpu_set(cpu, per_cpu(cpu_sibling_map, base + i));
+               cpu_set(base + i, per_cpu(cpu_sibling_map, cpu));
+
+               /* cpu_core_map should be a superset of
+                * cpu_sibling_map even if we don't have cache
+                * information, so update the former here, too.
+                */
+               cpu_set(cpu, per_cpu(cpu_core_map, base +i));
+               cpu_set(base + i, per_cpu(cpu_core_map, cpu));
+       }
+       l2_cache = cpu_to_l2cache(cpu);
+       for_each_online_cpu(i) {
+               struct device_node *np = cpu_to_l2cache(i);
+               if (!np)
+                       continue;
+               if (np == l2_cache) {
+                       cpu_set(cpu, per_cpu(cpu_core_map, i));
+                       cpu_set(i, per_cpu(cpu_core_map, cpu));
+               }
+               of_node_put(np);
+       }
+       of_node_put(l2_cache);
        ipi_call_unlock();
 
        local_irq_enable();
@@ -437,10 +518,42 @@ void __init smp_cpus_done(unsigned int max_cpus)
 #ifdef CONFIG_HOTPLUG_CPU
 int __cpu_disable(void)
 {
-       if (smp_ops->cpu_disable)
-               return smp_ops->cpu_disable();
+       struct device_node *l2_cache;
+       int cpu = smp_processor_id();
+       int base, i;
+       int err;
 
-       return -ENOSYS;
+       if (!smp_ops->cpu_disable)
+               return -ENOSYS;
+
+       err = smp_ops->cpu_disable();
+       if (err)
+               return err;
+
+       /* Update sibling maps */
+       base = cpu_first_thread_in_core(cpu);
+       for (i = 0; i < threads_per_core; i++) {
+               cpu_clear(cpu, per_cpu(cpu_sibling_map, base + i));
+               cpu_clear(base + i, per_cpu(cpu_sibling_map, cpu));
+               cpu_clear(cpu, per_cpu(cpu_core_map, base +i));
+               cpu_clear(base + i, per_cpu(cpu_core_map, cpu));
+       }
+
+       l2_cache = cpu_to_l2cache(cpu);
+       for_each_present_cpu(i) {
+               struct device_node *np = cpu_to_l2cache(i);
+               if (!np)
+                       continue;
+               if (np == l2_cache) {
+                       cpu_clear(cpu, per_cpu(cpu_core_map, i));
+                       cpu_clear(i, per_cpu(cpu_core_map, cpu));
+               }
+               of_node_put(np);
+       }
+       of_node_put(l2_cache);
+
+
+       return 0;
 }
 
 void __cpu_die(unsigned int cpu)
index f2589645870afe4d3aa009936c21f8d2e1fa7f22..b0dbb1daa4df1a6ea309b9b79f228834c888f9cc 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
-#include <linux/module.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 
index 8cee571075417fadd755e168ba4b0471bf58846f..6fc6328dc626c0809d1fe3e6f85814e26f4dce8c 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
  */
 
+#include <linux/mm.h>
 #include <asm/page.h>
 
 /* References to section boundaries */
index aba0ba95f0629cf320df4c006a38923d805f0aa8..56d172d16e5654b483e2ddaa087c9c6302e6e42d 100644 (file)
@@ -22,6 +22,8 @@
 
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
+static DEFINE_PER_CPU(struct kobject *, cache_toplevel);
+
 /* SMT stuff */
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
@@ -297,8 +299,289 @@ static struct sysdev_attribute pa6t_attrs[] = {
 #endif /* CONFIG_DEBUG_KERNEL */
 };
 
+struct cache_desc {
+       struct kobject kobj;
+       struct cache_desc *next;
+       const char *type;       /* Instruction, Data, or Unified */
+       u32 size;               /* total cache size in KB */
+       u32 line_size;          /* in bytes */
+       u32 nr_sets;            /* number of sets */
+       u32 level;              /* e.g. 1, 2, 3... */
+       u32 associativity;      /* e.g. 8-way... 0 is fully associative */
+};
+
+DEFINE_PER_CPU(struct cache_desc *, cache_desc);
+
+static struct cache_desc *kobj_to_cache_desc(struct kobject *k)
+{
+       return container_of(k, struct cache_desc, kobj);
+}
+
+static void cache_desc_release(struct kobject *k)
+{
+       struct cache_desc *desc = kobj_to_cache_desc(k);
+
+       pr_debug("%s: releasing %s\n", __func__, kobject_name(k));
+
+       if (desc->next)
+               kobject_put(&desc->next->kobj);
+
+       kfree(kobj_to_cache_desc(k));
+}
+
+static ssize_t cache_desc_show(struct kobject *k, struct attribute *attr, char *buf)
+{
+       struct kobj_attribute *kobj_attr;
+
+       kobj_attr = container_of(attr, struct kobj_attribute, attr);
+
+       return kobj_attr->show(k, kobj_attr, buf);
+}
+
+static struct sysfs_ops cache_desc_sysfs_ops = {
+       .show = cache_desc_show,
+};
+
+static struct kobj_type cache_desc_type = {
+       .release = cache_desc_release,
+       .sysfs_ops = &cache_desc_sysfs_ops,
+};
+
+static ssize_t cache_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+       struct cache_desc *cache = kobj_to_cache_desc(k);
+
+       return sprintf(buf, "%uK\n", cache->size);
+}
+
+static struct kobj_attribute cache_size_attr =
+       __ATTR(size, 0444, cache_size_show, NULL);
+
+static ssize_t cache_line_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+       struct cache_desc *cache = kobj_to_cache_desc(k);
+
+       return sprintf(buf, "%u\n", cache->line_size);
+}
+
+static struct kobj_attribute cache_line_size_attr =
+       __ATTR(coherency_line_size, 0444, cache_line_size_show, NULL);
+
+static ssize_t cache_nr_sets_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+       struct cache_desc *cache = kobj_to_cache_desc(k);
+
+       return sprintf(buf, "%u\n", cache->nr_sets);
+}
+
+static struct kobj_attribute cache_nr_sets_attr =
+       __ATTR(number_of_sets, 0444, cache_nr_sets_show, NULL);
+
+static ssize_t cache_type_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+       struct cache_desc *cache = kobj_to_cache_desc(k);
+
+       return sprintf(buf, "%s\n", cache->type);
+}
+
+static struct kobj_attribute cache_type_attr =
+       __ATTR(type, 0444, cache_type_show, NULL);
+
+static ssize_t cache_level_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+       struct cache_desc *cache = kobj_to_cache_desc(k);
+
+       return sprintf(buf, "%u\n", cache->level);
+}
+
+static struct kobj_attribute cache_level_attr =
+       __ATTR(level, 0444, cache_level_show, NULL);
+
+static ssize_t cache_assoc_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+       struct cache_desc *cache = kobj_to_cache_desc(k);
+
+       return sprintf(buf, "%u\n", cache->associativity);
+}
+
+static struct kobj_attribute cache_assoc_attr =
+       __ATTR(ways_of_associativity, 0444, cache_assoc_show, NULL);
+
+struct cache_desc_info {
+       const char *type;
+       const char *size_prop;
+       const char *line_size_prop;
+       const char *nr_sets_prop;
+};
+
+/* PowerPC Processor binding says the [di]-cache-* must be equal on
+ * unified caches, so just use d-cache properties. */
+static struct cache_desc_info ucache_info = {
+       .type = "Unified",
+       .size_prop = "d-cache-size",
+       .line_size_prop = "d-cache-line-size",
+       .nr_sets_prop = "d-cache-sets",
+};
 
-static void register_cpu_online(unsigned int cpu)
+static struct cache_desc_info dcache_info = {
+       .type = "Data",
+       .size_prop = "d-cache-size",
+       .line_size_prop = "d-cache-line-size",
+       .nr_sets_prop = "d-cache-sets",
+};
+
+static struct cache_desc_info icache_info = {
+       .type = "Instruction",
+       .size_prop = "i-cache-size",
+       .line_size_prop = "i-cache-line-size",
+       .nr_sets_prop = "i-cache-sets",
+};
+
+static struct cache_desc * __cpuinit create_cache_desc(struct device_node *np, struct kobject *parent, int index, int level, struct cache_desc_info *info)
+{
+       const u32 *cache_line_size;
+       struct cache_desc *new;
+       const u32 *cache_size;
+       const u32 *nr_sets;
+       int rc;
+
+       new = kzalloc(sizeof(*new), GFP_KERNEL);
+       if (!new)
+               return NULL;
+
+       rc = kobject_init_and_add(&new->kobj, &cache_desc_type, parent,
+                                 "index%d", index);
+       if (rc)
+               goto err;
+
+       /* type */
+       new->type = info->type;
+       rc = sysfs_create_file(&new->kobj, &cache_type_attr.attr);
+       WARN_ON(rc);
+
+       /* level */
+       new->level = level;
+       rc = sysfs_create_file(&new->kobj, &cache_level_attr.attr);
+       WARN_ON(rc);
+
+       /* size */
+       cache_size = of_get_property(np, info->size_prop, NULL);
+       if (cache_size) {
+               new->size = *cache_size / 1024;
+               rc = sysfs_create_file(&new->kobj,
+                                      &cache_size_attr.attr);
+               WARN_ON(rc);
+       }
+
+       /* coherency_line_size */
+       cache_line_size = of_get_property(np, info->line_size_prop, NULL);
+       if (cache_line_size) {
+               new->line_size = *cache_line_size;
+               rc = sysfs_create_file(&new->kobj,
+                                      &cache_line_size_attr.attr);
+               WARN_ON(rc);
+       }
+
+       /* number_of_sets */
+       nr_sets = of_get_property(np, info->nr_sets_prop, NULL);
+       if (nr_sets) {
+               new->nr_sets = *nr_sets;
+               rc = sysfs_create_file(&new->kobj,
+                                      &cache_nr_sets_attr.attr);
+               WARN_ON(rc);
+       }
+
+       /* ways_of_associativity */
+       if (new->nr_sets == 1) {
+               /* fully associative */
+               new->associativity = 0;
+               goto create_assoc;
+       }
+
+       if (new->nr_sets && new->size && new->line_size) {
+               /* If we have values for all of these we can derive
+                * the associativity. */
+               new->associativity =
+                       ((new->size * 1024) / new->nr_sets) / new->line_size;
+create_assoc:
+               rc = sysfs_create_file(&new->kobj,
+                                      &cache_assoc_attr.attr);
+               WARN_ON(rc);
+       }
+
+       return new;
+err:
+       kfree(new);
+       return NULL;
+}
+
+static bool cache_is_unified(struct device_node *np)
+{
+       return of_get_property(np, "cache-unified", NULL);
+}
+
+static struct cache_desc * __cpuinit create_cache_index_info(struct device_node *np, struct kobject *parent, int index, int level)
+{
+       const phandle *next_cache_phandle;
+       struct device_node *next_cache;
+       struct cache_desc *new, **end;
+
+       pr_debug("%s(node = %s, index = %d)\n", __func__, np->full_name, index);
+
+       if (cache_is_unified(np)) {
+               new = create_cache_desc(np, parent, index, level,
+                                       &ucache_info);
+       } else {
+               new = create_cache_desc(np, parent, index, level,
+                                       &dcache_info);
+               if (new) {
+                       index++;
+                       new->next = create_cache_desc(np, parent, index, level,
+                                                     &icache_info);
+               }
+       }
+       if (!new)
+               return NULL;
+
+       end = &new->next;
+       while (*end)
+               end = &(*end)->next;
+
+       next_cache_phandle = of_get_property(np, "l2-cache", NULL);
+       if (!next_cache_phandle)
+               goto out;
+
+       next_cache = of_find_node_by_phandle(*next_cache_phandle);
+       if (!next_cache)
+               goto out;
+
+       *end = create_cache_index_info(next_cache, parent, ++index, ++level);
+
+       of_node_put(next_cache);
+out:
+       return new;
+}
+
+static void __cpuinit create_cache_info(struct sys_device *sysdev)
+{
+       struct kobject *cache_toplevel;
+       struct device_node *np = NULL;
+       int cpu = sysdev->id;
+
+       cache_toplevel = kobject_create_and_add("cache", &sysdev->kobj);
+       if (!cache_toplevel)
+               return;
+       per_cpu(cache_toplevel, cpu) = cache_toplevel;
+       np = of_get_cpu_node(cpu, NULL);
+       if (np != NULL) {
+               per_cpu(cache_desc, cpu) =
+                       create_cache_index_info(np, cache_toplevel, 0, 1);
+               of_node_put(np);
+       }
+       return;
+}
+
+static void __cpuinit register_cpu_online(unsigned int cpu)
 {
        struct cpu *c = &per_cpu(cpu_devices, cpu);
        struct sys_device *s = &c->sysdev;
@@ -346,9 +629,33 @@ static void register_cpu_online(unsigned int cpu)
 
        if (cpu_has_feature(CPU_FTR_DSCR))
                sysdev_create_file(s, &attr_dscr);
+
+       create_cache_info(s);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
+static void remove_cache_info(struct sys_device *sysdev)
+{
+       struct kobject *cache_toplevel;
+       struct cache_desc *cache_desc;
+       int cpu = sysdev->id;
+
+       cache_desc = per_cpu(cache_desc, cpu);
+       if (cache_desc != NULL) {
+               sysfs_remove_file(&cache_desc->kobj, &cache_size_attr.attr);
+               sysfs_remove_file(&cache_desc->kobj, &cache_line_size_attr.attr);
+               sysfs_remove_file(&cache_desc->kobj, &cache_type_attr.attr);
+               sysfs_remove_file(&cache_desc->kobj, &cache_level_attr.attr);
+               sysfs_remove_file(&cache_desc->kobj, &cache_nr_sets_attr.attr);
+               sysfs_remove_file(&cache_desc->kobj, &cache_assoc_attr.attr);
+
+               kobject_put(&cache_desc->kobj);
+       }
+       cache_toplevel = per_cpu(cache_toplevel, cpu);
+       if (cache_toplevel != NULL)
+               kobject_put(cache_toplevel);
+}
+
 static void unregister_cpu_online(unsigned int cpu)
 {
        struct cpu *c = &per_cpu(cpu_devices, cpu);
@@ -399,6 +706,8 @@ static void unregister_cpu_online(unsigned int cpu)
 
        if (cpu_has_feature(CPU_FTR_DSCR))
                sysdev_remove_file(s, &attr_dscr);
+
+       remove_cache_info(s);
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
@@ -529,7 +838,8 @@ static void register_nodes(void)
 #endif
 
 /* Only valid if CPU is present. */
-static ssize_t show_physical_id(struct sys_device *dev, char *buf)
+static ssize_t show_physical_id(struct sys_device *dev,
+                               struct sysdev_attribute *attr, char *buf)
 {
        struct cpu *cpu = container_of(dev, struct cpu, sysdev);
 
index 878fbddb6ae10fe3150a329b4a214e07ff80f057..81ccb8dd1a54d8f95b0ed84f357d6e64e5395ab1 100644 (file)
@@ -1067,6 +1067,22 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
                }
 
                _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
+       } else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
+               regs->msr &= ~MSR_DE;
+
+               if (user_mode(regs)) {
+                       current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W |
+                                                               DBCR0_IDM);
+               } else {
+                       /* Disable DAC interupts */
+                       mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R |
+                                               DBSR_DAC1W | DBCR0_IDM));
+
+                       /* Clear the DAC event */
+                       mtspr(SPRN_DBSR, (DBSR_DAC1R | DBSR_DAC1W));
+               }
+               /* Setup and send the trap to the handler */
+               do_dabr(regs, mfspr(SPRN_DAC1), debug_status);
        }
 }
 #endif /* CONFIG_4xx || CONFIG_BOOKE */
index b77f8af7ddde7e5a4b2228065eddbae361fc05a5..22a3c33fd7513c5288cef156f931f62a1c4f41df 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * IBM PowerPC Virtual I/O Infrastructure Support.
  *
- *    Copyright (c) 2003-2005 IBM Corp.
+ *    Copyright (c) 2003,2008 IBM Corp.
  *     Dave Engebretsen engebret@us.ibm.com
  *     Santiago Leon santil@us.ibm.com
  *     Hollis Blanchard <hollisb@us.ibm.com>
  *     Stephen Rothwell
+ *     Robert Jennings <rcjenn@us.ibm.com>
  *
  *      This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -46,6 +47,996 @@ static struct vio_dev vio_bus_device  = { /* fake "parent" device */
        .dev.bus = &vio_bus_type,
 };
 
+#ifdef CONFIG_PPC_SMLPAR
+/**
+ * vio_cmo_pool - A pool of IO memory for CMO use
+ *
+ * @size: The size of the pool in bytes
+ * @free: The amount of free memory in the pool
+ */
+struct vio_cmo_pool {
+       size_t size;
+       size_t free;
+};
+
+/* How many ms to delay queued balance work */
+#define VIO_CMO_BALANCE_DELAY 100
+
+/* Portion out IO memory to CMO devices by this chunk size */
+#define VIO_CMO_BALANCE_CHUNK 131072
+
+/**
+ * vio_cmo_dev_entry - A device that is CMO-enabled and requires entitlement
+ *
+ * @vio_dev: struct vio_dev pointer
+ * @list: pointer to other devices on bus that are being tracked
+ */
+struct vio_cmo_dev_entry {
+       struct vio_dev *viodev;
+       struct list_head list;
+};
+
+/**
+ * vio_cmo - VIO bus accounting structure for CMO entitlement
+ *
+ * @lock: spinlock for entire structure
+ * @balance_q: work queue for balancing system entitlement
+ * @device_list: list of CMO-enabled devices requiring entitlement
+ * @entitled: total system entitlement in bytes
+ * @reserve: pool of memory from which devices reserve entitlement, incl. spare
+ * @excess: pool of excess entitlement not needed for device reserves or spare
+ * @spare: IO memory for device hotplug functionality
+ * @min: minimum necessary for system operation
+ * @desired: desired memory for system operation
+ * @curr: bytes currently allocated
+ * @high: high water mark for IO data usage
+ */
+struct vio_cmo {
+       spinlock_t lock;
+       struct delayed_work balance_q;
+       struct list_head device_list;
+       size_t entitled;
+       struct vio_cmo_pool reserve;
+       struct vio_cmo_pool excess;
+       size_t spare;
+       size_t min;
+       size_t desired;
+       size_t curr;
+       size_t high;
+} vio_cmo;
+
+/**
+ * vio_cmo_OF_devices - Count the number of OF devices that have DMA windows
+ */
+static int vio_cmo_num_OF_devs(void)
+{
+       struct device_node *node_vroot;
+       int count = 0;
+
+       /*
+        * Count the number of vdevice entries with an
+        * ibm,my-dma-window OF property
+        */
+       node_vroot = of_find_node_by_name(NULL, "vdevice");
+       if (node_vroot) {
+               struct device_node *of_node;
+               struct property *prop;
+
+               for_each_child_of_node(node_vroot, of_node) {
+                       prop = of_find_property(of_node, "ibm,my-dma-window",
+                                              NULL);
+                       if (prop)
+                               count++;
+               }
+       }
+       of_node_put(node_vroot);
+       return count;
+}
+
+/**
+ * vio_cmo_alloc - allocate IO memory for CMO-enable devices
+ *
+ * @viodev: VIO device requesting IO memory
+ * @size: size of allocation requested
+ *
+ * Allocations come from memory reserved for the devices and any excess
+ * IO memory available to all devices.  The spare pool used to service
+ * hotplug must be equal to %VIO_CMO_MIN_ENT for the excess pool to be
+ * made available.
+ *
+ * Return codes:
+ *  0 for successful allocation and -ENOMEM for a failure
+ */
+static inline int vio_cmo_alloc(struct vio_dev *viodev, size_t size)
+{
+       unsigned long flags;
+       size_t reserve_free = 0;
+       size_t excess_free = 0;
+       int ret = -ENOMEM;
+
+       spin_lock_irqsave(&vio_cmo.lock, flags);
+
+       /* Determine the amount of free entitlement available in reserve */
+       if (viodev->cmo.entitled > viodev->cmo.allocated)
+               reserve_free = viodev->cmo.entitled - viodev->cmo.allocated;
+
+       /* If spare is not fulfilled, the excess pool can not be used. */
+       if (vio_cmo.spare >= VIO_CMO_MIN_ENT)
+               excess_free = vio_cmo.excess.free;
+
+       /* The request can be satisfied */
+       if ((reserve_free + excess_free) >= size) {
+               vio_cmo.curr += size;
+               if (vio_cmo.curr > vio_cmo.high)
+                       vio_cmo.high = vio_cmo.curr;
+               viodev->cmo.allocated += size;
+               size -= min(reserve_free, size);
+               vio_cmo.excess.free -= size;
+               ret = 0;
+       }
+
+       spin_unlock_irqrestore(&vio_cmo.lock, flags);
+       return ret;
+}
+
+/**
+ * vio_cmo_dealloc - deallocate IO memory from CMO-enable devices
+ * @viodev: VIO device freeing IO memory
+ * @size: size of deallocation
+ *
+ * IO memory is freed by the device back to the correct memory pools.
+ * The spare pool is replenished first from either memory pool, then
+ * the reserve pool is used to reduce device entitlement, the excess
+ * pool is used to increase the reserve pool toward the desired entitlement
+ * target, and then the remaining memory is returned to the pools.
+ *
+ */
+static inline void vio_cmo_dealloc(struct vio_dev *viodev, size_t size)
+{
+       unsigned long flags;
+       size_t spare_needed = 0;
+       size_t excess_freed = 0;
+       size_t reserve_freed = size;
+       size_t tmp;
+       int balance = 0;
+
+       spin_lock_irqsave(&vio_cmo.lock, flags);
+       vio_cmo.curr -= size;
+
+       /* Amount of memory freed from the excess pool */
+       if (viodev->cmo.allocated > viodev->cmo.entitled) {
+               excess_freed = min(reserve_freed, (viodev->cmo.allocated -
+                                                  viodev->cmo.entitled));
+               reserve_freed -= excess_freed;
+       }
+
+       /* Remove allocation from device */
+       viodev->cmo.allocated -= (reserve_freed + excess_freed);
+
+       /* Spare is a subset of the reserve pool, replenish it first. */
+       spare_needed = VIO_CMO_MIN_ENT - vio_cmo.spare;
+
+       /*
+        * Replenish the spare in the reserve pool from the excess pool.
+        * This moves entitlement into the reserve pool.
+        */
+       if (spare_needed && excess_freed) {
+               tmp = min(excess_freed, spare_needed);
+               vio_cmo.excess.size -= tmp;
+               vio_cmo.reserve.size += tmp;
+               vio_cmo.spare += tmp;
+               excess_freed -= tmp;
+               spare_needed -= tmp;
+               balance = 1;
+       }
+
+       /*
+        * Replenish the spare in the reserve pool from the reserve pool.
+        * This removes entitlement from the device down to VIO_CMO_MIN_ENT,
+        * if needed, and gives it to the spare pool. The amount of used
+        * memory in this pool does not change.
+        */
+       if (spare_needed && reserve_freed) {
+               tmp = min(spare_needed, min(reserve_freed,
+                                           (viodev->cmo.entitled -
+                                            VIO_CMO_MIN_ENT)));
+
+               vio_cmo.spare += tmp;
+               viodev->cmo.entitled -= tmp;
+               reserve_freed -= tmp;
+               spare_needed -= tmp;
+               balance = 1;
+       }
+
+       /*
+        * Increase the reserve pool until the desired allocation is met.
+        * Move an allocation freed from the excess pool into the reserve
+        * pool and schedule a balance operation.
+        */
+       if (excess_freed && (vio_cmo.desired > vio_cmo.reserve.size)) {
+               tmp = min(excess_freed, (vio_cmo.desired - vio_cmo.reserve.size));
+
+               vio_cmo.excess.size -= tmp;
+               vio_cmo.reserve.size += tmp;
+               excess_freed -= tmp;
+               balance = 1;
+       }
+
+       /* Return memory from the excess pool to that pool */
+       if (excess_freed)
+               vio_cmo.excess.free += excess_freed;
+
+       if (balance)
+               schedule_delayed_work(&vio_cmo.balance_q, VIO_CMO_BALANCE_DELAY);
+       spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+/**
+ * vio_cmo_entitlement_update - Manage system entitlement changes
+ *
+ * @new_entitlement: new system entitlement to attempt to accommodate
+ *
+ * Increases in entitlement will be used to fulfill the spare entitlement
+ * and the rest is given to the excess pool.  Decreases, if they are
+ * possible, come from the excess pool and from unused device entitlement
+ *
+ * Returns: 0 on success, -ENOMEM when change can not be made
+ */
+int vio_cmo_entitlement_update(size_t new_entitlement)
+{
+       struct vio_dev *viodev;
+       struct vio_cmo_dev_entry *dev_ent;
+       unsigned long flags;
+       size_t avail, delta, tmp;
+
+       spin_lock_irqsave(&vio_cmo.lock, flags);
+
+       /* Entitlement increases */
+       if (new_entitlement > vio_cmo.entitled) {
+               delta = new_entitlement - vio_cmo.entitled;
+
+               /* Fulfill spare allocation */
+               if (vio_cmo.spare < VIO_CMO_MIN_ENT) {
+                       tmp = min(delta, (VIO_CMO_MIN_ENT - vio_cmo.spare));
+                       vio_cmo.spare += tmp;
+                       vio_cmo.reserve.size += tmp;
+                       delta -= tmp;
+               }
+
+               /* Remaining new allocation goes to the excess pool */
+               vio_cmo.entitled += delta;
+               vio_cmo.excess.size += delta;
+               vio_cmo.excess.free += delta;
+
+               goto out;
+       }
+
+       /* Entitlement decreases */
+       delta = vio_cmo.entitled - new_entitlement;
+       avail = vio_cmo.excess.free;
+
+       /*
+        * Need to check how much unused entitlement each device can
+        * sacrifice to fulfill entitlement change.
+        */
+       list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+               if (avail >= delta)
+                       break;
+
+               viodev = dev_ent->viodev;
+               if ((viodev->cmo.entitled > viodev->cmo.allocated) &&
+                   (viodev->cmo.entitled > VIO_CMO_MIN_ENT))
+                               avail += viodev->cmo.entitled -
+                                        max_t(size_t, viodev->cmo.allocated,
+                                              VIO_CMO_MIN_ENT);
+       }
+
+       if (delta <= avail) {
+               vio_cmo.entitled -= delta;
+
+               /* Take entitlement from the excess pool first */
+               tmp = min(vio_cmo.excess.free, delta);
+               vio_cmo.excess.size -= tmp;
+               vio_cmo.excess.free -= tmp;
+               delta -= tmp;
+
+               /*
+                * Remove all but VIO_CMO_MIN_ENT bytes from devices
+                * until entitlement change is served
+                */
+               list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+                       if (!delta)
+                               break;
+
+                       viodev = dev_ent->viodev;
+                       tmp = 0;
+                       if ((viodev->cmo.entitled > viodev->cmo.allocated) &&
+                           (viodev->cmo.entitled > VIO_CMO_MIN_ENT))
+                               tmp = viodev->cmo.entitled -
+                                     max_t(size_t, viodev->cmo.allocated,
+                                           VIO_CMO_MIN_ENT);
+                       viodev->cmo.entitled -= min(tmp, delta);
+                       delta -= min(tmp, delta);
+               }
+       } else {
+               spin_unlock_irqrestore(&vio_cmo.lock, flags);
+               return -ENOMEM;
+       }
+
+out:
+       schedule_delayed_work(&vio_cmo.balance_q, 0);
+       spin_unlock_irqrestore(&vio_cmo.lock, flags);
+       return 0;
+}
+
+/**
+ * vio_cmo_balance - Balance entitlement among devices
+ *
+ * @work: work queue structure for this operation
+ *
+ * Any system entitlement above the minimum needed for devices, or
+ * already allocated to devices, can be distributed to the devices.
+ * The list of devices is iterated through to recalculate the desired
+ * entitlement level and to determine how much entitlement above the
+ * minimum entitlement is allocated to devices.
+ *
+ * Small chunks of the available entitlement are given to devices until
+ * their requirements are fulfilled or there is no entitlement left to give.
+ * Upon completion sizes of the reserve and excess pools are calculated.
+ *
+ * The system minimum entitlement level is also recalculated here.
+ * Entitlement will be reserved for devices even after vio_bus_remove to
+ * accommodate reloading the driver.  The OF tree is walked to count the
+ * number of devices present and this will remove entitlement for devices
+ * that have actually left the system after having vio_bus_remove called.
+ */
+static void vio_cmo_balance(struct work_struct *work)
+{
+       struct vio_cmo *cmo;
+       struct vio_dev *viodev;
+       struct vio_cmo_dev_entry *dev_ent;
+       unsigned long flags;
+       size_t avail = 0, level, chunk, need;
+       int devcount = 0, fulfilled;
+
+       cmo = container_of(work, struct vio_cmo, balance_q.work);
+
+       spin_lock_irqsave(&vio_cmo.lock, flags);
+
+       /* Calculate minimum entitlement and fulfill spare */
+       cmo->min = vio_cmo_num_OF_devs() * VIO_CMO_MIN_ENT;
+       BUG_ON(cmo->min > cmo->entitled);
+       cmo->spare = min_t(size_t, VIO_CMO_MIN_ENT, (cmo->entitled - cmo->min));
+       cmo->min += cmo->spare;
+       cmo->desired = cmo->min;
+
+       /*
+        * Determine how much entitlement is available and reset device
+        * entitlements
+        */
+       avail = cmo->entitled - cmo->spare;
+       list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+               viodev = dev_ent->viodev;
+               devcount++;
+               viodev->cmo.entitled = VIO_CMO_MIN_ENT;
+               cmo->desired += (viodev->cmo.desired - VIO_CMO_MIN_ENT);
+               avail -= max_t(size_t, viodev->cmo.allocated, VIO_CMO_MIN_ENT);
+       }
+
+       /*
+        * Having provided each device with the minimum entitlement, loop
+        * over the devices portioning out the remaining entitlement
+        * until there is nothing left.
+        */
+       level = VIO_CMO_MIN_ENT;
+       while (avail) {
+               fulfilled = 0;
+               list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+                       viodev = dev_ent->viodev;
+
+                       if (viodev->cmo.desired <= level) {
+                               fulfilled++;
+                               continue;
+                       }
+
+                       /*
+                        * Give the device up to VIO_CMO_BALANCE_CHUNK
+                        * bytes of entitlement, but do not exceed the
+                        * desired level of entitlement for the device.
+                        */
+                       chunk = min_t(size_t, avail, VIO_CMO_BALANCE_CHUNK);
+                       chunk = min(chunk, (viodev->cmo.desired -
+                                           viodev->cmo.entitled));
+                       viodev->cmo.entitled += chunk;
+
+                       /*
+                        * If the memory for this entitlement increase was
+                        * already allocated to the device it does not come
+                        * from the available pool being portioned out.
+                        */
+                       need = max(viodev->cmo.allocated, viodev->cmo.entitled)-
+                              max(viodev->cmo.allocated, level);
+                       avail -= need;
+
+               }
+               if (fulfilled == devcount)
+                       break;
+               level += VIO_CMO_BALANCE_CHUNK;
+       }
+
+       /* Calculate new reserve and excess pool sizes */
+       cmo->reserve.size = cmo->min;
+       cmo->excess.free = 0;
+       cmo->excess.size = 0;
+       need = 0;
+       list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+               viodev = dev_ent->viodev;
+               /* Calculated reserve size above the minimum entitlement */
+               if (viodev->cmo.entitled)
+                       cmo->reserve.size += (viodev->cmo.entitled -
+                                             VIO_CMO_MIN_ENT);
+               /* Calculated used excess entitlement */
+               if (viodev->cmo.allocated > viodev->cmo.entitled)
+                       need += viodev->cmo.allocated - viodev->cmo.entitled;
+       }
+       cmo->excess.size = cmo->entitled - cmo->reserve.size;
+       cmo->excess.free = cmo->excess.size - need;
+
+       cancel_delayed_work(container_of(work, struct delayed_work, work));
+       spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
+                                          dma_addr_t *dma_handle, gfp_t flag)
+{
+       struct vio_dev *viodev = to_vio_dev(dev);
+       void *ret;
+
+       if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE))) {
+               atomic_inc(&viodev->cmo.allocs_failed);
+               return NULL;
+       }
+
+       ret = dma_iommu_ops.alloc_coherent(dev, size, dma_handle, flag);
+       if (unlikely(ret == NULL)) {
+               vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+               atomic_inc(&viodev->cmo.allocs_failed);
+       }
+
+       return ret;
+}
+
+static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
+                                        void *vaddr, dma_addr_t dma_handle)
+{
+       struct vio_dev *viodev = to_vio_dev(dev);
+
+       dma_iommu_ops.free_coherent(dev, size, vaddr, dma_handle);
+
+       vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+}
+
+static dma_addr_t vio_dma_iommu_map_single(struct device *dev, void *vaddr,
+                                           size_t size,
+                                           enum dma_data_direction direction,
+                                           struct dma_attrs *attrs)
+{
+       struct vio_dev *viodev = to_vio_dev(dev);
+       dma_addr_t ret = DMA_ERROR_CODE;
+
+       if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE))) {
+               atomic_inc(&viodev->cmo.allocs_failed);
+               return ret;
+       }
+
+       ret = dma_iommu_ops.map_single(dev, vaddr, size, direction, attrs);
+       if (unlikely(dma_mapping_error(dev, ret))) {
+               vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+               atomic_inc(&viodev->cmo.allocs_failed);
+       }
+
+       return ret;
+}
+
+static void vio_dma_iommu_unmap_single(struct device *dev,
+               dma_addr_t dma_handle, size_t size,
+               enum dma_data_direction direction,
+               struct dma_attrs *attrs)
+{
+       struct vio_dev *viodev = to_vio_dev(dev);
+
+       dma_iommu_ops.unmap_single(dev, dma_handle, size, direction, attrs);
+
+       vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+}
+
+static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
+                                int nelems, enum dma_data_direction direction,
+                                struct dma_attrs *attrs)
+{
+       struct vio_dev *viodev = to_vio_dev(dev);
+       struct scatterlist *sgl;
+       int ret, count = 0;
+       size_t alloc_size = 0;
+
+       for (sgl = sglist; count < nelems; count++, sgl++)
+               alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE);
+
+       if (vio_cmo_alloc(viodev, alloc_size)) {
+               atomic_inc(&viodev->cmo.allocs_failed);
+               return 0;
+       }
+
+       ret = dma_iommu_ops.map_sg(dev, sglist, nelems, direction, attrs);
+
+       if (unlikely(!ret)) {
+               vio_cmo_dealloc(viodev, alloc_size);
+               atomic_inc(&viodev->cmo.allocs_failed);
+       }
+
+       for (sgl = sglist, count = 0; count < ret; count++, sgl++)
+               alloc_size -= roundup(sgl->dma_length, IOMMU_PAGE_SIZE);
+       if (alloc_size)
+               vio_cmo_dealloc(viodev, alloc_size);
+
+       return ret;
+}
+
+static void vio_dma_iommu_unmap_sg(struct device *dev,
+               struct scatterlist *sglist, int nelems,
+               enum dma_data_direction direction,
+               struct dma_attrs *attrs)
+{
+       struct vio_dev *viodev = to_vio_dev(dev);
+       struct scatterlist *sgl;
+       size_t alloc_size = 0;
+       int count = 0;
+
+       for (sgl = sglist; count < nelems; count++, sgl++)
+               alloc_size += roundup(sgl->dma_length, IOMMU_PAGE_SIZE);
+
+       dma_iommu_ops.unmap_sg(dev, sglist, nelems, direction, attrs);
+
+       vio_cmo_dealloc(viodev, alloc_size);
+}
+
+struct dma_mapping_ops vio_dma_mapping_ops = {
+       .alloc_coherent = vio_dma_iommu_alloc_coherent,
+       .free_coherent  = vio_dma_iommu_free_coherent,
+       .map_single     = vio_dma_iommu_map_single,
+       .unmap_single   = vio_dma_iommu_unmap_single,
+       .map_sg         = vio_dma_iommu_map_sg,
+       .unmap_sg       = vio_dma_iommu_unmap_sg,
+};
+
+/**
+ * vio_cmo_set_dev_desired - Set desired entitlement for a device
+ *
+ * @viodev: struct vio_dev for device to alter
+ * @new_desired: new desired entitlement level in bytes
+ *
+ * For use by devices to request a change to their entitlement at runtime or
+ * through sysfs.  The desired entitlement level is changed and a balancing
+ * of system resources is scheduled to run in the future.
+ */
+void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired)
+{
+       unsigned long flags;
+       struct vio_cmo_dev_entry *dev_ent;
+       int found = 0;
+
+       if (!firmware_has_feature(FW_FEATURE_CMO))
+               return;
+
+       spin_lock_irqsave(&vio_cmo.lock, flags);
+       if (desired < VIO_CMO_MIN_ENT)
+               desired = VIO_CMO_MIN_ENT;
+
+       /*
+        * Changes will not be made for devices not in the device list.
+        * If it is not in the device list, then no driver is loaded
+        * for the device and it can not receive entitlement.
+        */
+       list_for_each_entry(dev_ent, &vio_cmo.device_list, list)
+               if (viodev == dev_ent->viodev) {
+                       found = 1;
+                       break;
+               }
+       if (!found)
+               return;
+
+       /* Increase/decrease in desired device entitlement */
+       if (desired >= viodev->cmo.desired) {
+               /* Just bump the bus and device values prior to a balance*/
+               vio_cmo.desired += desired - viodev->cmo.desired;
+               viodev->cmo.desired = desired;
+       } else {
+               /* Decrease bus and device values for desired entitlement */
+               vio_cmo.desired -= viodev->cmo.desired - desired;
+               viodev->cmo.desired = desired;
+               /*
+                * If less entitlement is desired than current entitlement, move
+                * any reserve memory in the change region to the excess pool.
+                */
+               if (viodev->cmo.entitled > desired) {
+                       vio_cmo.reserve.size -= viodev->cmo.entitled - desired;
+                       vio_cmo.excess.size += viodev->cmo.entitled - desired;
+                       /*
+                        * If entitlement moving from the reserve pool to the
+                        * excess pool is currently unused, add to the excess
+                        * free counter.
+                        */
+                       if (viodev->cmo.allocated < viodev->cmo.entitled)
+                               vio_cmo.excess.free += viodev->cmo.entitled -
+                                                      max(viodev->cmo.allocated, desired);
+                       viodev->cmo.entitled = desired;
+               }
+       }
+       schedule_delayed_work(&vio_cmo.balance_q, 0);
+       spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+/**
+ * vio_cmo_bus_probe - Handle CMO specific bus probe activities
+ *
+ * @viodev - Pointer to struct vio_dev for device
+ *
+ * Determine the devices IO memory entitlement needs, attempting
+ * to satisfy the system minimum entitlement at first and scheduling
+ * a balance operation to take care of the rest at a later time.
+ *
+ * Returns: 0 on success, -EINVAL when device doesn't support CMO, and
+ *          -ENOMEM when entitlement is not available for device or
+ *          device entry.
+ *
+ */
+static int vio_cmo_bus_probe(struct vio_dev *viodev)
+{
+       struct vio_cmo_dev_entry *dev_ent;
+       struct device *dev = &viodev->dev;
+       struct vio_driver *viodrv = to_vio_driver(dev->driver);
+       unsigned long flags;
+       size_t size;
+
+       /*
+        * Check to see that device has a DMA window and configure
+        * entitlement for the device.
+        */
+       if (of_get_property(viodev->dev.archdata.of_node,
+                           "ibm,my-dma-window", NULL)) {
+               /* Check that the driver is CMO enabled and get desired DMA */
+               if (!viodrv->get_desired_dma) {
+                       dev_err(dev, "%s: device driver does not support CMO\n",
+                               __func__);
+                       return -EINVAL;
+               }
+
+               viodev->cmo.desired = IOMMU_PAGE_ALIGN(viodrv->get_desired_dma(viodev));
+               if (viodev->cmo.desired < VIO_CMO_MIN_ENT)
+                       viodev->cmo.desired = VIO_CMO_MIN_ENT;
+               size = VIO_CMO_MIN_ENT;
+
+               dev_ent = kmalloc(sizeof(struct vio_cmo_dev_entry),
+                                 GFP_KERNEL);
+               if (!dev_ent)
+                       return -ENOMEM;
+
+               dev_ent->viodev = viodev;
+               spin_lock_irqsave(&vio_cmo.lock, flags);
+               list_add(&dev_ent->list, &vio_cmo.device_list);
+       } else {
+               viodev->cmo.desired = 0;
+               size = 0;
+               spin_lock_irqsave(&vio_cmo.lock, flags);
+       }
+
+       /*
+        * If the needs for vio_cmo.min have not changed since they
+        * were last set, the number of devices in the OF tree has
+        * been constant and the IO memory for this is already in
+        * the reserve pool.
+        */
+       if (vio_cmo.min == ((vio_cmo_num_OF_devs() + 1) *
+                           VIO_CMO_MIN_ENT)) {
+               /* Updated desired entitlement if device requires it */
+               if (size)
+                       vio_cmo.desired += (viodev->cmo.desired -
+                                       VIO_CMO_MIN_ENT);
+       } else {
+               size_t tmp;
+
+               tmp = vio_cmo.spare + vio_cmo.excess.free;
+               if (tmp < size) {
+                       dev_err(dev, "%s: insufficient free "
+                               "entitlement to add device. "
+                               "Need %lu, have %lu\n", __func__,
+                               size, (vio_cmo.spare + tmp));
+                       spin_unlock_irqrestore(&vio_cmo.lock, flags);
+                       return -ENOMEM;
+               }
+
+               /* Use excess pool first to fulfill request */
+               tmp = min(size, vio_cmo.excess.free);
+               vio_cmo.excess.free -= tmp;
+               vio_cmo.excess.size -= tmp;
+               vio_cmo.reserve.size += tmp;
+
+               /* Use spare if excess pool was insufficient */
+               vio_cmo.spare -= size - tmp;
+
+               /* Update bus accounting */
+               vio_cmo.min += size;
+               vio_cmo.desired += viodev->cmo.desired;
+       }
+       spin_unlock_irqrestore(&vio_cmo.lock, flags);
+       return 0;
+}
+
+/**
+ * vio_cmo_bus_remove - Handle CMO specific bus removal activities
+ *
+ * @viodev - Pointer to struct vio_dev for device
+ *
+ * Remove the device from the cmo device list.  The minimum entitlement
+ * will be reserved for the device as long as it is in the system.  The
+ * rest of the entitlement the device had been allocated will be returned
+ * to the system.
+ */
+static void vio_cmo_bus_remove(struct vio_dev *viodev)
+{
+       struct vio_cmo_dev_entry *dev_ent;
+       unsigned long flags;
+       size_t tmp;
+
+       spin_lock_irqsave(&vio_cmo.lock, flags);
+       if (viodev->cmo.allocated) {
+               dev_err(&viodev->dev, "%s: device had %lu bytes of IO "
+                       "allocated after remove operation.\n",
+                       __func__, viodev->cmo.allocated);
+               BUG();
+       }
+
+       /*
+        * Remove the device from the device list being maintained for
+        * CMO enabled devices.
+        */
+       list_for_each_entry(dev_ent, &vio_cmo.device_list, list)
+               if (viodev == dev_ent->viodev) {
+                       list_del(&dev_ent->list);
+                       kfree(dev_ent);
+                       break;
+               }
+
+       /*
+        * Devices may not require any entitlement and they do not need
+        * to be processed.  Otherwise, return the device's entitlement
+        * back to the pools.
+        */
+       if (viodev->cmo.entitled) {
+               /*
+                * This device has not yet left the OF tree, it's
+                * minimum entitlement remains in vio_cmo.min and
+                * vio_cmo.desired
+                */
+               vio_cmo.desired -= (viodev->cmo.desired - VIO_CMO_MIN_ENT);
+
+               /*
+                * Save min allocation for device in reserve as long
+                * as it exists in OF tree as determined by later
+                * balance operation
+                */
+               viodev->cmo.entitled -= VIO_CMO_MIN_ENT;
+
+               /* Replenish spare from freed reserve pool */
+               if (viodev->cmo.entitled && (vio_cmo.spare < VIO_CMO_MIN_ENT)) {
+                       tmp = min(viodev->cmo.entitled, (VIO_CMO_MIN_ENT -
+                                                        vio_cmo.spare));
+                       vio_cmo.spare += tmp;
+                       viodev->cmo.entitled -= tmp;
+               }
+
+               /* Remaining reserve goes to excess pool */
+               vio_cmo.excess.size += viodev->cmo.entitled;
+               vio_cmo.excess.free += viodev->cmo.entitled;
+               vio_cmo.reserve.size -= viodev->cmo.entitled;
+
+               /*
+                * Until the device is removed it will keep a
+                * minimum entitlement; this will guarantee that
+                * a module unload/load will result in a success.
+                */
+               viodev->cmo.entitled = VIO_CMO_MIN_ENT;
+               viodev->cmo.desired = VIO_CMO_MIN_ENT;
+               atomic_set(&viodev->cmo.allocs_failed, 0);
+       }
+
+       spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+static void vio_cmo_set_dma_ops(struct vio_dev *viodev)
+{
+       vio_dma_mapping_ops.dma_supported = dma_iommu_ops.dma_supported;
+       viodev->dev.archdata.dma_ops = &vio_dma_mapping_ops;
+}
+
+/**
+ * vio_cmo_bus_init - CMO entitlement initialization at bus init time
+ *
+ * Set up the reserve and excess entitlement pools based on available
+ * system entitlement and the number of devices in the OF tree that
+ * require entitlement in the reserve pool.
+ */
+static void vio_cmo_bus_init(void)
+{
+       struct hvcall_mpp_data mpp_data;
+       int err;
+
+       memset(&vio_cmo, 0, sizeof(struct vio_cmo));
+       spin_lock_init(&vio_cmo.lock);
+       INIT_LIST_HEAD(&vio_cmo.device_list);
+       INIT_DELAYED_WORK(&vio_cmo.balance_q, vio_cmo_balance);
+
+       /* Get current system entitlement */
+       err = h_get_mpp(&mpp_data);
+
+       /*
+        * On failure, continue with entitlement set to 0, will panic()
+        * later when spare is reserved.
+        */
+       if (err != H_SUCCESS) {
+               printk(KERN_ERR "%s: unable to determine system IO "\
+                      "entitlement. (%d)\n", __func__, err);
+               vio_cmo.entitled = 0;
+       } else {
+               vio_cmo.entitled = mpp_data.entitled_mem;
+       }
+
+       /* Set reservation and check against entitlement */
+       vio_cmo.spare = VIO_CMO_MIN_ENT;
+       vio_cmo.reserve.size = vio_cmo.spare;
+       vio_cmo.reserve.size += (vio_cmo_num_OF_devs() *
+                                VIO_CMO_MIN_ENT);
+       if (vio_cmo.reserve.size > vio_cmo.entitled) {
+               printk(KERN_ERR "%s: insufficient system entitlement\n",
+                      __func__);
+               panic("%s: Insufficient system entitlement", __func__);
+       }
+
+       /* Set the remaining accounting variables */
+       vio_cmo.excess.size = vio_cmo.entitled - vio_cmo.reserve.size;
+       vio_cmo.excess.free = vio_cmo.excess.size;
+       vio_cmo.min = vio_cmo.reserve.size;
+       vio_cmo.desired = vio_cmo.reserve.size;
+}
+
+/* sysfs device functions and data structures for CMO */
+
+#define viodev_cmo_rd_attr(name)                                        \
+static ssize_t viodev_cmo_##name##_show(struct device *dev,             \
+                                        struct device_attribute *attr,  \
+                                         char *buf)                     \
+{                                                                       \
+       return sprintf(buf, "%lu\n", to_vio_dev(dev)->cmo.name);        \
+}
+
+static ssize_t viodev_cmo_allocs_failed_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct vio_dev *viodev = to_vio_dev(dev);
+       return sprintf(buf, "%d\n", atomic_read(&viodev->cmo.allocs_failed));
+}
+
+static ssize_t viodev_cmo_allocs_failed_reset(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct vio_dev *viodev = to_vio_dev(dev);
+       atomic_set(&viodev->cmo.allocs_failed, 0);
+       return count;
+}
+
+static ssize_t viodev_cmo_desired_set(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct vio_dev *viodev = to_vio_dev(dev);
+       size_t new_desired;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &new_desired);
+       if (ret)
+               return ret;
+
+       vio_cmo_set_dev_desired(viodev, new_desired);
+       return count;
+}
+
+viodev_cmo_rd_attr(desired);
+viodev_cmo_rd_attr(entitled);
+viodev_cmo_rd_attr(allocated);
+
+static ssize_t name_show(struct device *, struct device_attribute *, char *);
+static ssize_t devspec_show(struct device *, struct device_attribute *, char *);
+static struct device_attribute vio_cmo_dev_attrs[] = {
+       __ATTR_RO(name),
+       __ATTR_RO(devspec),
+       __ATTR(cmo_desired,       S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
+              viodev_cmo_desired_show, viodev_cmo_desired_set),
+       __ATTR(cmo_entitled,      S_IRUGO, viodev_cmo_entitled_show,      NULL),
+       __ATTR(cmo_allocated,     S_IRUGO, viodev_cmo_allocated_show,     NULL),
+       __ATTR(cmo_allocs_failed, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
+              viodev_cmo_allocs_failed_show, viodev_cmo_allocs_failed_reset),
+       __ATTR_NULL
+};
+
+/* sysfs bus functions and data structures for CMO */
+
+#define viobus_cmo_rd_attr(name)                                        \
+static ssize_t                                                          \
+viobus_cmo_##name##_show(struct bus_type *bt, char *buf)                \
+{                                                                       \
+       return sprintf(buf, "%lu\n", vio_cmo.name);                     \
+}
+
+#define viobus_cmo_pool_rd_attr(name, var)                              \
+static ssize_t                                                          \
+viobus_cmo_##name##_pool_show_##var(struct bus_type *bt, char *buf)     \
+{                                                                       \
+       return sprintf(buf, "%lu\n", vio_cmo.name.var);                 \
+}
+
+static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf,
+                                     size_t count)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&vio_cmo.lock, flags);
+       vio_cmo.high = vio_cmo.curr;
+       spin_unlock_irqrestore(&vio_cmo.lock, flags);
+
+       return count;
+}
+
+viobus_cmo_rd_attr(entitled);
+viobus_cmo_pool_rd_attr(reserve, size);
+viobus_cmo_pool_rd_attr(excess, size);
+viobus_cmo_pool_rd_attr(excess, free);
+viobus_cmo_rd_attr(spare);
+viobus_cmo_rd_attr(min);
+viobus_cmo_rd_attr(desired);
+viobus_cmo_rd_attr(curr);
+viobus_cmo_rd_attr(high);
+
+static struct bus_attribute vio_cmo_bus_attrs[] = {
+       __ATTR(cmo_entitled, S_IRUGO, viobus_cmo_entitled_show, NULL),
+       __ATTR(cmo_reserve_size, S_IRUGO, viobus_cmo_reserve_pool_show_size, NULL),
+       __ATTR(cmo_excess_size, S_IRUGO, viobus_cmo_excess_pool_show_size, NULL),
+       __ATTR(cmo_excess_free, S_IRUGO, viobus_cmo_excess_pool_show_free, NULL),
+       __ATTR(cmo_spare,   S_IRUGO, viobus_cmo_spare_show,   NULL),
+       __ATTR(cmo_min,     S_IRUGO, viobus_cmo_min_show,     NULL),
+       __ATTR(cmo_desired, S_IRUGO, viobus_cmo_desired_show, NULL),
+       __ATTR(cmo_curr,    S_IRUGO, viobus_cmo_curr_show,    NULL),
+       __ATTR(cmo_high,    S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
+              viobus_cmo_high_show, viobus_cmo_high_reset),
+       __ATTR_NULL
+};
+
+static void vio_cmo_sysfs_init(void)
+{
+       vio_bus_type.dev_attrs = vio_cmo_dev_attrs;
+       vio_bus_type.bus_attrs = vio_cmo_bus_attrs;
+}
+#else /* CONFIG_PPC_SMLPAR */
+/* Dummy functions for iSeries platform */
+int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; }
+void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired) {}
+static int vio_cmo_bus_probe(struct vio_dev *viodev) { return 0; }
+static void vio_cmo_bus_remove(struct vio_dev *viodev) {}
+static void vio_cmo_set_dma_ops(struct vio_dev *viodev) {}
+static void vio_cmo_bus_init(void) {}
+static void vio_cmo_sysfs_init(void) { }
+#endif /* CONFIG_PPC_SMLPAR */
+EXPORT_SYMBOL(vio_cmo_entitlement_update);
+EXPORT_SYMBOL(vio_cmo_set_dev_desired);
+
 static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
 {
        const unsigned char *dma_window;
@@ -114,8 +1105,17 @@ static int vio_bus_probe(struct device *dev)
                return error;
 
        id = vio_match_device(viodrv->id_table, viodev);
-       if (id)
+       if (id) {
+               memset(&viodev->cmo, 0, sizeof(viodev->cmo));
+               if (firmware_has_feature(FW_FEATURE_CMO)) {
+                       error = vio_cmo_bus_probe(viodev);
+                       if (error)
+                               return error;
+               }
                error = viodrv->probe(viodev, id);
+               if (error)
+                       vio_cmo_bus_remove(viodev);
+       }
 
        return error;
 }
@@ -125,12 +1125,23 @@ static int vio_bus_remove(struct device *dev)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
        struct vio_driver *viodrv = to_vio_driver(dev->driver);
+       struct device *devptr;
+       int ret = 1;
+
+       /*
+        * Hold a reference to the device after the remove function is called
+        * to allow for CMO accounting cleanup for the device.
+        */
+       devptr = get_device(dev);
 
        if (viodrv->remove)
-               return viodrv->remove(viodev);
+               ret = viodrv->remove(viodev);
+
+       if (!ret && firmware_has_feature(FW_FEATURE_CMO))
+               vio_cmo_bus_remove(viodev);
 
-       /* driver can't remove */
-       return 1;
+       put_device(devptr);
+       return ret;
 }
 
 /**
@@ -215,7 +1226,11 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
                        viodev->unit_address = *unit_address;
        }
        viodev->dev.archdata.of_node = of_node_get(of_node);
-       viodev->dev.archdata.dma_ops = &dma_iommu_ops;
+
+       if (firmware_has_feature(FW_FEATURE_CMO))
+               vio_cmo_set_dma_ops(viodev);
+       else
+               viodev->dev.archdata.dma_ops = &dma_iommu_ops;
        viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev);
        viodev->dev.archdata.numa_node = of_node_to_nid(of_node);
 
@@ -245,6 +1260,9 @@ static int __init vio_bus_init(void)
        int err;
        struct device_node *node_vroot;
 
+       if (firmware_has_feature(FW_FEATURE_CMO))
+               vio_cmo_sysfs_init();
+
        err = bus_register(&vio_bus_type);
        if (err) {
                printk(KERN_ERR "failed to register VIO bus\n");
@@ -262,6 +1280,9 @@ static int __init vio_bus_init(void)
                return err;
        }
 
+       if (firmware_has_feature(FW_FEATURE_CMO))
+               vio_cmo_bus_init();
+
        node_vroot = of_find_node_by_name(NULL, "vdevice");
        if (node_vroot) {
                struct device_node *of_node;
index a914411bced5defb4179628c9b0049d68a360ab0..4a8ce62fe1121c1a774f04a9af6223a96f945c23 100644 (file)
@@ -85,7 +85,7 @@ SECTIONS
 
        /* The dummy segment contents for the bug workaround mentioned above
           near PHDRS.  */
-       .dummy : {
+       .dummy : AT(ADDR(.dummy) - LOAD_OFFSET) {
                LONG(0xf177)
        } :kernel :dummy
 
index 75dff7cfa814130a465098ea880c1f05cbf882e5..5a5602da50910d441f806c6b0a111fcd3e19aab3 100644 (file)
@@ -177,7 +177,8 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
                                                    vcpu->arch.msr & MSR_PR);
 }
 
-void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid)
+void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
+                           gva_t eend, u32 asid)
 {
        unsigned int pid = asid & 0xff;
        int i;
@@ -191,7 +192,7 @@ void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid)
                if (!get_tlb_v(stlbe))
                        continue;
 
-               if (eaddr < get_tlb_eaddr(stlbe))
+               if (eend < get_tlb_eaddr(stlbe))
                        continue;
 
                if (eaddr > get_tlb_end(stlbe))
index 0000974612834121aa9c6a4048e0e89e09695374..8c605d0a5488fdce0268cbbdf3055d9404028f7b 100644 (file)
@@ -137,7 +137,7 @@ static int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u32 inst)
        if (tlbe->word0 & PPC44x_TLB_VALID) {
                eaddr = get_tlb_eaddr(tlbe);
                asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
-               kvmppc_mmu_invalidate(vcpu, eaddr, asid);
+               kvmppc_mmu_invalidate(vcpu, eaddr, get_tlb_end(tlbe), asid);
        }
 
        switch (ws) {
index 0559fe086eb4a020d2b2434def7e4ab9f4ae8395..7c975d43e3f388d50152bbdcb42a72adfcb50a13 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
+#include <linux/mm.h>
 #include <asm/page.h>
 #include <asm/code-patching.h>
 
index 1707d00331fc931dde7e7865def1422ff8e8c1e9..565b7a237c847929e885eb5597fe4cdb14746cf3 100644 (file)
@@ -100,31 +100,6 @@ static int store_updates_sp(struct pt_regs *regs)
        return 0;
 }
 
-#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
-static void do_dabr(struct pt_regs *regs, unsigned long address,
-                   unsigned long error_code)
-{
-       siginfo_t info;
-
-       if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
-                       11, SIGSEGV) == NOTIFY_STOP)
-               return;
-
-       if (debugger_dabr_match(regs))
-               return;
-
-       /* Clear the DABR */
-       set_dabr(0);
-
-       /* Deliver the signal to userspace */
-       info.si_signo = SIGTRAP;
-       info.si_errno = 0;
-       info.si_code = TRAP_HWBKPT;
-       info.si_addr = (void __user *)address;
-       force_sig_info(SIGTRAP, &info, current);
-}
-#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
-
 /*
  * For 600- and 800-family processors, the error_code parameter is DSISR
  * for a data fault, SRR1 for an instruction fault. For 400-family processors
index 8d3b58ebd38e62d737f2f10aa773406d7c0c6473..5ce5a4dcd00823c17447737f18ad5ad03c820185 100644 (file)
@@ -68,6 +68,7 @@
 
 #define KB (1024)
 #define MB (1024*KB)
+#define GB (1024L*MB)
 
 /*
  * Note:  pte   --> Linux PTE
@@ -102,7 +103,6 @@ int mmu_kernel_ssize = MMU_SEGSIZE_256M;
 int mmu_highuser_ssize = MMU_SEGSIZE_256M;
 u16 mmu_slb_size = 64;
 #ifdef CONFIG_HUGETLB_PAGE
-int mmu_huge_psize = MMU_PAGE_16M;
 unsigned int HPAGE_SHIFT;
 #endif
 #ifdef CONFIG_PPC_64K_PAGES
@@ -329,6 +329,44 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
        return 0;
 }
 
+/* Scan for 16G memory blocks that have been set aside for huge pages
+ * and reserve those blocks for 16G huge pages.
+ */
+static int __init htab_dt_scan_hugepage_blocks(unsigned long node,
+                                       const char *uname, int depth,
+                                       void *data) {
+       char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+       unsigned long *addr_prop;
+       u32 *page_count_prop;
+       unsigned int expected_pages;
+       long unsigned int phys_addr;
+       long unsigned int block_size;
+
+       /* We are scanning "memory" nodes only */
+       if (type == NULL || strcmp(type, "memory") != 0)
+               return 0;
+
+       /* This property is the log base 2 of the number of virtual pages that
+        * will represent this memory block. */
+       page_count_prop = of_get_flat_dt_prop(node, "ibm,expected#pages", NULL);
+       if (page_count_prop == NULL)
+               return 0;
+       expected_pages = (1 << page_count_prop[0]);
+       addr_prop = of_get_flat_dt_prop(node, "reg", NULL);
+       if (addr_prop == NULL)
+               return 0;
+       phys_addr = addr_prop[0];
+       block_size = addr_prop[1];
+       if (block_size != (16 * GB))
+               return 0;
+       printk(KERN_INFO "Huge page(16GB) memory: "
+                       "addr = 0x%lX size = 0x%lX pages = %d\n",
+                       phys_addr, block_size, expected_pages);
+       lmb_reserve(phys_addr, block_size * expected_pages);
+       add_gpage(phys_addr, block_size, expected_pages);
+       return 0;
+}
+
 static void __init htab_init_page_sizes(void)
 {
        int rc;
@@ -418,15 +456,18 @@ static void __init htab_init_page_sizes(void)
               );
 
 #ifdef CONFIG_HUGETLB_PAGE
-       /* Init large page size. Currently, we pick 16M or 1M depending
+       /* Reserve 16G huge page memory sections for huge pages */
+       of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL);
+
+/* Set default large page size. Currently, we pick 16M or 1M depending
         * on what is available
         */
        if (mmu_psize_defs[MMU_PAGE_16M].shift)
-               set_huge_psize(MMU_PAGE_16M);
+               HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_16M].shift;
        /* With 4k/4level pagetables, we can't (for now) cope with a
         * huge page size < PMD_SIZE */
        else if (mmu_psize_defs[MMU_PAGE_1M].shift)
-               set_huge_psize(MMU_PAGE_1M);
+               HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M].shift;
 #endif /* CONFIG_HUGETLB_PAGE */
 }
 
@@ -847,7 +888,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 
 #ifdef CONFIG_HUGETLB_PAGE
        /* Handle hugepage regions */
-       if (HPAGE_SHIFT && psize == mmu_huge_psize) {
+       if (HPAGE_SHIFT && mmu_huge_psizes[psize]) {
                DBG_LOW(" -> huge page !\n");
                return hash_huge_page(mm, access, ea, vsid, local, trap);
        }
index 0d12fba31bc596d13ceaf58ea8d04c23663082ac..f1c2d55b4377c1a09af0e860316e80d56f6557e2 100644 (file)
 #include <asm/cputable.h>
 #include <asm/spu.h>
 
-#define HPAGE_SHIFT_64K        16
-#define HPAGE_SHIFT_16M        24
+#define PAGE_SHIFT_64K 16
+#define PAGE_SHIFT_16M 24
+#define PAGE_SHIFT_16G 34
 
 #define NUM_LOW_AREAS  (0x100000000UL >> SID_SHIFT)
 #define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
+#define MAX_NUMBER_GPAGES      1024
 
-unsigned int hugepte_shift;
-#define PTRS_PER_HUGEPTE       (1 << hugepte_shift)
-#define HUGEPTE_TABLE_SIZE     (sizeof(pte_t) << hugepte_shift)
+/* Tracks the 16G pages after the device tree is scanned and before the
+ * huge_boot_pages list is ready.  */
+static unsigned long gpage_freearray[MAX_NUMBER_GPAGES];
+static unsigned nr_gpages;
 
-#define HUGEPD_SHIFT           (HPAGE_SHIFT + hugepte_shift)
-#define HUGEPD_SIZE            (1UL << HUGEPD_SHIFT)
-#define HUGEPD_MASK            (~(HUGEPD_SIZE-1))
+/* Array of valid huge page sizes - non-zero value(hugepte_shift) is
+ * stored for the huge page sizes that are valid.
+ */
+unsigned int mmu_huge_psizes[MMU_PAGE_COUNT] = { }; /* initialize all to 0 */
+
+#define hugepte_shift                  mmu_huge_psizes
+#define PTRS_PER_HUGEPTE(psize)                (1 << hugepte_shift[psize])
+#define HUGEPTE_TABLE_SIZE(psize)      (sizeof(pte_t) << hugepte_shift[psize])
+
+#define HUGEPD_SHIFT(psize)            (mmu_psize_to_shift(psize) \
+                                               + hugepte_shift[psize])
+#define HUGEPD_SIZE(psize)             (1UL << HUGEPD_SHIFT(psize))
+#define HUGEPD_MASK(psize)             (~(HUGEPD_SIZE(psize)-1))
+
+/* Subtract one from array size because we don't need a cache for 4K since
+ * is not a huge page size */
+#define huge_pgtable_cache(psize)      (pgtable_cache[HUGEPTE_CACHE_NUM \
+                                                       + psize-1])
+#define HUGEPTE_CACHE_NAME(psize)      (huge_pgtable_cache_name[psize])
 
-#define huge_pgtable_cache     (pgtable_cache[HUGEPTE_CACHE_NUM])
+static const char *huge_pgtable_cache_name[MMU_PAGE_COUNT] = {
+       "unused_4K", "hugepte_cache_64K", "unused_64K_AP",
+       "hugepte_cache_1M", "hugepte_cache_16M", "hugepte_cache_16G"
+};
 
 /* Flag to mark huge PD pointers.  This means pmd_bad() and pud_bad()
  * will choke on pointers to hugepte tables, which is handy for
@@ -49,24 +71,49 @@ typedef struct { unsigned long pd; } hugepd_t;
 
 #define hugepd_none(hpd)       ((hpd).pd == 0)
 
+static inline int shift_to_mmu_psize(unsigned int shift)
+{
+       switch (shift) {
+#ifndef CONFIG_PPC_64K_PAGES
+       case PAGE_SHIFT_64K:
+           return MMU_PAGE_64K;
+#endif
+       case PAGE_SHIFT_16M:
+           return MMU_PAGE_16M;
+       case PAGE_SHIFT_16G:
+           return MMU_PAGE_16G;
+       }
+       return -1;
+}
+
+static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
+{
+       if (mmu_psize_defs[mmu_psize].shift)
+               return mmu_psize_defs[mmu_psize].shift;
+       BUG();
+}
+
 static inline pte_t *hugepd_page(hugepd_t hpd)
 {
        BUG_ON(!(hpd.pd & HUGEPD_OK));
        return (pte_t *)(hpd.pd & ~HUGEPD_OK);
 }
 
-static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr)
+static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
+                                   struct hstate *hstate)
 {
-       unsigned long idx = ((addr >> HPAGE_SHIFT) & (PTRS_PER_HUGEPTE-1));
+       unsigned int shift = huge_page_shift(hstate);
+       int psize = shift_to_mmu_psize(shift);
+       unsigned long idx = ((addr >> shift) & (PTRS_PER_HUGEPTE(psize)-1));
        pte_t *dir = hugepd_page(*hpdp);
 
        return dir + idx;
 }
 
 static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
-                          unsigned long address)
+                          unsigned long address, unsigned int psize)
 {
-       pte_t *new = kmem_cache_alloc(huge_pgtable_cache,
+       pte_t *new = kmem_cache_zalloc(huge_pgtable_cache(psize),
                                      GFP_KERNEL|__GFP_REPEAT);
 
        if (! new)
@@ -74,7 +121,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
 
        spin_lock(&mm->page_table_lock);
        if (!hugepd_none(*hpdp))
-               kmem_cache_free(huge_pgtable_cache, new);
+               kmem_cache_free(huge_pgtable_cache(psize), new);
        else
                hpdp->pd = (unsigned long)new | HUGEPD_OK;
        spin_unlock(&mm->page_table_lock);
@@ -83,27 +130,60 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
 
 /* Base page size affects how we walk hugetlb page tables */
 #ifdef CONFIG_PPC_64K_PAGES
-#define hpmd_offset(pud, addr)         pmd_offset(pud, addr)
-#define hpmd_alloc(mm, pud, addr)      pmd_alloc(mm, pud, addr)
+#define hpmd_offset(pud, addr, h)      pmd_offset(pud, addr)
+#define hpmd_alloc(mm, pud, addr, h)   pmd_alloc(mm, pud, addr)
 #else
 static inline
-pmd_t *hpmd_offset(pud_t *pud, unsigned long addr)
+pmd_t *hpmd_offset(pud_t *pud, unsigned long addr, struct hstate *hstate)
 {
-       if (HPAGE_SHIFT == HPAGE_SHIFT_64K)
+       if (huge_page_shift(hstate) == PAGE_SHIFT_64K)
                return pmd_offset(pud, addr);
        else
                return (pmd_t *) pud;
 }
 static inline
-pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr)
+pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
+                 struct hstate *hstate)
 {
-       if (HPAGE_SHIFT == HPAGE_SHIFT_64K)
+       if (huge_page_shift(hstate) == PAGE_SHIFT_64K)
                return pmd_alloc(mm, pud, addr);
        else
                return (pmd_t *) pud;
 }
 #endif
 
+/* Build list of addresses of gigantic pages.  This function is used in early
+ * boot before the buddy or bootmem allocator is setup.
+ */
+void add_gpage(unsigned long addr, unsigned long page_size,
+       unsigned long number_of_pages)
+{
+       if (!addr)
+               return;
+       while (number_of_pages > 0) {
+               gpage_freearray[nr_gpages] = addr;
+               nr_gpages++;
+               number_of_pages--;
+               addr += page_size;
+       }
+}
+
+/* Moves the gigantic page addresses from the temporary list to the
+ * huge_boot_pages list.
+ */
+int alloc_bootmem_huge_page(struct hstate *hstate)
+{
+       struct huge_bootmem_page *m;
+       if (nr_gpages == 0)
+               return 0;
+       m = phys_to_virt(gpage_freearray[--nr_gpages]);
+       gpage_freearray[nr_gpages] = 0;
+       list_add(&m->list, &huge_boot_pages);
+       m->hstate = hstate;
+       return 1;
+}
+
+
 /* Modelled after find_linux_pte() */
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
@@ -111,39 +191,52 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
        pud_t *pu;
        pmd_t *pm;
 
-       BUG_ON(get_slice_psize(mm, addr) != mmu_huge_psize);
+       unsigned int psize;
+       unsigned int shift;
+       unsigned long sz;
+       struct hstate *hstate;
+       psize = get_slice_psize(mm, addr);
+       shift = mmu_psize_to_shift(psize);
+       sz = ((1UL) << shift);
+       hstate = size_to_hstate(sz);
 
-       addr &= HPAGE_MASK;
+       addr &= hstate->mask;
 
        pg = pgd_offset(mm, addr);
        if (!pgd_none(*pg)) {
                pu = pud_offset(pg, addr);
                if (!pud_none(*pu)) {
-                       pm = hpmd_offset(pu, addr);
+                       pm = hpmd_offset(pu, addr, hstate);
                        if (!pmd_none(*pm))
-                               return hugepte_offset((hugepd_t *)pm, addr);
+                               return hugepte_offset((hugepd_t *)pm, addr,
+                                                     hstate);
                }
        }
 
        return NULL;
 }
 
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+                       unsigned long addr, unsigned long sz)
 {
        pgd_t *pg;
        pud_t *pu;
        pmd_t *pm;
        hugepd_t *hpdp = NULL;
+       struct hstate *hstate;
+       unsigned int psize;
+       hstate = size_to_hstate(sz);
 
-       BUG_ON(get_slice_psize(mm, addr) != mmu_huge_psize);
+       psize = get_slice_psize(mm, addr);
+       BUG_ON(!mmu_huge_psizes[psize]);
 
-       addr &= HPAGE_MASK;
+       addr &= hstate->mask;
 
        pg = pgd_offset(mm, addr);
        pu = pud_alloc(mm, pg, addr);
 
        if (pu) {
-               pm = hpmd_alloc(mm, pu, addr);
+               pm = hpmd_alloc(mm, pu, addr, hstate);
                if (pm)
                        hpdp = (hugepd_t *)pm;
        }
@@ -151,10 +244,10 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        if (! hpdp)
                return NULL;
 
-       if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr))
+       if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, psize))
                return NULL;
 
-       return hugepte_offset(hpdp, addr);
+       return hugepte_offset(hpdp, addr, hstate);
 }
 
 int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
@@ -162,19 +255,22 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
        return 0;
 }
 
-static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp)
+static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp,
+                              unsigned int psize)
 {
        pte_t *hugepte = hugepd_page(*hpdp);
 
        hpdp->pd = 0;
        tlb->need_flush = 1;
-       pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, HUGEPTE_CACHE_NUM,
+       pgtable_free_tlb(tlb, pgtable_free_cache(hugepte,
+                                                HUGEPTE_CACHE_NUM+psize-1,
                                                 PGF_CACHENUM_MASK));
 }
 
 static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
                                   unsigned long addr, unsigned long end,
-                                  unsigned long floor, unsigned long ceiling)
+                                  unsigned long floor, unsigned long ceiling,
+                                  unsigned int psize)
 {
        pmd_t *pmd;
        unsigned long next;
@@ -186,7 +282,7 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
                next = pmd_addr_end(addr, end);
                if (pmd_none(*pmd))
                        continue;
-               free_hugepte_range(tlb, (hugepd_t *)pmd);
+               free_hugepte_range(tlb, (hugepd_t *)pmd, psize);
        } while (pmd++, addr = next, addr != end);
 
        start &= PUD_MASK;
@@ -212,6 +308,9 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
        pud_t *pud;
        unsigned long next;
        unsigned long start;
+       unsigned int shift;
+       unsigned int psize = get_slice_psize(tlb->mm, addr);
+       shift = mmu_psize_to_shift(psize);
 
        start = addr;
        pud = pud_offset(pgd, addr);
@@ -220,16 +319,18 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
 #ifdef CONFIG_PPC_64K_PAGES
                if (pud_none_or_clear_bad(pud))
                        continue;
-               hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling);
+               hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling,
+                                      psize);
 #else
-               if (HPAGE_SHIFT == HPAGE_SHIFT_64K) {
+               if (shift == PAGE_SHIFT_64K) {
                        if (pud_none_or_clear_bad(pud))
                                continue;
-                       hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling);
+                       hugetlb_free_pmd_range(tlb, pud, addr, next, floor,
+                                              ceiling, psize);
                } else {
                        if (pud_none(*pud))
                                continue;
-                       free_hugepte_range(tlb, (hugepd_t *)pud);
+                       free_hugepte_range(tlb, (hugepd_t *)pud, psize);
                }
 #endif
        } while (pud++, addr = next, addr != end);
@@ -255,7 +356,7 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
  *
  * Must be called with pagetable lock held.
  */
-void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+void hugetlb_free_pgd_range(struct mmu_gather *tlb,
                            unsigned long addr, unsigned long end,
                            unsigned long floor, unsigned long ceiling)
 {
@@ -297,31 +398,33 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb,
         * now has no other vmas using it, so can be freed, we don't
         * bother to round floor or end up - the tests don't need that.
         */
+       unsigned int psize = get_slice_psize(tlb->mm, addr);
 
-       addr &= HUGEPD_MASK;
+       addr &= HUGEPD_MASK(psize);
        if (addr < floor) {
-               addr += HUGEPD_SIZE;
+               addr += HUGEPD_SIZE(psize);
                if (!addr)
                        return;
        }
        if (ceiling) {
-               ceiling &= HUGEPD_MASK;
+               ceiling &= HUGEPD_MASK(psize);
                if (!ceiling)
                        return;
        }
        if (end - 1 > ceiling - 1)
-               end -= HUGEPD_SIZE;
+               end -= HUGEPD_SIZE(psize);
        if (addr > end - 1)
                return;
 
        start = addr;
-       pgd = pgd_offset((*tlb)->mm, addr);
+       pgd = pgd_offset(tlb->mm, addr);
        do {
-               BUG_ON(get_slice_psize((*tlb)->mm, addr) != mmu_huge_psize);
+               psize = get_slice_psize(tlb->mm, addr);
+               BUG_ON(!mmu_huge_psizes[psize]);
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
                        continue;
-               hugetlb_free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
+               hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
        } while (pgd++, addr = next, addr != end);
 }
 
@@ -334,7 +437,11 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
                 * necessary anymore if we make hpte_need_flush() get the
                 * page size from the slices
                 */
-               pte_update(mm, addr & HPAGE_MASK, ptep, ~0UL, 1);
+               unsigned int psize = get_slice_psize(mm, addr);
+               unsigned int shift = mmu_psize_to_shift(psize);
+               unsigned long sz = ((1UL) << shift);
+               struct hstate *hstate = size_to_hstate(sz);
+               pte_update(mm, addr & hstate->mask, ptep, ~0UL, 1);
        }
        *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
 }
@@ -351,14 +458,19 @@ follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
 {
        pte_t *ptep;
        struct page *page;
+       unsigned int mmu_psize = get_slice_psize(mm, address);
 
-       if (get_slice_psize(mm, address) != mmu_huge_psize)
+       /* Verify it is a huge page else bail. */
+       if (!mmu_huge_psizes[mmu_psize])
                return ERR_PTR(-EINVAL);
 
        ptep = huge_pte_offset(mm, address);
        page = pte_page(*ptep);
-       if (page)
-               page += (address % HPAGE_SIZE) / PAGE_SIZE;
+       if (page) {
+               unsigned int shift = mmu_psize_to_shift(mmu_psize);
+               unsigned long sz = ((1UL) << shift);
+               page += (address % sz) / PAGE_SIZE;
+       }
 
        return page;
 }
@@ -368,6 +480,11 @@ int pmd_huge(pmd_t pmd)
        return 0;
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *
 follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                pmd_t *pmd, int write)
@@ -381,15 +498,16 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                                        unsigned long len, unsigned long pgoff,
                                        unsigned long flags)
 {
-       return slice_get_unmapped_area(addr, len, flags,
-                                      mmu_huge_psize, 1, 0);
+       struct hstate *hstate = hstate_file(file);
+       int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
+       return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
 }
 
 /*
  * Called by asm hashtable.S for doing lazy icache flush
  */
 static unsigned int hash_huge_page_do_lazy_icache(unsigned long rflags,
-                                                 pte_t pte, int trap)
+                                       pte_t pte, int trap, unsigned long sz)
 {
        struct page *page;
        int i;
@@ -402,7 +520,7 @@ static unsigned int hash_huge_page_do_lazy_icache(unsigned long rflags,
        /* page is dirty */
        if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) {
                if (trap == 0x400) {
-                       for (i = 0; i < (HPAGE_SIZE / PAGE_SIZE); i++)
+                       for (i = 0; i < (sz / PAGE_SIZE); i++)
                                __flush_dcache_icache(page_address(page+i));
                        set_bit(PG_arch_1, &page->flags);
                } else {
@@ -418,11 +536,16 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
 {
        pte_t *ptep;
        unsigned long old_pte, new_pte;
-       unsigned long va, rflags, pa;
+       unsigned long va, rflags, pa, sz;
        long slot;
        int err = 1;
        int ssize = user_segment_size(ea);
+       unsigned int mmu_psize;
+       int shift;
+       mmu_psize = get_slice_psize(mm, ea);
 
+       if (!mmu_huge_psizes[mmu_psize])
+               goto out;
        ptep = huge_pte_offset(mm, ea);
 
        /* Search the Linux page table for a match with va */
@@ -465,30 +588,32 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
        rflags = 0x2 | (!(new_pte & _PAGE_RW));
        /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */
        rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N);
+       shift = mmu_psize_to_shift(mmu_psize);
+       sz = ((1UL) << shift);
        if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
                /* No CPU has hugepages but lacks no execute, so we
                 * don't need to worry about that case */
                rflags = hash_huge_page_do_lazy_icache(rflags, __pte(old_pte),
-                                                      trap);
+                                                      trap, sz);
 
        /* Check if pte already has an hpte (case 2) */
        if (unlikely(old_pte & _PAGE_HASHPTE)) {
                /* There MIGHT be an HPTE for this pte */
                unsigned long hash, slot;
 
-               hash = hpt_hash(va, HPAGE_SHIFT, ssize);
+               hash = hpt_hash(va, shift, ssize);
                if (old_pte & _PAGE_F_SECOND)
                        hash = ~hash;
                slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                slot += (old_pte & _PAGE_F_GIX) >> 12;
 
-               if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_huge_psize,
+               if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_psize,
                                         ssize, local) == -1)
                        old_pte &= ~_PAGE_HPTEFLAGS;
        }
 
        if (likely(!(old_pte & _PAGE_HASHPTE))) {
-               unsigned long hash = hpt_hash(va, HPAGE_SHIFT, ssize);
+               unsigned long hash = hpt_hash(va, shift, ssize);
                unsigned long hpte_group;
 
                pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
@@ -509,7 +634,7 @@ repeat:
 
                /* Insert into the hash table, primary slot */
                slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0,
-                                         mmu_huge_psize, ssize);
+                                         mmu_psize, ssize);
 
                /* Primary is full, try the secondary */
                if (unlikely(slot == -1)) {
@@ -517,7 +642,7 @@ repeat:
                                      HPTES_PER_GROUP) & ~0x7UL; 
                        slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags,
                                                  HPTE_V_SECONDARY,
-                                                 mmu_huge_psize, ssize);
+                                                 mmu_psize, ssize);
                        if (slot == -1) {
                                if (mftb() & 0x1)
                                        hpte_group = ((hash & htab_hash_mask) *
@@ -549,45 +674,54 @@ void set_huge_psize(int psize)
 {
        /* Check that it is a page size supported by the hardware and
         * that it fits within pagetable limits. */
-       if (mmu_psize_defs[psize].shift && mmu_psize_defs[psize].shift < SID_SHIFT &&
+       if (mmu_psize_defs[psize].shift &&
+               mmu_psize_defs[psize].shift < SID_SHIFT_1T &&
                (mmu_psize_defs[psize].shift > MIN_HUGEPTE_SHIFT ||
-                       mmu_psize_defs[psize].shift == HPAGE_SHIFT_64K)) {
-               HPAGE_SHIFT = mmu_psize_defs[psize].shift;
-               mmu_huge_psize = psize;
-#ifdef CONFIG_PPC_64K_PAGES
-               hugepte_shift = (PMD_SHIFT-HPAGE_SHIFT);
-#else
-               if (HPAGE_SHIFT == HPAGE_SHIFT_64K)
-                       hugepte_shift = (PMD_SHIFT-HPAGE_SHIFT);
-               else
-                       hugepte_shift = (PUD_SHIFT-HPAGE_SHIFT);
-#endif
-
+                mmu_psize_defs[psize].shift == PAGE_SHIFT_64K ||
+                mmu_psize_defs[psize].shift == PAGE_SHIFT_16G)) {
+               /* Return if huge page size has already been setup or is the
+                * same as the base page size. */
+               if (mmu_huge_psizes[psize] ||
+                  mmu_psize_defs[psize].shift == PAGE_SHIFT)
+                       return;
+               hugetlb_add_hstate(mmu_psize_defs[psize].shift - PAGE_SHIFT);
+
+               switch (mmu_psize_defs[psize].shift) {
+               case PAGE_SHIFT_64K:
+                   /* We only allow 64k hpages with 4k base page,
+                    * which was checked above, and always put them
+                    * at the PMD */
+                   hugepte_shift[psize] = PMD_SHIFT;
+                   break;
+               case PAGE_SHIFT_16M:
+                   /* 16M pages can be at two different levels
+                    * of pagestables based on base page size */
+                   if (PAGE_SHIFT == PAGE_SHIFT_64K)
+                           hugepte_shift[psize] = PMD_SHIFT;
+                   else /* 4k base page */
+                           hugepte_shift[psize] = PUD_SHIFT;
+                   break;
+               case PAGE_SHIFT_16G:
+                   /* 16G pages are always at PGD level */
+                   hugepte_shift[psize] = PGDIR_SHIFT;
+                   break;
+               }
+               hugepte_shift[psize] -= mmu_psize_defs[psize].shift;
        } else
-               HPAGE_SHIFT = 0;
+               hugepte_shift[psize] = 0;
 }
 
 static int __init hugepage_setup_sz(char *str)
 {
        unsigned long long size;
-       int mmu_psize = -1;
+       int mmu_psize;
        int shift;
 
        size = memparse(str, &str);
 
        shift = __ffs(size);
-       switch (shift) {
-#ifndef CONFIG_PPC_64K_PAGES
-       case HPAGE_SHIFT_64K:
-               mmu_psize = MMU_PAGE_64K;
-               break;
-#endif
-       case HPAGE_SHIFT_16M:
-               mmu_psize = MMU_PAGE_16M;
-               break;
-       }
-
-       if (mmu_psize >=0 && mmu_psize_defs[mmu_psize].shift)
+       mmu_psize = shift_to_mmu_psize(shift);
+       if (mmu_psize >= 0 && mmu_psize_defs[mmu_psize].shift)
                set_huge_psize(mmu_psize);
        else
                printk(KERN_WARNING "Invalid huge page size specified(%llu)\n", size);
@@ -596,23 +730,40 @@ static int __init hugepage_setup_sz(char *str)
 }
 __setup("hugepagesz=", hugepage_setup_sz);
 
-static void zero_ctor(struct kmem_cache *cache, void *addr)
-{
-       memset(addr, 0, kmem_cache_size(cache));
-}
-
 static int __init hugetlbpage_init(void)
 {
+       unsigned int psize;
+
        if (!cpu_has_feature(CPU_FTR_16M_PAGE))
                return -ENODEV;
 
-       huge_pgtable_cache = kmem_cache_create("hugepte_cache",
-                                              HUGEPTE_TABLE_SIZE,
-                                              HUGEPTE_TABLE_SIZE,
-                                              0,
-                                              zero_ctor);
-       if (! huge_pgtable_cache)
-               panic("hugetlbpage_init(): could not create hugepte cache\n");
+       /* Add supported huge page sizes.  Need to change HUGE_MAX_HSTATE
+        * and adjust PTE_NONCACHE_NUM if the number of supported huge page
+        * sizes changes.
+        */
+       set_huge_psize(MMU_PAGE_16M);
+       set_huge_psize(MMU_PAGE_16G);
+
+       /* Temporarily disable support for 64K huge pages when 64K SPU local
+        * store support is enabled as the current implementation conflicts.
+        */
+#ifndef CONFIG_SPU_FS_64K_LS
+       set_huge_psize(MMU_PAGE_64K);
+#endif
+
+       for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+               if (mmu_huge_psizes[psize]) {
+                       huge_pgtable_cache(psize) = kmem_cache_create(
+                                               HUGEPTE_CACHE_NAME(psize),
+                                               HUGEPTE_TABLE_SIZE(psize),
+                                               HUGEPTE_TABLE_SIZE(psize),
+                                               0,
+                                               NULL);
+                       if (!huge_pgtable_cache(psize))
+                               panic("hugetlbpage_init(): could not create %s"\
+                                     "\n", HUGEPTE_CACHE_NAME(psize));
+               }
+       }
 
        return 0;
 }
index 6ef63caca6822bdfaa29b8884c8b06873acd33a7..4f7df85129d837202df55df241aaa9223a3a9d72 100644 (file)
@@ -136,9 +136,14 @@ static int __init setup_kcore(void)
 module_init(setup_kcore);
 #endif
 
-static void zero_ctor(struct kmem_cache *cache, void *addr)
+static void pgd_ctor(void *addr)
 {
-       memset(addr, 0, kmem_cache_size(cache));
+       memset(addr, 0, PGD_TABLE_SIZE);
+}
+
+static void pmd_ctor(void *addr)
+{
+       memset(addr, 0, PMD_TABLE_SIZE);
 }
 
 static const unsigned int pgtable_cache_size[2] = {
@@ -153,29 +158,18 @@ static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
 };
 
 #ifdef CONFIG_HUGETLB_PAGE
-/* Hugepages need one extra cache, initialized in hugetlbpage.c.  We
- * can't put into the tables above, because HPAGE_SHIFT is not compile
- * time constant. */
-struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1];
+/* Hugepages need an extra cache per hugepagesize, initialized in
+ * hugetlbpage.c.  We can't put into the tables above, because HPAGE_SHIFT
+ * is not compile time constant. */
+struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+MMU_PAGE_COUNT];
 #else
 struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
 #endif
 
 void pgtable_cache_init(void)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) {
-               int size = pgtable_cache_size[i];
-               const char *name = pgtable_cache_name[i];
-
-               pr_debug("Allocating page table cache %s (#%d) "
-                       "for size: %08x...\n", name, i, size);
-               pgtable_cache[i] = kmem_cache_create(name,
-                                                    size, size,
-                                                    SLAB_PANIC,
-                                                    zero_ctor);
-       }
+       pgtable_cache[0] = kmem_cache_create(pgtable_cache_name[0], PGD_TABLE_SIZE, PGD_TABLE_SIZE, SLAB_PANIC, pgd_ctor);
+       pgtable_cache[1] = kmem_cache_create(pgtable_cache_name[1], PMD_TABLE_SIZE, PMD_TABLE_SIZE, SLAB_PANIC, pmd_ctor);
 }
 
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
index 1ca2235f0965339e3d7ec3d2c4f1c0d40c225a25..702691cb9e82361bd5de91cc8c0445411aea6c37 100644 (file)
@@ -186,45 +186,6 @@ walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg,
 }
 EXPORT_SYMBOL_GPL(walk_memory_resource);
 
-void show_mem(void)
-{
-       unsigned long total = 0, reserved = 0;
-       unsigned long shared = 0, cached = 0;
-       unsigned long highmem = 0;
-       struct page *page;
-       pg_data_t *pgdat;
-       unsigned long i;
-
-       printk("Mem-info:\n");
-       show_free_areas();
-       for_each_online_pgdat(pgdat) {
-               unsigned long flags;
-               pgdat_resize_lock(pgdat, &flags);
-               for (i = 0; i < pgdat->node_spanned_pages; i++) {
-                       if (!pfn_valid(pgdat->node_start_pfn + i))
-                               continue;
-                       page = pgdat_page_nr(pgdat, i);
-                       total++;
-                       if (PageHighMem(page))
-                               highmem++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
-               }
-               pgdat_resize_unlock(pgdat, &flags);
-       }
-       printk("%ld pages of RAM\n", total);
-#ifdef CONFIG_HIGHMEM
-       printk("%ld pages of HIGHMEM\n", highmem);
-#endif
-       printk("%ld reserved pages\n", reserved);
-       printk("%ld pages shared\n", shared);
-       printk("%ld pages swap cached\n", cached);
-}
-
 /*
  * Initialize the bootmem system and give it all the memory we
  * have available.  If we are using highmem, we only put the
index cf4bffba6f7cb3357feec5f47698cd0a8882a117..d9a1813513322889af782dd71625f46db3bab1c4 100644 (file)
@@ -39,7 +39,6 @@ EXPORT_SYMBOL(numa_cpu_lookup_table);
 EXPORT_SYMBOL(numa_cpumask_lookup_table);
 EXPORT_SYMBOL(node_data);
 
-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;
 
@@ -816,7 +815,7 @@ void __init do_init_bootmem(void)
                dbg("node %d\n", nid);
                dbg("NODE_DATA() = %p\n", NODE_DATA(nid));
 
-               NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+               NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
                NODE_DATA(nid)->node_start_pfn = start_pfn;
                NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
 
index c7584072dfcc0768cf2de86d53ee48fa5d734043..2001abdb1912bec23dfa6635010359edddf4423b 100644 (file)
@@ -145,13 +145,20 @@ void pte_free(struct mm_struct *mm, pgtable_t ptepage)
 void __iomem *
 ioremap(phys_addr_t addr, unsigned long size)
 {
-       return __ioremap(addr, size, _PAGE_NO_CACHE);
+       return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
 }
 EXPORT_SYMBOL(ioremap);
 
 void __iomem *
 ioremap_flags(phys_addr_t addr, unsigned long size, unsigned long flags)
 {
+       /* writeable implies dirty for kernel addresses */
+       if (flags & _PAGE_RW)
+               flags |= _PAGE_DIRTY | _PAGE_HWWRITE;
+
+       /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
+       flags &= ~(_PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC);
+
        return __ioremap(addr, size, flags);
 }
 EXPORT_SYMBOL(ioremap_flags);
@@ -163,6 +170,14 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
        phys_addr_t p;
        int err;
 
+       /* Make sure we have the base flags */
+       if ((flags & _PAGE_PRESENT) == 0)
+               flags |= _PAGE_KERNEL;
+
+       /* Non-cacheable page cannot be coherent */
+       if (flags & _PAGE_NO_CACHE)
+               flags &= ~_PAGE_COHERENT;
+
        /*
         * Choose an address to map it to.
         * Once the vmalloc system is running, we use it.
@@ -219,11 +234,6 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
                v = (ioremap_bot -= size);
        }
 
-       if ((flags & _PAGE_PRESENT) == 0)
-               flags |= _PAGE_KERNEL;
-       if (flags & _PAGE_NO_CACHE)
-               flags |= _PAGE_GUARDED;
-
        /*
         * Should check if it is a candidate for a BAT mapping
         */
index 3ef0ad2f9ca0a6f1e1edb15effa10b3c7a558ec6..365e61ae5dbcf54f7f4789d2cfed5bb7072201e3 100644 (file)
@@ -107,9 +107,18 @@ void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
 {
        unsigned long i;
 
+       /* Make sure we have the base flags */
        if ((flags & _PAGE_PRESENT) == 0)
                flags |= pgprot_val(PAGE_KERNEL);
 
+       /* Non-cacheable page cannot be coherent */
+       if (flags & _PAGE_NO_CACHE)
+               flags &= ~_PAGE_COHERENT;
+
+       /* We don't support the 4K PFN hack with ioremap */
+       if (flags & _PAGE_4K_PFN)
+               return NULL;
+
        WARN_ON(pa & ~PAGE_MASK);
        WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
        WARN_ON(size & ~PAGE_MASK);
@@ -190,6 +199,13 @@ void __iomem * ioremap(phys_addr_t addr, unsigned long size)
 void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size,
                             unsigned long flags)
 {
+       /* writeable implies dirty for kernel addresses */
+       if (flags & _PAGE_RW)
+               flags |= _PAGE_DIRTY;
+
+       /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
+       flags &= ~(_PAGE_USER | _PAGE_EXEC);
+
        if (ppc_md.ioremap)
                return ppc_md.ioremap(addr, size, flags);
        return __ioremap(addr, size, flags);
index a01b5c608ff9333d5424efa12b57035608948473..409fcc7b63ce410872a2e6a58ca1f95f41bdf9e2 100644 (file)
@@ -147,7 +147,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
         */
        if (huge) {
 #ifdef CONFIG_HUGETLB_PAGE
-               psize = mmu_huge_psize;
+               psize = get_slice_psize(mm, addr);;
 #else
                BUG();
                psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */
index d664b1bce381afcc30b2988f4beb1d28e1508df0..696a5ee4962d20c81737b5a36db3ece5a13041bd 100644 (file)
@@ -1,7 +1,6 @@
 config PPC_MPC52xx
        bool "52xx-based boards"
        depends on PPC_MULTIPLATFORM && PPC32
-       select FSL_SOC
        select PPC_CLOCK
        select PPC_PCI_CHOICE
 
@@ -48,6 +47,7 @@ config PPC_MPC5200_BUGFIX
 config PPC_MPC5200_GPIO
        bool "MPC5200 GPIO support"
        depends on PPC_MPC52xx
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
+       select GENERIC_GPIO
        help
          Enable gpiolib support for mpc5200 based boards
index 0e04f8fb152a55a9e5ad0aa9c97bd164738392ea..3e7e0f1568ef50d705de43fa889ce8722c2fd352 100644 (file)
@@ -281,7 +281,7 @@ static int __init scc_pciex_iowa_init(struct iowa_bus *bus, void *data)
 
        dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va,
                                       PAGE_SIZE, DMA_FROM_DEVICE);
-       if (dma_mapping_error(dummy_page_da)) {
+       if (dma_mapping_error(bus->phb->parent, dummy_page_da)) {
                pr_err("PCIEX:Map dummy page failed.\n");
                kfree(dummy_page_va);
                return -1;
index 208005ca262c62ac58b466c94e21ff3f47932924..e06420af5fe9116cd007645594ee6cd0a962a6ea 100644 (file)
@@ -172,7 +172,7 @@ static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte,
        }
 }
 
-static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
+static int tce_build_cell(struct iommu_table *tbl, long index, long npages,
                unsigned long uaddr, enum dma_data_direction direction,
                struct dma_attrs *attrs)
 {
@@ -213,6 +213,7 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
 
        pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n",
                 index, npages, direction, base_pte);
+       return 0;
 }
 
 static void tce_free_cell(struct iommu_table *tbl, long index, long npages)
@@ -1150,12 +1151,23 @@ static int iommu_fixed_disabled;
 
 static int __init setup_iommu_fixed(char *str)
 {
+       struct device_node *pciep;
+
        if (strcmp(str, "off") == 0)
                iommu_fixed_disabled = 1;
 
-       else if (strcmp(str, "weak") == 0)
+       /* If we can find a pcie-endpoint in the device tree assume that
+        * we're on a triblade or a CAB so by default the fixed mapping
+        * should be set to be weakly ordered; but only if the boot
+        * option WASN'T set for strong ordering
+        */
+       pciep = of_find_node_by_type(NULL, "pcie-endpoint");
+
+       if (strcmp(str, "weak") == 0 || (pciep && strcmp(str, "strong") != 0))
                iommu_fixed_is_weak = 1;
 
+       of_node_put(pciep);
+
        return 1;
 }
 __setup("iommu_fixed=", setup_iommu_fixed);
index 418b605ac35aefff35224aaabccc1d086473ac44..5122ec145271e0e65608718a0233138144a77561 100644 (file)
@@ -111,7 +111,7 @@ static int __init spiderpci_pci_setup_chip(struct pci_controller *phb,
 
        dummy_page_da = dma_map_single(phb->parent, dummy_page_va,
                                       PAGE_SIZE, DMA_FROM_DEVICE);
-       if (dma_mapping_error(dummy_page_da)) {
+       if (dma_mapping_error(phb->parent, dummy_page_da)) {
                pr_err("SPIDER-IOWA:Map dummy page filed.\n");
                kfree(dummy_page_va);
                return -1;
index 99c73066b82f860cefc09f496d682be15b012aa0..010a51f59796b7a9068103bb6598843f9195fff4 100644 (file)
@@ -288,9 +288,32 @@ spufs_mem_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        return VM_FAULT_NOPAGE;
 }
 
+static int spufs_mem_mmap_access(struct vm_area_struct *vma,
+                               unsigned long address,
+                               void *buf, int len, int write)
+{
+       struct spu_context *ctx = vma->vm_file->private_data;
+       unsigned long offset = address - vma->vm_start;
+       char *local_store;
+
+       if (write && !(vma->vm_flags & VM_WRITE))
+               return -EACCES;
+       if (spu_acquire(ctx))
+               return -EINTR;
+       if ((offset + len) > vma->vm_end)
+               len = vma->vm_end - offset;
+       local_store = ctx->ops->get_ls(ctx);
+       if (write)
+               memcpy_toio(local_store + offset, buf, len);
+       else
+               memcpy_fromio(buf, local_store + offset, len);
+       spu_release(ctx);
+       return len;
+}
 
 static struct vm_operations_struct spufs_mem_mmap_vmops = {
        .fault = spufs_mem_mmap_fault,
+       .access = spufs_mem_mmap_access,
 };
 
 static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
index 7123472801d922067ba5e801808245b4eef10b15..690ca7b0dcf68e5f96562efef97b092b4a5433c6 100644 (file)
@@ -78,7 +78,7 @@ spufs_destroy_inode(struct inode *inode)
 }
 
 static void
-spufs_init_once(struct kmem_cache *cachep, void *p)
+spufs_init_once(void *p)
 {
        struct spufs_inode_info *ei = p;
 
index 34654743363dccf871534441f36bbcf2149459ef..2deeeba7eccfc9c555d5d32aca370507f08268be 100644 (file)
@@ -312,10 +312,27 @@ static struct spu *aff_ref_location(struct spu_context *ctx, int mem_aff,
         */
        node = cpu_to_node(raw_smp_processor_id());
        for (n = 0; n < MAX_NUMNODES; n++, node++) {
+               int available_spus;
+
                node = (node < MAX_NUMNODES) ? node : 0;
                if (!node_allowed(ctx, node))
                        continue;
+
+               available_spus = 0;
                mutex_lock(&cbe_spu_info[node].list_mutex);
+               list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
+                       if (spu->ctx && spu->ctx->gang
+                                       && spu->ctx->aff_offset == 0)
+                               available_spus -=
+                                       (spu->ctx->gang->contexts - 1);
+                       else
+                               available_spus++;
+               }
+               if (available_spus < ctx->gang->contexts) {
+                       mutex_unlock(&cbe_spu_info[node].list_mutex);
+                       continue;
+               }
+
                list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
                        if ((!mem_aff || spu->has_mem_affinity) &&
                                                        sched_spu(spu)) {
@@ -389,6 +406,9 @@ static int has_affinity(struct spu_context *ctx)
        if (list_empty(&ctx->aff_list))
                return 0;
 
+       if (atomic_read(&ctx->gang->aff_sched_count) == 0)
+               ctx->gang->aff_ref_spu = NULL;
+
        if (!gang->aff_ref_spu) {
                if (!(gang->aff_flags & AFF_MERGED))
                        aff_merge_remaining_ctxs(gang);
@@ -416,14 +436,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
        if (spu->ctx->flags & SPU_CREATE_NOSCHED)
                atomic_dec(&cbe_spu_info[spu->node].reserved_spus);
 
-       if (ctx->gang){
-               mutex_lock(&ctx->gang->aff_mutex);
-               if (has_affinity(ctx)) {
-                       if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
-                               ctx->gang->aff_ref_spu = NULL;
-               }
-               mutex_unlock(&ctx->gang->aff_mutex);
-       }
+       if (ctx->gang)
+               atomic_dec_if_positive(&ctx->gang->aff_sched_count);
 
        spu_switch_notify(spu, NULL);
        spu_unmap_mappings(ctx);
@@ -562,10 +576,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
                                goto found;
                        mutex_unlock(&cbe_spu_info[node].list_mutex);
 
-                       mutex_lock(&ctx->gang->aff_mutex);
-                       if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
-                               ctx->gang->aff_ref_spu = NULL;
-                       mutex_unlock(&ctx->gang->aff_mutex);
+                       atomic_dec(&ctx->gang->aff_sched_count);
                        goto not_found;
                }
                mutex_unlock(&ctx->gang->aff_mutex);
index 8c0e95766a628503860ccb7b194132e29622e4f3..92d20e993ede097d5e732a2bf0b751f9931eb7d1 100644 (file)
@@ -196,8 +196,7 @@ static int __init sputrace_init(void)
        struct proc_dir_entry *entry;
        int i, error = -ENOMEM;
 
-       sputrace_log = kcalloc(sizeof(struct sputrace),
-                               bufsize, GFP_KERNEL);
+       sputrace_log = kcalloc(bufsize, sizeof(struct sputrace), GFP_KERNEL);
        if (!sputrace_log)
                goto out;
 
index bc818e4e203321b50557361ae2f5c4f2717cd4dc..bb464d1211b2f5842bdb6d09862396600b6d9e33 100644 (file)
@@ -41,7 +41,7 @@
 #include <asm/iseries/hv_call_event.h>
 #include <asm/iseries/iommu.h>
 
-static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
+static int tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
                unsigned long uaddr, enum dma_data_direction direction,
                struct dma_attrs *attrs)
 {
@@ -71,6 +71,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
                index++;
                uaddr += TCE_PAGE_SIZE;
        }
+       return 0;
 }
 
 static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
index 1dc7295746dac6471503b098182c9f1e128239d8..731d7b157749e29547c0a615e66b35e0329ea72d 100644 (file)
@@ -871,7 +871,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
                count = 256 - off;
 
        dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE);
-       if (dma_mapping_error(dma_addr))
+       if (dma_mapping_error(NULL, dma_addr))
                return -ENOMEM;
        memset(page, 0, off + count);
        memset(&vsp_cmd, 0, sizeof(vsp_cmd));
index b72120751bbed16460b9f3c87c3e849b59228c2c..70b688c1aefb9f7512c74d0d20d1583454328c70 100644 (file)
@@ -561,7 +561,7 @@ static void yield_shared_processor(void)
 static void iseries_shared_idle(void)
 {
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched() && !hvlpevent_is_pending()) {
                        local_irq_disable();
                        ppc64_runlatch_off();
@@ -591,7 +591,7 @@ static void iseries_dedicated_idle(void)
        set_thread_flag(TIF_POLLING_NRFLAG);
 
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                if (!need_resched()) {
                        while (!need_resched()) {
                                ppc64_runlatch_off();
index 70541b7a5013ab68faed9758d86487be360bbe8c..a0ff03a3d8daf566350a2ead9e05131df36b65e7 100644 (file)
@@ -83,7 +83,7 @@ static u32 *iob_l2_base;
 static struct iommu_table iommu_table_iobmap;
 static int iommu_table_iobmap_inited;
 
-static void iobmap_build(struct iommu_table *tbl, long index,
+static int iobmap_build(struct iommu_table *tbl, long index,
                         long npages, unsigned long uaddr,
                         enum dma_data_direction direction,
                         struct dma_attrs *attrs)
@@ -108,6 +108,7 @@ static void iobmap_build(struct iommu_table *tbl, long index,
                uaddr += IOBMAP_PAGE_SIZE;
                bus_addr += IOBMAP_PAGE_SIZE;
        }
+       return 0;
 }
 
 
index 31635446901a95bbbab17a69543912c95f79ab5e..88ccf3a08a9c387ef13ac373d3f08e2368460350 100644 (file)
@@ -541,6 +541,78 @@ static int __init pmac_declare_of_platform_devices(void)
 }
 machine_device_initcall(powermac, pmac_declare_of_platform_devices);
 
+#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
+/*
+ * This is called very early, as part of console_init() (typically just after
+ * time_init()). This function is respondible for trying to find a good
+ * default console on serial ports. It tries to match the open firmware
+ * default output with one of the available serial console drivers.
+ */
+static int __init check_pmac_serial_console(void)
+{
+       struct device_node *prom_stdout = NULL;
+       int offset = 0;
+       const char *name;
+#ifdef CONFIG_SERIAL_PMACZILOG_TTYS
+       char *devname = "ttyS";
+#else
+       char *devname = "ttyPZ";
+#endif
+
+       pr_debug(" -> check_pmac_serial_console()\n");
+
+       /* The user has requested a console so this is already set up. */
+       if (strstr(boot_command_line, "console=")) {
+               pr_debug(" console was specified !\n");
+               return -EBUSY;
+       }
+
+       if (!of_chosen) {
+               pr_debug(" of_chosen is NULL !\n");
+               return -ENODEV;
+       }
+
+       /* We are getting a weird phandle from OF ... */
+       /* ... So use the full path instead */
+       name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+       if (name == NULL) {
+               pr_debug(" no linux,stdout-path !\n");
+               return -ENODEV;
+       }
+       prom_stdout = of_find_node_by_path(name);
+       if (!prom_stdout) {
+               pr_debug(" can't find stdout package %s !\n", name);
+               return -ENODEV;
+       }
+       pr_debug("stdout is %s\n", prom_stdout->full_name);
+
+       name = of_get_property(prom_stdout, "name", NULL);
+       if (!name) {
+               pr_debug(" stdout package has no name !\n");
+               goto not_found;
+       }
+
+       if (strcmp(name, "ch-a") == 0)
+               offset = 0;
+       else if (strcmp(name, "ch-b") == 0)
+               offset = 1;
+       else
+               goto not_found;
+       of_node_put(prom_stdout);
+
+       pr_debug("Found serial console at %s%d\n", devname, offset);
+
+       return add_preferred_console(devname, offset, NULL);
+
+ not_found:
+       pr_debug("No preferred console found !\n");
+       of_node_put(prom_stdout);
+       return -ENODEV;
+}
+console_initcall(check_pmac_serial_console);
+
+#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
index 47de4d3fc1674008f90dbf380e0971c6cb2417ac..572771fd84636aaaece971daa9a6648005b862ca 100644 (file)
@@ -125,13 +125,23 @@ void udbg_scc_init(int force_scc)
        out_8(sccc, 0xc0);
 
        /* If SCC was the OF output port, read the BRG value, else
-        * Setup for 57600 8N1
+        * Setup for 38400 or 57600 8N1 depending on the machine
         */
        if (ch_def != NULL) {
                out_8(sccc, 13);
                scc_inittab[1] = in_8(sccc);
                out_8(sccc, 12);
                scc_inittab[3] = in_8(sccc);
+       } else if (machine_is_compatible("RackMac1,1")
+                  || machine_is_compatible("RackMac1,2")
+                  || machine_is_compatible("MacRISC4")) {
+               /* Xserves and G5s default to 57600 */
+               scc_inittab[1] = 0;
+               scc_inittab[3] = 0;
+       } else {
+               /* Others default to 38400 */
+               scc_inittab[1] = 0;
+               scc_inittab[3] = 1;
        }
 
        for (i = 0; i < sizeof(scc_inittab); ++i)
index 757c0296e0b83e7456d28f5402f5db3c5918d4f4..97619fd51e393870d1c0c1da8a6bdb1926a52a57 100644 (file)
@@ -40,3 +40,26 @@ config PPC_PSERIES_DEBUG
        depends on PPC_PSERIES && PPC_EARLY_DEBUG
        bool "Enable extra debug logging in platforms/pseries"
        default y
+
+config PPC_SMLPAR
+       bool "Support for shared-memory logical partitions"
+       depends on PPC_PSERIES
+       select LPARCFG
+       default n
+       help
+         Select this option to enable shared memory partition support.
+         With this option a system running in an LPAR can be given more
+         memory than physically available and will allow firmware to
+         balance memory across many LPARs.
+
+config CMM
+       tristate "Collaborative memory management"
+       depends on PPC_SMLPAR
+       default y
+       help
+         Select this option, if you want to enable the kernel interface
+         to reduce the memory size of the system. This is accomplished
+         by allocating pages of memory and put them "on hold". This only
+         makes sense for a system running in an LPAR where the unused pages
+         will be reused for other LPARs. The interface allows firmware to
+         balance memory across many LPARs.
index 554c6e42ef2a9ff1f78340a0d5a9c49f5d46b611..dfe574af2dc090bd5ce3aaac503fef02e8bddb91 100644 (file)
@@ -24,3 +24,4 @@ obj-$(CONFIG_HVC_CONSOLE)     += hvconsole.o
 obj-$(CONFIG_HVCS)             += hvcserver.o
 obj-$(CONFIG_HCALL_STATS)      += hvCall_inst.o
 obj-$(CONFIG_PHYP_DUMP)        += phyp_dump.o
+obj-$(CONFIG_CMM)              += cmm.o
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c
new file mode 100644 (file)
index 0000000..38fe32a
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * Collaborative memory management interface.
+ *
+ * Copyright (C) 2008 IBM Corporation
+ * Author(s): Brian King (brking@linux.vnet.ibm.com),
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the 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/ctype.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/oom.h>
+#include <linux/sched.h>
+#include <linux/stringify.h>
+#include <linux/swap.h>
+#include <linux/sysdev.h>
+#include <asm/firmware.h>
+#include <asm/hvcall.h>
+#include <asm/mmu.h>
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+
+#include "plpar_wrappers.h"
+
+#define CMM_DRIVER_VERSION     "1.0.0"
+#define CMM_DEFAULT_DELAY      1
+#define CMM_DEBUG                      0
+#define CMM_DISABLE            0
+#define CMM_OOM_KB             1024
+#define CMM_MIN_MEM_MB         256
+#define KB2PAGES(_p)           ((_p)>>(PAGE_SHIFT-10))
+#define PAGES2KB(_p)           ((_p)<<(PAGE_SHIFT-10))
+
+static unsigned int delay = CMM_DEFAULT_DELAY;
+static unsigned int oom_kb = CMM_OOM_KB;
+static unsigned int cmm_debug = CMM_DEBUG;
+static unsigned int cmm_disabled = CMM_DISABLE;
+static unsigned long min_mem_mb = CMM_MIN_MEM_MB;
+static struct sys_device cmm_sysdev;
+
+MODULE_AUTHOR("Brian King <brking@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("IBM System p Collaborative Memory Manager");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CMM_DRIVER_VERSION);
+
+module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. "
+                "[Default=" __stringify(CMM_DEFAULT_DELAY) "]");
+module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. "
+                "[Default=" __stringify(CMM_OOM_KB) "]");
+module_param_named(min_mem_mb, min_mem_mb, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(min_mem_mb, "Minimum amount of memory (in MB) to not balloon. "
+                "[Default=" __stringify(CMM_MIN_MEM_MB) "]");
+module_param_named(debug, cmm_debug, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable module debugging logging. Set to 1 to enable. "
+                "[Default=" __stringify(CMM_DEBUG) "]");
+
+#define CMM_NR_PAGES ((PAGE_SIZE - sizeof(void *) - sizeof(unsigned long)) / sizeof(unsigned long))
+
+#define cmm_dbg(...) if (cmm_debug) { printk(KERN_INFO "cmm: "__VA_ARGS__); }
+
+struct cmm_page_array {
+       struct cmm_page_array *next;
+       unsigned long index;
+       unsigned long page[CMM_NR_PAGES];
+};
+
+static unsigned long loaned_pages;
+static unsigned long loaned_pages_target;
+static unsigned long oom_freed_pages;
+
+static struct cmm_page_array *cmm_page_list;
+static DEFINE_SPINLOCK(cmm_lock);
+
+static struct task_struct *cmm_thread_ptr;
+
+/**
+ * cmm_alloc_pages - Allocate pages and mark them as loaned
+ * @nr:        number of pages to allocate
+ *
+ * Return value:
+ *     number of pages requested to be allocated which were not
+ **/
+static long cmm_alloc_pages(long nr)
+{
+       struct cmm_page_array *pa, *npa;
+       unsigned long addr;
+       long rc;
+
+       cmm_dbg("Begin request for %ld pages\n", nr);
+
+       while (nr) {
+               addr = __get_free_page(GFP_NOIO | __GFP_NOWARN |
+                                      __GFP_NORETRY | __GFP_NOMEMALLOC);
+               if (!addr)
+                       break;
+               spin_lock(&cmm_lock);
+               pa = cmm_page_list;
+               if (!pa || pa->index >= CMM_NR_PAGES) {
+                       /* Need a new page for the page list. */
+                       spin_unlock(&cmm_lock);
+                       npa = (struct cmm_page_array *)__get_free_page(GFP_NOIO | __GFP_NOWARN |
+                                                                      __GFP_NORETRY | __GFP_NOMEMALLOC);
+                       if (!npa) {
+                               pr_info("%s: Can not allocate new page list\n", __FUNCTION__);
+                               free_page(addr);
+                               break;
+                       }
+                       spin_lock(&cmm_lock);
+                       pa = cmm_page_list;
+
+                       if (!pa || pa->index >= CMM_NR_PAGES) {
+                               npa->next = pa;
+                               npa->index = 0;
+                               pa = npa;
+                               cmm_page_list = pa;
+                       } else
+                               free_page((unsigned long) npa);
+               }
+
+               if ((rc = plpar_page_set_loaned(__pa(addr)))) {
+                       pr_err("%s: Can not set page to loaned. rc=%ld\n", __FUNCTION__, rc);
+                       spin_unlock(&cmm_lock);
+                       free_page(addr);
+                       break;
+               }
+
+               pa->page[pa->index++] = addr;
+               loaned_pages++;
+               totalram_pages--;
+               spin_unlock(&cmm_lock);
+               nr--;
+       }
+
+       cmm_dbg("End request with %ld pages unfulfilled\n", nr);
+       return nr;
+}
+
+/**
+ * cmm_free_pages - Free pages and mark them as active
+ * @nr:        number of pages to free
+ *
+ * Return value:
+ *     number of pages requested to be freed which were not
+ **/
+static long cmm_free_pages(long nr)
+{
+       struct cmm_page_array *pa;
+       unsigned long addr;
+
+       cmm_dbg("Begin free of %ld pages.\n", nr);
+       spin_lock(&cmm_lock);
+       pa = cmm_page_list;
+       while (nr) {
+               if (!pa || pa->index <= 0)
+                       break;
+               addr = pa->page[--pa->index];
+
+               if (pa->index == 0) {
+                       pa = pa->next;
+                       free_page((unsigned long) cmm_page_list);
+                       cmm_page_list = pa;
+               }
+
+               plpar_page_set_active(__pa(addr));
+               free_page(addr);
+               loaned_pages--;
+               nr--;
+               totalram_pages++;
+       }
+       spin_unlock(&cmm_lock);
+       cmm_dbg("End request with %ld pages unfulfilled\n", nr);
+       return nr;
+}
+
+/**
+ * cmm_oom_notify - OOM notifier
+ * @self:      notifier block struct
+ * @dummy:     not used
+ * @parm:      returned - number of pages freed
+ *
+ * Return value:
+ *     NOTIFY_OK
+ **/
+static int cmm_oom_notify(struct notifier_block *self,
+                         unsigned long dummy, void *parm)
+{
+       unsigned long *freed = parm;
+       long nr = KB2PAGES(oom_kb);
+
+       cmm_dbg("OOM processing started\n");
+       nr = cmm_free_pages(nr);
+       loaned_pages_target = loaned_pages;
+       *freed += KB2PAGES(oom_kb) - nr;
+       oom_freed_pages += KB2PAGES(oom_kb) - nr;
+       cmm_dbg("OOM processing complete\n");
+       return NOTIFY_OK;
+}
+
+/**
+ * cmm_get_mpp - Read memory performance parameters
+ *
+ * Makes hcall to query the current page loan request from the hypervisor.
+ *
+ * Return value:
+ *     nothing
+ **/
+static void cmm_get_mpp(void)
+{
+       int rc;
+       struct hvcall_mpp_data mpp_data;
+       unsigned long active_pages_target;
+       signed long page_loan_request;
+
+       rc = h_get_mpp(&mpp_data);
+
+       if (rc != H_SUCCESS)
+               return;
+
+       page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE);
+       loaned_pages_target = page_loan_request + loaned_pages;
+       if (loaned_pages_target > oom_freed_pages)
+               loaned_pages_target -= oom_freed_pages;
+       else
+               loaned_pages_target = 0;
+
+       active_pages_target = totalram_pages + loaned_pages - loaned_pages_target;
+
+       if ((min_mem_mb * 1024 * 1024) > (active_pages_target * PAGE_SIZE))
+               loaned_pages_target = totalram_pages + loaned_pages -
+                       ((min_mem_mb * 1024 * 1024) / PAGE_SIZE);
+
+       cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n",
+               page_loan_request, loaned_pages, loaned_pages_target,
+               oom_freed_pages, totalram_pages);
+}
+
+static struct notifier_block cmm_oom_nb = {
+       .notifier_call = cmm_oom_notify
+};
+
+/**
+ * cmm_thread - CMM task thread
+ * @dummy:     not used
+ *
+ * Return value:
+ *     0
+ **/
+static int cmm_thread(void *dummy)
+{
+       unsigned long timeleft;
+
+       while (1) {
+               timeleft = msleep_interruptible(delay * 1000);
+
+               if (kthread_should_stop() || timeleft) {
+                       loaned_pages_target = loaned_pages;
+                       break;
+               }
+
+               cmm_get_mpp();
+
+               if (loaned_pages_target > loaned_pages) {
+                       if (cmm_alloc_pages(loaned_pages_target - loaned_pages))
+                               loaned_pages_target = loaned_pages;
+               } else if (loaned_pages_target < loaned_pages)
+                       cmm_free_pages(loaned_pages - loaned_pages_target);
+       }
+       return 0;
+}
+
+#define CMM_SHOW(name, format, args...)                        \
+       static ssize_t show_##name(struct sys_device *dev,      \
+                                  struct sysdev_attribute *attr,       \
+                                  char *buf)                   \
+       {                                                       \
+               return sprintf(buf, format, ##args);            \
+       }                                                       \
+       static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
+
+CMM_SHOW(loaned_kb, "%lu\n", PAGES2KB(loaned_pages));
+CMM_SHOW(loaned_target_kb, "%lu\n", PAGES2KB(loaned_pages_target));
+
+static ssize_t show_oom_pages(struct sys_device *dev,
+                             struct sysdev_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%lu\n", PAGES2KB(oom_freed_pages));
+}
+
+static ssize_t store_oom_pages(struct sys_device *dev,
+                              struct sysdev_attribute *attr,
+                              const char *buf, size_t count)
+{
+       unsigned long val = simple_strtoul (buf, NULL, 10);
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       if (val != 0)
+               return -EBADMSG;
+
+       oom_freed_pages = 0;
+       return count;
+}
+
+static SYSDEV_ATTR(oom_freed_kb, S_IWUSR| S_IRUGO,
+                  show_oom_pages, store_oom_pages);
+
+static struct sysdev_attribute *cmm_attrs[] = {
+       &attr_loaned_kb,
+       &attr_loaned_target_kb,
+       &attr_oom_freed_kb,
+};
+
+static struct sysdev_class cmm_sysdev_class = {
+       .name = "cmm",
+};
+
+/**
+ * cmm_sysfs_register - Register with sysfs
+ *
+ * Return value:
+ *     0 on success / other on failure
+ **/
+static int cmm_sysfs_register(struct sys_device *sysdev)
+{
+       int i, rc;
+
+       if ((rc = sysdev_class_register(&cmm_sysdev_class)))
+               return rc;
+
+       sysdev->id = 0;
+       sysdev->cls = &cmm_sysdev_class;
+
+       if ((rc = sysdev_register(sysdev)))
+               goto class_unregister;
+
+       for (i = 0; i < ARRAY_SIZE(cmm_attrs); i++) {
+               if ((rc = sysdev_create_file(sysdev, cmm_attrs[i])))
+                       goto fail;
+       }
+
+       return 0;
+
+fail:
+       while (--i >= 0)
+               sysdev_remove_file(sysdev, cmm_attrs[i]);
+       sysdev_unregister(sysdev);
+class_unregister:
+       sysdev_class_unregister(&cmm_sysdev_class);
+       return rc;
+}
+
+/**
+ * cmm_unregister_sysfs - Unregister from sysfs
+ *
+ **/
+static void cmm_unregister_sysfs(struct sys_device *sysdev)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(cmm_attrs); i++)
+               sysdev_remove_file(sysdev, cmm_attrs[i]);
+       sysdev_unregister(sysdev);
+       sysdev_class_unregister(&cmm_sysdev_class);
+}
+
+/**
+ * cmm_init - Module initialization
+ *
+ * Return value:
+ *     0 on success / other on failure
+ **/
+static int cmm_init(void)
+{
+       int rc = -ENOMEM;
+
+       if (!firmware_has_feature(FW_FEATURE_CMO))
+               return -EOPNOTSUPP;
+
+       if ((rc = register_oom_notifier(&cmm_oom_nb)) < 0)
+               return rc;
+
+       if ((rc = cmm_sysfs_register(&cmm_sysdev)))
+               goto out_oom_notifier;
+
+       if (cmm_disabled)
+               return rc;
+
+       cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
+       if (IS_ERR(cmm_thread_ptr)) {
+               rc = PTR_ERR(cmm_thread_ptr);
+               goto out_unregister_sysfs;
+       }
+
+       return rc;
+
+out_unregister_sysfs:
+       cmm_unregister_sysfs(&cmm_sysdev);
+out_oom_notifier:
+       unregister_oom_notifier(&cmm_oom_nb);
+       return rc;
+}
+
+/**
+ * cmm_exit - Module exit
+ *
+ * Return value:
+ *     nothing
+ **/
+static void cmm_exit(void)
+{
+       if (cmm_thread_ptr)
+               kthread_stop(cmm_thread_ptr);
+       unregister_oom_notifier(&cmm_oom_nb);
+       cmm_free_pages(loaned_pages);
+       cmm_unregister_sysfs(&cmm_sysdev);
+}
+
+/**
+ * cmm_set_disable - Disable/Enable CMM
+ *
+ * Return value:
+ *     0 on success / other on failure
+ **/
+static int cmm_set_disable(const char *val, struct kernel_param *kp)
+{
+       int disable = simple_strtoul(val, NULL, 10);
+
+       if (disable != 0 && disable != 1)
+               return -EINVAL;
+
+       if (disable && !cmm_disabled) {
+               if (cmm_thread_ptr)
+                       kthread_stop(cmm_thread_ptr);
+               cmm_thread_ptr = NULL;
+               cmm_free_pages(loaned_pages);
+       } else if (!disable && cmm_disabled) {
+               cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
+               if (IS_ERR(cmm_thread_ptr))
+                       return PTR_ERR(cmm_thread_ptr);
+       }
+
+       cmm_disabled = disable;
+       return 0;
+}
+
+module_param_call(disable, cmm_set_disable, param_get_uint,
+                 &cmm_disabled, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(disable, "Disable CMM. Set to 1 to disable. "
+                "[Default=" __stringify(CMM_DISABLE) "]");
+
+module_init(cmm_init);
+module_exit(cmm_exit);
index 5377dd4b849a5bc8fced028eae7bd2b59c758207..a8c446697f9e3b0e737b418f1f966fbec3bd1f49 100644 (file)
@@ -48,7 +48,7 @@
 #include "plpar_wrappers.h"
 
 
-static void tce_build_pSeries(struct iommu_table *tbl, long index,
+static int tce_build_pSeries(struct iommu_table *tbl, long index,
                              long npages, unsigned long uaddr,
                              enum dma_data_direction direction,
                              struct dma_attrs *attrs)
@@ -72,6 +72,7 @@ static void tce_build_pSeries(struct iommu_table *tbl, long index,
                uaddr += TCE_PAGE_SIZE;
                tcep++;
        }
+       return 0;
 }
 
 
@@ -94,14 +95,19 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
        return *tcep;
 }
 
-static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
+static void tce_free_pSeriesLP(struct iommu_table*, long, long);
+static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long);
+
+static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
                                long npages, unsigned long uaddr,
                                enum dma_data_direction direction,
                                struct dma_attrs *attrs)
 {
-       u64 rc;
+       u64 rc = 0;
        u64 proto_tce, tce;
        u64 rpn;
+       int ret = 0;
+       long tcenum_start = tcenum, npages_start = npages;
 
        rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
        proto_tce = TCE_PCI_READ;
@@ -112,6 +118,13 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
                tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
                rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
 
+               if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
+                       ret = (int)rc;
+                       tce_free_pSeriesLP(tbl, tcenum_start,
+                                          (npages_start - (npages + 1)));
+                       break;
+               }
+
                if (rc && printk_ratelimit()) {
                        printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
                        printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
@@ -123,25 +136,27 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
                tcenum++;
                rpn++;
        }
+       return ret;
 }
 
 static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
 
-static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                                     long npages, unsigned long uaddr,
                                     enum dma_data_direction direction,
                                     struct dma_attrs *attrs)
 {
-       u64 rc;
+       u64 rc = 0;
        u64 proto_tce;
        u64 *tcep;
        u64 rpn;
        long l, limit;
+       long tcenum_start = tcenum, npages_start = npages;
+       int ret = 0;
 
        if (npages == 1) {
-               tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
-                                   direction, attrs);
-               return;
+               return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+                                          direction, attrs);
        }
 
        tcep = __get_cpu_var(tce_page);
@@ -153,9 +168,8 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                tcep = (u64 *)__get_free_page(GFP_ATOMIC);
                /* If allocation fails, fall back to the loop implementation */
                if (!tcep) {
-                       tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+                       return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
                                            direction, attrs);
-                       return;
                }
                __get_cpu_var(tce_page) = tcep;
        }
@@ -187,6 +201,13 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                tcenum += limit;
        } while (npages > 0 && !rc);
 
+       if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
+               ret = (int)rc;
+               tce_freemulti_pSeriesLP(tbl, tcenum_start,
+                                       (npages_start - (npages + limit)));
+               return ret;
+       }
+
        if (rc && printk_ratelimit()) {
                printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
                printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
@@ -194,6 +215,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                printk("\ttce[0] val = 0x%lx\n", tcep[0]);
                show_stack(current, (unsigned long *)__get_SP());
        }
+       return ret;
 }
 
 static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
index d8680b589dc96c325afb09725c47f5c6a008a3e6..a437267c6bf86efb7443a44bfbf9ed693614371a 100644 (file)
@@ -42,6 +42,16 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)
        return vpa_call(0x3, cpu, vpa);
 }
 
+static inline long plpar_page_set_loaned(unsigned long vpa)
+{
+       return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa, 0);
+}
+
+static inline long plpar_page_set_active(unsigned long vpa)
+{
+       return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa, 0);
+}
+
 extern void vpa_init(int cpu);
 
 static inline long plpar_pte_enter(unsigned long flags,
index 90beb444e1dd670f64836fdceff20c247b79ed07..063a0d2fba30e2576771a300460220c4e21c4cec 100644 (file)
@@ -314,6 +314,76 @@ static int pseries_set_xdabr(unsigned long dabr)
                        H_DABRX_KERNEL | H_DABRX_USER);
 }
 
+#define CMO_CHARACTERISTICS_TOKEN 44
+#define CMO_MAXLENGTH 1026
+
+/**
+ * fw_cmo_feature_init - FW_FEATURE_CMO is not stored in ibm,hypertas-functions,
+ * handle that here. (Stolen from parse_system_parameter_string)
+ */
+void pSeries_cmo_feature_init(void)
+{
+       char *ptr, *key, *value, *end;
+       int call_status;
+       int PrPSP = -1;
+       int SecPSP = -1;
+
+       pr_debug(" -> fw_cmo_feature_init()\n");
+       spin_lock(&rtas_data_buf_lock);
+       memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE);
+       call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
+                               NULL,
+                               CMO_CHARACTERISTICS_TOKEN,
+                               __pa(rtas_data_buf),
+                               RTAS_DATA_BUF_SIZE);
+
+       if (call_status != 0) {
+               spin_unlock(&rtas_data_buf_lock);
+               pr_debug("CMO not available\n");
+               pr_debug(" <- fw_cmo_feature_init()\n");
+               return;
+       }
+
+       end = rtas_data_buf + CMO_MAXLENGTH - 2;
+       ptr = rtas_data_buf + 2;        /* step over strlen value */
+       key = value = ptr;
+
+       while (*ptr && (ptr <= end)) {
+               /* Separate the key and value by replacing '=' with '\0' and
+                * point the value at the string after the '='
+                */
+               if (ptr[0] == '=') {
+                       ptr[0] = '\0';
+                       value = ptr + 1;
+               } else if (ptr[0] == '\0' || ptr[0] == ',') {
+                       /* Terminate the string containing the key/value pair */
+                       ptr[0] = '\0';
+
+                       if (key == value) {
+                               pr_debug("Malformed key/value pair\n");
+                               /* Never found a '=', end processing */
+                               break;
+                       }
+
+                       if (0 == strcmp(key, "PrPSP"))
+                               PrPSP = simple_strtol(value, NULL, 10);
+                       else if (0 == strcmp(key, "SecPSP"))
+                               SecPSP = simple_strtol(value, NULL, 10);
+                       value = key = ptr + 1;
+               }
+               ptr++;
+       }
+
+       if (PrPSP != -1 || SecPSP != -1) {
+               pr_info("CMO enabled\n");
+               pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+               powerpc_firmware_features |= FW_FEATURE_CMO;
+       } else
+               pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+       spin_unlock(&rtas_data_buf_lock);
+       pr_debug(" <- fw_cmo_feature_init()\n");
+}
+
 /*
  * Early initialization.  Relocation is on but do not reference unbolted pages
  */
@@ -329,6 +399,7 @@ static void __init pSeries_init_early(void)
        else if (firmware_has_feature(FW_FEATURE_XDABR))
                ppc_md.set_dabr = pseries_set_xdabr;
 
+       pSeries_cmo_feature_init();
        iommu_init_early_pSeries();
 
        pr_debug(" <- pSeries_init_early()\n");
index de8c8b542cfa157d76281163e7ca21dfe1071b36..89639ecbf38162621ca3d57654866ff08f4033d5 100644 (file)
@@ -147,7 +147,7 @@ static void dart_flush(struct iommu_table *tbl)
        }
 }
 
-static void dart_build(struct iommu_table *tbl, long index,
+static int dart_build(struct iommu_table *tbl, long index,
                       long npages, unsigned long uaddr,
                       enum dma_data_direction direction,
                       struct dma_attrs *attrs)
@@ -184,6 +184,7 @@ static void dart_build(struct iommu_table *tbl, long index,
        } else {
                dart_dirty = 1;
        }
+       return 0;
 }
 
 
index 4bb18f57901e5c3585bc5e9bd60d18704239c96c..1ce546462be5af559539fb00314c8fc89d0c03b1 100644 (file)
@@ -29,7 +29,7 @@ config QE_GPIO
        bool "QE GPIO support"
        depends on QUICC_ENGINE
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
        help
          Say Y here if you're going to use hardware that connects to the
          QE GPIOs.
index eb530b4128ba9353a9fa6d397102b0e52de77cd7..2ed88122be9319ea735da3b7b7a6cfd8e6700f67 100644 (file)
@@ -565,6 +565,7 @@ bool "s390 guest support (EXPERIMENTAL)"
        depends on 64BIT && EXPERIMENTAL
        select VIRTIO
        select VIRTIO_RING
+       select VIRTIO_CONSOLE
        help
          Select this option if you want to run the kernel under s390 linux
 endmenu
index 288ad490a6dd7ce931c0622c353d078eaf7a9799..569079ec4ff004f010d64df7d746b0a01caff44c 100644 (file)
@@ -197,7 +197,7 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
        args.new = BREAKPOINT_INSTRUCTION;
 
        kcb->kprobe_status = KPROBE_SWAP_INST;
-       stop_machine_run(swap_instruction, &args, NR_CPUS);
+       stop_machine(swap_instruction, &args, NULL);
        kcb->kprobe_status = status;
 }
 
@@ -212,7 +212,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
        args.new = p->opcode;
 
        kcb->kprobe_status = KPROBE_SWAP_INST;
-       stop_machine_run(swap_instruction, &args, NR_CPUS);
+       stop_machine(swap_instruction, &args, NULL);
        kcb->kprobe_status = status;
 }
 
@@ -270,7 +270,6 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
        __ctl_store(kcb->kprobe_saved_ctl, 9, 11);
 }
 
-/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                        struct pt_regs *regs)
 {
@@ -332,7 +331,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
                 * No kprobe at this address. The fault has not been
                 * caused by a kprobe breakpoint. The race of breakpoint
                 * vs. kprobe remove does not exist because on s390 we
-                * use stop_machine_run to arm/disarm the breakpoints.
+                * use stop_machine to arm/disarm the breakpoints.
                 */
                goto no_kprobe;
 
@@ -377,8 +376,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
        unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
 
        INIT_HLIST_HEAD(&empty_rp);
-       spin_lock_irqsave(&kretprobe_lock, flags);
-       head = kretprobe_inst_table_head(current);
+       kretprobe_hash_lock(current, &head, &flags);
 
        /*
         * It is possible to have multiple instances associated with a given
@@ -417,7 +415,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
        regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE;
 
        reset_current_kprobe();
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
+       kretprobe_hash_unlock(current, &flags);
        preempt_enable_no_resched();
 
        hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
index 85defd01d2937c36ccd0a92b18932969dfb8520f..9839767d0842e5d065524181db75aa075c154798 100644 (file)
@@ -142,7 +142,7 @@ static void default_idle(void)
 void cpu_idle(void)
 {
        for (;;) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        default_idle();
                tick_nohz_restart_sched_tick();
index b358e18273b07f2e1e31315e77835fd84f880bfc..62122bad1e3316f2112ae66c22e51859c7214b52 100644 (file)
@@ -54,6 +54,7 @@
 #include <asm/sections.h>
 #include <asm/ebcdic.h>
 #include <asm/compat.h>
+#include <asm/kvm_virtio.h>
 
 long psw_kernel_bits   = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY |
                           PSW_MASK_MCHECK | PSW_DEFAULT_KEY);
@@ -766,7 +767,8 @@ setup_arch(char **cmdline_p)
                printk("We are running under VM (64 bit mode)\n");
        else if (MACHINE_IS_KVM) {
                printk("We are running under KVM (64 bit mode)\n");
-               add_preferred_console("ttyS", 1, NULL);
+               add_preferred_console("hvc", 0, NULL);
+               s390_virtio_console_init();
        } else
                printk("We are running native (64 bit mode)\n");
 #endif /* CONFIG_64BIT */
index 212d618b00952a17152e9985b8a3d27a3ac657cd..632b13e100538704758cea2eebd75c6cfdc15bf7 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/device.h>
 #include <linux/bootmem.h>
 #include <linux/sched.h>
-#include <linux/kthread.h>
 #include <linux/workqueue.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
@@ -230,20 +229,9 @@ void arch_update_cpu_topology(void)
        }
 }
 
-static int topology_kthread(void *data)
-{
-       arch_reinit_sched_domains();
-       return 0;
-}
-
 static void topology_work_fn(struct work_struct *work)
 {
-       /* We can't call arch_reinit_sched_domains() from a multi-threaded
-        * workqueue context since it may deadlock in case of cpu hotplug.
-        * So we have to create a kernel thread in order to call
-        * arch_reinit_sched_domains().
-        */
-       kthread_run(topology_kthread, NULL, "topology_update");
+       arch_reinit_sched_domains();
 }
 
 void topology_schedule_update(void)
index 4e0633c413f3841dc1132c39d06dc5645b57f66d..ed60f3a74a85f1ca6a8e994a974fc2bba6dd1652 100644 (file)
 #include <asm/uaccess.h>
 
 static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
-                                              u64 guestaddr)
+                                              unsigned long guestaddr)
 {
-       u64 prefix  = vcpu->arch.sie_block->prefix;
-       u64 origin  = vcpu->kvm->arch.guest_origin;
-       u64 memsize = vcpu->kvm->arch.guest_memsize;
+       unsigned long prefix  = vcpu->arch.sie_block->prefix;
+       unsigned long origin  = vcpu->kvm->arch.guest_origin;
+       unsigned long memsize = vcpu->kvm->arch.guest_memsize;
 
        if (guestaddr < 2 * PAGE_SIZE)
                guestaddr += prefix;
@@ -37,7 +37,7 @@ static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
        return (void __user *) guestaddr;
 }
 
-static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
+static inline int get_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
                                u64 *result)
 {
        void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@@ -47,10 +47,10 @@ static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
        if (IS_ERR((void __force *) uptr))
                return PTR_ERR((void __force *) uptr);
 
-       return get_user(*result, (u64 __user *) uptr);
+       return get_user(*result, (unsigned long __user *) uptr);
 }
 
-static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
+static inline int get_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
                                u32 *result)
 {
        void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@@ -63,7 +63,7 @@ static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
        return get_user(*result, (u32 __user *) uptr);
 }
 
-static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
+static inline int get_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
                                u16 *result)
 {
        void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@@ -76,7 +76,7 @@ static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
        return get_user(*result, (u16 __user *) uptr);
 }
 
-static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
+static inline int get_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
                               u8 *result)
 {
        void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@@ -87,7 +87,7 @@ static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
        return get_user(*result, (u8 __user *) uptr);
 }
 
-static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
+static inline int put_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
                                u64 value)
 {
        void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@@ -100,7 +100,7 @@ static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
        return put_user(value, (u64 __user *) uptr);
 }
 
-static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
+static inline int put_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
                                u32 value)
 {
        void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@@ -113,7 +113,7 @@ static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
        return put_user(value, (u32 __user *) uptr);
 }
 
-static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
+static inline int put_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
                                u16 value)
 {
        void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@@ -126,7 +126,7 @@ static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
        return put_user(value, (u16 __user *) uptr);
 }
 
-static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
+static inline int put_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
                               u8 value)
 {
        void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@@ -138,7 +138,8 @@ static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
 }
 
 
-static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest,
+static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
+                                      unsigned long guestdest,
                                       const void *from, unsigned long n)
 {
        int rc;
@@ -153,12 +154,12 @@ static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest,
        return 0;
 }
 
-static inline int copy_to_guest(struct kvm_vcpu *vcpu, u64 guestdest,
+static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
                                const void *from, unsigned long n)
 {
-       u64 prefix  = vcpu->arch.sie_block->prefix;
-       u64 origin  = vcpu->kvm->arch.guest_origin;
-       u64 memsize = vcpu->kvm->arch.guest_memsize;
+       unsigned long prefix  = vcpu->arch.sie_block->prefix;
+       unsigned long origin  = vcpu->kvm->arch.guest_origin;
+       unsigned long memsize = vcpu->kvm->arch.guest_memsize;
 
        if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
                goto slowpath;
@@ -189,7 +190,8 @@ slowpath:
 }
 
 static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
-                                        u64 guestsrc, unsigned long n)
+                                        unsigned long guestsrc,
+                                        unsigned long n)
 {
        int rc;
        unsigned long i;
@@ -204,11 +206,11 @@ static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
 }
 
 static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
-                                 u64 guestsrc, unsigned long n)
+                                 unsigned long guestsrc, unsigned long n)
 {
-       u64 prefix  = vcpu->arch.sie_block->prefix;
-       u64 origin  = vcpu->kvm->arch.guest_origin;
-       u64 memsize = vcpu->kvm->arch.guest_memsize;
+       unsigned long prefix  = vcpu->arch.sie_block->prefix;
+       unsigned long origin  = vcpu->kvm->arch.guest_origin;
+       unsigned long memsize = vcpu->kvm->arch.guest_memsize;
 
        if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
                goto slowpath;
@@ -238,11 +240,12 @@ slowpath:
        return __copy_from_guest_slow(vcpu, to, guestsrc, n);
 }
 
-static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest,
+static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
+                                        unsigned long guestdest,
                                         const void *from, unsigned long n)
 {
-       u64 origin  = vcpu->kvm->arch.guest_origin;
-       u64 memsize = vcpu->kvm->arch.guest_memsize;
+       unsigned long origin  = vcpu->kvm->arch.guest_origin;
+       unsigned long memsize = vcpu->kvm->arch.guest_memsize;
 
        if (guestdest + n > memsize)
                return -EFAULT;
@@ -256,10 +259,11 @@ static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest,
 }
 
 static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
-                                          u64 guestsrc, unsigned long n)
+                                          unsigned long guestsrc,
+                                          unsigned long n)
 {
-       u64 origin  = vcpu->kvm->arch.guest_origin;
-       u64 memsize = vcpu->kvm->arch.guest_memsize;
+       unsigned long origin  = vcpu->kvm->arch.guest_origin;
+       unsigned long memsize = vcpu->kvm->arch.guest_memsize;
 
        if (guestsrc + n > memsize)
                return -EFAULT;
index 47a0b642174c1ef807ca5d16774f9d10c6584197..61236102203e8746933ae96dab4876b421d901d6 100644 (file)
@@ -20,7 +20,7 @@
 #include "kvm-s390.h"
 #include "gaccess.h"
 
-static int handle_lctg(struct kvm_vcpu *vcpu)
+static int handle_lctlg(struct kvm_vcpu *vcpu)
 {
        int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
        int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
@@ -30,7 +30,7 @@ static int handle_lctg(struct kvm_vcpu *vcpu)
        u64 useraddr;
        int reg, rc;
 
-       vcpu->stat.instruction_lctg++;
+       vcpu->stat.instruction_lctlg++;
        if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
                return -ENOTSUPP;
 
@@ -38,9 +38,12 @@ static int handle_lctg(struct kvm_vcpu *vcpu)
        if (base2)
                useraddr += vcpu->arch.guest_gprs[base2];
 
+       if (useraddr & 7)
+               return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
        reg = reg1;
 
-       VCPU_EVENT(vcpu, 5, "lctg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
+       VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
                   disp2);
 
        do {
@@ -74,6 +77,9 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
        if (base2)
                useraddr += vcpu->arch.guest_gprs[base2];
 
+       if (useraddr & 3)
+               return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
        VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
                   disp2);
 
@@ -99,7 +105,7 @@ static intercept_handler_t instruction_handlers[256] = {
        [0xae] = kvm_s390_handle_sigp,
        [0xb2] = kvm_s390_handle_priv,
        [0xb7] = handle_lctl,
-       [0xeb] = handle_lctg,
+       [0xeb] = handle_lctlg,
 };
 
 static int handle_noop(struct kvm_vcpu *vcpu)
index 11230b0db957e3f8d5c3cbea6016bd9d917f0760..2960702b48246488087546669b1459524ead2958 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/lowcore.h>
 #include <asm/uaccess.h>
 #include <linux/kvm_host.h>
+#include <linux/signal.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 
@@ -246,15 +247,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
        default:
                BUG();
        }
-
        if (exception) {
-               VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering"
-                          " interrupt");
-               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
-               if (inti->type == KVM_S390_PROGRAM_INT) {
-                       printk(KERN_WARNING "kvm: recursive program check\n");
-                       BUG();
-               }
+               printk("kvm: The guest lowcore is not mapped during interrupt "
+                       "delivery, killing userspace\n");
+               do_exit(SIGKILL);
        }
 }
 
@@ -277,14 +273,11 @@ static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
                __LC_EXT_NEW_PSW, sizeof(psw_t));
        if (rc == -EFAULT)
                exception = 1;
-
        if (exception) {
-               VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" \
-                          " ckc interrupt");
-               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
-               return 0;
+               printk("kvm: The guest lowcore is not mapped during interrupt "
+                       "delivery, killing userspace\n");
+               do_exit(SIGKILL);
        }
-
        return 1;
 }
 
index 1782cbcd2829545270d897cd4f911d95f54d0fa7..8b00eb2ddf57459c9469d8455d0762d365a71c1f 100644 (file)
@@ -39,7 +39,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "exit_instruction", VCPU_STAT(exit_instruction) },
        { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
        { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
-       { "instruction_lctg", VCPU_STAT(instruction_lctg) },
+       { "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
        { "instruction_lctl", VCPU_STAT(instruction_lctl) },
        { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
        { "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
@@ -112,7 +112,12 @@ long kvm_arch_dev_ioctl(struct file *filp,
 
 int kvm_dev_ioctl_check_extension(long ext)
 {
-       return 0;
+       switch (ext) {
+       case KVM_CAP_USER_MEMORY:
+               return 1;
+       default:
+               return 0;
+       }
 }
 
 /* Section: vm related */
index 5a556114eaa58dd067955d0048f931cd5a0ac369..170392687ce042f64c69ea7f4fe85d863025b768 100644 (file)
@@ -43,7 +43,8 @@
 #define SIGP_STAT_RECEIVER_CHECK    0x00000001UL
 
 
-static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, u64 *reg)
+static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
+                       unsigned long *reg)
 {
        struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
        int rc;
@@ -167,7 +168,7 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
 }
 
 static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
-                            u64 *reg)
+                            unsigned long *reg)
 {
        struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
        struct kvm_s390_local_interrupt *li;
index f4b6124fdb75d1308d6b112081fab60cd039da9d..f28c43d2f61dd6b679b8cc8afb14c12e57e33273 100644 (file)
@@ -72,7 +72,8 @@ void arch_release_hugepage(struct page *page)
        page[1].index = 0;
 }
 
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+                       unsigned long addr, unsigned long sz)
 {
        pgd_t *pgdp;
        pud_t *pudp;
@@ -119,6 +120,11 @@ int pmd_huge(pmd_t pmd)
        return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                             pmd_t *pmdp, int write)
 {
index 388cc742005544b05747d32a485e88c5c37cf5a6..4993b0f594eb86ac0b5604e06112b36de20e492a 100644 (file)
@@ -42,38 +42,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
 
-void show_mem(void)
-{
-       unsigned long i, total = 0, reserved = 0;
-       unsigned long shared = 0, cached = 0;
-       unsigned long flags;
-       struct page *page;
-       pg_data_t *pgdat;
-
-       printk("Mem-info:\n");
-       show_free_areas();
-       for_each_online_pgdat(pgdat) {
-               pgdat_resize_lock(pgdat, &flags);
-               for (i = 0; i < pgdat->node_spanned_pages; i++) {
-                       if (!pfn_valid(pgdat->node_start_pfn + i))
-                               continue;
-                       page = pfn_to_page(pgdat->node_start_pfn + i);
-                       total++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
-               }
-               pgdat_resize_unlock(pgdat, &flags);
-       }
-       printk("%ld pages of RAM\n", total);
-       printk("%ld reserved pages\n", reserved);
-       printk("%ld pages shared\n", shared);
-       printk("%ld pages swap cached\n", cached);
-}
-
 /*
  * paging_init() sets up the page tables
  */
index 3e7384f4619c9cd97002fd7264240aa69c7ba3ff..0b88dc462d731c7c8c46525e3fa71eeb53e46cfd 100644 (file)
@@ -8,8 +8,10 @@ mainmenu "Linux/SuperH Kernel Configuration"
 config SUPERH
        def_bool y
        select EMBEDDED
+       select HAVE_CLK
        select HAVE_IDE
        select HAVE_OPROFILE
+       select HAVE_GENERIC_DMA_COHERENT
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
@@ -476,6 +478,10 @@ config SH_RTS7751R2D
          Select RTS7751R2D if configuring for a Renesas Technology
          Sales SH-Graphics board.
 
+config SH_RSK7203
+       bool "RSK7203"
+       depends on CPU_SUBTYPE_SH7203
+
 config SH_SDK7780
        bool "SDK7780R3"
        depends on CPU_SUBTYPE_SH7780
@@ -490,6 +496,21 @@ config SH_HIGHLANDER
        select SYS_SUPPORTS_PCI
        select IO_TRAPPED
 
+config SH_SH7785LCR
+       bool "SH7785LCR"
+       depends on CPU_SUBTYPE_SH7785
+       select SYS_SUPPORTS_PCI
+       select IO_TRAPPED
+
+config SH_SH7785LCR_29BIT_PHYSMAPS
+       bool "SH7785LCR 29bit physmaps"
+       depends on SH_SH7785LCR
+       default y
+       help
+         This board has 2 physical memory maps. It can be changed with
+         DIP switch(S2-5). If you set the DIP switch for S2-5 = ON,
+         you can access all on-board device in 29bit address mode.
+
 config SH_MIGOR
        bool "Migo-R"
        depends on CPU_SUBTYPE_SH7722
@@ -497,6 +518,20 @@ config SH_MIGOR
          Select Migo-R if configuring for the SH7722 Migo-R platform
           by Renesas System Solutions Asia Pte. Ltd.
 
+config SH_AP325RXA
+       bool "AP-325RXA"
+       depends on CPU_SUBTYPE_SH7723
+       help
+         Renesas "AP-325RXA" support.
+         Compatible with ALGO SYSTEM CO.,LTD. "AP-320A"
+
+config SH_SH7763RDP
+       bool "SH7763RDP"
+       depends on CPU_SUBTYPE_SH7763
+       help
+         Select SH7763RDP if configuring for a Renesas SH7763
+         evaluation board.
+
 config SH_EDOSK7705
        bool "EDOSK7705"
        depends on CPU_SUBTYPE_SH7705
@@ -558,6 +593,7 @@ endmenu
 source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
 source "arch/sh/boards/renesas/r7780rp/Kconfig"
 source "arch/sh/boards/renesas/sdk7780/Kconfig"
+source "arch/sh/boards/renesas/migor/Kconfig"
 source "arch/sh/boards/magicpanelr2/Kconfig"
 
 menu "Timer and clock configuration"
index 0f4549860226636a888e0321f4df402a135a1b19..36f4b1f7066d193f9290e11a88a89bd5dc4cdb5d 100644 (file)
@@ -36,7 +36,8 @@ config EARLY_SCIF_CONSOLE_PORT
        default "0xff804000" if CPU_SUBTYPE_MXG
        default "0xffc30000" if CPU_SUBTYPE_SHX3
        default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
-                               CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366
+                               CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \
+                               CPU_SUBTYPE_SH7343
        default "0xffe80000" if CPU_SH4
        default "0xffea0000" if CPU_SUBTYPE_SH7785
        default "0xfffe8000" if CPU_SUBTYPE_SH7203
index fb7b1b15e3923f2eee2ba30ac67c30fc6d2ef746..c627e45c4df74b9abec100067a4fec6895117a93 100644 (file)
@@ -121,6 +121,10 @@ machdir-$(CONFIG_SH_HIGHLANDER)                    += renesas/r7780rp
 machdir-$(CONFIG_SH_MIGOR)                     += renesas/migor
 machdir-$(CONFIG_SH_SDK7780)                   += renesas/sdk7780
 machdir-$(CONFIG_SH_X3PROTO)                   += renesas/x3proto
+machdir-$(CONFIG_SH_RSK7203)                   += renesas/rsk7203
+machdir-$(CONFIG_SH_AP325RXA)                  += renesas/ap325rxa
+machdir-$(CONFIG_SH_SH7763RDP)                 += renesas/sh7763rdp
+machdir-$(CONFIG_SH_SH7785LCR)                 += renesas/sh7785lcr
 machdir-$(CONFIG_SH_SH4202_MICRODEV)           += superh/microdev
 machdir-$(CONFIG_SH_LANDISK)                   += landisk
 machdir-$(CONFIG_SH_TITAN)                     += titan
index b3a876a3b85978363e7b9de6ccf5a464a026b55c..a7433685798d83b26695c5530de6750f1dcdc377 100644 (file)
@@ -30,7 +30,7 @@
  *
  * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch.
  */
-void aica_rtc_gettimeofday(struct timespec *ts)
+static void aica_rtc_gettimeofday(struct timespec *ts)
 {
        unsigned long val1, val2;
 
@@ -54,7 +54,7 @@ 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)
+static int aica_rtc_settimeofday(const time_t secs)
 {
        unsigned long val1, val2;
        unsigned long adj = secs + TWENTY_YEARS;
diff --git a/arch/sh/boards/renesas/ap325rxa/Makefile b/arch/sh/boards/renesas/ap325rxa/Makefile
new file mode 100644 (file)
index 0000000..f663768
--- /dev/null
@@ -0,0 +1 @@
+obj-y  := setup.o
diff --git a/arch/sh/boards/renesas/ap325rxa/setup.c b/arch/sh/boards/renesas/ap325rxa/setup.c
new file mode 100644 (file)
index 0000000..7fa7446
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Renesas - AP-325RXA
+ * (Compatible with Algo System ., LTD. - AP-320A)
+ *
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ * Author : Yusuke Goda <goda.yuske@renesas.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/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/smc911x.h>
+#include <media/soc_camera_platform.h>
+#include <media/sh_mobile_ceu.h>
+#include <asm/sh_mobile_lcdc.h>
+#include <asm/io.h>
+#include <asm/clock.h>
+
+static struct smc911x_platdata smc911x_info = {
+       .flags = SMC911X_USE_32BIT,
+       .irq_flags = IRQF_TRIGGER_LOW,
+};
+
+static struct resource smc9118_resources[] = {
+       [0] = {
+               .start  = 0xb6080000,
+               .end    = 0xb60fffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 35,
+               .end    = 35,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device smc9118_device = {
+       .name           = "smc911x",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(smc9118_resources),
+       .resource       = smc9118_resources,
+       .dev            = {
+               .platform_data = &smc911x_info,
+       },
+};
+
+static struct mtd_partition ap325rxa_nor_flash_partitions[] = {
+       {
+                .name = "uboot",
+                .offset = 0,
+                .size = (1 * 1024 * 1024),
+                .mask_flags = MTD_WRITEABLE,   /* Read-only */
+       }, {
+                .name = "kernel",
+                .offset = MTDPART_OFS_APPEND,
+                .size = (2 * 1024 * 1024),
+       }, {
+                .name = "other",
+                .offset = MTDPART_OFS_APPEND,
+                .size = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct physmap_flash_data ap325rxa_nor_flash_data = {
+       .width          = 2,
+       .parts          = ap325rxa_nor_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(ap325rxa_nor_flash_partitions),
+};
+
+static struct resource ap325rxa_nor_flash_resources[] = {
+       [0] = {
+               .name   = "NOR Flash",
+               .start  = 0x00000000,
+               .end    = 0x00ffffff,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device ap325rxa_nor_flash_device = {
+       .name           = "physmap-flash",
+       .resource       = ap325rxa_nor_flash_resources,
+       .num_resources  = ARRAY_SIZE(ap325rxa_nor_flash_resources),
+       .dev            = {
+               .platform_data = &ap325rxa_nor_flash_data,
+       },
+};
+
+#define FPGA_LCDREG    0xB4100180
+#define FPGA_BKLREG    0xB4100212
+#define FPGA_LCDREG_VAL        0x0018
+#define PORT_PHCR      0xA405010E
+#define PORT_PLCR      0xA4050114
+#define PORT_PMCR      0xA4050116
+#define PORT_PRCR      0xA405011C
+#define PORT_PSCR      0xA405011E
+#define PORT_PZCR      0xA405014C
+#define PORT_HIZCRA    0xA4050158
+#define PORT_MSELCRB   0xA4050182
+#define PORT_PSDR      0xA405013E
+#define PORT_PZDR      0xA405016C
+#define PORT_PSELD     0xA4050154
+
+static void ap320_wvga_power_on(void *board_data)
+{
+       msleep(100);
+
+       /* ASD AP-320/325 LCD ON */
+       ctrl_outw(FPGA_LCDREG_VAL, FPGA_LCDREG);
+
+       /* backlight */
+       ctrl_outw((ctrl_inw(PORT_PSCR) & ~0x00C0) | 0x40, PORT_PSCR);
+       ctrl_outb(ctrl_inb(PORT_PSDR) & ~0x08, PORT_PSDR);
+       ctrl_outw(0x100, FPGA_BKLREG);
+}
+
+static struct sh_mobile_lcdc_info lcdc_info = {
+       .clock_source = LCDC_CLK_EXTERNAL,
+       .ch[0] = {
+               .chan = LCDC_CHAN_MAINLCD,
+               .bpp = 16,
+               .interface_type = RGB18,
+               .clock_divider = 1,
+               .lcd_cfg = {
+                       .name = "LB070WV1",
+                       .xres = 800,
+                       .yres = 480,
+                       .left_margin = 40,
+                       .right_margin = 160,
+                       .hsync_len = 8,
+                       .upper_margin = 63,
+                       .lower_margin = 80,
+                       .vsync_len = 1,
+                       .sync = 0, /* hsync and vsync are active low */
+               },
+               .board_cfg = {
+                       .display_on = ap320_wvga_power_on,
+               },
+       }
+};
+
+static struct resource lcdc_resources[] = {
+       [0] = {
+               .name   = "LCDC",
+               .start  = 0xfe940000, /* P4-only space */
+               .end    = 0xfe941fff,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device lcdc_device = {
+       .name           = "sh_mobile_lcdc_fb",
+       .num_resources  = ARRAY_SIZE(lcdc_resources),
+       .resource       = lcdc_resources,
+       .dev            = {
+               .platform_data  = &lcdc_info,
+       },
+};
+
+static unsigned char camera_ncm03j_magic[] =
+{
+       0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8,
+       0x1D, 0x00, 0x1E, 0x8A, 0x21, 0x00, 0x33, 0x36,
+       0x36, 0x60, 0x37, 0x08, 0x3B, 0x31, 0x44, 0x0F,
+       0x46, 0xF0, 0x4B, 0x28, 0x4C, 0x21, 0x4D, 0x55,
+       0x4E, 0x1B, 0x4F, 0xC7, 0x50, 0xFC, 0x51, 0x12,
+       0x58, 0x02, 0x66, 0xC0, 0x67, 0x46, 0x6B, 0xA0,
+       0x6C, 0x34, 0x7E, 0x25, 0x7F, 0x25, 0x8D, 0x0F,
+       0x92, 0x40, 0x93, 0x04, 0x94, 0x26, 0x95, 0x0A,
+       0x99, 0x03, 0x9A, 0xF0, 0x9B, 0x14, 0x9D, 0x7A,
+       0xC5, 0x02, 0xD6, 0x07, 0x59, 0x00, 0x5A, 0x1A,
+       0x5B, 0x2A, 0x5C, 0x37, 0x5D, 0x42, 0x5E, 0x56,
+       0xC8, 0x00, 0xC9, 0x1A, 0xCA, 0x2A, 0xCB, 0x37,
+       0xCC, 0x42, 0xCD, 0x56, 0xCE, 0x00, 0xCF, 0x1A,
+       0xD0, 0x2A, 0xD1, 0x37, 0xD2, 0x42, 0xD3, 0x56,
+       0x5F, 0x68, 0x60, 0x87, 0x61, 0xA3, 0x62, 0xBC,
+       0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
+};
+
+static int camera_set_capture(struct soc_camera_platform_info *info,
+                             int enable)
+{
+       struct i2c_adapter *a = i2c_get_adapter(0);
+       struct i2c_msg msg;
+       int ret = 0;
+       int i;
+
+       if (!enable)
+               return 0; /* no disable for now */
+
+       for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
+               u_int8_t buf[8];
+
+               msg.addr = 0x6e;
+               msg.buf = buf;
+               msg.len = 2;
+               msg.flags = 0;
+
+               buf[0] = camera_ncm03j_magic[i];
+               buf[1] = camera_ncm03j_magic[i + 1];
+
+               ret = (ret < 0) ? ret : i2c_transfer(a, &msg, 1);
+       }
+
+       return ret;
+}
+
+static struct soc_camera_platform_info camera_info = {
+       .iface = 0,
+       .format_name = "UYVY",
+       .format_depth = 16,
+       .format = {
+               .pixelformat = V4L2_PIX_FMT_UYVY,
+               .colorspace = V4L2_COLORSPACE_SMPTE170M,
+               .width = 640,
+               .height = 480,
+       },
+       .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
+       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
+       .set_capture = camera_set_capture,
+};
+
+static struct platform_device camera_device = {
+       .name           = "soc_camera_platform",
+       .dev            = {
+               .platform_data  = &camera_info,
+       },
+};
+
+static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
+       .flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
+       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
+};
+
+static struct resource ceu_resources[] = {
+       [0] = {
+               .name   = "CEU",
+               .start  = 0xfe910000,
+               .end    = 0xfe91009f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 52,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device ceu_device = {
+       .name           = "sh_mobile_ceu",
+       .num_resources  = ARRAY_SIZE(ceu_resources),
+       .resource       = ceu_resources,
+       .dev            = {
+               .platform_data  = &sh_mobile_ceu_info,
+       },
+};
+
+static struct platform_device *ap325rxa_devices[] __initdata = {
+       &smc9118_device,
+       &ap325rxa_nor_flash_device,
+       &lcdc_device,
+       &ceu_device,
+       &camera_device,
+};
+
+static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = {
+};
+
+static int __init ap325rxa_devices_setup(void)
+{
+       clk_always_enable("mstp200"); /* LCDC */
+       clk_always_enable("mstp203"); /* CEU */
+
+       platform_resource_setup_memory(&ceu_device, "ceu", 4 << 20);
+
+       i2c_register_board_info(0, ap325rxa_i2c_devices,
+                               ARRAY_SIZE(ap325rxa_i2c_devices));
+       return platform_add_devices(ap325rxa_devices,
+                               ARRAY_SIZE(ap325rxa_devices));
+}
+device_initcall(ap325rxa_devices_setup);
+
+static void __init ap325rxa_setup(char **cmdline_p)
+{
+       /* LCDC configuration */
+       ctrl_outw(ctrl_inw(PORT_PHCR) & ~0xffff, PORT_PHCR);
+       ctrl_outw(ctrl_inw(PORT_PLCR) & ~0xffff, PORT_PLCR);
+       ctrl_outw(ctrl_inw(PORT_PMCR) & ~0xffff, PORT_PMCR);
+       ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x03ff, PORT_PRCR);
+       ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01C0, PORT_HIZCRA);
+
+       /* CEU */
+       ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0001, PORT_MSELCRB);
+       ctrl_outw(ctrl_inw(PORT_PSELD) & ~0x0003, PORT_PSELD);
+       ctrl_outw((ctrl_inw(PORT_PZCR) & ~0xff00) | 0x5500, PORT_PZCR);
+       ctrl_outb((ctrl_inb(PORT_PZDR) & ~0xf0) | 0x20, PORT_PZDR);
+}
+
+static struct sh_machine_vector mv_ap325rxa __initmv = {
+       .mv_name = "AP-325RXA",
+       .mv_setup = ap325rxa_setup,
+};
diff --git a/arch/sh/boards/renesas/migor/Kconfig b/arch/sh/boards/renesas/migor/Kconfig
new file mode 100644 (file)
index 0000000..a7b3b72
--- /dev/null
@@ -0,0 +1,15 @@
+if SH_MIGOR
+
+choice
+       prompt "Migo-R LCD Panel Board Selection"
+       default SH_MIGOR_QVGA
+
+config SH_MIGOR_QVGA
+       bool "QVGA (320x240)"
+
+config SH_MIGOR_RTA_WVGA
+       bool "RTA WVGA (800x480)"
+
+endchoice
+
+endif
index 77037567633b674f1a312fd190db2d6eb9013ec3..5f231dd25c0e730fe5f74153eeb144fdcdb0d0cb 100644 (file)
@@ -1 +1,2 @@
 obj-y   := setup.o
+obj-$(CONFIG_SH_MIGOR_QVGA)    +=  lcd_qvga.o
diff --git a/arch/sh/boards/renesas/migor/lcd_qvga.c b/arch/sh/boards/renesas/migor/lcd_qvga.c
new file mode 100644 (file)
index 0000000..6e96095
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Support for SuperH MigoR Quarter VGA LCD Panel
+ *
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * Based on lcd_powertip.c from Kenati Technologies Pvt Ltd.
+ * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.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/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/sh_mobile_lcdc.h>
+#include <asm/migor.h>
+
+/* LCD Module is a PH240320T according to board schematics. This module
+ * is made up of a 240x320 LCD hooked up to a R61505U (or HX8347-A01?)
+ * Driver IC. This IC is connected to the SH7722 built-in LCDC using a
+ * SYS-80 interface configured in 16 bit mode.
+ *
+ * Index 0: "Device Code Read" returns 0x1505.
+ */
+
+static void reset_lcd_module(void)
+{
+       ctrl_outb(ctrl_inb(PORT_PHDR) & ~0x04, PORT_PHDR);
+       mdelay(2);
+       ctrl_outb(ctrl_inb(PORT_PHDR) | 0x04, PORT_PHDR);
+       mdelay(1);
+}
+
+/* DB0-DB7 are connected to D1-D8, and DB8-DB15 to D10-D17 */
+
+static unsigned long adjust_reg18(unsigned short data)
+{
+       unsigned long tmp1, tmp2;
+
+       tmp1 = (data<<1 | 0x00000001) & 0x000001FF;
+       tmp2 = (data<<2 | 0x00000200) & 0x0003FE00;
+       return tmp1 | tmp2;
+}
+
+static void write_reg(void *sys_ops_handle,
+                      struct sh_mobile_lcdc_sys_bus_ops *sys_ops,
+                      unsigned short reg, unsigned short data)
+{
+       sys_ops->write_index(sys_ops_handle, adjust_reg18(reg << 8 | data));
+}
+
+static void write_reg16(void *sys_ops_handle,
+                       struct sh_mobile_lcdc_sys_bus_ops *sys_ops,
+                       unsigned short reg, unsigned short data)
+{
+       sys_ops->write_index(sys_ops_handle, adjust_reg18(reg));
+       sys_ops->write_data(sys_ops_handle, adjust_reg18(data));
+}
+
+static unsigned long read_reg16(void *sys_ops_handle,
+                               struct sh_mobile_lcdc_sys_bus_ops *sys_ops,
+                               unsigned short reg)
+{
+       unsigned long data;
+
+       sys_ops->write_index(sys_ops_handle, adjust_reg18(reg));
+       data = sys_ops->read_data(sys_ops_handle);
+       return ((data >> 1) & 0xff) | ((data >> 2) & 0xff00);
+}
+
+static void migor_lcd_qvga_seq(void *sys_ops_handle,
+                              struct sh_mobile_lcdc_sys_bus_ops *sys_ops,
+                              unsigned short const *data, int no_data)
+{
+       int i;
+
+       for (i = 0; i < no_data; i += 2)
+               write_reg16(sys_ops_handle, sys_ops, data[i], data[i + 1]);
+}
+
+static const unsigned short sync_data[] = {
+       0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const unsigned short magic0_data[] = {
+       0x0060, 0x2700, 0x0008, 0x0808, 0x0090, 0x001A, 0x0007, 0x0001,
+       0x0017, 0x0001, 0x0019, 0x0000, 0x0010, 0x17B0, 0x0011, 0x0116,
+       0x0012, 0x0198, 0x0013, 0x1400, 0x0029, 0x000C, 0x0012, 0x01B8,
+};
+
+static const unsigned short magic1_data[] = {
+       0x0030, 0x0307, 0x0031, 0x0303, 0x0032, 0x0603, 0x0033, 0x0202,
+       0x0034, 0x0202, 0x0035, 0x0202, 0x0036, 0x1F1F, 0x0037, 0x0303,
+       0x0038, 0x0303, 0x0039, 0x0603, 0x003A, 0x0202, 0x003B, 0x0102,
+       0x003C, 0x0204, 0x003D, 0x0000, 0x0001, 0x0100, 0x0002, 0x0300,
+       0x0003, 0x5028, 0x0020, 0x00ef, 0x0021, 0x0000, 0x0004, 0x0000,
+       0x0009, 0x0000, 0x000A, 0x0008, 0x000C, 0x0000, 0x000D, 0x0000,
+       0x0015, 0x8000,
+};
+
+static const unsigned short magic2_data[] = {
+       0x0061, 0x0001, 0x0092, 0x0100, 0x0093, 0x0001, 0x0007, 0x0021,
+};
+
+static const unsigned short magic3_data[] = {
+       0x0010, 0x16B0, 0x0011, 0x0111, 0x0007, 0x0061,
+};
+
+int migor_lcd_qvga_setup(void *board_data, void *sohandle,
+                        struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+       unsigned long xres = 320;
+       unsigned long yres = 240;
+       int k;
+
+       reset_lcd_module();
+       migor_lcd_qvga_seq(sohandle, so, sync_data, ARRAY_SIZE(sync_data));
+
+       if (read_reg16(sohandle, so, 0) != 0x1505)
+               return -ENODEV;
+
+       pr_info("Migo-R QVGA LCD Module detected.\n");
+
+       migor_lcd_qvga_seq(sohandle, so, sync_data, ARRAY_SIZE(sync_data));
+       write_reg16(sohandle, so, 0x00A4, 0x0001);
+       mdelay(10);
+
+       migor_lcd_qvga_seq(sohandle, so, magic0_data, ARRAY_SIZE(magic0_data));
+       mdelay(100);
+
+       migor_lcd_qvga_seq(sohandle, so, magic1_data, ARRAY_SIZE(magic1_data));
+       write_reg16(sohandle, so, 0x0050, 0xef - (yres - 1));
+       write_reg16(sohandle, so, 0x0051, 0x00ef);
+       write_reg16(sohandle, so, 0x0052, 0x0000);
+       write_reg16(sohandle, so, 0x0053, xres - 1);
+
+       migor_lcd_qvga_seq(sohandle, so, magic2_data, ARRAY_SIZE(magic2_data));
+       mdelay(10);
+
+       migor_lcd_qvga_seq(sohandle, so, magic3_data, ARRAY_SIZE(magic3_data));
+       mdelay(40);
+
+       /* clear GRAM to avoid displaying garbage */
+
+       write_reg16(sohandle, so, 0x0020, 0x0000); /* horiz addr */
+       write_reg16(sohandle, so, 0x0021, 0x0000); /* vert addr */
+
+       for (k = 0; k < (xres * 256); k++) /* yes, 256 words per line */
+               write_reg16(sohandle, so, 0x0022, 0x0000);
+
+       write_reg16(sohandle, so, 0x0020, 0x0000); /* reset horiz addr */
+       write_reg16(sohandle, so, 0x0021, 0x0000); /* reset vert addr */
+       write_reg16(sohandle, so, 0x0007, 0x0173);
+       mdelay(40);
+
+       /* enable display */
+       write_reg(sohandle, so, 0x00, 0x22);
+       mdelay(100);
+       return 0;
+}
index 963c99322095176767963c31cb6feee68573c3db..7bd365ad2d060e7bd6ccc1ee80ddeabe3019a3e8 100644 (file)
 #include <linux/mtd/nand.h>
 #include <linux/i2c.h>
 #include <linux/smc91x.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <media/soc_camera_platform.h>
+#include <media/sh_mobile_ceu.h>
+#include <asm/clock.h>
 #include <asm/machvec.h>
 #include <asm/io.h>
 #include <asm/sh_keysc.h>
+#include <asm/sh_mobile_lcdc.h>
 #include <asm/migor.h>
 
 /* Address     IRQ  Size  Bus  Description
@@ -198,14 +204,237 @@ static struct platform_device migor_nand_flash_device = {
        }
 };
 
+static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
+#ifdef CONFIG_SH_MIGOR_RTA_WVGA
+       .clock_source = LCDC_CLK_BUS,
+       .ch[0] = {
+               .chan = LCDC_CHAN_MAINLCD,
+               .bpp = 16,
+               .interface_type = RGB16,
+               .clock_divider = 2,
+               .lcd_cfg = {
+                       .name = "LB070WV1",
+                       .xres = 800,
+                       .yres = 480,
+                       .left_margin = 64,
+                       .right_margin = 16,
+                       .hsync_len = 120,
+                       .upper_margin = 1,
+                       .lower_margin = 17,
+                       .vsync_len = 2,
+                       .sync = 0,
+               },
+       }
+#endif
+#ifdef CONFIG_SH_MIGOR_QVGA
+       .clock_source = LCDC_CLK_PERIPHERAL,
+       .ch[0] = {
+               .chan = LCDC_CHAN_MAINLCD,
+               .bpp = 16,
+               .interface_type = SYS16A,
+               .clock_divider = 10,
+               .lcd_cfg = {
+                       .name = "PH240320T",
+                       .xres = 320,
+                       .yres = 240,
+                       .left_margin = 0,
+                       .right_margin = 16,
+                       .hsync_len = 8,
+                       .upper_margin = 1,
+                       .lower_margin = 17,
+                       .vsync_len = 2,
+                       .sync = FB_SYNC_HOR_HIGH_ACT,
+               },
+               .board_cfg = {
+                       .setup_sys = migor_lcd_qvga_setup,
+               },
+               .sys_bus_cfg = {
+                       .ldmt2r = 0x06000a09,
+                       .ldmt3r = 0x180e3418,
+               },
+       }
+#endif
+};
+
+static struct resource migor_lcdc_resources[] = {
+       [0] = {
+               .name   = "LCDC",
+               .start  = 0xfe940000, /* P4-only space */
+               .end    = 0xfe941fff,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device migor_lcdc_device = {
+       .name           = "sh_mobile_lcdc_fb",
+       .num_resources  = ARRAY_SIZE(migor_lcdc_resources),
+       .resource       = migor_lcdc_resources,
+       .dev    = {
+               .platform_data  = &sh_mobile_lcdc_info,
+       },
+};
+
+static struct clk *camera_clk;
+
+static void camera_power_on(void)
+{
+       unsigned char value;
+
+       camera_clk = clk_get(NULL, "video_clk");
+       clk_set_rate(camera_clk, 24000000);
+       clk_enable(camera_clk); /* start VIO_CKO */
+
+       mdelay(10);
+       value = ctrl_inb(PORT_PTDR);
+       value &= ~0x09;
+#ifndef CONFIG_SH_MIGOR_RTA_WVGA
+       value |= 0x01;
+#endif
+       ctrl_outb(value, PORT_PTDR);
+       mdelay(10);
+
+       ctrl_outb(value | 8, PORT_PTDR);
+}
+
+static void camera_power_off(void)
+{
+       clk_disable(camera_clk); /* stop VIO_CKO */
+       clk_put(camera_clk);
+
+       ctrl_outb(ctrl_inb(PORT_PTDR) & ~0x08, PORT_PTDR);
+}
+
+static unsigned char camera_ov772x_magic[] =
+{
+       0x09, 0x01, 0x0c, 0x10, 0x0d, 0x41, 0x0e, 0x01,
+       0x12, 0x00, 0x13, 0x8F, 0x14, 0x4A, 0x15, 0x00,
+       0x16, 0x00, 0x17, 0x23, 0x18, 0xa0, 0x19, 0x07,
+       0x1a, 0xf0, 0x1b, 0x40, 0x1f, 0x00, 0x20, 0x10,
+       0x22, 0xff, 0x23, 0x01, 0x28, 0x00, 0x29, 0xa0,
+       0x2a, 0x00, 0x2b, 0x00, 0x2c, 0xf0, 0x2d, 0x00,
+       0x2e, 0x00, 0x30, 0x80, 0x31, 0x60, 0x32, 0x00,
+       0x33, 0x00, 0x34, 0x00, 0x3d, 0x80, 0x3e, 0xe2,
+       0x3f, 0x1f, 0x42, 0x80, 0x43, 0x80, 0x44, 0x80,
+       0x45, 0x80, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00,
+       0x49, 0x50, 0x4a, 0x30, 0x4b, 0x50, 0x4c, 0x50,
+       0x4d, 0x00, 0x4e, 0xef, 0x4f, 0x10, 0x50, 0x60,
+       0x51, 0x00, 0x52, 0x00, 0x53, 0x24, 0x54, 0x7a,
+       0x55, 0xfc, 0x62, 0xff, 0x63, 0xf0, 0x64, 0x1f,
+       0x65, 0x00, 0x66, 0x10, 0x67, 0x00, 0x68, 0x00,
+       0x69, 0x5c, 0x6a, 0x11, 0x6b, 0xa2, 0x6c, 0x01,
+       0x6d, 0x50, 0x6e, 0x80, 0x6f, 0x80, 0x70, 0x0f,
+       0x71, 0x00, 0x72, 0x00, 0x73, 0x0f, 0x74, 0x0f,
+       0x75, 0xff, 0x78, 0x10, 0x79, 0x70, 0x7a, 0x70,
+       0x7b, 0xf0, 0x7c, 0xf0, 0x7d, 0xf0, 0x7e, 0x0e,
+       0x7f, 0x1a, 0x80, 0x31, 0x81, 0x5a, 0x82, 0x69,
+       0x83, 0x75, 0x84, 0x7e, 0x85, 0x88, 0x86, 0x8f,
+       0x87, 0x96, 0x88, 0xa3, 0x89, 0xaf, 0x8a, 0xc4,
+       0x8b, 0xd7, 0x8c, 0xe8, 0x8d, 0x20, 0x8e, 0x00,
+       0x8f, 0x00, 0x90, 0x08, 0x91, 0x10, 0x92, 0x1f,
+       0x93, 0x01, 0x94, 0x2c, 0x95, 0x24, 0x96, 0x08,
+       0x97, 0x14, 0x98, 0x24, 0x99, 0x38, 0x9a, 0x9e,
+       0x9b, 0x00, 0x9c, 0x40, 0x9e, 0x11, 0x9f, 0x02,
+       0xa0, 0x00, 0xa1, 0x40, 0xa2, 0x40, 0xa3, 0x06,
+       0xa4, 0x00, 0xa6, 0x00, 0xa7, 0x40, 0xa8, 0x40,
+       0xa9, 0x80, 0xaa, 0x80, 0xab, 0x06, 0xac, 0xff,
+       0x12, 0x06, 0x64, 0x3f, 0x12, 0x46, 0x17, 0x3f,
+       0x18, 0x50, 0x19, 0x03, 0x1a, 0x78, 0x29, 0x50,
+       0x2c, 0x78,
+};
+
+static int ov772x_set_capture(struct soc_camera_platform_info *info,
+                             int enable)
+{
+       struct i2c_adapter *a = i2c_get_adapter(0);
+       struct i2c_msg msg;
+       int ret = 0;
+       int i;
+
+       if (!enable)
+               return 0; /* camera_power_off() is enough */
+
+       for (i = 0; i < ARRAY_SIZE(camera_ov772x_magic); i += 2) {
+               u_int8_t buf[8];
+
+               msg.addr = 0x21;
+               msg.buf = buf;
+               msg.len = 2;
+               msg.flags = 0;
+
+               buf[0] = camera_ov772x_magic[i];
+               buf[1] = camera_ov772x_magic[i + 1];
+
+               ret = (ret < 0) ? ret : i2c_transfer(a, &msg, 1);
+       }
+
+       return ret;
+}
+
+static struct soc_camera_platform_info ov772x_info = {
+       .iface = 0,
+       .format_name = "RGB565",
+       .format_depth = 16,
+       .format = {
+               .pixelformat = V4L2_PIX_FMT_RGB565,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .width = 320,
+               .height = 240,
+       },
+       .bus_param =  SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
+       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
+       .set_capture = ov772x_set_capture,
+};
+
+static struct platform_device migor_camera_device = {
+       .name           = "soc_camera_platform",
+       .dev    = {
+               .platform_data  = &ov772x_info,
+       },
+};
+
+static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
+       .flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \
+       | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH,
+       .enable_camera = camera_power_on,
+       .disable_camera = camera_power_off,
+};
+
+static struct resource migor_ceu_resources[] = {
+       [0] = {
+               .name   = "CEU",
+               .start  = 0xfe910000,
+               .end    = 0xfe91009f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 52,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device migor_ceu_device = {
+       .name           = "sh_mobile_ceu",
+       .num_resources  = ARRAY_SIZE(migor_ceu_resources),
+       .resource       = migor_ceu_resources,
+       .dev    = {
+               .platform_data  = &sh_mobile_ceu_info,
+       },
+};
+
 static struct platform_device *migor_devices[] __initdata = {
        &smc91x_eth_device,
        &sh_keysc_device,
+       &migor_lcdc_device,
+       &migor_ceu_device,
+       &migor_camera_device,
        &migor_nor_flash_device,
        &migor_nand_flash_device,
 };
 
-static struct i2c_board_info __initdata migor_i2c_devices[] = {
+static struct i2c_board_info migor_i2c_devices[] = {
        {
                I2C_BOARD_INFO("rs5c372b", 0x32),
        },
@@ -217,6 +446,12 @@ static struct i2c_board_info __initdata migor_i2c_devices[] = {
 
 static int __init migor_devices_setup(void)
 {
+       clk_always_enable("mstp214"); /* KEYSC */
+       clk_always_enable("mstp200"); /* LCDC */
+       clk_always_enable("mstp203"); /* CEU */
+
+       platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
+
        i2c_register_board_info(0, migor_i2c_devices,
                                ARRAY_SIZE(migor_i2c_devices));
  
@@ -235,20 +470,51 @@ static void __init migor_setup(char **cmdline_p)
        ctrl_outw(ctrl_inw(PORT_PSELA) & ~0x4100, PORT_PSELA);
        ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
        ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
-       ctrl_outl(ctrl_inl(MSTPCR2) & ~0x00004000, MSTPCR2);
 
        /* NAND Flash */
        ctrl_outw(ctrl_inw(PORT_PXCR) & 0x0fff, PORT_PXCR);
        ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x00000600) | 0x00000200,
                  BSC_CS6ABCR);
 
-       /* I2C */
-       ctrl_outl(ctrl_inl(MSTPCR1) & ~0x00000200, MSTPCR1);
-
        /* Touch Panel - Enable IRQ6 */
        ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR);
        ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA);
        ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC);
+
+#ifdef CONFIG_SH_MIGOR_RTA_WVGA
+       /* LCDC - WVGA - Enable RGB Interface signals */
+       ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
+       ctrl_outw(0x0000, PORT_PHCR);
+       ctrl_outw(0x0000, PORT_PLCR);
+       ctrl_outw(0x0000, PORT_PMCR);
+       ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x000f, PORT_PRCR);
+       ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x000d) | 0x0400, PORT_PSELD);
+       ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0100, PORT_MSELCRB);
+       ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
+#endif
+#ifdef CONFIG_SH_MIGOR_QVGA
+       /* LCDC - QVGA - Enable SYS Interface signals */
+       ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
+       ctrl_outw((ctrl_inw(PORT_PHCR) & ~0xcfff) | 0x0010, PORT_PHCR);
+       ctrl_outw(0x0000, PORT_PLCR);
+       ctrl_outw(0x0000, PORT_PMCR);
+       ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x030f, PORT_PRCR);
+       ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x0001) | 0x0420, PORT_PSELD);
+       ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x0100, PORT_MSELCRB);
+       ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
+#endif
+
+       /* CEU */
+       ctrl_outw((ctrl_inw(PORT_PTCR) & ~0x03c3) | 0x0051, PORT_PTCR);
+       ctrl_outw(ctrl_inw(PORT_PUCR) & ~0x03ff, PORT_PUCR);
+       ctrl_outw(ctrl_inw(PORT_PVCR) & ~0x03ff, PORT_PVCR);
+       ctrl_outw(ctrl_inw(PORT_PWCR) & ~0x3c00, PORT_PWCR);
+       ctrl_outw(ctrl_inw(PORT_PSELC) | 0x0001, PORT_PSELC);
+       ctrl_outw(ctrl_inw(PORT_PSELD) & ~0x2000, PORT_PSELD);
+       ctrl_outw(ctrl_inw(PORT_PSELE) | 0x000f, PORT_PSELE);
+       ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x2200, PORT_MSELCRB);
+       ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x0a00, PORT_HIZCRA);
+       ctrl_outw(ctrl_inw(PORT_HIZCRB) & ~0x0003, PORT_HIZCRB);
 }
 
 static struct sh_machine_vector mv_migor __initmv = {
diff --git a/arch/sh/boards/renesas/rsk7203/Makefile b/arch/sh/boards/renesas/rsk7203/Makefile
new file mode 100644 (file)
index 0000000..f663768
--- /dev/null
@@ -0,0 +1 @@
+obj-y  := setup.o
diff --git a/arch/sh/boards/renesas/rsk7203/setup.c b/arch/sh/boards/renesas/rsk7203/setup.c
new file mode 100644 (file)
index 0000000..0bbda04
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Renesas Technology Europe RSK+ 7203 Support.
+ *
+ * Copyright (C) 2008 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/types.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/map.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+
+static struct resource smc911x_resources[] = {
+       [0] = {
+               .start          = 0x24000000,
+               .end            = 0x24000000 + 0x100,
+               .flags          = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start          = 64,
+               .end            = 64,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device smc911x_device = {
+       .name           = "smc911x",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(smc911x_resources),
+       .resource       = smc911x_resources,
+};
+
+static const char *probes[] = { "cmdlinepart", NULL };
+
+static struct mtd_partition *parsed_partitions;
+
+static struct mtd_partition rsk7203_partitions[] = {
+       {
+               .name           = "Bootloader",
+               .offset         = 0x00000000,
+               .size           = 0x00040000,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "Kernel",
+               .offset         = MTDPART_OFS_NXTBLK,
+               .size           = 0x001c0000,
+       }, {
+               .name           = "Flash_FS",
+               .offset         = MTDPART_OFS_NXTBLK,
+               .size           = MTDPART_SIZ_FULL,
+       }
+};
+
+static struct physmap_flash_data flash_data = {
+       .width          = 2,
+};
+
+static struct resource flash_resource = {
+       .start          = 0x20000000,
+       .end            = 0x20400000,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+       .name           = "physmap-flash",
+       .id             = -1,
+       .resource       = &flash_resource,
+       .num_resources  = 1,
+       .dev            = {
+               .platform_data = &flash_data,
+       },
+};
+
+static struct mtd_info *flash_mtd;
+
+static struct map_info rsk7203_flash_map = {
+       .name           = "RSK+ Flash",
+       .size           = 0x400000,
+       .bankwidth      = 2,
+};
+
+static void __init set_mtd_partitions(void)
+{
+       int nr_parts = 0;
+
+       simple_map_init(&rsk7203_flash_map);
+       flash_mtd = do_map_probe("cfi_probe", &rsk7203_flash_map);
+       nr_parts = parse_mtd_partitions(flash_mtd, probes,
+                                       &parsed_partitions, 0);
+       /* If there is no partition table, used the hard coded table */
+       if (nr_parts <= 0) {
+               flash_data.parts = rsk7203_partitions;
+               flash_data.nr_parts = ARRAY_SIZE(rsk7203_partitions);
+       } else {
+               flash_data.nr_parts = nr_parts;
+               flash_data.parts = parsed_partitions;
+       }
+}
+
+
+static struct platform_device *rsk7203_devices[] __initdata = {
+       &smc911x_device,
+       &flash_device,
+};
+
+static int __init rsk7203_devices_setup(void)
+{
+       set_mtd_partitions();
+       return platform_add_devices(rsk7203_devices,
+                                   ARRAY_SIZE(rsk7203_devices));
+}
+device_initcall(rsk7203_devices_setup);
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_rsk7203 __initmv = {
+       .mv_name        = "RSK+7203",
+};
diff --git a/arch/sh/boards/renesas/sh7763rdp/Makefile b/arch/sh/boards/renesas/sh7763rdp/Makefile
new file mode 100644 (file)
index 0000000..f6c0b55
--- /dev/null
@@ -0,0 +1 @@
+obj-y    := setup.o irq.o
diff --git a/arch/sh/boards/renesas/sh7763rdp/irq.c b/arch/sh/boards/renesas/sh7763rdp/irq.c
new file mode 100644 (file)
index 0000000..fd850ba
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/sh/boards/renesas/sh7763rdp/irq.c
+ *
+ * Renesas Solutions SH7763RDP Support.
+ *
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ * Copyright (C) 2008  Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.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/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sh7763rdp.h>
+
+#define INTC_BASE              (0xFFD00000)
+#define INTC_INT2PRI7   (INTC_BASE+0x4001C)
+#define INTC_INT2MSKCR (INTC_BASE+0x4003C)
+#define INTC_INT2MSKCR1        (INTC_BASE+0x400D4)
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_sh7763rdp_IRQ(void)
+{
+       /* GPIO enabled */
+       ctrl_outl(1 << 25, INTC_INT2MSKCR);
+
+       /* enable GPIO interrupts */
+       ctrl_outl((ctrl_inl(INTC_INT2PRI7) & 0xFF00FFFF) | 0x000F0000,
+                 INTC_INT2PRI7);
+
+       /* USBH enabled */
+       ctrl_outl(1 << 17, INTC_INT2MSKCR1);
+
+       /* GETHER enabled */
+       ctrl_outl(1 << 16, INTC_INT2MSKCR1);
+
+       /* DMAC enabled */
+       ctrl_outl(1 << 8, INTC_INT2MSKCR);
+}
diff --git a/arch/sh/boards/renesas/sh7763rdp/setup.c b/arch/sh/boards/renesas/sh7763rdp/setup.c
new file mode 100644 (file)
index 0000000..925f16a
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * linux/arch/sh/boards/renesas/sh7763rdp/setup.c
+ *
+ * Renesas Solutions sh7763rdp board
+ *
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ * Copyright (C) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.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/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/mtd/physmap.h>
+#include <asm/io.h>
+#include <asm/sh7763rdp.h>
+
+/* NOR Flash */
+static struct mtd_partition sh7763rdp_nor_flash_partitions[] = {
+       {
+               .name = "U-Boot",
+               .offset = 0,
+               .size = (2 * 128 * 1024),
+               .mask_flags = MTD_WRITEABLE,    /* Read-only */
+       }, {
+               .name = "Linux-Kernel",
+               .offset = MTDPART_OFS_APPEND,
+               .size = (20 * 128 * 1024),
+       }, {
+               .name = "Root Filesystem",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct physmap_flash_data sh7763rdp_nor_flash_data = {
+       .width = 2,
+       .parts = sh7763rdp_nor_flash_partitions,
+       .nr_parts = ARRAY_SIZE(sh7763rdp_nor_flash_partitions),
+};
+
+static struct resource sh7763rdp_nor_flash_resources[] = {
+       [0] = {
+               .name = "NOR Flash",
+               .start = 0,
+               .end = (64 * 1024 * 1024),
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device sh7763rdp_nor_flash_device = {
+       .name = "physmap-flash",
+       .resource = sh7763rdp_nor_flash_resources,
+       .num_resources = ARRAY_SIZE(sh7763rdp_nor_flash_resources),
+       .dev = {
+               .platform_data = &sh7763rdp_nor_flash_data,
+       },
+};
+
+static struct platform_device *sh7763rdp_devices[] __initdata = {
+       &sh7763rdp_nor_flash_device,
+};
+
+static int __init sh7763rdp_devices_setup(void)
+{
+       return platform_add_devices(sh7763rdp_devices,
+                                   ARRAY_SIZE(sh7763rdp_devices));
+}
+__initcall(sh7763rdp_devices_setup);
+
+static void __init sh7763rdp_setup(char **cmdline_p)
+{
+       /* Board version check */
+       if (ctrl_inw(CPLD_BOARD_ID_ERV_REG) == 0xECB1)
+               printk(KERN_INFO "RTE Standard Configuration\n");
+       else
+               printk(KERN_INFO "RTA Standard Configuration\n");
+
+       /* USB pin select bits (clear bit 5-2 to 0) */
+       ctrl_outw((ctrl_inw(PORT_PSEL2) & 0xFFC3), PORT_PSEL2);
+       /* USBH setup port I controls to other (clear bits 4-9 to 0) */
+       ctrl_outw(ctrl_inw(PORT_PICR) & 0xFC0F, PORT_PICR);
+
+       /* Select USB Host controller */
+       ctrl_outw(0x00, USB_USBHSC);
+
+       /* For LCD */
+       /* set PTJ7-1, bits 15-2 of PJCR to 0 */
+       ctrl_outw(ctrl_inw(PORT_PJCR) & 0x0003, PORT_PJCR);
+       /* set PTI5, bits 11-10 of PICR to 0 */
+       ctrl_outw(ctrl_inw(PORT_PICR) & 0xF3FF, PORT_PICR);
+       ctrl_outw(0, PORT_PKCR);
+       ctrl_outw(0, PORT_PLCR);
+       /* set PSEL2 bits 14-8, 5-4, of PSEL2 to 0 */
+       ctrl_outw((ctrl_inw(PORT_PSEL2) & 0x00C0), PORT_PSEL2);
+       /* set PSEL3 bits 14-12, 6-4, 2-0 of PSEL3 to 0 */
+       ctrl_outw((ctrl_inw(PORT_PSEL3) & 0x0700), PORT_PSEL3);
+
+       /* For HAC */
+       /* bit3-0  0100:HAC & SSI1 enable */
+       ctrl_outw((ctrl_inw(PORT_PSEL1) & 0xFFF0) | 0x0004, PORT_PSEL1);
+       /* bit14      1:SSI_HAC_CLK enable */
+       ctrl_outw(ctrl_inw(PORT_PSEL4) | 0x4000, PORT_PSEL4);
+
+       /* SH-Ether */
+       ctrl_outw((ctrl_inw(PORT_PSEL1) & ~0xff00) | 0x2400, PORT_PSEL1);
+       ctrl_outw(0x0, PORT_PFCR);
+       ctrl_outw(0x0, PORT_PFCR);
+       ctrl_outw(0x0, PORT_PFCR);
+
+       /* MMC */
+       /*selects SCIF and MMC other functions */
+       ctrl_outw(0x0001, PORT_PSEL0);
+       /* MMC clock operates */
+       ctrl_outl(ctrl_inl(MSTPCR1) & ~0x8, MSTPCR1);
+       ctrl_outw(ctrl_inw(PORT_PACR) & ~0x3000, PORT_PACR);
+       ctrl_outw(ctrl_inw(PORT_PCCR) & ~0xCFC3, PORT_PCCR);
+}
+
+static struct sh_machine_vector mv_sh7763rdp __initmv = {
+       .mv_name = "sh7763drp",
+       .mv_setup = sh7763rdp_setup,
+       .mv_nr_irqs = 112,
+       .mv_init_irq = init_sh7763rdp_IRQ,
+};
diff --git a/arch/sh/boards/renesas/sh7785lcr/Makefile b/arch/sh/boards/renesas/sh7785lcr/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/sh7785lcr/setup.c b/arch/sh/boards/renesas/sh7785lcr/setup.c
new file mode 100644 (file)
index 0000000..b95d674
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Renesas Technology Corp. R0P7785LC0011RL Support.
+ *
+ * Copyright (C) 2008  Yoshihiro Shimoda
+ *
+ * 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/sm501.h>
+#include <linux/sm501-regs.h>
+#include <linux/fb.h>
+#include <linux/mtd/physmap.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-pca-platform.h>
+#include <linux/i2c-algo-pca.h>
+#include <asm/heartbeat.h>
+#include <asm/sh7785lcr.h>
+
+/*
+ * NOTE: This board has 2 physical memory maps.
+ *      Please look at include/asm-sh/sh7785lcr.h or hardware manual.
+ */
+static struct resource heartbeat_resources[] = {
+       [0] = {
+               .start  = PLD_LEDCR,
+               .end    = PLD_LEDCR,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct heartbeat_data heartbeat_data = {
+       .regsize = 8,
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = &heartbeat_data,
+       },
+       .num_resources  = ARRAY_SIZE(heartbeat_resources),
+       .resource       = heartbeat_resources,
+};
+
+static struct mtd_partition nor_flash_partitions[] = {
+       {
+               .name           = "loader",
+               .offset         = 0x00000000,
+               .size           = 512 * 1024,
+       },
+       {
+               .name           = "bootenv",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 512 * 1024,
+       },
+       {
+               .name           = "kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 4 * 1024 * 1024,
+       },
+       {
+               .name           = "data",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct physmap_flash_data nor_flash_data = {
+       .width          = 4,
+       .parts          = nor_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(nor_flash_partitions),
+};
+
+static struct resource nor_flash_resources[] = {
+       [0]     = {
+               .start  = NOR_FLASH_ADDR,
+               .end    = NOR_FLASH_ADDR + NOR_FLASH_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device nor_flash_device = {
+       .name           = "physmap-flash",
+       .dev            = {
+               .platform_data  = &nor_flash_data,
+       },
+       .num_resources  = ARRAY_SIZE(nor_flash_resources),
+       .resource       = nor_flash_resources,
+};
+
+static struct resource r8a66597_usb_host_resources[] = {
+       [0] = {
+               .name   = "r8a66597_hcd",
+               .start  = R8A66597_ADDR,
+               .end    = R8A66597_ADDR + R8A66597_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .name   = "r8a66597_hcd",
+               .start  = 2,
+               .end    = 2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device r8a66597_usb_host_device = {
+       .name           = "r8a66597_hcd",
+       .id             = -1,
+       .dev = {
+               .dma_mask               = NULL,
+               .coherent_dma_mask      = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(r8a66597_usb_host_resources),
+       .resource       = r8a66597_usb_host_resources,
+};
+
+static struct resource sm501_resources[] = {
+       [0]     = {
+               .start  = SM107_MEM_ADDR,
+               .end    = SM107_MEM_ADDR + SM107_MEM_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1]     = {
+               .start  = SM107_REG_ADDR,
+               .end    = SM107_REG_ADDR + SM107_REG_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [2]     = {
+               .start  = 10,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct fb_videomode sm501_default_mode_crt = {
+       .pixclock       = 35714,        /* 28MHz */
+       .xres           = 640,
+       .yres           = 480,
+       .left_margin    = 105,
+       .right_margin   = 16,
+       .upper_margin   = 33,
+       .lower_margin   = 10,
+       .hsync_len      = 39,
+       .vsync_len      = 2,
+       .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct fb_videomode sm501_default_mode_pnl = {
+       .pixclock       = 40000,        /* 25MHz */
+       .xres           = 640,
+       .yres           = 480,
+       .left_margin    = 2,
+       .right_margin   = 16,
+       .upper_margin   = 33,
+       .lower_margin   = 10,
+       .hsync_len      = 39,
+       .vsync_len      = 2,
+       .sync           = 0,
+};
+
+static struct sm501_platdata_fbsub sm501_pdata_fbsub_pnl = {
+       .def_bpp        = 16,
+       .def_mode       = &sm501_default_mode_pnl,
+       .flags          = SM501FB_FLAG_USE_INIT_MODE |
+                         SM501FB_FLAG_USE_HWCURSOR |
+                         SM501FB_FLAG_USE_HWACCEL |
+                         SM501FB_FLAG_DISABLE_AT_EXIT |
+                         SM501FB_FLAG_PANEL_NO_VBIASEN,
+};
+
+static struct sm501_platdata_fbsub sm501_pdata_fbsub_crt = {
+       .def_bpp        = 16,
+       .def_mode       = &sm501_default_mode_crt,
+       .flags          = SM501FB_FLAG_USE_INIT_MODE |
+                         SM501FB_FLAG_USE_HWCURSOR |
+                         SM501FB_FLAG_USE_HWACCEL |
+                         SM501FB_FLAG_DISABLE_AT_EXIT,
+};
+
+static struct sm501_platdata_fb sm501_fb_pdata = {
+       .fb_route       = SM501_FB_OWN,
+       .fb_crt         = &sm501_pdata_fbsub_crt,
+       .fb_pnl         = &sm501_pdata_fbsub_pnl,
+};
+
+static struct sm501_initdata sm501_initdata = {
+       .gpio_high      = {
+               .set    = 0x00001fe0,
+               .mask   = 0x0,
+       },
+       .devices        = 0,
+       .mclk           = 84 * 1000000,
+       .m1xclk         = 112 * 1000000,
+};
+
+static struct sm501_platdata sm501_platform_data = {
+       .init           = &sm501_initdata,
+       .fb             = &sm501_fb_pdata,
+};
+
+static struct platform_device sm501_device = {
+       .name           = "sm501",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &sm501_platform_data,
+       },
+       .num_resources  = ARRAY_SIZE(sm501_resources),
+       .resource       = sm501_resources,
+};
+
+static struct resource i2c_resources[] = {
+       [0] = {
+               .start  = PCA9564_ADDR,
+               .end    = PCA9564_ADDR + PCA9564_SIZE - 1,
+               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
+       },
+       [1] = {
+               .start  = 12,
+               .end    = 12,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct i2c_pca9564_pf_platform_data i2c_platform_data = {
+       .gpio                   = 0,
+       .i2c_clock_speed        = I2C_PCA_CON_330kHz,
+       .timeout                = 100,
+};
+
+static struct platform_device i2c_device = {
+       .name           = "i2c-pca-platform",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &i2c_platform_data,
+       },
+       .num_resources  = ARRAY_SIZE(i2c_resources),
+       .resource       = i2c_resources,
+};
+
+static struct platform_device *sh7785lcr_devices[] __initdata = {
+       &heartbeat_device,
+       &nor_flash_device,
+       &r8a66597_usb_host_device,
+       &sm501_device,
+       &i2c_device,
+};
+
+static struct i2c_board_info __initdata sh7785lcr_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("r2025sd", 0x32),
+       },
+};
+
+static int __init sh7785lcr_devices_setup(void)
+{
+       i2c_register_board_info(0, sh7785lcr_i2c_devices,
+                               ARRAY_SIZE(sh7785lcr_i2c_devices));
+
+       return platform_add_devices(sh7785lcr_devices,
+                                   ARRAY_SIZE(sh7785lcr_devices));
+}
+__initcall(sh7785lcr_devices_setup);
+
+/* Initialize IRQ setting */
+void __init init_sh7785lcr_IRQ(void)
+{
+       plat_irq_setup_pins(IRQ_MODE_IRQ7654);
+       plat_irq_setup_pins(IRQ_MODE_IRQ3210);
+}
+
+static void sh7785lcr_power_off(void)
+{
+       ctrl_outb(0x01, P2SEGADDR(PLD_POFCR));
+}
+
+/* Initialize the board */
+static void __init sh7785lcr_setup(char **cmdline_p)
+{
+       void __iomem *sm501_reg;
+
+       printk(KERN_INFO "Renesas Technology Corp. R0P7785LC0011RL support.\n");
+
+       pm_power_off = sh7785lcr_power_off;
+
+       /* sm501 DRAM configuration */
+       sm501_reg = (void __iomem *)0xb3e00000 + SM501_DRAM_CONTROL;
+       writel(0x000307c2, sm501_reg);
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_sh7785lcr __initmv = {
+       .mv_name                = "SH7785LCR",
+       .mv_setup               = sh7785lcr_setup,
+       .mv_init_irq            = init_sh7785lcr_IRQ,
+};
+
index 763f6deba814cdc748314ca116e2492c35646bdf..1112e86aa93abfc31f9342e681b83bc57315f334 100644 (file)
 /*
- * arch/sh/boards/se/7343/irq.c
+ * linux/arch/sh/boards/se/7343/irq.c
  *
+ * Copyright (C) 2008  Yoshihiro Shimoda
+ *
+ * Based on linux/arch/sh/boards/se/7722/irq.c
+ * Copyright (C) 2007  Nobuhiro Iwamatsu
+ *
+ * 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/interrupt.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/mach/se7343.h>
+#include <asm/se7343.h>
 
-static void
-disable_intreq_irq(unsigned int irq)
+static void disable_se7343_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);
+       unsigned int bit = irq - SE7343_FPGA_IRQ_BASE;
+       ctrl_outw(ctrl_inw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK);
 }
 
-static void
-enable_intreq_irq(unsigned int irq)
+static void enable_se7343_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);
+       unsigned int bit = irq - SE7343_FPGA_IRQ_BASE;
+       ctrl_outw(ctrl_inw(PA_CPLD_IMSK) & ~(1 << bit), 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 struct irq_chip se7343_irq_chip __read_mostly = {
+       .name           = "SE7343-FPGA",
+       .mask           = disable_se7343_irq,
+       .unmask         = enable_se7343_irq,
+       .mask_ack       = disable_se7343_irq,
 };
 
-static void
-make_intreq_irq(unsigned int irq)
-{
-       disable_irq_nosync(irq);
-       irq_desc[irq].chip = &intreq_irq_type;
-       disable_intreq_irq(irq);
-}
-
-int
-shmse_irq_demux(int irq)
+static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       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;
+       unsigned short intv = ctrl_inw(PA_CPLD_ST);
+       struct irq_desc *ext_desc;
+       unsigned int ext_irq = SE7343_FPGA_IRQ_BASE;
+
+       intv &= (1 << SE7343_FPGA_IRQ_NR) - 1;
+
+       while (intv) {
+               if (intv & 1) {
+                       ext_desc = irq_desc + ext_irq;
+                       handle_level_irq(ext_irq, ext_desc);
+               }
+               intv >>= 1;
+               ext_irq++;
        }
-       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 = {
-       .handler = no_action,
-       .mask = CPU_MASK_NONE,
-       .name = "IRQ5-cascade",
-};
-
-static struct ipr_data se7343_irq5_ipr_map[] = {
-       { IRQ5_IRQ, IRQ5_IPR_ADDR+2, IRQ5_IPR_POS, IRQ5_PRIORITY },
-};
-static struct ipr_data se7343_siof0_vpu_ipr_map[] = {
-       { SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY },
-       { VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8 },
-};
-static struct ipr_data se7343_other_ipr_map[] = {
-       { DMTE0_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
-       { DMTE1_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
-       { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
-       { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
-       { DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY },
-       { DMTE5_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY },
-
-       /* I2C block */
-       { IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY },
-       { IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY },
-       { IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY },
-       { IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY },
-
-       { IIC1_ALI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY },
-       { IIC1_TACKI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY },
-       { IIC1_WAITI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY },
-       { IIC1_DTEI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY },
-
-       /* SIOF */
-       { SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY },
-
-       /* SIU */
-       { SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY },
-
-       /* VIO interrupt */
-       { CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
-       { BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
-       { VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
-
-       /*MFI interrupt*/
-
-       { MFI_IRQ, MFI_IPR_ADDR, MFI_IPR_POS, MFI_PRIORITY },
-
-       /* LCD controller */
-       { LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY },
-};
-
 /*
  * Initialize IRQ setting
  */
-void __init
-init_7343se_IRQ(void)
+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(se7343_irq5_ipr_map, ARRAY_SIZE(se7343_irq5_ipr_map));
-
-       setup_irq(IRQ5_IRQ, &irq5);
-       /* Set port control to use IRQ5 */
-       *(u16 *)0xA4050108 &= ~0xc;
-
-       make_ipr_irq(se7343_siof0_vpu_ipr_map, ARRAY_SIZE(se7343_siof0_vpu_ipr_map));
-
-       ctrl_outb(0x0f, INTC_IMCR5);    /* enable SCIF IRQ */
-
-       make_ipr_irq(se7343_other_ipr_map, ARRAY_SIZE(se7343_other_ipr_map));
-
-       ctrl_outw(0x2000, PA_MRSHPC + 0x0c);    /* mrshpc irq enable */
+       int i;
+
+       ctrl_outw(0, PA_CPLD_IMSK);     /* disable all irqs */
+       ctrl_outw(0x2000, 0xb03fffec);  /* mrshpc irq enable */
+
+       for (i = 0; i < SE7343_FPGA_IRQ_NR; i++)
+               set_irq_chip_and_handler_name(SE7343_FPGA_IRQ_BASE + i,
+                                             &se7343_irq_chip,
+                                             handle_level_irq, "level");
+
+       set_irq_chained_handler(IRQ0_IRQ, se7343_irq_demux);
+       set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+       set_irq_chained_handler(IRQ1_IRQ, se7343_irq_demux);
+       set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
+       set_irq_chained_handler(IRQ4_IRQ, se7343_irq_demux);
+       set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW);
+       set_irq_chained_handler(IRQ5_IRQ, se7343_irq_demux);
+       set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
index c9431b3a051b48694fd24771e8b662a103c24f10..8ae718d6c71006587445f69e07f17396cf38eb73 100644 (file)
@@ -1,10 +1,11 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
 #include <asm/machvec.h>
 #include <asm/mach/se7343.h>
+#include <asm/heartbeat.h>
 #include <asm/irq.h>
-
-void init_7343se_IRQ(void);
+#include <asm/io.h>
 
 static struct resource smc91x_resources[] = {
        [0] = {
@@ -17,8 +18,8 @@ static struct resource smc91x_resources[] = {
                 * shared with other devices via externel
                 * interrupt controller in FPGA...
                 */
-               .start  = EXT_IRQ2,
-               .end    = EXT_IRQ2,
+               .start  = SMC_IRQ,
+               .end    = SMC_IRQ,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -38,16 +39,65 @@ static struct resource heartbeat_resources[] = {
        },
 };
 
+static struct heartbeat_data heartbeat_data = {
+       .regsize = 16,
+};
+
 static struct platform_device heartbeat_device = {
        .name           = "heartbeat",
        .id             = -1,
+       .dev = {
+               .platform_data = &heartbeat_data,
+       },
        .num_resources  = ARRAY_SIZE(heartbeat_resources),
        .resource       = heartbeat_resources,
 };
 
+static struct mtd_partition nor_flash_partitions[] = {
+       {
+               .name           = "loader",
+               .offset         = 0x00000000,
+               .size           = 128 * 1024,
+       },
+       {
+               .name           = "rootfs",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 31 * 1024 * 1024,
+       },
+       {
+               .name           = "data",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct physmap_flash_data nor_flash_data = {
+       .width          = 2,
+       .parts          = nor_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(nor_flash_partitions),
+};
+
+static struct resource nor_flash_resources[] = {
+       [0]     = {
+               .start  = 0x00000000,
+               .end    = 0x01ffffff,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device nor_flash_device = {
+       .name           = "physmap-flash",
+       .dev            = {
+               .platform_data  = &nor_flash_data,
+       },
+       .num_resources  = ARRAY_SIZE(nor_flash_resources),
+       .resource       = nor_flash_resources,
+};
+
 static struct platform_device *sh7343se_platform_devices[] __initdata = {
        &smc91x_device,
        &heartbeat_device,
+       &nor_flash_device,
 };
 
 static int __init sh7343se_devices_setup(void)
@@ -55,10 +105,19 @@ static int __init sh7343se_devices_setup(void)
        return platform_add_devices(sh7343se_platform_devices,
                                    ARRAY_SIZE(sh7343se_platform_devices));
 }
+device_initcall(sh7343se_devices_setup);
 
+/*
+ * Initialize the board
+ */
 static void __init sh7343se_setup(char **cmdline_p)
 {
-       device_initcall(sh7343se_devices_setup);
+       ctrl_outw(0xf900, FPGA_OUT);    /* FPGA */
+
+       ctrl_outw(0x0002, PORT_PECR);   /* PORT E 1 = IRQ5 */
+       ctrl_outw(0x0020, PORT_PSELD);
+
+       printk(KERN_INFO "MS7343CP01 Setup...done\n");
 }
 
 /*
@@ -90,5 +149,4 @@ static struct sh_machine_vector mv_7343se __initmv = {
        .mv_outsl = sh7343se_outsl,
 
        .mv_init_irq = init_7343se_IRQ,
-       .mv_irq_demux = shmse_irq_demux,
 };
index c4550473d4c33f2dc4e4bac5371cd9ccf19c1fcf..b1ec085b8673091c692a710698435e6a751b76fa 100644 (file)
@@ -1,25 +1,13 @@
-/* $Id: io.c,v 1.7 2006/02/05 21:55:29 lethal Exp $
- *
- * linux/arch/sh/kernel/io_se.c
- *
+/*
  * Copyright (C) 2000  Kazumoto Kojima
  *
  * I/O routine for Hitachi SolutionEngine.
- *
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <asm/io.h>
 #include <asm/se.h>
 
-/* 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;
-
 /* 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.  */
@@ -33,8 +21,6 @@ port2adr(unsigned int port)
                return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
        else if (port >= 0x1000)
                return (volatile __u16 *) (PA_83902 + (port << 1));
-       else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
-               return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
        else
                return (volatile __u16 *) (PA_SUPERIO + (port << 1));
 }
@@ -51,32 +37,27 @@ shifted_port(unsigned long port)
 
 unsigned char se_inb(unsigned long port)
 {
-       if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
-               return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
-       else if (shifted_port(port))
-               return (*port2adr(port) >> 8); 
+       if (shifted_port(port))
+               return (*port2adr(port) >> 8);
        else
-               return (*port2adr(port))&0xff; 
+               return (*port2adr(port))&0xff;
 }
 
 unsigned char se_inb_p(unsigned long port)
 {
        unsigned long v;
 
-       if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
-               v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
-       else if (shifted_port(port))
-               v = (*port2adr(port) >> 8); 
+       if (shifted_port(port))
+               v = (*port2adr(port) >> 8);
        else
-               v = (*port2adr(port))&0xff; 
+               v = (*port2adr(port))&0xff;
        ctrl_delay();
        return v;
 }
 
 unsigned short se_inw(unsigned long port)
 {
-       if (port >= 0x2000 ||
-           (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+       if (port >= 0x2000)
                return *port2adr(port);
        else
                maybebadio(port);
@@ -91,9 +72,7 @@ unsigned int se_inl(unsigned long port)
 
 void se_outb(unsigned char value, unsigned long port)
 {
-       if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
-               *(__u8 *)(sh_pcic_io_wbase + port) = value; 
-       else if (shifted_port(port))
+       if (shifted_port(port))
                *(port2adr(port)) = value << 8;
        else
                *(port2adr(port)) = value;
@@ -101,9 +80,7 @@ void se_outb(unsigned char value, unsigned long port)
 
 void se_outb_p(unsigned char value, unsigned long port)
 {
-       if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
-               *(__u8 *)(sh_pcic_io_wbase + port) = value; 
-       else if (shifted_port(port))
+       if (shifted_port(port))
                *(port2adr(port)) = value << 8;
        else
                *(port2adr(port)) = value;
@@ -112,8 +89,7 @@ void se_outb_p(unsigned char value, unsigned long port)
 
 void se_outw(unsigned short value, unsigned long port)
 {
-       if (port >= 0x2000 ||
-           (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+       if (port >= 0x2000)
                *port2adr(port) = value;
        else
                maybebadio(port);
@@ -129,11 +105,7 @@ void se_insb(unsigned long port, void *addr, unsigned long count)
        volatile __u16 *p = port2adr(port);
        __u8 *ap = addr;
 
-       if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
-               volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
-               while (count--)
-                       *ap++ = *bp;
-       } else if (shifted_port(port)) {
+       if (shifted_port(port)) {
                while (count--)
                        *ap++ = *p >> 8;
        } else {
@@ -160,11 +132,7 @@ void se_outsb(unsigned long port, const void *addr, unsigned long count)
        volatile __u16 *p = port2adr(port);
        const __u8 *ap = addr;
 
-       if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
-               volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); 
-               while (count--)
-                       *bp = *ap++;
-       } else if (shifted_port(port)) {
+       if (shifted_port(port)) {
                while (count--)
                        *p = *ap++ << 8;
        } else {
@@ -177,6 +145,7 @@ void se_outsw(unsigned long port, const void *addr, unsigned long count)
 {
        volatile __u16 *p = port2adr(port);
        const __u16 *ap = addr;
+
        while (count--)
                *p = *ap++;
 }
index 318bc8a3969c2d1d03fbbbb68a8b75225287302a..cf4a5ba12df4f2c343dfa3b109ed1eb93f4ed49c 100644 (file)
@@ -14,8 +14,6 @@
 #include <asm/smc37c93x.h>
 #include <asm/heartbeat.h>
 
-void init_se_IRQ(void);
-
 /*
  * Configure the Super I/O chip
  */
@@ -73,7 +71,7 @@ static struct resource cf_ide_resources[] = {
        },
        [1] = {
                .start  = PA_MRSHPC_IO + 0x1f0 + 0x206,
-               .end    = PA_MRSHPC_IO + 0x1f0 +8 + 0x206 + 8,
+               .end    = PA_MRSHPC_IO + 0x1f0 + 8 + 0x206 + 8,
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
@@ -115,9 +113,58 @@ static struct platform_device heartbeat_device = {
        .resource       = heartbeat_resources,
 };
 
+/* SH771X Ethernet driver */
+static struct resource sh_eth0_resources[] = {
+       [0] = {
+               .start = SH_ETH0_BASE,
+               .end = SH_ETH0_BASE + 0x1B8,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = SH_ETH0_IRQ,
+               .end = SH_ETH0_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device sh_eth0_device = {
+       .name = "sh-eth",
+       .id     = 0,
+       .dev = {
+               .platform_data = PHY_ID,
+       },
+       .num_resources = ARRAY_SIZE(sh_eth0_resources),
+       .resource = sh_eth0_resources,
+};
+
+static struct resource sh_eth1_resources[] = {
+       [0] = {
+               .start = SH_ETH1_BASE,
+               .end = SH_ETH1_BASE + 0x1B8,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = SH_ETH1_IRQ,
+               .end = SH_ETH1_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device sh_eth1_device = {
+       .name = "sh-eth",
+       .id     = 1,
+       .dev = {
+               .platform_data = PHY_ID,
+       },
+       .num_resources = ARRAY_SIZE(sh_eth1_resources),
+       .resource = sh_eth1_resources,
+};
+
 static struct platform_device *se_devices[] __initdata = {
        &heartbeat_device,
        &cf_ide_device,
+       &sh_eth0_device,
+       &sh_eth1_device,
 };
 
 static int __init se_devices_setup(void)
index ede3957fc14afa676eb8f609c06f97d651cc6949..6e228ea59788755526b0b1169a52a15a1c19afb0 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/input.h>
 #include <linux/smc91x.h>
 #include <asm/machvec.h>
+#include <asm/clock.h>
 #include <asm/se7722.h>
 #include <asm/io.h>
 #include <asm/heartbeat.h>
@@ -145,6 +146,8 @@ static struct platform_device *se7722_devices[] __initdata = {
 
 static int __init se7722_devices_setup(void)
 {
+       clk_always_enable("mstp214"); /* KEYSC */
+
        return platform_add_devices(se7722_devices,
                ARRAY_SIZE(se7722_devices));
 }
@@ -154,11 +157,6 @@ static void __init se7722_setup(char **cmdline_p)
 {
        ctrl_outw(0x010D, FPGA_OUT);    /* FPGA */
 
-       ctrl_outl(0x00051001, MSTPCR0);
-       ctrl_outl(0x00000000, MSTPCR1);
-       /* KEYSC, VOU, BEU, CEU, VEU, VPU, LCDC, USB */
-       ctrl_outl(0xffffb7c0, MSTPCR2);
-
        ctrl_outw(0x0000, PORT_PECR);   /* PORT E 1 = IRQ5 ,E 0 = BS */
        ctrl_outw(0x1000, PORT_PJCR);   /* PORT J 1 = IRQ1,J 0 =IRQ0 */
 
index 89b408620dcbbfb68d2e3f02a534fc22e86f3a64..8b37869a822759efd58dbddfd007590aa873db76 100644 (file)
@@ -40,7 +40,7 @@ KERNEL_LOAD   := $(shell /bin/bash -c 'printf "0x%08x" \
 KERNEL_ENTRY   := $(shell /bin/bash -c 'printf "0x%08x" \
                     $$[$(CONFIG_PAGE_OFFSET)  + \
                        $(CONFIG_MEMORY_START) + \
-                       $(CONFIG_ZERO_PAGE_OFFSET)+0x1000]')
+                       $(CONFIG_ZERO_PAGE_OFFSET) + $(CONFIG_ENTRY_OFFSET)]')
 
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \
index c0d25fb1aa608bb4829294d0907bde736a02f82c..47685f618ae748e504bc76a99a5f3a8b822f6534 100644 (file)
@@ -35,8 +35,7 @@ $(obj)/vmlinux.bin: vmlinux FORCE
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
        $(call if_changed,gzip)
 
-LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh-linux -T
 OBJCOPYFLAGS += -R .empty_zero_page
 
-$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
-       $(call if_changed,ld)
+$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
+       $(call if_changed,as_o_S)
index 912f3e205a0d38678c532cff4a884f80fd541d77..658d4f91555679b474e8c3c12fc00665fd5ef197 100644 (file)
@@ -37,8 +37,7 @@ $(obj)/vmlinux.bin: vmlinux FORCE
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
        $(call if_changed,gzip)
 
-LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh64-linux -T
 OBJCOPYFLAGS += -R .empty_zero_page
 
-$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
-       $(call if_changed,ld)
+$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
+       $(call if_changed,as_o_S)
index adcea31e663eade000c375f47badafa14189caf8..f386997e4d9c3b0c347b209b54852d3d4194e2bb 100644 (file)
@@ -74,8 +74,6 @@ static unsigned outcnt = 0;  /* bytes in output buffer */
 static int  fill_inbuf(void);
 static void flush_window(void);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 extern char input_data[];
 extern int input_len;
@@ -84,11 +82,7 @@ static long bytes_out = 0;
 static uch *output_data;
 static unsigned long output_ptr = 0;
 
-static void *malloc(int size);
-static void free(void *where);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 int puts(const char *);
 
@@ -101,38 +95,6 @@ static unsigned long free_mem_end_ptr;
 
 #include "../../../../lib/inflate.c"
 
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size <0) error("Malloc error");
-       if (free_mem_ptr == 0) error("Memory error");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *)free_mem_ptr;
-       free_mem_ptr += size;
-
-       if (free_mem_ptr >= free_mem_end_ptr)
-               error("Out of memory");
-
-       return p;
-}
-
-static void free(void *where)
-{      /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
-       *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
-       free_mem_ptr = (long) *ptr;
-}
-
 #ifdef CONFIG_SH_STANDARD_BIOS
 size_t strlen(const char *s)
 {
index a006ef89b9dd26bbf655f5e35a10cf73495cf331..2941657e18aafe3aad77352c574100771864728d 100644 (file)
@@ -72,8 +72,6 @@ static unsigned outcnt = 0;   /* bytes in output buffer */
 static int fill_inbuf(void);
 static void flush_window(void);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 extern char input_data[];
 extern int input_len;
@@ -82,11 +80,7 @@ static long bytes_out = 0;
 static uch *output_data;
 static unsigned long output_ptr = 0;
 
-static void *malloc(int size);
-static void free(void *where);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 static void puts(const char *);
 
@@ -99,40 +93,6 @@ static unsigned long free_mem_end_ptr;
 
 #include "../../../../lib/inflate.c"
 
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size < 0)
-               error("Malloc error\n");
-       if (free_mem_ptr == 0)
-               error("Memory error\n");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *) free_mem_ptr;
-       free_mem_ptr += size;
-
-       if (free_mem_ptr >= free_mem_end_ptr)
-               error("\nOut of memory\n");
-
-       return p;
-}
-
-static void free(void *where)
-{                              /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
-       *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
-       free_mem_ptr = (long) *ptr;
-}
-
 void puts(const char *s)
 {
 }
diff --git a/arch/sh/boot/compressed/piggy.S b/arch/sh/boot/compressed/piggy.S
new file mode 100644 (file)
index 0000000..5660719
--- /dev/null
@@ -0,0 +1,8 @@
+       .global input_len, input_data
+       .data
+input_len:
+       .long   input_data_end - input_data
+input_data:
+       .incbin "arch/sh/boot/compressed/vmlinux.bin.gz"
+input_data_end:
+       .end
diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr
deleted file mode 100644 (file)
index 1ed9d79..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-SECTIONS
-{
-  .data : { 
-       input_len = .;
-       LONG(input_data_end - input_data) input_data = .; 
-       *(.data) 
-       input_data_end = .; 
-       }
-}
diff --git a/arch/sh/configs/ap325rxa_defconfig b/arch/sh/configs/ap325rxa_defconfig
new file mode 100644 (file)
index 0000000..5471df5
--- /dev/null
@@ -0,0 +1,947 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc4
+# Wed Jun  4 17:30:00 2008
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=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_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=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_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+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
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG 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"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG 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
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# 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
+CONFIG_CPU_SUBTYPE_SH7723=y
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+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_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=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+CONFIG_SH_AP325RXA=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_GUSA=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=tty1 console=ttySC5,38400 root=/dev/nfs ip=dhcp"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# 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_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+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=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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 is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xffffffff
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# 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
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC91X is not set
+CONFIG_SMC911X=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV 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_TABLET 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=y
+CONFIG_DEVKMEM=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=6
+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
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# 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_EXT4DEV_FS is not set
+CONFIG_JBD=y
+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_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA 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_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+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_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 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_SUNRPC_BIND34 is not set
+# 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 is not set
+CONFIG_MSDOS_PARTITION=y
+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
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 84c0075e2ad47c6492f0d5d7ba081097565e8fbd..7b72736384474f23ca39f755a0bfbcc9ee61786b 100644 (file)
@@ -1,40 +1,55 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 11:46:17 2006
+# Linux kernel version: 2.6.26-rc8
+# Mon Jul  7 13:12:45 2008
 #
 CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=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_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
 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_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -46,33 +61,41 @@ CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 # CONFIG_SHMEM is not set
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 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_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
 
 #
 # IO Schedulers
@@ -86,62 +109,28 @@ CONFIG_DEFAULT_DEADLINE=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_CLASSIC_RCU=y
 
 #
 # 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
 CONFIG_CPU_SH4AL_DSP=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_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG 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_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -150,67 +139,88 @@ CONFIG_CPU_SH4AL_DSP=y
 # 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_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
 CONFIG_CPU_SUBTYPE_SH7343=y
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x01000000
-CONFIG_32BIT=y
+CONFIG_29BIT=y
 CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+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_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_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
-# CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
 
 #
 # Processor features
 #
 CONFIG_CPU_LITTLE_ENDIAN=y
-# CONFIG_SH_FPU is not set
+# CONFIG_CPU_BIG_ENDIAN 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
+CONFIG_CPU_HAS_DSP=y
+
+#
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7343_SOLUTION_ENGINE=y
 
 #
-# Timer support
+# Timer and clock configuration
 #
 CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
 CONFIG_SH_PCLK_FREQ=27000000
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
 # CPU Frequency scaling
@@ -225,56 +235,49 @@ CONFIG_SH_PCLK_FREQ=27000000
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
 CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
 
 #
 # Kernel features
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
 # CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
 
 #
 # 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_CF_ENABLER is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 # 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
 #
@@ -283,22 +286,20 @@ CONFIG_NET=y
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
 # 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_IP_PNP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
@@ -310,29 +311,18 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -345,10 +335,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 # CONFIG_NET_SCHED is not set
 
 #
@@ -356,9 +342,20 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -367,36 +364,32 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # 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=y
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -422,13 +415,15 @@ 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_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
 # CONFIG_MTD_PLATRAM is not set
 
 #
@@ -445,130 +440,101 @@ CONFIG_MTD_RAM=y
 # 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
+# UBI - Unsorted block images
 #
+# CONFIG_MTD_UBI is not set
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # 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_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
 
 #
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
+# SCSI support type (disk, tape, CD-ROM)
 #
+# CONFIG_BLK_DEV_SD is not set
+# 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
 
 #
-# I2O device support
+# 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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
-# Network device support
+# SCSI Transports
 #
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
 CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
+# CONFIG_VETH is not set
 # CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
+# CONFIG_AX88796 is not set
 # CONFIG_STNIC is not set
 CONFIG_SMC91X=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_E1000E_ENABLED is not set
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
 #
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
 # 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
 
 #
@@ -576,13 +542,13 @@ CONFIG_SMC91X=y
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
 #
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
@@ -592,6 +558,7 @@ CONFIG_INPUT=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -608,6 +575,7 @@ CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -626,147 +594,102 @@ 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_HW_RANDOM=y
-# 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_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_STUB 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_I2C is not set
 # CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
 
 #
-# Dallas's 1-wire bus
+# Sonics Silicon Backplane
 #
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
 
 #
-# Misc devices
+# Multimedia devices
 #
 
 #
-# Multimedia devices
+# Multimedia core support
 #
 CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_ALLOW_V4L1=y
 CONFIG_VIDEO_V4L1_COMPAT=y
-CONFIG_VIDEO_V4L2=y
-
-#
-# Video Capture Adapters
-#
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
 
 #
-# Video Capture Adapters
+# Multimedia drivers
 #
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
 # CONFIG_VIDEO_ADV_DEBUG is not set
 CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
 # 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
-
-#
-# Radio Adapters
-#
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_EPSON1355 is not set
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
-# Console display driver support
+# Display device support
 #
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
-# Logo configuration
+# Console display driver support
 #
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
 # CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -802,85 +725,63 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_MPU401 is not set
 
 #
-# Open Sound System
+# SUPERH devices
 #
-# CONFIG_SOUND_PRIME is not set
 
 #
-# USB support
+# System on Chip audio 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
+# CONFIG_SND_SOC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# SoC Audio support for SuperH
 #
 
 #
-# USB Gadget Support
+# ALSA SoC audio for Freescale SOCs
 #
-# CONFIG_USB_GADGET is not set
 
 #
-# MMC/SD Card support
+# SoC Audio for the Texas Instruments OMAP
 #
-# CONFIG_MMC is not set
 
 #
-# LED devices
+# Open Sound System
 #
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
+# CONFIG_UIO is not set
 
 #
 # File systems
 #
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY 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
@@ -909,7 +810,6 @@ CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -922,40 +822,39 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
 # 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_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
 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_NFSD_V4 is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -963,56 +862,130 @@ CONFIG_SUNRPC=y
 # 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
+# CONFIG_DLM is not set
 
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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_SAMPLES is not set
 # CONFIG_SH_STANDARD_BIOS is not set
-# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe00000
+CONFIG_EARLY_PRINTK=y
+# CONFIG_SH_KGDB is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
 
 #
-# Cryptographic options
+# Compression
 #
-# CONFIG_CRYPTO is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
 
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 2dd83af988f065419b975b6fa70c0089b2816e8f..7be79cd04eb0385936d2f7d01642988813bf7d83 100644 (file)
@@ -1,53 +1,57 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc4
-# Wed Mar 28 10:19:02 2007
+# Linux kernel version: 2.6.26-rc6
+# Wed Jun 18 16:36:08 2008
 #
 CONFIG_SUPERH=y
+CONFIG_SUPERH32=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_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
 CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -55,33 +59,41 @@ CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 # CONFIG_BUG is not set
 CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
 # CONFIG_BASE_FULL is not set
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 # CONFIG_SHMEM is not set
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 # CONFIG_MODULE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 # CONFIG_KMOD is not set
-
-#
-# Block layer
-#
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
 
 #
 # IO Schedulers
@@ -95,57 +107,17 @@ CONFIG_IOSCHED_NOOP=y
 # CONFIG_DEFAULT_CFQ is not set
 CONFIG_DEFAULT_NOOP=y
 CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
 
 #
 # System type
 #
-CONFIG_SOLUTION_ENGINE=y
-CONFIG_SH_SOLUTION_ENGINE=y
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_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_SATURN is not set
-# CONFIG_SH_DREAMCAST 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_HIGHLANDER 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_7206_SOLUTION_ENGINE is not set
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_LBOX_RE2 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
 # CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
 # CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
@@ -153,10 +125,8 @@ CONFIG_CPU_SH3=y
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
 CONFIG_CPU_SUBTYPE_SH7712=y
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -165,37 +135,37 @@ CONFIG_CPU_SUBTYPE_SH7712=y
 # 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_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
 # CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x02000000
+CONFIG_29BIT=y
 CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 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_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -203,21 +173,21 @@ CONFIG_FLATMEM_MANUAL=y
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
-# CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
 
 #
 # Processor features
@@ -230,6 +200,14 @@ CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_DSP=y
+
+#
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_SOLUTION_ENGINE=y
+# CONFIG_SH_AP325RXA is not set
 
 #
 # Timer and clock configuration
@@ -237,6 +215,10 @@ CONFIG_CPU_HAS_SR_RB=y
 CONFIG_SH_TMU=y
 CONFIG_SH_TIMER_IRQ=16
 CONFIG_SH_PCLK_FREQ=66666666
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
 # CPU Frequency scaling
@@ -251,7 +233,6 @@ CONFIG_SH_PCLK_FREQ=66666666
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
 
 #
 # Additional SuperH Device Drivers
@@ -267,47 +248,39 @@ CONFIG_HZ_250=y
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
 # CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+# CONFIG_GUSA_RB is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
-# CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
 
 #
 # Bus options
 #
-# CONFIG_PCI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 # 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
 #
@@ -316,7 +289,6 @@ CONFIG_NET=y
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -324,6 +296,7 @@ CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
 CONFIG_NET_KEY=y
 # CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
@@ -334,11 +307,10 @@ CONFIG_ASK_IP_FIB_HASH=y
 CONFIG_IP_FIB_HASH=y
 CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_MULTIPATH=y
-# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP 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
@@ -355,30 +327,17 @@ CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -391,15 +350,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_LAPB 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_FIFO=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
@@ -408,6 +359,7 @@ CONFIG_NET_SCH_CBQ=y
 CONFIG_NET_SCH_HTB=y
 CONFIG_NET_SCH_HFSC=y
 CONFIG_NET_SCH_PRIO=y
+# CONFIG_NET_SCH_RR is not set
 CONFIG_NET_SCH_RED=y
 CONFIG_NET_SCH_SFQ=y
 CONFIG_NET_SCH_TEQL=y
@@ -415,7 +367,6 @@ CONFIG_NET_SCH_TBF=y
 CONFIG_NET_SCH_GRED=y
 CONFIG_NET_SCH_DSMARK=y
 CONFIG_NET_SCH_NETEM=y
-CONFIG_NET_SCH_INGRESS=y
 
 #
 # Classification
@@ -429,22 +380,33 @@ CONFIG_NET_CLS_FW=y
 # CONFIG_NET_CLS_U32 is not set
 # CONFIG_NET_CLS_RSVP is not set
 # CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
 # CONFIG_NET_EMATCH is not set
 # CONFIG_NET_CLS_ACT is not set
-# CONFIG_NET_CLS_POLICE is not set
 CONFIG_NET_CLS_IND=y
-CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_SCH_FIFO=y
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_AF_RXRPC is not set
 CONFIG_FIB_RULES=y
 
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
 #
 # Device Drivers
 #
@@ -452,27 +414,21 @@ CONFIG_FIB_RULES=y
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
 # CONFIG_CONNECTOR 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
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
@@ -485,6 +441,7 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -510,7 +467,6 @@ 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
@@ -533,44 +489,25 @@ CONFIG_MTD_CFI_UTIL=y
 # 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
+# UBI - Unsorted block images
 #
+# CONFIG_MTD_UBI is not set
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # 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_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
@@ -578,6 +515,7 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
 # CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
@@ -599,6 +537,7 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -606,94 +545,72 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
 # CONFIG_SCSI_SAS_LIBSAS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_MV is not set
 CONFIG_PATA_PLATFORM=y
-
-#
-# 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_NETDEVICES_MULTIQUEUE is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET 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_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+CONFIG_SH_ETH=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMC911X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_E1000E_ENABLED is not set
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
 # 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
 
 #
@@ -711,6 +628,7 @@ CONFIG_NETDEVICES=y
 # Character devices
 #
 # CONFIG_VT is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -728,99 +646,78 @@ CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=m
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
-
-#
-# SPI support
-#
 # CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
 # CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
 
 #
-# Hardware Monitoring support
+# Sonics Silicon Backplane
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
 
 #
-# Digital Video Broadcasting Devices
+# Multimedia drivers
 #
-# CONFIG_DVB is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
-# Sound
+# Display device support
 #
-# CONFIG_SOUND is not set
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
-# USB support
+# Sound
 #
-# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_SOUND is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 # CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB 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_MEMSTICK is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 
@@ -834,40 +731,10 @@ CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_TRIGGERS=y
 # CONFIG_LEDS_TRIGGER_TIMER is not set
 # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
-
-#
-# InfiniBand support
-#
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
+# CONFIG_UIO is not set
 
 #
 # File systems
@@ -877,20 +744,21 @@ 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 is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
 # CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
 CONFIG_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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY 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
@@ -919,7 +787,6 @@ CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -935,68 +802,67 @@ CONFIG_RAMFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
 # 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_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_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_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
 # CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
 # CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
 
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
 #
 # Kernel hacking
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DETECT_SOFTLOCKUP is not set
+CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -1004,21 +870,28 @@ CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT 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_INFO=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
 # CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
 CONFIG_FRAME_POINTER=y
-# CONFIG_FORCED_INLINING is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_DEBUG_BOOTMEM is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
+# CONFIG_IRQSTACKS is not set
 # CONFIG_SH_KGDB is not set
 
 #
@@ -1026,62 +899,100 @@ CONFIG_FRAME_POINTER=y
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
 
 #
-# Cryptographic options
+# Crypto core or helper
 #
-CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
 CONFIG_CRYPTO_BLKCIPHER=y
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
 CONFIG_CRYPTO_SHA1=y
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
 # CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA 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_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-CONFIG_CRYPTO_DEFLATE=y
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
 
 #
-# Hardware crypto devices
+# Compression
 #
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
 CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/sh7763rdp_defconfig b/arch/sh/configs/sh7763rdp_defconfig
new file mode 100644 (file)
index 0000000..83f3fe5
--- /dev/null
@@ -0,0 +1,1052 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc4
+# Fri Jun  6 12:20:17 2008
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=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_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG 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"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG 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
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# 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
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7763=y
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_29BIT=y
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+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_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+CONFIG_SH_SH7763RDP=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_PCLK_FREQ=66666666
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC2,115200 root=/dev/sda1 rootdelay=10"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# 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_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+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
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_BLKDEVS=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+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=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# 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=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# 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
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS 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_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV 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_TABLET 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_DEVKMEM=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=3
+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
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM 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_ISD200 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_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO 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_EXT4DEV_FS is not set
+CONFIG_JBD=y
+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_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# 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 is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# 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 is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_KOI8_U=y
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/sh7785lcr_defconfig b/arch/sh/configs/sh7785lcr_defconfig
new file mode 100644 (file)
index 0000000..ff72697
--- /dev/null
@@ -0,0 +1,1388 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc8
+# Tue Jul 15 21:37:59 2008
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=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_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_NUMA=y
+CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_IO_TRAPPED=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=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_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+# CONFIG_OPROFILE is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+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
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG 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"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG 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
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# 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
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+CONFIG_CPU_SUBTYPE_SH7785=y
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_29BIT=y
+# CONFIG_PMB is not set
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+# CONFIG_NUMA is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=2
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+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_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_HIGHLANDER is not set
+CONFIG_SH_SH7785LCR=y
+CONFIG_SH_SH7785LCR_29BIT_PHYSMAPS=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_GUSA=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# 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_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# 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_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+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
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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 is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x00000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_INTEL_VR_NOR 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
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_NET_ETHERNET is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB 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_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS 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_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_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# 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_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# 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_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SH_KEYSC is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET 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=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI 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=6
+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
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_ALGOPCA=y
+
+#
+# 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_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_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+CONFIG_I2C_PCA_PLATFORM=y
+# CONFIG_I2C_SH_MOBILE is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_SM501=y
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+CONFIG_FB_SM501=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+# CONFIG_LOGO_SUPERH_CLUT224 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+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
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+CONFIG_USB_R8A66597_HCD=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM 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_ISD200 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_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+CONFIG_RTC_DRV_RS5C372=y
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SH is not set
+# CONFIG_UIO 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_EXT4DEV_FS is not set
+CONFIG_JBD=y
+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_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA 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_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_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=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_SUNRPC_BIND34 is not set
+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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+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
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# 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_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_DEBUG_BOOTMEM is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_4KSTACKS is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 0718805774e8760377bb29a929166e8009d278bb..847e90894d1b45e8d43a04696c3310f7e9a7242d 100644 (file)
@@ -23,3 +23,4 @@ obj-$(CONFIG_SH_LANDISK)              += ops-landisk.o
 obj-$(CONFIG_SH_LBOX_RE2)              += ops-lboxre2.o fixups-lboxre2.o
 obj-$(CONFIG_SH_7780_SOLUTION_ENGINE)  += ops-se7780.o fixups-se7780.o
 obj-$(CONFIG_SH_CAYMAN)                        += ops-cayman.o
+obj-$(CONFIG_SH_SH7785LCR)             += ops-sh7785lcr.o fixups-sh7785lcr.o
diff --git a/arch/sh/drivers/pci/fixups-sh7785lcr.c b/arch/sh/drivers/pci/fixups-sh7785lcr.c
new file mode 100644 (file)
index 0000000..4949e60
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * arch/sh/drivers/pci/fixups-sh7785lcr.c
+ *
+ * R0P7785LC0011RL PCI fixups
+ * Copyright (C) 2008  Yoshihiro Shimoda
+ *
+ * Based on arch/sh/drivers/pci/fixups-r7780rp.c
+ * 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"
+
+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 e1284fc693611a266c5b4307f569bf81fa1ff0d7..f54c291db37b1d10d8944f2657b62ba3b396da99 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/pci.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -48,6 +49,7 @@ struct pci_channel board_pci_channels[] = {
          &gapspci_mem_resource, 0, 1 },
        { 0, }
 };
+EXPORT_SYMBOL(board_pci_channels);
 
 /*
  * The !gapspci_config_access case really shouldn't happen, ever, unless
diff --git a/arch/sh/drivers/pci/ops-sh7785lcr.c b/arch/sh/drivers/pci/ops-sh7785lcr.c
new file mode 100644 (file)
index 0000000..b3bd687
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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 R0P7785LC0011RL board
+ * Based on arch/sh/drivers/pci/ops-r7780rp.c
+ *
+ */
+#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 char irq_tab[] __initdata = {
+       65, 66, 67, 68,
+};
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+       return irq_tab[slot];
+}
+
+static struct resource sh7785_io_resource = {
+       .name   = "SH7785_IO",
+       .start  = SH7780_PCI_IO_BASE,
+       .end    = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
+       .flags  = IORESOURCE_IO
+};
+
+static struct resource sh7785_mem_resource = {
+       .name   = "SH7785_mem",
+       .start  = SH7780_PCI_MEMORY_BASE,
+       .end    = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
+       .flags  = IORESOURCE_MEM
+};
+
+struct pci_channel board_pci_channels[] = {
+       { &sh4_pci_ops, &sh7785_io_resource, &sh7785_mem_resource, 0, 0xff },
+       { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh4_pci_address_map sh7785_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(&sh7785_pci_map);
+}
index ea404704ace83b03682bd478f63f5f03f5eaac3b..cf48b12ee58cba02b85192f0ed80cd51f5d92a80 100644 (file)
@@ -78,7 +78,7 @@ static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
 }
 
 #define EARLY_PCI_OP(rw, size, type)                                   \
-int early_##rw##_config_##size(struct pci_channel *hose,               \
+static int early_##rw##_config_##size(struct pci_channel *hose,                \
        int top_bus, int bus, int devfn, int offset, type value)        \
 {                                                                      \
        return pci_##rw##_config_##size(                                \
index f57095a2617c064700fa0ec7123322eddcfadd80..d3839e609aacc1f9d0767c218d716053e139137e 100644 (file)
@@ -135,7 +135,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
  *  If we set up a device for bus mastering, we need to check and set
  *  the latency timer as it may not be properly set.
  */
-unsigned int pcibios_max_latency = 255;
+static unsigned int pcibios_max_latency = 255;
 
 void pcibios_set_master(struct pci_dev *dev)
 {
index 4bbdce36b92b2dd95483202024275ffd1f79bb81..0e6905fe9fec80b54198ba4f7fd1561fac284a65 100644 (file)
@@ -21,7 +21,7 @@ obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_PM)               += pm.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
-obj-$(CONFIG_BINFMT_ELF)       += dump_task.o
+obj-$(CONFIG_ELF_CORE)         += dump_task.o
 obj-$(CONFIG_IO_TRAPPED)       += io_trapped.o
 
 EXTRA_CFLAGS += -Werror
index 01ff4d05aab0303c38cdad719302db33fd904a59..d3d9f32042302f42f2788ba1fd9fe58069553fff 100644 (file)
@@ -157,7 +157,7 @@ static int __init cf_init_se(void)
 }
 #endif
 
-int __init cf_init(void)
+static int __init cf_init(void)
 {
        if (mach_is_se() || mach_is_7722se() || mach_is_7721se())
                return cf_init_se();
index b5f1e23ed57cc3ef68a7bc6f05560f133fd0c8a2..f5eb56e6bc59b8bb68e8b1552f82f64150b527ea 100644 (file)
@@ -88,7 +88,7 @@ static void propagate_rate(struct clk *clk)
        }
 }
 
-int __clk_enable(struct clk *clk)
+static int __clk_enable(struct clk *clk)
 {
        /*
         * See if this is the first time we're enabling the clock, some
@@ -111,7 +111,6 @@ int __clk_enable(struct clk *clk)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(__clk_enable);
 
 int clk_enable(struct clk *clk)
 {
@@ -131,7 +130,7 @@ static void clk_kref_release(struct kref *kref)
        /* Nothing to do */
 }
 
-void __clk_disable(struct clk *clk)
+static void __clk_disable(struct clk *clk)
 {
        int count = kref_put(&clk->kref, clk_kref_release);
 
@@ -143,7 +142,6 @@ void __clk_disable(struct clk *clk)
                        clk->ops->disable(clk);
        }
 }
-EXPORT_SYMBOL_GPL(__clk_disable);
 
 void clk_disable(struct clk *clk)
 {
@@ -310,15 +308,11 @@ static int show_clocks(char *buf, char **start, off_t off,
        list_for_each_entry_reverse(clk, &clock_list, node) {
                unsigned long rate = clk_get_rate(clk);
 
-               /*
-                * Don't bother listing dummy clocks with no ancestry
-                * that only support enable and disable ops.
-                */
-               if (unlikely(!rate && !clk->parent))
-                       continue;
-
-               p += sprintf(p, "%-12s\t: %ld.%02ldMHz\n", clk->name,
-                            rate / 1000000, (rate % 1000000) / 10000);
+               p += sprintf(p, "%-12s\t: %ld.%02ldMHz\t%s\n", clk->name,
+                            rate / 1000000, (rate % 1000000) / 10000,
+                            ((clk->flags & CLK_ALWAYS_ENABLED) ||
+                             (atomic_read(&clk->kref.refcount) != 1)) ?
+                            "enabled" : "disabled");
        }
 
        return p - buf;
index da5dae787888fe104fb78000290b4a0427d6b862..8c70e201bde0ff61994fc179ec02e70746b13bcc 100644 (file)
@@ -62,7 +62,7 @@ struct intc_desc_int {
 #endif
 
 static unsigned int intc_prio_level[NR_IRQS]; /* for now */
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 static unsigned long ack_handle[NR_IRQS];
 #endif
 
@@ -231,7 +231,7 @@ static void intc_disable(unsigned int irq)
        }
 }
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 static void intc_mask_ack(unsigned int irq)
 {
        struct intc_desc_int *d = get_intc_desc(irq);
@@ -244,8 +244,23 @@ static void intc_mask_ack(unsigned int irq)
 
        if (handle) {
                addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
-               ctrl_inb(addr);
-               ctrl_outb(0x3f ^ set_field(0, 1, handle), addr);
+               switch (_INTC_FN(handle)) {
+               case REG_FN_MODIFY_BASE + 0:    /* 8bit */
+                       ctrl_inb(addr);
+                       ctrl_outb(0xff ^ set_field(0, 1, handle), addr);
+                       break;
+               case REG_FN_MODIFY_BASE + 1:    /* 16bit */
+                       ctrl_inw(addr);
+                       ctrl_outw(0xffff ^ set_field(0, 1, handle), addr);
+                       break;
+               case REG_FN_MODIFY_BASE + 3:    /* 32bit */
+                       ctrl_inl(addr);
+                       ctrl_outl(0xffffffff ^ set_field(0, 1, handle), addr);
+                       break;
+               default:
+                       BUG();
+                       break;
+               }
        }
 }
 #endif
@@ -466,7 +481,7 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc,
        return 0;
 }
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 static unsigned int __init intc_ack_data(struct intc_desc *desc,
                                          struct intc_desc_int *d,
                                          intc_enum enum_id)
@@ -601,7 +616,7 @@ static void __init intc_register_irq(struct intc_desc *desc,
        /* irq should be disabled by default */
        d->chip.mask(irq);
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
        if (desc->ack_regs)
                ack_handle[irq] = intc_ack_data(desc, d, enum_id);
 #endif
@@ -635,7 +650,7 @@ void __init register_intc_controller(struct intc_desc *desc)
        d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
        d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
        d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
 #endif
        d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
@@ -676,7 +691,7 @@ void __init register_intc_controller(struct intc_desc *desc)
        d->chip.mask_ack = intc_disable;
        d->chip.set_type = intc_set_sense;
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
        if (desc->ack_regs) {
                for (i = 0; i < desc->nr_ack_regs; i++)
                        k += save_reg(d, k, desc->ack_regs[i].set_reg, 0);
index 0fc89069d8c7cd65566d19d1c06da515000dc014..ee894e5a45e7914315f498c407e2bad3931a3fc4 100644 (file)
@@ -3,7 +3,7 @@
  *
  * The SH-2 exception entry
  *
- * Copyright (C) 2005,2006 Yoshinori Sato
+ * Copyright (C) 2005-2008 Yoshinori Sato
  * Copyright (C) 2005  AXE,Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -36,43 +36,41 @@ OFF_TRA     =  (16*4+6*4)
 #include <asm/entry-macros.S>
 
 ENTRY(exception_handler)
-       ! already saved r0/r1
+       ! stack
+       ! r0 <- point sp
+       ! r1
+       ! pc
+       ! sr
+       ! r0 = temporary
+       ! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
        mov.l   r2,@-sp
        mov.l   r3,@-sp
-       mov     r0,r1
        cli
        mov.l   $cpu_mode,r2
        mov.l   @r2,r0
        mov.l   @(5*4,r15),r3   ! previous SR
-       shll2   r3              ! set "S" flag
-       rotl    r0              ! T <- "S" flag
-       rotl    r0              ! "S" flag is LSB
-       rotcr   r3              ! T -> r3:b30
-       shlr    r3
-       shlr    r0
-       bt/s    1f
-        mov.l  r3,@(5*4,r15)   ! copy cpu mode to SR
+       or      r0,r3           ! set MD
+       tst     r0,r0
+       bf/s    1f              ! previous mode check
+        mov.l  r3,@(5*4,r15)   ! update SR
        ! switch to kernel mode
-       mov     #1,r0
-       rotr    r0
-       rotr    r0
+       mov.l   __md_bit,r0
        mov.l   r0,@r2          ! enter kernel mode
        mov.l   $current_thread_info,r2
        mov.l   @r2,r2
-       mov     #0x20,r0
+       mov     #(THREAD_SIZE >> 8),r0
        shll8   r0
        add     r2,r0
        mov     r15,r2          ! r2 = user stack top
        mov     r0,r15          ! switch kernel stack
-       add     #-4,r15         ! dummy
        mov.l   r1,@-r15        ! TRA
        sts.l   macl, @-r15
        sts.l   mach, @-r15
        stc.l   gbr, @-r15
-       mov.l   @(4*4,r2),r0
-       mov.l   @(5*4,r2),r1
-       mov.l   r1,@-r15        ! original SR
+       mov.l   @(5*4,r2),r0
+       mov.l   r0,@-r15        ! original SR
        sts.l   pr,@-r15
+       mov.l   @(4*4,r2),r0
        mov.l   r0,@-r15        ! original PC
        mov     r2,r3
        add     #(4+2)*4,r3     ! rewind r0 - r3 + exception frame
@@ -88,14 +86,15 @@ ENTRY(exception_handler)
        mov.l   r6,@-r15
        mov.l   r5,@-r15
        mov.l   r4,@-r15
+       mov     r1,r9           ! save TRA
        mov     r2,r8           ! copy user -> kernel stack
-       mov.l   @r8+,r3
+       mov.l   @(0,r8),r3
        mov.l   r3,@-r15
-       mov.l   @r8+,r2
+       mov.l   @(4,r8),r2
        mov.l   r2,@-r15
-       mov.l   @r8+,r1
+       mov.l   @(12,r8),r1
        mov.l   r1,@-r15
-       mov.l   @r8+,r0
+       mov.l   @(8,r8),r0
        bra     2f
         mov.l  r0,@-r15
 1:
@@ -107,10 +106,11 @@ ENTRY(exception_handler)
        mov.l   r0,@-r15        
        mov.l   @r2+,r0         ! old R2
        mov.l   r0,@-r15        
-       mov.l   @r2+,r0         ! old R1
-       mov.l   r0,@-r15        
-       mov.l   @r2+,r0         ! old R0
+       mov.l   @(4,r2),r0      ! old R1
        mov.l   r0,@-r15        
+       mov.l   @r2,r0          ! old R0
+       mov.l   r0,@-r15
+       add     #8,r2
        mov.l   @r2+,r3         ! old PC
        mov.l   @r2+,r0         ! old SR
        add     #-4,r2          ! exception frame stub (sr)
@@ -135,14 +135,12 @@ ENTRY(exception_handler)
        mov.l   r6,@-r2
        mov.l   r5,@-r2
        mov.l   r4,@-r2
+       mov     r1,r9
        mov.l   @(OFF_R0,r15),r0
        mov.l   @(OFF_R1,r15),r1
        mov.l   @(OFF_R2,r15),r2
        mov.l   @(OFF_R3,r15),r3
 2:
-       mov     #OFF_TRA,r8
-       add     r15,r8
-       mov.l   @r8,r9  
        mov     #64,r8
        cmp/hs  r8,r9
        bt      interrupt_entry ! vec >= 64 is interrupt
@@ -150,26 +148,14 @@ ENTRY(exception_handler)
        cmp/hs  r8,r9
        bt      trap_entry      ! 64 > vec >= 32  is trap
 
-#if defined(CONFIG_SH_FPU)
-       mov     #13,r8
-       cmp/eq  r8,r9
-       bt      10f             ! fpu
-       nop
-#endif
-
        mov.l   4f,r8
        mov     r9,r4
        shll2   r9
        add     r9,r8
-       mov.l   @r8,r8
-       mov     #0,r9
-       cmp/eq  r9,r8
+       mov.l   @r8,r8          ! exception handler address
+       tst     r8,r8
        bf      3f
        mov.l   8f,r8           ! unhandled exception
-#if defined(CONFIG_SH_FPU)
-10:
-       mov.l   9f, r8          ! unhandled exception
-#endif
 3:
        mov.l   5f,r10
        jmp     @r8
@@ -188,10 +174,7 @@ interrupt_entry:
 5:     .long   ret_from_exception
 6:     .long   ret_from_irq
 7:     .long   do_IRQ
-8:     .long   do_exception_error
-#ifdef CONFIG_SH_FPU
-9:     .long   fpu_error_trap_handler
-#endif
+8:     .long   exception_error
 
 trap_entry:
        mov     #0x30,r8
@@ -200,24 +183,9 @@ trap_entry:
        add     #-0x10,r9       ! convert SH2 to SH3/4 ABI
 1:     
        shll2   r9                      ! TRA
-       mov     #OFF_TRA,r8
-       add     r15,r8
-       mov.l   r9,@r8
-       mov     r9,r8
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   2f, r9
-       jsr     @r9
-        nop
-#endif
-       sti
-       bra     system_call
-        nop
+       bra     system_call     ! jump common systemcall entry
+        mov    r9,r8
        
-       .align  2
-#ifdef CONFIG_TRACE_IRQFLAGS
-2:     .long   trace_hardirqs_on
-#endif
-
 #if defined(CONFIG_SH_STANDARD_BIOS)
        /* Unwind the stack and jmp to the debug entry */
 ENTRY(sh_bios_handler)
@@ -240,7 +208,7 @@ ENTRY(sh_bios_handler)
        mov.l   @r2,r2
        stc     sr,r3
        mov.l   r2,@r0
-       mov.l   r3,@r0
+       mov.l   r3,@(4,r0)
        mov.l   r1,@(8,r0)      
        mov.l   @r15+, r0
        mov.l   @r15+, r1
@@ -272,22 +240,30 @@ ENTRY(address_error_trap_handler)
        mov.l   1f,r0
        jmp     @r0
         mov    #0,r5                           ! writeaccess is unknown
-       .align  2
 
+       .align  2
 1:     .long   do_address_error
 
 restore_all:
-       cli
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   1f, r0
-       jsr     @r0
-        nop
-#endif
+       stc     sr,r0
+       or      #0xf0,r0
+       ldc     r0,sr                           ! all interrupt block (same BL = 1)
+       ! restore special register
+       ! overlap exception frame
+       mov     r15,r0
+       add     #17*4,r0
+       lds.l   @r0+,pr
+       add     #4,r0
+       ldc.l   @r0+,gbr
+       lds.l   @r0+,mach
+       lds.l   @r0+,macl
        mov     r15,r0
        mov.l   $cpu_mode,r2
        mov     #OFF_SR,r3
        mov.l   @(r0,r3),r1
-       mov.l   r1,@r2
+       mov.l   __md_bit,r3
+       and     r1,r3                           ! copy MD bit
+       mov.l   r3,@r2
        shll2   r1                              ! clear MD bit
        shlr2   r1
        mov.l   @(OFF_SP,r0),r2
@@ -297,12 +273,6 @@ restore_all:
        mov     #OFF_PC,r3
        mov.l   @(r0,r3),r1
        mov.l   r1,@r2                          ! set pc
-       add     #4*16+4,r0
-       lds.l   @r0+,pr
-       add     #4,r0                           ! skip sr
-       ldc.l   @r0+,gbr
-       lds.l   @r0+,mach
-       lds.l   @r0+,macl
        get_current_thread_info r0, r1
        mov.l   $current_thread_info,r1
        mov.l   r0,@r1
@@ -326,9 +296,8 @@ restore_all:
         nop
 
        .align 2
-#ifdef CONFIG_TRACE_IRQFLAGS
-1:     .long   trace_hardirqs_off
-#endif
+__md_bit:
+       .long   0x40000000
 $current_thread_info:
        .long   __current_thread_info
 $cpu_mode:     
index 6d285af7846cb5d1ad8d0d8741fd91a1ff6db28c..85b0bf81fc1d80c304ac01178f80cc68b8082d50 100644 (file)
 exception_entry:       
 no     =       0
        .rept   256
-       mov.l   r0,@-sp
-       mov     #no,r0
+       mov.l   r1,@-sp
        bra     exception_trampoline
-       and     #0xff,r0
+       mov     #no,r1
 no     =       no + 1
        .endr
 exception_trampoline:
-       mov.l   r1,@-sp
-       mov.l   $exception_handler,r1
-       jmp     @r1
+       mov.l   r0,@-sp
+       mov.l   $exception_handler,r0
+       extu.b  r1,r1
+       jmp     @r0
+         extu.w        r1,r1
 
        .align  2
 $exception_entry:
@@ -41,6 +42,6 @@ $exception_handler:
 ENTRY(vbr_base)
 vector =       0
        .rept   256
-       .long   exception_entry + vector * 8
+       .long   exception_entry + vector * 6
 vector =       vector + 1
        .endr
index cc530f4d84d679a1418571319cf3b98be02d18fd..56e5878e55164f69b26aa54500d72227e794a63c 100644 (file)
@@ -96,8 +96,32 @@ static struct platform_device sci_device = {
        },
 };
 
+static struct resource eth_resources[] = {
+       [0] = {
+               .start = 0xfb000000,
+               .end =   0xfb0001c8,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = 85,
+               .end = 85,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device eth_device = {
+       .name = "sh-eth",
+       .id     = -1,
+       .dev = {
+               .platform_data = (void *)1,
+       },
+       .num_resources = ARRAY_SIZE(eth_resources),
+       .resource = eth_resources,
+};
+
 static struct platform_device *sh7619_devices[] __initdata = {
        &sci_device,
+       &eth_device,
 };
 
 static int __init sh7619_devices_setup(void)
index 7e2b90cfa7bf88492e08d253fb100bad5f261273..1ab1ecf4c7685d9a03d077c788c66ec85b70729b 100644 (file)
@@ -4,7 +4,7 @@
 
 obj-y  := common.o probe.o opcode_helper.o
 
-common-y       += $(addprefix ../sh2/, ex.o entry.o)
+common-y       += ex.o entry.o
 
 obj-$(CONFIG_SH_FPU)   += fpu.o
 
diff --git a/arch/sh/kernel/cpu/sh2a/entry.S b/arch/sh/kernel/cpu/sh2a/entry.S
new file mode 100644 (file)
index 0000000..47096dc
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/entry.S
+ *
+ * The SH-2A exception entry
+ *
+ * Copyright (C) 2008 Yoshinori Sato
+ * Based on arch/sh/kernel/cpu/sh2/entry.S
+ *
+ * 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/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/cpu/mmu_context.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/page.h>
+       
+/* Offsets to the stack */
+OFF_R0  =  0           /* Return value. New ABI also arg4 */
+OFF_R1  =  4           /* New ABI: arg5 */
+OFF_R2  =  8           /* New ABI: arg6 */
+OFF_R3  =  12          /* New ABI: syscall_nr */
+OFF_R4  =  16          /* New ABI: arg0 */
+OFF_R5  =  20          /* New ABI: arg1 */
+OFF_R6  =  24          /* New ABI: arg2 */
+OFF_R7  =  28          /* New ABI: arg3 */
+OFF_SP =  (15*4)
+OFF_PC  =  (16*4)
+OFF_SR =  (16*4+2*4)
+OFF_TRA        =  (16*4+6*4)
+
+#include <asm/entry-macros.S>
+
+ENTRY(exception_handler)
+       ! stack
+       ! r0 <- point sp
+       ! r1
+       ! pc
+       ! sr
+       ! r0 = temporary
+       ! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
+       mov.l   r2,@-sp
+       cli
+       mov.l   $cpu_mode,r2
+       bld.b   #6,@(0,r2)      !previus SR.MD
+       bst.b   #6,@(4*4,r15)   !set cpu mode to SR.MD
+       bt      1f
+       ! switch to kernel mode
+       bset.b  #6,@(0,r2)      !set SR.MD
+       mov.l   $current_thread_info,r2
+       mov.l   @r2,r2
+       mov     #(THREAD_SIZE >> 8),r0
+       shll8   r0
+       add     r2,r0           ! r0 = kernel stack tail
+       mov     r15,r2          ! r2 = user stack top
+       mov     r0,r15          ! switch kernel stack
+       mov.l   r1,@-r15        ! TRA
+       sts.l   macl, @-r15
+       sts.l   mach, @-r15
+       stc.l   gbr, @-r15
+       mov.l   @(4*4,r2),r0
+       mov.l   r0,@-r15        ! original SR
+       sts.l   pr,@-r15
+       mov.l   @(3*4,r2),r0
+       mov.l   r0,@-r15        ! original PC
+       mov     r2,r0
+       add     #(3+2)*4,r0     ! rewind r0 - r3 + exception frame
+       lds     r0,pr           ! pr = original SP
+       movmu.l r3,@-r15        ! save regs
+       mov     r2,r8           ! r8 =  previus stack top
+       mov     r1,r9           ! r9 = interrupt vector
+       ! restore previous stack
+       mov.l   @r8+,r2
+       mov.l   @r8+,r0
+       mov.l   @r8+,r1
+       bra     2f
+        movml.l r2,@-r15
+1:
+       ! in kernel exception
+       mov     r15,r2
+       add     #-((OFF_TRA + 4) - OFF_PC) + 5*4,r15
+       movmu.l r3,@-r15
+       mov     r2,r8           ! r8 = previous stack top
+       mov     r1,r9           ! r9 = interrupt vector
+       ! restore exception frame & regs
+       mov.l   @r8+,r2         ! old R2
+       mov.l   @r8+,r0         ! old R0
+       mov.l   @r8+,r1         ! old R1
+       mov.l   @r8+,r10        ! old PC
+       mov.l   @r8+,r11        ! old SR
+       movml.l r2,@-r15
+       mov.l   r10,@(OFF_PC,r15)
+       mov.l   r11,@(OFF_SR,r15)
+       mov.l   r8,@(OFF_SP,r15)        ! save old sp
+       mov     r15,r8
+       add     #OFF_TRA + 4,r8
+       mov.l   r9,@-r8
+       sts.l   macl,@-r8
+       sts.l   mach,@-r8
+       stc.l   gbr,@-r8
+       add     #-4,r8
+       sts.l   pr,@-r8
+2:
+       ! dispatch exception / interrupt
+       mov     #64,r8
+       cmp/hs  r8,r9
+       bt      interrupt_entry ! vec >= 64 is interrupt
+       mov     #32,r8
+       cmp/hs  r8,r9
+       bt      trap_entry      ! 64 > vec >= 32  is trap
+
+       mov.l   4f,r8
+       mov     r9,r4
+       shll2   r9
+       add     r9,r8
+       mov.l   @r8,r8          ! exception handler address
+       tst     r8,r8
+       bf      3f
+       mov.l   8f,r8           ! unhandled exception
+3:
+       mov.l   5f,r10
+       jmp     @r8
+        lds    r10,pr
+
+interrupt_entry:
+       mov     r9,r4
+       mov     r15,r5
+       mov.l   7f,r8
+       mov.l   6f,r9
+       jmp     @r8
+        lds    r9,pr
+
+       .align  2
+4:     .long   exception_handling_table
+5:     .long   ret_from_exception
+6:     .long   ret_from_irq
+7:     .long   do_IRQ
+8:     .long   exception_error
+
+trap_entry:
+       mov     #0x30,r8
+       cmp/ge  r8,r9           ! vector 0x20-0x2f is systemcall
+       bt      1f
+       add     #-0x10,r9       ! convert SH2 to SH3/4 ABI
+1:     
+       shll2   r9                      ! TRA
+       bra     system_call     ! jump common systemcall entry
+        mov    r9,r8
+       
+#if defined(CONFIG_SH_STANDARD_BIOS)
+       /* Unwind the stack and jmp to the debug entry */
+ENTRY(sh_bios_handler)
+       mov     r15,r0
+       add     #(22-4)*4-4,r0
+       ldc.l   @r0+,gbr
+       lds.l   @r0+,mach
+       lds.l   @r0+,macl
+       mov     r15,r0
+       mov.l   @(OFF_SP,r0),r1
+       mov.l   @(OFF_SR,r2),r3
+       mov.l   r3,@-r1
+       mov.l   @(OFF_SP,r2),r3
+       mov.l   r3,@-r1
+       mov     r15,r0
+       add     #(22-4)*4-8,r0
+       mov.l   1f,r2
+       mov.l   @r2,r2
+       stc     sr,r3
+       mov.l   r2,@r0
+       mov.l   r3,@(4,r0)
+       mov.l   r1,@(8,r0)
+       movml.l @r15+,r14
+       add     #8,r15
+       lds.l   @r15+, pr
+       rte
+        mov.l  @r15+,r15
+       .align  2
+1:     .long   gdb_vbr_vector
+#endif /* CONFIG_SH_STANDARD_BIOS */
+
+ENTRY(address_error_trap_handler)
+       mov     r15,r4                          ! regs
+       mov.l   @(OFF_PC,r15),r6                ! pc
+       mov.l   1f,r0
+       jmp     @r0
+        mov    #0,r5                           ! writeaccess is unknown
+
+       .align  2
+1:     .long   do_address_error
+
+restore_all:
+       stc     sr,r0
+       or      #0xf0,r0
+       ldc     r0,sr                           ! all interrupt block (same BL = 1)
+       ! restore special register
+       ! overlap exception frame
+       mov     r15,r0
+       add     #17*4,r0
+       lds.l   @r0+,pr
+       add     #4,r0
+       ldc.l   @r0+,gbr
+       lds.l   @r0+,mach
+       lds.l   @r0+,macl
+       mov     r15,r0
+       mov.l   $cpu_mode,r2
+       bld.b   #6,@(OFF_SR,r15)
+       bst.b   #6,@(0,r2)                      ! save CPU mode
+       mov.l   @(OFF_SR,r0),r1
+       shll2   r1
+       shlr2   r1                              ! clear MD bit
+       mov.l   @(OFF_SP,r0),r2
+       add     #-8,r2
+       mov.l   r2,@(OFF_SP,r0)                 ! point exception frame top
+       mov.l   r1,@(4,r2)                      ! set sr
+       mov.l   @(OFF_PC,r0),r1
+       mov.l   r1,@r2                          ! set pc
+       get_current_thread_info r0, r1
+       mov.l   $current_thread_info,r1
+       mov.l   r0,@r1
+       movml.l @r15+,r14
+       mov.l   @r15,r15
+       rte
+        nop
+
+       .align 2
+$current_thread_info:
+       .long   __current_thread_info
+$cpu_mode:     
+       .long   __cpu_mode
+               
+! common exception handler
+#include "../../entry-common.S"
+       
+       .data
+! cpu operation mode 
+! bit30 = MD (compatible SH3/4)
+__cpu_mode:
+       .long   0x40000000
+               
+       .section        .bss
+__current_thread_info:
+       .long   0
+
+ENTRY(exception_handling_table)
+       .space  4*32
diff --git a/arch/sh/kernel/cpu/sh2a/ex.S b/arch/sh/kernel/cpu/sh2a/ex.S
new file mode 100644 (file)
index 0000000..3ead9e6
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/ex.S
+ *
+ * The SH-2A exception vector table
+ *
+ * Copyright (C) 2008 Yoshinori Sato
+ *
+ * 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>
+
+!
+! convert Exception Vector to Exception Number
+!
+
+! exception no 0 to 255
+exception_entry0:
+no     =       0
+       .rept   256
+       mov.l   r1,@-sp
+       bra     exception_trampoline0
+       mov     #no,r1
+no     =       no + 1
+       .endr
+exception_trampoline0:
+       mov.l   r0,@-sp
+       mov.l   1f,r0
+       extu.b  r1,r1
+       jmp     @r0
+         extu.w        r1,r1
+        
+       .align  2
+1:     .long   exception_handler
+
+! exception no 256 to 511
+exception_entry1:
+no     =       0
+       .rept   256
+       mov.l   r1,@-sp
+       bra     exception_trampoline1
+       mov     #no,r1
+no     =       no + 1
+       .endr
+exception_trampoline1:
+       mov.l   r0,@-sp
+       extu.b  r1,r1
+       movi20  #0x100,r0
+       add     r0,r1
+       mov.l   1f,r0
+       jmp     @r0
+         extu.w        r1,r1
+       
+       .align  2
+1:     .long   exception_handler
+
+       !
+! Exception Vector Base
+!
+       .align  2
+ENTRY(vbr_base)
+vector =       0
+       .rept   256
+       .long   exception_entry0 + vector * 6
+vector =       vector + 1
+       .endr
+       .rept   256
+       .long   exception_entry1 + vector * 6
+vector =       vector + 1
+       .endr
index 11b6d9c6edaefabbb8040004e31db7a7d6edbdff..dac42972689932b00100fd1c3a654a26aa61d1e9 100644 (file)
@@ -4,7 +4,7 @@
  *  The SH-3 and SH-4 exception vector table.
 
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- *  Copyright (C) 2003 - 2006  Paul Mundt
+ *  Copyright (C) 2003 - 2008  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
  */
 #include <linux/linkage.h>
 
+#if !defined(CONFIG_MMU)
+#define        tlb_miss_load                   exception_error
+#define tlb_miss_store                 exception_error
+#define initial_page_write             exception_error
+#define tlb_protection_violation_load  exception_error
+#define tlb_protection_violation_store exception_error
+#define address_error_load             exception_error
+#define address_error_store            exception_error
+#endif
+
+#if !defined(CONFIG_SH_FPU)
+#define        fpu_error_trap_handler          exception_error
+#endif
+
+#if !defined(CONFIG_KGDB_NMI)
+#define kgdb_handle_exception          exception_error
+#endif
+
        .align 2
        .data
 
 ENTRY(exception_handling_table)
        .long   exception_error         /* 000 */
        .long   exception_error
-#if defined(CONFIG_MMU)
        .long   tlb_miss_load           /* 040 */
        .long   tlb_miss_store
        .long   initial_page_write
@@ -26,30 +43,13 @@ ENTRY(exception_handling_table)
        .long   tlb_protection_violation_store
        .long   address_error_load
        .long   address_error_store     /* 100 */
-#else
-       .long   exception_error ! tlb miss load         /* 040 */
-       .long   exception_error ! tlb miss store
-       .long   exception_error ! initial page write
-       .long   exception_error ! tlb prot violation load
-       .long   exception_error ! tlb prot violation store
-       .long   exception_error ! address error load
-       .long   exception_error ! address error store   /* 100 */
-#endif
-#if defined(CONFIG_SH_FPU)
        .long   fpu_error_trap_handler  /* 120 */
-#else
-       .long   exception_error         /* 120 */
-#endif
        .long   exception_error         /* 140 */
        .long   system_call     ! Unconditional Trap     /* 160 */
        .long   exception_error ! reserved_instruction (filled by trap_init) /* 180 */
        .long   exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
 ENTRY(nmi_slot)
-#if defined (CONFIG_KGDB_NMI)
        .long   kgdb_handle_exception   /* 1C0 */       ! Allow trap to debugger
-#else
-       .long   exception_none  /* 1C0 */       ! Not implemented yet
-#endif
 ENTRY(user_break_point_trap)
        .long   break_point_trap        /* 1E0 */
 
index be4926969181299d26339c5dcefd84be2ae41f46..2e42572b1b119aa832c50a104d8f4fd5c1fe0acf 100644 (file)
@@ -50,14 +50,18 @@ int __init detect_cpu_and_cache_system(void)
        boot_cpu_data.dcache.ways               = 1;
        boot_cpu_data.dcache.linesz             = L1_CACHE_BYTES;
 
+       /* We don't know the chip cut */
+       boot_cpu_data.cut_major = boot_cpu_data.cut_minor = -1;
+
        /*
         * Setup some generic flags we can probe on SH-4A parts
         */
-       if (((pvr >> 24) & 0xff) == 0x10) {
+       if (((pvr >> 16) & 0xff) == 0x10) {
                if ((cvr & 0x10000000) == 0)
                        boot_cpu_data.flags |= CPU_HAS_DSP;
 
                boot_cpu_data.flags |= CPU_HAS_LLSC;
+               boot_cpu_data.cut_major = pvr & 0x7f;
        }
 
        /* FPU detection works for everyone */
index a880e7968750a63aa3aba1ae4ea3fcd477d06b82..9381ad8da263825164922874529c794d2ebb8223 100644 (file)
@@ -21,7 +21,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7763)    := clock-sh7763.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7770)     := clock-sh7770.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7780)     := clock-sh7780.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7785)     := clock-sh7785.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7343)     := clock-sh7343.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7343)     := clock-sh7722.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7722)     := clock-sh7722.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7723)     := clock-sh7722.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7366)     := clock-sh7722.o
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
deleted file mode 100644 (file)
index 7adc4f1..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * arch/sh/kernel/cpu/sh4a/clock-sh7343.c
- *
- * SH7343/SH7722 support for the clock framework
- *
- *  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/kernel.h>
-#include <linux/io.h>
-#include <asm/clock.h>
-#include <asm/freq.h>
-
-/*
- * SH7343/SH7722 uses a common set of multipliers and divisors, so this
- * is quite simple..
- */
-static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
-static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
-
-#define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1)
-
-static void master_clk_init(struct clk *clk)
-{
-       clk->parent = clk_get(NULL, "cpu_clk");
-}
-
-static void master_clk_recalc(struct clk *clk)
-{
-       int idx = (ctrl_inl(FRQCR) & 0x000f);
-       clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx];
-}
-
-static struct clk_ops sh7343_master_clk_ops = {
-       .init           = master_clk_init,
-       .recalc         = master_clk_recalc,
-};
-
-static void module_clk_init(struct clk *clk)
-{
-       clk->parent = NULL;
-       clk->rate = CONFIG_SH_PCLK_FREQ;
-}
-
-static struct clk_ops sh7343_module_clk_ops = {
-       .init           = module_clk_init,
-};
-
-static void bus_clk_init(struct clk *clk)
-{
-       clk->parent = clk_get(NULL, "cpu_clk");
-}
-
-static void bus_clk_recalc(struct clk *clk)
-{
-       int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f;
-       clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx];
-}
-
-static struct clk_ops sh7343_bus_clk_ops = {
-       .init           = bus_clk_init,
-       .recalc         = bus_clk_recalc,
-};
-
-static void cpu_clk_init(struct clk *clk)
-{
-       clk->parent = clk_get(NULL, "module_clk");
-       clk->flags |= CLK_RATE_PROPAGATES;
-       clk_set_rate(clk, clk_get_rate(clk));
-}
-
-static void cpu_clk_recalc(struct clk *clk)
-{
-       int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f;
-       clk->rate = clk->parent->rate * pll_calc() *
-               multipliers[idx] / divisors[idx];
-}
-
-static struct clk_ops sh7343_cpu_clk_ops = {
-       .init           = cpu_clk_init,
-       .recalc         = cpu_clk_recalc,
-};
-
-static struct clk_ops *sh7343_clk_ops[] = {
-       &sh7343_master_clk_ops,
-       &sh7343_module_clk_ops,
-       &sh7343_bus_clk_ops,
-       &sh7343_cpu_clk_ops,
-};
-
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
-       if (idx < ARRAY_SIZE(sh7343_clk_ops))
-               *ops = sh7343_clk_ops[idx];
-}
index 299138ebe1607263632b3124006610e12c23368d..db913855c2fd24fc81e3a1cac39997a4df1b09d1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7722.c
  *
- * SH7722 & SH7366 support for the clock framework
+ * SH7343, SH7722, SH7723 & SH7366 support for the clock framework
  *
  * Copyright (c) 2006-2007 Nomad Global Solutions Inc
  * Based on code for sh7343 by Paul Mundt
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/errno.h>
+#include <linux/stringify.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
@@ -411,40 +412,40 @@ static struct clk_ops sh7722_frqcr_clk_ops = {
  * clock ops methods for SIU A/B and IrDA clock
  *
  */
-static int sh7722_siu_which(struct clk *clk)
+
+#ifndef CONFIG_CPU_SUBTYPE_SH7343
+
+static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id)
 {
-       if (!strcmp(clk->name, "siu_a_clk"))
-               return 0;
-       if (!strcmp(clk->name, "siu_b_clk"))
-               return 1;
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-       if (!strcmp(clk->name, "irda_clk"))
-               return 2;
-#endif
-       return -EINVAL;
+       unsigned long r;
+       int div;
+
+       r = ctrl_inl(clk->arch_flags);
+       div = sh7722_find_divisors(clk->parent->rate, rate);
+       if (div < 0)
+               return div;
+       r = (r & ~0xF) | div;
+       ctrl_outl(r, clk->arch_flags);
+       return 0;
 }
 
-static unsigned long sh7722_siu_regs[] = {
-       [0] = SCLKACR,
-       [1] = SCLKBCR,
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-       [2] = IrDACLKCR,
-#endif
-};
+static void sh7722_siu_recalc(struct clk *clk)
+{
+       unsigned long r;
+
+       r = ctrl_inl(clk->arch_flags);
+       clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF];
+}
 
 static int sh7722_siu_start_stop(struct clk *clk, int enable)
 {
-       int siu = sh7722_siu_which(clk);
        unsigned long r;
 
-       if (siu < 0)
-               return siu;
-       BUG_ON(siu > 2);
-       r = ctrl_inl(sh7722_siu_regs[siu]);
+       r = ctrl_inl(clk->arch_flags);
        if (enable)
-               ctrl_outl(r & ~(1 << 8), sh7722_siu_regs[siu]);
+               ctrl_outl(r & ~(1 << 8), clk->arch_flags);
        else
-               ctrl_outl(r | (1 << 8), sh7722_siu_regs[siu]);
+               ctrl_outl(r | (1 << 8), clk->arch_flags);
        return 0;
 }
 
@@ -458,6 +459,15 @@ static void sh7722_siu_disable(struct clk *clk)
        sh7722_siu_start_stop(clk, 0);
 }
 
+static struct clk_ops sh7722_siu_clk_ops = {
+       .recalc = sh7722_siu_recalc,
+       .set_rate = sh7722_siu_set_rate,
+       .enable = sh7722_siu_enable,
+       .disable = sh7722_siu_disable,
+};
+
+#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
+
 static void sh7722_video_enable(struct clk *clk)
 {
        unsigned long r;
@@ -494,43 +504,6 @@ static void sh7722_video_recalc(struct clk *clk)
        clk->rate = clk->parent->rate / ((r & 0x3F) + 1);
 }
 
-static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id)
-{
-       int siu = sh7722_siu_which(clk);
-       unsigned long r;
-       int div;
-
-       if (siu < 0)
-               return siu;
-       BUG_ON(siu > 2);
-       r = ctrl_inl(sh7722_siu_regs[siu]);
-       div = sh7722_find_divisors(clk->parent->rate, rate);
-       if (div < 0)
-               return div;
-       r = (r & ~0xF) | div;
-       ctrl_outl(r, sh7722_siu_regs[siu]);
-       return 0;
-}
-
-static void sh7722_siu_recalc(struct clk *clk)
-{
-       int siu = sh7722_siu_which(clk);
-       unsigned long r;
-
-       if (siu < 0)
-               return /* siu */ ;
-       BUG_ON(siu > 2);
-       r = ctrl_inl(sh7722_siu_regs[siu]);
-       clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF];
-}
-
-static struct clk_ops sh7722_siu_clk_ops = {
-       .recalc = sh7722_siu_recalc,
-       .set_rate = sh7722_siu_set_rate,
-       .enable = sh7722_siu_enable,
-       .disable = sh7722_siu_disable,
-};
-
 static struct clk_ops sh7722_video_clk_ops = {
        .recalc = sh7722_video_recalc,
        .set_rate = sh7722_video_set_rate,
@@ -560,6 +533,9 @@ static struct clk sh7722_sdram_clock = {
        .ops = &sh7722_frqcr_clk_ops,
 };
 
+
+#ifndef CONFIG_CPU_SUBTYPE_SH7343
+
 /*
  * these three clocks - SIU A, SIU B, IrDA - share the same clk_ops
  * methods of clk_ops determine which register they should access by
@@ -567,35 +543,150 @@ static struct clk sh7722_sdram_clock = {
  */
 static struct clk sh7722_siu_a_clock = {
        .name = "siu_a_clk",
+       .arch_flags = SCLKACR,
        .ops = &sh7722_siu_clk_ops,
 };
 
 static struct clk sh7722_siu_b_clock = {
        .name = "siu_b_clk",
+       .arch_flags = SCLKBCR,
        .ops = &sh7722_siu_clk_ops,
 };
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7722)
 static struct clk sh7722_irda_clock = {
        .name = "irda_clk",
+       .arch_flags = IrDACLKCR,
        .ops = &sh7722_siu_clk_ops,
 };
 #endif
+#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
 
 static struct clk sh7722_video_clock = {
        .name = "video_clk",
        .ops = &sh7722_video_clk_ops,
 };
 
+static int sh7722_mstpcr_start_stop(struct clk *clk, unsigned long reg,
+                                   int enable)
+{
+       unsigned long bit = clk->arch_flags;
+       unsigned long r;
+
+       r = ctrl_inl(reg);
+
+       if (enable)
+               r &= ~(1 << bit);
+       else
+               r |= (1 << bit);
+
+       ctrl_outl(r, reg);
+       return 0;
+}
+
+static void sh7722_mstpcr0_enable(struct clk *clk)
+{
+       sh7722_mstpcr_start_stop(clk, MSTPCR0, 1);
+}
+
+static void sh7722_mstpcr0_disable(struct clk *clk)
+{
+       sh7722_mstpcr_start_stop(clk, MSTPCR0, 0);
+}
+
+static void sh7722_mstpcr1_enable(struct clk *clk)
+{
+       sh7722_mstpcr_start_stop(clk, MSTPCR1, 1);
+}
+
+static void sh7722_mstpcr1_disable(struct clk *clk)
+{
+       sh7722_mstpcr_start_stop(clk, MSTPCR1, 0);
+}
+
+static void sh7722_mstpcr2_enable(struct clk *clk)
+{
+       sh7722_mstpcr_start_stop(clk, MSTPCR2, 1);
+}
+
+static void sh7722_mstpcr2_disable(struct clk *clk)
+{
+       sh7722_mstpcr_start_stop(clk, MSTPCR2, 0);
+}
+
+static struct clk_ops sh7722_mstpcr0_clk_ops = {
+       .enable = sh7722_mstpcr0_enable,
+       .disable = sh7722_mstpcr0_disable,
+};
+
+static struct clk_ops sh7722_mstpcr1_clk_ops = {
+       .enable = sh7722_mstpcr1_enable,
+       .disable = sh7722_mstpcr1_disable,
+};
+
+static struct clk_ops sh7722_mstpcr2_clk_ops = {
+       .enable = sh7722_mstpcr2_enable,
+       .disable = sh7722_mstpcr2_disable,
+};
+
+#define DECLARE_MSTPCRN(regnr, bitnr, bitstr)          \
+{                                                      \
+       .name = "mstp" __stringify(regnr) bitstr,       \
+       .arch_flags = bitnr,                            \
+       .ops = &sh7722_mstpcr ## regnr ## _clk_ops,     \
+}
+
+#define DECLARE_MSTPCR(regnr) \
+       DECLARE_MSTPCRN(regnr, 31, "31"), \
+       DECLARE_MSTPCRN(regnr, 30, "30"), \
+       DECLARE_MSTPCRN(regnr, 29, "29"), \
+       DECLARE_MSTPCRN(regnr, 28, "28"), \
+       DECLARE_MSTPCRN(regnr, 27, "27"), \
+       DECLARE_MSTPCRN(regnr, 26, "26"), \
+       DECLARE_MSTPCRN(regnr, 25, "25"), \
+       DECLARE_MSTPCRN(regnr, 24, "24"), \
+       DECLARE_MSTPCRN(regnr, 23, "23"), \
+       DECLARE_MSTPCRN(regnr, 22, "22"), \
+       DECLARE_MSTPCRN(regnr, 21, "21"), \
+       DECLARE_MSTPCRN(regnr, 20, "20"), \
+       DECLARE_MSTPCRN(regnr, 19, "19"), \
+       DECLARE_MSTPCRN(regnr, 18, "18"), \
+       DECLARE_MSTPCRN(regnr, 17, "17"), \
+       DECLARE_MSTPCRN(regnr, 16, "16"), \
+       DECLARE_MSTPCRN(regnr, 15, "15"), \
+       DECLARE_MSTPCRN(regnr, 14, "14"), \
+       DECLARE_MSTPCRN(regnr, 13, "13"), \
+       DECLARE_MSTPCRN(regnr, 12, "12"), \
+       DECLARE_MSTPCRN(regnr, 11, "11"), \
+       DECLARE_MSTPCRN(regnr, 10, "10"), \
+       DECLARE_MSTPCRN(regnr, 9, "09"), \
+       DECLARE_MSTPCRN(regnr, 8, "08"), \
+       DECLARE_MSTPCRN(regnr, 7, "07"), \
+       DECLARE_MSTPCRN(regnr, 6, "06"), \
+       DECLARE_MSTPCRN(regnr, 5, "05"), \
+       DECLARE_MSTPCRN(regnr, 4, "04"), \
+       DECLARE_MSTPCRN(regnr, 3, "03"), \
+       DECLARE_MSTPCRN(regnr, 2, "02"), \
+       DECLARE_MSTPCRN(regnr, 1, "01"), \
+       DECLARE_MSTPCRN(regnr, 0, "00")
+
+static struct clk sh7722_mstpcr[] = {
+       DECLARE_MSTPCR(0),
+       DECLARE_MSTPCR(1),
+       DECLARE_MSTPCR(2),
+};
+
 static struct clk *sh7722_clocks[] = {
        &sh7722_umem_clock,
        &sh7722_sh_clock,
        &sh7722_peripheral_clock,
        &sh7722_sdram_clock,
+#ifndef CONFIG_CPU_SUBTYPE_SH7343
        &sh7722_siu_a_clock,
        &sh7722_siu_b_clock,
 #if defined(CONFIG_CPU_SUBTYPE_SH7722)
        &sh7722_irda_clock,
+#endif
 #endif
        &sh7722_video_clock,
 };
@@ -629,5 +720,11 @@ int __init arch_clk_init(void)
                clk_register(sh7722_clocks[i]);
        }
        clk_put(master);
+
+       for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr); i++) {
+               pr_debug( "Registering mstpcr '%s'\n", sh7722_mstpcr[i].name);
+               clk_register(&sh7722_mstpcr[i]);
+       }
+
        return 0;
 }
index 6d4f50cd4aaf62ece55cce91bdab88c134f6e165..78881b4214da8e8a94ad366e0e3843cc586f9360 100644 (file)
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/uio_driver.h>
+#include <asm/clock.h>
+
+static struct resource iic0_resources[] = {
+       [0] = {
+               .name   = "IIC0",
+               .start  = 0x04470000,
+               .end    = 0x04470017,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 96,
+               .end    = 99,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device iic0_device = {
+       .name           = "i2c-sh_mobile",
+       .num_resources  = ARRAY_SIZE(iic0_resources),
+       .resource       = iic0_resources,
+};
+
+static struct resource iic1_resources[] = {
+       [0] = {
+               .name   = "IIC1",
+               .start  = 0x04750000,
+               .end    = 0x04750017,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 44,
+               .end    = 47,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device iic1_device = {
+       .name           = "i2c-sh_mobile",
+       .num_resources  = ARRAY_SIZE(iic1_resources),
+       .resource       = iic1_resources,
+};
+
+static struct uio_info vpu_platform_data = {
+       .name = "VPU4",
+       .version = "0",
+       .irq = 60,
+};
+
+static struct resource vpu_resources[] = {
+       [0] = {
+               .name   = "VPU",
+               .start  = 0xfe900000,
+               .end    = 0xfe9022eb,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device vpu_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 0,
+       .dev = {
+               .platform_data  = &vpu_platform_data,
+       },
+       .resource       = vpu_resources,
+       .num_resources  = ARRAY_SIZE(vpu_resources),
+};
+
+static struct uio_info veu_platform_data = {
+       .name = "VEU",
+       .version = "0",
+       .irq = 54,
+};
+
+static struct resource veu_resources[] = {
+       [0] = {
+               .name   = "VEU",
+               .start  = 0xfe920000,
+               .end    = 0xfe9200b7,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device veu_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 1,
+       .dev = {
+               .platform_data  = &veu_platform_data,
+       },
+       .resource       = veu_resources,
+       .num_resources  = ARRAY_SIZE(veu_resources),
+};
 
 static struct plat_sci_port sci_platform_data[] = {
        {
@@ -32,16 +130,171 @@ static struct platform_device sci_device = {
 };
 
 static struct platform_device *sh7343_devices[] __initdata = {
+       &iic0_device,
+       &iic1_device,
        &sci_device,
+       &vpu_device,
+       &veu_device,
 };
 
 static int __init sh7343_devices_setup(void)
 {
+       clk_always_enable("mstp031"); /* TLB */
+       clk_always_enable("mstp030"); /* IC */
+       clk_always_enable("mstp029"); /* OC */
+       clk_always_enable("mstp028"); /* URAM */
+       clk_always_enable("mstp026"); /* XYMEM */
+       clk_always_enable("mstp023"); /* INTC3 */
+       clk_always_enable("mstp022"); /* INTC */
+       clk_always_enable("mstp020"); /* SuperHyway */
+       clk_always_enable("mstp109"); /* I2C0 */
+       clk_always_enable("mstp108"); /* I2C1 */
+       clk_always_enable("mstp202"); /* VEU */
+       clk_always_enable("mstp201"); /* VPU */
+
+       platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20);
+       platform_resource_setup_memory(&veu_device, "veu", 2 << 20);
+
        return platform_add_devices(sh7343_devices,
                                    ARRAY_SIZE(sh7343_devices));
 }
 __initcall(sh7343_devices_setup);
 
+enum {
+       UNUSED = 0,
+
+       /* interrupt sources */
+       IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+       DMAC0, DMAC1, DMAC2, DMAC3,
+       VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU,
+       MFI, VPU, TPU, Z3D4, USBI0, USBI1,
+       MMC_ERR, MMC_TRAN, MMC_FSTAT, MMC_FRDY,
+       DMAC4, DMAC5, DMAC_DADERR,
+       KEYSC,
+       SCIF, SCIF1, SCIF2, SCIF3, SCIF4,
+       SIOF0, SIOF1, SIO,
+       FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
+       I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI,
+       I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI,
+       SIM_TEI, SIM_TXI, SIM_RXI, SIM_ERI,
+       IRDA,
+       SDHI0, SDHI1, SDHI2, SDHI3,
+       CMT, TSIF, SIU,
+       TMU0, TMU1, TMU2,
+       JPU, LCDC,
+
+       /* interrupt groups */
+
+       DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C0, I2C1, SIM, SDHI, USB,
+};
+
+static struct intc_vect vectors[] __initdata = {
+       INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
+       INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
+       INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
+       INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0),
+       INTC_VECT(I2C1_ALI, 0x780), INTC_VECT(I2C1_TACKI, 0x7a0),
+       INTC_VECT(I2C1_WAITI, 0x7c0), INTC_VECT(I2C1_DTEI, 0x7e0),
+       INTC_VECT(DMAC0, 0x800), INTC_VECT(DMAC1, 0x820),
+       INTC_VECT(DMAC2, 0x840), INTC_VECT(DMAC3, 0x860),
+       INTC_VECT(VIO_CEUI, 0x880), INTC_VECT(VIO_BEUI, 0x8a0),
+       INTC_VECT(VIO_VEUI, 0x8c0), INTC_VECT(VOU, 0x8e0),
+       INTC_VECT(MFI, 0x900), INTC_VECT(VPU, 0x980),
+       INTC_VECT(TPU, 0x9a0), INTC_VECT(Z3D4, 0x9e0),
+       INTC_VECT(USBI0, 0xa20), INTC_VECT(USBI1, 0xa40),
+       INTC_VECT(MMC_ERR, 0xb00), INTC_VECT(MMC_TRAN, 0xb20),
+       INTC_VECT(MMC_FSTAT, 0xb40), INTC_VECT(MMC_FRDY, 0xb60),
+       INTC_VECT(DMAC4, 0xb80), INTC_VECT(DMAC5, 0xba0),
+       INTC_VECT(DMAC_DADERR, 0xbc0), INTC_VECT(KEYSC, 0xbe0),
+       INTC_VECT(SCIF, 0xc00), INTC_VECT(SCIF1, 0xc20),
+       INTC_VECT(SCIF2, 0xc40), INTC_VECT(SCIF3, 0xc60),
+       INTC_VECT(SIOF0, 0xc80), INTC_VECT(SIOF1, 0xca0),
+       INTC_VECT(SIO, 0xd00),
+       INTC_VECT(FLCTL_FLSTEI, 0xd80), INTC_VECT(FLCTL_FLENDI, 0xda0),
+       INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0),
+       INTC_VECT(I2C0_ALI, 0xe00), INTC_VECT(I2C0_TACKI, 0xe20),
+       INTC_VECT(I2C0_WAITI, 0xe40), INTC_VECT(I2C0_DTEI, 0xe60),
+       INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0),
+       INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0),
+       INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20),
+       INTC_VECT(SIU, 0xf80),
+       INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+       INTC_VECT(TMU2, 0x440),
+       INTC_VECT(JPU, 0x560), INTC_VECT(LCDC, 0x580),
+};
+
+static struct intc_group groups[] __initdata = {
+       INTC_GROUP(DMAC0123, DMAC0, DMAC1, DMAC2, DMAC3),
+       INTC_GROUP(VIOVOU, VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU),
+       INTC_GROUP(MMC, MMC_FRDY, MMC_FSTAT, MMC_TRAN, MMC_ERR),
+       INTC_GROUP(DMAC45, DMAC4, DMAC5, DMAC_DADERR),
+       INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI,
+                  FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
+       INTC_GROUP(I2C0, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI),
+       INTC_GROUP(I2C1, I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI),
+       INTC_GROUP(SIM, SIM_TEI, SIM_TXI, SIM_RXI, SIM_ERI),
+       INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3),
+       INTC_GROUP(USB, USBI0, USBI1),
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+       { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
+         { VOU, VIO_VEUI, VIO_BEUI, VIO_CEUI, DMAC3, DMAC2, DMAC1, DMAC0 } },
+       { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
+         { 0, 0, 0, VPU, 0, 0, 0, MFI } },
+       { 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */
+         { SIM_TEI, SIM_TXI, SIM_RXI, SIM_ERI, 0, 0, 0, IRDA } },
+       { 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */
+         { 0, TMU2, TMU1, TMU0, JPU, 0, 0, LCDC } },
+       { 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */
+         { KEYSC, DMAC_DADERR, DMAC5, DMAC4, SCIF3, SCIF2, SCIF1, SCIF } },
+       { 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */
+         { 0, 0, 0, SIO, Z3D4, 0, SIOF1, SIOF0 } },
+       { 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */
+         { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI,
+           FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } },
+       { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
+         { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, 0, SIU } },
+       { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
+         { 0, 0, 0, CMT, 0, USBI1, USBI0 } },
+       { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
+         { MMC_FRDY, MMC_FSTAT, MMC_TRAN, MMC_ERR } },
+       { 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */
+         { I2C1_DTEI, I2C1_WAITI, I2C1_TACKI, I2C1_ALI, TPU, 0, 0, TSIF } },
+       { 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+       { 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2 } },
+       { 0xa4080004, 0, 16, 4, /* IPRB */ { JPU, LCDC, SIM } },
+       { 0xa4080010, 0, 16, 4, /* IPRE */ { DMAC0123, VIOVOU, MFI, VPU } },
+       { 0xa4080014, 0, 16, 4, /* IPRF */ { KEYSC, DMAC45, USB, CMT } },
+       { 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF, SCIF1, SCIF2, SCIF3 } },
+       { 0xa408001c, 0, 16, 4, /* IPRH */ { SIOF0, SIOF1, FLCTL, I2C0 } },
+       { 0xa4080020, 0, 16, 4, /* IPRI */ { SIO, 0, TSIF, I2C1 } },
+       { 0xa4080024, 0, 16, 4, /* IPRJ */ { Z3D4, 0, SIU } },
+       { 0xa4080028, 0, 16, 4, /* IPRK */ { 0, MMC, 0, SDHI } },
+       { 0xa408002c, 0, 16, 4, /* IPRL */ { 0, 0, TPU } },
+       { 0xa4140010, 0, 32, 4, /* INTPRI00 */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_sense_reg sense_registers[] __initdata = {
+       { 0xa414001c, 16, 2, /* ICR1 */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_mask_reg ack_registers[] __initdata = {
+       { 0xa4140024, 0, 8, /* INTREQ00 */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc, "sh7343", vectors, groups,
+                            mask_registers, prio_registers, sense_registers,
+                            ack_registers);
+
 void __init plat_irq_setup(void)
 {
+       register_intc_controller(&intc_desc);
 }
index f26b5cdad0d1fd0349665b30ea2c93ecef918ca1..6851dba02f31897327c529adfef041c1673969b4 100644 (file)
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/uio_driver.h>
+#include <asm/clock.h>
+
+static struct resource iic_resources[] = {
+       [0] = {
+               .name   = "IIC",
+               .start  = 0x04470000,
+               .end    = 0x04470017,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 96,
+               .end    = 99,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device iic_device = {
+       .name           = "i2c-sh_mobile",
+       .num_resources  = ARRAY_SIZE(iic_resources),
+       .resource       = iic_resources,
+};
+
+static struct uio_info vpu_platform_data = {
+       .name = "VPU5",
+       .version = "0",
+       .irq = 60,
+};
+
+static struct resource vpu_resources[] = {
+       [0] = {
+               .name   = "VPU",
+               .start  = 0xfe900000,
+               .end    = 0xfe902807,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device vpu_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 0,
+       .dev = {
+               .platform_data  = &vpu_platform_data,
+       },
+       .resource       = vpu_resources,
+       .num_resources  = ARRAY_SIZE(vpu_resources),
+};
+
+static struct uio_info veu0_platform_data = {
+       .name = "VEU",
+       .version = "0",
+       .irq = 54,
+};
+
+static struct resource veu0_resources[] = {
+       [0] = {
+               .name   = "VEU(1)",
+               .start  = 0xfe920000,
+               .end    = 0xfe9200b7,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device veu0_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 1,
+       .dev = {
+               .platform_data  = &veu0_platform_data,
+       },
+       .resource       = veu0_resources,
+       .num_resources  = ARRAY_SIZE(veu0_resources),
+};
+
+static struct uio_info veu1_platform_data = {
+       .name = "VEU",
+       .version = "0",
+       .irq = 27,
+};
+
+static struct resource veu1_resources[] = {
+       [0] = {
+               .name   = "VEU(2)",
+               .start  = 0xfe924000,
+               .end    = 0xfe9240b7,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device veu1_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 2,
+       .dev = {
+               .platform_data  = &veu1_platform_data,
+       },
+       .resource       = veu1_resources,
+       .num_resources  = ARRAY_SIZE(veu1_resources),
+};
 
 static struct plat_sci_port sci_platform_data[] = {
        {
@@ -34,11 +140,32 @@ static struct platform_device sci_device = {
 };
 
 static struct platform_device *sh7366_devices[] __initdata = {
+       &iic_device,
        &sci_device,
+       &vpu_device,
+       &veu0_device,
+       &veu1_device,
 };
 
 static int __init sh7366_devices_setup(void)
 {
+       clk_always_enable("mstp031"); /* TLB */
+       clk_always_enable("mstp030"); /* IC */
+       clk_always_enable("mstp029"); /* OC */
+       clk_always_enable("mstp028"); /* RSMEM */
+       clk_always_enable("mstp026"); /* XYMEM */
+       clk_always_enable("mstp023"); /* INTC3 */
+       clk_always_enable("mstp022"); /* INTC */
+       clk_always_enable("mstp020"); /* SuperHyway */
+       clk_always_enable("mstp109"); /* I2C */
+       clk_always_enable("mstp207"); /* VEU-2 */
+       clk_always_enable("mstp202"); /* VEU-1 */
+       clk_always_enable("mstp201"); /* VPU */
+
+       platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
+       platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
+       platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
+
        return platform_add_devices(sh7366_devices,
                                    ARRAY_SIZE(sh7366_devices));
 }
@@ -97,7 +224,7 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(SIU, 0xf80),
        INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
        INTC_VECT(TMU2, 0x440),
-       INTC_VECT(VEU2, 0x580), INTC_VECT(LCDC, 0x580),
+       INTC_VECT(VEU2, 0x560), INTC_VECT(LCDC, 0x580),
 };
 
 static struct intc_group groups[] __initdata = {
@@ -163,8 +290,14 @@ static struct intc_sense_reg sense_registers[] __initdata = {
          { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7366", vectors, groups,
-                        mask_registers, prio_registers, sense_registers);
+static struct intc_mask_reg ack_registers[] __initdata = {
+       { 0xa4140024, 0, 8, /* INTREQ00 */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc, "sh7366", vectors, groups,
+                            mask_registers, prio_registers, sense_registers,
+                            ack_registers);
 
 void __init plat_irq_setup(void)
 {
index 62ebccf18b3c27b2a9d91d7cbe925e854cc6af23..de1ede92176e8a3253e6c23c2e45246e0eccef62 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/mm.h>
+#include <linux/uio_driver.h>
+#include <asm/clock.h>
 #include <asm/mmzone.h>
 
 static struct resource usbf_resources[] = {
@@ -59,6 +61,62 @@ static struct platform_device iic_device = {
        .resource       = iic_resources,
 };
 
+static struct uio_info vpu_platform_data = {
+       .name = "VPU4",
+       .version = "0",
+       .irq = 60,
+};
+
+static struct resource vpu_resources[] = {
+       [0] = {
+               .name   = "VPU",
+               .start  = 0xfe900000,
+               .end    = 0xfe9022eb,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device vpu_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 0,
+       .dev = {
+               .platform_data  = &vpu_platform_data,
+       },
+       .resource       = vpu_resources,
+       .num_resources  = ARRAY_SIZE(vpu_resources),
+};
+
+static struct uio_info veu_platform_data = {
+       .name = "VEU",
+       .version = "0",
+       .irq = 54,
+};
+
+static struct resource veu_resources[] = {
+       [0] = {
+               .name   = "VEU",
+               .start  = 0xfe920000,
+               .end    = 0xfe9200b7,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device veu_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 1,
+       .dev = {
+               .platform_data  = &veu_platform_data,
+       },
+       .resource       = veu_resources,
+       .num_resources  = ARRAY_SIZE(veu_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
        {
                .mapbase        = 0xffe00000,
@@ -95,10 +153,27 @@ static struct platform_device *sh7722_devices[] __initdata = {
        &usbf_device,
        &iic_device,
        &sci_device,
+       &vpu_device,
+       &veu_device,
 };
 
 static int __init sh7722_devices_setup(void)
 {
+       clk_always_enable("mstp031"); /* TLB */
+       clk_always_enable("mstp030"); /* IC */
+       clk_always_enable("mstp029"); /* OC */
+       clk_always_enable("mstp028"); /* URAM */
+       clk_always_enable("mstp026"); /* XYMEM */
+       clk_always_enable("mstp022"); /* INTC */
+       clk_always_enable("mstp020"); /* SuperHyway */
+       clk_always_enable("mstp109"); /* I2C */
+       clk_always_enable("mstp211"); /* USB */
+       clk_always_enable("mstp202"); /* VEU */
+       clk_always_enable("mstp201"); /* VPU */
+
+       platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20);
+       platform_resource_setup_memory(&veu_device, "veu", 2 << 20);
+
        return platform_add_devices(sh7722_devices,
                                    ARRAY_SIZE(sh7722_devices));
 }
@@ -229,8 +304,14 @@ static struct intc_sense_reg sense_registers[] __initdata = {
          { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7722", vectors, groups,
-                        mask_registers, prio_registers, sense_registers);
+static struct intc_mask_reg ack_registers[] __initdata = {
+       { 0xa4140024, 0, 8, /* INTREQ00 */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc, "sh7722", vectors, groups,
+                            mask_registers, prio_registers, sense_registers,
+                            ack_registers);
 
 void __init plat_irq_setup(void)
 {
index a0470f2f54798af027a157112277c8974400803b..cd6baffdc89624684f2fe0e88f8d4e173d292e02 100644 (file)
 #include <linux/serial.h>
 #include <linux/mm.h>
 #include <linux/serial_sci.h>
+#include <linux/uio_driver.h>
+#include <asm/clock.h>
 #include <asm/mmzone.h>
 
+static struct uio_info vpu_platform_data = {
+       .name = "VPU5",
+       .version = "0",
+       .irq = 60,
+};
+
+static struct resource vpu_resources[] = {
+       [0] = {
+               .name   = "VPU",
+               .start  = 0xfe900000,
+               .end    = 0xfe902807,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device vpu_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 0,
+       .dev = {
+               .platform_data  = &vpu_platform_data,
+       },
+       .resource       = vpu_resources,
+       .num_resources  = ARRAY_SIZE(vpu_resources),
+};
+
+static struct uio_info veu0_platform_data = {
+       .name = "VEU",
+       .version = "0",
+       .irq = 54,
+};
+
+static struct resource veu0_resources[] = {
+       [0] = {
+               .name   = "VEU2H0",
+               .start  = 0xfe920000,
+               .end    = 0xfe92027b,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device veu0_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 1,
+       .dev = {
+               .platform_data  = &veu0_platform_data,
+       },
+       .resource       = veu0_resources,
+       .num_resources  = ARRAY_SIZE(veu0_resources),
+};
+
+static struct uio_info veu1_platform_data = {
+       .name = "VEU",
+       .version = "0",
+       .irq = 27,
+};
+
+static struct resource veu1_resources[] = {
+       [0] = {
+               .name   = "VEU2H1",
+               .start  = 0xfe924000,
+               .end    = 0xfe92427b,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device veu1_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 2,
+       .dev = {
+               .platform_data  = &veu1_platform_data,
+       },
+       .resource       = veu1_resources,
+       .num_resources  = ARRAY_SIZE(veu1_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
        {
                .mapbase        = 0xffe00000,
@@ -113,14 +199,56 @@ static struct platform_device sh7723_usb_host_device = {
        .resource       = sh7723_usb_host_resources,
 };
 
+static struct resource iic_resources[] = {
+       [0] = {
+               .name   = "IIC",
+               .start  = 0x04470000,
+               .end    = 0x04470017,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 96,
+               .end    = 99,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device iic_device = {
+       .name           = "i2c-sh_mobile",
+       .num_resources  = ARRAY_SIZE(iic_resources),
+       .resource       = iic_resources,
+};
+
 static struct platform_device *sh7723_devices[] __initdata = {
        &sci_device,
        &rtc_device,
+       &iic_device,
        &sh7723_usb_host_device,
+       &vpu_device,
+       &veu0_device,
+       &veu1_device,
 };
 
 static int __init sh7723_devices_setup(void)
 {
+       clk_always_enable("mstp031"); /* TLB */
+       clk_always_enable("mstp030"); /* IC */
+       clk_always_enable("mstp029"); /* OC */
+       clk_always_enable("mstp024"); /* FPU */
+       clk_always_enable("mstp022"); /* INTC */
+       clk_always_enable("mstp020"); /* SuperHyway */
+       clk_always_enable("mstp000"); /* MERAM */
+       clk_always_enable("mstp109"); /* I2C */
+       clk_always_enable("mstp108"); /* RTC */
+       clk_always_enable("mstp211"); /* USB */
+       clk_always_enable("mstp206"); /* VEU2H1 */
+       clk_always_enable("mstp202"); /* VEU2H0 */
+       clk_always_enable("mstp201"); /* VPU */
+
+       platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
+       platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
+       platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
+
        return platform_add_devices(sh7723_devices,
                                    ARRAY_SIZE(sh7723_devices));
 }
@@ -326,8 +454,14 @@ static struct intc_sense_reg sense_registers[] __initdata = {
          { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7723", vectors, groups,
-                        mask_registers, prio_registers, sense_registers);
+static struct intc_mask_reg ack_registers[] __initdata = {
+       { 0xa4140024, 0, 8, /* INTREQ00 */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc, "sh7723", vectors, groups,
+                            mask_registers, prio_registers, sense_registers,
+                            ack_registers);
 
 void __init plat_irq_setup(void)
 {
index f189a559462bdf791775ec949d85cc08597b0082..3c5b629887a8e3a54fa2a0cb5a2b886e7e9271ee 100644 (file)
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2006  Paul Mundt
  *  Copyright (C) 2007  Yoshihiro Shimoda
+ *  Copyright (C) 2008  Nobuhiro Iwamatsu
  *
  * 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
@@ -55,6 +56,11 @@ static struct plat_sci_port sci_platform_data[] = {
                .flags          = UPF_BOOT_AUTOCONF,
                .type           = PORT_SCIF,
                .irqs           = { 76, 77, 79, 78 },
+       }, {
+               .mapbase        = 0xffe10000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 104, 105, 107, 106 },
        }, {
                .flags = 0,
        }
@@ -208,8 +214,8 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(TMU5, 0xe40), INTC_VECT(ADC, 0xe60),
        INTC_VECT(SSI0, 0xe80), INTC_VECT(SSI1, 0xea0),
        INTC_VECT(SSI2, 0xec0), INTC_VECT(SSI3, 0xee0),
-       INTC_VECT(SCIF1_ERI, 0xf00), INTC_VECT(SCIF1_RXI, 0xf20),
-       INTC_VECT(SCIF1_BRI, 0xf40), INTC_VECT(SCIF1_TXI, 0xf60),
+       INTC_VECT(SCIF2_ERI, 0xf00), INTC_VECT(SCIF2_RXI, 0xf20),
+       INTC_VECT(SCIF2_BRI, 0xf40), INTC_VECT(SCIF2_TXI, 0xf60),
        INTC_VECT(GPIO_CH0, 0xf80), INTC_VECT(GPIO_CH1, 0xfa0),
        INTC_VECT(GPIO_CH2, 0xfc0), INTC_VECT(GPIO_CH3, 0xfe0),
 };
@@ -290,9 +296,14 @@ static struct intc_sense_reg irq_sense_registers[] __initdata = {
                                            IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_irq_desc, "sh7763-irq", irq_vectors,
-                       NULL, irq_mask_registers, irq_prio_registers,
-                       irq_sense_registers);
+static struct intc_mask_reg irq_ack_registers[] __initdata = {
+       { 0xffd00024, 0, 32, /* INTREQ */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_irq_desc, "sh7763-irq", irq_vectors,
+                            NULL, irq_mask_registers, irq_prio_registers,
+                            irq_sense_registers, irq_ack_registers);
 
 
 /* External interrupt pins in IRL mode */
index 18dbbe23fea1b172a22532b9cd93005d2eb52562..fb8200cc74409db26b27051d12c2dc77e2da1dde 100644 (file)
@@ -217,9 +217,14 @@ static struct intc_sense_reg irq_sense_registers[] __initdata = {
                                            IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_irq_desc, "sh7780-irq", irq_vectors,
-                        NULL, irq_mask_registers, irq_prio_registers,
-                        irq_sense_registers);
+static struct intc_mask_reg irq_ack_registers[] __initdata = {
+       { 0xffd00024, 0, 32, /* INTREQ */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_irq_desc, "sh7780-irq", irq_vectors,
+                            NULL, irq_mask_registers, irq_prio_registers,
+                            irq_sense_registers, irq_ack_registers);
 
 /* External interrupt pins in IRL mode */
 
index 621e7329ec63747b766301e72859a324dee8290e..30baa63b24c8e728b7d0763d36709938b8388cdc 100644 (file)
@@ -238,13 +238,18 @@ static struct intc_sense_reg sense_registers[] __initdata = {
                                            IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_desc_irq0123, "sh7785-irq0123", vectors_irq0123,
-                        NULL, mask_registers, prio_registers,
-                        sense_registers);
+static struct intc_mask_reg ack_registers[] __initdata = {
+       { 0xffd00024, 0, 32, /* INTREQ */
+         { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh7785-irq0123",
+                            vectors_irq0123, NULL, mask_registers,
+                            prio_registers, sense_registers, ack_registers);
 
-static DECLARE_INTC_DESC(intc_desc_irq4567, "sh7785-irq4567", vectors_irq4567,
-                        NULL, mask_registers, prio_registers,
-                        sense_registers);
+static DECLARE_INTC_DESC_ACK(intc_desc_irq4567, "sh7785-irq4567",
+                            vectors_irq4567, NULL, mask_registers,
+                            prio_registers, sense_registers, ack_registers);
 
 /* External interrupt pins in IRL mode */
 
index 718bd2356b34bf109a9608d0b6b7d20549dc310a..5e0dd1933847b5cbd772e4681f6a7b149fafa5b3 100644 (file)
@@ -192,7 +192,7 @@ work_resched:
        .align  2
 1:     .long   schedule
 2:     .long   do_notify_resume
-3:     .long   restore_all
+3:     .long   resume_userspace
 #ifdef CONFIG_TRACE_IRQFLAGS
 4:     .long   trace_hardirqs_on
 5:     .long   trace_hardirqs_off
index 5c17de51987e59eed62b937e601372b824b7bc4e..ec1eadce4aaaebdf8d7ed8da1b44f42653b1aa9c 100644 (file)
@@ -70,7 +70,7 @@ static void kexec_info(struct kimage *image)
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
  */
-NORET_TYPE void machine_kexec(struct kimage *image)
+void machine_kexec(struct kimage *image)
 {
 
        unsigned long page_list;
index b98e37a1f54c05229c18eb4d865ff0e6e0e26437..3326a45749d9ee2c0af9c9c35b4934cc57c487d9 100644 (file)
@@ -34,18 +34,6 @@ void (*pm_idle)(void);
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
-void disable_hlt(void)
-{
-       hlt_counter++;
-}
-EXPORT_SYMBOL(disable_hlt);
-
-void enable_hlt(void)
-{
-       hlt_counter--;
-}
-EXPORT_SYMBOL(enable_hlt);
-
 static int __init nohlt_setup(char *__unused)
 {
        hlt_counter = 1;
@@ -60,7 +48,7 @@ static int __init hlt_setup(char *__unused)
 }
 __setup("hlt", hlt_setup);
 
-void default_idle(void)
+static void default_idle(void)
 {
        if (!hlt_counter) {
                clear_thread_flag(TIF_POLLING_NRFLAG);
@@ -86,7 +74,7 @@ void cpu_idle(void)
                if (!idle)
                        idle = default_idle;
 
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        idle();
                tick_nohz_restart_sched_tick();
index 0283d8133075b0507d04d5ca5417a3a6c1425017..b9dbd2d3b4a5845624829c547ed613c8fe259b51 100644 (file)
@@ -36,16 +36,6 @@ static int hlt_counter = 1;
 
 #define HARD_IDLE_TIMEOUT (HZ / 3)
 
-void disable_hlt(void)
-{
-       hlt_counter++;
-}
-
-void enable_hlt(void)
-{
-       hlt_counter--;
-}
-
 static int __init nohlt_setup(char *__unused)
 {
        hlt_counter = 1;
index fddb547f3c2b90f1483a9b54e4104701dc7eae8a..2bc72def5cf87d00e66b6d068019b1ade4cf33a5 100644 (file)
@@ -240,6 +240,29 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                }
                break;
        }
+#endif
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+       case PTRACE_GETFDPIC: {
+               unsigned long tmp = 0;
+
+               switch (addr) {
+               case PTRACE_GETFDPIC_EXEC:
+                       tmp = child->mm->context.exec_fdpic_loadmap;
+                       break;
+               case PTRACE_GETFDPIC_INTERP:
+                       tmp = child->mm->context.interp_fdpic_loadmap;
+                       break;
+               default:
+                       break;
+               }
+
+               ret = 0;
+               if (put_user(tmp, (unsigned long *) data)) {
+                       ret = -EFAULT;
+                       break;
+               }
+               break;
+       }
 #endif
        default:
                ret = ptrace_request(child, request, addr, data);
index bca2bbc575dbe034e7c0ded352c437997ee8308d..6339d0c9571557c481613bc7d06f7adee9fa6140 100644 (file)
@@ -398,6 +398,7 @@ const char *get_cpu_subtype(struct sh_cpuinfo *c)
 {
        return cpu_name[c->type];
 }
+EXPORT_SYMBOL(get_cpu_subtype);
 
 #ifdef CONFIG_PROC_FS
 /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
@@ -452,6 +453,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        seq_printf(m, "processor\t: %d\n", cpu);
        seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
        seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype(c));
+       if (c->cut_major == -1)
+               seq_printf(m, "cut\t\t: unknown\n");
+       else if (c->cut_minor == -1)
+               seq_printf(m, "cut\t\t: %d.x\n", c->cut_major);
+       else
+               seq_printf(m, "cut\t\t: %d.%d\n", c->cut_major, c->cut_minor);
 
        show_cpuflags(m, c);
 
index f311551d9a05b253fccd2b2d2ac0b8a78418bd6f..4bbbde895a5353c41e7ecacd6cf019545c8e8202 100644 (file)
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
+struct fdpic_func_descriptor {
+       unsigned long   text;
+       unsigned long   GOT;
+};
+
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -368,6 +373,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
                err |= __put_user(OR_R0_R0, &frame->retcode[6]);
                err |= __put_user((__NR_sigreturn), &frame->retcode[7]);
                regs->pr = (unsigned long) frame->retcode;
+               flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
        }
 
        if (err)
@@ -378,18 +384,21 @@ static int setup_frame(int sig, struct k_sigaction *ka,
        regs->regs[4] = signal; /* Arg for signal handler */
        regs->regs[5] = 0;
        regs->regs[6] = (unsigned long) &frame->sc;
-       regs->pc = (unsigned long) ka->sa.sa_handler;
+
+       if (current->personality & FDPIC_FUNCPTRS) {
+               struct fdpic_func_descriptor __user *funcptr =
+                       (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
+
+               __get_user(regs->pc, &funcptr->text);
+               __get_user(regs->regs[12], &funcptr->GOT);
+       } else
+               regs->pc = (unsigned long)ka->sa.sa_handler;
 
        set_fs(USER_DS);
 
        pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
                 current->comm, task_pid_nr(current), 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 0;
 
 give_sigsegv:
@@ -458,17 +467,22 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->regs[4] = signal; /* Arg for signal handler */
        regs->regs[5] = (unsigned long) &frame->info;
        regs->regs[6] = (unsigned long) &frame->uc;
-       regs->pc = (unsigned long) ka->sa.sa_handler;
+
+       if (current->personality & FDPIC_FUNCPTRS) {
+               struct fdpic_func_descriptor __user *funcptr =
+                       (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
+
+               __get_user(regs->pc, &funcptr->text);
+               __get_user(regs->regs[12], &funcptr->GOT);
+       } else
+               regs->pc = (unsigned long)ka->sa.sa_handler;
 
        set_fs(USER_DS);
 
        pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
                 current->comm, task_pid_nr(current), 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);
+       flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
 
        return 0;
 
index 1b2ae35c4a76504f5d08ba43ff5e0a68a36aa04f..54d1f61aa00778c22cb55552e5fc18197e12d3b8 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 #include <linux/thread_info.h>
+#include <linux/module.h>
 #include <asm/ptrace.h>
 
 /*
index 125e493ead8291b18a6e78d9e1d95c4f75c63aeb..f0aa5c398656ca5b7fc1e4d0812b41951c57a79b 100644 (file)
@@ -29,7 +29,7 @@ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
        int fd[2];
        int error;
 
-       error = do_pipe(fd);
+       error = do_pipe_flags(fd, 0);
        if (!error) {
                regs->regs[1] = fd[1];
                return fd[0];
index a46cc3a411485d4b71320015c5d1bb47ece080c1..0af693e65764d494dc487eb9a386baeb3a95d3aa 100644 (file)
@@ -343,3 +343,9 @@ ENTRY(sys_call_table)
        .long sys_fallocate
        .long sys_timerfd_settime       /* 325 */
        .long sys_timerfd_gettime
+       .long sys_signalfd4
+       .long sys_eventfd2
+       .long sys_epoll_create1
+       .long sys_dup3                  /* 330 */
+       .long sys_pipe2
+       .long sys_inotify_init1
index d5d7843aad94c1c8ff79da288a16e422a7a9ad1b..0b436aa3cad7931df028a5e8dfa44e0e8e02d6d5 100644 (file)
@@ -381,3 +381,9 @@ sys_call_table:
        .long sys_fallocate
        .long sys_timerfd_settime
        .long sys_timerfd_gettime
+       .long sys_signalfd4             /* 355 */
+       .long sys_eventfd2
+       .long sys_epoll_create1
+       .long sys_dup3
+       .long sys_pipe2
+       .long sys_inotify_init1         /* 360 */
index 7281342c044d6dd24247ea33fa89060c687fbc88..0758b5ee818079b3fd2f3948da6dfe7af5825d0b 100644 (file)
@@ -211,7 +211,7 @@ unsigned long sh_hpt_frequency = 0;
 
 #define NSEC_PER_CYC_SHIFT     10
 
-struct clocksource clocksource_sh = {
+static struct clocksource clocksource_sh = {
        .name           = "SuperH",
        .rating         = 200,
        .mask           = CLOCKSOURCE_MASK(32),
index 8935570008d2eb192d9d6698c2b4580ea3c0882c..1ca9ad49b54145c89b001d24371b40876751ba49 100644 (file)
@@ -209,7 +209,7 @@ static int tmu_timer_init(void)
        return 0;
 }
 
-struct sys_timer_ops tmu_timer_ops = {
+static struct sys_timer_ops tmu_timer_ops = {
        .init           = tmu_timer_init,
        .start          = tmu_timer_start,
        .stop           = tmu_timer_stop,
index e08b3bfeb6566fc430e5a50c0ed93cde07eedf3c..511a9426cec58a348fb7fd45bdf4db11d654b31c 100644 (file)
@@ -43,6 +43,7 @@
 # define TRAP_ILLEGAL_SLOT_INST        6
 # define TRAP_ADDRESS_ERROR    9
 # ifdef CONFIG_CPU_SH2A
+#  define TRAP_FPU_ERROR       13
 #  define TRAP_DIVZERO_ERROR   17
 #  define TRAP_DIVOVF_ERROR    18
 # endif
@@ -851,6 +852,9 @@ void __init trap_init(void)
 #ifdef CONFIG_CPU_SH2A
        set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error);
        set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error);
+#ifdef CONFIG_SH_FPU
+       set_exception_table_vec(TRAP_FPU_ERROR, fpu_error_trap_handler);
+#endif
 #endif
 
        /* Setup VBR for boot cpu */
index ebb55d1149f55ab3ea44c79e2704dc1ac2ea0cb5..8596cc78e18d0927cb938466f934bd4d8fc22ec8 100644 (file)
@@ -2,9 +2,11 @@
 # Makefile for SuperH-specific library files..
 #
 
-lib-y  = delay.o io.o memset.o memmove.o memchr.o \
+lib-y  = delay.o memset.o memmove.o memchr.o \
         checksum.o strlen.o div64.o div64-generic.o
 
+obj-y                          += io.o
+
 memcpy-y                       := memcpy.o
 memcpy-$(CONFIG_CPU_SH4)       := memcpy-sh4.o
 
index 5fd218430b19a9e1b91fc17c6f75d4650cf40142..56d0a7daa34ba61e45fdcff6e4b9fddf51f902ef 100644 (file)
@@ -145,25 +145,39 @@ choice
 
 config PAGE_SIZE_4KB
        bool "4kB"
-       depends on !X2TLB
+       depends on !MMU || !X2TLB
        help
          This is the default page size used by all SuperH CPUs.
 
 config PAGE_SIZE_8KB
        bool "8kB"
-       depends on X2TLB
+       depends on !MMU || X2TLB
        help
          This enables 8kB pages as supported by SH-X2 and later MMUs.
 
+config PAGE_SIZE_16KB
+       bool "16kB"
+       depends on !MMU
+       help
+         This enables 16kB pages on MMU-less SH systems.
+
 config PAGE_SIZE_64KB
        bool "64kB"
-       depends on CPU_SH4 || CPU_SH5
+       depends on !MMU || CPU_SH4 || CPU_SH5
        help
          This enables support for 64kB pages, possible on all SH-4
          CPUs and later.
 
 endchoice
 
+config ENTRY_OFFSET
+       hex
+       default "0x00001000" if PAGE_SIZE_4KB
+       default "0x00002000" if PAGE_SIZE_8KB
+       default "0x00004000" if PAGE_SIZE_16KB
+       default "0x00010000" if PAGE_SIZE_64KB
+       default "0x00000000"
+
 choice
        prompt "HugeTLB page size"
        depends on HUGETLB_PAGE && (CPU_SH4 || CPU_SH5) && MMU
index c5b56d52b7d27cf7d87a6bd3e2d1e99b24f97bf2..0e189ccd4a77a7ce7462f9eb863409d419a71150 100644 (file)
@@ -120,7 +120,7 @@ static const struct file_operations cache_debugfs_fops = {
        .open           = cache_debugfs_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = single_release,
 };
 
 static int __init cache_debugfs_init(void)
index 43d7ff6b6ec7c71cfbaccc244d46bc6bcf0a7ce7..1fdc8d90254a177bbb4a345456712378a17fdb2c 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  * Copyright (C) 2001 - 2007  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
+ * Copyright (c) 2007 STMicroelectronics (R&D) Ltd.
  *
  * 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
@@ -22,6 +23,7 @@
  * entirety.
  */
 #define MAX_DCACHE_PAGES       64      /* XXX: Tune for ways */
+#define MAX_ICACHE_PAGES       32
 
 static void __flush_dcache_segment_1way(unsigned long start,
                                        unsigned long extent);
@@ -178,42 +180,45 @@ void __flush_invalidate_region(void *start, int size)
 /*
  * Write back the range of D-cache, and purge the I-cache.
  *
- * Called from kernel/module.c:sys_init_module and routine for a.out format.
+ * Called from kernel/module.c:sys_init_module and routine for a.out format,
+ * signal handler code and kprobes code
  */
 void flush_icache_range(unsigned long start, unsigned long end)
 {
-       flush_cache_all();
-}
-
-/*
- * 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 __uses_jump_to_uncached flush_cache_sigtramp(unsigned long addr)
-{
-       unsigned long v, index;
-       unsigned long flags;
+       int icacheaddr;
+       unsigned long flags, v;
        int i;
 
-       v = addr & ~(L1_CACHE_BYTES-1);
-       asm volatile("ocbwb     %0"
-                    : /* no output */
-                    : "m" (__m(v)));
-
-       index = CACHE_IC_ADDRESS_ARRAY |
-                       (v & boot_cpu_data.icache.entry_mask);
-
-       local_irq_save(flags);
-       jump_to_uncached();
-
-       for (i = 0; i < boot_cpu_data.icache.ways;
-            i++, index += boot_cpu_data.icache.way_incr)
-               ctrl_outl(0, index);    /* Clear out Valid-bit */
-
-       back_to_cached();
-       wmb();
-       local_irq_restore(flags);
+       /* If there are too many pages then just blow the caches */
+        if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
+                flush_cache_all();
+       } else {
+               /* selectively flush d-cache then invalidate the i-cache */
+               /* this is inefficient, so only use for small ranges */
+               start &= ~(L1_CACHE_BYTES-1);
+               end += L1_CACHE_BYTES-1;
+               end &= ~(L1_CACHE_BYTES-1);
+
+               local_irq_save(flags);
+               jump_to_uncached();
+
+               for (v = start; v < end; v+=L1_CACHE_BYTES) {
+                       asm volatile("ocbwb     %0"
+                                    : /* no output */
+                                    : "m" (__m(v)));
+
+                       icacheaddr = CACHE_IC_ADDRESS_ARRAY | (
+                                       v & cpu_data->icache.entry_mask);
+
+                       for (i = 0; i < cpu_data->icache.ways;
+                               i++, icacheaddr += cpu_data->icache.way_incr)
+                                       /* Clear i-cache line valid-bit */
+                                       ctrl_outl(0, icacheaddr);
+               }
+
+               back_to_cached();
+               local_irq_restore(flags);
+       }
 }
 
 static inline void flush_cache_4096(unsigned long start,
index d3c33fc5b1c2d252bc739717c8d5dd50dd096482..b2ce014401b5516ed8ae51c4ca98cf5d0c4a026e 100644 (file)
@@ -10,6 +10,7 @@
  * for more details.
  */
 #include <linux/mm.h>
+#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <asm/cacheflush.h>
 #include <asm/addrspace.h>
@@ -27,21 +28,10 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
                           dma_addr_t *dma_handle, gfp_t gfp)
 {
        void *ret, *ret_nocache;
-       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
        int order = get_order(size);
 
-       if (mem) {
-               int page = bitmap_find_free_region(mem->bitmap, mem->size,
-                                                    order);
-               if (page >= 0) {
-                       *dma_handle = mem->device_base + (page << PAGE_SHIFT);
-                       ret = mem->virt_base + (page << PAGE_SHIFT);
-                       memset(ret, 0, size);
-                       return ret;
-               }
-               if (mem->flags & DMA_MEMORY_EXCLUSIVE)
-                       return NULL;
-       }
+       if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
+               return ret;
 
        ret = (void *)__get_free_pages(gfp, order);
        if (!ret)
@@ -71,11 +61,7 @@ void dma_free_coherent(struct device *dev, size_t size,
        struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
        int order = get_order(size);
 
-       if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
-               int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
-
-               bitmap_release_region(mem->bitmap, page, order);
-       } else {
+       if (!dma_release_from_coherent(dev, order, vaddr)) {
                WARN_ON(irqs_disabled());       /* for portability */
                BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE);
                free_pages((unsigned long)phys_to_virt(dma_handle), order);
@@ -84,83 +70,6 @@ void dma_free_coherent(struct device *dev, size_t size,
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
-int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
-                               dma_addr_t device_addr, size_t size, int flags)
-{
-       void __iomem *mem_base = NULL;
-       int pages = size >> PAGE_SHIFT;
-       int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
-
-       if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
-               goto out;
-       if (!size)
-               goto out;
-       if (dev->dma_mem)
-               goto out;
-
-       /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
-
-       mem_base = ioremap_nocache(bus_addr, size);
-       if (!mem_base)
-               goto out;
-
-       dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
-       if (!dev->dma_mem)
-               goto out;
-       dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-       if (!dev->dma_mem->bitmap)
-               goto free1_out;
-
-       dev->dma_mem->virt_base = mem_base;
-       dev->dma_mem->device_base = device_addr;
-       dev->dma_mem->size = pages;
-       dev->dma_mem->flags = flags;
-
-       if (flags & DMA_MEMORY_MAP)
-               return DMA_MEMORY_MAP;
-
-       return DMA_MEMORY_IO;
-
- free1_out:
-       kfree(dev->dma_mem);
- out:
-       if (mem_base)
-               iounmap(mem_base);
-       return 0;
-}
-EXPORT_SYMBOL(dma_declare_coherent_memory);
-
-void dma_release_declared_memory(struct device *dev)
-{
-       struct dma_coherent_mem *mem = dev->dma_mem;
-
-       if (!mem)
-               return;
-       dev->dma_mem = NULL;
-       iounmap(mem->virt_base);
-       kfree(mem->bitmap);
-       kfree(mem);
-}
-EXPORT_SYMBOL(dma_release_declared_memory);
-
-void *dma_mark_declared_memory_occupied(struct device *dev,
-                                       dma_addr_t device_addr, size_t size)
-{
-       struct dma_coherent_mem *mem = dev->dma_mem;
-       int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       int pos, err;
-
-       if (!mem)
-               return ERR_PTR(-EINVAL);
-
-       pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
-       err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
-       if (err != 0)
-               return ERR_PTR(err);
-       return mem->virt_base + (pos << PAGE_SHIFT);
-}
-EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
-
 void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                    enum dma_data_direction direction)
 {
@@ -185,3 +94,32 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
        }
 }
 EXPORT_SYMBOL(dma_cache_sync);
+
+int platform_resource_setup_memory(struct platform_device *pdev,
+                                  char *name, unsigned long memsize)
+{
+       struct resource *r;
+       dma_addr_t dma_handle;
+       void *buf;
+
+       r = pdev->resource + pdev->num_resources - 1;
+       if (r->flags) {
+               pr_warning("%s: unable to find empty space for resource\n",
+                       name);
+               return -EINVAL;
+       }
+
+       buf = dma_alloc_coherent(NULL, memsize, &dma_handle, GFP_KERNEL);
+       if (!buf) {
+               pr_warning("%s: unable to allocate memory\n", name);
+               return -ENOMEM;
+       }
+
+       memset(buf, 0, memsize);
+
+       r->flags = IORESOURCE_MEM;
+       r->start = dma_handle;
+       r->end = r->start + memsize - 1;
+       r->name = name;
+       return 0;
+}
index d1fa27594c6e4f0d7340670597e0c5ee4517b9c5..0c776fdfbddae6800480dc0a3dc7be54103509b3 100644 (file)
@@ -37,16 +37,12 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        int fault;
        siginfo_t info;
 
-       trace_hardirqs_on();
-       local_irq_enable();
-
 #ifdef CONFIG_SH_KGDB
        if (kgdb_nofault && kgdb_bus_err_hook)
                kgdb_bus_err_hook();
 #endif
 
        tsk = current;
-       mm = tsk->mm;
        si_code = SEGV_MAPERR;
 
        if (unlikely(address >= TASK_SIZE)) {
@@ -88,6 +84,14 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
                return;
        }
 
+       /* Only enable interrupts if they were on before the fault */
+       if ((regs->sr & SR_IMASK) != SR_IMASK) {
+               trace_hardirqs_on();
+               local_irq_enable();
+       }
+
+       mm = tsk->mm;
+
        /*
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
index ae8c321d6e2a960e0e7fe1bd55ab5224e7a586cc..9304117039c4f887d7a94f70e48a73c6d1549ef8 100644 (file)
@@ -22,7 +22,8 @@
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+                       unsigned long addr, unsigned long sz)
 {
        pgd_t *pgd;
        pud_t *pud;
@@ -78,6 +79,11 @@ int pmd_huge(pmd_t pmd)
        return 0;
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                             pmd_t *pmd, int write)
 {
index d7df26bd1e5468b0f79a702220bf85352c61a0bc..b75a7acd62fb7818f8fec20cc72aa7794d0ff159 100644 (file)
@@ -25,47 +25,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 unsigned long cached_to_uncached = 0;
 
-void show_mem(void)
-{
-       int total = 0, reserved = 0, free = 0;
-       int shared = 0, cached = 0, slab = 0;
-       pg_data_t *pgdat;
-
-       printk("Mem-info:\n");
-       show_free_areas();
-
-       for_each_online_pgdat(pgdat) {
-               unsigned long flags, i;
-
-               pgdat_resize_lock(pgdat, &flags);
-               for (i = 0; i < pgdat->node_spanned_pages; i++) {
-                       struct page *page = pgdat_page_nr(pgdat, i);
-                       total++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (PageSlab(page))
-                               slab++;
-                       else if (!page_count(page))
-                               free++;
-                       else
-                               shared += page_count(page) - 1;
-               }
-               pgdat_resize_unlock(pgdat, &flags);
-       }
-
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-       printk("%d pages of RAM\n", total);
-       printk("%d free pages\n", free);
-       printk("%d reserved pages\n", reserved);
-       printk("%d slab pages\n", slab);
-       printk("%d pages shared\n", shared);
-       printk("%d pages swap cached\n", cached);
-       printk(KERN_INFO "Total of %ld pages in page table cache\n",
-              quicklist_total_size());
-}
-
 #ifdef CONFIG_MMU
 static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
 {
@@ -191,7 +150,7 @@ void __init paging_init(void)
                pg_data_t *pgdat = NODE_DATA(nid);
                unsigned long low, start_pfn;
 
-               start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT;
+               start_pfn = pgdat->bdata->node_min_pfn;
                low = pgdat->bdata->node_low_pfn;
 
                if (max_zone_pfns[ZONE_NORMAL] < low)
index 1663199ce888649a6ecd0368f2c114ae7866a38e..095d93bec7cd2aebe1b6b6b408b13eff1e2a617b 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/pfn.h>
 #include <asm/sections.h>
 
-static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL_GPL(node_data);
 
@@ -35,7 +34,7 @@ void __init setup_memory(void)
        NODE_DATA(0) = pfn_to_kaddr(free_pfn);
        memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
        free_pfn += PFN_UP(sizeof(struct pglist_data));
-       NODE_DATA(0)->bdata = &plat_node_bdata[0];
+       NODE_DATA(0)->bdata = &bootmem_node_data[0];
 
        /* Set up node 0 */
        setup_bootmem_allocator(free_pfn);
@@ -66,7 +65,7 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
        free_pfn += PFN_UP(sizeof(struct pglist_data));
        memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
-       NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+       NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
        NODE_DATA(nid)->node_start_pfn = start_pfn;
        NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
 
index 8c7a9ca79879aef2de7de1f253a6e8c8b5969121..38870e0fc182af3347ed90986d9fb3b31578fadb 100644 (file)
@@ -111,7 +111,7 @@ EXPORT_SYMBOL(copy_user_highpage);
 /*
  * For SH-4, we have our own implementation for ptep_get_and_clear
  */
-inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        pte_t pte = *ptep;
 
index 7f885b7f8afffa36a4bac0d73e4180aeecf04ded..eaf25147194c80947a5ce74aadd93ca7e22ced26 100644 (file)
@@ -118,7 +118,7 @@ void copy_user_page(void *to, void *from, unsigned long address, struct page *pg
  * For SH7705, we have our own implementation for ptep_get_and_clear
  * Copied from pg-sh4.c
  */
-inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        pte_t pte = *ptep;
 
index 0b0ec6e047530bd1b7a4dde27088a004631755d5..cef727669c8759dde6ce20ceb9ecc138d71a28bb 100644 (file)
@@ -293,7 +293,7 @@ void pmb_unmap(unsigned long addr)
        } while (pmbe);
 }
 
-static void pmb_cache_ctor(struct kmem_cache *cachep, void *pmb)
+static void pmb_cache_ctor(void *pmb)
 {
        struct pmb_entry *pmbe = pmb;
 
@@ -385,7 +385,7 @@ static const struct file_operations pmb_debugfs_fops = {
        .open           = pmb_debugfs_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = single_release,
 };
 
 static int __init pmb_debugfs_init(void)
index 1bba7d36be9067de687cbb2d28065393b2e1369a..0a11cc08f0a593d0bf134bade882b0de0e6f2449 100644 (file)
@@ -46,3 +46,7 @@ R2D_1                 RTS7751R2D_1
 CAYMAN                 SH_CAYMAN
 SDK7780                        SH_SDK7780
 MIGOR                  SH_MIGOR
+RSK7203                        SH_RSK7203
+AP325RXA               SH_AP325RXA
+SH7763RDP              SH_SH7763RDP
+SH7785LCR              SH_SH7785LCR
index 789724e61e8345e90ca7b155e1c23b543781de3c..a214002114ed90b0f8924c6837cbfcc622af737c 100644 (file)
@@ -68,6 +68,7 @@ config SPARC
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_ARCH_KGDB if !SMP
+       select HAVE_ARCH_TRACEHOOK
 
 # Identify this as a Sparc32 build
 config SPARC32
@@ -298,20 +299,6 @@ config UNIX98_PTYS
          Read the instructions in <file:Documentation/Changes> pertaining to
          pseudo terminals. It's safe to say N.
 
-config UNIX98_PTY_COUNT
-       int "Maximum number of Unix98 PTYs in use (0-2048)"
-       depends on UNIX98_PTYS
-       default "256"
-       help
-         The maximum number of Unix98 PTYs that can be used at any one time.
-         The default is 256, and should be enough for desktop systems. Server
-         machines which support incoming telnet/rlogin/ssh connections and/or
-         serve several X terminals may want to increase this: every incoming
-         connection and every xterm uses up one PTY.
-
-         When not in use, each additional set of 256 PTYs occupy
-         approximately 8 KB of kernel memory on 32-bit architectures.
-
 endmenu
 
 source "fs/Kconfig"
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
new file mode 100644 (file)
index 0000000..a5f0ce7
--- /dev/null
@@ -0,0 +1,45 @@
+# User exported sparc header files
+include include/asm-generic/Kbuild.asm
+
+header-y += ipcbuf_32.h
+header-y += ipcbuf_64.h
+header-y += posix_types_32.h
+header-y += posix_types_64.h
+header-y += ptrace_32.h
+header-y += ptrace_64.h
+header-y += sigcontext_32.h
+header-y += sigcontext_64.h
+header-y += siginfo_32.h
+header-y += siginfo_64.h
+header-y += signal_32.h
+header-y += signal_64.h
+header-y += stat_32.h
+header-y += stat_64.h
+header-y += statfs_32.h
+header-y += statfs_64.h
+header-y += unistd_32.h
+header-y += unistd_64.h
+
+header-y += apc.h
+header-y += asi.h
+header-y += bpp.h
+header-y += display7seg.h
+header-y += envctrl.h
+header-y += fbio.h
+header-y += jsflash.h
+header-y += openprom.h
+header-y += openprom_32.h
+header-y += openprom_64.h
+header-y += openpromio.h
+header-y += perfctr.h
+header-y += psrcompat.h
+header-y += psr.h
+header-y += pstate.h
+header-y += reg.h
+header-y += reg_32.h
+header-y += reg_64.h
+header-y += traps.h
+header-y += uctx.h
+header-y += utrap.h
+header-y += vfc_ioctls.h
+header-y += watchdog.h
similarity index 65%
rename from include/asm-sparc/atomic.h
rename to arch/sparc/include/asm/atomic.h
index 66d8166ec1d7d768e321b7fe06414140ac7d7bf6..8ff83d8cc33fd7f4abd2f7ae2b018baa1006cdd7 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_ATOMIC_H
 #define ___ASM_SPARC_ATOMIC_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/atomic_64.h>
+#include <asm/atomic_64.h>
 #else
-#include <asm-sparc/atomic_32.h>
+#include <asm/atomic_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/auxio.h
rename to arch/sparc/include/asm/auxio.h
index 24c6f3c0f5779c5ea9d2789ae8b91017f2ab97e3..13dc67f03011eae7624c26957cf4f6a5085a4c34 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_AUXIO_H
 #define ___ASM_SPARC_AUXIO_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/auxio_64.h>
+#include <asm/auxio_64.h>
 #else
-#include <asm-sparc/auxio_32.h>
+#include <asm/auxio_32.h>
 #endif
 #endif
similarity index 97%
rename from include/asm-sparc/auxio_32.h
rename to arch/sparc/include/asm/auxio_32.h
index 4db8f23db20f1c930c96354f529657525dced95f..e03e088be95f23eb2b01a1ab2915a22e47beb7dd 100644 (file)
@@ -36,7 +36,7 @@
  * understand the hardware you are querying!
  */
 extern void set_auxio(unsigned char bits_on, unsigned char bits_off);
-extern unsigned char get_auxio(void); /* .../asm-sparc/floppy.h */
+extern unsigned char get_auxio(void); /* .../asm/floppy.h */
 
 /*
  * The following routines are provided for driver-compatibility
similarity index 65%
rename from include/asm-sparc/bitops.h
rename to arch/sparc/include/asm/bitops.h
index 1a2949d0193fa85defd4a7a2698bf4afb372b7cf..b1edd94bd64f398d6363132519ab995cc549c452 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_BITOPS_H
 #define ___ASM_SPARC_BITOPS_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/bitops_64.h>
+#include <asm/bitops_64.h>
 #else
-#include <asm-sparc/bitops_32.h>
+#include <asm/bitops_32.h>
 #endif
 #endif
similarity index 99%
rename from include/asm-sparc/btfixup.h
rename to arch/sparc/include/asm/btfixup.h
index 08277e6fb4cd51dcc5a5349c782d70ab4ba07361..797722cf69f2869943f4d347a4acb6ad9f72bb77 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  asm-sparc/btfixup.h:    Macros for boot time linking.
+ *  asm/btfixup.h:    Macros for boot time linking.
  *
  *  Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
similarity index 87%
rename from include/asm-sparc/bugs.h
rename to arch/sparc/include/asm/bugs.h
index 2dfc07bc8e5472ec9b319dd137a8c7a69535338e..e179bc12f64a478ff9d3eaba6bf337f1a27b1539 100644 (file)
@@ -1,4 +1,4 @@
-/* include/asm-sparc/bugs.h:  Sparc probes for various bugs.
+/* include/asm/bugs.h:  Sparc probes for various bugs.
  *
  * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
  */
similarity index 64%
rename from include/asm-sparc/cacheflush.h
rename to arch/sparc/include/asm/cacheflush.h
index 2b6a37957c2da803739a7e0a71779ea264f2b5d4..049168087b198fd37e5a144bc55e7682ef1ffc6f 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_CACHEFLUSH_H
 #define ___ASM_SPARC_CACHEFLUSH_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/cacheflush_64.h>
+#include <asm/cacheflush_64.h>
 #else
-#include <asm-sparc/cacheflush_32.h>
+#include <asm/cacheflush_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/checksum.h
rename to arch/sparc/include/asm/checksum.h
index 4e3553d4f6e17a3eb6c07be765b1fe08b4542604..7ac0d7497bc593bbc6c87f69964073cbcd8d1d14 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_CHECKSUM_H
 #define ___ASM_SPARC_CHECKSUM_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/checksum_64.h>
+#include <asm/checksum_64.h>
 #else
-#include <asm-sparc/checksum_32.h>
+#include <asm/checksum_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/cpudata.h
rename to arch/sparc/include/asm/cpudata.h
index b76fac0c8d8feb549fcb7d43c9e18ebdb7449933..b5976de7cacdb32528f576eef418ce4d35685e4e 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_CPUDATA_H
 #define ___ASM_SPARC_CPUDATA_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/cpudata_64.h>
+#include <asm/cpudata_64.h>
 #else
-#include <asm-sparc/cpudata_32.h>
+#include <asm/cpudata_32.h>
 #endif
 #endif
similarity index 89%
rename from include/asm-sparc/cpudata_32.h
rename to arch/sparc/include/asm/cpudata_32.h
index a2c4d51d36c4c478f81dc0ba99a05a8809690137..31d48a0e32c7cd3cd3b4eda72325229496f00411 100644 (file)
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2004 Keith M Wesolowski (wesolows@foobazco.org)
  *
- * Based on include/asm-sparc64/cpudata.h and Linux 2.4 smp.h
+ * Based on include/asm/cpudata.h and Linux 2.4 smp.h
  * both (C) David S. Miller.
  */
 
similarity index 96%
rename from include/asm-sparc/current.h
rename to arch/sparc/include/asm/current.h
index 8a1d9d6643b059343919a615064fb0068246a2be..10a0df55a574aeb8758e57c99073ccf8cf4e2d54 100644 (file)
@@ -1,4 +1,4 @@
-/* include/asm-sparc/current.h
+/* include/asm/current.h
  *
  * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  * Copyright (C) 2002 Pete Zaitcev (zaitcev@yahoo.com)
similarity index 65%
rename from include/asm-sparc/delay.h
rename to arch/sparc/include/asm/delay.h
index 6210a3ce97517860de53a9b1823a4eaa5b56e871..467caa2a97a04199ec379aa1540a29c7fd62a49d 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_DELAY_H
 #define ___ASM_SPARC_DELAY_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/delay_64.h>
+#include <asm/delay_64.h>
 #else
-#include <asm-sparc/delay_32.h>
+#include <asm/delay_32.h>
 #endif
 #endif
similarity index 64%
rename from include/asm-sparc/dma-mapping.h
rename to arch/sparc/include/asm/dma-mapping.h
index 7483504259cef140dd187a87af7025a18d689486..0f4150e26619c3a2063f92abe4ff95ca8dece6cc 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_DMA_MAPPING_H
 #define ___ASM_SPARC_DMA_MAPPING_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/dma-mapping_64.h>
+#include <asm/dma-mapping_64.h>
 #else
-#include <asm-sparc/dma-mapping_32.h>
+#include <asm/dma-mapping_32.h>
 #endif
 #endif
similarity index 98%
rename from include/asm-sparc/dma-mapping_64.h
rename to arch/sparc/include/asm/dma-mapping_64.h
index 38cbec76a33f1c04bd14948786891e90185c9277..bfa64f9702d548806c9bd2fa0a117195d6c25ef0 100644 (file)
@@ -135,7 +135,7 @@ static inline void dma_sync_sg_for_device(struct device *dev,
        /* No flushing needed to sync cpu writes to the device.  */
 }
 
-static inline int dma_mapping_error(dma_addr_t dma_addr)
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return (dma_addr == DMA_ERROR_CODE);
 }
similarity index 66%
rename from include/asm-sparc/dma.h
rename to arch/sparc/include/asm/dma.h
index 8cc69bfaae2ab8459433dadaf6a10ce1e20eae65..aa1d90ac04c58b2db3c907ab8e5555aa7ae90b75 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_DMA_H
 #define ___ASM_SPARC_DMA_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/dma_64.h>
+#include <asm/dma_64.h>
 #else
-#include <asm-sparc/dma_32.h>
+#include <asm/dma_32.h>
 #endif
 #endif
similarity index 99%
rename from include/asm-sparc/dma_32.h
rename to arch/sparc/include/asm/dma_32.h
index 959d6c8a71ae72365f6d33e2c1921bebbe012317..cf7189c0079b2c3b6b46c02b65e53d70caddd506 100644 (file)
@@ -1,4 +1,4 @@
-/* include/asm-sparc/dma.h
+/* include/asm/dma.h
  *
  * Copyright 1995 (C) David S. Miller (davem@davemloft.net)
  */
similarity index 99%
rename from include/asm-sparc/dma_64.h
rename to arch/sparc/include/asm/dma_64.h
index 9d4c024bd3b3874f0091c4c3e83cd4392006110f..46a8aecffc02c182b63cf794e83746ac64499674 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sparc64/dma.h
+ * include/asm/dma.h
  *
  * Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu)
  */
similarity index 66%
rename from include/asm-sparc/ebus.h
rename to arch/sparc/include/asm/ebus.h
index a5da2d00cd1814728af538bbca535919f2086cdd..83a6d16c22e68bd5c7f463fb13edc5a7e6af0949 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_EBUS_H
 #define ___ASM_SPARC_EBUS_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/ebus_64.h>
+#include <asm/ebus_64.h>
 #else
-#include <asm-sparc/ebus_32.h>
+#include <asm/ebus_32.h>
 #endif
 #endif
similarity index 66%
rename from include/asm-sparc/elf.h
rename to arch/sparc/include/asm/elf.h
index f035c45d7b5e3ee4f02fce36767775fd85083cb3..0a2816c50b07faa54c98a1b75798d4d192ddc2da 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_ELF_H
 #define ___ASM_SPARC_ELF_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/elf_64.h>
+#include <asm/elf_64.h>
 #else
-#include <asm-sparc/elf_32.h>
+#include <asm/elf_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/floppy.h
rename to arch/sparc/include/asm/floppy.h
index 6c628ba15a8d62ceaccb1e0124457435c478b445..faebd335b600647493ff6306f817220b23167af6 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_FLOPPY_H
 #define ___ASM_SPARC_FLOPPY_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/floppy_64.h>
+#include <asm/floppy_64.h>
 #else
-#include <asm-sparc/floppy_32.h>
+#include <asm/floppy_32.h>
 #endif
 #endif
similarity index 99%
rename from include/asm-sparc/floppy_32.h
rename to arch/sparc/include/asm/floppy_32.h
index acdd06eafe596c0c360264f44e6be4bdf379a2d9..ae3f00bf22ff91d990ab4c47aaa200729c570181 100644 (file)
@@ -1,4 +1,4 @@
-/* asm-sparc/floppy.h: Sparc specific parts of the Floppy driver.
+/* asm/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
  */
similarity index 65%
rename from include/asm-sparc/futex.h
rename to arch/sparc/include/asm/futex.h
index c6a9f038c531b22defd2ba117c975a14c660f747..736335f3671370532ce9c8ced8e0adb14e42776a 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_FUTEX_H
 #define ___ASM_SPARC_FUTEX_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/futex_64.h>
+#include <asm/futex_64.h>
 #else
-#include <asm-sparc/futex_32.h>
+#include <asm/futex_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/hardirq.h
rename to arch/sparc/include/asm/hardirq.h
index 15647877310031815fdbcfc2bada8d5de6c856f2..44d4e23451486a9c3d5f0041c42c58bbd3bb145c 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_HARDIRQ_H
 #define ___ASM_SPARC_HARDIRQ_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/hardirq_64.h>
+#include <asm/hardirq_64.h>
 #else
-#include <asm-sparc/hardirq_32.h>
+#include <asm/hardirq_32.h>
 #endif
 #endif
similarity index 66%
rename from include/asm-sparc/head.h
rename to arch/sparc/include/asm/head.h
index 14652abdea31c42cf97a6a3dc93df7bcb19804ca..be8f03f3e731d568e2260bb09bb1006708a9e2cb 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_HEAD_H
 #define ___ASM_SPARC_HEAD_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/head_64.h>
+#include <asm/head_64.h>
 #else
-#include <asm-sparc/head_32.h>
+#include <asm/head_32.h>
 #endif
 #endif
similarity index 91%
rename from include/asm-sparc/hugetlb.h
rename to arch/sparc/include/asm/hugetlb.h
index 412af58926a0af752854dffdc113bc5dac04ae3a..177061064ee602ed4dc0e8e956a4b682695c79f0 100644 (file)
@@ -22,7 +22,8 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
  * If the arch doesn't supply something else, assume that hugepage
  * size aligned regions are ok without further preparation.
  */
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+                       unsigned long addr, unsigned long len)
 {
        if (len & ~HPAGE_MASK)
                return -EINVAL;
@@ -31,7 +32,7 @@ static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
        return 0;
 }
 
-static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
                                          unsigned long addr, unsigned long end,
                                          unsigned long floor,
                                          unsigned long ceiling)
similarity index 98%
rename from include/asm-sparc/ide.h
rename to arch/sparc/include/asm/ide.h
index 879fcec72dc12e0bdd2726b19b6d77aba1d489b1..b7af3d6582394b6fb2b370479bd2523f21e6281e 100644 (file)
@@ -21,9 +21,6 @@
 #include <asm/psr.h>
 #endif
 
-#undef  MAX_HWIFS
-#define MAX_HWIFS      2
-
 #define __ide_insl(data_reg, buffer, wcount) \
        __ide_insw(data_reg, buffer, (wcount)<<1)
 #define __ide_outsl(data_reg, buffer, wcount) \
similarity index 67%
rename from include/asm-sparc/io.h
rename to arch/sparc/include/asm/io.h
index fc9024d3dfc30f5fdd7990c581abc33e19acc93b..a34b2994937ab2e4323de0308ab8a630729dcf70 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_IO_H
 #define ___ASM_SPARC_IO_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/io_64.h>
+#include <asm/io_64.h>
 #else
-#include <asm-sparc/io_32.h>
+#include <asm/io_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/iommu.h
rename to arch/sparc/include/asm/iommu.h
index 91b072b0d7a083b1dfa272b7622ecf25d9859974..e650965b4a8d18224c0e68b9abd52d9bdf996fcf 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_IOMMU_H
 #define ___ASM_SPARC_IOMMU_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/iommu_64.h>
+#include <asm/iommu_64.h>
 #else
-#include <asm-sparc/iommu_32.h>
+#include <asm/iommu_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/ipcbuf.h
rename to arch/sparc/include/asm/ipcbuf.h
index 037605d986e25f7c527468c67ee33330c2bce9a1..17d6ef7b23a480665487925d0837ccd688833a73 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_IPCBUF_H
 #define ___ASM_SPARC_IPCBUF_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/ipcbuf_64.h>
+#include <asm/ipcbuf_64.h>
 #else
-#include <asm-sparc/ipcbuf_32.h>
+#include <asm/ipcbuf_32.h>
 #endif
 #endif
similarity index 66%
rename from include/asm-sparc/irq.h
rename to arch/sparc/include/asm/irq.h
index 7af6bb4aa09c8043c68f42fb7ae1a620afc61d57..3b44a6a140747d91837a415496d4b3a065b02abe 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_IRQ_H
 #define ___ASM_SPARC_IRQ_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/irq_64.h>
+#include <asm/irq_64.h>
 #else
-#include <asm-sparc/irq_32.h>
+#include <asm/irq_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/irqflags.h
rename to arch/sparc/include/asm/irqflags.h
index c6402b187e23cca383976e3beacc6bafd8968919..1e138632bd3f03689da1583cb6e70cd377e74698 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_IRQFLAGS_H
 #define ___ASM_SPARC_IRQFLAGS_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/irqflags_64.h>
+#include <asm/irqflags_64.h>
 #else
-#include <asm-sparc/irqflags_32.h>
+#include <asm/irqflags_32.h>
 #endif
 #endif
similarity index 96%
rename from include/asm-sparc/irqflags_32.h
rename to arch/sparc/include/asm/irqflags_32.h
index db398fb328263051be401e0e0aabb97fcdf2a77f..0fca9d97d44f15bd1a3832de7e02a990e0fa6577 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sparc/irqflags.h
+ * include/asm/irqflags.h
  *
  * IRQ flags handling
  *
similarity index 97%
rename from include/asm-sparc/irqflags_64.h
rename to arch/sparc/include/asm/irqflags_64.h
index 024fc54d068205befa262d80582d6dc591f34fe6..bb42e59162aab85829566a369255a55ce67180aa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sparc64/irqflags.h
+ * include/asm/irqflags.h
  *
  * IRQ flags handling
  *
similarity index 65%
rename from include/asm-sparc/kdebug.h
rename to arch/sparc/include/asm/kdebug.h
index fe07d00d0534424d0d295341f60ba59cd72e3510..8d12581ca38616458ee1a04a9e7454b6208caa4c 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_KDEBUG_H
 #define ___ASM_SPARC_KDEBUG_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/kdebug_64.h>
+#include <asm/kdebug_64.h>
 #else
-#include <asm-sparc/kdebug_32.h>
+#include <asm/kdebug_32.h>
 #endif
 #endif
similarity index 64%
rename from include/asm-sparc/mc146818rtc.h
rename to arch/sparc/include/asm/mc146818rtc.h
index 9ab65c21e9e43233b2c9c925438bf4c8f1cceba7..67ed9e3a02357260dacd8a065ef8840a9a34de56 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_MC146818RTC_H
 #define ___ASM_SPARC_MC146818RTC_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/mc146818rtc_64.h>
+#include <asm/mc146818rtc_64.h>
 #else
-#include <asm-sparc/mc146818rtc_32.h>
+#include <asm/mc146818rtc_32.h>
 #endif
 #endif
similarity index 66%
rename from include/asm-sparc/mmu.h
rename to arch/sparc/include/asm/mmu.h
index ee66bf6dcbd6b1deefbc8a2b90dc5f65d2385827..88fa313887dbafff2db6f62fbb5a8c1eef805a07 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_MMU_H
 #define ___ASM_SPARC_MMU_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/mmu_64.h>
+#include <asm/mmu_64.h>
 #else
-#include <asm-sparc/mmu_32.h>
+#include <asm/mmu_32.h>
 #endif
 #endif
similarity index 64%
rename from include/asm-sparc/mmu_context.h
rename to arch/sparc/include/asm/mmu_context.h
index e14efb9532ff235c4f5f6e769197a8f557584953..5531346c64f9b55d90d58b07437cc5a1b842ab49 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_MMU_CONTEXT_H
 #define ___ASM_SPARC_MMU_CONTEXT_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/mmu_context_64.h>
+#include <asm/mmu_context_64.h>
 #else
-#include <asm-sparc/mmu_context_32.h>
+#include <asm/mmu_context_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/module.h
rename to arch/sparc/include/asm/module.h
index 516138fe681a53117f673b942ba1b293a203ccee..e82cf9a3e60ee53e22ba05abdb0ef2a024e8b487 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_MODULE_H
 #define ___ASM_SPARC_MODULE_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/module_64.h>
+#include <asm/module_64.h>
 #else
-#include <asm-sparc/module_32.h>
+#include <asm/module_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/mostek.h
rename to arch/sparc/include/asm/mostek.h
index 5b9f7fec7ee74cb1b6bb2d72bb952d5268ef8b82..433be3e0a69b375d057ae4a424ab61c806703b59 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_MOSTEK_H
 #define ___ASM_SPARC_MOSTEK_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/mostek_64.h>
+#include <asm/mostek_64.h>
 #else
-#include <asm-sparc/mostek_32.h>
+#include <asm/mostek_32.h>
 #endif
 #endif
similarity index 64%
rename from include/asm-sparc/of_platform.h
rename to arch/sparc/include/asm/of_platform.h
index 851eb84d737ef61a3eb9ea9fe2c1bcc459373acf..aa699775ffba8c9dd40b56465d725f6aba224fb1 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_OF_PLATFORM_H
 #define ___ASM_SPARC_OF_PLATFORM_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/of_platform_64.h>
+#include <asm/of_platform_64.h>
 #else
-#include <asm-sparc/of_platform_32.h>
+#include <asm/of_platform_32.h>
 #endif
 #endif
similarity index 91%
rename from include/asm-sparc/of_platform_32.h
rename to arch/sparc/include/asm/of_platform_32.h
index 38334351c36b04685861015c7a997676bd224b3a..723f7c9b7411dbce7f5d995b1538a26928cdd630 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
  *                      <benh@kernel.crashing.org>
- *    Modified for Sparc by merging parts of asm-sparc/of_device.h
+ *    Modified for Sparc by merging parts of asm/of_device.h
  *             by Stephen Rothwell
  *
  *  This program is free software; you can redistribute it and/or
similarity index 91%
rename from include/asm-sparc/of_platform_64.h
rename to arch/sparc/include/asm/of_platform_64.h
index 78aa032b674c42bb7a4e1f02aaa6d243d298d13f..4f66a5f6342d88dae63419b799707fbabba1c3f2 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
  *                      <benh@kernel.crashing.org>
- *    Modified for Sparc by merging parts of asm-sparc/of_device.h
+ *    Modified for Sparc by merging parts of asm/of_device.h
  *             by Stephen Rothwell
  *
  *  This program is free software; you can redistribute it and/or
similarity index 65%
rename from include/asm-sparc/openprom.h
rename to arch/sparc/include/asm/openprom.h
index 8c349f0619946939cbcef609a403db678620e495..aaeae905ed3f945482a27d812a7df0b245ec22a9 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_OPENPROM_H
 #define ___ASM_SPARC_OPENPROM_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/openprom_64.h>
+#include <asm/openprom_64.h>
 #else
-#include <asm-sparc/openprom_32.h>
+#include <asm/openprom_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/oplib.h
rename to arch/sparc/include/asm/oplib.h
index e88d7c04a292279013e44b15a83843752d4dffa0..72e04e13a6b4059b1c0f5a0946c2510db51f6ce9 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_OPLIB_H
 #define ___ASM_SPARC_OPLIB_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/oplib_64.h>
+#include <asm/oplib_64.h>
 #else
-#include <asm-sparc/oplib_32.h>
+#include <asm/oplib_32.h>
 #endif
 #endif
similarity index 66%
rename from include/asm-sparc/page.h
rename to arch/sparc/include/asm/page.h
index f32f49fcf75c71f4cf37f4b0123dc833a1a19f7c..f21de034902596744ed071a80b0a53147b04460e 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_PAGE_H
 #define ___ASM_SPARC_PAGE_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/page_64.h>
+#include <asm/page_64.h>
 #else
-#include <asm-sparc/page_32.h>
+#include <asm/page_32.h>
 #endif
 #endif
similarity index 97%
rename from include/asm-sparc/page_32.h
rename to arch/sparc/include/asm/page_32.h
index 14de518cc38ffddb1bf7786d3ba5722ae4902a78..cf5fb70ca1c1c3f562bdeae825db12fda8f90963 100644 (file)
@@ -134,9 +134,6 @@ BTFIXUPDEF_SETHI(sparc_unmapped_base)
 
 #endif /* !(__ASSEMBLY__) */
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 #define PAGE_OFFSET    0xf0000000
 #ifndef __ASSEMBLY__
 extern unsigned long phys_base;
similarity index 97%
rename from include/asm-sparc/page_64.h
rename to arch/sparc/include/asm/page_64.h
index a8a2bba032c1a158704279383b0d59cfac0877fb..b579b910ef5123b24c1fc02fc92c1d4520e6ea9e 100644 (file)
@@ -106,9 +106,6 @@ typedef struct page *pgtable_t;
 
 #endif /* !(__ASSEMBLY__) */
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 /* We used to stick this into a hard-coded global register (%g4)
  * but that does not make sense anymore.
  */
similarity index 66%
rename from include/asm-sparc/pci.h
rename to arch/sparc/include/asm/pci.h
index b807d52a48091164b0010be6bd4466863508ed8c..6e14fd179335d0a24d05cc71293589b63331607f 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_PCI_H
 #define ___ASM_SPARC_PCI_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/pci_64.h>
+#include <asm/pci_64.h>
 #else
-#include <asm-sparc/pci_32.h>
+#include <asm/pci_32.h>
 #endif
 #endif
similarity index 98%
rename from include/asm-sparc/pci_32.h
rename to arch/sparc/include/asm/pci_32.h
index b93b6c79e08f6d48692f1539ced9fb7dbfeb8629..0ee949d220c06d3c3a7beec15b19ca3abf33e367 100644 (file)
@@ -154,7 +154,8 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 
 #define PCI_DMA_ERROR_CODE      (~(dma_addr_t)0x0)
 
-static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
+static inline int pci_dma_mapping_error(struct pci_dev *pdev,
+                                       dma_addr_t dma_addr)
 {
         return (dma_addr == PCI_DMA_ERROR_CODE);
 }
similarity index 97%
rename from include/asm-sparc/pci_64.h
rename to arch/sparc/include/asm/pci_64.h
index f59f2571295b69e8304ba406d54d17d7e6260b49..4f79a54948f6913c00c8b4400a9e1849cbc7b803 100644 (file)
@@ -140,9 +140,10 @@ extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
 #define PCI64_REQUIRED_MASK    (~(dma64_addr_t)0)
 #define PCI64_ADDR_BASE                0xfffc000000000000UL
 
-static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
+static inline int pci_dma_mapping_error(struct pci_dev *pdev,
+                                       dma_addr_t dma_addr)
 {
-       return dma_mapping_error(dma_addr);
+       return dma_mapping_error(&pdev->dev, dma_addr);
 }
 
 #ifdef CONFIG_PCI
similarity index 65%
rename from include/asm-sparc/percpu.h
rename to arch/sparc/include/asm/percpu.h
index d98ed6cf2e36cdc31541e80bdcb9abd8d9f44a86..bfb1d19ff1bf1ed11303f2a50895d3c692601d90 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_PERCPU_H
 #define ___ASM_SPARC_PERCPU_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/percpu_64.h>
+#include <asm/percpu_64.h>
 #else
-#include <asm-sparc/percpu_32.h>
+#include <asm/percpu_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/pgalloc.h
rename to arch/sparc/include/asm/pgalloc.h
index 7fa02b53d392cef4e9c48a82decdbc639c9b97ae..b6db1f7cdcab325d216c4549a4e3426cf73ca9b5 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_PGALLOC_H
 #define ___ASM_SPARC_PGALLOC_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/pgalloc_64.h>
+#include <asm/pgalloc_64.h>
 #else
-#include <asm-sparc/pgalloc_32.h>
+#include <asm/pgalloc_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/pgtable.h
rename to arch/sparc/include/asm/pgtable.h
index 63cdef53bc52ef78ef6521cfe19205be61001d1e..59ba6f6207322ef7533a73998f54d1b1b888fc94 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_PGTABLE_H
 #define ___ASM_SPARC_PGTABLE_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/pgtable_64.h>
+#include <asm/pgtable_64.h>
 #else
-#include <asm-sparc/pgtable_32.h>
+#include <asm/pgtable_32.h>
 #endif
 #endif
similarity index 99%
rename from include/asm-sparc/pgtable_32.h
rename to arch/sparc/include/asm/pgtable_32.h
index 781bd4694a1c1fd2ce698c84c014caecf189bf97..08237fda8874390b267a2036564f364e79eaf1a6 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
-/*  asm-sparc/pgtable.h:  Defines and functions used to work
+/*  asm/pgtable.h:  Defines and functions used to work
  *                        with Sparc page tables.
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
similarity index 64%
rename from include/asm-sparc/posix_types.h
rename to arch/sparc/include/asm/posix_types.h
index 58c820d75e8335db5ab20f7bf375d6f2706fe802..03a0e091a884a1909e5f2e7fb8a03e01a0079370 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_POSIX_TYPES_H
 #define ___ASM_SPARC_POSIX_TYPES_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/posix_types_64.h>
+#include <asm/posix_types_64.h>
 #else
-#include <asm-sparc/posix_types_32.h>
+#include <asm/posix_types_32.h>
 #endif
 #endif
similarity index 64%
rename from include/asm-sparc/processor.h
rename to arch/sparc/include/asm/processor.h
index 11a66bb02eaa01b1dc520e05dfef5adfd2193823..9da9646bf6c6b326ee6d6f47b1d60bd4dd970453 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_PROCESSOR_H
 #define ___ASM_SPARC_PROCESSOR_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/processor_64.h>
+#include <asm/processor_64.h>
 #else
-#include <asm-sparc/processor_32.h>
+#include <asm/processor_32.h>
 #endif
 #endif
similarity index 97%
rename from include/asm-sparc/processor_32.h
rename to arch/sparc/include/asm/processor_32.h
index 562c0d69c537adc6914dc100c1e10124a92a3c4c..2ae67a2e7f3a877c21644cbd83adac3e235ae522 100644 (file)
@@ -1,4 +1,4 @@
-/* include/asm-sparc/processor.h
+/* include/asm/processor.h
  *
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -114,6 +114,7 @@ extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 extern unsigned long get_wchan(struct task_struct *);
 
+#define task_pt_regs(tsk) ((tsk)->thread.kregs)
 #define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
 #define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
 
similarity index 99%
rename from include/asm-sparc/processor_64.h
rename to arch/sparc/include/asm/processor_64.h
index 70d42801a0d20cd08f78eb5dcc544adf49cafc19..137a6bd72fc805f9ddfd4f4a12acd3fdf7199c78 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sparc64/processor.h
+ * include/asm/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
similarity index 65%
rename from include/asm-sparc/ptrace.h
rename to arch/sparc/include/asm/ptrace.h
index f36ab6c30ff30cbf19c71e39af7a33c877b4b4bb..6dcbe2eed2e201a4c8bc980dcb15b868474fbcf3 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_PTRACE_H
 #define ___ASM_SPARC_PTRACE_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/ptrace_64.h>
+#include <asm/ptrace_64.h>
 #else
-#include <asm-sparc/ptrace_32.h>
+#include <asm/ptrace_32.h>
 #endif
 #endif
similarity index 98%
rename from include/asm-sparc/ptrace_32.h
rename to arch/sparc/include/asm/ptrace_32.h
index 0401cc7ec38e9cd04f839333c5825b97d6795271..d43c88b86834d2fc08986b32e1191b4962bf0f9d 100644 (file)
@@ -74,6 +74,7 @@ struct sparc_stackf {
 
 #define user_mode(regs) (!((regs)->psr & PSR_PS))
 #define instruction_pointer(regs) ((regs)->pc)
+#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
 unsigned long profile_pc(struct pt_regs *);
 extern void show_regs(struct pt_regs *);
 #endif
similarity index 99%
rename from include/asm-sparc/ptrace_64.h
rename to arch/sparc/include/asm/ptrace_64.h
index a682e66d5c4a635e09cc3941d22f74150d87e948..ec6d45c84cd0e4a0a0aa12cbc6e229b975d6f38e 100644 (file)
@@ -146,6 +146,7 @@ do {        current_thread_info()->syscall_noerror = 1; \
 } while (0)
 #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
 #define instruction_pointer(regs) ((regs)->tpc)
+#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
 #define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
 #ifdef CONFIG_SMP
 extern unsigned long profile_pc(struct pt_regs *);
similarity index 66%
rename from include/asm-sparc/reg.h
rename to arch/sparc/include/asm/reg.h
index cb34b0a49aad47375066c73ed031845d64be868d..0c16e19cae4da870e1bee3a512009bb7943ebe9b 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_REG_H
 #define ___ASM_SPARC_REG_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/reg_64.h>
+#include <asm/reg_64.h>
 #else
-#include <asm-sparc/reg_32.h>
+#include <asm/reg_32.h>
 #endif
 #endif
similarity index 98%
rename from include/asm-sparc/reg_32.h
rename to arch/sparc/include/asm/reg_32.h
index 42fecfcd97e7bc92ddc3aee27b01ddcc18e0914a..1efb056fb3d15994c96214ed77ad6348fb097fe4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-sparc/reg.h
+ * linux/include/asm/reg.h
  * Layout of the registers as expected by gdb on the Sparc
  * we should replace the user.h definitions with those in
  * this file, we don't even use the other
similarity index 97%
rename from include/asm-sparc/reg_64.h
rename to arch/sparc/include/asm/reg_64.h
index eb24a07ff4d568c9d9e53fb30368e6c0e3bc039f..6f277d7c7d88f6114d5d5f2859f78a1323997d00 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/asm-sparc64/reg.h
+ * linux/asm/reg.h
  * Layout of the registers as expected by gdb on the Sparc
  * we should replace the user.h definitions with those in
  * this file, we don't even use the other
similarity index 66%
rename from include/asm-sparc/sbus.h
rename to arch/sparc/include/asm/sbus.h
index 8f29a19796658336930648cd958b6b3f4f2833cd..f82481ab44db043cd27314ffa30bf4268ef39e7e 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SBUS_H
 #define ___ASM_SPARC_SBUS_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/sbus_64.h>
+#include <asm/sbus_64.h>
 #else
-#include <asm-sparc/sbus_32.h>
+#include <asm/sbus_32.h>
 #endif
 #endif
similarity index 64%
rename from include/asm-sparc/scatterlist.h
rename to arch/sparc/include/asm/scatterlist.h
index b1a0e316c2b6f762d9f26c3dd530a82caa967fd4..ec21a4517641b16b8414baab15f18a55a4363e27 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SCATTERLIST_H
 #define ___ASM_SPARC_SCATTERLIST_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/scatterlist_64.h>
+#include <asm/scatterlist_64.h>
 #else
-#include <asm-sparc/scatterlist_32.h>
+#include <asm/scatterlist_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/sections.h
rename to arch/sparc/include/asm/sections.h
index cbd019162425bf90b4df4ef526b7c42370513cc1..c7c69b00967ffe4fa826dcdbece00d901c1fe270 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SECTIONS_H
 #define ___ASM_SPARC_SECTIONS_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/sections_64.h>
+#include <asm/sections_64.h>
 #else
-#include <asm-sparc/sections_32.h>
+#include <asm/sections_32.h>
 #endif
 #endif
similarity index 64%
rename from include/asm-sparc/sfp-machine.h
rename to arch/sparc/include/asm/sfp-machine.h
index c676fcc2dd277df52fe27378f00f97f91ad32706..4ebc3823ed4fec0a5fb66ad3324bedab98fe19a2 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SFP_MACHINE_H
 #define ___ASM_SPARC_SFP_MACHINE_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/sfp-machine_64.h>
+#include <asm/sfp-machine_64.h>
 #else
-#include <asm-sparc/sfp-machine_32.h>
+#include <asm/sfp-machine_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/shmparam.h
rename to arch/sparc/include/asm/shmparam.h
index 16fda7e9acc851c17ba99616e5c677ecceb73e46..8bf0cfe0694f8951717b8a885c415c254b77949b 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SHMPARAM_H
 #define ___ASM_SPARC_SHMPARAM_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/shmparam_64.h>
+#include <asm/shmparam_64.h>
 #else
-#include <asm-sparc/shmparam_32.h>
+#include <asm/shmparam_32.h>
 #endif
 #endif
similarity index 64%
rename from include/asm-sparc/sigcontext.h
rename to arch/sparc/include/asm/sigcontext.h
index 82fc7d54a4fa18a55af42944c99ed6fed0d18751..e92de7e286b54dceaf41b679bef2d50a854cdadc 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SIGCONTEXT_H
 #define ___ASM_SPARC_SIGCONTEXT_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/sigcontext_64.h>
+#include <asm/sigcontext_64.h>
 #else
-#include <asm-sparc/sigcontext_32.h>
+#include <asm/sigcontext_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/siginfo.h
rename to arch/sparc/include/asm/siginfo.h
index 2c9fccf4ce18f65bccf3becbb1e110cc79057cc3..bd81f8d7f5ce5aff8b846f61daef596a7a342ffa 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SIGINFO_H
 #define ___ASM_SPARC_SIGINFO_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/siginfo_64.h>
+#include <asm/siginfo_64.h>
 #else
-#include <asm-sparc/siginfo_32.h>
+#include <asm/siginfo_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/signal.h
rename to arch/sparc/include/asm/signal.h
index 36f5f9e482f7240ad91f199d4468d114cadd8ac2..27ab05dc203e82bc838d7e9d999e7a2ea827a343 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SIGNAL_H
 #define ___ASM_SPARC_SIGNAL_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/signal_64.h>
+#include <asm/signal_64.h>
 #else
-#include <asm-sparc/signal_32.h>
+#include <asm/signal_32.h>
 #endif
 #endif
similarity index 66%
rename from include/asm-sparc/smp.h
rename to arch/sparc/include/asm/smp.h
index 1f9dedfbabd816c0cbd8c2abb7d9d1f4e4c10e5c..b59672d0e19b6dd988fda29ad2871040e833168d 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SMP_H
 #define ___ASM_SPARC_SMP_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/smp_64.h>
+#include <asm/smp_64.h>
 #else
-#include <asm-sparc/smp_32.h>
+#include <asm/smp_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/spinlock.h
rename to arch/sparc/include/asm/spinlock.h
index 3b71c50b72eb10c615dc6cd3ba481433bb5352c2..f276b0036b2c4d3d547d25a2a7ff5e9722eac7af 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SPINLOCK_H
 #define ___ASM_SPARC_SPINLOCK_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/spinlock_64.h>
+#include <asm/spinlock_64.h>
 #else
-#include <asm-sparc/spinlock_32.h>
+#include <asm/spinlock_32.h>
 #endif
 #endif
similarity index 66%
rename from include/asm-sparc/stat.h
rename to arch/sparc/include/asm/stat.h
index 9fdcaf8c9cd30b180b81bbb1dedff0f437601ac3..d8153013df7270d134416ed0ce272db68ab80cb7 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_STAT_H
 #define ___ASM_SPARC_STAT_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/stat_64.h>
+#include <asm/stat_64.h>
 #else
-#include <asm-sparc/stat_32.h>
+#include <asm/stat_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/statfs.h
rename to arch/sparc/include/asm/statfs.h
index a70cc52e7018f6fad845c7f6d8f826924e97a7c7..5e937a73743dd85d7b830db6be254be72ed01105 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_STATFS_H
 #define ___ASM_SPARC_STATFS_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/statfs_64.h>
+#include <asm/statfs_64.h>
 #else
-#include <asm-sparc/statfs_32.h>
+#include <asm/statfs_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/string.h
rename to arch/sparc/include/asm/string.h
index 14c04c7697a5e4b61c3bc1703409a1c477d55ca1..98b72a0c8e6e624d0ea6618e4f8ace5736369309 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_STRING_H
 #define ___ASM_SPARC_STRING_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/string_64.h>
+#include <asm/string_64.h>
 #else
-#include <asm-sparc/string_32.h>
+#include <asm/string_32.h>
 #endif
 #endif
similarity index 99%
rename from include/asm-sparc/sunbpp.h
rename to arch/sparc/include/asm/sunbpp.h
index 92ee1a8ff3a2783a248c417cb1f19198f163e814..d81a02eaf78bfc392fb0431adf40fe3b82f39fd7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sparc/sunbpp.h
+ * include/asm/sunbpp.h
  */
 
 #ifndef _ASM_SPARC_SUNBPP_H
diff --git a/arch/sparc/include/asm/syscall.h b/arch/sparc/include/asm/syscall.h
new file mode 100644 (file)
index 0000000..7486c60
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef __ASM_SPARC_SYSCALL_H
+#define __ASM_SPARC_SYSCALL_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+
+/* The system call number is given by the user in %g1 */
+static inline long syscall_get_nr(struct task_struct *task,
+                                 struct pt_regs *regs)
+{
+       int syscall_p = pt_regs_is_syscall(regs);
+
+       return (syscall_p ? regs->u_regs[UREG_G1] : -1L);
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+                                   struct pt_regs *regs)
+{
+       /* XXX This needs some thought.  On Sparc we don't
+        * XXX save away the original %o0 value somewhere.
+        * XXX Instead we hold it in register %l5 at the top
+        * XXX level trap frame and pass this down to the signal
+        * XXX dispatch code which is the only place that value
+        * XXX ever was needed.
+        */
+}
+
+#ifdef CONFIG_SPARC32
+static inline bool syscall_has_error(struct pt_regs *regs)
+{
+       return (regs->psr & PSR_C) ? true : false;
+}
+static inline void syscall_set_error(struct pt_regs *regs)
+{
+       regs->psr |= PSR_C;
+}
+static inline void syscall_clear_error(struct pt_regs *regs)
+{
+       regs->psr &= ~PSR_C;
+}
+#else
+static inline bool syscall_has_error(struct pt_regs *regs)
+{
+       return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false;
+}
+static inline void syscall_set_error(struct pt_regs *regs)
+{
+       regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY);
+}
+static inline void syscall_clear_error(struct pt_regs *regs)
+{
+       regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY);
+}
+#endif
+
+static inline long syscall_get_error(struct task_struct *task,
+                                    struct pt_regs *regs)
+{
+       long val = regs->u_regs[UREG_I0];
+
+       return (syscall_has_error(regs) ? -val : 0);
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+                                           struct pt_regs *regs)
+{
+       long val = regs->u_regs[UREG_I0];
+
+       return val;
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+                                           struct pt_regs *regs,
+                                           int error, long val)
+{
+       if (error) {
+               syscall_set_error(regs);
+               regs->u_regs[UREG_I0] = -error;
+       } else {
+               syscall_clear_error(regs);
+               regs->u_regs[UREG_I0] = val;
+       }
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned int i, unsigned int n,
+                                        unsigned long *args)
+{
+       int zero_extend = 0;
+       unsigned int j;
+
+#ifdef CONFIG_SPARC64
+       if (test_tsk_thread_flag(task, TIF_32BIT))
+               zero_extend = 1;
+#endif
+
+       for (j = 0; j < n; j++) {
+               unsigned long val = regs->u_regs[UREG_I0 + i + j];
+
+               if (zero_extend)
+                       args[j] = (u32) val;
+               else
+                       args[j] = val;
+       }
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned int i, unsigned int n,
+                                        const unsigned long *args)
+{
+       unsigned int j;
+
+       for (j = 0; j < n; j++)
+               regs->u_regs[UREG_I0 + i + j] = args[j];
+}
+
+#endif /* __ASM_SPARC_SYSCALL_H */
similarity index 65%
rename from include/asm-sparc/system.h
rename to arch/sparc/include/asm/system.h
index 15e2a3bc4f6154f95f17a8bb2a1de37214b3a381..7944a7cfc99636032c358bfa894332fb50c07c3a 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_SYSTEM_H
 #define ___ASM_SPARC_SYSTEM_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/system_64.h>
+#include <asm/system_64.h>
 #else
-#include <asm-sparc/system_32.h>
+#include <asm/system_32.h>
 #endif
 #endif
similarity index 64%
rename from include/asm-sparc/thread_info.h
rename to arch/sparc/include/asm/thread_info.h
index 64155cf89f3706130c586bb5a0eebc2eb6ef87d8..122d7acc07e6b91519b756e9676e4dbe10c69ab9 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_THREAD_INFO_H
 #define ___ASM_SPARC_THREAD_INFO_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/thread_info_64.h>
+#include <asm/thread_info_64.h>
 #else
-#include <asm-sparc/thread_info_32.h>
+#include <asm/thread_info_32.h>
 #endif
 #endif
similarity index 94%
rename from include/asm-sparc/thread_info_32.h
rename to arch/sparc/include/asm/thread_info_32.h
index 91b9f5888c855defa112d38ec20761a6664f1875..cbb892d0dff04b033ae371af6175cb443cb2c06e 100644 (file)
@@ -86,6 +86,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define THREAD_INFO_ORDER  1
 #endif
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void)
 #define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)()
 
@@ -128,7 +130,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
  * thread information flag bit numbers
  */
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
-/* flag bit 1 is available */
+#define TIF_NOTIFY_RESUME      1       /* callback before returning to user */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK    4       /* restore signal mask in do_signal() */
@@ -140,12 +142,17 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
 
 /* as above, but as bit values */
 #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_DO_NOTIFY_RESUME_MASK     (_TIF_NOTIFY_RESUME | \
+                                        _TIF_SIGPENDING | \
+                                        _TIF_RESTORE_SIGMASK)
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_THREAD_INFO_H */
similarity index 96%
rename from include/asm-sparc/thread_info_64.h
rename to arch/sparc/include/asm/thread_info_64.h
index c6d2e6c7f844cf43a88a852c388519b70b8fc91d..c0a737d7292c4462456f0b0e27ff6aae149142a6 100644 (file)
@@ -155,6 +155,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define __THREAD_INFO_ORDER    0
 #endif /* PAGE_SHIFT == 13 */
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 #ifdef CONFIG_DEBUG_STACK_USAGE
 #define alloc_thread_info(tsk)                                 \
 ({                                                             \
@@ -217,7 +219,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
  *      nop
  */
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
-/* flags bit 1 is available */
+#define TIF_NOTIFY_RESUME      1       /* callback before returning to user */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_PERFCTR            4       /* performance counters active */
@@ -237,6 +239,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define TIF_POLLING_NRFLAG     14
 
 #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_PERFCTR           (1<<TIF_PERFCTR)
@@ -248,8 +251,9 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_USER_WORK_MASK    ((0xff << TI_FLAG_WSAVED_SHIFT) | \
-                                (_TIF_SIGPENDING | \
-                                 _TIF_NEED_RESCHED | _TIF_PERFCTR))
+                                _TIF_DO_NOTIFY_RESUME_MASK | \
+                                _TIF_NEED_RESCHED | _TIF_PERFCTR)
+#define _TIF_DO_NOTIFY_RESUME_MASK     (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING)
 
 /*
  * Thread-synchronous status.
similarity index 65%
rename from include/asm-sparc/timer.h
rename to arch/sparc/include/asm/timer.h
index 475baa05a96eff30f0a5a71e7ac2b9b5b923b9e8..612fd2779d9eaffe78dbf590194290e14fb05a98 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_TIMER_H
 #define ___ASM_SPARC_TIMER_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/timer_64.h>
+#include <asm/timer_64.h>
 #else
-#include <asm-sparc/timer_32.h>
+#include <asm/timer_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/timex.h
rename to arch/sparc/include/asm/timex.h
index 01d9f199d45243c1025fcbf15c48c4c79d47af01..70cc37b73827bc2fe1a3a5045326a893da6c3844 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_TIMEX_H
 #define ___ASM_SPARC_TIMEX_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/timex_64.h>
+#include <asm/timex_64.h>
 #else
-#include <asm-sparc/timex_32.h>
+#include <asm/timex_32.h>
 #endif
 #endif
similarity index 89%
rename from include/asm-sparc/timex_32.h
rename to arch/sparc/include/asm/timex_32.h
index 71b45c90ccae3d5db1959b755d5ad4e7690b386e..b6ccdb0d6f7de3fb23b8691c036be8acaa62e91f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-sparc/timex.h
+ * linux/include/asm/timex.h
  *
  * sparc architecture timex specifications
  */
similarity index 90%
rename from include/asm-sparc/timex_64.h
rename to arch/sparc/include/asm/timex_64.h
index c622535c45600bd6c9faab97b40255e71685214d..18b30bc9823b4e132d381c5d3de985f7b20c38fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-sparc64/timex.h
+ * linux/include/asm/timex.h
  *
  * sparc64 architecture timex specifications
  */
similarity index 66%
rename from include/asm-sparc/tlb.h
rename to arch/sparc/include/asm/tlb.h
index a821057327c4994d34544d87c9aab549b40971c0..92d0393bbcdc5d16b5a0ee9308171e79bc7469a2 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_TLB_H
 #define ___ASM_SPARC_TLB_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/tlb_64.h>
+#include <asm/tlb_64.h>
 #else
-#include <asm-sparc/tlb_32.h>
+#include <asm/tlb_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/tlbflush.h
rename to arch/sparc/include/asm/tlbflush.h
index 6e6bc12227b86f180108a1df5f26f01b07917aa6..2c9629fad1e2c33c6d33106ac53318e8ca98d94d 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_TLBFLUSH_H
 #define ___ASM_SPARC_TLBFLUSH_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/tlbflush_64.h>
+#include <asm/tlbflush_64.h>
 #else
-#include <asm-sparc/tlbflush_32.h>
+#include <asm/tlbflush_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/topology.h
rename to arch/sparc/include/asm/topology.h
index ed13630f32e25f68057f134b4a3083ef6c668f0f..ee4f191d394aa2789e48cdd98d8f51c2d3c8d45e 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_TOPOLOGY_H
 #define ___ASM_SPARC_TOPOLOGY_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/topology_64.h>
+#include <asm/topology_64.h>
 #else
-#include <asm-sparc/topology_32.h>
+#include <asm/topology_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/uaccess.h
rename to arch/sparc/include/asm/uaccess.h
index 424facce5238774118d29473f2a6218d8f7a5adf..e88fbe5c0457a922cd7f761d81378ac91c562703 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_UACCESS_H
 #define ___ASM_SPARC_UACCESS_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/uaccess_64.h>
+#include <asm/uaccess_64.h>
 #else
-#include <asm-sparc/uaccess_32.h>
+#include <asm/uaccess_32.h>
 #endif
 #endif
similarity index 65%
rename from include/asm-sparc/unistd.h
rename to arch/sparc/include/asm/unistd.h
index 3c2609618a099e037306190ce38ebbd56d848218..4207fb362da03e300ce2cff530ca68401560c7f7 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_UNISTD_H
 #define ___ASM_SPARC_UNISTD_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/unistd_64.h>
+#include <asm/unistd_64.h>
 #else
-#include <asm-sparc/unistd_32.h>
+#include <asm/unistd_32.h>
 #endif
 #endif
similarity index 99%
rename from include/asm-sparc/unistd_32.h
rename to arch/sparc/include/asm/unistd_32.h
index 2338a027637705052632b6c535170bc05ca5e312..648643a9f139b62930a6fd39ab6f4b614bd74c92 100644 (file)
 #define __NR_fallocate         314
 #define __NR_timerfd_settime   315
 #define __NR_timerfd_gettime   316
+#define __NR_signalfd4         317
+#define __NR_eventfd2          318
+#define __NR_epoll_create1     319
+#define __NR_dup3              320
+#define __NR_pipe2             321
+#define __NR_inotify_init1     322
 
-#define NR_SYSCALLS            317
+#define NR_SYSCALLS            323
 
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
  * it never had the plain ones and there is no value to adding those
similarity index 99%
rename from include/asm-sparc/unistd_64.h
rename to arch/sparc/include/asm/unistd_64.h
index 13be4453a1f0808f62cfa4cd276e15b664848a9b..c5cc0e052321850157df1edaf92b6020b5fb22d0 100644 (file)
 #define __NR_fallocate         314
 #define __NR_timerfd_settime   315
 #define __NR_timerfd_gettime   316
+#define __NR_signalfd4         317
+#define __NR_eventfd2          318
+#define __NR_epoll_create1     319
+#define __NR_dup3              320
+#define __NR_pipe2             321
+#define __NR_inotify_init1     322
 
-#define NR_SYSCALLS            317
+#define NR_SYSCALLS            323
 
 #ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
similarity index 97%
rename from include/asm-sparc/utrap.h
rename to arch/sparc/include/asm/utrap.h
index 9da37babbe5b895ca7538d0d8880bbc9e6fe9ad5..b10e527c22d967b72d1e172c3d55acef4a7ba34f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sparc64/utrap.h
+ * include/asm/utrap.h
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
similarity index 97%
rename from include/asm-sparc/vaddrs.h
rename to arch/sparc/include/asm/vaddrs.h
index a22fed5a3c6bef64d9b0d6eb75e9699e81754a68..541e13755cecb7159826de08cad615e4c091fbf8 100644 (file)
@@ -4,7 +4,7 @@
 #include <asm/head.h>
 
 /*
- * asm-sparc/vaddrs.h:  Here we define the virtual addresses at
+ * asm/vaddrs.h:  Here we define the virtual addresses at
  *                      which important things will be mapped.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
similarity index 66%
rename from include/asm-sparc/xor.h
rename to arch/sparc/include/asm/xor.h
index 35089a838c3f9713a68d6273bcc71f8fb52e0f03..8ed591c7db2dc1ee7220e543759165895bcfa52c 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef ___ASM_SPARC_XOR_H
 #define ___ASM_SPARC_XOR_H
 #if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/xor_64.h>
+#include <asm/xor_64.h>
 #else
-#include <asm-sparc/xor_32.h>
+#include <asm/xor_32.h>
 #endif
 #endif
similarity index 99%
rename from include/asm-sparc/xor_32.h
rename to arch/sparc/include/asm/xor_32.h
index f34b2cfa82069f760ae371f16f7e1060578daa12..44bfa0787f3ffeb244b63a044e189f6e88782e8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sparc/xor.h
+ * include/asm/xor.h
  *
  * Optimized RAID-5 checksumming functions for 32-bit Sparc.
  *
similarity index 98%
rename from include/asm-sparc/xor_64.h
rename to arch/sparc/include/asm/xor_64.h
index a0233884fc94c6084045b7db829c849ba9a06f24..bee4bf4be3af8cb4a41df1554252381eaddf952b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/asm-sparc64/xor.h
+ * include/asm/xor.h
  *
  * High speed xor_block operation for RAID4/5 utilizing the
  * UltraSparc Visual Instruction Set and Niagara block-init
index 2f96256dc5153bf04e06b176bff63da240495c3f..e8cdf715a546ccb0af9b0802d249368470a5a119 100644 (file)
@@ -1196,8 +1196,9 @@ sys_rt_sigreturn:
        be      1f
         nop
 
+       add     %sp, STACKFRAME_SZ, %o0
        call    syscall_trace
-        nop
+        mov    1, %o1
 
 1:
        /* We are returning to a signal handler. */
@@ -1287,8 +1288,12 @@ linux_fast_syscall:
         mov    %i3, %o3
 
 linux_syscall_trace:
+       add     %sp, STACKFRAME_SZ, %o0
        call    syscall_trace
-        nop
+        mov    0, %o1
+       cmp     %o0, 0
+       bne     3f
+        mov    -ENOSYS, %o0
        mov     %i0, %o0
        mov     %i1, %o1
        mov     %i2, %o2
@@ -1337,6 +1342,7 @@ syscall_is_too_hard:
        call    %l7
         mov    %i5, %o5
 
+3:
        st      %o0, [%sp + STACKFRAME_SZ + PT_I0]
 
 ret_sys_call:
@@ -1374,6 +1380,8 @@ ret_sys_call:
         st     %l2, [%sp + STACKFRAME_SZ + PT_NPC]
 
 linux_syscall_trace2:
+       add     %sp, STACKFRAME_SZ, %o0
+       mov     1, %o1
        call    syscall_trace
         add    %l1, 0x4, %l2                   /* npc = npc+4 */
        st      %l1, [%sp + STACKFRAME_SZ + PT_PC]
index 81f3b929743f12c17ec44642acb58f6526d4319c..20699c701412dc85506770375e94e3ccbe79efc5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/signal.h>
 #include <linux/regset.h>
 #include <linux/elf.h>
+#include <linux/tracehook.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -450,21 +451,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        return ret;
 }
 
-asmlinkage void syscall_trace(void)
+asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p)
 {
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
-       if (!(current->ptrace & PT_PTRACED))
-               return;
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                ? 0x80 : 0));
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig (current->exit_code, current, 1);
-               current->exit_code = 0;
+       int ret = 0;
+
+       if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+               if (syscall_exit_p)
+                       tracehook_report_syscall_exit(regs, 0);
+               else
+                       ret = tracehook_report_syscall_entry(regs);
        }
+
+       return ret;
 }
index 891f460b7b96ab1e8fb47d3483ba2aadf7361826..4da2e1f6629091ea60e7bccd81fc95b495ae065d 100644 (file)
@@ -69,12 +69,13 @@ ret_trap_lockless_ipi:
 
        ld      [%curptr + TI_FLAGS], %g2
 signal_p:
-       andcc   %g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0
+       andcc   %g2, _TIF_DO_NOTIFY_RESUME_MASK, %g0
        bz,a    ret_trap_continue
         ld     [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
 
+       mov     %g2, %o2
        mov     %l5, %o1
-       call    do_signal
+       call    do_notify_resume
         add    %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr
 
        /* Fall through. */
index 3fd1df9f9ba7e849609f5018d443378a301fb2e4..c94f91c8b6e0996dba7f057a815d0005376925d7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/smp.h>
 #include <linux/binfmts.h>     /* do_coredum */
 #include <linux/bitops.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
@@ -513,7 +514,7 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0)
+static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
 {
        struct k_sigaction ka;
        int restart_syscall;
@@ -552,6 +553,8 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0)
                 */
                if (test_thread_flag(TIF_RESTORE_SIGMASK))
                        clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+               tracehook_signal_handler(signr, &info, &ka, regs, 0);
                return;
        }
        if (restart_syscall &&
@@ -579,6 +582,17 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0)
        }
 }
 
+void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0,
+                     unsigned long thread_info_flags)
+{
+       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+               do_signal(regs, orig_i0);
+       if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+               clear_thread_flag(TIF_NOTIFY_RESUME);
+               tracehook_notify_resume(regs);
+       }
+}
+
 asmlinkage int
 do_sys_sigstack(struct sigstack __user *ssptr, struct sigstack __user *ossptr,
                unsigned long sp)
index 3c6b49a53ae82f8e7a77dc67b4445eb753591f6f..4d73421559c3aa1c62c79b77210fdabc9f5497fb 100644 (file)
@@ -97,7 +97,7 @@ asmlinkage int sparc_pipe(struct pt_regs *regs)
        int fd[2];
        int error;
 
-       error = do_pipe(fd);
+       error = do_pipe_flags(fd, 0);
        if (error)
                goto out;
        regs->u_regs[UREG_I1] = fd[1];
index 5a7c4c8345c3193b144c087b6820bbb32c238729..e1b9233b90ab3133587481322f30d3a260fc6569 100644 (file)
@@ -80,4 +80,5 @@ sys_call_table:
 /*300*/        .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
 /*305*/        .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
 /*310*/        .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
-/*315*/        .long sys_timerfd_settime, sys_timerfd_gettime
+/*315*/        .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
+/*320*/        .long sys_dup3, sys_pipe2, sys_inotify_init1
index c624e04ff03e4e03ad8c851a51dde6de88444c9d..ee30462598fc72b763da88077b72438be730cbf4 100644 (file)
@@ -1352,8 +1352,7 @@ void __init srmmu_paging_init(void)
                zones_size[ZONE_HIGHMEM] = npages;
                zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-               free_area_init_node(0, &contig_page_data, zones_size,
-                                   pfn_base, zholes_size);
+               free_area_init_node(0, zones_size, pfn_base, zholes_size);
        }
 }
 
index 2375fe9dc3124346673dfb462d2a137b05374a92..d1782f6368beeadf9afbc9936b3b8e39da75db90 100644 (file)
@@ -2123,8 +2123,7 @@ void __init sun4c_paging_init(void)
                zones_size[ZONE_HIGHMEM] = npages;
                zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-               free_area_init_node(0, &contig_page_data, zones_size,
-                                   pfn_base, zholes_size);
+               free_area_init_node(0, zones_size, pfn_base, zholes_size);
        }
 
        cnt = 0;
index 7c88263256af216c2b6889481297eeb95434949c..923a98959fa7349930efa343a4ab1febd4d5b05f 100644 (file)
@@ -17,6 +17,7 @@ config SPARC64
        select HAVE_LMB
        select HAVE_ARCH_KGDB
        select USE_GENERIC_SMP_HELPERS if SMP
+       select HAVE_ARCH_TRACEHOOK
 
 config GENERIC_TIME
        bool
index c1979482aa929bbf85db4a97ca7138365b35bda6..c831b0a4e660b69d1221230a2d5460db62459fef 100644 (file)
@@ -1,4 +1,4 @@
-#include <asm-sparc/unistd.h>
+#include <asm/unistd_32.h>
 
 unsigned sparc32_dir_class[] = {
 #include <asm-generic/audit_dir_write.h>
index 32fbab620852063dbe525bf3e9e32720af8b2323..fc294a292899ee383906e5040e2509907776527e 100644 (file)
@@ -22,8 +22,7 @@ extern void do_notify_resume(struct pt_regs *regs,
                             unsigned long orig_i0,
                             unsigned long thread_info_flags);
 
-extern asmlinkage void syscall_trace(struct pt_regs *regs,
-                                    int syscall_exit_p);
+extern asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p);
 
 extern void bad_trap_tl1(struct pt_regs *regs, long lvl);
 
index f3575a614fa2e643dbcc5f93e3e2e03f26e77e2e..53b19c8231a931ee1ab2f1a863e62053026ac748 100644 (file)
@@ -23,7 +23,7 @@
 #define IO_PAGE_SHIFT                  13
 #define IO_PAGE_SIZE                   (1UL << IO_PAGE_SHIFT)
 #define IO_PAGE_MASK                   (~(IO_PAGE_SIZE-1))
-#define IO_PAGE_ALIGN(addr)            (((addr)+IO_PAGE_SIZE-1)&IO_PAGE_MASK)
+#define IO_PAGE_ALIGN(addr)            ALIGN(addr, IO_PAGE_SIZE)
 
 #define IO_TSB_ENTRIES                 (128*1024)
 #define IO_TSB_SIZE                    (IO_TSB_ENTRIES * 8)
index b441a26b73b03ab514aa772609c92e8a179d2e12..c481673d249cb485dc1ceca3c02a073ebfc2aacc 100644 (file)
@@ -621,8 +621,9 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
 unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 {
        struct irq_handler_data *data;
-       struct ino_bucket *bucket;
        unsigned long hv_err, cookie;
+       struct ino_bucket *bucket;
+       struct irq_desc *desc;
        unsigned int virt_irq;
 
        bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
@@ -643,6 +644,13 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
        if (unlikely(!data))
                return 0;
 
+       /* In order to make the LDC channel startup sequence easier,
+        * especially wrt. locking, we do not let request_irq() enable
+        * the interrupt.
+        */
+       desc = irq_desc + virt_irq;
+       desc->status |= IRQ_NOAUTOEN;
+
        set_irq_chip_data(virt_irq, data);
 
        /* Catch accidental accesses to these things.  IMAP/ICLR handling
index f43b5d7553545ab8dcf7ec3900f9ba9100602591..201a6e547e4aa0d256d062d251525c30ca49ea8f 100644 (file)
@@ -478,9 +478,9 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
        return 0;
 }
 
-/* Called with kretprobe_lock held.  The value stored in the return
- * address register is actually 2 instructions before where the
- * callee will return to.  Sequences usually look something like this
+/* The value stored in the return address register is actually 2
+ * instructions before where the callee will return to.
+ * Sequences usually look something like this
  *
  *             call    some_function   <--- return register points here
  *              nop                    <--- call delay slot
@@ -512,8 +512,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
        unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
 
        INIT_HLIST_HEAD(&empty_rp);
-       spin_lock_irqsave(&kretprobe_lock, flags);
-       head = kretprobe_inst_table_head(current);
+       kretprobe_hash_lock(current, &head, &flags);
 
        /*
         * It is possible to have multiple instances associated with a given
@@ -553,7 +552,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
        regs->tnpc = orig_ret_address + 4;
 
        reset_current_kprobe();
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
+       kretprobe_hash_unlock(current, &flags);
        preempt_enable_no_resched();
 
        hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
index 63969f6102847b75ca033f500ff3e277fa9488fd..d68982330f66f7ed2da259232b5134bd3da5531d 100644 (file)
@@ -1,6 +1,6 @@
 /* ldc.c: Logical Domain Channel link-layer protocol driver.
  *
- * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
  */
 
 #include <linux/kernel.h>
@@ -23,8 +23,8 @@
 
 #define DRV_MODULE_NAME                "ldc"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.0"
-#define DRV_MODULE_RELDATE     "June 25, 2007"
+#define DRV_MODULE_VERSION     "1.1"
+#define DRV_MODULE_RELDATE     "July 22, 2008"
 
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -1235,13 +1235,9 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
        unsigned long hv_err, flags;
        int err = -EINVAL;
 
-       spin_lock_irqsave(&lp->lock, flags);
-
-       if (!name)
-               goto out_err;
-
-       if (lp->state != LDC_STATE_INIT)
-               goto out_err;
+       if (!name ||
+           (lp->state != LDC_STATE_INIT))
+               return -EINVAL;
 
        snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
        snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
@@ -1250,25 +1246,32 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
                          IRQF_SAMPLE_RANDOM | IRQF_SHARED,
                          lp->rx_irq_name, lp);
        if (err)
-               goto out_err;
+               return err;
 
        err = request_irq(lp->cfg.tx_irq, ldc_tx,
                          IRQF_SAMPLE_RANDOM | IRQF_SHARED,
                          lp->tx_irq_name, lp);
-       if (err)
-               goto out_free_rx_irq;
+       if (err) {
+               free_irq(lp->cfg.rx_irq, lp);
+               return err;
+       }
+
 
+       spin_lock_irqsave(&lp->lock, flags);
+
+       enable_irq(lp->cfg.rx_irq);
+       enable_irq(lp->cfg.tx_irq);
 
        lp->flags |= LDC_FLAG_REGISTERED_IRQS;
 
        err = -ENODEV;
        hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
        if (hv_err)
-               goto out_free_tx_irq;
+               goto out_free_irqs;
 
        hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
        if (hv_err)
-               goto out_free_tx_irq;
+               goto out_free_irqs;
 
        hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
        if (hv_err)
@@ -1304,14 +1307,11 @@ out_unmap_rx:
 out_unmap_tx:
        sun4v_ldc_tx_qconf(lp->id, 0, 0);
 
-out_free_tx_irq:
+out_free_irqs:
        lp->flags &= ~LDC_FLAG_REGISTERED_IRQS;
        free_irq(lp->cfg.tx_irq, lp);
-
-out_free_rx_irq:
        free_irq(lp->cfg.rx_irq, lp);
 
-out_err:
        spin_unlock_irqrestore(&lp->lock, flags);
 
        return err;
index 31ea752d307be15132530cbc1f7aa9ad1b97c630..8a9cd3e165b9af46818a107b62470554ce8c80a7 100644 (file)
@@ -96,7 +96,7 @@ void cpu_idle(void)
        set_thread_flag(TIF_POLLING_NRFLAG);
 
        while(1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
 
                while (!need_resched() && !cpu_is_offline(cpu))
                        sparc64_yield(cpu);
index f6c9fc92921d4405693f6f23ab2817bdee3993fa..bd578cc4856d6de60ed4e3ba54cec2874b32480c 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/audit.h>
 #include <linux/signal.h>
 #include <linux/regset.h>
+#include <linux/tracehook.h>
 #include <linux/compat.h>
 #include <linux/elf.h>
 
@@ -1049,8 +1050,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        return ret;
 }
 
-asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
+asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p)
 {
+       int ret = 0;
+
        /* do the secure computing check first */
        secure_computing(regs->u_regs[UREG_G1]);
 
@@ -1064,27 +1067,14 @@ asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
                audit_syscall_exit(result, regs->u_regs[UREG_I0]);
        }
 
-       if (!(current->ptrace & PT_PTRACED))
-               goto out;
-
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               goto out;
-
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                ? 0x80 : 0));
-
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
+       if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+               if (syscall_exit_p)
+                       tracehook_report_syscall_exit(regs, 0);
+               else
+                       ret = tracehook_report_syscall_entry(regs);
        }
 
-out:
-       if (unlikely(current->audit_context) && !syscall_exit_p)
+       if (unlikely(current->audit_context) && !syscall_exit_p && !ret)
                audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
                                     AUDIT_ARCH_SPARC :
                                     AUDIT_ARCH_SPARC64),
@@ -1093,4 +1083,6 @@ out:
                                    regs->u_regs[UREG_I1],
                                    regs->u_regs[UREG_I2],
                                    regs->u_regs[UREG_I3]);
+
+       return ret;
 }
index c6fc695fe1fe79fb7c695a3d2f51069e031c10b5..97a993c1f7f31bd62e7b310b08077b084622adff 100644 (file)
@@ -46,7 +46,7 @@ __handle_user_windows:
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
                ldx                     [%g6 + TI_FLAGS], %l0
 
-1:             andcc                   %l0, _TIF_SIGPENDING, %g0
+1:             andcc                   %l0, _TIF_DO_NOTIFY_RESUME_MASK, %g0
                be,pt                   %xcc, __handle_user_windows_continue
                 nop
                mov                     %l5, %o1
@@ -86,7 +86,7 @@ __handle_perfctrs:
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
                ldx                     [%g6 + TI_FLAGS], %l0
-1:             andcc                   %l0, _TIF_SIGPENDING, %g0
+1:             andcc                   %l0, _TIF_DO_NOTIFY_RESUME_MASK, %g0
 
                be,pt                   %xcc, __handle_perfctrs_continue
                 sethi                  %hi(TSTATE_PEF), %o0
@@ -195,7 +195,7 @@ __handle_preemption_continue:
                 andcc                  %l1, %o0, %g0
                andcc                   %l0, _TIF_NEED_RESCHED, %g0
                bne,pn                  %xcc, __handle_preemption
-                andcc                  %l0, _TIF_SIGPENDING, %g0
+                andcc                  %l0, _TIF_DO_NOTIFY_RESUME_MASK, %g0
                bne,pn                  %xcc, __handle_signal
 __handle_signal_continue:
                 ldub                   [%g6 + TI_WSAVED], %o2
index 9667e96fd5138ba3531f507d8292483e40242a80..d1b84456a9eef969d6be3013432ccf1583631971 100644 (file)
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/unistd.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
 #include <linux/bitops.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
@@ -574,6 +576,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
                 * clear the TS_RESTORE_SIGMASK flag.
                 */
                current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+
+               tracehook_signal_handler(signr, &info, &ka, regs, 0);
                return;
        }
        if (restart_syscall &&
@@ -605,4 +609,8 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long
 {
        if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs, orig_i0);
+       if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+               clear_thread_flag(TIF_NOTIFY_RESUME);
+               tracehook_notify_resume(regs);
+       }
 }
index 97cdd1bf4a100201a60a77de7f40ab37e5fb27e8..ba5b09ad6666397a953af76945205961868edb29 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/binfmts.h>
 #include <linux/compat.h>
 #include <linux/bitops.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
@@ -794,6 +795,8 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
                 * clear the TS_RESTORE_SIGMASK flag.
                 */
                current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+
+               tracehook_signal_handler(signr, &info, &ka, regs, 0);
                return;
        }
        if (restart_syscall &&
index e1f4eba2e5760191a728f472345ead476fc72ba5..39749e32dc7e74ced52506ea3e90381c41d5f048 100644 (file)
@@ -418,7 +418,7 @@ asmlinkage long sparc_pipe(struct pt_regs *regs)
        int fd[2];
        int error;
 
-       error = do_pipe(fd);
+       error = do_pipe_flags(fd, 0);
        if (error)
                goto out;
        regs->u_regs[UREG_I1] = fd[1];
index db19ed67acf67fee9df800a5f82a763b47b9635a..a2f24270ed8af9f95b95ee0f685419b621244fa2 100644 (file)
@@ -162,6 +162,8 @@ linux_syscall_trace32:
        add     %sp, PTREGS_OFF, %o0
        call    syscall_trace
         clr    %o1
+       brnz,pn %o0, 3f
+        mov    -ENOSYS, %o0
        srl     %i0, 0, %o0
        srl     %i4, 0, %o4
        srl     %i1, 0, %o1
@@ -173,6 +175,8 @@ linux_syscall_trace:
        add     %sp, PTREGS_OFF, %o0
        call    syscall_trace
         clr    %o1
+       brnz,pn %o0, 3f
+        mov    -ENOSYS, %o0
        mov     %i0, %o0
        mov     %i1, %o1
        mov     %i2, %o2
index 8b5282d433c44b6c1d04ebaf525cda6470b9a9f2..1095bf4c5100a90a3c79edf081f44861c74f083e 100644 (file)
@@ -81,7 +81,8 @@ sys_call_table32:
 /*300*/        .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
        .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
 /*310*/        .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
-       .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime
+       .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
+/*320*/        .word sys_dup3, sys_pipe2, sys_inotify_init1
 
 #endif /* CONFIG_COMPAT */
 
@@ -154,4 +155,5 @@ sys_call_table:
 /*300*/        .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
        .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
 /*310*/        .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
-       .word sys_timerfd_settime, sys_timerfd_gettime
+       .word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
+/*320*/        .word sys_dup3, sys_pipe2, sys_inotify_init1
index bedc4c159b1c8e29cee6d346619d66c389d9a5f3..a0c6a97eec6ee5883968a6fe313b0aa467fafb56 100644 (file)
@@ -884,6 +884,16 @@ static struct notifier_block sparc64_cpufreq_notifier_block = {
        .notifier_call  = sparc64_cpufreq_notifier
 };
 
+static int __init register_sparc64_cpufreq_notifier(void)
+{
+
+       cpufreq_register_notifier(&sparc64_cpufreq_notifier_block,
+                                 CPUFREQ_TRANSITION_NOTIFIER);
+       return 0;
+}
+
+core_initcall(register_sparc64_cpufreq_notifier);
+
 #endif /* CONFIG_CPU_FREQ */
 
 static int sparc64_next_event(unsigned long delta,
@@ -1050,11 +1060,6 @@ void __init time_init(void)
               sparc64_clockevent.mult, sparc64_clockevent.shift);
 
        setup_sparc64_timer();
-
-#ifdef CONFIG_CPU_FREQ
-       cpufreq_register_notifier(&sparc64_cpufreq_notifier_block,
-                                 CPUFREQ_TRANSITION_NOTIFIER);
-#endif
 }
 
 unsigned long long sched_clock(void)
index ebefd2a14375b25104030cf04d649dc9b7da72fd..f27d10369e0cdea561c78c7e3be4e0b326ffd8be 100644 (file)
@@ -175,7 +175,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                return -ENOMEM;
 
        if (flags & MAP_FIXED) {
-               if (prepare_hugepage_range(addr, len))
+               if (prepare_hugepage_range(file, addr, len))
                        return -EINVAL;
                return addr;
        }
@@ -195,7 +195,8 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                                pgoff, flags);
 }
 
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+                       unsigned long addr, unsigned long sz)
 {
        pgd_t *pgd;
        pud_t *pud;
@@ -294,6 +295,11 @@ int pmd_huge(pmd_t pmd)
        return 0;
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                             pmd_t *pmd, int write)
 {
index 84898c44dd4d81fa8dfa2f1ada68e492ad2da867..4e821b3ecb039faa71991809c0d4139354ee2a8d 100644 (file)
@@ -392,51 +392,6 @@ void __kprobes flush_icache_range(unsigned long start, unsigned long end)
        }
 }
 
-void show_mem(void)
-{
-       unsigned long total = 0, reserved = 0;
-       unsigned long shared = 0, cached = 0;
-       pg_data_t *pgdat;
-
-       printk(KERN_INFO "Mem-info:\n");
-       show_free_areas();
-       printk(KERN_INFO "Free swap:       %6ldkB\n",
-              nr_swap_pages << (PAGE_SHIFT-10));
-       for_each_online_pgdat(pgdat) {
-               unsigned long i, flags;
-
-               pgdat_resize_lock(pgdat, &flags);
-               for (i = 0; i < pgdat->node_spanned_pages; i++) {
-                       struct page *page = pgdat_page_nr(pgdat, i);
-                       total++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
-               }
-               pgdat_resize_unlock(pgdat, &flags);
-       }
-
-       printk(KERN_INFO "%lu pages of RAM\n", total);
-       printk(KERN_INFO "%lu reserved pages\n", reserved);
-       printk(KERN_INFO "%lu pages shared\n", shared);
-       printk(KERN_INFO "%lu pages swap cached\n", cached);
-
-       printk(KERN_INFO "%lu pages dirty\n",
-              global_page_state(NR_FILE_DIRTY));
-       printk(KERN_INFO "%lu pages writeback\n",
-              global_page_state(NR_WRITEBACK));
-       printk(KERN_INFO "%lu pages mapped\n",
-              global_page_state(NR_FILE_MAPPED));
-       printk(KERN_INFO "%lu pages slab\n",
-               global_page_state(NR_SLAB_RECLAIMABLE) +
-               global_page_state(NR_SLAB_UNRECLAIMABLE));
-       printk(KERN_INFO "%lu pages pagetables\n",
-              global_page_state(NR_PAGETABLE));
-}
-
 void mmu_info(struct seq_file *m)
 {
        if (tlb_type == cheetah)
@@ -788,7 +743,6 @@ int numa_cpu_lookup_table[NR_CPUS];
 cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
 
 #ifdef CONFIG_NEED_MULTIPLE_NODES
-static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
 
 struct mdesc_mblock {
        u64     base;
@@ -871,7 +825,7 @@ static void __init allocate_node_data(int nid)
        NODE_DATA(nid) = __va(paddr);
        memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
-       NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+       NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
 #endif
 
        p = NODE_DATA(nid);
index 4f775597fd5fa3bed63890a8b752f8705f265367..fba3895274f9ba9e2834cdb063b76f1cf295f5e9 100644 (file)
@@ -13,8 +13,6 @@ extern int um_request_irq(unsigned int irq, int fd, int type,
                          irq_handler_t handler,
                          unsigned long irqflags,  const char * devname,
                          void *dev_id);
-extern int init_aio_irq(int irq, char *name,
-                       irq_handler_t handler);
 
 #endif
 
index e60b31873de135ebd949723ca2cdc283deab31d3..c6c784df2673a93e7ad0d794a9e1ff38824c0791 100644 (file)
@@ -21,8 +21,6 @@ struct irq_fd {
 enum { IRQ_READ, IRQ_WRITE };
 
 extern void sigio_handler(int sig, struct uml_pt_regs *regs);
-extern int activate_fd(int irq, int fd, int type, void *dev_id);
-extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id);
 extern void free_irq_by_fd(int fd);
 extern void reactivate_fd(int fd, int irqnum);
 extern void deactivate_fd(int fd, int irqnum);
index b073f8a86bd3b38dc340c5cd6bd539e6f164ebfc..64d2c74433060601c1c5a847fde0c64849178381 100644 (file)
@@ -16,7 +16,6 @@ extern int user_thread(unsigned long stack, int flags);
 extern void new_thread_handler(void);
 extern void handle_syscall(struct uml_pt_regs *regs);
 extern int new_mm(unsigned long stack);
-extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
 extern long execute_syscall_skas(void *r);
 extern unsigned long current_stub_stack(void);
 
index 2b6fc8e0f07137bdec6f6b5fcd166f9e79d4e0d6..45c04999d670d1129acb401eb94ed26974213623 100644 (file)
@@ -34,7 +34,6 @@ extern int copy_to_user(void __user *to, const void *from, int n);
 
 extern int __do_copy_to_user(void *to, const void *from, int n,
                             void **fault_addr, jmp_buf **fault_catcher);
-extern void __do_copy(void *to, const void *from, int n);
 
 /*
  * strncpy_from_user: - Copy a NUL terminated string from userspace.
index 91587f8db34019a1045c81159f120eb1bd69c1ce..3d7aad09b171cfeca9fdc0a132ccf86f3d6a71f9 100644 (file)
@@ -102,7 +102,7 @@ void sigio_handler(int sig, struct uml_pt_regs *regs)
 
 static DEFINE_SPINLOCK(irq_lock);
 
-int activate_fd(int irq, int fd, int type, void *dev_id)
+static int activate_fd(int irq, int fd, int type, void *dev_id)
 {
        struct pollfd *tmp_pfd;
        struct irq_fd *new_fd, *irq_fd;
@@ -216,7 +216,7 @@ static int same_irq_and_dev(struct irq_fd *irq, void *d)
        return ((irq->irq == data->irq) && (irq->id == data->dev));
 }
 
-void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
+static void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
 {
        struct irq_and_dev data = ((struct irq_and_dev) { .irq  = irq,
                                                          .dev  = dev });
@@ -403,37 +403,6 @@ void __init init_IRQ(void)
        }
 }
 
-int init_aio_irq(int irq, char *name, irq_handler_t handler)
-{
-       int fds[2], err;
-
-       err = os_pipe(fds, 1, 1);
-       if (err) {
-               printk(KERN_ERR "init_aio_irq - os_pipe failed, err = %d\n",
-                      -err);
-               goto out;
-       }
-
-       err = um_request_irq(irq, fds[0], IRQ_READ, handler,
-                            IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name,
-                            (void *) (long) fds[0]);
-       if (err) {
-               printk(KERN_ERR "init_aio_irq - : um_request_irq failed, "
-                      "err = %d\n",
-                      err);
-               goto out_close;
-       }
-
-       err = fds[1];
-       goto out;
-
- out_close:
-       os_close_file(fds[0]);
-       os_close_file(fds[1]);
- out:
-       return err;
-}
-
 /*
  * IRQ stack entry and exit:
  *
index ccc02a616c22d071d8bb9a0bae0331aa4b002e80..836fc9b9470717dcbe81bc8cabe0e1261892dd7b 100644 (file)
@@ -18,7 +18,6 @@ EXPORT_SYMBOL(get_signals);
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(sys_waitpid);
 EXPORT_SYMBOL(flush_tlb_range);
-EXPORT_SYMBOL(arch_validate);
 
 EXPORT_SYMBOL(high_physmem);
 EXPORT_SYMBOL(empty_zero_page);
index b0ee64622ff70a91bc3a44d52965b402dfaa81c1..61d7e6138ff51ba8bcb10ca1ac12880aa197ccb5 100644 (file)
@@ -21,7 +21,7 @@
 /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
 unsigned long *empty_zero_page = NULL;
 /* allocated in paging_init and unchanged thereafter */
-unsigned long *empty_bad_page = NULL;
+static unsigned long *empty_bad_page = NULL;
 
 /*
  * Initialized during boot, and readonly for initializing page tables
@@ -240,37 +240,6 @@ void __init paging_init(void)
 #endif
 }
 
-struct page *arch_validate(struct page *page, gfp_t mask, int order)
-{
-       unsigned long addr, zero = 0;
-       int i;
-
- again:
-       if (page == NULL)
-               return page;
-       if (PageHighMem(page))
-               return page;
-
-       addr = (unsigned long) page_address(page);
-       for (i = 0; i < (1 << order); i++) {
-               current->thread.fault_addr = (void *) addr;
-               if (__do_copy_to_user((void __user *) addr, &zero,
-                                    sizeof(zero),
-                                    &current->thread.fault_addr,
-                                    &current->thread.fault_catcher)) {
-                       if (!(mask & __GFP_WAIT))
-                               return NULL;
-                       else break;
-               }
-               addr += PAGE_SIZE;
-       }
-
-       if (i == (1 << order))
-               return page;
-       page = alloc_pages(mask, order);
-       goto again;
-}
-
 /*
  * This can't do anything because nothing in the kernel image can be freed
  * since it's not in kernel physical memory.
@@ -295,37 +264,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 }
 #endif
 
-void show_mem(void)
-{
-       int pfn, total = 0, reserved = 0;
-       int shared = 0, cached = 0;
-       int high_mem = 0;
-       struct page *page;
-
-       printk(KERN_INFO "Mem-info:\n");
-       show_free_areas();
-       printk(KERN_INFO "Free swap:       %6ldkB\n",
-              nr_swap_pages<<(PAGE_SHIFT-10));
-       pfn = max_mapnr;
-       while (pfn-- > 0) {
-               page = pfn_to_page(pfn);
-               total++;
-               if (PageHighMem(page))
-                       high_mem++;
-               if (PageReserved(page))
-                       reserved++;
-               else if (PageSwapCache(page))
-                       cached++;
-               else if (page_count(page))
-                       shared += page_count(page) - 1;
-       }
-       printk(KERN_INFO "%d pages of RAM\n", total);
-       printk(KERN_INFO "%d pages of HIGHMEM\n", high_mem);
-       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);
-}
-
 /* Allocate and free page tables. */
 
 pgd_t *pgd_alloc(struct mm_struct *mm)
index 9757085a022097fe1804373bfd8e498bd38b4991..a1a9090254c29fdd07ad9f982a46d54dd29563ee 100644 (file)
@@ -185,7 +185,7 @@ unsigned long find_iomem(char *driver, unsigned long *len_out)
        return 0;
 }
 
-int setup_iomem(void)
+static int setup_iomem(void)
 {
        struct iomem_region *region = iomem_regions;
        unsigned long iomem_start = high_physmem + PAGE_SIZE;
index 83603cfbde819ce736a034d414361ea71c24cca7..a1c6d07cac3e46b2f3460e04729cf6a2ca203571 100644 (file)
@@ -243,7 +243,7 @@ void default_idle(void)
                if (need_resched())
                        schedule();
 
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                nsecs = disable_timer();
                idle_sleep(nsecs);
                tick_nohz_restart_sched_tick();
index 47b57b497d5529e570591e97a0f041e0d55d842e..15e8b7c4de1383b57a01587b1634171f2a0f26a5 100644 (file)
@@ -225,7 +225,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        return ret;
 }
 
-void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
+static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
                  int error_code)
 {
        struct siginfo info;
index c3e2f369c33cae2af0c682eb5a9a32a03781e056..47f04f4a3464a918850b67573e1a67a7cf5c3dec 100644 (file)
 #include "kern_util.h"
 #include "os.h"
 
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-       return (unsigned long long)jiffies_64 * (NSEC_PER_SEC / HZ);
-}
-
 void timer_handler(int sig, struct uml_pt_regs *regs)
 {
        unsigned long flags;
index f0f4b040d7c51cb1b17e44402ce5be1b03ec8f40..dd33f040c52631bb1c5b5dd1a0b659b8e9693f4b 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/string.h>
 #include "os.h"
 
-void __do_copy(void *to, const void *from, int n)
+static void __do_copy(void *to, const void *from, int n)
 {
        memcpy(to, from, n);
 }
index eb8f2e4be1929c8f731b8349bbf161afea27c751..63d299df152bb266f614d576b47e9039df531cf4 100644 (file)
@@ -530,7 +530,7 @@ static void tty_close(int master, int slave)
                printk(UM_KERN_CONT "No, enabling workaround\n");
 }
 
-void __init check_sigio(void)
+static void __init check_sigio(void)
 {
        if ((access("/dev/ptmx", R_OK) < 0) &&
            (access("/dev/ptyp0", R_OK) < 0)) {
index 5aade6027e40e71f78ae1c49d5253a2a79bcc534..6ae180703a6361bf9a8f0a7efd01b17e72e6da0f 100644 (file)
@@ -126,7 +126,7 @@ void set_sigstack(void *sig_stack, int size)
                panic("enabling signal stack failed, errno = %d\n", errno);
 }
 
-void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+static void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
 
 void handle_signal(int sig, struct sigcontext *sc)
 {
index 172ad8f72e12e71af5d2b1463a3ec3af272095ed..d6e0a2234b869267e7bfcdf15170716086a55154 100644 (file)
@@ -96,7 +96,7 @@ bad_wait:
 
 extern unsigned long current_stub_stack(void);
 
-void get_skas_faultinfo(int pid, struct faultinfo * fi)
+static void get_skas_faultinfo(int pid, struct faultinfo *fi)
 {
        int err;
 
index 106fa8641553664721bafd33ea8f9ee81d51e6e9..a27defb81884e294ddab6dca2260a3b3cc867c58 100644 (file)
@@ -245,7 +245,7 @@ int __init set_umid(char *name)
 /* Changed in make_umid, which is called during early boot */
 static int umid_setup = 0;
 
-int __init make_umid(void)
+static int __init make_umid(void)
 {
        int fd, err;
        char tmp[256];
index a74442d1376213bc5ad41bf3eb11772a743cdeaa..2c6d0d731c12c9bdcdf0e5a2521cec52ff1e7f25 100644 (file)
@@ -12,7 +12,7 @@
 #include "sysdep/ptrace.h"
 
 /* Set during early boot */
-int host_has_cmov = 1;
+static int host_has_cmov = 1;
 static jmp_buf cmov_test_return;
 
 static void cmov_sigill_test_handler(int sig)
index 62c7e564f22eb4719b8b10c54c290849be55f5f9..f058d2f82e189b0bea284da767766ed1ba20a781 100644 (file)
@@ -243,13 +243,12 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst,
        .previous
 
 .align 4
-.globl csum_partial_copy_generic_i386
-                               
+
 #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
 
 #define ARGBASE 16             
 #define FP             12
-               
+
 csum_partial_copy_generic_i386:
        subl  $4,%esp   
        pushl %edi
index a34263e6b08d3cc2cedf5e87ed0083ef05288e0b..a4846a84a7be2ddae740675dfcec28e5a6a88328 100644 (file)
@@ -14,8 +14,8 @@
 
 extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
 
-long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
-                    void **addr, int done)
+static long write_ldt_entry(struct mm_id *mm_idp, int func,
+                    struct user_desc *desc, void **addr, int done)
 {
        long res;
 
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
deleted file mode 100644 (file)
index 4379f43..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-#############################################################################
-#
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/kconfig-language.txt.
-#
-#############################################################################
-
-mainmenu "uClinux/v850 (w/o MMU) Kernel Configuration"
-
-config MMU
-               bool
-       default n
-config ZONE_DMA
-       bool
-       default y
-config RWSEM_GENERIC_SPINLOCK
-       bool
-       default y
-config RWSEM_XCHGADD_ALGORITHM
-       bool
-       default n
-config GENERIC_FIND_NEXT_BIT
-       bool
-       default y
-config GENERIC_HWEIGHT
-       bool
-       default y
-config GENERIC_CALIBRATE_DELAY
-       bool
-       default y
-
-config GENERIC_HARDIRQS
-       bool
-       default y
-
-config GENERIC_IRQ_PROBE
-       bool
-       default y
-
-config GENERIC_TIME
-       bool
-       default y
-
-config TIME_LOW_RES
-       bool
-       default y
-
-config ARCH_HAS_ILOG2_U32
-       bool
-       default n
-
-config ARCH_HAS_ILOG2_U64
-       bool
-       default n
-
-config ARCH_SUPPORTS_AOUT
-       def_bool y
-
-# Turn off some random 386 crap that can affect device config
-config ISA
-       bool
-       default n
-config ISAPNP
-       bool
-       default n
-config EISA
-       bool
-       default n
-config MCA
-       bool
-       default n
-
-
-#############################################################################
-#### v850-specific config
-
-# Define the architecture
-config V850
-       bool
-       default y
-       select HAVE_IDE
-
-menu "Processor type and features"
-
-   choice
-         prompt "Platform"
-         default GDB
-      config V850E_SIM
-            bool "GDB"
-      config RTE_CB_MA1
-            bool "RTE-V850E/MA1-CB"
-      config RTE_CB_NB85E
-            bool "RTE-V850E/NB85E-CB"
-      config RTE_CB_ME2
-            bool "RTE-V850E/ME2-CB"
-      config V850E_AS85EP1
-            bool "AS85EP1"
-      config V850E2_SIM85E2C
-            bool "sim85e2c"
-      config V850E2_SIM85E2S
-            bool "sim85e2s"
-      config V850E2_FPGA85E2C
-            bool "NA85E2C-FPGA"
-      config V850E2_ANNA
-            bool "Anna"
-   endchoice
-
-   #### V850E processor-specific config
-
-   # All CPUs currently supported use the v850e architecture
-   config V850E
-         bool
-         default y
-
-   # The RTE-V850E/MA1-CB is the only type of V850E/MA1 platform we
-   # currently support
-   config V850E_MA1
-         bool
-         depends on RTE_CB_MA1
-         default y
-   # Similarly for the RTE-V850E/NB85E-CB - V850E/TEG
-   config V850E_TEG
-         bool
-         depends on RTE_CB_NB85E
-         default y
-   # ... and the RTE-V850E/ME2-CB - V850E/ME2
-   config V850E_ME2
-         bool
-         depends on RTE_CB_ME2
-         default y
-
-
-   #### sim85e2-specific config
-
-   config V850E2_SIM85E2
-         bool
-         depends on V850E2_SIM85E2C || V850E2_SIM85E2S
-         default y
-
-
-   #### V850E2 processor-specific config
-
-   # V850E2 processors
-   config V850E2
-         bool
-         depends on V850E2_SIM85E2 || V850E2_FPGA85E2C || V850E2_ANNA
-         default y
-
-
-   #### RTE-CB platform-specific config
-
-   # Boards in the RTE-x-CB series
-   config RTE_CB
-         bool
-         depends on RTE_CB_MA1 || RTE_CB_NB85E || RTE_CB_ME2
-         default y
-
-   config RTE_CB_MULTI
-         bool
-         # RTE_CB_NB85E can either have multi ROM support or not, but
-         # other platforms (currently only RTE_CB_MA1) require it.
-         prompt "Multi monitor ROM support" if RTE_CB_NB85E
-         depends on RTE_CB_MA1 || RTE_CB_NB85E
-         default y
-
-   config RTE_CB_MULTI_DBTRAP
-         bool "Pass illegal insn trap / dbtrap to kernel"
-         depends on RTE_CB_MULTI
-         default n
-
-   config RTE_CB_MA1_KSRAM
-         bool "Kernel in SRAM (limits size of kernel)"
-         depends on RTE_CB_MA1 && RTE_CB_MULTI
-         default n
-
-   config RTE_MB_A_PCI
-         bool "Mother-A PCI support"
-         depends on RTE_CB
-         default y
-
-   # The GBUS is used to talk to the RTE-MOTHER-A board
-   config RTE_GBUS_INT
-         bool
-         depends on RTE_MB_A_PCI
-         default y
-
-   # The only PCI bus we support is on the RTE-MOTHER-A board
-   config PCI
-         bool
-         default RTE_MB_A_PCI
-
-   #### Some feature-specific configs
-
-   # Everything except for the GDB simulator uses the same interrupt controller
-   config V850E_INTC
-         bool
-         default !V850E_SIM
-
-   # Everything except for the various simulators uses the "Timer D" unit
-   config V850E_TIMER_D
-         bool
-         default !V850E_SIM && !V850E2_SIM85E2
-
-   # Cache control used on some v850e1 processors
-   config V850E_CACHE
-          bool
-         default V850E_TEG || V850E_ME2
-
-   # Cache control used on v850e2 processors; I think this should
-   # actually apply to more, but currently only the SIM85E2S uses it
-   config V850E2_CACHE
-         bool
-         default V850E2_SIM85E2S
-
-   config NO_CACHE
-         bool
-         default !V850E_CACHE && !V850E2_CACHE
-
-   # HZ depends on the platform
-   config HZ
-         int
-         default 24  if V850E_SIM || V850E2_SIM85E2
-         default 122 if V850E2_FPGA85E2C
-         default 100
-
-   #### Misc config
-
-   config ROM_KERNEL
-         bool "Kernel in ROM"
-         depends on V850E2_ANNA || V850E_AS85EP1 || RTE_CB_ME2
-
-   # Some platforms pre-zero memory, in which case the kernel doesn't need to
-   config ZERO_BSS
-         bool
-         depends on !V850E2_SIM85E2C
-         default y
-
-   # The crappy-ass zone allocator requires that the start of allocatable
-   # memory be aligned to the largest possible allocation.
-   config FORCE_MAX_ZONEORDER
-         int
-         default 8 if V850E2_SIM85E2C || V850E2_FPGA85E2C
-
-   config V850E_HIGHRES_TIMER
-         bool "High resolution timer support"
-         depends on V850E_TIMER_D
-   config TIME_BOOTUP
-         bool "Time bootup"
-         depends on V850E_HIGHRES_TIMER
-
-   config RESET_GUARD
-         bool "Reset Guard"
-
-source "mm/Kconfig"
-
-endmenu
-
-
-#############################################################################
-
-source init/Kconfig
-
-#############################################################################
-
-menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
-
-#    config PCI
-#         bool "PCI support"
-#         help
-#           Support for PCI bus.
-
-source "drivers/pci/Kconfig"
-
-source "drivers/pcmcia/Kconfig"
-
-source "drivers/pci/hotplug/Kconfig"
-
-endmenu
-
-menu "Executable file formats"
-
-source "fs/Kconfig.binfmt"
-
-endmenu
-
-source "net/Kconfig"
-
-#############################################################################
-
-source "drivers/base/Kconfig"
-
-source drivers/mtd/Kconfig
-
-source drivers/parport/Kconfig
-
-#source drivers/pnp/Kconfig
-
-source drivers/block/Kconfig
-
-#############################################################################
-
-menu "Disk device support"
-
-source "drivers/ide/Kconfig"
-
-source "drivers/scsi/Kconfig"
-
-endmenu
-
-#############################################################################
-
-
-source "drivers/md/Kconfig"
-
-source "drivers/message/fusion/Kconfig"
-
-source "drivers/ieee1394/Kconfig"
-
-source "drivers/message/i2o/Kconfig"
-
-source "drivers/net/Kconfig"
-
-source "drivers/isdn/Kconfig"
-
-#source "drivers/telephony/Kconfig"
-
-#
-# input before char - char/joystick depends on it. As does USB.
-#
-source "drivers/input/Kconfig"
-
-source "drivers/char/Kconfig"
-
-#source drivers/misc/Config.in
-source "drivers/media/Kconfig"
-
-source "fs/Kconfig"
-
-source "drivers/video/Kconfig"
-
-source "sound/Kconfig"
-
-source "drivers/usb/Kconfig"
-
-source "arch/v850/Kconfig.debug"
-
-source "security/Kconfig"
-
-source "crypto/Kconfig"
-
-source "lib/Kconfig"
-
-#############################################################################
diff --git a/arch/v850/Kconfig.debug b/arch/v850/Kconfig.debug
deleted file mode 100644 (file)
index 4acfb9c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-menu "Kernel hacking"
-
-source "lib/Kconfig.debug"
-
-config NO_KERNEL_MSG
-       bool "Suppress Kernel BUG Messages"
-       help
-         Do not output any debug BUG messages within the kernel.
-
-endmenu
diff --git a/arch/v850/Makefile b/arch/v850/Makefile
deleted file mode 100644 (file)
index 8b629df..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# arch/v850/Makefile
-#
-#  Copyright (C) 2001,02,03,05  NEC Corporation
-#  Copyright (C) 2001,02,03,05  Miles Bader <miles@gnu.org>
-#
-# This file is included by the global makefile so that you can add your own
-# architecture-specific flags and dependencies. Remember to do have actions
-# for "archclean" and "archdep" for cleaning up and making dependencies for
-# this architecture
-#
-# 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.
-#
-
-arch_dir = arch/v850
-
-KBUILD_CFLAGS += -mv850e
-# r16 is a fixed pointer to the current task
-KBUILD_CFLAGS += -ffixed-r16 -mno-prolog-function
-KBUILD_CFLAGS += -fno-builtin
-KBUILD_CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\"
-
-# By default, build a kernel that runs on the gdb v850 simulator.
-KBUILD_DEFCONFIG := sim_defconfig
-
-# This prevents the linker from consolidating the .gnu.linkonce.this_module
-# section into .text (which the v850 default linker script for -r does for
-# some reason)
-LDFLAGS_MODULE += --unique=.gnu.linkonce.this_module
-
-OBJCOPY_FLAGS_BLOB := -I binary -O elf32-little -B v850e
-
-
-head-y := $(arch_dir)/kernel/head.o $(arch_dir)/kernel/init_task.o
-core-y += $(arch_dir)/kernel/
-libs-y += $(arch_dir)/lib/
-
-
-# Deal with the initial contents of the root device
-ifdef ROOT_FS_IMAGE
-core-y += root_fs_image.o
-
-# Because the kernel build-system erases all explicit .o build rules, we
-# have to use an intermediate target to fool it into building for us.
-# This results in it being built anew each time, but that's alright.
-root_fs_image.o: root_fs_image_force
-
-root_fs_image_force: $(ROOT_FS_IMAGE)
-       $(OBJCOPY) $(OBJCOPY_FLAGS_BLOB) --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o
-endif
-
-CLEAN_FILES += root_fs_image.o
diff --git a/arch/v850/README b/arch/v850/README
deleted file mode 100644 (file)
index 12f7f7a..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-This port to the NEC V850E processor supports the following platforms:
-
-   "sim"
-       The gdb v850e simulator (CONFIG_V850E_SIM).
-
-   "rte-ma1-cb"
-       The Midas labs RTE-V850E/MA1-CB and RTE-V850E/NB85E-CB evaluation
-       boards (CONFIG_RTE_CB_MA1 and CONFIG_RTE_CB_NB85E).  This support
-       has only been tested when running with the Multi-debugger monitor
-       ROM (for the Green Hills Multi debugger).  The optional NEC
-       Solution Gear RTE-MOTHER-A motherboard is also supported, which
-       allows PCI boards to be used (CONFIG_RTE_MB_A_PCI).
-
-   "rte-me2-cb"
-       The Midas labs RTE-V850E/ME2-CB evaluation board (CONFIG_RTE_CB_ME2).
-       This has only been tested using a kernel downloaded via an ICE
-       connection using the Multi debugger.  Support for the RTE-MOTHER-A is
-       present, but hasn't been tested (unlike the other Midas labs cpu
-       boards, the RTE-V850E/ME2-CB includes an ethernet adaptor).
-
-   "as85ep1"
-       The NEC AS85EP1 V850E evaluation chip/board (CONFIG_V850E_AS85EP1).
-
-   "anna"
-       The NEC `Anna' (board/chip) implementation of the V850E2 processor
-       (CONFIG_V850E2_ANNA).
-
-   "sim85e2c", "sim85e2s"
-       The sim85e2c and sim85e2s simulators, which are verilog simulations
-       of the V850E2 NA85E2C/NA85E2S cpu cores (CONFIG_V850E2_SIM85E2C and
-       CONFIG_V850E2_SIM85E2S).
-
-   "fpga85e2c"
-       A FPGA implementation of the V850E2 NA85E2C cpu core
-       (CONFIG_V850E2_FPGA85E2C).
-
-To get a default kernel configuration for a particular platform, you can
-use a <platform>_defconfig make target (e.g., "make rte-me2-cb_defconfig");
-to see which default configurations are possible, look in the directory
-"arch/v850/configs".
-
-Porting to anything with a V850E/MA1 or MA2 processor should be simple.
-See the file <asm-v850/machdep.h> and the files it includes for an example of
-how to add platform/chip-specific support.
diff --git a/arch/v850/configs/rte-ma1-cb_defconfig b/arch/v850/configs/rte-ma1-cb_defconfig
deleted file mode 100644 (file)
index 1a5beda..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-uc0
-# Fri Sep  2 13:54:27 2005
-#
-# CONFIG_MMU is not set
-# CONFIG_UID16 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_ISA is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-CONFIG_V850=y
-
-#
-# Processor type and features
-#
-# CONFIG_V850E_SIM is not set
-CONFIG_RTE_CB_MA1=y
-# CONFIG_RTE_CB_NB85E is not set
-# CONFIG_RTE_CB_ME2 is not set
-# CONFIG_V850E_AS85EP1 is not set
-# CONFIG_V850E2_SIM85E2C is not set
-# CONFIG_V850E2_SIM85E2S is not set
-# CONFIG_V850E2_FPGA85E2C is not set
-# CONFIG_V850E2_ANNA is not set
-CONFIG_V850E=y
-CONFIG_V850E_MA1=y
-CONFIG_RTE_CB=y
-CONFIG_RTE_CB_MULTI=y
-CONFIG_RTE_CB_MULTI_DBTRAP=y
-# CONFIG_RTE_CB_MA1_KSRAM is not set
-CONFIG_RTE_MB_A_PCI=y
-CONFIG_RTE_GBUS_INT=y
-CONFIG_PCI=y
-CONFIG_V850E_INTC=y
-CONFIG_V850E_TIMER_D=y
-# CONFIG_V850E_CACHE is not set
-# CONFIG_V850E2_CACHE is not set
-CONFIG_NO_CACHE=y
-CONFIG_ZERO_BSS=y
-# CONFIG_V850E_HIGHRES_TIMER is not set
-# CONFIG_RESET_GUARD is not set
-CONFIG_LARGE_ALLOCS=y
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-# CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_BASE_SMALL=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
-# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_FLAT=y
-# CONFIG_BINFMT_ZFLAT is not set
-# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_UNIX is not set
-# 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_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 is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-# 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_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE 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
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER 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 is not set
-
-#
-# 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
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE 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_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-CONFIG_MTD_SLRAM=y
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD 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
-
-#
-# 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_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 is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD 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_ATA_OVER_ETH is not set
-
-#
-# Disk device support
-#
-
-#
-# 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
-#
-# CONFIG_FUSION 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
-
-#
-# 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_NET_VENDOR_SMC 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_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI 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 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_R8169 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_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_PPP is not set
-# CONFIG_SLIP 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 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_V850E_UART=y
-CONFIG_V850E_UART_CONSOLE=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# 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
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=y
-# CONFIG_MAGIC_ROM_PTR 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
-
-#
-# 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 is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_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_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB 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 is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET 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_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
-# CONFIG_NO_KERNEL_MSG 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_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/v850/configs/rte-me2-cb_defconfig b/arch/v850/configs/rte-me2-cb_defconfig
deleted file mode 100644 (file)
index 15e6664..0000000
+++ /dev/null
@@ -1,462 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-uc0
-# Fri Sep  2 13:47:50 2005
-#
-# CONFIG_MMU is not set
-# CONFIG_UID16 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_ISA is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-CONFIG_V850=y
-
-#
-# Processor type and features
-#
-# CONFIG_V850E_SIM is not set
-# CONFIG_RTE_CB_MA1 is not set
-# CONFIG_RTE_CB_NB85E is not set
-CONFIG_RTE_CB_ME2=y
-# CONFIG_V850E_AS85EP1 is not set
-# CONFIG_V850E2_SIM85E2C is not set
-# CONFIG_V850E2_SIM85E2S is not set
-# CONFIG_V850E2_FPGA85E2C is not set
-# CONFIG_V850E2_ANNA is not set
-CONFIG_V850E=y
-CONFIG_V850E_ME2=y
-CONFIG_RTE_CB=y
-# CONFIG_RTE_MB_A_PCI is not set
-# CONFIG_PCI is not set
-CONFIG_V850E_INTC=y
-CONFIG_V850E_TIMER_D=y
-CONFIG_V850E_CACHE=y
-# CONFIG_V850E2_CACHE is not set
-# CONFIG_NO_CACHE is not set
-# CONFIG_ROM_KERNEL is not set
-CONFIG_ZERO_BSS=y
-# CONFIG_V850E_HIGHRES_TIMER is not set
-# CONFIG_RESET_GUARD is not set
-CONFIG_LARGE_ALLOCS=y
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-# CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_BASE_SMALL=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_FLAT=y
-# CONFIG_BINFMT_ZFLAT is not set
-# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
-# CONFIG_NET is not set
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER 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 is not set
-
-#
-# 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
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE 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_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-CONFIG_MTD_SLRAM=y
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD 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
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD 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
-
-#
-# Disk device support
-#
-
-#
-# 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
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-
-#
-# 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=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# 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=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_V850E_UART is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# 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
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=y
-# CONFIG_MAGIC_ROM_PTR 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
-
-#
-# 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 is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_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
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS 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
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET 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_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
-# CONFIG_NO_KERNEL_MSG 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_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/v850/configs/sim_defconfig b/arch/v850/configs/sim_defconfig
deleted file mode 100644 (file)
index f31ba73..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-uc0
-# Fri Sep  2 13:36:43 2005
-#
-# CONFIG_MMU is not set
-# CONFIG_UID16 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_ISA is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-CONFIG_V850=y
-
-#
-# Processor type and features
-#
-CONFIG_V850E_SIM=y
-# CONFIG_RTE_CB_MA1 is not set
-# CONFIG_RTE_CB_NB85E is not set
-# CONFIG_RTE_CB_ME2 is not set
-# CONFIG_V850E_AS85EP1 is not set
-# CONFIG_V850E2_SIM85E2C is not set
-# CONFIG_V850E2_SIM85E2S is not set
-# CONFIG_V850E2_FPGA85E2C is not set
-# CONFIG_V850E2_ANNA is not set
-CONFIG_V850E=y
-# CONFIG_PCI is not set
-# CONFIG_V850E_INTC is not set
-# CONFIG_V850E_TIMER_D is not set
-# CONFIG_V850E_CACHE is not set
-# CONFIG_V850E2_CACHE is not set
-CONFIG_NO_CACHE=y
-CONFIG_ZERO_BSS=y
-# CONFIG_RESET_GUARD is not set
-CONFIG_LARGE_ALLOCS=y
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-# CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_BASE_SMALL=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_FLAT=y
-# CONFIG_BINFMT_ZFLAT is not set
-# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
-# CONFIG_NET is not set
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER 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 is not set
-
-#
-# 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
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE 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_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-CONFIG_MTD_SLRAM=y
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD 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
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD 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
-
-#
-# Disk device support
-#
-
-#
-# 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
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-
-#
-# 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=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# 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_UNIX98_PTYS is not set
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# 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
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=y
-# CONFIG_MAGIC_ROM_PTR 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
-
-#
-# 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 is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_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
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS 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
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET 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_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
-# CONFIG_NO_KERNEL_MSG 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_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
deleted file mode 100644 (file)
index da5889c..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# arch/v850/kernel/Makefile
-#
-#  Copyright (C) 2001,02,03  NEC Electronics Corporation
-#  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-
-extra-y := head.o init_task.o vmlinux.lds
-
-obj-y += intv.o entry.o process.o syscalls.o time.o setup.o \
-        signal.o irq.o mach.o ptrace.o bug.o
-obj-$(CONFIG_MODULES)          += module.o v850_ksyms.o
-# chip-specific code
-obj-$(CONFIG_V850E_MA1)                += ma.o
-obj-$(CONFIG_V850E_ME2)                += me2.o
-obj-$(CONFIG_V850E_TEG)                += teg.o
-obj-$(CONFIG_V850E_AS85EP1)    += as85ep1.o
-obj-$(CONFIG_V850E2_ANNA)      += anna.o
-# platform-specific code
-obj-$(CONFIG_V850E_SIM)                += sim.o simcons.o
-obj-$(CONFIG_V850E2_SIM85E2)   += sim85e2.o memcons.o
-obj-$(CONFIG_V850E2_FPGA85E2C) += fpga85e2c.o memcons.o
-obj-$(CONFIG_RTE_CB)           += rte_cb.o rte_cb_leds.o
-obj-$(CONFIG_RTE_CB_MA1)       += rte_ma1_cb.o
-obj-$(CONFIG_RTE_CB_ME2)       += rte_me2_cb.o
-obj-$(CONFIG_RTE_CB_NB85E)     += rte_nb85e_cb.o
-obj-$(CONFIG_RTE_CB_MULTI)     += rte_cb_multi.o
-obj-$(CONFIG_RTE_MB_A_PCI)     += rte_mb_a_pci.o
-obj-$(CONFIG_RTE_GBUS_INT)     += gbus_int.o
-# feature-specific code
-obj-$(CONFIG_V850E_INTC)       += v850e_intc.o
-obj-$(CONFIG_V850E_TIMER_D)    += v850e_timer_d.o v850e_utils.o
-obj-$(CONFIG_V850E_CACHE)      += v850e_cache.o
-obj-$(CONFIG_V850E2_CACHE)     += v850e2_cache.o
-obj-$(CONFIG_V850E_HIGHRES_TIMER) += highres_timer.o
-obj-$(CONFIG_PROC_FS)          += procfs.o
diff --git a/arch/v850/kernel/anna-rom.ld b/arch/v850/kernel/anna-rom.ld
deleted file mode 100644 (file)
index 7c54e7e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Linker script for the Midas labs Anna V850E2 evaluation board
-   (CONFIG_V850E2_ANNA), with kernel in ROM (CONFIG_ROM_KERNEL).  */
-
-MEMORY {
-       /* 8MB of flash ROM.  */
-       ROM   : ORIGIN = 0,          LENGTH = 0x00800000
-
-       /* 1MB of static RAM.  This memory is mirrored 64 times.  */
-       SRAM  : ORIGIN = SRAM_ADDR,  LENGTH = SRAM_SIZE
-       /* 64MB of DRAM.  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
-       ROMK_SECTIONS(ROM, SRAM)
-}
diff --git a/arch/v850/kernel/anna.c b/arch/v850/kernel/anna.c
deleted file mode 100644 (file)
index 5978a25..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * arch/v850/kernel/anna.c -- Anna V850E2 evaluation chip/board
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/major.h>
-#include <linux/irq.h>
-
-#include <asm/machdep.h>
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/v850e_timer_d.h>
-#include <asm/v850e_uart.h>
-
-#include "mach.h"
-
-
-/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see
-   mach_reserve_bootmem for details); use both as one big area.  */
-#define RAM_START      SRAM_ADDR
-#define RAM_END                (SDRAM_ADDR + SDRAM_SIZE)
-
-/* The bits of this port are connected to an 8-LED bar-graph.  */
-#define LEDS_PORT      0
-
-
-static void anna_led_tick (void);
-
-
-void __init mach_early_init (void)
-{
-       ANNA_ILBEN    = 0;
-
-       V850E2_CSC(0) = 0x402F;
-       V850E2_CSC(1) = 0x4000;
-       V850E2_BPC    = 0;
-       V850E2_BSC    = 0xAAAA;
-       V850E2_BEC    = 0;
-
-#if 0
-       V850E2_BHC    = 0xFFFF; /* icache all memory, dcache all */
-#else
-       V850E2_BHC    = 0;      /* cache no memory */
-#endif
-       V850E2_BCT(0) = 0xB088;
-       V850E2_BCT(1) = 0x0008;
-       V850E2_DWC(0) = 0x0027;
-       V850E2_DWC(1) = 0;
-       V850E2_BCC    = 0x0006;
-       V850E2_ASC    = 0;
-       V850E2_LBS    = 0x0089;
-       V850E2_SCR(3) = 0x21A9;
-       V850E2_RFS(3) = 0x8121;
-
-       v850e_intc_disable_irqs ();
-}
-
-void __init mach_setup (char **cmdline)
-{
-       ANNA_PORT_PM (LEDS_PORT) = 0;   /* Make all LED pins output pins.  */
-       mach_tick = anna_led_tick;
-}
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
-                                  unsigned long *ram_len)
-{
-       *ram_start = RAM_START;
-       *ram_len = RAM_END - RAM_START;
-}
-
-void __init mach_reserve_bootmem ()
-{
-       /* The space between SRAM and SDRAM is filled with duplicate
-          images of SRAM.  Prevent the kernel from using them.  */
-       reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
-                        SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE),
-                        BOOTMEM_DEFAULT);
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
-       tv->tv_sec = 0;
-       tv->tv_nsec = 0;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
-       /* Start hardware timer.  */
-       v850e_timer_d_configure (0, HZ);
-       /* Install timer interrupt handler.  */
-       setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
-       { "IRQ", 0,             NUM_MACH_IRQS,  1, 7 },
-       { "PIN", IRQ_INTP(0),   IRQ_INTP_NUM,   1, 4 },
-       { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 },
-       { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
-       { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 },
-       { "DMXER", IRQ_INTDMXER,1,              1, 2 },
-       { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 },
-       { "SR",  IRQ_INTSR(0),  IRQ_INTSR_NUM,  3, 4 },
-       { "ST",  IRQ_INTST(0),  IRQ_INTST_NUM,  3, 5 },
-       { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-void __init mach_init_irqs (void)
-{
-       v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-void machine_restart (char *__unused)
-{
-#ifdef CONFIG_RESET_GUARD
-       disable_reset_guard ();
-#endif
-       asm ("jmp r0"); /* Jump to the reset vector.  */
-}
-
-void machine_halt (void)
-{
-#ifdef CONFIG_RESET_GUARD
-       disable_reset_guard ();
-#endif
-       local_irq_disable ();   /* Ignore all interrupts.  */
-       ANNA_PORT_IO(LEDS_PORT) = 0xAA; /* Note that we halted.  */
-       for (;;)
-               asm ("halt; nop; nop; nop; nop; nop");
-}
-
-void machine_power_off (void)
-{
-       machine_halt ();
-}
-
-/* Called before configuring an on-chip UART.  */
-void anna_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
-       /* The Anna connects some general-purpose I/O pins on the CPU to
-          the RTS/CTS lines of UART 1's serial connection.  I/O pins P07
-          and P37 are RTS and CTS respectively.  */
-       if (chan == 1) {
-               ANNA_PORT_PM(0) &= ~0x80; /* P07 in output mode */
-               ANNA_PORT_PM(3) |=  0x80; /* P37 in input mode */
-       }
-}
-
-/* Minimum and maximum bounds for the moving upper LED boundary in the
-   clock tick display.  We can't use the last bit because it's used for
-   UART0's CTS output.  */
-#define MIN_MAX_POS 0
-#define MAX_MAX_POS 6
-
-/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if
-   we pick 6 and 0 as above, we get 49 cycles, which is when divided into
-   the standard 100 value for HZ, gives us an almost 1s total time.  */
-#define TICKS_PER_FRAME \
-       (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS))
-
-static void anna_led_tick ()
-{
-       static unsigned counter = 0;
-       
-       if (++counter == TICKS_PER_FRAME) {
-               static int pos = 0, max_pos = MAX_MAX_POS, dir = 1;
-
-               if (dir > 0 && pos == max_pos) {
-                       dir = -1;
-                       if (max_pos == MIN_MAX_POS)
-                               max_pos = MAX_MAX_POS;
-                       else
-                               max_pos--;
-               } else {
-                       if (dir < 0 && pos == 0)
-                               dir = 1;
-
-                       if (pos + dir <= max_pos) {
-                               /* Each bit of port 0 has a LED. */
-                               clear_bit (pos, &ANNA_PORT_IO(LEDS_PORT));
-                               pos += dir;
-                               set_bit (pos, &ANNA_PORT_IO(LEDS_PORT));
-                       }
-               }
-
-               counter = 0;
-       }
-}
diff --git a/arch/v850/kernel/anna.ld b/arch/v850/kernel/anna.ld
deleted file mode 100644 (file)
index df7f80f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Linker script for the Midas labs Anna V850E2 evaluation board
-   (CONFIG_V850E2_ANNA).  */
-
-MEMORY {
-       /* 256KB of internal memory (followed by one mirror).  */
-       iMEM0 : ORIGIN = 0,          LENGTH = 0x00040000
-       /* 256KB of internal memory (followed by one mirror).  */
-       iMEM1 : ORIGIN = 0x00040000, LENGTH = 0x00040000
-
-       /* 1MB of static RAM.  This memory is mirrored 64 times.  */
-       SRAM  : ORIGIN = SRAM_ADDR,  LENGTH = SRAM_SIZE
-       /* 64MB of DRAM.  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
-       .intv : { INTV_CONTENTS } > iMEM0
-       .sram : { RAMK_KRAM_CONTENTS } > SRAM
-       .root : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/as85ep1-rom.ld b/arch/v850/kernel/as85ep1-rom.ld
deleted file mode 100644 (file)
index fe2a9a3..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Linker script for the NEC AS85EP1 V850E evaluation board
-   (CONFIG_V850E_AS85EP1), with kernel in ROM (CONFIG_ROM_KERNEL).  */
-
-MEMORY {
-       /* 4MB of flash ROM.  */
-       ROM   : ORIGIN = 0,          LENGTH = 0x00400000
-
-       /* 1MB of static RAM.  */
-       SRAM  : ORIGIN = SRAM_ADDR,  LENGTH = SRAM_SIZE
-
-       /* About 58MB of DRAM.  This can actually be at one of two
-          positions, determined by jumper JP3; we have to use the first
-          position because the second is partially out of processor
-          instruction addressing range (though in the second position
-          there's actually 64MB available).  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
-       ROMK_SECTIONS(ROM, SRAM)
-}
diff --git a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c
deleted file mode 100644 (file)
index b525ecf..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/major.h>
-#include <linux/irq.h>
-
-#include <asm/machdep.h>
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/v850e_timer_d.h>
-#include <asm/v850e_uart.h>
-
-#include "mach.h"
-
-
-/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see
-   mach_reserve_bootmem for details); use both as one big area.  */
-#define RAM_START      SRAM_ADDR
-#define RAM_END                (SDRAM_ADDR + SDRAM_SIZE)
-
-/* The bits of this port are connected to an 8-LED bar-graph.  */
-#define LEDS_PORT      4
-
-
-static void as85ep1_led_tick (void);
-
-extern char _intv_copy_src_start, _intv_copy_src_end;
-extern char _intv_copy_dst_start;
-
-
-void __init mach_early_init (void)
-{
-#ifndef CONFIG_ROM_KERNEL
-       const u32 *src;
-       register u32 *dst asm ("ep");
-#endif
-
-       AS85EP1_CSC(0) = 0x0403;
-       AS85EP1_BCT(0) = 0xB8B8;
-       AS85EP1_DWC(0) = 0x0104;
-       AS85EP1_BCC    = 0x0012;
-       AS85EP1_ASC    = 0;
-       AS85EP1_LBS    = 0x00A9;
-
-       AS85EP1_PORT_PMC(6)  = 0xFF; /* valid A0,A1,A20-A25 */
-       AS85EP1_PORT_PMC(7)  = 0x0E; /* valid CS1-CS3       */
-       AS85EP1_PORT_PMC(9)  = 0xFF; /* valid D16-D23       */
-       AS85EP1_PORT_PMC(10) = 0xFF; /* valid D24-D31       */
-
-       AS85EP1_RFS(1) = 0x800c;
-       AS85EP1_RFS(3) = 0x800c;
-       AS85EP1_SCR(1) = 0x20A9;
-       AS85EP1_SCR(3) = 0x20A9;
-
-#ifndef CONFIG_ROM_KERNEL
-       /* The early chip we have is buggy, and writing the interrupt
-          vectors into low RAM may screw up, so for non-ROM kernels, we
-          only rely on the reset vector being downloaded, and copy the
-          rest of the interrupt vectors into place here.  The specific bug
-          is that writing address N, where (N & 0x10) == 0x10, will _also_
-          write to address (N - 0x10).  We avoid this (effectively) by
-          writing in 16-byte chunks backwards from the end.  */
-
-       AS85EP1_IRAMM = 0x3;    /* "write-mode" for the internal instruction memory */
-
-       src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF);
-       dst = (u32 *)&_intv_copy_dst_start
-               + (src - (u32 *)&_intv_copy_src_start);
-       do {
-               u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
-               dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
-               dst -= 4;
-               src -= 4;
-       } while (src > (u32 *)&_intv_copy_src_start);
-
-       AS85EP1_IRAMM = 0x0;    /* "read-mode" for the internal instruction memory */
-#endif /* !CONFIG_ROM_KERNEL */
-
-       v850e_intc_disable_irqs ();
-}
-
-void __init mach_setup (char **cmdline)
-{
-       AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */
-       AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins.  */
-       mach_tick = as85ep1_led_tick;
-}
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
-                                  unsigned long *ram_len)
-{
-       *ram_start = RAM_START;
-       *ram_len = RAM_END - RAM_START;
-}
-
-/* Convenience macros.  */
-#define SRAM_END       (SRAM_ADDR + SRAM_SIZE)
-#define SDRAM_END      (SDRAM_ADDR + SDRAM_SIZE)
-
-void __init mach_reserve_bootmem ()
-{
-       if (SDRAM_ADDR < RAM_END && SDRAM_ADDR > RAM_START)
-               /* We can't use the space between SRAM and SDRAM, so
-                  prevent the kernel from trying.  */
-               reserve_bootmem(SRAM_END, SDRAM_ADDR - SRAM_END,
-                               BOOTMEM_DEFAULT);
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
-       tv->tv_sec = 0;
-       tv->tv_nsec = 0;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
-       /* Start hardware timer.  */
-       v850e_timer_d_configure (0, HZ);
-       /* Install timer interrupt handler.  */
-       setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
-       { "IRQ", 0,             NUM_MACH_IRQS,  1, 7 },
-       { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 },
-       { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
-       { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 },
-       { "SR",  IRQ_INTSR(0),  IRQ_INTSR_NUM,  3, 4 },
-       { "ST",  IRQ_INTST(0),  IRQ_INTST_NUM,  3, 5 },
-       { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-void __init mach_init_irqs (void)
-{
-       v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-void machine_restart (char *__unused)
-{
-#ifdef CONFIG_RESET_GUARD
-       disable_reset_guard ();
-#endif
-       asm ("jmp r0"); /* Jump to the reset vector.  */
-}
-
-void machine_halt (void)
-{
-#ifdef CONFIG_RESET_GUARD
-       disable_reset_guard ();
-#endif
-       local_irq_disable ();   /* Ignore all interrupts.  */
-       AS85EP1_PORT_IO (LEDS_PORT) = 0xAA;     /* Note that we halted.  */
-       for (;;)
-               asm ("halt; nop; nop; nop; nop; nop");
-}
-
-void machine_power_off (void)
-{
-       machine_halt ();
-}
-
-/* Called before configuring an on-chip UART.  */
-void as85ep1_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
-       /* Make the shared uart/port pins be uart pins.  */
-       AS85EP1_PORT_PMC(3) |= (0x5 << chan);
-
-       /* The AS85EP1 connects some general-purpose I/O pins on the CPU to
-          the RTS/CTS lines of UART 1's serial connection.  I/O pins P53
-          and P54 are RTS and CTS respectively.  */
-       if (chan == 1) {
-               /* Put P53 & P54 in I/O port mode.  */
-               AS85EP1_PORT_PMC(5) &= ~0x18;
-               /* Make P53 an output, and P54 an input.  */
-               AS85EP1_PORT_PM(5) |=  0x10;
-       }
-}
-
-/* Minimum and maximum bounds for the moving upper LED boundary in the
-   clock tick display.  */
-#define MIN_MAX_POS 0
-#define MAX_MAX_POS 7
-
-/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if
-   we pick 6 and 0 as above, we get 49 cycles, which is when divided into
-   the standard 100 value for HZ, gives us an almost 1s total time.  */
-#define TICKS_PER_FRAME \
-       (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS))
-
-static void as85ep1_led_tick ()
-{
-       static unsigned counter = 0;
-       
-       if (++counter == TICKS_PER_FRAME) {
-               static int pos = 0, max_pos = MAX_MAX_POS, dir = 1;
-
-               if (dir > 0 && pos == max_pos) {
-                       dir = -1;
-                       if (max_pos == MIN_MAX_POS)
-                               max_pos = MAX_MAX_POS;
-                       else
-                               max_pos--;
-               } else {
-                       if (dir < 0 && pos == 0)
-                               dir = 1;
-
-                       if (pos + dir <= max_pos) {
-                               /* Each bit of port 0 has a LED. */
-                               set_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
-                               pos += dir;
-                               clear_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
-                       }
-               }
-
-               counter = 0;
-       }
-}
diff --git a/arch/v850/kernel/as85ep1.ld b/arch/v850/kernel/as85ep1.ld
deleted file mode 100644 (file)
index ef2c439..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Linker script for the NEC AS85EP1 V850E evaluation board
-   (CONFIG_V850E_AS85EP1).  */
-
-MEMORY {
-       /* 1MB of internal instruction memory. */
-       iMEM0 : ORIGIN = 0,          LENGTH = 0x00100000
-
-       /* 1MB of static RAM.  */
-       SRAM  : ORIGIN = SRAM_ADDR,  LENGTH = SRAM_SIZE
-
-       /* About 58MB of DRAM.  This can actually be at one of two
-          positions, determined by jump JP3; we have to use the first
-          position because the second is partially out of processor
-          instruction addressing range (though in the second position
-          there's actually 64MB available).  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
-       .resetv : {
-               __intv_start = . ;
-                       *(.intv.reset)  /* Reset vector */
-       } > iMEM0
-
-       .sram : {
-               RAMK_KRAM_CONTENTS
-
-               /* We stick most of the interrupt vectors here; they'll be
-                  copied into the proper location by the early init code (we
-                  can't put them directly in the right place because of
-                  hardware bugs).  The vectors shouldn't need to be
-                  relocated, so we don't have to use `> ...  AT> ...' to
-                  split the load/vm addresses (and we can't because of
-                  problems with the loader).  */
-               . = ALIGN (0x10) ;
-               __intv_copy_src_start = . ;
-                       *(.intv.common) /* Vectors common to all v850e proc. */
-                       *(.intv.mach)   /* Machine-specific int. vectors.  */
-               . = ALIGN (0x10) ;
-               __intv_copy_src_end = . ;
-       } > SRAM
-
-       /* Where we end up putting the vectors.  */
-       __intv_copy_dst_start = 0x10 ;
-       __intv_copy_dst_end = __intv_copy_dst_start + (__intv_copy_src_end - __intv_copy_src_start) ;
-       __intv_end = __intv_copy_dst_end ;
-
-       .root : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/asm-offsets.c b/arch/v850/kernel/asm-offsets.c
deleted file mode 100644 (file)
index 581e698..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This program is used to generate definitions needed by
- * assembly language modules.
- *
- * We use the technique used in the OSF Mach kernel code:
- * generate asm statements containing #defines,
- * compile this file to assembler, and then extract the
- * #defines from the assembly-language output.
- */
-
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/ptrace.h>
-#include <linux/hardirq.h>
-#include <linux/kbuild.h>
-
-#include <asm/irq.h>
-#include <asm/errno.h>
-
-int main (void)
-{
-       /* offsets into the task struct */
-       DEFINE (TASK_STATE, offsetof (struct task_struct, state));
-       DEFINE (TASK_FLAGS, offsetof (struct task_struct, flags));
-       DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace));
-       DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked));
-       DEFINE (TASK_THREAD, offsetof (struct task_struct, thread));
-       DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, stack));
-       DEFINE (TASK_MM, offsetof (struct task_struct, mm));
-       DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
-       DEFINE (TASK_PID, offsetof (struct task_struct, pid));
-
-       /* offsets into the kernel_stat struct */
-       DEFINE (STAT_IRQ, offsetof (struct kernel_stat, irqs));
-
-
-       /* signal defines */
-       DEFINE (SIGSEGV, SIGSEGV);
-       DEFINE (SEGV_MAPERR, SEGV_MAPERR);
-       DEFINE (SIGTRAP, SIGTRAP);
-       DEFINE (SIGCHLD, SIGCHLD);
-       DEFINE (SIGILL, SIGILL);
-       DEFINE (TRAP_TRACE, TRAP_TRACE);
-
-       /* ptrace flag bits */
-       DEFINE (PT_PTRACED, PT_PTRACED);
-       DEFINE (PT_DTRACE, PT_DTRACE);
-
-       /* error values */
-       DEFINE (ENOSYS, ENOSYS);
-
-       /* clone flag bits */
-       DEFINE (CLONE_VFORK, CLONE_VFORK);
-       DEFINE (CLONE_VM, CLONE_VM);
-
-       return 0;
-}
diff --git a/arch/v850/kernel/bug.c b/arch/v850/kernel/bug.c
deleted file mode 100644 (file)
index c78cf75..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * arch/v850/kernel/bug.c -- Bug reporting functions
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/reboot.h>
-#include <linux/sched.h>
-#include <linux/module.h>
-
-#include <asm/errno.h>
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/current.h>
-
-/* We should use __builtin_return_address, but it doesn't work in gcc-2.90
-   (which is currently our standard compiler on the v850).  */
-#define ret_addr() ({ register u32 lp asm ("lp"); lp; })
-#define stack_addr() ({ register u32 sp asm ("sp"); sp; })
-
-void __bug ()
-{
-       printk (KERN_CRIT "kernel BUG at PC 0x%x (SP ~0x%x)!\n",
-               ret_addr() - 4, /* - 4 for `jarl' */
-               stack_addr());
-       machine_halt ();
-}
-
-int bad_trap (int trap_num, struct pt_regs *regs)
-{
-       printk (KERN_CRIT
-               "unimplemented trap %d called at 0x%08lx, pid %d!\n",
-               trap_num, regs->pc, current->pid);
-       return -ENOSYS;
-}
-
-#ifdef CONFIG_RESET_GUARD
-void unexpected_reset (unsigned long ret_addr, unsigned long kmode,
-                      struct task_struct *task, unsigned long sp)
-{
-       printk (KERN_CRIT
-               "unexpected reset in %s mode, pid %d"
-               " (ret_addr = 0x%lx, sp = 0x%lx)\n",
-               kmode ? "kernel" : "user",
-               task ? task->pid : -1,
-               ret_addr, sp);
-
-       machine_halt ();
-}
-#endif /* CONFIG_RESET_GUARD */
-
-\f
-
-struct spec_reg_name {
-       const char *name;
-       int gpr;
-};
-
-struct spec_reg_name spec_reg_names[] = {
-       { "sp", GPR_SP },
-       { "gp", GPR_GP },
-       { "tp", GPR_TP },
-       { "ep", GPR_EP },
-       { "lp", GPR_LP },
-       { 0, 0 }
-};
-
-void show_regs (struct pt_regs *regs)
-{
-       int gpr_base, gpr_offs;
-
-       printk ("     pc 0x%08lx    psw 0x%08lx                       kernel_mode %d\n",
-               regs->pc, regs->psw, regs->kernel_mode);
-       printk ("   ctpc 0x%08lx  ctpsw 0x%08lx   ctbp 0x%08lx\n",
-               regs->ctpc, regs->ctpsw, regs->ctbp);
-
-       for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) {
-               for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) {
-                       int gpr = gpr_base + gpr_offs;
-                       long val = regs->gpr[gpr];
-                       struct spec_reg_name *srn;
-
-                       for (srn = spec_reg_names; srn->name; srn++)
-                               if (srn->gpr == gpr)
-                                       break;
-
-                       if (srn->name)
-                               printk ("%7s 0x%08lx", srn->name, val);
-                       else
-                               printk ("    r%02d 0x%08lx", gpr, val);
-               }
-
-               printk ("\n");
-       }
-}
-
-/*
- * TASK is a pointer to the task whose backtrace we want to see (or NULL
- * for current task), SP is the stack pointer of the first frame that
- * should be shown in the back trace (or NULL if the entire call-chain of
- * the task should be shown).
- */
-void show_stack (struct task_struct *task, unsigned long *sp)
-{
-       unsigned long addr, end;
-
-       if (sp)
-               addr = (unsigned long)sp;
-       else if (task)
-               addr = task_sp (task);
-       else
-               addr = stack_addr ();
-
-       addr = addr & ~3;
-       end = (addr + THREAD_SIZE - 1) & THREAD_MASK;
-
-       while (addr < end) {
-               printk ("%8lX: ", addr);
-               while (addr < end) {
-                       printk (" %8lX", *(unsigned long *)addr);
-                       addr += sizeof (unsigned long);
-                       if (! (addr & 0xF))
-                               break;
-               }
-               printk ("\n");
-       }
-}
-
-void dump_stack ()
-{
-       show_stack (0, 0);
-}
-
-EXPORT_SYMBOL(dump_stack);
diff --git a/arch/v850/kernel/entry.S b/arch/v850/kernel/entry.S
deleted file mode 100644 (file)
index e4327a8..0000000
+++ /dev/null
@@ -1,1121 +0,0 @@
-/*
- * arch/v850/kernel/entry.S -- Low-level system-call handling, trap handlers,
- *     and context-switching
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/sys.h>
-
-#include <asm/entry.h>
-#include <asm/current.h>
-#include <asm/thread_info.h>
-#include <asm/clinkage.h>
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <asm/errno.h>
-
-#include <asm/asm-offsets.h>
-
-
-/* Make a slightly more convenient alias for C_SYMBOL_NAME.  */
-#define CSYM   C_SYMBOL_NAME
-
-
-/* The offset of the struct pt_regs in a state-save-frame on the stack.  */
-#define PTO    STATE_SAVE_PT_OFFSET
-
-
-/* Save argument registers to the state-save-frame pointed to by EP.  */
-#define SAVE_ARG_REGS                                                        \
-       sst.w   r6, PTO+PT_GPR(6)[ep];                                        \
-       sst.w   r7, PTO+PT_GPR(7)[ep];                                        \
-       sst.w   r8, PTO+PT_GPR(8)[ep];                                        \
-       sst.w   r9, PTO+PT_GPR(9)[ep]
-/* Restore argument registers from the state-save-frame pointed to by EP.  */
-#define RESTORE_ARG_REGS                                                     \
-       sld.w   PTO+PT_GPR(6)[ep], r6;                                        \
-       sld.w   PTO+PT_GPR(7)[ep], r7;                                        \
-       sld.w   PTO+PT_GPR(8)[ep], r8;                                        \
-       sld.w   PTO+PT_GPR(9)[ep], r9
-
-/* Save value return registers to the state-save-frame pointed to by EP.  */
-#define SAVE_RVAL_REGS                                                       \
-       sst.w   r10, PTO+PT_GPR(10)[ep];                                      \
-       sst.w   r11, PTO+PT_GPR(11)[ep]
-/* Restore value return registers from the state-save-frame pointed to by EP.  */
-#define RESTORE_RVAL_REGS                                                    \
-       sld.w   PTO+PT_GPR(10)[ep], r10;                                      \
-       sld.w   PTO+PT_GPR(11)[ep], r11
-
-
-#define SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS                                 \
-       sst.w   r1, PTO+PT_GPR(1)[ep];                                        \
-       sst.w   r5, PTO+PT_GPR(5)[ep]
-#define SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL                                  \
-       sst.w   r12, PTO+PT_GPR(12)[ep];                                      \
-       sst.w   r13, PTO+PT_GPR(13)[ep];                                      \
-       sst.w   r14, PTO+PT_GPR(14)[ep];                                      \
-       sst.w   r15, PTO+PT_GPR(15)[ep];                                      \
-       sst.w   r16, PTO+PT_GPR(16)[ep];                                      \
-       sst.w   r17, PTO+PT_GPR(17)[ep];                                      \
-       sst.w   r18, PTO+PT_GPR(18)[ep];                                      \
-       sst.w   r19, PTO+PT_GPR(19)[ep]
-#define RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS                                      \
-       sld.w   PTO+PT_GPR(1)[ep], r1;                                        \
-       sld.w   PTO+PT_GPR(5)[ep], r5
-#define RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL                               \
-       sld.w   PTO+PT_GPR(12)[ep], r12;                                      \
-       sld.w   PTO+PT_GPR(13)[ep], r13;                                      \
-       sld.w   PTO+PT_GPR(14)[ep], r14;                                      \
-       sld.w   PTO+PT_GPR(15)[ep], r15;                                      \
-       sld.w   PTO+PT_GPR(16)[ep], r16;                                      \
-       sld.w   PTO+PT_GPR(17)[ep], r17;                                      \
-       sld.w   PTO+PT_GPR(18)[ep], r18;                                      \
-       sld.w   PTO+PT_GPR(19)[ep], r19
-
-/* Save `call clobbered' registers to the state-save-frame pointed to by EP.  */
-#define SAVE_CALL_CLOBBERED_REGS                                             \
-       SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS;                                 \
-       SAVE_ARG_REGS;                                                        \
-       SAVE_RVAL_REGS;                                                       \
-       SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
-/* Restore `call clobbered' registers from the state-save-frame pointed to
-   by EP.  */
-#define RESTORE_CALL_CLOBBERED_REGS                                          \
-       RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS;                              \
-       RESTORE_ARG_REGS;                                                     \
-       RESTORE_RVAL_REGS;                                                    \
-       RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
-
-/* Save `call clobbered' registers except for the return-value registers
-   to the state-save-frame pointed to by EP.  */
-#define SAVE_CALL_CLOBBERED_REGS_NO_RVAL                                     \
-       SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS;                                 \
-       SAVE_ARG_REGS;                                                        \
-       SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
-/* Restore `call clobbered' registers except for the return-value registers
-   from the state-save-frame pointed to by EP.  */
-#define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL                                  \
-       RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS;                              \
-       RESTORE_ARG_REGS;                                                     \
-       RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
-
-/* Save `call saved' registers to the state-save-frame pointed to by EP.  */
-#define SAVE_CALL_SAVED_REGS                                                 \
-       sst.w   r2, PTO+PT_GPR(2)[ep];                                        \
-       sst.w   r20, PTO+PT_GPR(20)[ep];                                      \
-       sst.w   r21, PTO+PT_GPR(21)[ep];                                      \
-       sst.w   r22, PTO+PT_GPR(22)[ep];                                      \
-       sst.w   r23, PTO+PT_GPR(23)[ep];                                      \
-       sst.w   r24, PTO+PT_GPR(24)[ep];                                      \
-       sst.w   r25, PTO+PT_GPR(25)[ep];                                      \
-       sst.w   r26, PTO+PT_GPR(26)[ep];                                      \
-       sst.w   r27, PTO+PT_GPR(27)[ep];                                      \
-       sst.w   r28, PTO+PT_GPR(28)[ep];                                      \
-       sst.w   r29, PTO+PT_GPR(29)[ep]
-/* Restore `call saved' registers from the state-save-frame pointed to by EP.  */
-#define RESTORE_CALL_SAVED_REGS                                                      \
-       sld.w   PTO+PT_GPR(2)[ep], r2;                                        \
-       sld.w   PTO+PT_GPR(20)[ep], r20;                                      \
-       sld.w   PTO+PT_GPR(21)[ep], r21;                                      \
-       sld.w   PTO+PT_GPR(22)[ep], r22;                                      \
-       sld.w   PTO+PT_GPR(23)[ep], r23;                                      \
-       sld.w   PTO+PT_GPR(24)[ep], r24;                                      \
-       sld.w   PTO+PT_GPR(25)[ep], r25;                                      \
-       sld.w   PTO+PT_GPR(26)[ep], r26;                                      \
-       sld.w   PTO+PT_GPR(27)[ep], r27;                                      \
-       sld.w   PTO+PT_GPR(28)[ep], r28;                                      \
-       sld.w   PTO+PT_GPR(29)[ep], r29
-
-
-/* Save the PC stored in the special register SAVEREG to the state-save-frame
-   pointed to by EP.  r19 is clobbered.  */
-#define SAVE_PC(savereg)                                                     \
-       stsr    SR_ ## savereg, r19;                                          \
-       sst.w   r19, PTO+PT_PC[ep]
-/* Restore the PC from the state-save-frame pointed to by EP, to the special
-   register SAVEREG.  LP is clobbered (it is used as a scratch register
-   because the POP_STATE macro restores it, and this macro is usually used
-   inside POP_STATE).  */
-#define RESTORE_PC(savereg)                                                  \
-       sld.w   PTO+PT_PC[ep], lp;                                            \
-       ldsr    lp, SR_ ## savereg
-/* Save the PSW register stored in the special register SAVREG to the
-   state-save-frame pointed to by EP.  r19 is clobbered.  */
-#define SAVE_PSW(savereg)                                                    \
-       stsr    SR_ ## savereg, r19;                                          \
-       sst.w   r19, PTO+PT_PSW[ep]
-/* Restore the PSW register from the state-save-frame pointed to by EP, to
-   the special register SAVEREG.  LP is clobbered (it is used as a scratch
-   register because the POP_STATE macro restores it, and this macro is
-   usually used inside POP_STATE).  */
-#define RESTORE_PSW(savereg)                                                 \
-       sld.w   PTO+PT_PSW[ep], lp;                                           \
-       ldsr    lp, SR_ ## savereg
-
-/* Save CTPC/CTPSW/CTBP registers to the state-save-frame pointed to by REG.
-   r19 is clobbered.  */
-#define SAVE_CT_REGS                                                         \
-       stsr    SR_CTPC, r19;                                                 \
-       sst.w   r19, PTO+PT_CTPC[ep];                                         \
-       stsr    SR_CTPSW, r19;                                                \
-       sst.w   r19, PTO+PT_CTPSW[ep];                                        \
-       stsr    SR_CTBP, r19;                                                 \
-       sst.w   r19, PTO+PT_CTBP[ep]
-/* Restore CTPC/CTPSW/CTBP registers from the state-save-frame pointed to by EP.
-   LP is clobbered (it is used as a scratch register because the POP_STATE
-   macro restores it, and this macro is usually used inside POP_STATE).  */
-#define RESTORE_CT_REGS                                                              \
-       sld.w   PTO+PT_CTPC[ep], lp;                                          \
-       ldsr    lp, SR_CTPC;                                                  \
-       sld.w   PTO+PT_CTPSW[ep], lp;                                         \
-       ldsr    lp, SR_CTPSW;                                                 \
-       sld.w   PTO+PT_CTBP[ep], lp;                                          \
-       ldsr    lp, SR_CTBP
-
-
-/* Push register state, except for the stack pointer, on the stack in the
-   form of a state-save-frame (plus some extra padding), in preparation for
-   a system call.  This macro makes sure that the EP, GP, and LP
-   registers are saved, and TYPE identifies the set of extra registers to
-   be saved as well.  Also copies (the new value of) SP to EP.  */
-#define PUSH_STATE(type)                                                     \
-       addi    -STATE_SAVE_SIZE, sp, sp; /* Make room on the stack.  */      \
-       st.w    ep, PTO+PT_GPR(GPR_EP)[sp];                                   \
-       mov     sp, ep;                                                       \
-       sst.w   gp, PTO+PT_GPR(GPR_GP)[ep];                                   \
-       sst.w   lp, PTO+PT_GPR(GPR_LP)[ep];                                   \
-       type ## _STATE_SAVER
-/* Pop a register state pushed by PUSH_STATE, except for the stack pointer,
-   from the stack.  */
-#define POP_STATE(type)                                                              \
-       mov     sp, ep;                                                       \
-       type ## _STATE_RESTORER;                                              \
-       sld.w   PTO+PT_GPR(GPR_GP)[ep], gp;                                   \
-       sld.w   PTO+PT_GPR(GPR_LP)[ep], lp;                                   \
-       sld.w   PTO+PT_GPR(GPR_EP)[ep], ep;                                   \
-       addi    STATE_SAVE_SIZE, sp, sp /* Clean up our stack space.  */
-
-
-/* Switch to the kernel stack if necessary, and push register state on the
-   stack in the form of a state-save-frame.  Also load the current task
-   pointer if switching from user mode.  The stack-pointer (r3) should have
-   already been saved to the memory location SP_SAVE_LOC (the reason for
-   this is that the interrupt vectors may be beyond a 22-bit signed offset
-   jump from the actual interrupt handler, and this allows them to save the
-   stack-pointer and use that register to do an indirect jump).  This macro
-   makes sure that `special' registers, system registers, and the stack
-   pointer are saved; TYPE identifies the set of extra registers to be
-   saved as well.  SYSCALL_NUM is the register in which the system-call
-   number this state is for is stored (r0 if this isn't a system call).
-   Interrupts should already be disabled when calling this.  */
-#define SAVE_STATE(type, syscall_num, sp_save_loc)                           \
-       tst1    0, KM;                  /* See if already in kernel mode.  */ \
-       bz      1f;                                                           \
-       ld.w    sp_save_loc, sp;        /* ... yes, use saved SP.  */         \
-       br      2f;                                                           \
-1:     ld.w    KSP, sp;                /* ... no, switch to kernel stack. */ \
-2:     PUSH_STATE(type);                                                     \
-       ld.b    KM, r19;                /* Remember old kernel-mode.  */      \
-       sst.w   r19, PTO+PT_KERNEL_MODE[ep];                                  \
-       ld.w    sp_save_loc, r19;       /* Remember old SP.  */               \
-       sst.w   r19, PTO+PT_GPR(GPR_SP)[ep];                                  \
-       mov     1, r19;                 /* Now definitely in kernel-mode. */  \
-       st.b    r19, KM;                                                      \
-       GET_CURRENT_TASK(CURRENT_TASK); /* Fetch the current task pointer. */ \
-       /* Save away the syscall number.  */                                  \
-       sst.w   syscall_num, PTO+PT_CUR_SYSCALL[ep]
-
-
-/* Save register state not normally saved by PUSH_STATE for TYPE, to the
-   state-save-frame on the stack; also copies SP to EP.  r19 may be trashed. */
-#define SAVE_EXTRA_STATE(type)                                               \
-       mov     sp, ep;                                                       \
-       type ## _EXTRA_STATE_SAVER
-/* Restore register state not normally restored by POP_STATE for TYPE,
-   from the state-save-frame on the stack; also copies SP to EP.
-   r19 may be trashed.  */
-#define RESTORE_EXTRA_STATE(type)                                            \
-       mov     sp, ep;                                                       \
-       type ## _EXTRA_STATE_RESTORER
-
-/* Save any call-clobbered registers not normally saved by PUSH_STATE for
-   TYPE, to the state-save-frame on the stack.
-   EP may be trashed, but is not guaranteed to contain a copy of SP
-   (unlike after most SAVE_... macros).  r19 may be trashed.  */
-#define SAVE_EXTRA_STATE_FOR_SCHEDULE(type)                                  \
-       type ## _SCHEDULE_EXTRA_STATE_SAVER
-/* Restore any call-clobbered registers not normally restored by
-   POP_STATE for TYPE, to the state-save-frame on the stack.
-   EP may be trashed, but is not guaranteed to contain a copy of SP
-   (unlike after most RESTORE_... macros).  r19 may be trashed.  */
-#define RESTORE_EXTRA_STATE_FOR_SCHEDULE(type)                               \
-       type ## _SCHEDULE_EXTRA_STATE_RESTORER
-
-
-/* These are extra_state_saver/restorer values for a user trap.  Note
-   that we save the argument registers so that restarted syscalls will
-   function properly (otherwise it wouldn't be necessary), and we must
-   _not_ restore the return-value registers (so that traps can return a
-   value!), but call-clobbered registers are not saved at all, as the
-   caller of the syscall function should have saved them.  */
-
-#define TRAP_RET reti
-/* Traps don't save call-clobbered registers (but do still save arg regs).
-   We preserve PSw to keep long-term state, namely interrupt status (for traps
-   from kernel-mode), and the single-step flag (for user traps).  */
-#define TRAP_STATE_SAVER                                                     \
-       SAVE_ARG_REGS;                                                        \
-       SAVE_PC(EIPC);                                                        \
-       SAVE_PSW(EIPSW)
-/* When traps return, they just leave call-clobbered registers (except for arg
-   regs) with whatever value they have from the kernel.  Traps don't preserve
-   the PSW, but we zero EIPSW to ensure it doesn't contain anything dangerous
-   (in particular, the single-step flag).  */
-#define TRAP_STATE_RESTORER                                                  \
-       RESTORE_ARG_REGS;                                                     \
-       RESTORE_PC(EIPC);                                                     \
-       RESTORE_PSW(EIPSW)
-/* Save registers not normally saved by traps.  We need to save r12, even
-   though it's nominally call-clobbered, because it's used when restarting
-   a system call (the signal-handling path uses SAVE_EXTRA_STATE, and
-   expects r12 to be restored when the trap returns).  */
-#define TRAP_EXTRA_STATE_SAVER                                               \
-       SAVE_RVAL_REGS;                                                       \
-       sst.w   r12, PTO+PT_GPR(12)[ep];                                      \
-       SAVE_CALL_SAVED_REGS;                                                 \
-       SAVE_CT_REGS
-#define TRAP_EXTRA_STATE_RESTORER                                            \
-       RESTORE_RVAL_REGS;                                                    \
-       sld.w   PTO+PT_GPR(12)[ep], r12;                                      \
-       RESTORE_CALL_SAVED_REGS;                                              \
-       RESTORE_CT_REGS
-/* Save registers prior to calling scheduler (just before trap returns).
-   We have to save the return-value registers to preserve the trap's return
-   value.  Note that ..._SCHEDULE_EXTRA_STATE_SAVER, unlike most ..._SAVER
-   macros, is required to setup EP itself if EP is needed (this is because
-   in many cases, the macro is empty).  */
-#define TRAP_SCHEDULE_EXTRA_STATE_SAVER                                              \
-       mov sp, ep;                                                           \
-       SAVE_RVAL_REGS
-/* Note that ..._SCHEDULE_EXTRA_STATE_RESTORER, unlike most ..._RESTORER
-   macros, is required to setup EP itself if EP is needed (this is because
-   in many cases, the macro is empty).  */
-#define TRAP_SCHEDULE_EXTRA_STATE_RESTORER                                   \
-       mov sp, ep;                                                           \
-       RESTORE_RVAL_REGS
-
-/* Register saving/restoring for maskable interrupts.  */
-#define IRQ_RET reti
-#define IRQ_STATE_SAVER                                                              \
-       SAVE_CALL_CLOBBERED_REGS;                                             \
-       SAVE_PC(EIPC);                                                        \
-       SAVE_PSW(EIPSW)
-#define IRQ_STATE_RESTORER                                                   \
-       RESTORE_CALL_CLOBBERED_REGS;                                          \
-       RESTORE_PC(EIPC);                                                     \
-       RESTORE_PSW(EIPSW)
-#define IRQ_EXTRA_STATE_SAVER                                                \
-       SAVE_CALL_SAVED_REGS;                                                 \
-       SAVE_CT_REGS
-#define IRQ_EXTRA_STATE_RESTORER                                             \
-       RESTORE_CALL_SAVED_REGS;                                              \
-       RESTORE_CT_REGS
-#define IRQ_SCHEDULE_EXTRA_STATE_SAVER      /* nothing */
-#define IRQ_SCHEDULE_EXTRA_STATE_RESTORER    /* nothing */
-
-/* Register saving/restoring for non-maskable interrupts.  */
-#define NMI_RET reti
-#define NMI_STATE_SAVER                                                              \
-       SAVE_CALL_CLOBBERED_REGS;                                             \
-       SAVE_PC(FEPC);                                                        \
-       SAVE_PSW(FEPSW);
-#define NMI_STATE_RESTORER                                                   \
-       RESTORE_CALL_CLOBBERED_REGS;                                          \
-       RESTORE_PC(FEPC);                                                     \
-       RESTORE_PSW(FEPSW);
-#define NMI_EXTRA_STATE_SAVER                                                \
-       SAVE_CALL_SAVED_REGS;                                                 \
-       SAVE_CT_REGS
-#define NMI_EXTRA_STATE_RESTORER                                             \
-       RESTORE_CALL_SAVED_REGS;                                              \
-       RESTORE_CT_REGS
-#define NMI_SCHEDULE_EXTRA_STATE_SAVER      /* nothing */
-#define NMI_SCHEDULE_EXTRA_STATE_RESTORER    /* nothing */
-
-/* Register saving/restoring for debug traps.  */
-#define DBTRAP_RET .long 0x014607E0 /* `dbret', but gas doesn't support it. */
-#define DBTRAP_STATE_SAVER                                                   \
-       SAVE_CALL_CLOBBERED_REGS;                                             \
-       SAVE_PC(DBPC);                                                        \
-       SAVE_PSW(DBPSW)
-#define DBTRAP_STATE_RESTORER                                                \
-       RESTORE_CALL_CLOBBERED_REGS;                                          \
-       RESTORE_PC(DBPC);                                                     \
-       RESTORE_PSW(DBPSW)
-#define DBTRAP_EXTRA_STATE_SAVER                                             \
-       SAVE_CALL_SAVED_REGS;                                                 \
-       SAVE_CT_REGS
-#define DBTRAP_EXTRA_STATE_RESTORER                                          \
-       RESTORE_CALL_SAVED_REGS;                                              \
-       RESTORE_CT_REGS
-#define DBTRAP_SCHEDULE_EXTRA_STATE_SAVER      /* nothing */
-#define DBTRAP_SCHEDULE_EXTRA_STATE_RESTORER   /* nothing */
-
-/* Register saving/restoring for a context switch.  We don't need to save
-   too many registers, because context-switching looks like a function call
-   (via the function `switch_thread'), so callers will save any
-   call-clobbered registers themselves.  We do need to save the CT regs, as
-   they're normally not saved during kernel entry (the kernel doesn't use
-   them).  We save PSW so that interrupt-status state will correctly follow
-   each thread (mostly NMI vs. normal-IRQ/trap), though for the most part
-   it doesn't matter since threads are always in almost exactly the same
-   processor state during a context switch.  The stack pointer and return
-   value are handled by switch_thread itself.  */
-#define SWITCH_STATE_SAVER                                                   \
-       SAVE_CALL_SAVED_REGS;                                                 \
-       SAVE_PSW(PSW);                                                        \
-       SAVE_CT_REGS
-#define SWITCH_STATE_RESTORER                                                \
-       RESTORE_CALL_SAVED_REGS;                                              \
-       RESTORE_PSW(PSW);                                                     \
-       RESTORE_CT_REGS
-
-
-/* Restore register state from the state-save-frame on the stack, switch back
-   to the user stack if necessary, and return from the trap/interrupt.
-   EXTRA_STATE_RESTORER is a sequence of assembly language statements to
-   restore anything not restored by this macro.  Only registers not saved by
-   the C compiler are restored (that is, R3(sp), R4(gp), R31(lp), and
-   anything restored by EXTRA_STATE_RESTORER).  */
-#define RETURN(type)                                                         \
-       ld.b    PTO+PT_KERNEL_MODE[sp], r19;                                  \
-       di;                             /* Disable interrupts */              \
-       cmp     r19, r0;                /* See if returning to kernel mode, */\
-       bne     2f;                     /* ... if so, skip resched &c.  */    \
-                                                                             \
-       /* We're returning to user mode, so check for various conditions that \
-          trigger rescheduling. */                                           \
-       GET_CURRENT_THREAD(r18);                                              \
-       ld.w    TI_FLAGS[r18], r19;                                           \
-       andi    _TIF_NEED_RESCHED, r19, r0;                                   \
-       bnz     3f;                     /* Call the scheduler.  */            \
-5:     andi    _TIF_SIGPENDING, r19, r18;                                    \
-       ld.w    TASK_PTRACE[CURRENT_TASK], r19; /* ptrace flags */            \
-       or      r18, r19;               /* see if either is non-zero */       \
-       bnz     4f;                     /* if so, handle them */              \
-                                                                             \
-/* Return to user state.  */                                                 \
-1:     st.b    r0, KM;                 /* Now officially in user state. */   \
-                                                                             \
-/* Final return.  The stack-pointer fiddling is not needed when returning     \
-   to kernel-mode, but they don't hurt, and this way we can share the        \
-   (sometimes rather lengthy) POP_STATE macro.  */                           \
-2:     POP_STATE(type);                                                      \
-       st.w    sp, KSP;                /* Save the kernel stack pointer. */  \
-       ld.w    PT_GPR(GPR_SP)-PT_SIZE[sp], sp; /* Restore stack pointer. */  \
-       type ## _RET;                   /* Return from the trap/interrupt. */ \
-                                                                             \
-/* Call the scheduler before returning from a syscall/trap. */               \
-3:     SAVE_EXTRA_STATE_FOR_SCHEDULE(type); /* Prepare to call scheduler. */ \
-       jarl    call_scheduler, lp;     /* Call scheduler */                  \
-       di;                             /* The scheduler enables interrupts */\
-       RESTORE_EXTRA_STATE_FOR_SCHEDULE(type);                               \
-       GET_CURRENT_THREAD(r18);                                              \
-       ld.w    TI_FLAGS[r18], r19;                                           \
-       br      5b;                     /* Continue with return path. */      \
-                                                                             \
-/* Handle a signal or ptraced process return.                                \
-   r18 should be non-zero if there are pending signals.  */                  \
-4:     /* Not all registers are saved by the normal trap/interrupt entry     \
-          points (for instance, call-saved registers (because the normal     \
-          C-compiler calling sequence in the kernel makes sure they're       \
-          preserved), and call-clobbered registers in the case of            \
-          traps), but signal handlers may want to examine or change the      \
-          complete register state.  Here we save anything not saved by       \
-          the normal entry sequence, so that it may be safely restored       \
-          (in a possibly modified form) after do_signal returns.  */         \
-       SAVE_EXTRA_STATE(type);         /* Save state not saved by entry. */  \
-       jarl    handle_signal_or_ptrace_return, lp;                           \
-       RESTORE_EXTRA_STATE(type);      /* Restore extra regs.  */            \
-       br      1b
-
-
-/* Jump to the appropriate function for the system call number in r12
-   (r12 is not preserved), or return an error if r12 is not valid.  The
-   LP register should point to the location where the called function
-   should return.  [note that MAKE_SYS_CALL uses label 1]  */
-#define MAKE_SYS_CALL                                                        \
-       /* Figure out which function to use for this system call.  */         \
-       shl     2, r12;                                                       \
-       /* See if the system call number is valid.  */                        \
-       addi    lo(CSYM(sys_call_table) - sys_call_table_end), r12, r0;       \
-       bnh     1f;                                                           \
-       mov     hilo(CSYM(sys_call_table)), r19;                              \
-       add     r19, r12;                                                     \
-       ld.w    0[r12], r12;                                                  \
-       /* Make the system call.  */                                          \
-       jmp     [r12];                                                        \
-       /* The syscall number is invalid, return an error.  */                \
-1:     addi    -ENOSYS, r0, r10;                                             \
-       jmp     [lp]
-
-
-       .text
-
-/*
- * User trap.
- *
- * Trap 0 system calls are also handled here.
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- *
- * Syscall protocol:
- *   Syscall number in r12, args in r6-r9
- *   Return value in r10
- */
-G_ENTRY(trap):
-       SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers.
-       stsr    SR_ECR, r19             // Find out which trap it was.
-       ei                              // Enable interrupts.
-       mov     hilo(ret_from_trap), lp // where the trap should return
-
-       // The following two shifts (1) clear out extraneous NMI data in the
-       // upper 16-bits, (2) convert the 0x40 - 0x5f range of trap ECR
-       // numbers into the (0-31) << 2 range we want, (3) set the flags.
-       shl     27, r19                 // chop off all high bits
-       shr     25, r19                 // scale back down and then << 2
-       bnz     2f                      // See if not trap 0.
-
-       // Trap 0 is a `short' system call, skip general trap table.
-       MAKE_SYS_CALL                   // Jump to the syscall function.
-
-2:     // For other traps, use a table lookup.
-       mov     hilo(CSYM(trap_table)), r18
-       add     r19, r18
-       ld.w    0[r18], r18
-       jmp     [r18]                   // Jump to the trap handler.
-END(trap)
-
-/* This is just like ret_from_trap, but first restores extra registers
-   saved by some wrappers.  */
-L_ENTRY(restore_extra_regs_and_ret_from_trap):
-       RESTORE_EXTRA_STATE(TRAP)
-       // fall through
-END(restore_extra_regs_and_ret_from_trap)
-
-/* Entry point used to return from a syscall/trap.  */
-L_ENTRY(ret_from_trap):
-       RETURN(TRAP)
-END(ret_from_trap)
-
-
-/* This the initial entry point for a new child thread, with an appropriate
-   stack in place that makes it look that the child is in the middle of an
-   syscall.  This function is actually `returned to' from switch_thread
-   (copy_thread makes ret_from_fork the return address in each new thread's
-   saved context).  */
-C_ENTRY(ret_from_fork):
-       mov     r10, r6                 // switch_thread returns the prev task.
-       jarl    CSYM(schedule_tail), lp // ...which is schedule_tail's arg
-       mov     r0, r10                 // Child's fork call should return 0.
-       br      ret_from_trap           // Do normal trap return.
-C_END(ret_from_fork)
-
-
-/*
- * Trap 1: `long' system calls
- * `Long' syscall protocol:
- *   Syscall number in r12, args in r6-r9, r13-r14
- *   Return value in r10
- */
-L_ENTRY(syscall_long):
-       // Push extra arguments on the stack.  Note that by default, the trap
-       // handler reserves enough stack space for 6 arguments, so we don't
-       // have to make any additional room.
-       st.w    r13, 16[sp]             // arg 5
-       st.w    r14, 20[sp]             // arg 6
-
-       // Make sure r13 and r14 are preserved, in case we have to restart a
-       // system call because of a signal (ep has already been set by caller).
-       st.w    r13, PTO+PT_GPR(13)[sp]
-       st.w    r14, PTO+PT_GPR(13)[sp]
-       mov     hilo(ret_from_long_syscall), lp
-
-       MAKE_SYS_CALL                   // Jump to the syscall function.
-END(syscall_long)
-
-/* Entry point used to return from a long syscall.  Only needed to restore
-   r13/r14 if the general trap mechanism doesnt' do so.  */
-L_ENTRY(ret_from_long_syscall):
-       ld.w    PTO+PT_GPR(13)[sp], r13 // Restore the extra registers
-       ld.w    PTO+PT_GPR(13)[sp], r14
-       br      ret_from_trap           // The rest is the same as other traps
-END(ret_from_long_syscall)
-
-
-/* These syscalls need access to the struct pt_regs on the stack, so we
-   implement them in assembly (they're basically all wrappers anyway).  */
-
-L_ENTRY(sys_fork_wrapper):
-#ifdef CONFIG_MMU
-       addi    SIGCHLD, r0, r6            // Arg 0: flags
-       ld.w    PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
-       movea   PTO, sp, r8                // Arg 2: parent context
-       mov     r0, r9                     // Arg 3/4/5: 0
-       st.w    r0, 16[sp]
-       st.w    r0, 20[sp]
-       mov     hilo(CSYM(do_fork)), r18   // Where the real work gets done
-       br      save_extra_state_tramp     // Save state and go there
-#else
-       // fork almost works, enough to trick you into looking elsewhere :-(
-       addi    -EINVAL, r0, r10
-       jmp     [lp]
-#endif
-END(sys_fork_wrapper)
-
-L_ENTRY(sys_vfork_wrapper):
-       addi    CLONE_VFORK | CLONE_VM | SIGCHLD, r0, r6 // Arg 0: flags
-       ld.w    PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
-       movea   PTO, sp, r8                // Arg 2: parent context
-       mov     r0, r9                     // Arg 3/4/5: 0
-       st.w    r0, 16[sp]
-       st.w    r0, 20[sp]
-       mov     hilo(CSYM(do_fork)), r18   // Where the real work gets done
-       br      save_extra_state_tramp     // Save state and go there
-END(sys_vfork_wrapper)
-
-L_ENTRY(sys_clone_wrapper):
-       ld.w    PTO+PT_GPR(GPR_SP)[sp], r19// parent's stack pointer
-       cmp     r7, r0                     // See if child SP arg (arg 1) is 0.
-       cmov    z, r19, r7, r7             // ... and use the parent's if so.
-       movea   PTO, sp, r8                // Arg 2: parent context
-       mov     r0, r9                     // Arg 3/4/5: 0
-       st.w    r0, 16[sp]
-       st.w    r0, 20[sp]
-       mov     hilo(CSYM(do_fork)), r18   // Where the real work gets done
-       br      save_extra_state_tramp     // Save state and go there
-END(sys_clone_wrapper)
-
-
-L_ENTRY(sys_execve_wrapper):
-       movea   PTO, sp, r9             // add user context as 4th arg
-       jr      CSYM(sys_execve)        // Do real work (tail-call).
-END(sys_execve_wrapper)
-
-
-L_ENTRY(sys_sigsuspend_wrapper):
-       movea   PTO, sp, r7             // add user context as 2nd arg
-       mov     hilo(CSYM(sys_sigsuspend)), r18 // syscall function
-       jarl    save_extra_state_tramp, lp      // Save state and do it
-       br      restore_extra_regs_and_ret_from_trap
-END(sys_sigsuspend_wrapper)
-L_ENTRY(sys_rt_sigsuspend_wrapper):
-       movea   PTO, sp, r8             // add user context as 3rd arg
-       mov     hilo(CSYM(sys_rt_sigsuspend)), r18 // syscall function
-       jarl    save_extra_state_tramp, lp         // Save state and do it
-       br      restore_extra_regs_and_ret_from_trap
-END(sys_rt_sigsuspend_wrapper)
-
-L_ENTRY(sys_sigreturn_wrapper):
-       movea   PTO, sp, r6             // add user context as 1st arg
-       mov     hilo(CSYM(sys_sigreturn)), r18  // syscall function
-       jarl    save_extra_state_tramp, lp      // Save state and do it
-       br      restore_extra_regs_and_ret_from_trap
-END(sys_sigreturn_wrapper)
-L_ENTRY(sys_rt_sigreturn_wrapper):
-       movea   PTO, sp, r6             // add user context as 1st arg
-       mov     hilo(CSYM(sys_rt_sigreturn)), r18// syscall function
-       jarl    save_extra_state_tramp, lp       // Save state and do it
-       br      restore_extra_regs_and_ret_from_trap
-END(sys_rt_sigreturn_wrapper)
-
-
-/* Save any state not saved by SAVE_STATE(TRAP), and jump to r18.
-   It's main purpose is to share the rather lengthy code sequence that
-   SAVE_STATE expands into among the above wrapper functions.  */
-L_ENTRY(save_extra_state_tramp):
-       SAVE_EXTRA_STATE(TRAP)          // Save state not saved by entry.
-       jmp     [r18]                   // Do the work the caller wants
-END(save_extra_state_tramp)
-
-
-/*
- * Hardware maskable interrupts.
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- */
-G_ENTRY(irq):
-       SAVE_STATE (IRQ, r0, ENTRY_SP)  // Save registers.
-
-       stsr    SR_ECR, r6              // Find out which interrupt it was.
-       movea   PTO, sp, r7             // User regs are arg2
-
-       // All v850 implementations I know about encode their interrupts as
-       // multiples of 0x10, starting at 0x80 (after NMIs and software
-       // interrupts).  Convert this number into a simple IRQ index for the
-       // rest of the kernel.  We also clear the upper 16 bits, which hold
-       // NMI info, and don't appear to be cleared when a NMI returns.
-       shl     16, r6                  // clear upper 16 bits
-       shr     20, r6                  // shift back, and remove lower nibble
-       add     -8, r6                  // remove bias for irqs
-
-       // Call the high-level interrupt handling code.
-       jarl    CSYM(handle_irq), lp
-
-       RETURN(IRQ)
-END(irq)
-
-
-/*
- * Debug trap / illegal-instruction exception
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- */
-G_ENTRY(dbtrap):
-       SAVE_STATE (DBTRAP, r0, ENTRY_SP)// Save registers.
-
-       /* First see if we came from kernel mode; if so, the dbtrap
-          instruction has a special meaning, to set the DIR (`debug
-          information register') register.  This is because the DIR register
-          can _only_ be manipulated/read while in `debug mode,' and debug
-          mode is only active while we're inside the dbtrap handler.  The
-          exact functionality is:  { DIR = (DIR | r6) & ~r7; return DIR; }. */
-       ld.b    PTO+PT_KERNEL_MODE[sp], r19
-       cmp     r19, r0
-       bz      1f
-
-       stsr    SR_DIR, r10
-       or      r6, r10
-       not     r7, r7
-       and     r7, r10
-       ldsr    r10, SR_DIR
-       stsr    SR_DIR, r10             // Confirm the value we set
-       st.w    r10, PTO+PT_GPR(10)[sp] // return it
-       br      3f
-
-1:     ei                              // Enable interrupts.
-
-       /* The default signal type we raise.  */
-       mov     SIGTRAP, r6
-
-       /* See if it's a single-step trap.  */
-       stsr    SR_DBPSW, r19
-       andi    0x0800, r19, r19
-       bnz     2f
-
-       /* Look to see if the preceding instruction was is a dbtrap or not,
-          to decide which signal we should use.  */
-       stsr    SR_DBPC, r19            // PC following trapping insn
-       ld.hu   -2[r19], r19
-       ori     0xf840, r0, r20         // DBTRAP insn
-       cmp     r19, r20                // Was this trap caused by DBTRAP?
-       cmov    ne, SIGILL, r6, r6      // Choose signal appropriately
-
-       /* Raise the desired signal.  */
-2:     mov     CURRENT_TASK, r7        // Arg 1: task
-       jarl    CSYM(send_sig), lp      // tail call
-
-3:     RETURN(DBTRAP)
-END(dbtrap)
-
-
-/*
- * Hardware non-maskable interrupts.
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- */
-G_ENTRY(nmi):
-       SAVE_STATE (NMI, r0, NMI_ENTRY_SP); /* Save registers.  */
-
-       stsr    SR_ECR, r6;             /* Find out which nmi it was.  */
-       shr     20, r6;                 /* Extract NMI code in bits 20-24. */
-       movea   PTO, sp, r7;            /* User regs are arg2.  */
-
-       /* Non-maskable interrupts always lie right after maskable interrupts.
-          Call the generic IRQ handler, with two arguments, the IRQ number,
-          and a pointer to the user registers, to handle the specifics.
-          (we subtract one because the first NMI has code 1).  */
-       addi    FIRST_NMI - 1, r6, r6
-       jarl    CSYM(handle_irq), lp
-
-       RETURN(NMI)
-END(nmi)
-
-
-/*
- * Trap with no handler
- */
-L_ENTRY(bad_trap_wrapper):
-       mov     r19, r6                 // Arg 0: trap number
-       movea   PTO, sp, r7             // Arg 1: user regs
-       jr      CSYM(bad_trap)          // tail call handler
-END(bad_trap_wrapper)
-
-
-/*
- * Invoke the scheduler, called from the trap/irq kernel exit path.
- *
- * This basically just calls `schedule', but also arranges for extra
- * registers to be saved for ptrace'd processes, so ptrace can modify them.
- */
-L_ENTRY(call_scheduler):
-       ld.w    TASK_PTRACE[CURRENT_TASK], r19  // See if task is ptrace'd
-       cmp     r19, r0
-       bnz     1f                      // ... yes, do special stuff
-       jr      CSYM(schedule)          // ... no, just tail-call scheduler
-
-       // Save extra regs for ptrace'd task.  We want to save anything
-       // that would otherwise only be `implicitly' saved by the normal
-       // compiler calling-convention.
-1:     mov     sp, ep                  // Setup EP for SAVE_CALL_SAVED_REGS
-       SAVE_CALL_SAVED_REGS            // Save call-saved registers to stack
-       mov     lp, r20                 // Save LP in a callee-saved register
-
-       jarl    CSYM(schedule), lp      // Call scheduler
-
-       mov     r20, lp
-       mov     sp, ep                  // We can't rely on EP after return
-       RESTORE_CALL_SAVED_REGS         // Restore (possibly modified) regs
-       jmp     [lp]                    // Return to the return path
-END(call_scheduler)
-
-
-/*
- * This is an out-of-line handler for two special cases during the kernel
- * trap/irq exit sequence:
- *
- *  (1) If r18 is non-zero then a signal needs to be handled, which is
- *     done, and then the caller returned to.
- *
- *  (2) If r18 is non-zero then we're returning to a ptraced process, which
- *     has several special cases -- single-stepping and trap tracing, both
- *     of which require using the `dbret' instruction to exit the kernel
- *     instead of the normal `reti' (this is because the CPU not correctly
- *     single-step after a reti).  In this case, of course, this handler
- *     never returns to the caller.
- *
- * In either case, all registers should have been saved to the current
- * state-save-frame on the stack, except for callee-saved registers.
- *
- * [These two different cases are combined merely to avoid bloating the
- * macro-inlined code, not because they really make much sense together!]
- */
-L_ENTRY(handle_signal_or_ptrace_return):
-       cmp     r18, r0                 // See if handling a signal
-       bz      1f                      // ... nope, go do ptrace return
-
-       // Handle a signal
-       mov     lp, r20                 // Save link-pointer
-       mov     r10, r21                // Save return-values (for trap)
-       mov     r11, r22
-
-       movea   PTO, sp, r6             // Arg 1: struct pt_regs *regs
-       mov     r0, r7                  // Arg 2: sigset_t *oldset
-       jarl    CSYM(do_signal), lp     // Handle the signal
-       di                              // sig handling enables interrupts
-
-       mov     r20, lp                 // Restore link-pointer
-       mov     r21, r10                // Restore return-values (for trap)
-       mov     r22, r11
-       ld.w    TASK_PTRACE[CURRENT_TASK], r19  // check ptrace flags too
-       cmp     r19, r0
-       bnz     1f                      // ... some set, so look more
-2:     jmp     [lp]                    // ... none set, so return normally
-
-       // ptrace return
-1:     ld.w    PTO+PT_PSW[sp], r19     // Look at user-processes's flags
-       andi    0x0800, r19, r19        // See if single-step flag is set
-       bz      2b                      // ... nope, return normally
-
-       // Return as if from a dbtrap insn
-       st.b    r0, KM                  // Now officially in user state.
-       POP_STATE(DBTRAP)               // Restore regs
-       st.w    sp, KSP                 // Save the kernel stack pointer.
-       ld.w    PT_GPR(GPR_SP)-PT_SIZE[sp], sp // Restore user stack pointer.
-       DBTRAP_RET                      // Return from the trap/interrupt.
-END(handle_signal_or_ptrace_return)
-
-
-/*
- * This is where we switch between two threads.  The arguments are:
- *   r6 -- pointer to the struct thread for the `current' process
- *   r7 -- pointer to the struct thread for the `new' process.
- * when this function returns, it will return to the new thread.
- */
-C_ENTRY(switch_thread):
-       // Return the previous task (r10 is not clobbered by restore below)
-       mov     CURRENT_TASK, r10
-       // First, push the current processor state on the stack
-       PUSH_STATE(SWITCH)
-       // Now save the location of the kernel stack pointer for this thread;
-       // since we've pushed all other state on the stack, this is enough to
-       // restore it all later.
-       st.w    sp, THREAD_KSP[r6]
-       // Now restore the stack pointer from the new process
-       ld.w    THREAD_KSP[r7], sp
-       // ... and restore all state from that
-       POP_STATE(SWITCH)
-       // Update the current task pointer
-       GET_CURRENT_TASK(CURRENT_TASK)
-       // Now return into the new thread
-       jmp     [lp]
-C_END(switch_thread)
-
-
-       .data
-
-       .align 4
-C_DATA(trap_table):
-       .long bad_trap_wrapper          // trap 0, doesn't use trap table.
-       .long syscall_long              // trap 1, `long' syscall.
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-       .long bad_trap_wrapper
-C_END(trap_table)
-
-
-       .section .rodata
-
-       .align 4
-C_DATA(sys_call_table):
-       .long CSYM(sys_restart_syscall) // 0
-       .long CSYM(sys_exit)
-       .long sys_fork_wrapper
-       .long CSYM(sys_read)
-       .long CSYM(sys_write)
-       .long CSYM(sys_open)            // 5
-       .long CSYM(sys_close)
-       .long CSYM(sys_waitpid)
-       .long CSYM(sys_creat)
-       .long CSYM(sys_link)
-       .long CSYM(sys_unlink)          // 10
-       .long sys_execve_wrapper
-       .long CSYM(sys_chdir)
-       .long CSYM(sys_time)
-       .long CSYM(sys_mknod)
-       .long CSYM(sys_chmod)           // 15
-       .long CSYM(sys_chown)
-       .long CSYM(sys_ni_syscall)      // was: break
-       .long CSYM(sys_ni_syscall)      // was: oldstat (aka stat)
-       .long CSYM(sys_lseek)
-       .long CSYM(sys_getpid)          // 20
-       .long CSYM(sys_mount)
-       .long CSYM(sys_oldumount)
-       .long CSYM(sys_setuid)
-       .long CSYM(sys_getuid)
-       .long CSYM(sys_stime)           // 25
-       .long CSYM(sys_ptrace)
-       .long CSYM(sys_alarm)
-       .long CSYM(sys_ni_syscall)      // was: oldfstat (aka fstat)
-       .long CSYM(sys_pause)
-       .long CSYM(sys_utime)           // 30
-       .long CSYM(sys_ni_syscall)      // was: stty
-       .long CSYM(sys_ni_syscall)      // was: gtty
-       .long CSYM(sys_access)
-       .long CSYM(sys_nice)
-       .long CSYM(sys_ni_syscall)      // 35, was: ftime
-       .long CSYM(sys_sync)
-       .long CSYM(sys_kill)
-       .long CSYM(sys_rename)
-       .long CSYM(sys_mkdir)
-       .long CSYM(sys_rmdir)           // 40
-       .long CSYM(sys_dup)
-       .long CSYM(sys_pipe)
-       .long CSYM(sys_times)
-       .long CSYM(sys_ni_syscall)      // was: prof
-       .long CSYM(sys_brk)             // 45
-       .long CSYM(sys_setgid)
-       .long CSYM(sys_getgid)
-       .long CSYM(sys_signal)
-       .long CSYM(sys_geteuid)
-       .long CSYM(sys_getegid)         // 50
-       .long CSYM(sys_acct)
-       .long CSYM(sys_umount)          // recycled never used phys()
-       .long CSYM(sys_ni_syscall)      // was: lock
-       .long CSYM(sys_ioctl)
-       .long CSYM(sys_fcntl)           // 55
-       .long CSYM(sys_ni_syscall)      // was: mpx
-       .long CSYM(sys_setpgid)
-       .long CSYM(sys_ni_syscall)      // was: ulimit
-       .long CSYM(sys_ni_syscall)
-       .long CSYM(sys_umask)           // 60
-       .long CSYM(sys_chroot)
-       .long CSYM(sys_ustat)
-       .long CSYM(sys_dup2)
-       .long CSYM(sys_getppid)
-       .long CSYM(sys_getpgrp)         // 65
-       .long CSYM(sys_setsid)
-       .long CSYM(sys_sigaction)
-       .long CSYM(sys_sgetmask)
-       .long CSYM(sys_ssetmask)
-       .long CSYM(sys_setreuid)        // 70
-       .long CSYM(sys_setregid)
-       .long sys_sigsuspend_wrapper
-       .long CSYM(sys_sigpending)
-       .long CSYM(sys_sethostname)
-       .long CSYM(sys_setrlimit)       // 75
-       .long CSYM(sys_getrlimit)
-       .long CSYM(sys_getrusage)
-       .long CSYM(sys_gettimeofday)
-       .long CSYM(sys_settimeofday)
-       .long CSYM(sys_getgroups)       // 80
-       .long CSYM(sys_setgroups)
-       .long CSYM(sys_select)
-       .long CSYM(sys_symlink)
-       .long CSYM(sys_ni_syscall)      // was: oldlstat (aka lstat)
-       .long CSYM(sys_readlink)        // 85
-       .long CSYM(sys_uselib)
-       .long CSYM(sys_swapon)
-       .long CSYM(sys_reboot)
-       .long CSYM(old_readdir)
-       .long CSYM(sys_mmap)            // 90
-       .long CSYM(sys_munmap)
-       .long CSYM(sys_truncate)
-       .long CSYM(sys_ftruncate)
-       .long CSYM(sys_fchmod)
-       .long CSYM(sys_fchown)          // 95
-       .long CSYM(sys_getpriority)
-       .long CSYM(sys_setpriority)
-       .long CSYM(sys_ni_syscall)      // was: profil
-       .long CSYM(sys_statfs)
-       .long CSYM(sys_fstatfs)         // 100
-       .long CSYM(sys_ni_syscall)      // i386: ioperm
-       .long CSYM(sys_socketcall)
-       .long CSYM(sys_syslog)
-       .long CSYM(sys_setitimer)
-       .long CSYM(sys_getitimer)       // 105
-       .long CSYM(sys_newstat)
-       .long CSYM(sys_newlstat)
-       .long CSYM(sys_newfstat)
-       .long CSYM(sys_ni_syscall)      // was: olduname (aka uname)
-       .long CSYM(sys_ni_syscall)      // 110, i386: iopl
-       .long CSYM(sys_vhangup)
-       .long CSYM(sys_ni_syscall)      // was: idle
-       .long CSYM(sys_ni_syscall)      // i386: vm86old
-       .long CSYM(sys_wait4)
-       .long CSYM(sys_swapoff)         // 115
-       .long CSYM(sys_sysinfo)
-       .long CSYM(sys_ipc)
-       .long CSYM(sys_fsync)
-       .long sys_sigreturn_wrapper
-       .long sys_clone_wrapper         // 120
-       .long CSYM(sys_setdomainname)
-       .long CSYM(sys_newuname)
-       .long CSYM(sys_ni_syscall)      // i386: modify_ldt, m68k: cacheflush
-       .long CSYM(sys_adjtimex)
-       .long CSYM(sys_ni_syscall)      // 125 - sys_mprotect
-       .long CSYM(sys_sigprocmask)
-       .long CSYM(sys_ni_syscall)      // sys_create_module
-       .long CSYM(sys_init_module)
-       .long CSYM(sys_delete_module)
-       .long CSYM(sys_ni_syscall)      // 130 - sys_get_kernel_syms
-       .long CSYM(sys_quotactl)
-       .long CSYM(sys_getpgid)
-       .long CSYM(sys_fchdir)
-       .long CSYM(sys_bdflush)
-       .long CSYM(sys_sysfs)           // 135
-       .long CSYM(sys_personality)
-       .long CSYM(sys_ni_syscall)      // for afs_syscall
-       .long CSYM(sys_setfsuid)
-       .long CSYM(sys_setfsgid)
-       .long CSYM(sys_llseek)          // 140
-       .long CSYM(sys_getdents)
-       .long CSYM(sys_select)          // for backward compat; remove someday
-       .long CSYM(sys_flock)
-       .long CSYM(sys_ni_syscall)      // sys_msync
-       .long CSYM(sys_readv)           // 145
-       .long CSYM(sys_writev)
-       .long CSYM(sys_getsid)
-       .long CSYM(sys_fdatasync)
-       .long CSYM(sys_sysctl)
-       .long CSYM(sys_ni_syscall)      // 150 - sys_mlock
-       .long CSYM(sys_ni_syscall)      // sys_munlock
-       .long CSYM(sys_ni_syscall)      // sys_mlockall
-       .long CSYM(sys_ni_syscall)      // sys_munlockall
-       .long CSYM(sys_sched_setparam)
-       .long CSYM(sys_sched_getparam)  // 155
-       .long CSYM(sys_sched_setscheduler)
-       .long CSYM(sys_sched_getscheduler)
-       .long CSYM(sys_sched_yield)
-       .long CSYM(sys_sched_get_priority_max)
-       .long CSYM(sys_sched_get_priority_min)  // 160
-       .long CSYM(sys_sched_rr_get_interval)
-       .long CSYM(sys_nanosleep)
-       .long CSYM(sys_ni_syscall)      // sys_mremap
-       .long CSYM(sys_setresuid)
-       .long CSYM(sys_getresuid)       // 165
-       .long CSYM(sys_ni_syscall)      // for vm86
-       .long CSYM(sys_ni_syscall)      // sys_query_module
-       .long CSYM(sys_poll)
-       .long CSYM(sys_nfsservctl)
-       .long CSYM(sys_setresgid)       // 170
-       .long CSYM(sys_getresgid)
-       .long CSYM(sys_prctl)
-       .long sys_rt_sigreturn_wrapper
-       .long CSYM(sys_rt_sigaction)
-       .long CSYM(sys_rt_sigprocmask)  // 175
-       .long CSYM(sys_rt_sigpending)
-       .long CSYM(sys_rt_sigtimedwait)
-       .long CSYM(sys_rt_sigqueueinfo)
-       .long sys_rt_sigsuspend_wrapper
-       .long CSYM(sys_pread64)         // 180
-       .long CSYM(sys_pwrite64)
-       .long CSYM(sys_lchown)
-       .long CSYM(sys_getcwd)
-       .long CSYM(sys_capget)
-       .long CSYM(sys_capset)          // 185
-       .long CSYM(sys_sigaltstack)
-       .long CSYM(sys_sendfile)
-       .long CSYM(sys_ni_syscall)      // streams1
-       .long CSYM(sys_ni_syscall)      // streams2
-       .long sys_vfork_wrapper         // 190
-       .long CSYM(sys_ni_syscall)
-       .long CSYM(sys_mmap2)
-       .long CSYM(sys_truncate64)
-       .long CSYM(sys_ftruncate64)
-       .long CSYM(sys_stat64)          // 195
-       .long CSYM(sys_lstat64)
-       .long CSYM(sys_fstat64)
-       .long CSYM(sys_fcntl64)
-       .long CSYM(sys_getdents64)
-       .long CSYM(sys_pivot_root)      // 200
-       .long CSYM(sys_gettid)
-       .long CSYM(sys_tkill)
-sys_call_table_end:
-C_END(sys_call_table)
diff --git a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c
deleted file mode 100644 (file)
index ab9cf16..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for
- *     FPGA implementation of V850E2/NA85E2C
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-#include <linux/bitops.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-
-#include "mach.h"
-
-extern void memcons_setup (void);
-
-
-#define REG_DUMP_ADDR          0x220000
-
-
-extern struct irqaction reg_snap_action; /* fwd decl */
-
-
-void __init mach_early_init (void)
-{
-       int i;
-       const u32 *src;
-       register u32 *dst asm ("ep");
-       extern u32 _intv_end, _intv_load_start;
-
-       /* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit,
-          everything else 32-bit.  */
-       V850E2_BSC = 0x2AA6;
-       for (i = 2; i <= 6; i++)
-               CSDEV(i) = 0;   /* 32 bit */
-
-       /* Ensure that the simulator halts on a panic, instead of going
-          into an infinite loop inside the panic function.  */
-       panic_timeout = -1;
-
-       /* Move the interrupt vectors into their real location.  Note that
-          any relocations there are relative to the real location, so we
-          don't have to fix anything up.  We use a loop instead of calling
-          memcpy to keep this a leaf function (to avoid a function
-          prologue being generated).  */
-       dst = 0x10;             /* &_intv_start + 0x10.  */
-       src = &_intv_load_start;
-       do {
-               u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
-               u32 t4 = src[4], t5 = src[5], t6 = src[6], t7 = src[7];
-               dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
-               dst[4] = t4; dst[5] = t5; dst[6] = t6; dst[7] = t7;
-               dst += 8;
-               src += 8;
-       } while (dst < &_intv_end);
-}
-
-void __init mach_setup (char **cmdline)
-{
-       memcons_setup ();
-
-       /* Setup up NMI0 to copy the registers to a known memory location.
-          The FGPA board has a button that produces NMI0 when pressed, so
-          this allows us to push the button, and then look at memory to see
-          what's in the registers (there's no other way to easily do so).
-          We have to use `setup_irq' instead of `request_irq' because it's
-          still too early to do memory allocation.  */
-       setup_irq (IRQ_NMI (0), &reg_snap_action);
-}
-
-void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
-{
-       *ram_start = ERAM_ADDR;
-       *ram_len = ERAM_SIZE;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
-       /* Setup up the timer interrupt.  The FPGA peripheral control
-          registers _only_ work with single-bit writes (set1/clr1)!  */
-       __clear_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
-       __clear_bit (RPU_GTMC_CLK_BIT, &RPU_GTMC);
-       __set_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
-
-       /* We use the first RPU interrupt, which occurs every 8.192ms.  */
-       setup_irq (IRQ_RPU (0), timer_action);
-}
-
-\f
-void mach_gettimeofday (struct timespec *tv)
-{
-       tv->tv_sec = 0;
-       tv->tv_nsec = 0;
-}
-
-void machine_halt (void) __attribute__ ((noreturn));
-void machine_halt (void)
-{
-       for (;;) {
-               DWC(0) = 0x7777;
-               DWC(1) = 0x7777;
-               ASC = 0xffff;
-               FLGREG(0) = 1;  /* Halt immediately.  */
-               asm ("di; halt; nop; nop; nop; nop; nop");
-       }
-}
-
-void machine_restart (char *__unused)
-{
-       machine_halt ();
-}
-
-void machine_power_off (void)
-{
-       machine_halt ();
-}
-
-\f
-/* Interrupts */
-
-struct v850e_intc_irq_init irq_inits[] = {
-       { "IRQ", 0,             NUM_MACH_IRQS,  1, 7 },
-       { "RPU", IRQ_RPU(0),    IRQ_RPU_NUM,    1, 6 },
-       { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-/* Initialize interrupts.  */
-void __init mach_init_irqs (void)
-{
-       v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-\f
-/* An interrupt handler that copies the registers to a known memory location,
-   for debugging purposes.  */
-
-static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs)
-{
-       (*(unsigned *)REG_DUMP_ADDR)++;
-       (*(struct pt_regs *)(REG_DUMP_ADDR + sizeof (unsigned))) = *regs;
-}
-
-static int reg_snap_dev_id;
-static struct irqaction reg_snap_action = {
-       .handler = make_reg_snap,
-       .mask = CPU_MASK_NONE,
-       .name = "reg_snap",
-       .dev_id = &reg_snap_dev_id,
-};
diff --git a/arch/v850/kernel/fpga85e2c.ld b/arch/v850/kernel/fpga85e2c.ld
deleted file mode 100644 (file)
index b5d4578..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Linker script for the FPGA implementation of the V850E2 NA85E2C cpu core
-   (CONFIG_V850E2_FPGA85E2C).  */
-
-MEMORY {
-       /* Reset vector.  */
-       RESET    : ORIGIN = 0, LENGTH = 0x10
-       /* Interrupt vectors.  */
-       INTV      : ORIGIN = 0x10, LENGTH = 0x470
-       /* The `window' in RAM were we're allowed to load stuff.  */
-       RAM_LOW   : ORIGIN = 0x480, LENGTH = 0x0005FB80
-       /* Some more ram above the window were we can put bss &c.  */
-       RAM_HIGH  : ORIGIN = 0x00060000, LENGTH = 0x000A0000
-       /* This is the area visible from the outside world (we can use
-          this only for uninitialized data).  */
-       VISIBLE   : ORIGIN = 0x00200000, LENGTH = 0x00060000
-}
-
-SECTIONS {
-       .reset : {
-               __kram_start = . ;
-               __intv_start = . ;
-                       *(.intv.reset)  /* Reset vector */
-       } > RESET
-
-       .ram_low : {
-               __r0_ram = . ;          /* Must be near address 0.  */
-               . = . + 32 ;
-
-               TEXT_CONTENTS
-               DATA_CONTENTS
-               ROOT_FS_CONTENTS
-               RAMK_INIT_CONTENTS_NO_END
-               INITRAMFS_CONTENTS
-       } > RAM_LOW
-
-        /* Where the interrupt vectors are initially loaded.  */
-       __intv_load_start = . ;
-
-       .intv : {
-                       *(.intv.common) /* Vectors common to all v850e proc. */
-                       *(.intv.mach)   /* Machine-specific int. vectors.  */
-               __intv_end = . ;
-       } > INTV  AT> RAM_LOW
-
-       .ram_high : {
-               /* This is here so that when we free init memory the
-                  load-time copy of the interrupt vectors and any empty
-                  space at the end of the `RAM_LOW' area is freed too.  */
-               . = ALIGN (4096);
-               __init_end = . ;
-
-               BSS_CONTENTS
-               __kram_end = . ;
-               BOOTMAP_CONTENTS
-       } > RAM_HIGH
-
-       .visible : {
-               _memcons_output = . ;
-               . = . + 0x8000 ;
-               _memcons_output_end = . ;
-       } > VISIBLE
-}
diff --git a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c
deleted file mode 100644 (file)
index b2bcc25..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * arch/v850/kernel/gbus_int.c -- Midas labs GBUS interrupt support
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-
-#include <asm/machdep.h>
-
-
-/* The number of shared GINT interrupts. */
-#define NUM_GINTS      4
-
-/* For each GINT interrupt, how many GBUS interrupts are using it.  */
-static unsigned gint_num_active_irqs[NUM_GINTS] = { 0 };
-
-/* A table of GINTn interrupts we actually use.
-   Note that we don't use GINT0 because all the boards we support treat it
-   specially.  */
-struct used_gint {
-       unsigned gint;
-       unsigned priority;
-} used_gint[] = {
-       { 1, GBUS_INT_PRIORITY_HIGH },
-       { 3, GBUS_INT_PRIORITY_LOW }
-};
-#define NUM_USED_GINTS ARRAY_SIZE(used_gint)
-
-/* A table of which GINT is used by each GBUS interrupts (they are
-   assigned based on priority).  */
-static unsigned char gbus_int_gint[IRQ_GBUS_INT_NUM];
-
-\f
-/* Interrupt enabling/disabling.  */
-
-/* Enable interrupt handling for interrupt IRQ.  */
-void gbus_int_enable_irq (unsigned irq)
-{
-       unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
-       GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
-               |= GBUS_INT_IRQ_MASK (irq);
-}
-
-/* Disable interrupt handling for interrupt IRQ.  Note that any
-   interrupts received while disabled will be delivered once the
-   interrupt is enabled again, unless they are explicitly cleared using
-   `gbus_int_clear_pending_irq'.  */
-void gbus_int_disable_irq (unsigned irq)
-{
-       unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
-       GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
-               &= ~GBUS_INT_IRQ_MASK (irq);
-}
-
-/* Return true if interrupt handling for interrupt IRQ is enabled.  */
-int gbus_int_irq_enabled (unsigned irq)
-{
-       unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
-       return (GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
-               & GBUS_INT_IRQ_MASK(irq));
-}
-
-/* Disable all GBUS irqs.  */
-void gbus_int_disable_irqs ()
-{
-       unsigned w, n;
-       for (w = 0; w < GBUS_INT_NUM_WORDS; w++)
-               for (n = 0; n < IRQ_GINT_NUM; n++)
-                       GBUS_INT_ENABLE (w, n) = 0;
-}
-
-/* Clear any pending interrupts for IRQ.  */
-void gbus_int_clear_pending_irq (unsigned irq)
-{
-       GBUS_INT_CLEAR (GBUS_INT_IRQ_WORD(irq)) = GBUS_INT_IRQ_MASK (irq);
-}
-
-/* Return true if interrupt IRQ is pending (but disabled).  */
-int gbus_int_irq_pending (unsigned irq)
-{
-       return (GBUS_INT_STATUS (GBUS_INT_IRQ_WORD(irq))
-               & GBUS_INT_IRQ_MASK(irq));
-}
-
-\f
-/* Delegating interrupts.  */
-
-/* Handle a shared GINT interrupt by passing to the appropriate GBUS
-   interrupt handler.  */
-static irqreturn_t gbus_int_handle_irq (int irq, void *dev_id,
-                                       struct pt_regs *regs)
-{
-       unsigned w;
-       irqreturn_t rval = IRQ_NONE;
-       unsigned gint = irq - IRQ_GINT (0);
-
-       for (w = 0; w < GBUS_INT_NUM_WORDS; w++) {
-               unsigned status = GBUS_INT_STATUS (w);
-               unsigned enable = GBUS_INT_ENABLE (w, gint);
-
-               /* Only pay attention to enabled interrupts.  */
-               status &= enable;
-               if (status) {
-                       irq = IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD);
-                       do {
-                               /* There's an active interrupt in word
-                                  W, find out which one, and call its
-                                  handler.  */
-
-                               while (! (status & 0x1)) {
-                                       irq++;
-                                       status >>= 1;
-                               }
-                               status &= ~0x1;
-
-                               /* Recursively call handle_irq to handle it. */
-                               handle_irq (irq, regs);
-                               rval = IRQ_HANDLED;
-                       } while (status);
-               }
-       }
-
-       /* Toggle the `all enable' bit back and forth, which should cause
-          another edge transition if there are any other interrupts
-          still pending, and so result in another CPU interrupt.  */
-       GBUS_INT_ENABLE (0, gint) &= ~0x1;
-       GBUS_INT_ENABLE (0, gint) |=  0x1;
-
-       return rval;
-}
-
-\f
-/* Initialize GBUS interrupt sources.  */
-
-static void irq_nop (unsigned irq) { }
-
-static unsigned gbus_int_startup_irq (unsigned irq)
-{
-       unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
-
-       if (gint_num_active_irqs[gint] == 0) {
-               /* First enable the CPU interrupt.  */
-               int rval =
-                       request_irq (IRQ_GINT(gint), gbus_int_handle_irq,
-                                    IRQF_DISABLED,
-                                    "gbus_int_handler",
-                                    &gint_num_active_irqs[gint]);
-               if (rval != 0)
-                       return rval;
-       }
-
-       gint_num_active_irqs[gint]++;
-
-       gbus_int_clear_pending_irq (irq);
-       gbus_int_enable_irq (irq);
-
-       return 0;
-}
-
-static void gbus_int_shutdown_irq (unsigned irq)
-{
-       unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
-
-       gbus_int_disable_irq (irq);
-
-       if (--gint_num_active_irqs[gint] == 0)
-               /* Disable the CPU interrupt.  */
-               free_irq (IRQ_GINT(gint), &gint_num_active_irqs[gint]);
-}
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
-   INITS (which is terminated by an entry with the name field == 0).  */
-void __init gbus_int_init_irq_types (struct gbus_int_irq_init *inits,
-                                    struct hw_interrupt_type *hw_irq_types)
-{
-       struct gbus_int_irq_init *init;
-       for (init = inits; init->name; init++) {
-               unsigned i;
-               struct hw_interrupt_type *hwit = hw_irq_types++;
-
-               hwit->typename = init->name;
-
-               hwit->startup  = gbus_int_startup_irq;
-               hwit->shutdown = gbus_int_shutdown_irq;
-               hwit->enable   = gbus_int_enable_irq;
-               hwit->disable  = gbus_int_disable_irq;
-               hwit->ack      = irq_nop;
-               hwit->end      = irq_nop;
-               
-               /* Initialize kernel IRQ infrastructure for this interrupt.  */
-               init_irq_handlers(init->base, init->num, init->interval, hwit);
-
-               /* Set the interrupt priorities.  */
-               for (i = 0; i < init->num; i++) {
-                       unsigned j;
-                       for (j = 0; j < NUM_USED_GINTS; j++)
-                               if (used_gint[j].priority > init->priority)
-                                       break;
-                       /* Wherever we stopped looking is one past the
-                          GINT we want. */
-                       gbus_int_gint[init->base + i * init->interval
-                                     - GBUS_INT_BASE_IRQ]
-                               = used_gint[j > 0 ? j - 1 : 0].gint;
-               }
-       }
-}
-
-\f
-/* Initialize IRQS.  */
-
-/* Chip interrupts (GINTn) shared among GBUS interrupts.  */
-static struct hw_interrupt_type gint_hw_itypes[NUM_USED_GINTS];
-
-
-/* GBUS interrupts themselves.  */
-
-struct gbus_int_irq_init gbus_irq_inits[] __initdata = {
-       /* First set defaults.  */
-       { "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6},
-       { 0 }
-};
-#define NUM_GBUS_IRQ_INITS (ARRAY_SIZE(gbus_irq_inits) - 1)
-
-static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
-
-
-/* Initialize GBUS interrupts.  */
-void __init gbus_int_init_irqs (void)
-{
-       unsigned i;
-
-       /* First initialize the shared gint interrupts.  */
-       for (i = 0; i < NUM_USED_GINTS; i++) {
-               unsigned gint = used_gint[i].gint;
-               struct v850e_intc_irq_init gint_irq_init[2];
-
-               /* We initialize one GINT interrupt at a time.  */
-               gint_irq_init[0].name = "GINT";
-               gint_irq_init[0].base = IRQ_GINT (gint);
-               gint_irq_init[0].num = 1;
-               gint_irq_init[0].interval = 1;
-               gint_irq_init[0].priority = used_gint[i].priority;
-
-               gint_irq_init[1].name = 0; /* Terminate the vector.  */
-
-               v850e_intc_init_irq_types (gint_irq_init, gint_hw_itypes);
-       }
-
-       /* Then the GBUS interrupts.  */
-       gbus_int_disable_irqs ();
-       gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes);
-       /* Turn on the `all enable' bits, which are ANDed with
-          individual interrupt enable bits; we only want to bother with
-          the latter.  They are the first bit in the first word of each
-          interrupt-enable area.  */
-       for (i = 0; i < NUM_USED_GINTS; i++)
-               GBUS_INT_ENABLE (0, used_gint[i].gint) = 0x1;
-}
diff --git a/arch/v850/kernel/head.S b/arch/v850/kernel/head.S
deleted file mode 100644 (file)
index c490b93..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * arch/v850/kernel/head.S -- Lowest-level startup code
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <asm/clinkage.h>
-#include <asm/current.h>
-#include <asm/entry.h>
-#include <asm/thread_info.h>
-#include <asm/irq.h>
-
-
-/* Make a slightly more convenient alias for C_SYMBOL_NAME.  */
-#define CSYM   C_SYMBOL_NAME
-
-
-       .text
-
-       // Define `mach_early_init' as a weak symbol
-       .global CSYM(mach_early_init)
-       .weak   CSYM(mach_early_init)
-
-C_ENTRY(start):
-       // Make sure interrupts are turned off, just in case
-       di
-
-#ifdef CONFIG_RESET_GUARD
-       // See if we got here via an unexpected reset
-       ld.w    RESET_GUARD, r19        // Check current value of reset guard
-       mov     RESET_GUARD_ACTIVE, r20
-       cmp     r19, r20
-       bne     1f                      // Guard was not active
-
-       // If we get here, the reset guard was active.  Load up some
-       // interesting values as arguments, and jump to the handler.
-       st.w    r0, RESET_GUARD         // Allow further resets to succeed
-       mov     lp, r6                  // Arg 0: return address
-       ld.b    KM, r7                  // Arg 1: kernel mode
-       mov     sp, r9                  // Arg 3: stack pointer
-       ld.w    KSP, r19                // maybe switch to kernel stack
-       cmp     r7, r0                  // see if already in kernel mode
-       cmov    z, r19, sp, sp          //  and switch to kernel stack if not
-       GET_CURRENT_TASK(r8)            // Arg 2: task pointer
-       jr      CSYM(unexpected_reset)
-
-1:     st.w    r20, RESET_GUARD        // Turn on reset guard
-#endif /* CONFIG_RESET_GUARD */
-
-       // Setup a temporary stack for doing pre-initialization function calls.
-       // 
-       // We can't use the initial kernel stack, because (1) it may be
-       // located in memory we're not allowed to touch, and (2) since
-       // it's in the data segment, calling memcpy to initialize that
-       // area from ROM will overwrite memcpy's return address.
-       mov     hilo(CSYM(_init_stack_end) - 4), sp
-
-       // See if there's a platform-specific early-initialization routine
-       // defined; it's a weak symbol, so it will have an address of zero if
-       // there's not.
-       mov     hilo(CSYM(mach_early_init)), r6
-       cmp     r6, r0
-       bz      3f
-
-       // There is one, so call it.  If this function is written in C, it
-       // should be very careful -- the stack pointer is valid, but very
-       // little else is (e.g., bss is not zeroed yet, and initialized data
-       // hasn't been).
-       jarl    2f, lp                  // first figure out return address
-2:     add     3f - ., lp
-       jmp     [r6]                    // do call
-3:
-
-#ifdef CONFIG_ROM_KERNEL
-       // Copy the data area from ROM to RAM
-       mov     hilo(CSYM(_rom_copy_dst_start)), r6
-       mov     hilo(CSYM(_rom_copy_src_start)), r7
-       mov     hilo(CSYM(_rom_copy_dst_end)), r8
-       sub     r6, r8
-       jarl    CSYM(memcpy), lp
-#endif
-
-       // Load the initial thread's stack, and current task pointer (in r16)
-       mov     hilo(CSYM(init_thread_union)), r19
-       movea   THREAD_SIZE, r19, sp
-       ld.w    TI_TASK[r19], CURRENT_TASK
-
-#ifdef CONFIG_TIME_BOOTUP
-       /* This stuff must come after mach_early_init, because interrupts may
-          not work until after its been called.  */
-       jarl    CSYM(highres_timer_reset), lp
-       jarl    CSYM(highres_timer_start), lp
-#endif
-
-       // Kernel stack pointer save location
-       st.w    sp, KSP
-
-       // Assert that we're in `kernel mode'
-       mov     1, r19
-       st.w    r19, KM
-
-#ifdef CONFIG_ZERO_BSS
-       // Zero bss area, since we can't rely upon any loader to do so
-       mov     hilo(CSYM(_sbss)), r6
-       mov     r0, r7
-       mov     hilo(CSYM(_ebss)), r8
-       sub     r6, r8
-       jarl    CSYM(memset), lp
-#endif
-
-       // What happens if the main kernel function returns (it shouldn't)
-       mov     hilo(CSYM(machine_halt)), lp
-
-       // Start the linux kernel.  We use an indirect jump to get extra
-       // range, because on some platforms this initial startup code
-       // (and the associated platform-specific code in mach_early_init)
-       // are located far away from the main kernel, e.g. so that they
-       // can initialize RAM first and copy the kernel or something.
-       mov     hilo(CSYM(start_kernel)), r12
-       jmp     [r12]
-C_END(start)
diff --git a/arch/v850/kernel/highres_timer.c b/arch/v850/kernel/highres_timer.c
deleted file mode 100644 (file)
index b16ad1e..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * arch/v850/kernel/highres_timer.c -- High resolution timing routines
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <asm/system.h>
-#include <asm/v850e_timer_d.h>
-#include <asm/highres_timer.h>
-
-#define HIGHRES_TIMER_USEC_SHIFT   12
-
-/* Pre-calculated constant used for converting ticks to real time
-   units.  We initialize it to prevent it being put into BSS.  */
-static u32 highres_timer_usec_prescale = 1;
-
-void highres_timer_slow_tick_irq (void) __attribute__ ((noreturn));
-void highres_timer_slow_tick_irq (void)
-{
-       /* This is an interrupt handler, so it must be very careful to
-          not to trash any registers.  At this point, the stack-pointer
-          (r3) has been saved in the chip ram location ENTRY_SP by the
-          interrupt vector, so we can use it as a scratch register; we
-          must also restore it before returning.  */
-       asm ("ld.w      %0[r0], sp;"
-            "add       1, sp;"
-            "st.w      sp, %0[r0];"
-            "ld.w      %1[r0], sp;" /* restore pre-irq stack-pointer */
-            "reti"
-            ::
-             "i" (HIGHRES_TIMER_SLOW_TICKS_ADDR),
-             "i" (ENTRY_SP_ADDR)
-            : "memory");
-}
-
-void highres_timer_reset (void)
-{
-       V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT) = 0;
-       HIGHRES_TIMER_SLOW_TICKS = 0;
-}
-
-void highres_timer_start (void)
-{
-       u32 fast_tick_rate;
-
-       /* Start hardware timer.  */
-       v850e_timer_d_configure (HIGHRES_TIMER_TIMER_D_UNIT,
-                                HIGHRES_TIMER_SLOW_TICK_RATE);
-
-       fast_tick_rate =
-               (V850E_TIMER_D_BASE_FREQ
-                >> V850E_TIMER_D_DIVLOG2 (HIGHRES_TIMER_TIMER_D_UNIT));
-
-       /* The obvious way of calculating microseconds from fast ticks
-          is to do:
-
-            usec = fast_ticks * 10^6 / fast_tick_rate
-
-          However, divisions are much slower than multiplications, and
-          the above calculation can overflow, so we do this instead:
-
-            usec = fast_ticks * (10^6 * 2^12 / fast_tick_rate) / 2^12
-
-           since we can pre-calculate (10^6 * (2^12 / fast_tick_rate))
-          and use a shift for dividing by 2^12, this avoids division,
-          and is almost as accurate (it differs by about 2 microseconds
-          at the extreme value of the fast-tick counter's ranger).  */
-       highres_timer_usec_prescale = ((1000000 << HIGHRES_TIMER_USEC_SHIFT)
-                                      / fast_tick_rate);
-
-       /* Enable the interrupt (which is hardwired to this use), and
-          give it the highest priority.  */
-       V850E_INTC_IC (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)) = 0;
-}
-
-void highres_timer_stop (void)
-{
-       /* Stop the timer.  */
-       V850E_TIMER_D_TMCD (HIGHRES_TIMER_TIMER_D_UNIT) =
-               V850E_TIMER_D_TMCD_CAE;
-       /* Disable its interrupt, just in case.  */
-       v850e_intc_disable_irq (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT));
-}
-
-inline void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks)
-{
-       int flags;
-       u32 fast_ticks_1, fast_ticks_2, _slow_ticks;
-
-       local_irq_save (flags);
-       fast_ticks_1 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
-       _slow_ticks = HIGHRES_TIMER_SLOW_TICKS;
-       fast_ticks_2 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
-       local_irq_restore (flags);
-
-       if (fast_ticks_2 < fast_ticks_1)
-               _slow_ticks++;
-
-       *slow_ticks = _slow_ticks;
-       *fast_ticks = fast_ticks_2;
-}
-
-inline void highres_timer_ticks_to_timeval (u32 slow_ticks, u32 fast_ticks,
-                                           struct timeval *tv)
-{
-       unsigned long sec, sec_rem, usec;
-
-       usec = ((fast_ticks * highres_timer_usec_prescale)
-               >> HIGHRES_TIMER_USEC_SHIFT);
-
-       sec = slow_ticks / HIGHRES_TIMER_SLOW_TICK_RATE;
-       sec_rem = slow_ticks % HIGHRES_TIMER_SLOW_TICK_RATE;
-
-       usec += sec_rem * (1000000 / HIGHRES_TIMER_SLOW_TICK_RATE);
-
-       tv->tv_sec = sec;
-       tv->tv_usec = usec;
-}
-
-void highres_timer_read (struct timeval *tv)
-{
-       u32 fast_ticks, slow_ticks;
-       highres_timer_read_ticks (&slow_ticks, &fast_ticks);
-       highres_timer_ticks_to_timeval (slow_ticks, fast_ticks, tv);
-}
diff --git a/arch/v850/kernel/init_task.c b/arch/v850/kernel/init_task.c
deleted file mode 100644 (file)
index 44b274d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * arch/v850/kernel/init_task.c -- Initial task/thread structures
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- */
-
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct fs_struct init_fs = INIT_FS;
-static struct signal_struct init_signals = INIT_SIGNALS (init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM (init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK (init_task);
-
-EXPORT_SYMBOL(init_task);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry.
- */
-union thread_union init_thread_union 
-       __attribute__((__section__(".data.init_task"))) =
-               { INIT_THREAD_INFO(init_task) };
diff --git a/arch/v850/kernel/intv.S b/arch/v850/kernel/intv.S
deleted file mode 100644 (file)
index 671e4c6..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * arch/v850/kernel/intv.S -- Interrupt vectors
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <asm/clinkage.h>
-#include <asm/irq.h>
-#include <asm/machdep.h>
-#include <asm/entry.h>
-
-#ifdef CONFIG_V850E_HIGHRES_TIMER
-#include <asm/highres_timer.h>
-#endif
-
-/* Jump to an interrupt/trap handler.  These handlers (defined in entry.S)
-   expect the stack-pointer to be saved in ENTRY_SP, so we use sp to do an
-   indirect jump (which avoids problems when the handler is more than a signed
-   22-bit offset away).  */
-#define JUMP_TO_HANDLER(name, sp_save_loc)                                   \
-       st.w    sp, sp_save_loc;                                              \
-       mov     hilo(name), sp;                                               \
-       jmp     [sp]
-
-
-       /* Reset vector.  */
-       .section        .intv.reset, "ax"
-       .org    0x0
-       mov     hilo(C_SYMBOL_NAME(start)), r1;
-       jmp     [r1]
-
-
-       /* Generic interrupt vectors.  */
-       .section        .intv.common, "ax"
-       .balign 0x10
-       JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP)     // 0x10 - NMI0
-       .balign 0x10
-       JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP)     // 0x20 - NMI1
-       .balign 0x10
-       JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP)     // 0x30 - NMI2
-       
-       .balign 0x10
-       JUMP_TO_HANDLER (trap, ENTRY_SP)        // 0x40 - TRAP0n
-       .balign 0x10
-       JUMP_TO_HANDLER (trap, ENTRY_SP)        // 0x50 - TRAP1n
-
-       .balign 0x10
-       JUMP_TO_HANDLER (dbtrap, ENTRY_SP)      // 0x60 - Illegal op / DBTRAP insn
-
-
-       /* Hardware interrupt vectors.  */
-       .section        .intv.mach, "ax"
-       .org    0x0
-
-#if defined (CONFIG_V850E_HIGHRES_TIMER) && defined (IRQ_INTCMD)
-
-       /* Interrupts before the highres timer interrupt.  */
-       .rept   IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)
-       .balign 0x10
-       JUMP_TO_HANDLER (irq, ENTRY_SP)
-       .endr
-
-       /* The highres timer interrupt.  */
-       .balign 0x10
-       JUMP_TO_HANDLER (C_SYMBOL_NAME (highres_timer_slow_tick_irq), ENTRY_SP)
-
-       /* Interrupts after the highres timer interrupt.  */
-       .rept   NUM_CPU_IRQS - IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT) - 1
-       .balign 0x10
-       JUMP_TO_HANDLER (irq, ENTRY_SP)
-       .endr
-
-#else /* No highres timer */
-
-       .rept   NUM_CPU_IRQS
-       .balign 0x10
-       JUMP_TO_HANDLER (irq, ENTRY_SP)
-       .endr
-
-#endif /* Highres timer */
diff --git a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c
deleted file mode 100644 (file)
index 858c458..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * arch/v850/kernel/irq.c -- High-level interrupt handling
- *
- *  Copyright (C) 2001,02,03,04,05  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03,04,05  Miles Bader <miles@gnu.org>
- *  Copyright (C) 1994-2000  Ralf Baechle
- *  Copyright (C) 1992  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.
- *
- * This file was was derived from the mips version, arch/mips/kernel/irq.c
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/irq.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/random.h>
-#include <linux/seq_file.h>
-
-#include <asm/system.h>
-
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves, it doesn't deserve
- * a generic callback i think.
- */
-void ack_bad_irq(unsigned int irq)
-{
-       printk("received IRQ %d with unknown interrupt type\n", irq);
-}
-
-volatile unsigned long irq_err_count, spurious_count;
-
-/*
- * Generic, controller-independent functions:
- */
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-       int irq = *(loff_t *) v;
-
-       if (irq == 0) {
-               int cpu;
-               seq_puts(p, "           ");
-               for (cpu=0; cpu < 1 /*smp_num_cpus*/; cpu++)
-                       seq_printf(p, "CPU%d       ", cpu);
-               seq_putc(p, '\n');
-       }
-
-       if (irq < NR_IRQS) {
-               unsigned long flags;
-               struct irqaction *action;
-
-               spin_lock_irqsave(&irq_desc[irq].lock, flags);
-
-               action = irq_desc[irq].action;
-               if (action) {
-                       int j;
-                       int count = 0;
-                       int num = -1;
-                       const char *type_name = irq_desc[irq].chip->typename;
-
-                       for (j = 0; j < NR_IRQS; j++)
-                               if (irq_desc[j].chip->typename == type_name){
-                                       if (irq == j)
-                                               num = count;
-                                       count++;
-                               }
-
-                       seq_printf(p, "%3d: ",irq);
-                       seq_printf(p, "%10u ", kstat_irqs(irq));
-                       if (count > 1) {
-                               int prec = (num >= 100 ? 3 : num >= 10 ? 2 : 1);
-                               seq_printf(p, " %*s%d", 14 - prec,
-                                          type_name, num);
-                       } else
-                               seq_printf(p, " %14s", type_name);
-               
-                       seq_printf(p, "  %s", action->name);
-                       for (action=action->next; action; action = action->next)
-                               seq_printf(p, ", %s", action->name);
-                       seq_putc(p, '\n');
-               }
-
-               spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
-       } else if (irq == NR_IRQS)
-               seq_printf(p, "ERR: %10lu\n", irq_err_count);
-
-       return 0;
-}
-
-/* Handle interrupt IRQ.  REGS are the registers at the time of ther
-   interrupt.  */
-unsigned int handle_irq (int irq, struct pt_regs *regs)
-{
-       irq_enter();
-       __do_IRQ(irq, regs);
-       irq_exit();
-       return 1;
-}
-
-/* Initialize irq handling for IRQs.
-   BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL
-   to IRQ_TYPE.  An IRQ_TYPE of 0 means to use a generic interrupt type.  */
-void __init
-init_irq_handlers (int base_irq, int num, int interval,
-                  struct hw_interrupt_type *irq_type)
-{
-       while (num-- > 0) {
-               irq_desc[base_irq].status  = IRQ_DISABLED;
-               irq_desc[base_irq].action  = NULL;
-               irq_desc[base_irq].depth   = 1;
-               irq_desc[base_irq].chip = irq_type;
-               base_irq += interval;
-       }
-}
diff --git a/arch/v850/kernel/ma.c b/arch/v850/kernel/ma.c
deleted file mode 100644 (file)
index 143774d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * arch/v850/kernel/ma.c -- V850E/MA series of cpu chips
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-#include <asm/v850e_timer_d.h>
-
-#include "mach.h"
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
-       /* Start hardware timer.  */
-       v850e_timer_d_configure (0, HZ);
-       /* Install timer interrupt handler.  */
-       setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
-       { "IRQ", 0,             NUM_MACH_IRQS,  1, 7 },
-       { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
-       { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 },
-       { "CSI", IRQ_INTCSI(0), IRQ_INTCSI_NUM, 4, 4 },
-       { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 4, 3 },
-       { "SR",  IRQ_INTSR(0),  IRQ_INTSR_NUM,  4, 4 },
-       { "ST",  IRQ_INTST(0),  IRQ_INTST_NUM,  4, 5 },
-       { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-/* Initialize MA chip interrupts.  */
-void __init ma_init_irqs (void)
-{
-       v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-/* Called before configuring an on-chip UART.  */
-void ma_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
-       /* We only know about the first two UART channels (though
-          specific chips may have more).  */
-       if (chan < 2) {
-               unsigned bits = 0x3 << (chan * 3);
-               /* Specify that the relevant pins on the chip should do
-                  serial I/O, not direct I/O.  */
-               MA_PORT4_PMC |= bits;
-               /* Specify that we're using the UART, not the CSI device.  */
-               MA_PORT4_PFC |= bits;
-       }
-}
diff --git a/arch/v850/kernel/mach.c b/arch/v850/kernel/mach.c
deleted file mode 100644 (file)
index b9db278..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * arch/v850/kernel/mach.c -- Defaults for some things defined by "mach.h"
- *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include "mach.h"
-
-/* Called with each timer tick, if non-zero.  */
-void (*mach_tick)(void) = 0;
diff --git a/arch/v850/kernel/mach.h b/arch/v850/kernel/mach.h
deleted file mode 100644 (file)
index 9e0e481..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * arch/v850/kernel/mach.h -- Machine-dependent functions used by v850 port
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MACH_H__
-#define __V850_MACH_H__
-
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/seq_file.h>
-
-#include <asm/ptrace.h>
-#include <asm/entry.h>
-#include <asm/clinkage.h>
-
-void mach_setup (char **cmdline);
-void mach_gettimeofday (struct timespec *tv);
-void mach_sched_init (struct irqaction *timer_action);
-void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len);
-void mach_init_irqs (void);
-
-/* If defined, is called very early in the kernel initialization.  The
-   stack pointer is valid, but very little has been initialized (e.g.,
-   bss is not zeroed yet) when this is called, so care must taken.  */
-void mach_early_init (void);
-
-/* If defined, called after the bootmem allocator has been initialized,
-   to allow the platform-dependent code to reserve any areas of RAM that
-   the kernel shouldn't touch.  */
-void mach_reserve_bootmem (void) __attribute__ ((__weak__));
-
-/* Called with each timer tick, if non-zero.  */
-extern void (*mach_tick) (void);
-
-/* The following establishes aliases for various mach_ functions to the
-   name by which the rest of the kernel calls them.  These statements
-   should only have an effect in the file that defines the actual functions. */
-#define MACH_ALIAS(to, from)                                                 \
-   asm (".global " macrology_stringify (C_SYMBOL_NAME (to)) ";"                      \
-       macrology_stringify (C_SYMBOL_NAME (to))                              \
-       " = " macrology_stringify (C_SYMBOL_NAME (from)))
-/* e.g.: MACH_ALIAS (kernel_name,      arch_spec_name);  */
-
-#endif /* __V850_MACH_H__ */
diff --git a/arch/v850/kernel/me2.c b/arch/v850/kernel/me2.c
deleted file mode 100644 (file)
index 007115d..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * arch/v850/kernel/me2.c -- V850E/ME2 chip-specific support
- *
- *  Copyright (C) 2003  NEC Corporation
- *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-#include <asm/v850e_timer_d.h>
-
-#include "mach.h"
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
-       /* Start hardware timer.  */
-       v850e_timer_d_configure (0, HZ);
-       /* Install timer interrupt handler.  */
-       setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
-       { "IRQ",    0,                NUM_CPU_IRQS,      1, 7 },
-       { "INTP",   IRQ_INTP(0),      IRQ_INTP_NUM,      1, 5 },
-       { "CMD",    IRQ_INTCMD(0),    IRQ_INTCMD_NUM,    1, 3 },
-       { "UBTIRE", IRQ_INTUBTIRE(0), IRQ_INTUBTIRE_NUM, 5, 4 },
-       { "UBTIR",  IRQ_INTUBTIR(0),  IRQ_INTUBTIR_NUM,  5, 4 },
-       { "UBTIT",  IRQ_INTUBTIT(0),  IRQ_INTUBTIT_NUM,  5, 4 },
-       { "UBTIF",  IRQ_INTUBTIF(0),  IRQ_INTUBTIF_NUM,  5, 4 },
-       { "UBTITO", IRQ_INTUBTITO(0), IRQ_INTUBTITO_NUM, 5, 4 },
-       { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-/* Initialize V850E/ME2 chip interrupts.  */
-void __init me2_init_irqs (void)
-{
-       v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-/* Called before configuring an on-chip UART.  */
-void me2_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
-       if (chan == 0) {
-               /* Specify that the relevant pins on the chip should do
-                  serial I/O, not direct I/O.  */
-               ME2_PORT1_PMC |= 0xC;
-               /* Specify that we're using the UART, not the CSI device. */
-               ME2_PORT1_PFC |= 0xC;
-       } else if (chan == 1) {
-               /* Specify that the relevant pins on the chip should do
-                  serial I/O, not direct I/O.  */
-               ME2_PORT2_PMC |= 0x6;
-               /* Specify that we're using the UART, not the CSI device. */
-               ME2_PORT2_PFC |= 0x6;
-       }
-}
diff --git a/arch/v850/kernel/memcons.c b/arch/v850/kernel/memcons.c
deleted file mode 100644 (file)
index 92f514f..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * arch/v850/kernel/memcons.c -- Console I/O to a memory buffer
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/init.h>
-
-/* If this device is enabled, the linker map should define start and
-   end points for its buffer. */
-extern char memcons_output[], memcons_output_end;
-
-/* Current offset into the buffer.  */
-static unsigned long memcons_offs = 0;
-
-/* Spinlock protecting memcons_offs.  */
-static DEFINE_SPINLOCK(memcons_lock);
-
-
-static size_t write (const char *buf, size_t len)
-{
-       unsigned long flags;
-       char *point;
-
-       spin_lock_irqsave (memcons_lock, flags);
-
-       point = memcons_output + memcons_offs;
-       if (point + len >= &memcons_output_end) {
-               len = &memcons_output_end - point;
-               memcons_offs = 0;
-       } else
-               memcons_offs += len;
-
-       spin_unlock_irqrestore (memcons_lock, flags);
-
-       memcpy (point, buf, len);
-
-       return len;
-}
-
-\f
-/*  Low-level console. */
-
-static void memcons_write (struct console *co, const char *buf, unsigned len)
-{
-       while (len > 0)
-               len -= write (buf, len);
-}
-
-static struct tty_driver *tty_driver;
-
-static struct tty_driver *memcons_device (struct console *co, int *index)
-{
-       *index = co->index;
-       return tty_driver;
-}
-
-static struct console memcons =
-{
-    .name      = "memcons",
-    .write     = memcons_write,
-    .device    = memcons_device,
-    .flags     = CON_PRINTBUFFER,
-    .index     = -1,
-};
-
-void memcons_setup (void)
-{
-       register_console (&memcons);
-       printk (KERN_INFO "Console: static memory buffer (memcons)\n");
-}
-\f
-/* Higher level TTY interface.  */
-
-int memcons_tty_open (struct tty_struct *tty, struct file *filp)
-{
-       return 0;
-}
-
-int memcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int len)
-{
-       return write (buf, len);
-}
-
-int memcons_tty_write_room (struct tty_struct *tty)
-{
-       return &memcons_output_end - (memcons_output + memcons_offs);
-}
-
-int memcons_tty_chars_in_buffer (struct tty_struct *tty)
-{
-       /* We have no buffer.  */
-       return 0;
-}
-
-static const struct tty_operations ops = {
-       .open = memcons_tty_open,
-       .write = memcons_tty_write,
-       .write_room = memcons_tty_write_room,
-       .chars_in_buffer = memcons_tty_chars_in_buffer,
-};
-
-int __init memcons_tty_init (void)
-{
-       int err;
-       struct tty_driver *driver = alloc_tty_driver(1);
-       if (!driver)
-               return -ENOMEM;
-
-       driver->name = "memcons";
-       driver->major = TTY_MAJOR;
-       driver->minor_start = 64;
-       driver->type = TTY_DRIVER_TYPE_SYSCONS;
-       driver->init_termios = tty_std_termios;
-       tty_set_operations(driver, &ops);
-       err = tty_register_driver(driver);
-       if (err) {
-               put_tty_driver(driver);
-               return err;
-       }
-       tty_driver = driver;
-       return 0;
-}
-__initcall (memcons_tty_init);
diff --git a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c
deleted file mode 100644 (file)
index 64aeb3e..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * arch/v850/kernel/module.c -- Architecture-specific module functions
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *  Copyright (C) 2001,03  Rusty Russell
- *
- * 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.
- *
- * Written by Miles Bader <miles@gnu.org>
- *
- * Derived in part from arch/ppc/kernel/module.c
- */
-
-#include <linux/kernel.h>
-#include <linux/vmalloc.h>
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt , ...)
-#endif
-
-void *module_alloc (unsigned long size)
-{
-       return size == 0 ? 0 : vmalloc (size);
-}
-
-void module_free (struct module *mod, void *module_region)
-{
-       vfree (module_region);
-       /* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
-}
-
-int module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
-                    struct module *mod)
-{
-       return 0;
-}
-
-/* Count how many different relocations (different symbol, different
-   addend) */
-static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
-{
-       unsigned int i, j, ret = 0;
-
-       /* Sure, this is order(n^2), but it's usually short, and not
-           time critical */
-       for (i = 0; i < num; i++) {
-               for (j = 0; j < i; j++) {
-                       /* If this addend appeared before, it's
-                           already been counted */
-                       if (ELF32_R_SYM(rela[i].r_info)
-                           == ELF32_R_SYM(rela[j].r_info)
-                           && rela[i].r_addend == rela[j].r_addend)
-                               break;
-               }
-               if (j == i) ret++;
-       }
-       return ret;
-}
-
-/* Get the potential trampolines size required of the init and
-   non-init sections */
-static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
-                                 const Elf32_Shdr *sechdrs,
-                                 const char *secstrings,
-                                 int is_init)
-{
-       unsigned long ret = 0;
-       unsigned i;
-
-       /* Everything marked ALLOC (this includes the exported
-           symbols) */
-       for (i = 1; i < hdr->e_shnum; i++) {
-               /* If it's called *.init*, and we're not init, we're
-                   not interested */
-               if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
-                   != is_init)
-                       continue;
-
-               if (sechdrs[i].sh_type == SHT_RELA) {
-                       DEBUGP("Found relocations in section %u\n", i);
-                       DEBUGP("Ptr: %p.  Number: %u\n",
-                              (void *)hdr + sechdrs[i].sh_offset,
-                              sechdrs[i].sh_size / sizeof(Elf32_Rela));
-                       ret += count_relocs((void *)hdr
-                                            + sechdrs[i].sh_offset,
-                                            sechdrs[i].sh_size
-                                            / sizeof(Elf32_Rela))
-                               * sizeof(struct v850_plt_entry);
-               }
-       }
-
-       return ret;
-}
-
-int module_frob_arch_sections(Elf32_Ehdr *hdr,
-                             Elf32_Shdr *sechdrs,
-                             char *secstrings,
-                             struct module *me)
-{
-       unsigned int i;
-
-       /* Find .plt and .pltinit sections */
-       for (i = 0; i < hdr->e_shnum; i++) {
-               if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
-                       me->arch.init_plt_section = i;
-               else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
-                       me->arch.core_plt_section = i;
-       }
-       if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
-               printk("Module doesn't contain .plt or .plt.init sections.\n");
-               return -ENOEXEC;
-       }
-
-       /* Override their sizes */
-       sechdrs[me->arch.core_plt_section].sh_size
-               = get_plt_size(hdr, sechdrs, secstrings, 0);
-       sechdrs[me->arch.init_plt_section].sh_size
-               = get_plt_size(hdr, sechdrs, secstrings, 1);
-       return 0;
-}
-
-int apply_relocate (Elf32_Shdr *sechdrs, const char *strtab,
-                   unsigned int symindex, unsigned int relsec,
-                   struct module *mod)
-{
-       printk ("Barf\n");
-       return -ENOEXEC;
-}
-
-/* Set up a trampoline in the PLT to bounce us to the distant function */
-static uint32_t do_plt_call (void *location, Elf32_Addr val,
-                            Elf32_Shdr *sechdrs, struct module *mod)
-{
-       struct v850_plt_entry *entry;
-       /* Instructions used to do the indirect jump.  */
-       uint32_t tramp[2];
-
-       /* We have to trash a register, so we assume that any control
-          transfer more than 21-bits away must be a function call
-          (so we can use a call-clobbered register).  */
-       tramp[0] = 0x0621 + ((val & 0xffff) << 16);   /* mov sym, r1 ... */
-       tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
-
-       /* Init, or core PLT? */
-       if (location >= mod->module_core
-           && location < mod->module_core + mod->core_size)
-               entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
-       else
-               entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
-
-       /* Find this entry, or if that fails, the next avail. entry */
-       while (entry->tramp[0])
-               if (entry->tramp[0] == tramp[0] && entry->tramp[1] == tramp[1])
-                       return (uint32_t)entry;
-               else
-                       entry++;
-
-       entry->tramp[0] = tramp[0];
-       entry->tramp[1] = tramp[1];
-
-       return (uint32_t)entry;
-}
-
-int apply_relocate_add (Elf32_Shdr *sechdrs, const char *strtab,
-                       unsigned int symindex, unsigned int relsec,
-                       struct module *mod)
-{
-       unsigned int i;
-       Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
-
-       DEBUGP ("Applying relocate section %u to %u\n", relsec,
-               sechdrs[relsec].sh_info);
-
-       for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) {
-               /* This is where to make the change */
-               uint32_t *loc
-                       = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-                          + rela[i].r_offset);
-               /* This is the symbol it is referring to.  Note that all
-                  undefined symbols have been resolved.  */
-               Elf32_Sym *sym
-                       = ((Elf32_Sym *)sechdrs[symindex].sh_addr
-                          + ELF32_R_SYM (rela[i].r_info));
-               uint32_t val = sym->st_value + rela[i].r_addend;
-
-               switch (ELF32_R_TYPE (rela[i].r_info)) {
-               case R_V850_32:
-                       /* We write two shorts instead of a long because even
-                          32-bit insns only need half-word alignment, but
-                          32-bit data writes need to be long-word aligned.  */
-                       val += ((uint16_t *)loc)[0];
-                       val += ((uint16_t *)loc)[1] << 16;
-                       ((uint16_t *)loc)[0] = val & 0xffff;
-                       ((uint16_t *)loc)[1] = (val >> 16) & 0xffff;
-                       break;
-
-               case R_V850_22_PCREL:
-                       /* Maybe jump indirectly via a PLT table entry.  */
-                       if ((int32_t)(val - (uint32_t)loc) > 0x1fffff
-                           || (int32_t)(val - (uint32_t)loc) < -0x200000)
-                               val = do_plt_call (loc, val, sechdrs, mod);
-
-                       val -= (uint32_t)loc;
-
-                       /* We write two shorts instead of a long because
-                          even 32-bit insns only need half-word alignment,
-                          but 32-bit data writes need to be long-word
-                          aligned.  */
-                       ((uint16_t *)loc)[0] =
-                               (*(uint16_t *)loc & 0xffc0) /* opcode + reg */
-                               | ((val >> 16) & 0xffc03f); /* offs high */
-                       ((uint16_t *)loc)[1] =
-                               (val & 0xffff);             /* offs low */
-                       break;
-
-               default:
-                       printk (KERN_ERR "module %s: Unknown reloc: %u\n",
-                               mod->name, ELF32_R_TYPE (rela[i].r_info));
-                       return -ENOEXEC;
-               }
-       }
-
-       return 0;
-}
-
-void
-module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c
deleted file mode 100644 (file)
index e4a4b8e..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * arch/v850/kernel/process.c -- Arch-dependent process handling
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/reboot.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
-
-extern void ret_from_fork (void);
-
-
-/* The idle loop.  */
-static void default_idle (void)
-{
-       while (! need_resched ())
-               asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
-}
-
-void (*idle)(void) = default_idle;
-
-/*
- * The idle thread. There's no useful work to be
- * done, so just try to conserve power and have a
- * low exit latency (ie sit in a loop waiting for
- * somebody to say that they'd like to reschedule)
- */
-void cpu_idle (void)
-{
-       /* endless idle loop with no priority at all */
-       while (1) {
-               while (!need_resched())
-                       (*idle) ();
-
-               preempt_enable_no_resched();
-               schedule();
-               preempt_disable();
-       }
-}
-
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process (ie the swapper or direct descendants who
- * haven't done an "execve()") should use this: it will work within a system
- * call from a "real" process, but the process memory space will not be free'd
- * until both the parent and the child have exited.
- */
-int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
-{
-       register mm_segment_t fs = get_fs ();
-       register unsigned long syscall asm (SYSCALL_NUM);
-       register unsigned long arg0 asm (SYSCALL_ARG0);
-       register unsigned long ret asm (SYSCALL_RET);
-
-       set_fs (KERNEL_DS);
-
-       /* Clone this thread.  Note that we don't pass the clone syscall's
-          second argument -- it's ignored for calls from kernel mode (the
-          child's SP is always set to the top of the kernel stack).  */
-       arg0 = flags | CLONE_VM;
-       syscall = __NR_clone;
-       asm volatile ("trap " SYSCALL_SHORT_TRAP
-                     : "=r" (ret), "=r" (syscall)
-                     : "1" (syscall), "r" (arg0)
-                     : SYSCALL_SHORT_CLOBBERS);
-
-       if (ret == 0) {
-               /* In child thread, call FN and exit.  */
-               arg0 = (*fn) (arg);
-               syscall = __NR_exit;
-               asm volatile ("trap " SYSCALL_SHORT_TRAP
-                             : "=r" (ret), "=r" (syscall)
-                             : "1" (syscall), "r" (arg0)
-                             : SYSCALL_SHORT_CLOBBERS);
-       }
-
-       /* In parent.  */
-       set_fs (fs);
-
-       return ret;
-}
-
-void flush_thread (void)
-{
-       set_fs (USER_DS);
-}
-
-int copy_thread (int nr, unsigned long clone_flags,
-                unsigned long stack_start, unsigned long stack_size,
-                struct task_struct *p, struct pt_regs *regs)
-{
-       /* Start pushing stuff from the top of the child's kernel stack.  */
-       unsigned long orig_ksp = task_tos(p);
-       unsigned long ksp = orig_ksp;
-       /* We push two `state save' stack fames (see entry.S) on the new
-          kernel stack:
-            1) The innermost one is what switch_thread would have
-               pushed, and is used when we context switch to the child
-               thread for the first time.  It's set up to return to
-               ret_from_fork in entry.S.
-            2) The outermost one (nearest the top) is what a syscall
-               trap would have pushed, and is set up to return to the
-               same location as the parent thread, but with a return
-               value of 0. */
-       struct pt_regs *child_switch_regs, *child_trap_regs;
-
-       /* Trap frame.  */
-       ksp -= STATE_SAVE_SIZE;
-       child_trap_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
-       /* Switch frame.  */
-       ksp -= STATE_SAVE_SIZE;
-       child_switch_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
-
-       /* First copy parent's register state to child.  */
-       *child_switch_regs = *regs;
-       *child_trap_regs = *regs;
-
-       /* switch_thread returns to the restored value of the lp
-          register (r31), so we make that the place where we want to
-          jump when the child thread begins running.  */
-       child_switch_regs->gpr[GPR_LP] = (v850_reg_t)ret_from_fork;
-
-       if (regs->kernel_mode)
-               /* Since we're returning to kernel-mode, make sure the child's
-                  stored kernel stack pointer agrees with what the actual
-                  stack pointer will be at that point (the trap return code
-                  always restores the SP, even when returning to
-                  kernel-mode).  */
-               child_trap_regs->gpr[GPR_SP] = orig_ksp;
-       else
-               /* Set the child's user-mode stack-pointer (the name
-                  `stack_start' is a misnomer, it's just the initial SP
-                  value).  */
-               child_trap_regs->gpr[GPR_SP] = stack_start;
-
-       /* Thread state for the child (everything else is on the stack).  */
-       p->thread.ksp = ksp;
-
-       return 0;
-}
-
-/*
- * sys_execve() executes a new program.
- */
-int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs)
-{
-       char *filename = getname (name);
-       int error = PTR_ERR (filename);
-
-       if (! IS_ERR (filename)) {
-               error = do_execve (filename, argv, envp, regs);
-               putname (filename);
-       }
-
-       return error;
-}
-
-
-/*
- * These bracket the sleeping functions..
- */
-#define first_sched    ((unsigned long)__sched_text_start)
-#define last_sched     ((unsigned long)__sched_text_end)
-
-unsigned long get_wchan (struct task_struct *p)
-{
-#if 0  /* Barf.  Figure out the stack-layout later.  XXX  */
-       unsigned long fp, pc;
-       int count = 0;
-
-       if (!p || p == current || p->state == TASK_RUNNING)
-               return 0;
-
-       pc = thread_saved_pc (p);
-
-       /* This quite disgusting function walks up the stack, following
-          saved return address, until it something that's out of bounds
-          (as defined by `first_sched' and `last_sched').  It then
-          returns the last PC that was in-bounds.  */
-       do {
-               if (fp < stack_page + sizeof (struct task_struct) ||
-                   fp >= 8184+stack_page)
-                       return 0;
-               pc = ((unsigned long *)fp)[1];
-               if (pc < first_sched || pc >= last_sched)
-                       return pc;
-               fp = *(unsigned long *) fp;
-       } while (count++ < 16);
-#endif
-
-       return 0;
-}
diff --git a/arch/v850/kernel/procfs.c b/arch/v850/kernel/procfs.c
deleted file mode 100644 (file)
index e433cde..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * arch/v850/kernel/procfs.c -- Introspection functions for /proc filesystem
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include "mach.h"
-
-static int cpuinfo_print (struct seq_file *m, void *v)
-{
-       extern unsigned long loops_per_jiffy;
-       
-       seq_printf (m, "CPU-Family:     v850\nCPU-Arch: %s\n", CPU_ARCH);
-
-#ifdef CPU_MODEL_LONG
-       seq_printf (m, "CPU-Model:      %s (%s)\n", CPU_MODEL, CPU_MODEL_LONG);
-#else
-       seq_printf (m, "CPU-Model:      %s\n", CPU_MODEL);
-#endif
-
-#ifdef CPU_CLOCK_FREQ
-       seq_printf (m, "CPU-Clock:      %ld (%ld MHz)\n",
-                   (long)CPU_CLOCK_FREQ,
-                   (long)CPU_CLOCK_FREQ / 1000000);
-#endif
-
-       seq_printf (m, "BogoMips:       %lu.%02lu\n",
-                   loops_per_jiffy/(500000/HZ),
-                   (loops_per_jiffy/(5000/HZ)) % 100);
-
-#ifdef PLATFORM_LONG
-       seq_printf (m, "Platform:       %s (%s)\n", PLATFORM, PLATFORM_LONG);
-#elif defined (PLATFORM)
-       seq_printf (m, "Platform:       %s\n", PLATFORM);
-#endif
-
-       return 0;
-}
-
-static void *cpuinfo_start (struct seq_file *m, loff_t *pos)
-{
-       return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
-}
-
-static void *cpuinfo_next (struct seq_file *m, void *v, loff_t *pos)
-{
-       ++*pos;
-       return cpuinfo_start (m, pos);
-}
-
-static void cpuinfo_stop (struct seq_file *m, void *v)
-{
-}
-
-const struct seq_operations cpuinfo_op = {
-       .start  = cpuinfo_start,
-       .next   = cpuinfo_next,
-       .stop   = cpuinfo_stop,
-       .show   = cpuinfo_print
-};
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
deleted file mode 100644 (file)
index a458ac9..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * arch/v850/kernel/ptrace.c -- `ptrace' system call
- *
- *  Copyright (C) 2002,03,04  NEC Electronics Corporation
- *  Copyright (C) 2002,03,04  Miles Bader <miles@gnu.org>
- *
- * Derived from arch/mips/kernel/ptrace.c:
- *
- *  Copyright (C) 1992 Ross Biro
- *  Copyright (C) Linus Torvalds
- *  Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
- *  Copyright (C) 1996 David S. Miller
- *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- *  Copyright (C) 1999 MIPS Technologies, 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/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/signal.h>
-
-#include <asm/errno.h>
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-
-/* Returns the address where the register at REG_OFFS in P is stashed away.  */
-static v850_reg_t *reg_save_addr (unsigned reg_offs, struct task_struct *t)
-{
-       struct pt_regs *regs;
-
-       /* Three basic cases:
-
-          (1) A register normally saved before calling the scheduler, is
-              available in the kernel entry pt_regs structure at the top
-              of the kernel stack.  The kernel trap/irq exit path takes
-              care to save/restore almost all registers for ptrace'd
-              processes.
-
-          (2) A call-clobbered register, where the process P entered the
-              kernel via [syscall] trap, is not stored anywhere; that's
-              OK, because such registers are not expected to be preserved
-              when the trap returns anyway (so we don't actually bother to
-              test for this case).
-
-          (3) A few registers not used at all by the kernel, and so
-              normally never saved except by context-switches, are in the
-              context switch state.  */
-
-       if (reg_offs == PT_CTPC || reg_offs == PT_CTPSW || reg_offs == PT_CTBP)
-               /* Register saved during context switch.  */
-               regs = thread_saved_regs (t);
-       else
-               /* Register saved during kernel entry (or not available).  */
-               regs = task_pt_regs (t);
-
-       return (v850_reg_t *)((char *)regs + reg_offs);
-}
-
-/* Set the bits SET and clear the bits CLEAR in the v850e DIR
-   (`debug information register').  Returns the new value of DIR.  */
-static inline v850_reg_t set_dir (v850_reg_t set, v850_reg_t clear)
-{
-       register v850_reg_t rval asm ("r10");
-       register v850_reg_t arg0 asm ("r6") = set;
-       register v850_reg_t arg1 asm ("r7") = clear;
-
-       /* The dbtrap handler has exactly this functionality when called
-          from kernel mode.  0xf840 is a `dbtrap' insn.  */
-       asm (".short 0xf840" : "=r" (rval) : "r" (arg0), "r" (arg1));
-
-       return rval;
-}
-
-/* Makes sure hardware single-stepping is (globally) enabled.
-   Returns true if successful.  */
-static inline int enable_single_stepping (void)
-{
-       static int enabled = 0; /* Remember whether we already did it.  */
-       if (! enabled) {
-               /* Turn on the SE (`single-step enable') bit, 0x100, in the
-                  DIR (`debug information register').  This may fail if a
-                  processor doesn't support it or something.  We also try
-                  to clear bit 0x40 (`INI'), which is necessary to use the
-                  debug stuff on the v850e2; on the v850e, clearing 0x40
-                  shouldn't cause any problem.  */
-               v850_reg_t dir = set_dir (0x100, 0x40);
-               /* Make sure it really got set.  */
-               if (dir & 0x100)
-                       enabled = 1;
-       }
-       return enabled;
-}
-
-/* Try to set CHILD's single-step flag to VAL.  Returns true if successful.  */
-static int set_single_step (struct task_struct *t, int val)
-{
-       v850_reg_t *psw_addr = reg_save_addr(PT_PSW, t);
-       if (val) {
-               /* Make sure single-stepping is enabled.  */
-               if (! enable_single_stepping ())
-                       return 0;
-               /* Set T's single-step flag.  */
-               *psw_addr |= 0x800;
-       } else
-               *psw_addr &= ~0x800;
-       return 1;
-}
-
-long arch_ptrace(struct task_struct *child, long request, long addr, long data)
-{
-       int rval;
-
-       switch (request) {
-               unsigned long val;
-
-       case PTRACE_PEEKTEXT: /* read word at location addr. */
-       case PTRACE_PEEKDATA:
-               rval = generic_ptrace_peekdata(child, addr, data);
-               goto out;
-
-       case PTRACE_POKETEXT: /* write the word at location addr. */
-       case PTRACE_POKEDATA:
-               rval = generic_ptrace_pokedata(child, addr, data);
-               goto out;
-
-       /* Read/write the word at location ADDR in the registers.  */
-       case PTRACE_PEEKUSR:
-       case PTRACE_POKEUSR:
-               rval = 0;
-               if (addr >= PT_SIZE && request == PTRACE_PEEKUSR) {
-                       /* Special requests that don't actually correspond
-                          to offsets in struct pt_regs.  */
-                       if (addr == PT_TEXT_ADDR)
-                               val = child->mm->start_code;
-                       else if (addr == PT_DATA_ADDR)
-                               val = child->mm->start_data;
-                       else if (addr == PT_TEXT_LEN)
-                               val = child->mm->end_code
-                                       - child->mm->start_code;
-                       else
-                               rval = -EIO;
-               } else if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
-                       v850_reg_t *reg_addr = reg_save_addr(addr, child);
-                       if (request == PTRACE_PEEKUSR)
-                               val = *reg_addr;
-                       else
-                               *reg_addr = data;
-               } else
-                       rval = -EIO;
-
-               if (rval == 0 && request == PTRACE_PEEKUSR)
-                       rval = put_user (val, (unsigned long *)data);
-               goto out;
-
-       /* Continue and stop at next (return from) syscall */
-       case PTRACE_SYSCALL:
-       /* Restart after a signal.  */
-       case PTRACE_CONT:
-       /* Execute a single instruction. */
-       case PTRACE_SINGLESTEP:
-               rval = -EIO;
-               if (!valid_signal(data))
-                       break;
-
-               /* Turn CHILD's single-step flag on or off.  */
-               if (! set_single_step (child, request == PTRACE_SINGLESTEP))
-                       break;
-
-               if (request == PTRACE_SYSCALL)
-                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               else
-                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
-               child->exit_code = data;
-               wake_up_process(child);
-               rval = 0;
-               break;
-
-       /*
-        * make the child exit.  Best I can do is send it a sigkill.
-        * perhaps it should be put in the status that it wants to
-        * exit.
-        */
-       case PTRACE_KILL:
-               rval = 0;
-               if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
-                       break;
-               child->exit_code = SIGKILL;
-               wake_up_process(child);
-               break;
-
-       case PTRACE_DETACH: /* detach a process that was attached. */
-               set_single_step (child, 0);  /* Clear single-step flag */
-               rval = ptrace_detach(child, data);
-               break;
-
-       default:
-               rval = -EIO;
-               goto out;
-       }
- out:
-       return rval;
-}
-
-asmlinkage void syscall_trace(void)
-{
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
-       if (!(current->ptrace & PT_PTRACED))
-               return;
-       /* The 0x80 provides a way for the tracing parent to distinguish
-          between a syscall stop and SIGTRAP delivery */
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                ? 0x80 : 0));
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
-       }
-}
-
-void ptrace_disable (struct task_struct *child)
-{
-       /* nothing to do */
-}
diff --git a/arch/v850/kernel/rte_cb.c b/arch/v850/kernel/rte_cb.c
deleted file mode 100644 (file)
index 43018e1..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * include/asm-v850/rte_cb.c -- Midas lab RTE-CB series of evaluation boards
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-#include <asm/machdep.h>
-#include <asm/v850e_uart.h>
-
-#include "mach.h"
-
-static void led_tick (void);
-
-/* LED access routines.  */
-extern unsigned read_leds (int pos, char *buf, int len);
-extern unsigned write_leds (int pos, const char *buf, int len);
-
-#ifdef CONFIG_RTE_CB_MULTI
-extern void multi_init (void);
-#endif
-
-\f
-void __init rte_cb_early_init (void)
-{
-       v850e_intc_disable_irqs ();
-
-#ifdef CONFIG_RTE_CB_MULTI
-       multi_init ();
-#endif
-}
-
-void __init mach_setup (char **cmdline)
-{
-#ifdef CONFIG_RTE_MB_A_PCI
-       /* Probe for Mother-A, and print a message if we find it.  */
-       *(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF;
-       if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) {
-               *(volatile unsigned long *)MB_A_SRAM_ADDR = 0x12345678;
-               if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0x12345678)
-                       printk (KERN_INFO
-                               "          NEC SolutionGear/Midas lab"
-                               " RTE-MOTHER-A motherboard\n");
-       }
-#endif /* CONFIG_RTE_MB_A_PCI */
-
-       mach_tick = led_tick;
-}
-
-void machine_restart (char *__unused)
-{
-#ifdef CONFIG_RESET_GUARD
-       disable_reset_guard ();
-#endif
-       asm ("jmp r0"); /* Jump to the reset vector.  */
-}
-
-/* This says `HALt.' in LEDese.  */
-static unsigned char halt_leds_msg[] = { 0x76, 0x77, 0x38, 0xF8 };
-
-void machine_halt (void)
-{
-#ifdef CONFIG_RESET_GUARD
-       disable_reset_guard ();
-#endif
-
-       /* Ignore all interrupts.  */
-       local_irq_disable ();
-
-       /* Write a little message.  */
-       write_leds (0, halt_leds_msg, sizeof halt_leds_msg);
-
-       /* Really halt.  */
-       for (;;)
-               asm ("halt; nop; nop; nop; nop; nop");
-}
-
-void machine_power_off (void)
-{
-       machine_halt ();
-}
-
-\f
-/* Animated LED display for timer tick.  */
-
-#define TICK_UPD_FREQ  6
-static int tick_frames[][10] = {
-       { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, -1 },
-       { 0x63, 0x5c, -1 },
-       { 0x5c, 0x00, -1 },
-       { 0x63, 0x00, -1 },
-       { -1 }
-};
-
-static void led_tick ()
-{
-       static unsigned counter = 0;
-       
-       if (++counter == (HZ / TICK_UPD_FREQ)) {
-               /* Which frame we're currently displaying for each digit.  */
-               static unsigned frame_nums[LED_NUM_DIGITS] = { 0 };
-               /* Display image.  */
-               static unsigned char image[LED_NUM_DIGITS] = { 0 };
-               unsigned char prev_image[LED_NUM_DIGITS];
-               int write_to_leds = 1; /* true if we should actually display */
-               int digit;
-
-               /* We check to see if the physical LEDs contains what we last
-                  wrote to them; if not, we suppress display (this is so that
-                  users can write to the LEDs, and not have their output
-                  overwritten).  As a special case, we start writing again if
-                  all the LEDs are blank, or our display image is all zeros
-                  (indicating that this is the initial update, when the actual
-                  LEDs might contain random data).  */
-               read_leds (0, prev_image, LED_NUM_DIGITS);
-               for (digit = 0; digit < LED_NUM_DIGITS; digit++)
-                       if (image[digit] != prev_image[digit]
-                           && image[digit] && prev_image[digit])
-                       {
-                               write_to_leds = 0;
-                               break;
-                       }
-
-               /* Update display image.  */
-               for (digit = 0;
-                    digit < LED_NUM_DIGITS && tick_frames[digit][0] >= 0;
-                    digit++)
-               {
-                       int frame = tick_frames[digit][frame_nums[digit]];
-                       if (frame < 0) {
-                               image[digit] = tick_frames[digit][0];
-                               frame_nums[digit] = 1;
-                       } else {
-                               image[digit] = frame;
-                               frame_nums[digit]++;
-                               break;
-                       }
-               }
-
-               if (write_to_leds)
-                       /* Write the display image to the physical LEDs.  */
-                       write_leds (0, image, LED_NUM_DIGITS);
-
-               counter = 0;
-       }
-}
-
-\f
-/* Mother-A interrupts.  */
-
-#ifdef CONFIG_RTE_GBUS_INT
-
-#define L GBUS_INT_PRIORITY_LOW
-#define M GBUS_INT_PRIORITY_MEDIUM
-#define H GBUS_INT_PRIORITY_HIGH
-
-static struct gbus_int_irq_init gbus_irq_inits[] = {
-#ifdef CONFIG_RTE_MB_A_PCI
-       { "MB_A_LAN",   IRQ_MB_A_LAN,           1,                   1, L },
-       { "MB_A_PCI1",  IRQ_MB_A_PCI1(0),       IRQ_MB_A_PCI1_NUM,   1, L },
-       { "MB_A_PCI2",  IRQ_MB_A_PCI2(0),       IRQ_MB_A_PCI2_NUM,   1, L },
-       { "MB_A_EXT",   IRQ_MB_A_EXT(0),        IRQ_MB_A_EXT_NUM,    1, L },
-       { "MB_A_USB_OC",IRQ_MB_A_USB_OC(0),     IRQ_MB_A_USB_OC_NUM, 1, L },
-       { "MB_A_PCMCIA_OC",IRQ_MB_A_PCMCIA_OC,  1,                   1, L },
-#endif
-       { 0 }
-};
-#define NUM_GBUS_IRQ_INITS (ARRAY_SIZE(gbus_irq_inits) - 1)
-
-static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
-
-#endif /* CONFIG_RTE_GBUS_INT */
-
-
-void __init rte_cb_init_irqs (void)
-{
-#ifdef CONFIG_RTE_GBUS_INT
-       gbus_int_init_irqs ();
-       gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes);
-#endif /* CONFIG_RTE_GBUS_INT */
-}
diff --git a/arch/v850/kernel/rte_cb_leds.c b/arch/v850/kernel/rte_cb_leds.c
deleted file mode 100644 (file)
index aa47ab1..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * include/asm-v850/rte_cb_leds.c -- Midas lab RTE-CB board LED device support
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-
-#include <asm/uaccess.h>
-
-#define LEDS_MINOR     169     /* Minor device number, using misc major.  */
-
-/* The actual LED hardware is write-only, so we hold the contents here too.  */
-static unsigned char leds_image[LED_NUM_DIGITS] = { 0 };
-
-/* Spinlock protecting the above leds.  */
-static DEFINE_SPINLOCK(leds_lock);
-
-/* Common body of LED read/write functions, checks POS and LEN for
-   correctness, declares a variable using IMG_DECL, initialized pointing at
-   the POS position in the LED image buffer, and and iterates COPY_EXPR
-   until BUF is equal to the last buffer position; finally, sets LEN to be
-   the amount actually copied.  IMG should be a variable declaration
-   (without an initializer or a terminating semicolon); POS, BUF, and LEN
-   should all be simple variables.  */
-#define DO_LED_COPY(img_decl, pos, buf, len, copy_expr)                        \
-do {                                                                   \
-       if (pos > LED_NUM_DIGITS)                                       \
-               len = 0;                                                \
-       else {                                                          \
-               if (pos + len > LED_NUM_DIGITS)                         \
-                       len = LED_NUM_DIGITS - pos;                     \
-                                                                       \
-               if (len > 0) {                                          \
-                       unsigned long _flags;                           \
-                       const char *_end = buf + len;                   \
-                       img_decl = &leds_image[pos];                    \
-                                                                       \
-                       spin_lock_irqsave (leds_lock, _flags);          \
-                       do                                              \
-                               (copy_expr);                            \
-                       while (buf != _end);                            \
-                       spin_unlock_irqrestore (leds_lock, _flags);     \
-               }                                                       \
-       }                                                               \
-} while (0)
-
-/* Read LEN bytes from LEDs at position POS, into BUF.
-   Returns actual amount read.  */
-unsigned read_leds (unsigned pos, char *buf, unsigned len)
-{
-       DO_LED_COPY (const char *img, pos, buf, len, *buf++ = *img++);
-       return len;
-}
-
-/* Write LEN bytes to LEDs at position POS, from BUF.
-   Returns actual amount written.  */
-unsigned write_leds (unsigned pos, const char *buf, unsigned len)
-{
-       /* We write the actual LED values backwards, because
-          increasing memory addresses reflect LEDs right-to-left. */
-       volatile char *led = &LED (LED_NUM_DIGITS - pos - 1);
-       /* We invert the value written to the hardware, because 1 = off,
-          and 0 = on.  */
-       DO_LED_COPY (char *img, pos, buf, len,
-                    *led-- = 0xFF ^ (*img++ = *buf++));
-       return len;
-}
-
-\f
-/* Device functions.  */
-
-static ssize_t leds_dev_read (struct file *file, char *buf, size_t len,
-                             loff_t *pos)
-{
-       char temp_buf[LED_NUM_DIGITS];
-       len = read_leds (*pos, temp_buf, len);
-       if (copy_to_user (buf, temp_buf, len))
-               return -EFAULT;
-       *pos += len;
-       return len;
-}
-
-static ssize_t leds_dev_write (struct file *file, const char *buf, size_t len,
-                              loff_t *pos)
-{
-       char temp_buf[LED_NUM_DIGITS];
-       if (copy_from_user (temp_buf, buf, min_t(size_t, len, LED_NUM_DIGITS)))
-               return -EFAULT;
-       len = write_leds (*pos, temp_buf, len);
-       *pos += len;
-       return len;
-}
-
-static loff_t leds_dev_lseek (struct file *file, loff_t offs, int whence)
-{
-       if (whence == 1)
-               offs += file->f_pos; /* relative */
-       else if (whence == 2)
-               offs += LED_NUM_DIGITS; /* end-relative */
-
-       if (offs < 0 || offs > LED_NUM_DIGITS)
-               return -EINVAL;
-
-       file->f_pos = offs;
-
-       return 0;
-}
-
-static const struct file_operations leds_fops = {
-       .read           = leds_dev_read,
-       .write          = leds_dev_write,
-       .llseek         = leds_dev_lseek
-};
-
-static struct miscdevice leds_miscdev = {
-       .name           = "leds",
-       .minor          = LEDS_MINOR,
-       .fops           = &leds_fops
-};
-
-int __init leds_dev_init (void)
-{
-       return misc_register (&leds_miscdev);
-}
-
-__initcall (leds_dev_init);
diff --git a/arch/v850/kernel/rte_cb_multi.c b/arch/v850/kernel/rte_cb_multi.c
deleted file mode 100644 (file)
index 963d55a..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * include/asm-v850/rte_multi.c -- Support for Multi debugger monitor ROM
- *     on Midas lab RTE-CB series of evaluation boards
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/init.h>
-
-#include <asm/machdep.h>
-
-#define IRQ_ADDR(irq) (0x80 + (irq) * 0x10)
-
-/* A table of which interrupt vectors to install, since blindly
-   installing all of them makes the debugger stop working.  This is a
-   list of offsets in the interrupt vector area; each entry means to
-   copy that particular 16-byte vector.  An entry less than zero ends
-   the table.  */
-static long multi_intv_install_table[] = {
-       /* Trap vectors */
-       0x40, 0x50,             
-
-#ifdef CONFIG_RTE_CB_MULTI_DBTRAP
-       /* Illegal insn / dbtrap.  These are used by multi, so only handle
-          them if configured to do so.  */
-       0x60,
-#endif
-
-       /* GINT1 - GINT3 (note, not GINT0!) */
-       IRQ_ADDR (IRQ_GINT(1)),
-       IRQ_ADDR (IRQ_GINT(2)),
-       IRQ_ADDR (IRQ_GINT(3)),
-
-       /* Timer D interrupts (up to 4 timers) */
-       IRQ_ADDR (IRQ_INTCMD(0)),
-#if IRQ_INTCMD_NUM > 1
-       IRQ_ADDR (IRQ_INTCMD(1)),
-#if IRQ_INTCMD_NUM > 2
-       IRQ_ADDR (IRQ_INTCMD(2)),
-#if IRQ_INTCMD_NUM > 3
-       IRQ_ADDR (IRQ_INTCMD(3)),
-#endif
-#endif
-#endif
-       
-       /* UART interrupts (up to 3 channels) */
-       IRQ_ADDR (IRQ_INTSER (0)), /* err */
-       IRQ_ADDR (IRQ_INTSR  (0)), /* rx */
-       IRQ_ADDR (IRQ_INTST  (0)), /* tx */
-#if IRQ_INTSR_NUM > 1
-       IRQ_ADDR (IRQ_INTSER (1)), /* err */
-       IRQ_ADDR (IRQ_INTSR  (1)), /* rx */
-       IRQ_ADDR (IRQ_INTST  (1)), /* tx */
-#if IRQ_INTSR_NUM > 2
-       IRQ_ADDR (IRQ_INTSER (2)), /* err */
-       IRQ_ADDR (IRQ_INTSR  (2)), /* rx */
-       IRQ_ADDR (IRQ_INTST  (2)), /* tx */
-#endif
-#endif
-
-       -1
-};
-
-/* Early initialization for kernel using Multi debugger ROM monitor.  */
-void __init multi_init (void)
-{
-       /* We're using the Multi debugger monitor, so we have to install
-          the interrupt vectors.  The monitor doesn't allow them to be
-          initially downloaded into their final destination because
-          it's in the monitor's scratch-RAM area.  Unfortunately, Multi
-          also doesn't deal correctly with ELF sections where the LMA
-          and VMA differ -- it just ignores the LMA -- so we can't use
-          that feature to work around the problem.  What we do instead
-          is just put the interrupt vectors into a normal section, and
-          do the necessary copying and relocation here.  Since the
-          interrupt vector basically only contains `jr' instructions
-          and no-ops, it's not that hard.  */
-       extern unsigned long _intv_load_start, _intv_start;
-       register unsigned long *src = &_intv_load_start;
-       register unsigned long *dst = (unsigned long *)INTV_BASE;
-       register unsigned long jr_fixup = (char *)&_intv_start - (char *)dst;
-       register long *ii;
-
-       /* Copy interrupt vectors as instructed by multi_intv_install_table. */
-       for (ii = multi_intv_install_table; *ii >= 0; ii++) {
-               /* Copy 16-byte interrupt vector at offset *ii.  */
-               int boffs;
-               for (boffs = 0; boffs < 0x10; boffs += sizeof *src) {
-                       /* Copy a single word, fixing up the jump offs
-                          if it's a `jr' instruction.  */
-                       int woffs = (*ii + boffs) / sizeof *src;
-                       unsigned long word = src[woffs];
-
-                       if ((word & 0xFC0) == 0x780) {
-                               /* A `jr' insn, fix up its offset (and yes, the
-                                  weird half-word swapping is intentional). */
-                               unsigned short hi = word & 0xFFFF;
-                               unsigned short lo = word >> 16;
-                               unsigned long udisp22
-                                       = lo + ((hi & 0x3F) << 16);
-                               long disp22 = (long)(udisp22 << 10) >> 10;
-
-                               disp22 += jr_fixup;
-
-                               hi = ((disp22 >> 16) & 0x3F) | 0x780;
-                               lo = disp22 & 0xFFFF;
-
-                               word = hi + (lo << 16);
-                       }
-
-                       dst[woffs] = word;
-               }
-       }
-}
diff --git a/arch/v850/kernel/rte_ma1_cb-rom.ld b/arch/v850/kernel/rte_ma1_cb-rom.ld
deleted file mode 100644 (file)
index 87b618f..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board
-   (CONFIG_RTE_CB_MA1), with kernel in ROM.  */
-
-MEMORY {
-       ROM   : ORIGIN = 0x00000000, LENGTH = 0x00100000
-       /* 1MB of SRAM.  This memory is mirrored 4 times.  */
-       SRAM  : ORIGIN = SRAM_ADDR,  LENGTH = SRAM_SIZE
-       /* 32MB of SDRAM.  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
-       ROMK_SECTIONS(ROM, SRAM)
-}
diff --git a/arch/v850/kernel/rte_ma1_cb.c b/arch/v850/kernel/rte_ma1_cb.c
deleted file mode 100644 (file)
index 08abf3d..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * arch/v850/kernel/rte_ma1_cb.c -- Midas labs RTE-V850E/MA1-CB board
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/ma1.h>
-#include <asm/rte_ma1_cb.h>
-#include <asm/v850e_timer_c.h>
-
-#include "mach.h"
-
-
-/* SRAM and SDRAM are almost contiguous (with a small hole in between;
-   see mach_reserve_bootmem for details), so just use both as one big area.  */
-#define RAM_START      SRAM_ADDR
-#define RAM_END                (SDRAM_ADDR + SDRAM_SIZE)
-
-
-void __init mach_early_init (void)
-{
-       rte_cb_early_init ();
-}
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
-                                  unsigned long *ram_len)
-{
-       *ram_start = RAM_START;
-       *ram_len = RAM_END - RAM_START;
-}
-
-void __init mach_reserve_bootmem ()
-{
-#ifdef CONFIG_RTE_CB_MULTI
-       /* Prevent the kernel from touching the monitor's scratch RAM.  */
-       reserve_bootmem(MON_SCRATCH_ADDR, MON_SCRATCH_SIZE,
-                       BOOTMEM_DEFAULT);
-#endif
-
-       /* The space between SRAM and SDRAM is filled with duplicate
-          images of SRAM.  Prevent the kernel from using them.  */
-       reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
-                        SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE),
-                        BOOTMEM_DEFAULT);
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
-       tv->tv_sec = 0;
-       tv->tv_nsec = 0;
-}
-
-/* Called before configuring an on-chip UART.  */
-void rte_ma1_cb_uart_pre_configure (unsigned chan,
-                                   unsigned cflags, unsigned baud)
-{
-       /* The RTE-MA1-CB connects some general-purpose I/O pins on the
-          CPU to the RTS/CTS lines of UART 0's serial connection.
-          I/O pins P42 and P43 are RTS and CTS respectively.  */
-       if (chan == 0) {
-               /* Put P42 & P43 in I/O port mode.  */
-               MA_PORT4_PMC &= ~0xC;
-               /* Make P42 an output, and P43 an input.  */
-               MA_PORT4_PM = (MA_PORT4_PM & ~0xC) | 0x8;
-       }
-
-       /* Do pre-configuration for the actual UART.  */
-       ma_uart_pre_configure (chan, cflags, baud);
-}
-
-void __init mach_init_irqs (void)
-{
-       unsigned tc;
-
-       /* Initialize interrupts.  */
-       ma_init_irqs ();
-       rte_cb_init_irqs ();
-
-       /* Use falling-edge-sensitivity for interrupts .  */
-       V850E_TIMER_C_SESC (0) &= ~0xC;
-       V850E_TIMER_C_SESC (1) &= ~0xF;
-
-       /* INTP000-INTP011 are shared with `Timer C', so we have to set
-          up Timer C to pass them through as raw interrupts.  */
-       for (tc = 0; tc < 2; tc++)
-               /* Turn on the timer.  */
-               V850E_TIMER_C_TMCC0 (tc) |= V850E_TIMER_C_TMCC0_CAE;
-
-       /* Make sure the relevant port0/port1 pins are assigned
-          interrupt duty.  We used INTP001-INTP011 (don't screw with
-          INTP000 because the monitor uses it).  */
-       MA_PORT0_PMC |= 0x4;    /* P02 (INTP001) in IRQ mode.  */
-       MA_PORT1_PMC |= 0x6;    /* P11 (INTP010) & P12 (INTP011) in IRQ mode.*/
-}
diff --git a/arch/v850/kernel/rte_ma1_cb.ld b/arch/v850/kernel/rte_ma1_cb.ld
deleted file mode 100644 (file)
index c8e16d1..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board
-   (CONFIG_RTE_CB_MA1), with kernel in SDRAM, under Multi debugger.  */
-
-MEMORY {
-       /* 1MB of SRAM; we can't use the last 32KB, because it's used by
-          the monitor scratch-RAM.  This memory is mirrored 4 times.  */
-       SRAM  : ORIGIN = SRAM_ADDR,  LENGTH = (SRAM_SIZE - MON_SCRATCH_SIZE)
-       /* Monitor scratch RAM; only the interrupt vectors should go here.  */
-       MRAM  : ORIGIN = MON_SCRATCH_ADDR,  LENGTH = MON_SCRATCH_SIZE
-       /* 32MB of SDRAM.  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-#ifdef CONFIG_RTE_CB_MA1_KSRAM
-# define KRAM SRAM
-#else
-# define KRAM SDRAM
-#endif
-
-SECTIONS {
-       /* We can't use RAMK_KRAM_CONTENTS because that puts the whole
-          kernel in a single ELF segment, and the Multi debugger (which
-          we use to load the kernel) appears to have bizarre problems
-          dealing with it.  */
-
-       .text : {
-               __kram_start = . ;
-               TEXT_CONTENTS
-       } > KRAM
-
-       .data : {
-               DATA_CONTENTS
-               BSS_CONTENTS
-               RAMK_INIT_CONTENTS
-               __kram_end = . ;
-               BOOTMAP_CONTENTS
-
-               /* The address at which the interrupt vectors are initially
-                  loaded by the loader.  We can't load the interrupt vectors
-                  directly into their target location, because the monitor
-                  ROM for the GHS Multi debugger barfs if we try.
-                  Unfortunately, Multi also doesn't deal correctly with ELF
-                  sections where the LMA and VMA differ (it just ignores the
-                  LMA), so we can't use that feature to work around the
-                  problem!  What we do instead is just put the interrupt
-                  vectors into a normal section, and have the
-                  `mach_early_init' function for Midas boards do the
-                  necessary copying and relocation at runtime (this section
-                  basically only contains `jr' instructions, so it's not
-                  that hard).  */
-               . = ALIGN (0x10) ;
-               __intv_load_start = . ;
-               INTV_CONTENTS
-       } > KRAM
-
-       .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
deleted file mode 100644 (file)
index 687e367..0000000
+++ /dev/null
@@ -1,819 +0,0 @@
-/*
- * arch/v850/kernel/mb_a_pci.c -- PCI support for Midas lab RTE-MOTHER-A board
- *
- *  Copyright (C) 2001,02,03,05  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03,05  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/pci.h>
-
-#include <asm/machdep.h>
-
-/* __nomods_init is like __devinit, but is a no-op when modules are enabled.
-   This is used by some routines that can be called either during boot
-   or by a module.  */
-#ifdef CONFIG_MODULES
-#define __nomods_init /*nothing*/
-#else
-#define __nomods_init __devinit
-#endif
-
-/* PCI devices on the Mother-A board can only do DMA to/from the MB SRAM
-   (the RTE-V850E/MA1-CB cpu board doesn't support PCI access to
-   CPU-board memory), and since linux DMA buffers are allocated in
-   normal kernel memory, we basically have to copy DMA blocks around
-   (this is like a `bounce buffer').  When a DMA block is `mapped', we
-   allocate an identically sized block in MB SRAM, and if we're doing
-   output to the device, copy the CPU-memory block to the MB-SRAM block.
-   When an active block is `unmapped', we will copy the block back to
-   CPU memory if necessary, and then deallocate the MB SRAM block.
-   Ack.  */
-
-/* Where the motherboard SRAM is in the PCI-bus address space (the
-   first 512K of it is also mapped at PCI address 0).  */
-#define PCI_MB_SRAM_ADDR 0x800000
-
-/* Convert CPU-view MB SRAM address to/from PCI-view addresses of the
-   same memory.  */
-#define MB_SRAM_TO_PCI(mb_sram_addr) \
-   ((dma_addr_t)mb_sram_addr - MB_A_SRAM_ADDR + PCI_MB_SRAM_ADDR)
-#define PCI_TO_MB_SRAM(pci_addr)     \
-   (void *)(pci_addr - PCI_MB_SRAM_ADDR + MB_A_SRAM_ADDR)
-
-static void pcibios_assign_resources (void);
-
-struct mb_pci_dev_irq {
-       unsigned dev;           /* PCI device number */
-       unsigned irq_base;      /* First IRQ  */
-       unsigned query_pin;     /* True if we should read the device's
-                                  Interrupt Pin info, and allocate
-                                  interrupt IRQ_BASE + PIN.  */
-};
-
-/* PCI interrupts are mapped statically to GBUS interrupts.  */
-static struct mb_pci_dev_irq mb_pci_dev_irqs[] = {
-       /* Motherboard SB82558 ethernet controller */
-       { 10,   IRQ_MB_A_LAN,           0 },
-       /* PCI slot 1 */
-       { 8,    IRQ_MB_A_PCI1(0),       1 },
-       /* PCI slot 2 */
-       { 9,    IRQ_MB_A_PCI2(0),       1 }
-};
-#define NUM_MB_PCI_DEV_IRQS ARRAY_SIZE(mb_pci_dev_irqs)
-
-\f
-/* PCI configuration primitives.  */
-
-#define CONFIG_DMCFGA(bus, devfn, offs)                                        \
-   (0x80000000                                                         \
-    | ((offs) & ~0x3)                                                  \
-    | ((devfn) << 8)                                                   \
-    | ((bus)->number << 16))
-
-static int
-mb_pci_read (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 *rval)
-{
-       u32 addr;
-       int flags;
-
-       local_irq_save (flags);
-
-       MB_A_PCI_PCICR = 0x7;
-       MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
-
-       addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
-
-       switch (size) {
-       case 1: *rval = *(volatile  u8 *)addr; break;
-       case 2: *rval = *(volatile u16 *)addr; break;
-       case 4: *rval = *(volatile u32 *)addr; break;
-       }
-
-        if (MB_A_PCI_PCISR & 0x2000) {
-               MB_A_PCI_PCISR = 0x2000;
-               *rval = ~0;
-        }
-
-       MB_A_PCI_DMCFGA = 0;
-
-       local_irq_restore (flags);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-mb_pci_write (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 val)
-{
-       u32 addr;
-       int flags;
-
-       local_irq_save (flags);
-
-       MB_A_PCI_PCICR = 0x7;
-       MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
-
-       addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
-
-       switch (size) {
-       case 1: *(volatile  u8 *)addr = val; break;
-       case 2: *(volatile u16 *)addr = val; break;
-       case 4: *(volatile u32 *)addr = val; break;
-       }
-
-        if (MB_A_PCI_PCISR & 0x2000)
-               MB_A_PCI_PCISR = 0x2000;
-
-       MB_A_PCI_DMCFGA = 0;
-
-       local_irq_restore (flags);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops mb_pci_config_ops = {
-       .read   = mb_pci_read,
-       .write  = mb_pci_write,
-};
-
-\f
-/* PCI Initialization.  */
-
-static struct pci_bus *mb_pci_bus = 0;
-
-/* Do initial PCI setup.  */
-static int __devinit pcibios_init (void)
-{
-       u32 id = MB_A_PCI_PCIHIDR;
-       u16 vendor = id & 0xFFFF;
-       u16 device = (id >> 16) & 0xFFFF;
-
-       if (vendor == PCI_VENDOR_ID_PLX && device == PCI_DEVICE_ID_PLX_9080) {
-               printk (KERN_INFO
-                       "PCI: PLX Technology PCI9080 HOST/PCI bridge\n");
-
-               MB_A_PCI_PCICR = 0x147;
-
-               MB_A_PCI_PCIBAR0 = 0x007FFF00;
-               MB_A_PCI_PCIBAR1 = 0x0000FF00;
-               MB_A_PCI_PCIBAR2 = 0x00800000;
-
-               MB_A_PCI_PCILTR = 0x20;
-
-               MB_A_PCI_PCIPBAM |= 0x3;
-
-               MB_A_PCI_PCISR =  ~0; /* Clear errors.  */
-
-               /* Reprogram the motherboard's IO/config address space,
-                  as we don't support the GCS7 address space that the
-                  default uses.  */
-
-               /* Significant address bits used for decoding PCI GCS5 space
-                  accesses.  */
-               MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1);
-
-               /* I don't understand this, but the SolutionGear example code
-                  uses such an offset, and it doesn't work without it.  XXX */
-#if GCS5_SIZE == 0x00800000
-#define GCS5_CFG_OFFS 0x00800000
-#else
-#define GCS5_CFG_OFFS 0
-#endif
-
-               /* Address bit values for matching.  Note that we have to give
-                  the address from the motherboard's point of view, which is
-                  different than the CPU's.  */
-               /* PCI memory space.  */
-               MB_A_PCI_DMLBAM = GCS5_CFG_OFFS + 0x0;
-               /* PCI I/O space.  */
-               MB_A_PCI_DMLBAI =
-                       GCS5_CFG_OFFS + (MB_A_PCI_IO_ADDR - GCS5_ADDR);
-
-               mb_pci_bus = pci_scan_bus (0, &mb_pci_config_ops, 0);
-
-               pcibios_assign_resources ();
-       } else
-               printk (KERN_ERR "PCI: HOST/PCI bridge not found\n");
-
-       return 0;
-}
-
-subsys_initcall (pcibios_init);
-
-char __devinit *pcibios_setup (char *option)
-{
-       /* Don't handle any options. */
-       return option;
-}
-
-\f
-int __nomods_init pcibios_enable_device (struct pci_dev *dev, int mask)
-{
-       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;
-}
-
-\f
-/* Resource allocation.  */
-static void __devinit pcibios_assign_resources (void)
-{
-       struct pci_dev *dev = NULL;
-       struct resource *r;
-
-       for_each_pci_dev(dev) {
-               unsigned di_num;
-               unsigned class = dev->class >> 8;
-
-               if (class && class != PCI_CLASS_BRIDGE_HOST) {
-                       unsigned r_num;
-                       for(r_num = 0; r_num < 6; r_num++) {
-                               r = &dev->resource[r_num];
-                               if (!r->start && r->end)
-                                       pci_assign_resource (dev, r_num);
-                       }
-               }
-
-               /* Assign interrupts.  */
-               for (di_num = 0; di_num < NUM_MB_PCI_DEV_IRQS; di_num++) {
-                       struct mb_pci_dev_irq *di = &mb_pci_dev_irqs[di_num];
-
-                       if (di->dev == PCI_SLOT (dev->devfn)) {
-                               unsigned irq = di->irq_base;
-
-                               if (di->query_pin) {
-                                       /* Find out which interrupt pin
-                                          this device uses (each PCI
-                                          slot has 4).  */
-                                       u8 irq_pin;
-
-                                       pci_read_config_byte (dev,
-                                                            PCI_INTERRUPT_PIN,
-                                                             &irq_pin);
-
-                                       if (irq_pin == 0)
-                                               /* Doesn't use interrupts.  */ 
-                                               continue;
-                                       else
-                                               irq += irq_pin - 1;
-                               }
-
-                               pcibios_update_irq (dev, irq);
-                       }
-               }
-       }
-}
-
-void __devinit pcibios_update_irq (struct pci_dev *dev, int irq)
-{
-       dev->irq = irq;
-       pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
-}
-
-void __devinit
-pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-                       struct resource *res)
-{
-       unsigned long offset = 0;
-
-       if (res->flags & IORESOURCE_IO) {
-               offset = MB_A_PCI_IO_ADDR;
-       } else if (res->flags & IORESOURCE_MEM) {
-               offset = MB_A_PCI_MEM_ADDR;
-       }
-
-       region->start = res->start - offset;
-       region->end = res->end - offset;
-}
-
-\f
-/* Stubs for things we don't use.  */
-
-/* Called after each bus is probed, but before its children are examined. */
-void pcibios_fixup_bus(struct pci_bus *b)
-{
-}
-
-void
-pcibios_align_resource (void *data, struct resource *res,
-                       resource_size_t size, resource_size_t align)
-{
-}
-
-void pcibios_set_master (struct pci_dev *dev)
-{
-}
-
-\f
-/* Mother-A SRAM memory allocation.  This is a simple first-fit allocator.  */
-
-/* A memory free-list node.  */
-struct mb_sram_free_area {
-       void *mem;
-       unsigned long size;
-       struct mb_sram_free_area *next;
-};
-
-/* The tail of the free-list, which starts out containing all the SRAM.  */
-static struct mb_sram_free_area mb_sram_free_tail = {
-       (void *)MB_A_SRAM_ADDR, MB_A_SRAM_SIZE, 0
-};
-
-/* The free-list.  */
-static struct mb_sram_free_area *mb_sram_free_areas = &mb_sram_free_tail;
-
-/* The free-list of free free-list nodes. (:-)  */
-static struct mb_sram_free_area *mb_sram_free_free_areas = 0;
-
-/* Spinlock protecting the above globals.  */
-static DEFINE_SPINLOCK(mb_sram_lock);
-
-/* Allocate a memory block at least SIZE bytes long in the Mother-A SRAM
-   space.  */
-static void *alloc_mb_sram (size_t size)
-{
-       struct mb_sram_free_area *prev, *fa;
-       unsigned long flags;
-       void *mem = 0;
-
-       spin_lock_irqsave (mb_sram_lock, flags);
-
-       /* Look for a free area that can contain SIZE bytes.  */
-       for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
-               if (fa->size >= size) {
-                       /* Found one!  */
-                       mem = fa->mem;
-
-                       if (fa->size == size) {
-                               /* In fact, it fits exactly, so remove
-                                  this node from the free-list.  */
-                               if (prev)
-                                       prev->next = fa->next;
-                               else
-                                       mb_sram_free_areas = fa->next;
-                               /* Put it on the free-list-entry-free-list. */
-                               fa->next = mb_sram_free_free_areas;
-                               mb_sram_free_free_areas = fa;
-                       } else {
-                               /* FA is bigger than SIZE, so just
-                                  reduce its size to account for this
-                                  allocation.  */
-                               fa->mem += size;
-                               fa->size -= size;
-                       }
-
-                       break;
-               }
-
-       spin_unlock_irqrestore (mb_sram_lock, flags);
-
-       return mem;
-}
-
-/* Return the memory area MEM of size SIZE to the MB SRAM free pool.  */
-static void free_mb_sram (void *mem, size_t size)
-{
-       struct mb_sram_free_area *prev, *fa, *new_fa;
-       unsigned long flags;
-       void *end = mem + size;
-
-       spin_lock_irqsave (mb_sram_lock, flags);
-
- retry:
-       /* Find an adjacent free-list entry.  */
-       for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
-               if (fa->mem == end) {
-                       /* FA is just after MEM, grow down to encompass it. */
-                       fa->mem = mem;
-                       fa->size += size;
-                       goto done;
-               } else if (fa->mem + fa->size == mem) {
-                       struct mb_sram_free_area *next_fa = fa->next;
-
-                       /* FA is just before MEM, expand to encompass it. */
-                       fa->size += size;
-
-                       /* See if FA can now be merged with its successor. */
-                       if (next_fa && fa->mem + fa->size == next_fa->mem) {
-                               /* Yup; merge NEXT_FA's info into FA.  */
-                               fa->size += next_fa->size;
-                               fa->next = next_fa->next;
-                               /* Free NEXT_FA.  */
-                               next_fa->next = mb_sram_free_free_areas;
-                               mb_sram_free_free_areas = next_fa;
-                       }
-                       goto done;
-               } else if (fa->mem > mem)
-                       /* We've reached the right spot in the free-list
-                          without finding an adjacent free-area, so add
-                          a new free area to hold mem. */
-                       break;
-
-       /* Make a new free-list entry.  */
-
-       /* First, get a free-list entry.  */
-       if (! mb_sram_free_free_areas) {
-               /* There are none, so make some.  */
-               void *block;
-               size_t block_size = sizeof (struct mb_sram_free_area) * 8;
-
-               /* Don't hold the lock while calling kmalloc (I'm not
-                  sure whether it would be a problem, since we use
-                  GFP_ATOMIC, but it makes me nervous).  */
-               spin_unlock_irqrestore (mb_sram_lock, flags);
-
-               block = kmalloc (block_size, GFP_ATOMIC);
-               if (! block)
-                       panic ("free_mb_sram: can't allocate free-list entry");
-
-               /* Now get the lock back.  */
-               spin_lock_irqsave (mb_sram_lock, flags);
-
-               /* Add the new free free-list entries.  */
-               while (block_size > 0) {
-                       struct mb_sram_free_area *nfa = block;
-                       nfa->next = mb_sram_free_free_areas;
-                       mb_sram_free_free_areas = nfa;
-                       block += sizeof *nfa;
-                       block_size -= sizeof *nfa;
-               }
-
-               /* Since we dropped the lock to call kmalloc, the
-                  free-list could have changed, so retry from the
-                  beginning.  */
-               goto retry;
-       }
-
-       /* Remove NEW_FA from the free-list of free-list entries.  */
-       new_fa = mb_sram_free_free_areas;
-       mb_sram_free_free_areas = new_fa->next;
-
-       /* NEW_FA initially holds only MEM.  */
-       new_fa->mem = mem;
-       new_fa->size = size;
-
-       /* Insert NEW_FA in the free-list between PREV and FA. */
-       new_fa->next = fa;
-       if (prev)
-               prev->next = new_fa;
-       else
-               mb_sram_free_areas = new_fa;
-
- done:
-       spin_unlock_irqrestore (mb_sram_lock, flags);
-}
-
-\f
-/* Maintainence of CPU -> Mother-A DMA mappings.  */
-
-struct dma_mapping {
-       void *cpu_addr;
-       void *mb_sram_addr;
-       size_t size;
-       struct dma_mapping *next;
-};
-
-/* A list of mappings from CPU addresses to MB SRAM addresses for active
-   DMA blocks (that have been `granted' to the PCI device).  */
-static struct dma_mapping *active_dma_mappings = 0;
-
-/* A list of free mapping objects.  */
-static struct dma_mapping *free_dma_mappings = 0;
-
-/* Spinlock protecting the above globals.  */
-static DEFINE_SPINLOCK(dma_mappings_lock);
-
-static struct dma_mapping *new_dma_mapping (size_t size)
-{
-       unsigned long flags;
-       struct dma_mapping *mapping;
-       void *mb_sram_block = alloc_mb_sram (size);
-
-       if (! mb_sram_block)
-               return 0;
-
-       spin_lock_irqsave (dma_mappings_lock, flags);
-
-       if (! free_dma_mappings) {
-               /* We're out of mapping structures, make more.  */
-               void *mblock;
-               size_t mblock_size = sizeof (struct dma_mapping) * 8;
-
-               /* Don't hold the lock while calling kmalloc (I'm not
-                  sure whether it would be a problem, since we use
-                  GFP_ATOMIC, but it makes me nervous).  */
-               spin_unlock_irqrestore (dma_mappings_lock, flags);
-
-               mblock = kmalloc (mblock_size, GFP_ATOMIC);
-               if (! mblock) {
-                       free_mb_sram (mb_sram_block, size);
-                       return 0;
-               }
-
-               /* Get the lock back.  */
-               spin_lock_irqsave (dma_mappings_lock, flags);
-
-               /* Add the new mapping structures to the free-list.  */
-               while (mblock_size > 0) {
-                       struct dma_mapping *fm = mblock;
-                       fm->next = free_dma_mappings;
-                       free_dma_mappings = fm;
-                       mblock += sizeof *fm;
-                       mblock_size -= sizeof *fm;
-               }
-       }
-
-       /* Get a mapping struct from the freelist.  */
-       mapping = free_dma_mappings;
-       free_dma_mappings = mapping->next;
-
-       /* Initialize the mapping.  Other fields should be filled in by
-          caller.  */
-       mapping->mb_sram_addr = mb_sram_block;
-       mapping->size = size;
-
-       /* Add it to the list of active mappings.  */
-       mapping->next = active_dma_mappings;
-       active_dma_mappings = mapping;
-
-       spin_unlock_irqrestore (dma_mappings_lock, flags);
-
-       return mapping;
-}
-
-static struct dma_mapping *find_dma_mapping (void *mb_sram_addr)
-{
-       unsigned long flags;
-       struct dma_mapping *mapping;
-
-       spin_lock_irqsave (dma_mappings_lock, flags);
-
-       for (mapping = active_dma_mappings; mapping; mapping = mapping->next)
-               if (mapping->mb_sram_addr == mb_sram_addr) {
-                       spin_unlock_irqrestore (dma_mappings_lock, flags);
-                       return mapping;
-               }
-
-       panic ("find_dma_mapping: unmapped PCI DMA addr 0x%x",
-              MB_SRAM_TO_PCI (mb_sram_addr));
-}
-
-static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr)
-{
-       unsigned long flags;
-       struct dma_mapping *mapping, *prev;
-
-       spin_lock_irqsave (dma_mappings_lock, flags);
-
-       for (prev = 0, mapping = active_dma_mappings;
-            mapping;
-            prev = mapping, mapping = mapping->next)
-       {
-               if (mapping->mb_sram_addr == mb_sram_addr) {
-                       /* This is the MAPPING; deactivate it.  */
-                       if (prev)
-                               prev->next = mapping->next;
-                       else
-                               active_dma_mappings = mapping->next;
-
-                       spin_unlock_irqrestore (dma_mappings_lock, flags);
-
-                       return mapping;
-               }
-       }
-
-       panic ("deactivate_dma_mapping: unmapped PCI DMA addr 0x%x",
-              MB_SRAM_TO_PCI (mb_sram_addr));
-}
-
-/* Return MAPPING to the freelist.  */
-static inline void
-free_dma_mapping (struct dma_mapping *mapping)
-{
-       unsigned long flags;
-
-       free_mb_sram (mapping->mb_sram_addr, mapping->size);
-
-       spin_lock_irqsave (dma_mappings_lock, flags);
-
-       mapping->next = free_dma_mappings;
-       free_dma_mappings = mapping;
-
-       spin_unlock_irqrestore (dma_mappings_lock, flags);
-}
-
-\f
-/* Single PCI DMA mappings.  */
-
-/* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA.  The
-   32-bit PCI bus mastering address to use is returned.  the device owns
-   this memory until either pci_unmap_single or pci_dma_sync_single is
-   performed.  */
-dma_addr_t
-pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir)
-{
-       struct dma_mapping *mapping = new_dma_mapping (size);
-
-       if (! mapping)
-               return 0;
-
-       mapping->cpu_addr = cpu_addr;
-
-       if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_TODEVICE)
-               memcpy (mapping->mb_sram_addr, cpu_addr, size);
-
-       return MB_SRAM_TO_PCI (mapping->mb_sram_addr);
-}
-
-/* Return to the CPU the PCI DMA memory block previously `granted' to
-   PDEV, at DMA_ADDR.  */
-void pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
-                      int dir)
-{
-       void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
-       struct dma_mapping *mapping = deactivate_dma_mapping (mb_sram_addr);
-
-       if (size != mapping->size)
-               panic ("pci_unmap_single: size (%d) doesn't match"
-                      " size of mapping at PCI DMA addr 0x%x (%d)\n",
-                      size, dma_addr, mapping->size);
-
-       /* Copy back the DMA'd contents if necessary.  */
-       if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_FROMDEVICE)
-               memcpy (mapping->cpu_addr, mb_sram_addr, size);
-
-       /* Return mapping to the freelist.  */
-       free_dma_mapping (mapping);
-}
-
-/* Make physical memory consistent for a single streaming mode DMA
-   translation after a transfer.
-
-   If you perform a pci_map_single() but wish to interrogate the
-   buffer using the cpu, yet do not wish to teardown the PCI dma
-   mapping, you must call this function before doing so.  At the next
-   point you give the PCI dma address back to the card, you must first
-   perform a pci_dma_sync_for_device, and then the device again owns
-   the buffer.  */
-void
-pci_dma_sync_single_for_cpu (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
-                    int dir)
-{
-       void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
-       struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr);
-
-       /* Synchronize the DMA buffer with the CPU buffer if necessary.  */
-       if (dir == PCI_DMA_FROMDEVICE)
-               memcpy (mapping->cpu_addr, mb_sram_addr, size);
-       else if (dir == PCI_DMA_TODEVICE)
-               ; /* nothing to do */
-       else
-               panic("pci_dma_sync_single: unsupported sync dir: %d", dir);
-}
-
-void
-pci_dma_sync_single_for_device (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
-                               int dir)
-{
-       void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
-       struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr);
-
-       /* Synchronize the DMA buffer with the CPU buffer if necessary.  */
-       if (dir == PCI_DMA_FROMDEVICE)
-               ; /* nothing to do */
-       else if (dir == PCI_DMA_TODEVICE)
-               memcpy (mb_sram_addr, mapping->cpu_addr, size);
-       else
-               panic("pci_dma_sync_single: unsupported sync dir: %d", dir);
-}
-
-\f
-/* Scatter-gather PCI DMA mappings.  */
-
-/* Do multiple DMA mappings at once.  */
-int
-pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir)
-{
-       BUG ();
-       return 0;
-}
-
-/* Unmap multiple DMA mappings at once.  */
-void
-pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,int dir)
-{
-       BUG ();
-}
-
-/* Make physical memory consistent for a set of streaming mode DMA
-   translations after a transfer.  The same as pci_dma_sync_single_* but
-   for a scatter-gather list, same rules and usage.  */
-
-void
-pci_dma_sync_sg_for_cpu (struct pci_dev *dev,
-                        struct scatterlist *sg, int sg_len,
-                        int dir)
-{
-       BUG ();
-}
-
-void
-pci_dma_sync_sg_for_device (struct pci_dev *dev,
-                           struct scatterlist *sg, int sg_len,
-                           int dir)
-{
-       BUG ();
-}
-
-\f
-/* PCI mem mapping.  */
-
-/* Allocate and map kernel buffer using consistent mode DMA for PCI
-   device.  Returns non-NULL cpu-view pointer to the buffer if
-   successful and sets *DMA_ADDR to the pci side dma address as well,
-   else DMA_ADDR is undefined.  */
-void *
-pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr)
-{
-       void *mb_sram_mem = alloc_mb_sram (size);
-       if (mb_sram_mem)
-               *dma_addr = MB_SRAM_TO_PCI (mb_sram_mem);
-       return mb_sram_mem;
-}
-
-/* Free and unmap a consistent DMA buffer.  CPU_ADDR and DMA_ADDR must
-   be values that were returned from pci_alloc_consistent.  SIZE must be
-   the same as what as passed into pci_alloc_consistent.  References to
-   the memory and mappings associated with CPU_ADDR or DMA_ADDR past
-   this call are illegal.  */
-void
-pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
-                    dma_addr_t dma_addr)
-{
-       void *mb_sram_mem = PCI_TO_MB_SRAM (dma_addr);
-       free_mb_sram (mb_sram_mem, size);
-}
-
-\f
-/* iomap/iomap */
-
-void __iomem *pci_iomap (struct pci_dev *dev, int bar, unsigned long max)
-{
-       resource_size_t start = pci_resource_start (dev, bar);
-       resource_size_t len = pci_resource_len (dev, bar);
-
-       if (!start || len == 0)
-               return 0;
-
-       /* None of the ioremap functions actually do anything, other than
-          re-casting their argument, so don't bother differentiating them.  */
-       return ioremap (start, len);
-}
-
-void pci_iounmap (struct pci_dev *dev, void __iomem *addr)
-{
-       /* nothing */
-}
-
-\f
-/* symbol exports (for modules) */
-
-EXPORT_SYMBOL (pci_map_single);
-EXPORT_SYMBOL (pci_unmap_single);
-EXPORT_SYMBOL (pci_alloc_consistent);
-EXPORT_SYMBOL (pci_free_consistent);
-EXPORT_SYMBOL (pci_dma_sync_single_for_cpu);
-EXPORT_SYMBOL (pci_dma_sync_single_for_device);
-EXPORT_SYMBOL (pci_iomap);
-EXPORT_SYMBOL (pci_iounmap);
diff --git a/arch/v850/kernel/rte_me2_cb.c b/arch/v850/kernel/rte_me2_cb.c
deleted file mode 100644 (file)
index 46803d4..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * arch/v850/kernel/rte_me2_cb.c -- Midas labs RTE-V850E/ME2-CB board
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/me2.h>
-#include <asm/rte_me2_cb.h>
-#include <asm/machdep.h>
-#include <asm/v850e_intc.h>
-#include <asm/v850e_cache.h>
-#include <asm/irq.h>
-
-#include "mach.h"
-
-extern unsigned long *_intv_start;
-extern unsigned long *_intv_end;
-
-/* LED access routines.  */
-extern unsigned read_leds (int pos, char *buf, int len);
-extern unsigned write_leds (int pos, const char *buf, int len);
-
-
-/* SDRAM are almost contiguous (with a small hole in between;
-   see mach_reserve_bootmem for details), so just use both as one big area.  */
-#define RAM_START      SDRAM_ADDR
-#define RAM_END                (SDRAM_ADDR + SDRAM_SIZE)
-
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
-                                  unsigned long *ram_len)
-{
-       *ram_start = RAM_START;
-       *ram_len = RAM_END - RAM_START;
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
-       tv->tv_sec = 0;
-       tv->tv_nsec = 0;
-}
-
-/* Called before configuring an on-chip UART.  */
-void rte_me2_cb_uart_pre_configure (unsigned chan,
-                                   unsigned cflags, unsigned baud)
-{
-       /* The RTE-V850E/ME2-CB connects some general-purpose I/O
-          pins on the CPU to the RTS/CTS lines of UARTB channel 0's
-          serial connection.
-          I/O pins P21 and P22 are RTS and CTS respectively.  */
-       if (chan == 0) {
-               /* Put P21 & P22 in I/O port mode.  */
-               ME2_PORT2_PMC &= ~0x6;
-               /* Make P21 and output, and P22 an input.  */
-               ME2_PORT2_PM = (ME2_PORT2_PM & ~0xC) | 0x4;
-       }
-
-       me2_uart_pre_configure (chan, cflags, baud);
-}
-
-void __init mach_init_irqs (void)
-{
-       /* Initialize interrupts.  */
-       me2_init_irqs ();
-       rte_me2_cb_init_irqs ();
-}
-
-#ifdef CONFIG_ROM_KERNEL
-/* Initialization for kernel in ROM.  */
-static inline rom_kernel_init (void)
-{
-       /* If the kernel is in ROM, we have to copy any initialized data
-          from ROM into RAM.  */
-       extern unsigned long _data_load_start, _sdata, _edata;
-       register unsigned long *src = &_data_load_start;
-       register unsigned long *dst = &_sdata, *end = &_edata;
-
-       while (dst != end)
-               *dst++ = *src++;
-}
-#endif /* CONFIG_ROM_KERNEL */
-
-static void install_interrupt_vectors (void)
-{
-       unsigned long *p1, *p2;
-
-       ME2_IRAMM = 0x03; /* V850E/ME2 iRAM write mode */
-
-       /* vector copy to iRAM */
-       p1 = (unsigned long *)0; /* v85x vector start */
-       p2 = (unsigned long *)&_intv_start;
-       while (p2 < (unsigned long *)&_intv_end)
-               *p1++ = *p2++;
-
-       ME2_IRAMM = 0x00; /* V850E/ME2 iRAM read mode */
-}
-\f
-/* CompactFlash */
-
-static void cf_power_on (void)
-{
-       /* CF card detected? */
-       if (CB_CF_STS0 & 0x0030)
-               return;
-
-       CB_CF_REG0 = 0x0002; /* reest on */
-       mdelay (10);
-       CB_CF_REG0 = 0x0003; /* power on */
-       mdelay (10);
-       CB_CF_REG0 = 0x0001; /* reset off */
-       mdelay (10);
-}
-
-static void cf_power_off (void)
-{
-       CB_CF_REG0 = 0x0003; /* power on */
-       mdelay (10);
-       CB_CF_REG0 = 0x0002; /* reest on */
-       mdelay (10);
-}
-
-void __init mach_early_init (void)
-{
-       install_interrupt_vectors ();
-
-       /* CS1 SDRAM instruction cache enable */
-       v850e_cache_enable (0x04, 0x03, 0);
-
-       rte_cb_early_init ();
-
-       /* CompactFlash power on */
-       cf_power_on ();
-
-#if defined (CONFIG_ROM_KERNEL)
-       rom_kernel_init ();
-#endif
-}
-
-\f
-/* RTE-V850E/ME2-CB Programmable Interrupt Controller.  */
-
-static struct cb_pic_irq_init cb_pic_irq_inits[] = {
-       { "CB_EXTTM0",       IRQ_CB_EXTTM0,       1, 1, 6 },
-       { "CB_EXTSIO",       IRQ_CB_EXTSIO,       1, 1, 6 },
-       { "CB_TOVER",        IRQ_CB_TOVER,        1, 1, 6 },
-       { "CB_GINT0",        IRQ_CB_GINT0,        1, 1, 6 },
-       { "CB_USB",          IRQ_CB_USB,          1, 1, 6 },
-       { "CB_LANC",         IRQ_CB_LANC,         1, 1, 6 },
-       { "CB_USB_VBUS_ON",  IRQ_CB_USB_VBUS_ON,  1, 1, 6 },
-       { "CB_USB_VBUS_OFF", IRQ_CB_USB_VBUS_OFF, 1, 1, 6 },
-       { "CB_EXTTM1",       IRQ_CB_EXTTM1,       1, 1, 6 },
-       { "CB_EXTTM2",       IRQ_CB_EXTTM2,       1, 1, 6 },
-       { 0 }
-};
-#define NUM_CB_PIC_IRQ_INITS (ARRAY_SIZE(cb_pic_irq_inits) - 1)
-
-static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS];
-static unsigned char cb_pic_active_irqs = 0;
-
-void __init rte_me2_cb_init_irqs (void)
-{
-       cb_pic_init_irq_types (cb_pic_irq_inits, cb_pic_hw_itypes);
-
-       /* Initalize on board PIC1 (not PIC0) enable */
-       CB_PIC_INT0M  = 0x0000;
-       CB_PIC_INT1M  = 0x0000;
-       CB_PIC_INTR   = 0x0000;
-       CB_PIC_INTEN |= CB_PIC_INT1EN;
-
-       ME2_PORT2_PMC    |= 0x08;       /* INTP23/SCK1 mode */
-       ME2_PORT2_PFC    &= ~0x08;      /* INTP23 mode */
-       ME2_INTR(2)      &= ~0x08;      /* INTP23 falling-edge detect */
-       ME2_INTF(2)      &= ~0x08;      /*   " */
-
-       rte_cb_init_irqs ();    /* gbus &c */
-}
-
-
-/* Enable interrupt handling for interrupt IRQ.  */
-void cb_pic_enable_irq (unsigned irq)
-{
-       CB_PIC_INT1M |= 1 << (irq - CB_PIC_BASE_IRQ);
-}
-
-void cb_pic_disable_irq (unsigned irq)
-{
-       CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
-}
-
-void cb_pic_shutdown_irq (unsigned irq)
-{
-       cb_pic_disable_irq (irq);
-
-       if (--cb_pic_active_irqs == 0)
-               free_irq (IRQ_CB_PIC, 0);
-
-       CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
-}
-
-static irqreturn_t cb_pic_handle_irq (int irq, void *dev_id,
-                                     struct pt_regs *regs)
-{
-       irqreturn_t rval = IRQ_NONE;
-       unsigned status = CB_PIC_INTR;
-       unsigned enable = CB_PIC_INT1M;
-
-       /* Only pay attention to enabled interrupts.  */
-       status &= enable;
-
-       CB_PIC_INTEN &= ~CB_PIC_INT1EN;
-
-       if (status) {
-               unsigned mask = 1;
-
-               irq = CB_PIC_BASE_IRQ;
-               do {
-                       /* There's an active interrupt, find out which one,
-                          and call its handler.  */
-                       while (! (status & mask)) {
-                               irq++;
-                               mask <<= 1;
-                       }
-                       status &= ~mask;
-
-                       CB_PIC_INTR = mask;
-
-                       /* Recursively call handle_irq to handle it. */
-                       handle_irq (irq, regs);
-                       rval = IRQ_HANDLED;
-               } while (status);
-       }
-
-       CB_PIC_INTEN |= CB_PIC_INT1EN;
-
-       return rval;
-}
-
-\f
-static void irq_nop (unsigned irq) { }
-
-static unsigned cb_pic_startup_irq (unsigned irq)
-{
-       int rval;
-
-       if (cb_pic_active_irqs == 0) {
-               rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq,
-                                   IRQF_DISABLED, "cb_pic_handler", 0);
-               if (rval != 0)
-                       return rval;
-       }
-
-       cb_pic_active_irqs++;
-
-       cb_pic_enable_irq (irq);
-
-       return 0;
-}
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
-   INITS (which is terminated by an entry with the name field == 0).  */
-void __init cb_pic_init_irq_types (struct cb_pic_irq_init *inits,
-                                  struct hw_interrupt_type *hw_irq_types)
-{
-       struct cb_pic_irq_init *init;
-       for (init = inits; init->name; init++) {
-               struct hw_interrupt_type *hwit = hw_irq_types++;
-
-               hwit->typename = init->name;
-
-               hwit->startup  = cb_pic_startup_irq;
-               hwit->shutdown = cb_pic_shutdown_irq;
-               hwit->enable   = cb_pic_enable_irq;
-               hwit->disable  = cb_pic_disable_irq;
-               hwit->ack      = irq_nop;
-               hwit->end      = irq_nop;
-
-               /* Initialize kernel IRQ infrastructure for this interrupt.  */
-               init_irq_handlers(init->base, init->num, init->interval, hwit);
-       }
-}
diff --git a/arch/v850/kernel/rte_me2_cb.ld b/arch/v850/kernel/rte_me2_cb.ld
deleted file mode 100644 (file)
index cf07660..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Linker script for the Midas labs RTE-V850E/ME2-CB evaluation board
-   (CONFIG_RTE_CB_ME2), with kernel in SDRAM.  */
-
-MEMORY {
-       /* 128Kbyte of IRAM */
-       IRAM : ORIGIN = 0x00000000, LENGTH = 0x00020000
-
-       /* 32MB of SDRAM.  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-#define KRAM SDRAM
-
-SECTIONS {
-       .text : {
-               __kram_start = . ;
-               TEXT_CONTENTS
-               INTV_CONTENTS   /* copy to iRAM (0x0-0x620) */
-       } > KRAM
-
-       .data : {
-               DATA_CONTENTS
-               BSS_CONTENTS
-               RAMK_INIT_CONTENTS
-               __kram_end = . ;
-               BOOTMAP_CONTENTS
-       } > KRAM
-       
-       .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/rte_nb85e_cb-multi.ld b/arch/v850/kernel/rte_nb85e_cb-multi.ld
deleted file mode 100644 (file)
index de347b4..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Linker script for the Midas labs RTE-NB85E-CB evaluation board
-   (CONFIG_RTE_CB_NB85E), with the Multi debugger ROM monitor .  */
-
-MEMORY {
-       /* 1MB of SRAM; we can't use the last 96KB, because it's used by
-          the monitor scratch-RAM.  This memory is mirrored 4 times.  */
-       SRAM  : ORIGIN = SRAM_ADDR,  LENGTH = (SRAM_SIZE - MON_SCRATCH_SIZE)
-       /* Monitor scratch RAM; only the interrupt vectors should go here.  */
-       MRAM  : ORIGIN = MON_SCRATCH_ADDR,  LENGTH = MON_SCRATCH_SIZE
-       /* 16MB of SDRAM.  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-#ifdef CONFIG_RTE_CB_NB85E_KSRAM
-# define KRAM SRAM
-#else
-# define KRAM SDRAM
-#endif
-
-SECTIONS {
-       /* We can't use RAMK_KRAM_CONTENTS because that puts the whole
-          kernel in a single ELF segment, and the Multi debugger (which
-          we use to load the kernel) appears to have bizarre problems
-          dealing with it.  */
-
-       .text : {
-               __kram_start = . ;
-               TEXT_CONTENTS
-       } > KRAM
-
-       .data : {
-               DATA_CONTENTS
-               BSS_CONTENTS
-               RAMK_INIT_CONTENTS
-               __kram_end = . ;
-               BOOTMAP_CONTENTS
-
-               /* The address at which the interrupt vectors are initially
-                  loaded by the loader.  We can't load the interrupt vectors
-                  directly into their target location, because the monitor
-                  ROM for the GHS Multi debugger barfs if we try.
-                  Unfortunately, Multi also doesn't deal correctly with ELF
-                  sections where the LMA and VMA differ (it just ignores the
-                  LMA), so we can't use that feature to work around the
-                  problem!  What we do instead is just put the interrupt
-                  vectors into a normal section, and have the
-                  `mach_early_init' function for Midas boards do the
-                  necessary copying and relocation at runtime (this section
-                  basically only contains `jr' instructions, so it's not
-                  that hard).  */
-               . = ALIGN (0x10) ;
-               __intv_load_start = . ;
-               INTV_CONTENTS
-       } > KRAM
-
-       .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/rte_nb85e_cb.c b/arch/v850/kernel/rte_nb85e_cb.c
deleted file mode 100644 (file)
index b4a045d..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * arch/v850/kernel/rte_nb85e_cb.c -- Midas labs RTE-V850E/NB85E-CB board
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/v850e.h>
-#include <asm/rte_nb85e_cb.h>
-
-#include "mach.h"
-
-void __init mach_early_init (void)
-{
-       /* Configure caching; some possible settings:
-
-            BHC = 0x0000, DCC = 0x0000  -- all caching disabled
-            BHC = 0x0040, DCC = 0x0000  -- SDRAM: icache only
-            BHC = 0x0080, DCC = 0x0C00  -- SDRAM: write-back dcache only
-            BHC = 0x00C0, DCC = 0x0C00  -- SDRAM: icache + write-back dcache
-            BHC = 0x00C0, DCC = 0x0800  -- SDRAM: icache + write-thru dcache
-
-          We can only cache SDRAM (we can't use cache SRAM because it's in
-          the same memory region as the on-chip RAM and I/O space).
-
-          Unfortunately, the dcache seems to be buggy, so we only use the
-          icache for now.  */
-       v850e_cache_enable (0x0040 /*BHC*/, 0x0003 /*ICC*/, 0x0000 /*DCC*/);
-
-       rte_cb_early_init ();
-}
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
-                                  unsigned long *ram_len)
-{
-       /* We just use SDRAM here.  */
-       *ram_start = SDRAM_ADDR;
-       *ram_len = SDRAM_SIZE;
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
-       tv->tv_sec = 0;
-       tv->tv_nsec = 0;
-}
-
-/* Called before configuring an on-chip UART.  */
-void rte_nb85e_cb_uart_pre_configure (unsigned chan,
-                                   unsigned cflags, unsigned baud)
-{
-       /* The RTE-NB85E-CB connects some general-purpose I/O pins on the
-          CPU to the RTS/CTS lines the UART's serial connection, as follows:
-          P00 = CTS (in), P01 = DSR (in), P02 = RTS (out), P03 = DTR (out). */
-
-       TEG_PORT0_PM = 0x03;    /* P00 and P01 inputs, P02 and P03 outputs */
-       TEG_PORT0_IO = 0x03;    /* Accept input */
-
-       /* Do pre-configuration for the actual UART.  */
-       teg_uart_pre_configure (chan, cflags, baud);
-}
-
-void __init mach_init_irqs (void)
-{
-       teg_init_irqs ();
-       rte_cb_init_irqs ();
-}
diff --git a/arch/v850/kernel/rte_nb85e_cb.ld b/arch/v850/kernel/rte_nb85e_cb.ld
deleted file mode 100644 (file)
index b672f48..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Linker script for the Midas labs RTE-NB85E-CB evaluation board
-   (CONFIG_RTE_CB_NB85E).  */
-
-MEMORY {
-       LOW   : ORIGIN = 0x0,        LENGTH = 0x00100000
-       /* 1MB of SRAM  This memory is mirrored 4 times.  */
-       SRAM  : ORIGIN = SRAM_ADDR,  LENGTH = SRAM_SIZE
-       /* 16MB of SDRAM.  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-#ifdef CONFIG_RTE_CB_NB85E_KSRAM
-# define KRAM SRAM
-#else
-# define KRAM SDRAM
-#endif
-
-SECTIONS {
-       .intv : { INTV_CONTENTS } > LOW
-       .sram : { RAMK_KRAM_CONTENTS } > KRAM
-       .root : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
deleted file mode 100644 (file)
index a0a8456..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * arch/v850/kernel/setup.c -- Arch-dependent initialization functions
- *
- *  Copyright (C) 2001,02,03,05,06  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03,05,06  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/swap.h>                /* we don't have swap, but for nr_free_pages */
-#include <linux/irq.h>
-#include <linux/reboot.h>
-#include <linux/personality.h>
-#include <linux/major.h>
-#include <linux/root_dev.h>
-#include <linux/mtd/mtd.h>
-#include <linux/init.h>
-
-#include <asm/irq.h>
-#include <asm/setup.h>
-
-#include "mach.h"
-
-/* These symbols are all defined in the linker map to delineate various
-   statically allocated regions of memory.  */
-
-extern char _intv_start, _intv_end;
-/* `kram' is only used if the kernel uses part of normal user RAM.  */
-extern char _kram_start __attribute__ ((__weak__));
-extern char _kram_end __attribute__ ((__weak__));
-extern char _init_start, _init_end;
-extern char _bootmap;
-extern char _stext, _etext, _sdata, _edata, _sbss, _ebss;
-/* Many platforms use an embedded root image.  */
-extern char _root_fs_image_start __attribute__ ((__weak__));
-extern char _root_fs_image_end __attribute__ ((__weak__));
-
-
-char __initdata command_line[COMMAND_LINE_SIZE];
-
-/* Memory not used by the kernel.  */
-static unsigned long total_ram_pages;
-
-/* System RAM.  */
-static unsigned long ram_start = 0, ram_len = 0;
-
-
-#define ADDR_TO_PAGE_UP(x)   ((((unsigned long)x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define ADDR_TO_PAGE(x)             (((unsigned long)x) >> PAGE_SHIFT)
-#define PAGE_TO_ADDR(x)             (((unsigned long)x) << PAGE_SHIFT)
-
-static void init_mem_alloc (unsigned long ram_start, unsigned long ram_len);
-
-void set_mem_root (void *addr, size_t len, char *cmd_line);
-
-
-void __init setup_arch (char **cmdline)
-{
-       /* Keep a copy of command line */
-       *cmdline = command_line;
-       memcpy (boot_command_line, command_line, COMMAND_LINE_SIZE);
-       boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
-
-       console_verbose ();
-
-       init_mm.start_code = (unsigned long) &_stext;
-       init_mm.end_code = (unsigned long) &_etext;
-       init_mm.end_data = (unsigned long) &_edata;
-       init_mm.brk = (unsigned long) &_kram_end;
-
-       /* Find out what mem this machine has.  */
-       mach_get_physical_ram (&ram_start, &ram_len);
-       /* ... and tell the kernel about it.  */
-       init_mem_alloc (ram_start, ram_len);
-
-       printk (KERN_INFO "CPU: %s\nPlatform: %s\n",
-               CPU_MODEL_LONG, PLATFORM_LONG);
-
-       /* do machine-specific setups.  */
-       mach_setup (cmdline);
-
-#ifdef CONFIG_MTD
-       if (!ROOT_DEV && &_root_fs_image_end > &_root_fs_image_start)
-               set_mem_root (&_root_fs_image_start,
-                             &_root_fs_image_end - &_root_fs_image_start,
-                             *cmdline);
-#endif
-}
-
-void __init trap_init (void)
-{
-}
-
-#ifdef CONFIG_MTD
-
-/* From drivers/mtd/devices/slram.c */
-#define SLRAM_BLK_SZ 0x4000
-
-/* Set the root filesystem to be the given memory region.
-   Some parameter may be appended to CMD_LINE.  */
-void set_mem_root (void *addr, size_t len, char *cmd_line)
-{
-       /* Some sort of idiocy in MTD means we must supply a length that's
-          a multiple of SLRAM_BLK_SZ.  We just round up the real length,
-          as the file system shouldn't attempt to access anything beyond
-          the end of the image anyway.  */
-       len = (((len - 1) + SLRAM_BLK_SZ) / SLRAM_BLK_SZ) * SLRAM_BLK_SZ;
-
-       /* The only way to pass info to the MTD slram driver is via
-          the command line.  */
-       if (*cmd_line) {
-               cmd_line += strlen (cmd_line);
-               *cmd_line++ = ' ';
-       }
-       sprintf (cmd_line, "slram=root,0x%x,+0x%x", (u32)addr, (u32)len);
-
-       ROOT_DEV = MKDEV (MTD_BLOCK_MAJOR, 0);
-}
-#endif
-
-\f
-static void irq_nop (unsigned irq) { }
-static unsigned irq_zero (unsigned irq) { return 0; }
-
-static void nmi_end (unsigned irq)
-{
-       if (irq != IRQ_NMI (0)) {
-               printk (KERN_CRIT "NMI %d is unrecoverable; restarting...",
-                       irq - IRQ_NMI (0));
-               machine_restart (0);
-       }
-}
-
-static struct hw_interrupt_type nmi_irq_type = {
-       .typename = "NMI",
-       .startup = irq_zero,            /* startup */
-       .shutdown = irq_nop,            /* shutdown */
-       .enable = irq_nop,              /* enable */
-       .disable = irq_nop,             /* disable */
-       .ack = irq_nop,         /* ack */
-       .end = nmi_end,         /* end */
-};
-
-void __init init_IRQ (void)
-{
-       init_irq_handlers (0, NUM_MACH_IRQS, 1, 0);
-       init_irq_handlers (IRQ_NMI (0), NUM_NMIS, 1, &nmi_irq_type);
-       mach_init_irqs ();
-}
-
-\f
-void __init mem_init (void)
-{
-       max_mapnr = MAP_NR (ram_start + ram_len);
-
-       num_physpages = ADDR_TO_PAGE (ram_len);
-
-       total_ram_pages = free_all_bootmem ();
-
-       printk (KERN_INFO
-               "Memory: %luK/%luK available"
-               " (%luK kernel code, %luK data)\n",
-               PAGE_TO_ADDR (nr_free_pages()) / 1024,
-               ram_len / 1024,
-               ((unsigned long)&_etext - (unsigned long)&_stext) / 1024,
-               ((unsigned long)&_ebss - (unsigned long)&_sdata) / 1024);
-}
-
-void free_initmem (void)
-{
-       unsigned long ram_end = ram_start + ram_len;
-       unsigned long start = PAGE_ALIGN ((unsigned long)(&_init_start));
-
-       if (start >= ram_start && start < ram_end) {
-               unsigned long addr;
-               unsigned long end = PAGE_ALIGN ((unsigned long)(&_init_end));
-
-               if (end > ram_end)
-                       end = ram_end;
-
-               printk("Freeing unused kernel memory: %ldK freed\n",
-                      (end - start) / 1024);
-
-               for (addr = start; addr < end; addr += PAGE_SIZE) {
-                       struct page *page = virt_to_page (addr);
-                       ClearPageReserved (page);
-                       init_page_count (page);
-                       __free_page (page);
-                       total_ram_pages++;
-               }
-       }
-}
-
-\f
-/* Initialize the `bootmem allocator'.  RAM_START and RAM_LEN identify
-   what RAM may be used.  */
-static void __init
-init_bootmem_alloc (unsigned long ram_start, unsigned long ram_len)
-{
-       /* The part of the kernel that's in the same managed RAM space
-          used for general allocation.  */
-       unsigned long kram_start = (unsigned long)&_kram_start;
-       unsigned long kram_end = (unsigned long)&_kram_end;
-       /* End of the managed RAM space.  */
-       unsigned long ram_end = ram_start + ram_len;
-       /* Address range of the interrupt vector table.  */
-       unsigned long intv_start = (unsigned long)&_intv_start;
-       unsigned long intv_end = (unsigned long)&_intv_end;
-       /* True if the interrupt vectors are in the managed RAM area.  */
-       int intv_in_ram = (intv_end > ram_start && intv_start < ram_end);
-       /* True if the interrupt vectors are inside the kernel's RAM.  */
-       int intv_in_kram = (intv_end > kram_start && intv_start < kram_end);
-       /* A pointer to an optional function that reserves platform-specific
-          memory regions.  We declare the pointer `volatile' to avoid gcc
-          turning the call into a static call (the problem is that since
-          it's a weak symbol, a static call may end up trying to reference
-          the location 0x0, which is not always reachable).  */
-       void (*volatile mrb) (void) = mach_reserve_bootmem;
-       /* The bootmem allocator's allocation bitmap.  */
-       unsigned long bootmap = (unsigned long)&_bootmap;
-       unsigned long bootmap_len;
-
-       /* Round bootmap location up to next page.  */
-       bootmap = PAGE_TO_ADDR (ADDR_TO_PAGE_UP (bootmap));
-
-       /* Initialize bootmem allocator.  */
-       bootmap_len = init_bootmem_node (NODE_DATA (0),
-                                        ADDR_TO_PAGE (bootmap),
-                                        ADDR_TO_PAGE (PAGE_OFFSET),
-                                        ADDR_TO_PAGE (ram_end));
-
-       /* Now make the RAM actually allocatable (it starts out `reserved'). */
-       free_bootmem (ram_start, ram_len);
-
-       if (kram_end > kram_start)
-               /* Reserve the RAM part of the kernel's address space, so it
-                  doesn't get allocated.  */
-               reserve_bootmem(kram_start, kram_end - kram_start,
-                               BOOTMEM_DEFAULT);
-       
-       if (intv_in_ram && !intv_in_kram)
-               /* Reserve the interrupt vector space.  */
-               reserve_bootmem(intv_start, intv_end - intv_start,
-                               BOOTMEM_DEFAULT);
-
-       if (bootmap >= ram_start && bootmap < ram_end)
-               /* Reserve the bootmap space.  */
-               reserve_bootmem(bootmap, bootmap_len,
-                               BOOTMEM_DEFAULT);
-
-       /* Reserve the memory used by the root filesystem image if it's
-          in RAM.  */
-       if (&_root_fs_image_end > &_root_fs_image_start
-           && (unsigned long)&_root_fs_image_start >= ram_start
-           && (unsigned long)&_root_fs_image_start < ram_end)
-               reserve_bootmem ((unsigned long)&_root_fs_image_start,
-                                &_root_fs_image_end - &_root_fs_image_start,
-                                BOOTMEM_DEFAULT);
-
-       /* Let the platform-dependent code reserve some too.  */
-       if (mrb)
-               (*mrb) ();
-}
-
-/* Tell the kernel about what RAM it may use for memory allocation.  */
-static void __init
-init_mem_alloc (unsigned long ram_start, unsigned long ram_len)
-{
-       unsigned i;
-       unsigned long zones_size[MAX_NR_ZONES];
-
-       init_bootmem_alloc (ram_start, ram_len);
-
-       for (i = 0; i < MAX_NR_ZONES; i++)
-               zones_size[i] = 0;
-
-       /* We stuff all the memory into one area, which includes the
-          initial gap from PAGE_OFFSET to ram_start.  */
-       zones_size[ZONE_DMA]
-               = ADDR_TO_PAGE (ram_len + (ram_start - PAGE_OFFSET));
-
-       /* The allocator is very picky about the address of the first
-          allocatable page -- it must be at least as aligned as the
-          maximum allocation -- so try to detect cases where it will get
-          confused and signal them at compile time (this is a common
-          problem when porting to a new platform with ).  There is a
-          similar runtime check in free_area_init_core.  */
-#if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1))
-#error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it)
-#endif
-       NODE_DATA(0)->node_mem_map = NULL;
-       free_area_init_node (0, NODE_DATA(0), zones_size,
-                            ADDR_TO_PAGE (PAGE_OFFSET), 0);
-}
-
-\f
-
-/* Taken from m68knommu */
-void show_mem(void)
-{
-    unsigned long i;
-    int free = 0, total = 0, reserved = 0, shared = 0;
-    int cached = 0;
-
-    printk(KERN_INFO "\nMem-info:\n");
-    show_free_areas();
-    i = max_mapnr;
-    while (i-- > 0) {
-       total++;
-       if (PageReserved(mem_map+i))
-           reserved++;
-       else if (PageSwapCache(mem_map+i))
-           cached++;
-       else if (!page_count(mem_map+i))
-           free++;
-       else
-           shared += page_count(mem_map+i) - 1;
-    }
-    printk(KERN_INFO "%d pages of RAM\n",total);
-    printk(KERN_INFO "%d free pages\n",free);
-    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);
-}
diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
deleted file mode 100644 (file)
index bf166e7..0000000
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * arch/v850/kernel/signal.c -- Signal handling
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *  Copyright (C) 1999,2000,2002  Niibe Yutaka & Kaz Kojima
- *  Copyright (C) 1991,1992  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.
- *
- * 1997-11-28  Modified for POSIX.1b signals by Richard Henderson
- *
- * This file was derived from the sh version, arch/sh/kernel/signal.c
- */
-
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
-#include <linux/personality.h>
-#include <linux/tty.h>
-
-#include <asm/ucontext.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/pgalloc.h>
-#include <asm/thread_info.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.
- */
-asmlinkage int
-sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
-{
-       sigset_t saveset;
-
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs->gpr[GPR_RVAL] = -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,
-                 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->gpr[GPR_RVAL] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
-}
-
-asmlinkage int 
-sys_sigaction(int sig, const struct old_sigaction *act,
-             struct old_sigaction *oact)
-{
-       struct k_sigaction new_ka, old_ka;
-       int ret;
-
-       if (act) {
-               old_sigset_t mask;
-               if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
-                   __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-                       return -EFAULT;
-               __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-               __get_user(mask, &act->sa_mask);
-               siginitset(&new_ka.sa.sa_mask, mask);
-       }
-
-       ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-       if (!ret && oact) {
-               if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-                   __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-                       return -EFAULT;
-               __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-               __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-       }
-
-       return ret;
-}
-
-asmlinkage int
-sys_sigaltstack(const stack_t *uss, stack_t *uoss,
-               struct pt_regs *regs)
-{
-       return do_sigaltstack(uss, uoss, regs->gpr[GPR_SP]);
-}
-
-
-/*
- * Do a signal return; undo the signal stack.
- */
-
-struct sigframe
-{
-       struct sigcontext sc;
-       unsigned long extramask[_NSIG_WORDS-1];
-       unsigned long tramp[2]; /* signal trampoline */
-};
-
-struct rt_sigframe
-{
-       struct siginfo info;
-       struct ucontext uc;
-       unsigned long tramp[2]; /* signal trampoline */
-};
-
-static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p)
-{
-       unsigned int err = 0;
-
-#define COPY(x)                err |= __get_user(regs->x, &sc->regs.x)
-       COPY(gpr[0]);   COPY(gpr[1]);   COPY(gpr[2]);   COPY(gpr[3]);
-       COPY(gpr[4]);   COPY(gpr[5]);   COPY(gpr[6]);   COPY(gpr[7]);
-       COPY(gpr[8]);   COPY(gpr[9]);   COPY(gpr[10]);  COPY(gpr[11]);
-       COPY(gpr[12]);  COPY(gpr[13]);  COPY(gpr[14]);  COPY(gpr[15]);
-       COPY(gpr[16]);  COPY(gpr[17]);  COPY(gpr[18]);  COPY(gpr[19]);
-       COPY(gpr[20]);  COPY(gpr[21]);  COPY(gpr[22]);  COPY(gpr[23]);
-       COPY(gpr[24]);  COPY(gpr[25]);  COPY(gpr[26]);  COPY(gpr[27]);
-       COPY(gpr[28]);  COPY(gpr[29]);  COPY(gpr[30]);  COPY(gpr[31]);
-       COPY(pc);       COPY(psw);
-       COPY(ctpc);     COPY(ctpsw);    COPY(ctbp);
-#undef COPY
-
-       return err;
-}
-
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
-{
-       struct sigframe *frame = (struct sigframe *)regs->gpr[GPR_SP];
-       sigset_t set;
-       int rval;
-
-       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-               goto badframe;
-
-       if (__get_user(set.sig[0], &frame->sc.oldmask)
-           || (_NSIG_WORDS > 1
-               && __copy_from_user(&set.sig[1], &frame->extramask,
-                                   sizeof(frame->extramask))))
-               goto badframe;
-
-       sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       if (restore_sigcontext(regs, &frame->sc, &rval))
-               goto badframe;
-       return rval;
-
-badframe:
-       force_sig(SIGSEGV, current);
-       return 0;
-}
-
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
-{
-       struct rt_sigframe *frame = (struct rt_sigframe *)regs->gpr[GPR_SP];
-       sigset_t set;
-       stack_t st;
-       int rval;
-
-       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-               goto badframe;
-
-       if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
-               goto badframe;
-
-       sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
-               goto badframe;
-
-       if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
-               goto badframe;
-       /* It is more difficult to avoid calling this function than to
-          call it and ignore errors.  */
-       do_sigaltstack(&st, NULL, regs->gpr[GPR_SP]);
-
-       return rval;
-
-badframe:
-       force_sig(SIGSEGV, current);
-       return 0;
-}      
-
-/*
- * Set up a signal frame.
- */
-
-static int
-setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
-                unsigned long mask)
-{
-       int err = 0;
-
-#define COPY(x)                err |= __put_user(regs->x, &sc->regs.x)
-       COPY(gpr[0]);   COPY(gpr[1]);   COPY(gpr[2]);   COPY(gpr[3]);
-       COPY(gpr[4]);   COPY(gpr[5]);   COPY(gpr[6]);   COPY(gpr[7]);
-       COPY(gpr[8]);   COPY(gpr[9]);   COPY(gpr[10]);  COPY(gpr[11]);
-       COPY(gpr[12]);  COPY(gpr[13]);  COPY(gpr[14]);  COPY(gpr[15]);
-       COPY(gpr[16]);  COPY(gpr[17]);  COPY(gpr[18]);  COPY(gpr[19]);
-       COPY(gpr[20]);  COPY(gpr[21]);  COPY(gpr[22]);  COPY(gpr[23]);
-       COPY(gpr[24]);  COPY(gpr[25]);  COPY(gpr[26]);  COPY(gpr[27]);
-       COPY(gpr[28]);  COPY(gpr[29]);  COPY(gpr[30]);  COPY(gpr[31]);
-       COPY(pc);       COPY(psw);
-       COPY(ctpc);     COPY(ctpsw);    COPY(ctbp);
-#undef COPY
-
-       err |= __put_user(mask, &sc->oldmask);
-
-       return err;
-}
-
-/*
- * Determine which stack to use..
- */
-static inline void *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
-       /* Default to using normal stack */
-       unsigned long sp = regs->gpr[GPR_SP];
-
-       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
-               sp = current->sas_ss_sp + current->sas_ss_size;
-
-       return (void *)((sp - frame_size) & -8UL);
-}
-
-static void setup_frame(int sig, struct k_sigaction *ka,
-                       sigset_t *set, struct pt_regs *regs)
-{
-       struct sigframe *frame;
-       int err = 0;
-       int signal;
-
-       frame = get_sigframe(ka, regs, sizeof(*frame));
-
-       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-               goto give_sigsegv;
-
-       signal = current_thread_info()->exec_domain
-               && current_thread_info()->exec_domain->signal_invmap
-               && sig < 32
-               ? current_thread_info()->exec_domain->signal_invmap[sig]
-               : sig;
-
-       err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
-
-       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->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
-       } else {
-               /* Note, these encodings are _little endian_!  */
-
-               /* addi  __NR_sigreturn, r0, r12  */
-               err |= __put_user(0x6600 | (__NR_sigreturn << 16),
-                                 frame->tramp + 0);
-               /* trap 0 */
-               err |= __put_user(0x010007e0,
-                                 frame->tramp + 1);
-
-               regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
-
-               flush_cache_sigtramp (regs->gpr[GPR_LP]);
-       }
-
-       if (err)
-               goto give_sigsegv;
-
-       /* Set up registers for signal handler.  */
-       regs->pc = (v850_reg_t) ka->sa.sa_handler;
-       regs->gpr[GPR_SP] = (v850_reg_t)frame;
-       /* Signal handler args:  */
-       regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
-       regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->sc;/* arg 1: sigcontext */
-
-       set_fs(USER_DS);
-
-#if DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=%p pc=%08lx ra=%08lx\n",
-               current->comm, current->pid, frame, regs->pc, );
-#endif
-
-       return;
-
-give_sigsegv:
-       force_sigsegv(sig, current);
-}
-
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-                          sigset_t *set, struct pt_regs *regs)
-{
-       struct rt_sigframe *frame;
-       int err = 0;
-       int signal;
-
-       frame = get_sigframe(ka, regs, sizeof(*frame));
-
-       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-               goto give_sigsegv;
-
-       signal = current_thread_info()->exec_domain
-               && current_thread_info()->exec_domain->signal_invmap
-               && sig < 32
-               ? current_thread_info()->exec_domain->signal_invmap[sig]
-               : sig;
-
-       err |= copy_siginfo_to_user(&frame->info, info);
-
-       /* Create the ucontext.  */
-       err |= __put_user(0, &frame->uc.uc_flags);
-       err |= __put_user(0, &frame->uc.uc_link);
-       err |= __put_user((void *)current->sas_ss_sp,
-                         &frame->uc.uc_stack.ss_sp);
-       err |= __put_user(sas_ss_flags(regs->gpr[GPR_SP]),
-                         &frame->uc.uc_stack.ss_flags);
-       err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-       err |= setup_sigcontext(&frame->uc.uc_mcontext,
-                               regs, set->sig[0]);
-       err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-
-       /* Set up to return from userspace.  If provided, use a stub
-          already in userspace.  */
-       if (ka->sa.sa_flags & SA_RESTORER) {
-               regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
-       } else {
-               /* Note, these encodings are _little endian_!  */
-
-               /* addi  __NR_sigreturn, r0, r12  */
-               err |= __put_user(0x6600 | (__NR_sigreturn << 16),
-                                 frame->tramp + 0);
-               /* trap 0 */
-               err |= __put_user(0x010007e0,
-                                 frame->tramp + 1);
-
-               regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
-
-               flush_cache_sigtramp (regs->gpr[GPR_LP]);
-       }
-
-       if (err)
-               goto give_sigsegv;
-
-       /* Set up registers for signal handler.  */
-       regs->pc = (v850_reg_t) ka->sa.sa_handler;
-       regs->gpr[GPR_SP] = (v850_reg_t)frame;
-       /* Signal handler args:  */
-       regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
-       regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->info; /* arg 1: siginfo */
-       regs->gpr[GPR_ARG2] = (v850_reg_t)&frame->uc; /* arg 2: ucontext */
-
-       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
-
-       return;
-
-give_sigsegv:
-       force_sigsegv(sig, current);
-}
-
-/*
- * OK, we're invoking a handler
- */    
-
-static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-             sigset_t *oldset, struct pt_regs * regs)
-{
-       /* Are we from a system call? */
-       if (PT_REGS_SYSCALL (regs)) {
-               /* If so, check system call restarting.. */
-               switch (regs->gpr[GPR_RVAL]) {
-               case -ERESTART_RESTARTBLOCK:
-                       current_thread_info()->restart_block.fn =
-                               do_no_restart_syscall;
-                       /* fall through */
-               case -ERESTARTNOHAND:
-                       regs->gpr[GPR_RVAL] = -EINTR;
-                       break;
-
-               case -ERESTARTSYS:
-                       if (!(ka->sa.sa_flags & SA_RESTART)) {
-                               regs->gpr[GPR_RVAL] = -EINTR;
-                               break;
-                       }
-                       /* fallthrough */
-               case -ERESTARTNOINTR:
-                       regs->gpr[12] = PT_REGS_SYSCALL (regs);
-                       regs->pc -= 4; /* Size of `trap 0' insn.  */
-               }
-
-               PT_REGS_SET_SYSCALL (regs, 0);
-       }
-
-       /* Set up the stack frame */
-       if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame(sig, ka, info, oldset, regs);
-       else
-               setup_frame(sig, ka, oldset, regs);
-
-       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);
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- *
- * Note that we go through the signals twice: once to check the signals that
- * 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)
-{
-       siginfo_t info;
-       int signr;
-       struct k_sigaction ka;
-
-       /*
-        * We want the common case to go fast, which
-        * is why we may in certain cases get here from
-        * kernel mode. Just return without doing anything
-        * if so.
-        */
-       if (!user_mode(regs))
-               return 1;
-
-       if (!oldset)
-               oldset = &current->blocked;
-
-       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-       if (signr > 0) {
-               /* Whee!  Actually deliver the signal.  */
-               handle_signal(signr, &info, &ka, oldset, regs);
-               return 1;
-       }
-
-       /* Did we come from a system call? */
-       if (PT_REGS_SYSCALL (regs)) {
-               int rval = (int)regs->gpr[GPR_RVAL];
-               /* Restart the system call - no handlers present */
-               if (rval == -ERESTARTNOHAND
-                   || rval == -ERESTARTSYS
-                   || rval == -ERESTARTNOINTR)
-               {
-                       regs->gpr[12] = PT_REGS_SYSCALL (regs);
-                       regs->pc -= 4; /* Size of `trap 0' insn.  */
-               }
-               else if (rval == -ERESTART_RESTARTBLOCK) {
-                       regs->gpr[12] = __NR_restart_syscall;
-                       regs->pc -= 4; /* Size of `trap 0' insn.  */
-               }
-       }
-       return 0;
-}
diff --git a/arch/v850/kernel/sim.c b/arch/v850/kernel/sim.c
deleted file mode 100644 (file)
index 467b4aa..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * arch/v850/kernel/sim.c -- Machine-specific stuff for GDB v850e simulator
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-#include <asm/simsyscall.h>
-
-#include "mach.h"
-
-/* The name of a file containing the root filesystem.  */
-#define ROOT_FS "rootfs.image"
-
-extern void simcons_setup (void);
-extern void simcons_poll_ttys (void);
-extern void set_mem_root (void *addr, size_t len, char *cmd_line);
-
-static int read_file (const char *name,
-                     unsigned long *addr, unsigned long *len,
-                     const char **err);
-
-void __init mach_setup (char **cmdline)
-{
-       const char *err;
-       unsigned long root_dev_addr, root_dev_len;
-
-       simcons_setup ();
-
-       printk (KERN_INFO "Reading root filesystem: %s", ROOT_FS);
-
-       if (read_file (ROOT_FS, &root_dev_addr, &root_dev_len, &err)) {
-               printk (" (size %luK)\n", root_dev_len / 1024);
-               set_mem_root ((void *)root_dev_addr, (size_t)root_dev_len,
-                             *cmdline);
-       } else
-               printk ("...%s failed!\n", err);
-}
-
-void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
-{
-       *ram_start = RAM_ADDR;
-       *ram_len = RAM_SIZE;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
-       /* ...do magic timer initialization?...  */
-       mach_tick = simcons_poll_ttys;
-       setup_irq (0, timer_action);
-}
-
-\f
-static void irq_nop (unsigned irq) { }
-static unsigned irq_zero (unsigned irq) { return 0; }
-
-static struct hw_interrupt_type sim_irq_type = {
-       .typename = "IRQ",
-       .startup = irq_zero,            /* startup */
-       .shutdown = irq_nop,            /* shutdown */
-       .enable = irq_nop,              /* enable */
-       .disable = irq_nop,             /* disable */
-       .ack = irq_nop,         /* ack */
-       .end = irq_nop,         /* end */
-};
-
-void __init mach_init_irqs (void)
-{
-       init_irq_handlers (0, NUM_MACH_IRQS, 1, &sim_irq_type);
-}
-
-\f
-void mach_gettimeofday (struct timespec *tv)
-{
-       long timeval[2], timezone[2];
-       int rval = V850_SIM_SYSCALL (gettimeofday, timeval, timezone);
-       if (rval == 0) {
-               tv->tv_sec = timeval[0];
-               tv->tv_nsec = timeval[1] * 1000;
-       }
-}
-
-void machine_restart (char *__unused)
-{
-       V850_SIM_SYSCALL (write, 1, "RESTART\n", 8);
-       V850_SIM_SYSCALL (exit, 0);
-}
-
-void machine_halt (void)
-{
-       V850_SIM_SYSCALL (write, 1, "HALT\n", 5);
-       V850_SIM_SYSCALL (exit, 0);
-}
-
-void machine_power_off (void)
-{
-       V850_SIM_SYSCALL (write, 1, "POWER OFF\n", 10);
-       V850_SIM_SYSCALL (exit, 0);
-}
-
-\f
-/* Load data from a file called NAME into ram.  The address and length
-   of the data image are returned in ADDR and LEN.  */
-static int __init
-read_file (const char *name,
-          unsigned long *addr, unsigned long *len,
-          const char **err)
-{
-       int rval, fd;
-       unsigned long cur, left;
-       /* Note this is not a normal stat buffer, it's an ad-hoc
-          structure defined by the simulator.  */
-       unsigned long stat_buf[10];
-
-       /* Stat the file to find out the length.  */
-       rval = V850_SIM_SYSCALL (stat, name, stat_buf);
-       if (rval < 0) {
-               if (err) *err = "stat";
-               return 0;
-       }
-       *len = stat_buf[4];
-
-       /* Open the file; `0' is O_RDONLY.  */
-       fd = V850_SIM_SYSCALL (open, name, 0);
-       if (fd < 0) {
-               if (err) *err = "open";
-               return 0;
-       }
-
-       *addr = (unsigned long)alloc_bootmem(*len);
-       if (! *addr) {
-               V850_SIM_SYSCALL (close, fd);
-               if (err) *err = "alloc_bootmem";
-               return 0;
-       }
-
-       cur = *addr;
-       left = *len;
-       while (left > 0) {
-               int chunk = V850_SIM_SYSCALL (read, fd, cur, left);
-               if (chunk <= 0)
-                       break;
-               cur += chunk;
-               left -= chunk;
-       }
-       V850_SIM_SYSCALL (close, fd);
-       if (left > 0) {
-               /* Some read failed.  */
-               free_bootmem (*addr, *len);
-               if (err) *err = "read";
-               return 0;
-       }
-
-       return 1;
-}
diff --git a/arch/v850/kernel/sim.ld b/arch/v850/kernel/sim.ld
deleted file mode 100644 (file)
index 101885f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* Linker script for the gdb v850e simulator (CONFIG_V850E_SIM).  */
-
-MEMORY {
-       /* Interrupt vectors.  */
-       INTV  : ORIGIN = 0x0, LENGTH = 0xe0
-       /* Main RAM.  */
-       RAM   : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE
-}
-
-SECTIONS {
-       .intv : { INTV_CONTENTS } > INTV
-       .ram : { RAMK_KRAM_CONTENTS } > RAM
-}
diff --git a/arch/v850/kernel/sim85e2.c b/arch/v850/kernel/sim85e2.c
deleted file mode 100644 (file)
index 566dde5..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * arch/v850/kernel/sim85e2.c -- Machine-specific stuff for
- *     V850E2 RTL simulator
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-
-#include "mach.h"
-
-
-/* There are 4 possible areas we can use:
-
-     IRAM (1MB) is fast for instruction fetches, but slow for data
-     DRAM (1020KB) is fast for data, but slow for instructions
-     ERAM is cached, so should be fast for both insns and data
-     SDRAM is external DRAM, similar to ERAM
-*/
-
-#define INIT_MEMC_FOR_SDRAM
-#define USE_SDRAM_AREA
-#define KERNEL_IN_SDRAM_AREA
-
-#define DCACHE_MODE    V850E2_CACHE_BTSC_DCM_WT
-/*#define DCACHE_MODE  V850E2_CACHE_BTSC_DCM_WB_ALLOC*/
-
-#ifdef USE_SDRAM_AREA
-#define RAM_START      SDRAM_ADDR
-#define RAM_END                (SDRAM_ADDR + SDRAM_SIZE)
-#else
-/* When we use DRAM, we need to account for the fact that the end of it is
-   used for R0_RAM.  */
-#define RAM_START      DRAM_ADDR
-#define RAM_END                R0_RAM_ADDR
-#endif
-
-
-extern void memcons_setup (void);
-
-
-#ifdef KERNEL_IN_SDRAM_AREA
-#define EARLY_INIT_SECTION_ATTR __attribute__ ((section (".early.text")))
-#else
-#define EARLY_INIT_SECTION_ATTR __init
-#endif
-
-void EARLY_INIT_SECTION_ATTR mach_early_init (void)
-{
-       /* The sim85e2 simulator tracks `undefined' values, so to make
-          debugging easier, we begin by zeroing out all otherwise
-          undefined registers.  This is not strictly necessary.
-
-          The registers we zero are:
-              Every GPR except:
-                  stack-pointer (r3)
-                  task-pointer (r16)
-                  our return addr (r31)
-              Every system register (SPR) that we know about except for
-              the PSW (SPR 5), which we zero except for the
-              disable-interrupts bit.
-       */
-
-       /* GPRs */
-       asm volatile ("             mov r0, r1 ; mov r0, r2              ");
-       asm volatile ("mov r0, r4 ; mov r0, r5 ; mov r0, r6 ; mov r0, r7 ");
-       asm volatile ("mov r0, r8 ; mov r0, r9 ; mov r0, r10; mov r0, r11");
-       asm volatile ("mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15");
-       asm volatile ("             mov r0, r17; mov r0, r18; mov r0, r19");
-       asm volatile ("mov r0, r20; mov r0, r21; mov r0, r22; mov r0, r23");
-       asm volatile ("mov r0, r24; mov r0, r25; mov r0, r26; mov r0, r27");
-       asm volatile ("mov r0, r28; mov r0, r29; mov r0, r30");
-
-       /* SPRs */
-       asm volatile ("ldsr r0, 0;  ldsr r0, 1;  ldsr r0, 2;  ldsr r0, 3");
-       asm volatile ("ldsr r0, 4");
-       asm volatile ("addi 0x20, r0, r1; ldsr r1, 5"); /* PSW */
-       asm volatile ("ldsr r0, 16; ldsr r0, 17; ldsr r0, 18; ldsr r0, 19");
-       asm volatile ("ldsr r0, 20");
-
-
-#ifdef INIT_MEMC_FOR_SDRAM
-       /* Settings for SDRAM controller.  */
-       V850E2_VSWC   = 0x0042;
-       V850E2_BSC    = 0x9286;
-       V850E2_BCT(0) = 0xb000; /* was: 0 */
-       V850E2_BCT(1) = 0x000b;
-       V850E2_ASC    = 0;
-       V850E2_LBS    = 0xa9aa; /* was: 0xaaaa */
-       V850E2_LBC(0) = 0;
-       V850E2_LBC(1) = 0;      /* was: 0x3 */
-       V850E2_BCC    = 0;
-       V850E2_RFS(4) = 0x800a; /* was: 0xf109 */
-       V850E2_SCR(4) = 0x2091; /* was: 0x20a1 */
-       V850E2_RFS(3) = 0x800c;
-       V850E2_SCR(3) = 0x20a1;
-       V850E2_DWC(0) = 0;
-       V850E2_DWC(1) = 0;
-#endif
-
-#if 0
-#ifdef CONFIG_V850E2_SIM85E2S
-       /* Turn on the caches.  */
-       V850E2_CACHE_BTSC = V850E2_CACHE_BTSC_ICM | DCACHE_MODE;
-       V850E2_BHC  = 0x1010;
-#elif CONFIG_V850E2_SIM85E2C
-       V850E2_CACHE_BTSC |= (V850E2_CACHE_BTSC_ICM | V850E2_CACHE_BTSC_DCM0);
-       V850E2_BUSM_BHC = 0xFFFF;
-#endif
-#else
-       V850E2_BHC  = 0;
-#endif
-
-       /* Don't stop the simulator at `halt' instructions.  */
-       SIM85E2_NOTHAL = 1;
-
-       /* Ensure that the simulator halts on a panic, instead of going
-          into an infinite loop inside the panic function.  */
-       panic_timeout = -1;
-}
-
-void __init mach_setup (char **cmdline)
-{
-       memcons_setup ();
-}
-
-void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
-{
-       *ram_start = RAM_START;
-       *ram_len = RAM_END - RAM_START;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
-       /* The simulator actually cycles through all interrupts
-          periodically.  We just pay attention to IRQ0, which gives us
-          1/64 the rate of the periodic interrupts.  */
-       setup_irq (0, timer_action);
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
-       tv->tv_sec = 0;
-       tv->tv_nsec = 0;
-}
-\f
-/* Interrupts */
-
-struct v850e_intc_irq_init irq_inits[] = {
-       { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
-       { 0 }
-};
-struct hw_interrupt_type hw_itypes[1];
-
-/* Initialize interrupts.  */
-void __init mach_init_irqs (void)
-{
-       v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-\f
-
-void machine_halt (void) __attribute__ ((noreturn));
-void machine_halt (void)
-{
-       SIM85E2_SIMFIN = 0;     /* Halt immediately.  */
-       for (;;) {}
-}
-
-void machine_restart (char *__unused)
-{
-       machine_halt ();
-}
-
-void machine_power_off (void)
-{
-       machine_halt ();
-}
-
diff --git a/arch/v850/kernel/sim85e2.ld b/arch/v850/kernel/sim85e2.ld
deleted file mode 100644 (file)
index 7470fd2..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Linker script for the sim85e2c simulator, which is a verilog simulation of
-   the V850E2 NA85E2C cpu core (CONFIG_V850E2_SIM85E2C).  */
-
-MEMORY {
-       /* 1MB of `instruction RAM', starting at 0.
-          Instruction fetches are much faster from IRAM than from DRAM.  */
-       IRAM : ORIGIN = IRAM_ADDR, LENGTH = IRAM_SIZE
-
-       /* 1MB of `data RAM', below and contiguous with the I/O space.
-          Data fetches are much faster from DRAM than from IRAM.  */
-       DRAM : ORIGIN = DRAM_ADDR, LENGTH = DRAM_SIZE
-
-       /* `external ram' (CS1 area), comes after IRAM.  */
-       ERAM : ORIGIN = ERAM_ADDR, LENGTH = ERAM_SIZE
-
-       /* Dynamic RAM; uses memory controller.  */
-       SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
-       .iram : {
-               INTV_CONTENTS
-               *arch/v850/kernel/head.o
-               *(.early.text)
-       } > IRAM
-       .dram : {
-               _memcons_output = . ;
-               . = . + 0x8000 ;
-               _memcons_output_end = . ;
-       } > DRAM
-       .sdram : {
-               /* We stick console output into a buffer here.  */
-               RAMK_KRAM_CONTENTS
-               ROOT_FS_CONTENTS
-       } > SDRAM
-}
diff --git a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c
deleted file mode 100644 (file)
index 9973596..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * arch/v850/kernel/simcons.c -- Console I/O for GDB v850e simulator
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/tty_driver.h>
-#include <linux/init.h>
-
-#include <asm/poll.h>
-#include <asm/string.h>
-#include <asm/simsyscall.h>
-
-\f
-/*  Low-level console. */
-
-static void simcons_write (struct console *co, const char *buf, unsigned len)
-{
-       V850_SIM_SYSCALL (write, 1, buf, len);
-}
-
-static int simcons_read (struct console *co, char *buf, unsigned len)
-{
-       return V850_SIM_SYSCALL (read, 0, buf, len);
-}
-
-static struct tty_driver *tty_driver;
-static struct tty_driver *simcons_device (struct console *c, int *index)
-{
-       *index = c->index;
-       return tty_driver;
-}
-
-static struct console simcons =
-{
-    .name      = "simcons",
-    .write     = simcons_write,
-    .read      = simcons_read,
-    .device    = simcons_device,
-    .flags     = CON_PRINTBUFFER,
-    .index     = -1,
-};
-\f
-/* Higher level TTY interface.  */
-
-int simcons_tty_open (struct tty_struct *tty, struct file *filp)
-{
-       return 0;
-}
-
-int simcons_tty_write (struct tty_struct *tty,
-                      const unsigned char *buf, int count)
-{
-       return V850_SIM_SYSCALL (write, 1, buf, count);
-}
-
-int simcons_tty_write_room (struct tty_struct *tty)
-{
-       /* Completely arbitrary.  */
-       return 0x100000;
-}
-
-int simcons_tty_chars_in_buffer (struct tty_struct *tty)
-{
-       /* We have no buffer.  */
-       return 0;
-}
-
-static const struct tty_operations ops = {
-       .open = simcons_tty_open,
-       .write = simcons_tty_write,
-       .write_room = simcons_tty_write_room,
-       .chars_in_buffer = simcons_tty_chars_in_buffer,
-};
-
-int __init simcons_tty_init (void)
-{
-       struct tty_driver *driver = alloc_tty_driver(1);
-       int err;
-       if (!driver)
-               return -ENOMEM;
-       driver->name = "simcons";
-       driver->major = TTY_MAJOR;
-       driver->minor_start = 64;
-       driver->type = TTY_DRIVER_TYPE_SYSCONS;
-       driver->init_termios = tty_std_termios;
-       tty_set_operations(driver, &ops);
-       err = tty_register_driver(driver);
-       if (err) {
-               put_tty_driver(driver);
-               return err;
-       }
-       tty_driver = driver;
-       return 0;
-}
-/* We use `late_initcall' instead of just `__initcall' as a workaround for
-   the fact that (1) simcons_tty_init can't be called before tty_init,
-   (2) tty_init is called via `module_init', (3) if statically linked,
-   module_init == device_init, and (4) there's no ordering of init lists.
-   We can do this easily because simcons is always statically linked, but
-   other tty drivers that depend on tty_init and which must use
-   `module_init' to declare their init routines are likely to be broken.  */
-late_initcall(simcons_tty_init);
-\f
-/* Poll for input on the console, and if there's any, deliver it to the
-   tty driver.  */
-void simcons_poll_tty (struct tty_struct *tty)
-{
-       char buf[32];   /* Not the nicest way to do it but I need it correct first */
-       int flip = 0, send_break = 0;
-       struct pollfd pfd;
-       pfd.fd = 0;
-       pfd.events = POLLIN;
-
-       if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) {
-               if (pfd.revents & POLLIN) {
-                       /* Real block hardware knows the transfer size before
-                          transfer so the new tty buffering doesn't try to handle
-                          this rather weird simulator specific case well */
-                       int rd = V850_SIM_SYSCALL (read, 0, buf, 32);
-                       if (rd > 0) {
-                               tty_insert_flip_string(tty, buf, rd);
-                               flip = 1;
-                       } else
-                               send_break = 1;
-               } else if (pfd.revents & POLLERR)
-                       send_break = 1;
-       }
-
-       if (send_break) {
-               tty_insert_flip_char (tty, 0, TTY_BREAK);               
-               flip = 1;
-       }
-
-       if (flip)
-               tty_schedule_flip (tty);
-}
-
-void simcons_poll_ttys (void)
-{
-       if (tty_driver && tty_driver->ttys[0])
-               simcons_poll_tty (tty_driver->ttys[0]);
-}
-\f
-void simcons_setup (void)
-{
-       V850_SIM_SYSCALL (make_raw, 0);
-       register_console (&simcons);
-       printk (KERN_INFO "Console: GDB V850E simulator stdio\n");
-}
diff --git a/arch/v850/kernel/syscalls.c b/arch/v850/kernel/syscalls.c
deleted file mode 100644 (file)
index 1a83daf..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * arch/v850/kernel/syscalls.c -- Various system-call definitions not
- *     defined in machine-independent code
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * This file was derived the ppc version, arch/ppc/kernel/syscalls.c
- * ... which was derived from "arch/i386/kernel/sys_i386.c" by Gary Thomas;
- *     modified by Cort Dougan (cort@cs.nmt.edu)
- *     and Paul Mackerras (paulus@cs.anu.edu.au).
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/syscalls.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/mman.h>
-#include <linux/sys.h>
-#include <linux/ipc.h>
-#include <linux/utsname.h>
-#include <linux/file.h>
-
-#include <asm/uaccess.h>
-#include <asm/unistd.h>
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-int
-sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
-{
-       int version, ret;
-
-       version = call >> 16; /* hack for backward compatibility */
-       call &= 0xffff;
-
-       ret = -EINVAL;
-       switch (call) {
-       case SEMOP:
-               ret = sys_semop (first, (struct sembuf *)ptr, second);
-               break;
-       case SEMGET:
-               ret = sys_semget (first, second, third);
-               break;
-       case SEMCTL:
-       {
-               union semun fourth;
-
-               if (!ptr)
-                       break;
-               if ((ret = access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
-                   || (ret = get_user(fourth.__pad, (void **)ptr)))
-                       break;
-               ret = sys_semctl (first, second, third, fourth);
-               break;
-       }
-       case MSGSND:
-               ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third);
-               break;
-       case MSGRCV:
-               switch (version) {
-               case 0: {
-                       struct ipc_kludge tmp;
-
-                       if (!ptr)
-                               break;
-                       if ((ret = access_ok(VERIFY_READ, ptr, sizeof(tmp)) ? 0 : -EFAULT)
-                           || (ret = copy_from_user(&tmp,
-                                               (struct ipc_kludge *) ptr,
-                                               sizeof (tmp))))
-                               break;
-                       ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
-                                         third);
-                       break;
-                       }
-               default:
-                       ret = sys_msgrcv (first, (struct msgbuf *) ptr,
-                                         second, fifth, third);
-                       break;
-               }
-               break;
-       case MSGGET:
-               ret = sys_msgget ((key_t) first, second);
-               break;
-       case MSGCTL:
-               ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
-               break;
-       case SHMAT:
-               switch (version) {
-               default: {
-                       ulong raddr;
-
-                       if ((ret = access_ok(VERIFY_WRITE, (ulong*) third,
-                                              sizeof(ulong)) ? 0 : -EFAULT))
-                               break;
-                       ret = do_shmat (first, (char *) ptr, second, &raddr);
-                       if (ret)
-                               break;
-                       ret = put_user (raddr, (ulong *) third);
-                       break;
-                       }
-               case 1: /* iBCS2 emulator entry point */
-                       if (!segment_eq(get_fs(), get_ds()))
-                               break;
-                       ret = do_shmat (first, (char *) ptr, second,
-                                        (ulong *) third);
-                       break;
-               }
-               break;
-       case SHMDT: 
-               ret = sys_shmdt ((char *)ptr);
-               break;
-       case SHMGET:
-               ret = sys_shmget (first, second, third);
-               break;
-       case SHMCTL:
-               ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
-               break;
-       }
-
-       return ret;
-}
-
-static inline unsigned long
-do_mmap2 (unsigned long addr, size_t len,
-        unsigned long prot, unsigned long flags,
-        unsigned long fd, unsigned long pgoff)
-{
-       struct file * file = NULL;
-       int ret = -EBADF;
-
-       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-       if (! (flags & MAP_ANONYMOUS)) {
-               if (!(file = fget (fd)))
-                       goto out;
-       }
-       
-       down_write (&current->mm->mmap_sem);
-       ret = do_mmap_pgoff (file, addr, len, prot, flags, pgoff);
-       up_write (&current->mm->mmap_sem);
-       if (file)
-               fput (file);
-out:
-       return ret;
-}
-
-unsigned long sys_mmap2 (unsigned long addr, size_t len,
-                       unsigned long prot, unsigned long flags,
-                       unsigned long fd, unsigned long pgoff)
-{
-       return do_mmap2 (addr, len, prot, flags, fd, pgoff);
-}
-
-unsigned long sys_mmap (unsigned long addr, size_t len,
-                      unsigned long prot, unsigned long flags,
-                      unsigned long fd, off_t offset)
-{
-       int err = -EINVAL;
-
-       if (offset & ~PAGE_MASK)
-               goto out;
-
-       err = do_mmap2 (addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
-out:
-       return err;
-}
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename, char *const argv[], char *const envp[])
-{
-       register char *__a __asm__ ("r6") = filename;
-       register void *__b __asm__ ("r7") = argv;
-       register void *__c __asm__ ("r8") = envp;
-       register unsigned long __syscall __asm__ ("r12") = __NR_execve;
-       register unsigned long __ret __asm__ ("r10");
-       __asm__ __volatile__ ("trap 0"
-                       : "=r" (__ret), "=r" (__syscall)
-                       : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
-                       : "r1", "r5", "r11", "r13", "r14",
-                         "r15", "r16", "r17", "r18", "r19");
-       return __ret;
-}
diff --git a/arch/v850/kernel/teg.c b/arch/v850/kernel/teg.c
deleted file mode 100644 (file)
index 699248f..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * arch/v850/kernel/teg.c -- NB85E-TEG cpu chip
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-#include <asm/v850e_timer_d.h>
-
-#include "mach.h"
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
-       /* Select timer interrupt instead of external pin.  */
-       TEG_ISS |= 0x1;
-       /* Start hardware timer.  */
-       v850e_timer_d_configure (0, HZ);
-       /* Install timer interrupt handler.  */
-       setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
-       { "IRQ", 0,             NUM_CPU_IRQS,   1, 7 },
-       { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
-       { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 1, 3 },
-       { "SR",  IRQ_INTSR(0),  IRQ_INTSR_NUM,  1, 4 },
-       { "ST",  IRQ_INTST(0),  IRQ_INTST_NUM,  1, 5 },
-       { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-/* Initialize MA chip interrupts.  */
-void __init teg_init_irqs (void)
-{
-       v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-/* Called before configuring an on-chip UART.  */
-void teg_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
-       /* Enable UART I/O pins instead of external interrupt pins, and
-          UART interrupts instead of external pin interrupts.  */
-       TEG_ISS |= 0x4E;
-}
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
deleted file mode 100644 (file)
index d810c93..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * linux/arch/v850/kernel/time.c -- Arch-dependent timer functions
- *
- *  Copyright (C) 1991, 1992, 1995, 2001, 2002  Linus Torvalds
- *
- * This file contains the v850-specific time handling details.
- * Most of the stuff is located in the machine specific files.
- *
- * 1997-09-10  Updated NTP code according to technical memorandum Jan '96
- *             "A Kernel Model for Precision Timekeeping" by Dave Mills
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/profile.h>
-
-#include <asm/io.h>
-
-#include "mach.h"
-
-#define TICK_SIZE      (tick_nsec / 1000)
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
-{
-#if 0
-       /* last time the cmos clock got updated */
-       static long last_rtc_update=0;
-#endif
-
-       /* may need to kick the hardware timer */
-       if (mach_tick)
-         mach_tick ();
-
-       do_timer (1);
-#ifndef CONFIG_SMP
-       update_process_times(user_mode(regs));
-#endif
-       profile_tick(CPU_PROFILING, regs);
-#if 0
-       /*
-        * If we have an externally synchronized Linux clock, then update
-        * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-        * called as close as possible to 500 ms before the new second starts.
-        */
-       if (ntp_synced() &&
-           xtime.tv_sec > last_rtc_update + 660 &&
-           (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
-           (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
-         if (set_rtc_mmss (xtime.tv_sec) == 0)
-           last_rtc_update = xtime.tv_sec;
-         else
-           last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-       }
-#ifdef CONFIG_HEARTBEAT
-       /* use power LED as a heartbeat instead -- much more useful
-          for debugging -- based on the version for PReP by Cort */
-       /* acts like an actual heart beat -- ie thump-thump-pause... */
-       if (mach_heartbeat) {
-           static unsigned cnt = 0, period = 0, dist = 0;
-
-           if (cnt == 0 || cnt == dist)
-               mach_heartbeat ( 1 );
-           else if (cnt == 7 || cnt == dist+7)
-               mach_heartbeat ( 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 */
-#endif /* 0 */
-
-       return IRQ_HANDLED;
-}
-
-static int timer_dev_id;
-static struct irqaction timer_irqaction = {
-       .handler = timer_interrupt,
-       .flags = IRQF_DISABLED,
-       .mask = CPU_MASK_NONE,
-       .name = "timer",
-       .dev_id = &timer_dev_id,
-};
-
-void time_init (void)
-{
-       mach_gettimeofday (&xtime);
-       mach_sched_init (&timer_irqaction);
-}
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
deleted file mode 100644 (file)
index 8d386a5..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/in6.h>
-#include <linux/interrupt.h>
-
-#include <asm/pgalloc.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/checksum.h>
-#include <asm/current.h>
-
-
-extern void *trap_table;
-EXPORT_SYMBOL (trap_table);
-
-/* platform dependent support */
-EXPORT_SYMBOL (kernel_thread);
-EXPORT_SYMBOL (__bug);
-
-/* Networking helper routines. */
-EXPORT_SYMBOL (csum_partial_copy_nocheck);
-EXPORT_SYMBOL (csum_partial_copy_from_user);
-EXPORT_SYMBOL (ip_compute_csum);
-EXPORT_SYMBOL (ip_fast_csum);
-
-/* string / mem functions */
-EXPORT_SYMBOL (memset);
-EXPORT_SYMBOL (memcpy);
-EXPORT_SYMBOL (memmove);
-
-/*
- * libgcc functions - functions that are used internally by the
- * compiler...  (prototypes are not correct though, but that
- * doesn't really matter since they're not versioned).
- */
-extern void __ashldi3 (void);
-extern void __ashrdi3 (void);
-extern void __lshrdi3 (void);
-extern void __muldi3 (void);
-extern void __negdi2 (void);
-
-EXPORT_SYMBOL (__ashldi3);
-EXPORT_SYMBOL (__ashrdi3);
-EXPORT_SYMBOL (__lshrdi3);
-EXPORT_SYMBOL (__muldi3);
-EXPORT_SYMBOL (__negdi2);
diff --git a/arch/v850/kernel/v850e2_cache.c b/arch/v850/kernel/v850e2_cache.c
deleted file mode 100644 (file)
index 4570312..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * arch/v850/kernel/v850e2_cache.c -- Cache control for V850E2 cache
- *     memories
- *
- *  Copyright (C) 2003  NEC Electronics Corporation
- *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/mm.h>
-
-#include <asm/v850e2_cache.h>
-
-/* Cache operations we can do.  The encoding corresponds directly to the
-   value we need to write into the COPR register.  */
-enum cache_op {
-       OP_SYNC_IF_DIRTY           = V850E2_CACHE_COPR_CFC(0), /* 000 */
-       OP_SYNC_IF_VALID           = V850E2_CACHE_COPR_CFC(1), /* 001 */
-       OP_SYNC_IF_VALID_AND_CLEAR = V850E2_CACHE_COPR_CFC(3), /* 011 */
-       OP_WAY_CLEAR               = V850E2_CACHE_COPR_CFC(4), /* 100 */
-       OP_FILL                    = V850E2_CACHE_COPR_CFC(5), /* 101 */
-       OP_CLEAR                   = V850E2_CACHE_COPR_CFC(6), /* 110 */
-       OP_CREATE_DIRTY            = V850E2_CACHE_COPR_CFC(7)  /* 111 */
-};
-
-/* Which cache to use.  This encoding also corresponds directly to the
-   value we need to write into the COPR register. */
-enum cache {
-       ICACHE = 0,
-       DCACHE = V850E2_CACHE_COPR_LBSL
-};
-
-/* Returns ADDR rounded down to the beginning of its cache-line.  */
-#define CACHE_LINE_ADDR(addr)  \
-   ((addr) & ~(V850E2_CACHE_LINE_SIZE - 1))
-/* Returns END_ADDR rounded up to the `limit' of its cache-line.  */
-#define CACHE_LINE_END_ADDR(end_addr)  \
-   CACHE_LINE_ADDR(end_addr + (V850E2_CACHE_LINE_SIZE - 1))
-
-\f
-/* Low-level cache ops.  */
-
-/* Apply cache-op OP to all entries in CACHE.  */
-static inline void cache_op_all (enum cache_op op, enum cache cache)
-{
-       int cmd = op | cache | V850E2_CACHE_COPR_WSLE | V850E2_CACHE_COPR_STRT;
-
-       if (op != OP_WAY_CLEAR) {
-               /* The WAY_CLEAR operation does the whole way, but other
-                  ops take begin-index and count params; we just indicate
-                  the entire cache.  */
-               V850E2_CACHE_CADL = 0;
-               V850E2_CACHE_CADH = 0;
-               V850E2_CACHE_CCNT = V850E2_CACHE_WAY_SIZE - 1;
-       }
-
-       V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(0); /* way 0 */
-       V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(1); /* way 1 */
-       V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(2); /* way 2 */
-       V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(3); /* way 3 */
-}
-
-/* Apply cache-op OP to all entries in CACHE covering addresses ADDR
-   through ADDR+LEN.  */
-static inline void cache_op_range (enum cache_op op, u32 addr, u32 len,
-                                  enum cache cache)
-{
-       u32 start = CACHE_LINE_ADDR (addr);
-       u32 end = CACHE_LINE_END_ADDR (addr + len);
-       u32 num_lines = (end - start) >> V850E2_CACHE_LINE_SIZE_BITS;
-
-       V850E2_CACHE_CADL = start & 0xFFFF;
-       V850E2_CACHE_CADH = start >> 16;
-       V850E2_CACHE_CCNT = num_lines - 1;
-
-       V850E2_CACHE_COPR = op | cache | V850E2_CACHE_COPR_STRT;
-}
-
-\f
-/* High-level ops.  */
-
-static void cache_exec_after_store_all (void)
-{
-       cache_op_all (OP_SYNC_IF_DIRTY, DCACHE);
-       cache_op_all (OP_WAY_CLEAR, ICACHE);
-}
-
-static void cache_exec_after_store_range (u32 start, u32 len)
-{
-       cache_op_range (OP_SYNC_IF_DIRTY, start, len, DCACHE);
-       cache_op_range (OP_CLEAR, start, len, ICACHE);
-}
-
-\f
-/* Exported functions.  */
-
-void flush_icache (void)
-{
-       cache_exec_after_store_all ();
-}
-
-void flush_icache_range (unsigned long start, unsigned long end)
-{
-       cache_exec_after_store_range (start, end - start);
-}
-
-void flush_icache_page (struct vm_area_struct *vma, struct page *page)
-{
-       cache_exec_after_store_range (page_to_virt (page), PAGE_SIZE);
-}
-
-void flush_icache_user_range (struct vm_area_struct *vma, struct page *page,
-                             unsigned long addr, int len)
-{
-       cache_exec_after_store_range (addr, len);
-}
-
-void flush_cache_sigtramp (unsigned long addr)
-{
-       /* For the exact size, see signal.c, but 16 bytes should be enough.  */
-       cache_exec_after_store_range (addr, 16);
-}
diff --git a/arch/v850/kernel/v850e_cache.c b/arch/v850/kernel/v850e_cache.c
deleted file mode 100644 (file)
index ea3e51c..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * arch/v850/kernel/v850e_cache.c -- Cache control for V850E cache memories
- *
- *  Copyright (C) 2003  NEC Electronics Corporation
- *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* This file implements cache control for the rather simple cache used on
-   some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2
-   CPU.  V850E2 processors have their own (better) cache
-   implementation.  */
-
-#include <asm/entry.h>
-#include <asm/cacheflush.h>
-#include <asm/v850e_cache.h>
-
-#define WAIT_UNTIL_CLEAR(value) while (value) {}
-
-/* Set caching params via the BHC and DCC registers.  */
-void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc)
-{
-       unsigned long *r0_ram = (unsigned long *)R0_RAM_ADDR;
-       register u16 bhc_val asm ("r6") = bhc;
-
-       /* Read the instruction cache control register (ICC) and confirm
-          that bits 0 and 1 (TCLR0, TCLR1) are all cleared.  */
-       WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
-       V850E_CACHE_ICC = icc;
-
-#ifdef V850E_CACHE_DCC
-       /* Configure data-cache.  */
-       V850E_CACHE_DCC = dcc;
-#endif /* V850E_CACHE_DCC */
-
-       /* Configure caching for various memory regions by writing the BHC
-          register.  The documentation says that an instruction _cannot_
-          enable/disable caching for the memory region in which the
-          instruction itself exists; to work around this, we store
-          appropriate instructions into the on-chip RAM area (which is never
-          cached), and briefly jump there to do the work.  */
-#ifdef V850E_CACHE_WRITE_IBS
-       *r0_ram++       = 0xf0720760;   /* st.h r0, 0xfffff072[r0] */
-#endif
-       *r0_ram++       = 0xf06a3760;   /* st.h r6, 0xfffff06a[r0] */
-       *r0_ram         = 0x5640006b;   /* jmp [r11] */
-
-       asm ("mov hilo(1f), r11; jmp [%1]; 1:;"
-            :: "r" (bhc_val), "r" (R0_RAM_ADDR) : "r11");
-}
-
-static void clear_icache (void)
-{
-       /* 1. Read the instruction cache control register (ICC) and confirm
-             that bits 0 and 1 (TCLR0, TCLR1) are all cleared.  */
-       WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
-
-       /* 2. Read the ICC register and confirm that bit 12 (LOCK0) is
-             cleared.  Bit 13 of the ICC register is always cleared.  */
-       WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x1000);
-
-       /* 3. Set the TCLR0 and TCLR1 bits of the ICC register as follows,
-             when clearing way 0 and way 1 at the same time:
-               (a) Set the TCLR0 and TCLR1 bits.
-               (b) Read the TCLR0 and TCLR1 bits to confirm that these bits
-                   are cleared.
-               (c) Perform (a) and (b) above again.  */
-       V850E_CACHE_ICC |= 0x3;
-       WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
-
-#ifdef V850E_CACHE_REPEAT_ICC_WRITE
-       /* Do it again.  */
-       V850E_CACHE_ICC |= 0x3;
-       WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
-#endif
-}
-
-#ifdef V850E_CACHE_DCC
-/* Flush or clear (or both) the data cache, depending on the value of FLAGS;
-   the procedure is the same for both, just the control bits used differ (and
-   both may be performed simultaneously).  */
-static void dcache_op (unsigned short flags)
-{
-       /* 1. Read the data cache control register (DCC) and confirm that bits
-             0, 1, 4, and 5 (DC00, DC01, DC04, DC05) are all cleared.  */
-       WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & 0x33);
-
-       /* 2. Clear DCC register bit 12 (DC12), bit 13 (DC13), or both
-             depending on the way for which tags are to be cleared.  */
-       V850E_CACHE_DCC &= ~0xC000;
-
-       /* 3. Set DCC register bit 0 (DC00), bit 1 (DC01) or both depending on
-             the way for which tags are to be cleared.
-             ...
-             Set DCC register bit 4 (DC04), bit 5 (DC05), or both depending
-             on the way to be data flushed.  */
-       V850E_CACHE_DCC |= flags;
-
-       /* 4. Read DCC register bit DC00, DC01 [DC04, DC05], or both depending
-             on the way for which tags were cleared [flushed] and confirm
-             that that bit is cleared.  */
-       WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & flags);
-}
-#endif /* V850E_CACHE_DCC */
-
-/* Flushes the contents of the dcache to memory.  */
-static inline void flush_dcache (void)
-{
-#ifdef V850E_CACHE_DCC
-       /* We only need to do something if in write-back mode.  */
-       if (V850E_CACHE_DCC & 0x0400)
-               dcache_op (0x30);
-#endif /* V850E_CACHE_DCC */
-}
-
-/* Flushes the contents of the dcache to memory, and then clears it.  */
-static inline void clear_dcache (void)
-{
-#ifdef V850E_CACHE_DCC
-       /* We only need to do something if the dcache is enabled.  */
-       if (V850E_CACHE_DCC & 0x0C00)
-               dcache_op (0x33);
-#endif /* V850E_CACHE_DCC */
-}
-
-/* Clears the dcache without flushing to memory first.  */
-static inline void clear_dcache_no_flush (void)
-{
-#ifdef V850E_CACHE_DCC
-       /* We only need to do something if the dcache is enabled.  */
-       if (V850E_CACHE_DCC & 0x0C00)
-               dcache_op (0x3);
-#endif /* V850E_CACHE_DCC */
-}
-
-static inline void cache_exec_after_store (void)
-{
-       flush_dcache ();
-       clear_icache ();
-}
-
-\f
-/* Exported functions.  */
-
-void flush_icache (void)
-{
-       cache_exec_after_store ();
-}
-
-void flush_icache_range (unsigned long start, unsigned long end)
-{
-       cache_exec_after_store ();
-}
-
-void flush_icache_page (struct vm_area_struct *vma, struct page *page)
-{
-       cache_exec_after_store ();
-}
-
-void flush_icache_user_range (struct vm_area_struct *vma, struct page *page,
-                             unsigned long adr, int len)
-{
-       cache_exec_after_store ();
-}
-
-void flush_cache_sigtramp (unsigned long addr)
-{
-       cache_exec_after_store ();
-}
diff --git a/arch/v850/kernel/v850e_intc.c b/arch/v850/kernel/v850e_intc.c
deleted file mode 100644 (file)
index 8d39a52..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * arch/v850/kernel/v850e_intc.c -- V850E interrupt controller (INTC)
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/v850e_intc.h>
-
-static void irq_nop (unsigned irq) { }
-
-static unsigned v850e_intc_irq_startup (unsigned irq)
-{
-       v850e_intc_clear_pending_irq (irq);
-       v850e_intc_enable_irq (irq);
-       return 0;
-}
-
-static void v850e_intc_end_irq (unsigned irq)
-{
-       unsigned long psw, temp;
-
-       /* Clear the highest-level bit in the In-service priority register
-          (ISPR), to allow this interrupt (or another of the same or
-          lesser priority) to happen again.
-
-          The `reti' instruction normally does this automatically when the
-          PSW bits EP and NP are zero, but we can't always rely on reti
-          being used consistently to return after an interrupt (another
-          process can be scheduled, for instance, which can delay the
-          associated reti for a long time, or this process may be being
-          single-stepped, which uses the `dbret' instruction to return
-          from the kernel).
-
-          We also set the PSW EP bit, which prevents reti from also
-          trying to modify the ISPR itself.  */
-
-       /* Get PSW and disable interrupts.  */
-       asm volatile ("stsr psw, %0; di" : "=r" (psw));
-       /* We don't want to do anything for NMIs (they don't use the ISPR).  */
-       if (! (psw & 0xC0)) {
-               /* Transition to `trap' state, so that an eventual real
-                  reti instruction won't modify the ISPR.  */
-               psw |= 0x40;
-               /* Fake an interrupt return, which automatically clears the
-                  appropriate bit in the ISPR.  */
-               asm volatile ("mov hilo(1f), %0;"
-                             "ldsr %0, eipc; ldsr %1, eipsw;"
-                             "reti;"
-                             "1:"
-                             : "=&r" (temp) : "r" (psw));
-       }
-}
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
-   INITS (which is terminated by an entry with the name field == 0).  */
-void __init v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits,
-                                      struct hw_interrupt_type *hw_irq_types)
-{
-       struct v850e_intc_irq_init *init;
-       for (init = inits; init->name; init++) {
-               unsigned i;
-               struct hw_interrupt_type *hwit = hw_irq_types++;
-
-               hwit->typename = init->name;
-
-               hwit->startup  = v850e_intc_irq_startup;
-               hwit->shutdown = v850e_intc_disable_irq;
-               hwit->enable   = v850e_intc_enable_irq;
-               hwit->disable  = v850e_intc_disable_irq;
-               hwit->ack      = irq_nop;
-               hwit->end      = v850e_intc_end_irq;
-               
-               /* Initialize kernel IRQ infrastructure for this interrupt.  */
-               init_irq_handlers(init->base, init->num, init->interval, hwit);
-
-               /* Set the interrupt priorities.  */
-               for (i = 0; i < init->num; i++) {
-                       unsigned irq = init->base + i * init->interval;
-
-                       /* If the interrupt is currently enabled (all
-                          interrupts are initially disabled), then
-                          assume whoever enabled it has set things up
-                          properly, and avoid messing with it.  */
-                       if (! v850e_intc_irq_enabled (irq))
-                               /* This write also (1) disables the
-                                  interrupt, and (2) clears any pending
-                                  interrupts.  */
-                               V850E_INTC_IC (irq)
-                                       = (V850E_INTC_IC_PR (init->priority)
-                                          | V850E_INTC_IC_MK);
-               }
-       }
-}
diff --git a/arch/v850/kernel/v850e_timer_d.c b/arch/v850/kernel/v850e_timer_d.c
deleted file mode 100644 (file)
index d2a4ece..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * include/asm-v850/v850e_timer_d.c -- `Timer D' component often used
- *     with V850E CPUs
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-
-#include <asm/v850e_utils.h>
-#include <asm/v850e_timer_d.h>
-
-/* Start interval timer TIMER (0-3).  The timer will issue the
-   corresponding INTCMD interrupt RATE times per second.
-   This function does not enable the interrupt.  */
-void v850e_timer_d_configure (unsigned timer, unsigned rate)
-{
-       unsigned divlog2, count;
-
-       /* Calculate params for timer.  */
-       if (! calc_counter_params (
-                   V850E_TIMER_D_BASE_FREQ, rate,
-                   V850E_TIMER_D_TMCD_CS_MIN, V850E_TIMER_D_TMCD_CS_MAX, 16,
-                   &divlog2, &count))
-               printk (KERN_WARNING
-                       "Cannot find interval timer %d setting suitable"
-                       " for rate of %dHz.\n"
-                       "Using rate of %dHz instead.\n",
-                       timer, rate,
-                       (V850E_TIMER_D_BASE_FREQ >> divlog2) >> 16);
-
-       /* Do the actual hardware timer initialization:  */
-
-       /* Enable timer.  */
-       V850E_TIMER_D_TMCD(timer) = V850E_TIMER_D_TMCD_CAE;
-       /* Set clock divider.  */
-       V850E_TIMER_D_TMCD(timer)
-               = V850E_TIMER_D_TMCD_CAE
-               | V850E_TIMER_D_TMCD_CS(divlog2);
-       /* Set timer compare register.  */
-       V850E_TIMER_D_CMD(timer) = count;
-       /* Start counting.  */
-       V850E_TIMER_D_TMCD(timer)
-               = V850E_TIMER_D_TMCD_CAE
-               | V850E_TIMER_D_TMCD_CS(divlog2)
-               | V850E_TIMER_D_TMCD_CE;
-}
diff --git a/arch/v850/kernel/v850e_utils.c b/arch/v850/kernel/v850e_utils.c
deleted file mode 100644 (file)
index e6807ef..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * include/asm-v850/v850e_utils.h -- Utility functions associated with
- *     V850E CPUs
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <asm/v850e_utils.h>
-
-/* Calculate counter clock-divider and count values to attain the
-   desired frequency RATE from the base frequency BASE_FREQ.  The
-   counter is expected to have a clock-divider, which can divide the
-   system cpu clock by a power of two value from MIN_DIVLOG2 to
-   MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
-   counts up and resets whenever it's equal to the compare register,
-   generating an interrupt or whatever when it does so).  The returned
-   values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
-   -- the counter compare value to use.  Returns true if it was possible
-   to find a reasonable value, otherwise false (and the other return
-   values will be set to be as good as possible).  */
-int calc_counter_params (unsigned long base_freq,
-                        unsigned long rate,
-                        unsigned min_divlog2, unsigned max_divlog2,
-                        unsigned counter_size,
-                        unsigned *divlog2, unsigned *count)
-{
-       unsigned _divlog2;
-       int ok = 0;
-
-       /* Find the lowest clock divider setting that can represent RATE.  */
-       for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) {
-               /* Minimum interrupt rate possible using this divider.  */
-               unsigned min_int_rate
-                       = (base_freq >> _divlog2) >> counter_size;
-
-               if (min_int_rate <= rate) {
-                       /* This setting is the highest resolution
-                          setting that's slow enough enough to attain
-                          RATE interrupts per second, so use it.  */
-                       ok = 1;
-                       break;
-               }
-       }
-
-       if (_divlog2 > max_divlog2)
-               /* Can't find correct setting.  */
-               _divlog2 = max_divlog2;
-
-       if (divlog2)
-               *divlog2 = _divlog2;
-       if (count)
-               *count = ((base_freq >> _divlog2) + rate/2) / rate;
-
-       return ok;
-}
diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
deleted file mode 100644 (file)
index d08cd1d..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * arch/v850/vmlinux.lds.S -- kernel linker script for v850 platforms
- *
- *  Copyright (C) 2002,03,04,05  NEC Electronics Corporation
- *  Copyright (C) 2002,03,04,05  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-
-#define VMLINUX_SYMBOL(_sym_) _##_sym_
-#include <asm-generic/vmlinux.lds.h>
-
-/* For most platforms, this will define useful things like RAM addr/size.  */
-#include <asm/machdep.h>
-
-
-/* The following macros contain the usual definitions for various data areas.
-   The prefix `RAMK_' is used to indicate macros suitable for kernels loaded
-   into RAM, and similarly `ROMK_' for ROM-resident kernels.  Note that all
-   symbols are prefixed with an extra `_' for compatibility with the v850
-   toolchain.  */
-
-       
-/* Interrupt vectors.  */
-#define INTV_CONTENTS                                                        \
-               . = ALIGN (0x10) ;                                            \
-               __intv_start = . ;                                            \
-                       *(.intv.reset)  /* Reset vector */                    \
-               . = __intv_start + 0x10 ;                                     \
-                       *(.intv.common) /* Vectors common to all v850e proc */\
-               . = __intv_start + 0x80 ;                                     \
-                       *(.intv.mach)   /* Machine-specific int. vectors.  */ \
-               __intv_end = . ;
-
-#define RODATA_CONTENTS                                                              \
-               . = ALIGN (16) ;                                              \
-                       *(.rodata) *(.rodata.*)                               \
-                       *(__vermagic)           /* Kernel version magic */    \
-                       *(.rodata1)                                           \
-               /* PCI quirks */                                              \
-               ___start_pci_fixups_early = . ;                               \
-                       *(.pci_fixup_early)                                   \
-               ___end_pci_fixups_early = . ;                                 \
-               ___start_pci_fixups_header = . ;                              \
-                       *(.pci_fixup_header)                                  \
-               ___end_pci_fixups_header = . ;                                \
-               ___start_pci_fixups_final = . ;                               \
-                       *(.pci_fixup_final)                                   \
-               ___end_pci_fixups_final = . ;                                 \
-               ___start_pci_fixups_enable = . ;                              \
-                       *(.pci_fixup_enable)                                  \
-               ___end_pci_fixups_enable = . ;                                \
-               /* Kernel symbol table: Normal symbols */                     \
-               ___start___ksymtab = .;                                       \
-                       *(__ksymtab)                                          \
-               ___stop___ksymtab = .;                                        \
-               /* Kernel symbol table: GPL-only symbols */                   \
-               ___start___ksymtab_gpl = .;                                   \
-                       *(__ksymtab_gpl)                                      \
-               ___stop___ksymtab_gpl = .;                                    \
-               /* Kernel symbol table: GPL-future symbols */                 \
-               ___start___ksymtab_gpl_future = .;                            \
-                       *(__ksymtab_gpl_future)                               \
-               ___stop___ksymtab_gpl_future = .;                             \
-               /* Kernel symbol table: strings */                            \
-                       *(__ksymtab_strings)                                  \
-               /* Kernel symbol table: Normal symbols */                     \
-               ___start___kcrctab = .;                                       \
-                       *(__kcrctab)                                          \
-               ___stop___kcrctab = .;                                        \
-               /* Kernel symbol table: GPL-only symbols */                   \
-               ___start___kcrctab_gpl = .;                                   \
-                       *(__kcrctab_gpl)                                      \
-               ___stop___kcrctab_gpl = .;                                    \
-               /* Kernel symbol table: GPL-future symbols */                 \
-               ___start___kcrctab_gpl_future = .;                            \
-                       *(__kcrctab_gpl_future)                               \
-               ___stop___kcrctab_gpl_future = .;                             \
-               /* Built-in module parameters */                              \
-               . = ALIGN (4) ;                                               \
-               ___start___param = .;                                         \
-               *(__param)                                                    \
-               ___stop___param = .;
-
-
-/* Kernel text segment, and some constant data areas.  */
-#define TEXT_CONTENTS                                                        \
-               _text = .;                                                    \
-               __stext = . ;                                                 \
-               TEXT_TEXT                                                     \
-               SCHED_TEXT                                                    \
-                       *(.exit.text)   /* 2.5 convention */                  \
-                       *(.text.exit)   /* 2.4 convention */                  \
-                       *(.text.lock)                                         \
-                       *(.exitcall.exit)                                     \
-               __real_etext = . ;      /* There may be data after here.  */  \
-               RODATA_CONTENTS                                               \
-               . = ALIGN (4) ;                                               \
-                       *(.call_table_data)                                   \
-                       *(.call_table_text)                                   \
-               . = ALIGN (16) ;        /* Exception table.  */               \
-               ___start___ex_table = . ;                                     \
-                       *(__ex_table)                                         \
-               ___stop___ex_table = . ;                                      \
-               . = ALIGN (4) ;                                               \
-               __etext = . ;
-
-/* Kernel data segment.  */
-#define DATA_CONTENTS                                                        \
-               __sdata = . ;                                                 \
-               DATA_DATA                                                     \
-                       EXIT_DATA       /* 2.5 convention */                  \
-                       *(.data.exit)   /* 2.4 convention */                  \
-               . = ALIGN (16) ;                                              \
-               *(.data.cacheline_aligned)                                    \
-               . = ALIGN (0x2000) ;                                          \
-               *(.data.init_task)                                            \
-               . = ALIGN (0x2000) ;                                          \
-               __edata = . ;
-
-/* Kernel BSS segment.  */
-#define BSS_CONTENTS                                                         \
-               __sbss = . ;                                                  \
-                       *(.bss)                                               \
-                       *(COMMON)                                             \
-               . = ALIGN (4) ;                                               \
-               __init_stack_end = . ;                                        \
-               __ebss = . ;
-
-/* `initcall' tables.  */
-#define INITCALL_CONTENTS                                                    \
-               . = ALIGN (16) ;                                              \
-               ___setup_start = . ;                                          \
-                       *(.init.setup)  /* 2.5 convention */                  \
-                       *(.setup.init)  /* 2.4 convention */                  \
-               ___setup_end = . ;                                            \
-               ___initcall_start = . ;                                       \
-                       *(.initcall.init)                                     \
-                       INITCALLS                                             \
-               . = ALIGN (4) ;                                               \
-               ___initcall_end = . ;                                         \
-               ___con_initcall_start = .;                                    \
-                       *(.con_initcall.init)                                 \
-               ___con_initcall_end = .;
-
-/* Contents of `init' section for a kernel that's loaded into RAM.  */
-#define RAMK_INIT_CONTENTS                                                   \
-               RAMK_INIT_CONTENTS_NO_END                                     \
-               __init_end = . ;
-/* Same as RAMK_INIT_CONTENTS, but doesn't define the `__init_end' symbol.  */
-#define RAMK_INIT_CONTENTS_NO_END                                            \
-               . = ALIGN (4096) ;                                            \
-               __init_start = . ;                                            \
-                       __sinittext = .;                                      \
-                       INIT_TEXT       /* 2.5 convention */                  \
-                       __einittext = .;                                      \
-                       INIT_DATA                                             \
-                       *(.text.init)   /* 2.4 convention */                  \
-                       *(.data.init)                                         \
-               INITCALL_CONTENTS                                             \
-               INITRAMFS_CONTENTS
-
-/* The contents of `init' section for a ROM-resident kernel which
-   should go into RAM.  */     
-#define ROMK_INIT_RAM_CONTENTS                                               \
-               . = ALIGN (4096) ;                                            \
-               __init_start = . ;                                            \
-                       INIT_DATA       /* 2.5 convention */                  \
-                       *(.data.init)   /* 2.4 convention */                  \
-               __init_end = . ;                                              \
-               . = ALIGN (4096) ;
-
-/* The contents of `init' section for a ROM-resident kernel which
-   should go into ROM.  */     
-#define ROMK_INIT_ROM_CONTENTS                                               \
-                       _sinittext = .;                                       \
-                       INIT_TEXT       /* 2.5 convention */                  \
-                       _einittext = .;                                       \
-                       *(.text.init)   /* 2.4 convention */                  \
-               INITCALL_CONTENTS                                             \
-               INITRAMFS_CONTENTS
-
-/* A root filesystem image, for kernels with an embedded root filesystem.  */
-#define ROOT_FS_CONTENTS                                                     \
-               __root_fs_image_start = . ;                                   \
-               *(.root)                                                      \
-               __root_fs_image_end = . ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-/* The initramfs archive.  */
-#define INITRAMFS_CONTENTS                                                   \
-               . = ALIGN (4) ;                                               \
-               ___initramfs_start = . ;                                      \
-                       *(.init.ramfs)                                        \
-               ___initramfs_end = . ;
-#endif
-
-/* Where the initial bootmap (bitmap for the boot-time memory allocator) 
-   should be place.  */
-#define BOOTMAP_CONTENTS                                                     \
-               . = ALIGN (4096) ;                                            \
-               __bootmap = . ;                                               \
-               . = . + 4096 ;          /* enough for 128MB.   */
-
-/* The contents of a `typical' kram area for a kernel in RAM.  */
-#define RAMK_KRAM_CONTENTS                                                   \
-               __kram_start = . ;                                            \
-               TEXT_CONTENTS                                                 \
-               DATA_CONTENTS                                                 \
-               BSS_CONTENTS                                                  \
-               RAMK_INIT_CONTENTS                                            \
-               __kram_end = . ;                                              \
-               BOOTMAP_CONTENTS
-
-
-/* Define output sections normally used for a ROM-resident kernel.  
-   ROM and RAM should be appropriate memory areas to use for kernel
-   ROM and RAM data.  This assumes that ROM starts at 0 (and thus can
-   hold the interrupt vectors).  */
-#define ROMK_SECTIONS(ROM, RAM)                                                      \
-       .rom : {                                                              \
-               INTV_CONTENTS                                                 \
-               TEXT_CONTENTS                                                 \
-               ROMK_INIT_ROM_CONTENTS                                        \
-               ROOT_FS_CONTENTS                                              \
-       } > ROM                                                               \
-                                                                             \
-       __rom_copy_src_start = . ;                                            \
-                                                                             \
-       .data : {                                                             \
-               __kram_start = . ;                                            \
-               __rom_copy_dst_start = . ;                                    \
-               DATA_CONTENTS                                                 \
-               ROMK_INIT_RAM_CONTENTS                                        \
-               __rom_copy_dst_end = . ;                                      \
-       } > RAM  AT> ROM                                                      \
-                                                                             \
-       .bss ALIGN (4) : {                                                    \
-               BSS_CONTENTS                                                  \
-               __kram_end = . ;                                              \
-               BOOTMAP_CONTENTS                                              \
-       } > RAM
-
-
-/* The 32-bit variable `jiffies' is just the lower 32-bits of `jiffies_64'.  */
-_jiffies = _jiffies_64 ;
-
-
-/* Include an appropriate platform-dependent linker-script (which
-   usually should use the above macros to do most of the work).  */
-
-#ifdef CONFIG_V850E_SIM
-# include "sim.ld"
-#endif
-
-#ifdef CONFIG_V850E2_SIM85E2
-# include "sim85e2.ld"
-#endif
-
-#ifdef CONFIG_V850E2_FPGA85E2C
-# include "fpga85e2c.ld"
-#endif
-
-#ifdef CONFIG_V850E2_ANNA
-# ifdef CONFIG_ROM_KERNEL
-#  include "anna-rom.ld"
-# else
-#  include "anna.ld"
-# endif
-#endif
-
-#ifdef CONFIG_V850E_AS85EP1
-# ifdef CONFIG_ROM_KERNEL
-#  include "as85ep1-rom.ld"
-# else
-#  include "as85ep1.ld"
-# endif
-#endif
-
-#ifdef CONFIG_RTE_CB_MA1
-# ifdef CONFIG_ROM_KERNEL
-#  include "rte_ma1_cb-rom.ld"
-# else
-#  include "rte_ma1_cb.ld"
-# endif
-#endif
-
-#ifdef CONFIG_RTE_CB_NB85E
-# ifdef CONFIG_ROM_KERNEL
-#  include "rte_nb85e_cb-rom.ld"
-# elif defined(CONFIG_RTE_CB_MULTI)
-#  include "rte_nb85e_cb-multi.ld"
-# else
-#  include "rte_nb85e_cb.ld"
-# endif
-#endif
-
-#ifdef CONFIG_RTE_CB_ME2
-#  include "rte_me2_cb.ld"
-#endif
-
diff --git a/arch/v850/lib/Makefile b/arch/v850/lib/Makefile
deleted file mode 100644 (file)
index 1c78b72..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# arch/v850/lib/Makefile
-#
-
-lib-y  = ashrdi3.o ashldi3.o lshrdi3.o muldi3.o negdi2.o \
-        checksum.o memcpy.o memset.o
diff --git a/arch/v850/lib/ashldi3.c b/arch/v850/lib/ashldi3.c
deleted file mode 100644 (file)
index 9e792d5..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* ashldi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#define BITS_PER_UNIT 8
-
-typedef         int SItype     __attribute__ ((mode (SI)));
-typedef unsigned int USItype   __attribute__ ((mode (SI)));
-typedef                 int DItype     __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
-} DIunion;
-
-DItype
-__ashldi3 (DItype u, word_type b)
-{
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.low = 0;
-      w.s.high = (USItype)uu.s.low << -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.low >> bm;
-      w.s.low = (USItype)uu.s.low << b;
-      w.s.high = ((USItype)uu.s.high << b) | carries;
-    }
-
-  return w.ll;
-}
diff --git a/arch/v850/lib/ashrdi3.c b/arch/v850/lib/ashrdi3.c
deleted file mode 100644 (file)
index 78efb65..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#define BITS_PER_UNIT 8
-
-typedef         int SItype     __attribute__ ((mode (SI)));
-typedef unsigned int USItype   __attribute__ ((mode (SI)));
-typedef                 int DItype     __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
-} DIunion;
-
-DItype
-__ashrdi3 (DItype u, word_type b)
-{
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      /* w.s.high = 1..1 or 0..0 */
-      w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
-      w.s.low = uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
-
-  return w.ll;
-}
diff --git a/arch/v850/lib/checksum.c b/arch/v850/lib/checksum.c
deleted file mode 100644 (file)
index 042158d..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * INET                An implementation of the TCP/IP protocol suite for the LINUX
- *             operating system.  INET is implemented using the  BSD Socket
- *             interface as the means of communication with the user level.
- *
- *             MIPS specific IP/TCP/UDP checksumming routines
- *
- * Authors:    Ralf Baechle, <ralf@waldorf-gmbh.de>
- *             Lots of code moved from tcp.c and ip.c; see those files
- *             for more names.
- *
- *             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.
- *
- * $Id: checksum.c,v 1.1 2002/09/28 14:58:40 gerg Exp $
- */
-#include <net/checksum.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-static inline unsigned short from32to16 (unsigned long sum)
-{
-       unsigned int result;
-       /*
-                               %0              %1
-             hsw %1, %0        H     L         L     H
-             add %1, %0        H     L         H+L+C H+L
-       */
-       asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum));
-       return result >> 16;
-}
-
-static inline unsigned int do_csum(const unsigned char * buff, int len)
-{
-       int odd, count;
-       unsigned int result = 0;
-
-       if (len <= 0)
-               goto out;
-       odd = 1 & (unsigned long) buff;
-       if (odd) {
-               result = be16_to_cpu(*buff);
-               len--;
-               buff++;
-       }
-       count = len >> 1;               /* nr of 16-bit words.. */
-       if (count) {
-               if (2 & (unsigned long) buff) {
-                       result += *(unsigned short *) buff;
-                       count--;
-                       len -= 2;
-                       buff += 2;
-               }
-               count >>= 1;            /* nr of 32-bit words.. */
-               if (count) {
-                       unsigned int carry = 0;
-                       do {
-                               unsigned int w = *(unsigned int *) buff;
-                               count--;
-                               buff += 4;
-                               result += carry;
-                               result += w;
-                               carry = (w > result);
-                       } while (count);
-                       result += carry;
-                       result = (result & 0xffff) + (result >> 16);
-               }
-               if (len & 2) {
-                       result += *(unsigned short *) buff;
-                       buff += 2;
-               }
-       }
-       if (len & 1)
-               result += le16_to_cpu(*buff);
-       result = from32to16(result);
-       if (odd)
-               result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
-       return result;
-}
-
-/*
- *     This is a version of ip_compute_csum() optimized for IP headers,
- *     which always checksum on 4 octet boundaries.
- */
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-       return (__force __sum16)~do_csum(iph,ihl*4);
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum(const void *buff, int len)
-{
-       return (__force __sum16)~do_csum(buff,len);
-}
-
-/*
- * computes a partial checksum, e.g. for TCP/UDP fragments
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum)
-{
-       unsigned int result = do_csum(buff, len);
-
-       /* add in old sum, and carry.. */
-       result += (__force u32)sum;
-       if ((__force u32)sum > result)
-               result += 1;
-       return (__force __wsum)result;
-}
-
-EXPORT_SYMBOL(csum_partial);
-
-/*
- * copy while checksumming, otherwise like csum_partial
- */
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-                               int len, __wsum sum)
-{
-       /*
-        * It's 2:30 am and I don't feel like doing it real ...
-        * This is lots slower than the real thing (tm)
-        */
-       sum = csum_partial(src, len, sum);
-       memcpy(dst, src, len);
-
-       return sum;
-}
-
-/*
- * Copy from userspace and compute checksum.  If we catch an exception
- * then zero the rest of the buffer.
- */
-__wsum csum_partial_copy_from_user (const void *src,
-                                         void *dst,
-                                          int len, __wsum sum,
-                                          int *err_ptr)
-{
-       int missing;
-
-       missing = copy_from_user(dst, src, len);
-       if (missing) {
-               memset(dst + len - missing, 0, missing);
-               *err_ptr = -EFAULT;
-       }
-               
-       return csum_partial(dst, len, sum);
-}
diff --git a/arch/v850/lib/lshrdi3.c b/arch/v850/lib/lshrdi3.c
deleted file mode 100644 (file)
index 93b1cb6..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#define BITS_PER_UNIT 8
-
-typedef         int SItype     __attribute__ ((mode (SI)));
-typedef unsigned int USItype   __attribute__ ((mode (SI)));
-typedef                 int DItype     __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
-} DIunion;
-
-DItype
-__lshrdi3 (DItype u, word_type b)
-{
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.high = 0;
-      w.s.low = (USItype)uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = (USItype)uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
-
-  return w.ll;
-}
diff --git a/arch/v850/lib/memcpy.c b/arch/v850/lib/memcpy.c
deleted file mode 100644 (file)
index 492847b..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * arch/v850/lib/memcpy.c -- Memory copying
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/types.h>
-#include <asm/string.h>
-
-#define CHUNK_SIZE             32 /* bytes */
-#define CHUNK_ALIGNED(addr)    (((unsigned long)addr & 0x3) == 0)
-
-/* Note that this macro uses 8 call-clobbered registers (not including
-   R1), which are few enough so that the following functions don't need
-   to spill anything to memory.  It also uses R1, which is nominally
-   reserved for the assembler, but here it should be OK.  */
-#define COPY_CHUNK(src, dst)                   \
-   asm ("mov %0, ep;"                          \
-       "sld.w 0[ep], r1; sld.w 4[ep], r12;"    \
-       "sld.w 8[ep], r13; sld.w 12[ep], r14;"  \
-       "sld.w 16[ep], r15; sld.w 20[ep], r17;" \
-       "sld.w 24[ep], r18; sld.w 28[ep], r19;" \
-       "mov %1, ep;"                           \
-       "sst.w r1, 0[ep]; sst.w r12, 4[ep];"    \
-       "sst.w r13, 8[ep]; sst.w r14, 12[ep];"  \
-       "sst.w r15, 16[ep]; sst.w r17, 20[ep];" \
-       "sst.w r18, 24[ep]; sst.w r19, 28[ep]"  \
-       :: "r" (src), "r" (dst)                 \
-       : "r1", "r12", "r13", "r14", "r15",     \
-         "r17", "r18", "r19", "ep", "memory");
-
-void *memcpy (void *dst, const void *src, __kernel_size_t size)
-{
-       char *_dst = dst;
-       const char *_src = src;
-
-       if (size >= CHUNK_SIZE && CHUNK_ALIGNED(_src) && CHUNK_ALIGNED(_dst)) {
-               /* Copy large blocks efficiently.  */
-               unsigned count;
-               for (count = size / CHUNK_SIZE; count; count--) {
-                       COPY_CHUNK (_src, _dst);
-                       _src += CHUNK_SIZE;
-                       _dst += CHUNK_SIZE;
-               }
-               size %= CHUNK_SIZE;
-       }
-
-       if (size > 0)
-               do
-                       *_dst++ = *_src++;
-               while (--size);
-
-       return dst;
-}
-
-void *memmove (void *dst, const void *src, __kernel_size_t size)
-{
-       if ((unsigned long)dst < (unsigned long)src
-           || (unsigned long)src + size < (unsigned long)dst)
-               return memcpy (dst, src, size);
-       else {
-               char *_dst = dst + size;
-               const char *_src = src + size;
-
-               if (size >= CHUNK_SIZE
-                   && CHUNK_ALIGNED (_src) && CHUNK_ALIGNED (_dst))
-               {
-                       /* Copy large blocks efficiently.  */
-                       unsigned count;
-                       for (count = size / CHUNK_SIZE; count; count--) {
-                               _src -= CHUNK_SIZE;
-                               _dst -= CHUNK_SIZE;
-                               COPY_CHUNK (_src, _dst);
-                       }
-                       size %= CHUNK_SIZE;
-               }
-
-               if (size > 0)
-                       do
-                               *--_dst = *--_src;
-                       while (--size);
-
-               return _dst;
-       }
-}
diff --git a/arch/v850/lib/memset.c b/arch/v850/lib/memset.c
deleted file mode 100644 (file)
index d1b2ad8..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/v850/lib/memset.c -- Memory initialization
- *
- *  Copyright (C) 2001,02,04  NEC Corporation
- *  Copyright (C) 2001,02,04  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/types.h>
-
-void *memset (void *dst, int val, __kernel_size_t count)
-{
-       if (count) {
-               register unsigned loop;
-               register void *ptr asm ("ep") = dst;
-
-               /* replicate VAL into a long.  */
-               val &= 0xff;
-               val |= val << 8;
-               val |= val << 16;
-
-               /* copy initial unaligned bytes.  */
-               if ((long)ptr & 1) {
-                       *(char *)ptr = val;
-                       ptr = (void *)((char *)ptr + 1);
-                       count--;
-               }
-               if (count > 2 && ((long)ptr & 2)) {
-                       *(short *)ptr = val;
-                       ptr = (void *)((short *)ptr + 1);
-                       count -= 2;
-               }
-
-               /* 32-byte copying loop.  */
-               for (loop = count / 32; loop; loop--) {
-                       asm ("sst.w %0, 0[ep]; sst.w %0, 4[ep];"
-                            "sst.w %0, 8[ep]; sst.w %0, 12[ep];"
-                            "sst.w %0, 16[ep]; sst.w %0, 20[ep];"
-                            "sst.w %0, 24[ep]; sst.w %0, 28[ep]"
-                            :: "r" (val) : "memory");
-                       ptr += 32;
-               }
-               count %= 32;
-
-               /* long copying loop.  */
-               for (loop = count / 4; loop; loop--) {
-                       *(long *)ptr = val;
-                       ptr = (void *)((long *)ptr + 1);
-               }
-               count %= 4;
-
-               /* finish up with any trailing bytes.  */
-               if (count & 2) {
-                       *(short *)ptr = val;
-                       ptr = (void *)((short *)ptr + 1);
-               }
-               if (count & 1) {
-                       *(char *)ptr = val;
-               }
-       }
-
-       return dst;
-}
diff --git a/arch/v850/lib/muldi3.c b/arch/v850/lib/muldi3.c
deleted file mode 100644 (file)
index 277ca25..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and 
-                          gcc-2.7.2.3/longlong.h which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 2001 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#define umul_ppmm(w1, w0, u, v) \
-  __asm__ ("mulu %3, %0, %1"                                           \
-           : "=r" ((USItype)(w0)),                                     \
-             "=r" ((USItype)(w1))                                      \
-           : "%0" ((USItype)(u)),                                      \
-             "r" ((USItype)(v)))
-
-#define __umulsidi3(u, v) \
-  ({DIunion __w;                                                       \
-    umul_ppmm (__w.s.high, __w.s.low, u, v);                           \
-    __w.ll; })
-
-typedef         int SItype     __attribute__ ((mode (SI)));
-typedef unsigned int USItype   __attribute__ ((mode (SI)));
-typedef                 int DItype     __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
-} DIunion;
-
-DItype
-__muldi3 (DItype u, DItype v)
-{
-  DIunion w;
-  DIunion uu, vv;
-
-  uu.ll = u,
-  vv.ll = v;
-
-  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
-  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
-              + (USItype) uu.s.high * (USItype) vv.s.low);
-
-  return w.ll;
-}
diff --git a/arch/v850/lib/negdi2.c b/arch/v850/lib/negdi2.c
deleted file mode 100644 (file)
index 571e04f..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/v850/lib/negdi2.c -- 64-bit negation
- *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-typedef                 int DItype     __attribute__ ((mode (DI)));
-
-DItype __negdi2 (DItype x)
-{
-       __asm__ __volatile__
-               ("not   r6, r10;"
-                "add   1, r10;"
-                "setf  c, r6;"
-                "not   r7, r11;"
-                "add   r6, r11"
-                ::: "r6", "r7", "r10", "r11");
-}
index 03980cb042916c6f37bd131c1d43553f51c8ade6..3d0f2b6a5a16e6edd6f349b4b19756a5d2cecff7 100644 (file)
@@ -21,12 +21,17 @@ config X86
        select HAVE_UNSTABLE_SCHED_CLOCK
        select HAVE_IDE
        select HAVE_OPROFILE
+       select HAVE_IOREMAP_PROT
+       select HAVE_GET_USER_PAGES_FAST
        select HAVE_KPROBES
+       select ARCH_WANT_OPTIONAL_GPIOLIB
        select HAVE_KRETPROBES
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FTRACE
        select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
        select HAVE_ARCH_KGDB if !X86_VOYAGER
+       select HAVE_GENERIC_DMA_COHERENT if X86_32
+       select HAVE_EFFICIENT_UNALIGNED_ACCESS
 
 config ARCH_DEFCONFIG
        string
@@ -329,20 +334,6 @@ config X86_BIGSMP
 
 endif
 
-config X86_RDC321X
-       bool "RDC R-321x SoC"
-       depends on X86_32
-       select M486
-       select X86_REBOOTFIXUPS
-       select GENERIC_GPIO
-       select LEDS_CLASS
-       select LEDS_GPIO
-       select NEW_LEDS
-       help
-         This option is needed for RDC R-321x system-on-chip, also known
-         as R-8610-(G).
-         If you don't have one of these chips, you should say N here.
-
 config X86_VSMP
        bool "Support for ScaleMP vSMP"
        select PARAVIRT
@@ -366,6 +357,16 @@ config X86_VISWS
          A kernel compiled for the Visual Workstation will run on general
          PCs as well. See <file:Documentation/sgi-visws.txt> for details.
 
+config X86_RDC321X
+       bool "RDC R-321x SoC"
+       depends on X86_32
+       select M486
+       select X86_REBOOTFIXUPS
+       help
+         This option is needed for RDC R-321x system-on-chip, also known
+         as R-8610-(G).
+         If you don't have one of these chips, you should say N here.
+
 config SCHED_NO_NO_OMIT_FRAME_POINTER
        def_bool y
        prompt "Single-depth WCHAN output"
@@ -1276,6 +1277,14 @@ config CRASH_DUMP
          (CONFIG_RELOCATABLE=y).
          For more details see Documentation/kdump/kdump.txt
 
+config KEXEC_JUMP
+       bool "kexec jump (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       depends on KEXEC && HIBERNATION && X86_32
+       help
+         Jump between original kernel and kexeced kernel and invoke
+         code in physical address mode via KEXEC
+
 config PHYSICAL_START
        hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
        default "0x1000000" if X86_NUMAQ
index 919ce21ea6545592fb10ce10461d0d1f053a3d00..f5631da585b69ac1722891bc0bee1e63a1ec652c 100644 (file)
@@ -118,11 +118,6 @@ mflags-$(CONFIG_X86_GENERICARCH):= -Iinclude/asm-x86/mach-generic
 fcore-$(CONFIG_X86_GENERICARCH)        += arch/x86/mach-generic/
 mcore-$(CONFIG_X86_GENERICARCH)        := arch/x86/mach-default/
 
-# RDC R-321x subarch support
-mflags-$(CONFIG_X86_RDC321X)   := -Iinclude/asm-x86/mach-rdc321x
-mcore-$(CONFIG_X86_RDC321X)    := arch/x86/mach-default/
-core-$(CONFIG_X86_RDC321X)     += arch/x86/mach-rdc321x/
-
 # default subarch .h files
 mflags-y += -Iinclude/asm-x86/mach-default
 
index bc5553b496f719c665ed1e7876eae3e0f2d69b1a..9fea737064798bfd10ab78cf729b14cfd8b87681 100644 (file)
@@ -182,8 +182,6 @@ static unsigned             outcnt;
 static int  fill_inbuf(void);
 static void flush_window(void);
 static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
 
 /*
  * This is set up by the setup-routine at boot-time
@@ -196,9 +194,6 @@ extern int input_len;
 
 static long bytes_out;
 
-static void *malloc(int size);
-static void free(void *where);
-
 static void *memset(void *s, int c, unsigned n);
 static void *memcpy(void *dest, const void *src, unsigned n);
 
@@ -220,40 +215,6 @@ static int lines, cols;
 
 #include "../../../../lib/inflate.c"
 
-static void *malloc(int size)
-{
-       void *p;
-
-       if (size < 0)
-               error("Malloc error");
-       if (free_mem_ptr <= 0)
-               error("Memory error");
-
-       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
-       p = (void *)free_mem_ptr;
-       free_mem_ptr += size;
-
-       if (free_mem_ptr >= free_mem_end_ptr)
-               error("Out of memory");
-
-       return p;
-}
-
-static void free(void *where)
-{      /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
-       *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
-       free_mem_ptr = (memptr) *ptr;
-}
-
 static void scroll(void)
 {
        int i;
index 58cccb6483b0580d28d935b4692f62b2675f7d02..a0e1dbe67dc145cd437661ea2f472c9865e08578 100644 (file)
@@ -441,12 +441,6 @@ beyond_if:
        regs->r8 = regs->r9 = regs->r10 = regs->r11 =
        regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;
        set_fs(USER_DS);
-       if (unlikely(current->ptrace & PT_PTRACED)) {
-               if (current->ptrace & PT_TRACE_EXEC)
-                       ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
-               else
-                       send_sig(SIGTRAP, current, 0);
-       }
        return 0;
 }
 
index 021d71bc69b5dbc1765f9aadfb3b9629b375e399..ffc1bb4fed7d1ade2ed385597fd05464fea55528 100644 (file)
@@ -201,7 +201,7 @@ sysexit_from_sys_call:
        movl RDI-ARGOFFSET(%rsp),%r8d   /* reload 5th syscall arg */
        .endm
 
-       .macro auditsys_exit exit
+       .macro auditsys_exit exit,ebpsave=RBP
        testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
        jnz int_ret_from_sys_call
        TRACE_IRQS_ON
@@ -214,7 +214,7 @@ sysexit_from_sys_call:
        call audit_syscall_exit
        GET_THREAD_INFO(%r10)
        movl RAX-ARGOFFSET(%rsp),%eax   /* reload syscall return value */
-       movl RBP-ARGOFFSET(%rsp),%ebp   /* reload user register value */
+       movl \ebpsave-ARGOFFSET(%rsp),%ebp /* reload user register value */
        movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
        cli
        TRACE_IRQS_OFF
@@ -347,7 +347,7 @@ cstar_auditsys:
        jmp cstar_dispatch
 
 sysretl_audit:
-       auditsys_exit sysretl_from_sys_call
+       auditsys_exit sysretl_from_sys_call, RCX /* user %ebp in RCX slot */
 #endif
 
 cstar_tracesys:
@@ -826,4 +826,10 @@ ia32_sys_call_table:
        .quad sys32_fallocate
        .quad compat_sys_timerfd_settime        /* 325 */
        .quad compat_sys_timerfd_gettime
+       .quad compat_sys_signalfd4
+       .quad sys_eventfd2
+       .quad sys_epoll_create1
+       .quad sys_dup3                  /* 330 */
+       .quad sys_pipe2
+       .quad sys_inotify_init1
 ia32_syscall_end:
index f00afdf61e6735bbee01085fa24dc42ea529bed7..d3c64088b981f02fe5614ec53c3539b5bd3b703a 100644 (file)
@@ -238,7 +238,7 @@ asmlinkage long sys32_pipe(int __user *fd)
        int retval;
        int fds[2];
 
-       retval = do_pipe(fds);
+       retval = do_pipe_flags(fds, 0);
        if (retval)
                goto out;
        if (copy_to_user(fd, fds, sizeof(fds)))
index 9220cf46aa10645a50ceb65e8ca24c69c9841958..c2502eb9aa8355488a7057602bfdfa71134785a7 100644 (file)
@@ -73,7 +73,6 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
        struct cpuinfo_x86 *c = &cpu_data(cpu);
 
        cpumask_t saved_mask;
-       cpumask_of_cpu_ptr(new_mask, cpu);
        int retval;
        unsigned int eax, ebx, ecx, edx;
        unsigned int edx_part;
@@ -92,7 +91,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
 
        /* Make sure we are running on right CPU */
        saved_mask = current->cpus_allowed;
-       retval = set_cpus_allowed_ptr(current, new_mask);
+       retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
        if (retval)
                return -1;
 
index a3ddad18aaa35b37c5344c4080b59d3a46c99021..fa2161d5003b78ad6e7b021523efd7b761894602 100644 (file)
@@ -150,6 +150,10 @@ static int __init acpi_sleep_setup(char *str)
                        acpi_realmode_flags |= 2;
                if (strncmp(str, "s3_beep", 7) == 0)
                        acpi_realmode_flags |= 4;
+#ifdef CONFIG_HIBERNATION
+               if (strncmp(str, "s4_nohwsig", 10) == 0)
+                       acpi_no_s4_hw_signature();
+#endif
                if (strncmp(str, "old_ordering", 12) == 0)
                        acpi_old_suspend_ordering();
                str = strchr(str, ',');
index c25210e6ac888e94224b460e6eb82f3c556d7616..22d7d050905dd1f6b6192707b2697e38a2fd38bd 100644 (file)
@@ -29,9 +29,6 @@
 
 #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
 
-#define to_pages(addr, size) \
-        (round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT)
-
 #define EXIT_LOOP_COUNT 10000000
 
 static DEFINE_RWLOCK(amd_iommu_devtable_lock);
@@ -185,7 +182,7 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
                u64 address, size_t size)
 {
        int s = 0;
-       unsigned pages = to_pages(address, size);
+       unsigned pages = iommu_num_pages(address, size);
 
        address &= PAGE_MASK;
 
@@ -557,8 +554,8 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu,
        if (iommu->exclusion_start &&
            iommu->exclusion_start < dma_dom->aperture_size) {
                unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
-               int pages = to_pages(iommu->exclusion_start,
-                               iommu->exclusion_length);
+               int pages = iommu_num_pages(iommu->exclusion_start,
+                                           iommu->exclusion_length);
                dma_ops_reserve_addresses(dma_dom, startpage, pages);
        }
 
@@ -667,7 +664,7 @@ static int get_device_resources(struct device *dev,
        _bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
 
        /* device not translated by any IOMMU in the system? */
-       if (_bdf >= amd_iommu_last_bdf) {
+       if (_bdf > amd_iommu_last_bdf) {
                *iommu = NULL;
                *domain = NULL;
                *bdf = 0xffff;
@@ -767,7 +764,7 @@ static dma_addr_t __map_single(struct device *dev,
        unsigned int pages;
        int i;
 
-       pages = to_pages(paddr, size);
+       pages = iommu_num_pages(paddr, size);
        paddr &= PAGE_MASK;
 
        address = dma_ops_alloc_addresses(dev, dma_dom, pages);
@@ -802,7 +799,7 @@ static void __unmap_single(struct amd_iommu *iommu,
        if ((dma_addr == 0) || (dma_addr + size > dma_dom->aperture_size))
                return;
 
-       pages = to_pages(dma_addr, size);
+       pages = iommu_num_pages(dma_addr, size);
        dma_addr &= PAGE_MASK;
        start = dma_addr;
 
@@ -1085,7 +1082,7 @@ void prealloc_protection_domains(void)
 
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
                devid = (dev->bus->number << 8) | dev->devfn;
-               if (devid >= amd_iommu_last_bdf)
+               if (devid > amd_iommu_last_bdf)
                        continue;
                devid = amd_iommu_alias_table[devid];
                if (domain_for_device(devid))
index c9d8ff2eb130b3ed384bc525ef13a5c4784161d7..d9a9da597e796cbcda869180879a7804888e70ea 100644 (file)
@@ -732,7 +732,7 @@ static int __init init_exclusion_range(struct ivmd_header *m)
                set_device_exclusion_range(m->devid, m);
                break;
        case ACPI_IVMD_TYPE_ALL:
-               for (i = 0; i < amd_iommu_last_bdf; ++i)
+               for (i = 0; i <= amd_iommu_last_bdf; ++i)
                        set_device_exclusion_range(i, m);
                break;
        case ACPI_IVMD_TYPE_RANGE:
@@ -934,7 +934,7 @@ int __init amd_iommu_init(void)
        /*
         * let all alias entries point to itself
         */
-       for (i = 0; i < amd_iommu_last_bdf; ++i)
+       for (i = 0; i <= amd_iommu_last_bdf; ++i)
                amd_iommu_alias_table[i] = i;
 
        /*
index bf9b441331e9fb2f42ec1a89fcc683d48c6af839..9ee24e6bc4b0e5a661c4ac3dd669c60bf1f82a45 100644 (file)
 #include <linux/time.h>
 #include <linux/sched.h>
 #include <linux/pm.h>
-#include <linux/pm_legacy.h>
 #include <linux/capability.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
index ff2fff56f0a8f2f1340a98a3305da24cd1dd3da1..dd097b835839dd73d4139d807c23e8fca1648344 100644 (file)
@@ -200,12 +200,10 @@ static void drv_read(struct drv_cmd *cmd)
 static void drv_write(struct drv_cmd *cmd)
 {
        cpumask_t saved_mask = current->cpus_allowed;
-       cpumask_of_cpu_ptr_declare(cpu_mask);
        unsigned int i;
 
        for_each_cpu_mask_nr(i, cmd->mask) {
-               cpumask_of_cpu_ptr_next(cpu_mask, i);
-               set_cpus_allowed_ptr(current, cpu_mask);
+               set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
                do_drv_write(cmd);
        }
 
@@ -269,12 +267,11 @@ static unsigned int get_measured_perf(unsigned int cpu)
        } aperf_cur, mperf_cur;
 
        cpumask_t saved_mask;
-       cpumask_of_cpu_ptr(cpu_mask, cpu);
        unsigned int perf_percent;
        unsigned int retval;
 
        saved_mask = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, cpu_mask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
        if (get_cpu() != cpu) {
                /* We were not able to run on requested processor */
                put_cpu();
@@ -340,7 +337,6 @@ static unsigned int get_measured_perf(unsigned int cpu)
 
 static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
 {
-       cpumask_of_cpu_ptr(cpu_mask, cpu);
        struct acpi_cpufreq_data *data = per_cpu(drv_data, cpu);
        unsigned int freq;
        unsigned int cached_freq;
@@ -353,7 +349,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
        }
 
        cached_freq = data->freq_table[data->acpi_data->state].frequency;
-       freq = extract_freq(get_cur_val(cpu_mask), data);
+       freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
        if (freq != cached_freq) {
                /*
                 * The dreaded BIOS frequency change behind our back.
index 53c7b6936973c6da85137145ed0eea8eec18746f..c45ca6d4dce101fbe7e5044420410edab5ad8b42 100644 (file)
@@ -479,12 +479,11 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
 static int check_supported_cpu(unsigned int cpu)
 {
        cpumask_t oldmask;
-       cpumask_of_cpu_ptr(cpu_mask, cpu);
        u32 eax, ebx, ecx, edx;
        unsigned int rc = 0;
 
        oldmask = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, cpu_mask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
 
        if (smp_processor_id() != cpu) {
                printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
@@ -1017,7 +1016,6 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
 static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
 {
        cpumask_t oldmask;
-       cpumask_of_cpu_ptr(cpu_mask, pol->cpu);
        struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
        u32 checkfid;
        u32 checkvid;
@@ -1032,7 +1030,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
 
        /* only run on specific CPU from here on */
        oldmask = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, cpu_mask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
 
        if (smp_processor_id() != pol->cpu) {
                printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
@@ -1107,7 +1105,6 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 {
        struct powernow_k8_data *data;
        cpumask_t oldmask;
-       cpumask_of_cpu_ptr_declare(newmask);
        int rc;
 
        if (!cpu_online(pol->cpu))
@@ -1159,8 +1156,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 
        /* only run on specific CPU from here on */
        oldmask = current->cpus_allowed;
-       cpumask_of_cpu_ptr_next(newmask, pol->cpu);
-       set_cpus_allowed_ptr(current, newmask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
 
        if (smp_processor_id() != pol->cpu) {
                printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
@@ -1182,7 +1178,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
        set_cpus_allowed_ptr(current, &oldmask);
 
        if (cpu_family == CPU_HW_PSTATE)
-               pol->cpus = *newmask;
+               pol->cpus = cpumask_of_cpu(pol->cpu);
        else
                pol->cpus = per_cpu(cpu_core_map, pol->cpu);
        data->available_cores = &(pol->cpus);
@@ -1248,7 +1244,6 @@ static unsigned int powernowk8_get (unsigned int cpu)
 {
        struct powernow_k8_data *data;
        cpumask_t oldmask = current->cpus_allowed;
-       cpumask_of_cpu_ptr(newmask, cpu);
        unsigned int khz = 0;
        unsigned int first;
 
@@ -1258,7 +1253,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
        if (!data)
                return -EINVAL;
 
-       set_cpus_allowed_ptr(current, newmask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
        if (smp_processor_id() != cpu) {
                printk(KERN_ERR PFX
                        "limiting to CPU %d failed in powernowk8_get\n", cpu);
index ca2ac13b7af20b2221aaa1d883a7fb89821bf4d5..15e13c01cc3621ce3d4d610ab34225437eb8f413 100644 (file)
@@ -324,10 +324,9 @@ static unsigned int get_cur_freq(unsigned int cpu)
        unsigned l, h;
        unsigned clock_freq;
        cpumask_t saved_mask;
-       cpumask_of_cpu_ptr(new_mask, cpu);
 
        saved_mask = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, new_mask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
        if (smp_processor_id() != cpu)
                return 0;
 
@@ -585,15 +584,12 @@ static int centrino_target (struct cpufreq_policy *policy,
                 * Best effort undo..
                 */
 
-               if (!cpus_empty(*covered_cpus)) {
-                       cpumask_of_cpu_ptr_declare(new_mask);
-
+               if (!cpus_empty(*covered_cpus))
                        for_each_cpu_mask_nr(j, *covered_cpus) {
-                               cpumask_of_cpu_ptr_next(new_mask, j);
-                               set_cpus_allowed_ptr(current, new_mask);
+                               set_cpus_allowed_ptr(current,
+                                                    &cpumask_of_cpu(j));
                                wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
                        }
-               }
 
                tmp = freqs.new;
                freqs.new = freqs.old;
index 2f3728dc24f60cc41db81e0066927a4ff15f409f..191f7263c61dce1b42864cd4709e249773339243 100644 (file)
@@ -244,8 +244,7 @@ static unsigned int _speedstep_get(const cpumask_t *cpus)
 
 static unsigned int speedstep_get(unsigned int cpu)
 {
-       cpumask_of_cpu_ptr(newmask, cpu);
-       return _speedstep_get(newmask);
+       return _speedstep_get(&cpumask_of_cpu(cpu));
 }
 
 /**
index 650d40f7912bea81023dc7f9698b8b10ced4d6fa..6b0a10b002f184406dac952f1370ac5c4eeb34e7 100644 (file)
@@ -516,7 +516,6 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
        unsigned long           j;
        int                     retval;
        cpumask_t               oldmask;
-       cpumask_of_cpu_ptr(newmask, cpu);
 
        if (num_cache_leaves == 0)
                return -ENOENT;
@@ -527,7 +526,7 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
                return -ENOMEM;
 
        oldmask = current->cpus_allowed;
-       retval = set_cpus_allowed_ptr(current, newmask);
+       retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
        if (retval)
                goto out;
 
index f67e93441caf2a892d637a54061257b1d4002828..a7010c3a377a436f29552e3b26a2b9a0b7a35084 100644 (file)
@@ -456,9 +456,6 @@ is386:      movl $2,%ecx            # set MP
 1:
 #endif /* CONFIG_SMP */
        jmp *(initial_code)
-.align 4
-ENTRY(initial_code)
-       .long i386_start_kernel
 
 /*
  * We depend on ET to be correct. This checks for 287/387.
@@ -601,6 +598,11 @@ ignore_int:
 #endif
        iret
 
+.section .cpuinit.data,"wa"
+.align 4
+ENTRY(initial_code)
+       .long i386_start_kernel
+
 .section .text
 /*
  * Real beginning of normal "text" segment
index 0ea6a19bfdfead682bbee695f165b05e9e4b9070..ad2b15a1334d919419b9040b52c2062dd5d3666d 100644 (file)
@@ -468,7 +468,7 @@ void hpet_disable(void)
 #define RTC_NUM_INTS           1
 
 static unsigned long hpet_rtc_flags;
-static unsigned long hpet_prev_update_sec;
+static int hpet_prev_update_sec;
 static struct rtc_time hpet_alarm_time;
 static unsigned long hpet_pie_count;
 static unsigned long hpet_t1_cmp;
@@ -575,6 +575,9 @@ int hpet_set_rtc_irq_bit(unsigned long bit_mask)
 
        hpet_rtc_flags |= bit_mask;
 
+       if ((bit_mask & RTC_UIE) && !(oldbits & RTC_UIE))
+               hpet_prev_update_sec = -1;
+
        if (!oldbits)
                hpet_rtc_timer_init();
 
@@ -652,7 +655,7 @@ static void hpet_rtc_timer_reinit(void)
                if (hpet_rtc_flags & RTC_PIE)
                        hpet_pie_count += lost_ints;
                if (printk_ratelimit())
-                       printk(KERN_WARNING "rtc: lost %d interrupts\n",
+                       printk(KERN_WARNING "hpet1: lost %d rtc interrupts\n",
                                lost_ints);
        }
 }
@@ -670,7 +673,8 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
 
        if (hpet_rtc_flags & RTC_UIE &&
            curr_time.tm_sec != hpet_prev_update_sec) {
-               rtc_int_flag = RTC_UF;
+               if (hpet_prev_update_sec >= 0)
+                       rtc_int_flag = RTC_UF;
                hpet_prev_update_sec = curr_time.tm_sec;
        }
 
index 0373e88de95ab5be0760b9adb34ace988d253fcc..1f26fd9ec4f4ea101c69ee030ac4142f4458d5ae 100644 (file)
 
 #define BUILD_IRQ(nr)                          \
        asmlinkage void IRQ_NAME(nr);           \
-       asm("\n.p2align\n"                      \
+       asm("\n.text\n.p2align\n"               \
            "IRQ" #nr "_interrupt:\n\t"         \
            "push $~(" #nr ") ; "               \
-           "jmp common_interrupt");
+           "jmp common_interrupt\n"            \
+           ".previous");
 
 #define BI(x,y) \
        BUILD_IRQ(x##y)
index 43c019f85f0db749425e451957bd2279cee47b80..6c27679ec6aa1753be87e05b6c72a10553f69574 100644 (file)
@@ -431,7 +431,6 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
                regs->ip = (unsigned long)p->ainsn.insn;
 }
 
-/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
                                      struct pt_regs *regs)
 {
@@ -682,8 +681,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
        unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
 
        INIT_HLIST_HEAD(&empty_rp);
-       spin_lock_irqsave(&kretprobe_lock, flags);
-       head = kretprobe_inst_table_head(current);
+       kretprobe_hash_lock(current, &head, &flags);
        /* fixup registers */
 #ifdef CONFIG_X86_64
        regs->cs = __KERNEL_CS;
@@ -732,7 +730,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
 
        kretprobe_assert(ri, orig_ret_address, trampoline_address);
 
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
+       kretprobe_hash_unlock(current, &flags);
 
        hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
                hlist_del(&ri->hlist);
index 3fee2aa50f3f63d594304611090338d36f3fcc01..6e388412a854ece43f2ce41f8831840c3f31a221 100644 (file)
@@ -51,6 +51,8 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
        memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
               (mincount - oldsize) * LDT_ENTRY_SIZE);
 
+       paravirt_alloc_ldt(newldt, mincount);
+
 #ifdef CONFIG_X86_64
        /* CHECKME: Do we really need this ? */
        wmb();
@@ -62,12 +64,10 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
 
        if (reload) {
 #ifdef CONFIG_SMP
-               cpumask_of_cpu_ptr_declare(mask);
-
                preempt_disable();
                load_LDT(pc);
-               cpumask_of_cpu_ptr_next(mask, smp_processor_id());
-               if (!cpus_equal(current->mm->cpu_vm_mask, *mask))
+               if (!cpus_equal(current->mm->cpu_vm_mask,
+                               cpumask_of_cpu(smp_processor_id())))
                        smp_call_function(flush_ldt, current->mm, 1);
                preempt_enable();
 #else
@@ -75,6 +75,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
 #endif
        }
        if (oldsize) {
+               paravirt_free_ldt(oldldt, oldsize);
                if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
                        vfree(oldldt);
                else
@@ -86,10 +87,13 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
 static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
 {
        int err = alloc_ldt(new, old->size, 0);
+       int i;
 
        if (err < 0)
                return err;
-       memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE);
+
+       for(i = 0; i < old->size; i++)
+               write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
        return 0;
 }
 
@@ -126,6 +130,7 @@ void destroy_context(struct mm_struct *mm)
                if (mm == current->active_mm)
                        clear_LDT();
 #endif
+               paravirt_free_ldt(mm->context.ldt, mm->context.size);
                if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
                        vfree(mm->context.ldt);
                else
index 8864230d55afd11476e96e13429c4a1ba03ce8cd..9fe478d984068fea53488d4405db4066863df39c 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/cpufeature.h>
 #include <asm/desc.h>
 #include <asm/system.h>
+#include <asm/cacheflush.h>
 
 #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
 static u32 kexec_pgd[1024] PAGE_ALIGNED;
@@ -85,10 +86,12 @@ static void load_segments(void)
  * reboot code buffer to allow us to avoid allocations
  * later.
  *
- * Currently nothing.
+ * Make control page executable.
  */
 int machine_kexec_prepare(struct kimage *image)
 {
+       if (nx_enabled)
+               set_pages_x(image->control_code_page, 1);
        return 0;
 }
 
@@ -98,27 +101,48 @@ int machine_kexec_prepare(struct kimage *image)
  */
 void machine_kexec_cleanup(struct kimage *image)
 {
+       if (nx_enabled)
+               set_pages_nx(image->control_code_page, 1);
 }
 
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
  */
-NORET_TYPE void machine_kexec(struct kimage *image)
+void machine_kexec(struct kimage *image)
 {
        unsigned long page_list[PAGES_NR];
        void *control_page;
+       asmlinkage unsigned long
+               (*relocate_kernel_ptr)(unsigned long indirection_page,
+                                      unsigned long control_page,
+                                      unsigned long start_address,
+                                      unsigned int has_pae,
+                                      unsigned int preserve_context);
 
        tracer_disable();
 
        /* Interrupts aren't acceptable while we reboot */
        local_irq_disable();
 
+       if (image->preserve_context) {
+#ifdef CONFIG_X86_IO_APIC
+               /* We need to put APICs in legacy mode so that we can
+                * get timer interrupts in second kernel. kexec/kdump
+                * paths already have calls to disable_IO_APIC() in
+                * one form or other. kexec jump path also need
+                * one.
+                */
+               disable_IO_APIC();
+#endif
+       }
+
        control_page = page_address(image->control_code_page);
-       memcpy(control_page, relocate_kernel, PAGE_SIZE);
+       memcpy(control_page, relocate_kernel, PAGE_SIZE/2);
 
+       relocate_kernel_ptr = control_page;
        page_list[PA_CONTROL_PAGE] = __pa(control_page);
-       page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
+       page_list[VA_CONTROL_PAGE] = (unsigned long)control_page;
        page_list[PA_PGD] = __pa(kexec_pgd);
        page_list[VA_PGD] = (unsigned long)kexec_pgd;
 #ifdef CONFIG_X86_PAE
@@ -131,6 +155,7 @@ NORET_TYPE void machine_kexec(struct kimage *image)
        page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
        page_list[PA_PTE_1] = __pa(kexec_pte1);
        page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
+       page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page) << PAGE_SHIFT);
 
        /* The segment registers are funny things, they have both a
         * visible and an invisible part.  Whenever the visible part is
@@ -149,8 +174,10 @@ NORET_TYPE void machine_kexec(struct kimage *image)
        set_idt(phys_to_virt(0),0);
 
        /* now call it */
-       relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
-                       image->start, cpu_has_pae);
+       image->start = relocate_kernel_ptr((unsigned long)image->head,
+                                          (unsigned long)page_list,
+                                          image->start, cpu_has_pae,
+                                          image->preserve_context);
 }
 
 void arch_crash_save_vmcoreinfo(void)
index 9dd9262693a330ae8aa81f386af90b0defb8c904..c43caa3a91f349ecd527da1ec936872785815092 100644 (file)
@@ -181,7 +181,7 @@ void machine_kexec_cleanup(struct kimage *image)
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
  */
-NORET_TYPE void machine_kexec(struct kimage *image)
+void machine_kexec(struct kimage *image)
 {
        unsigned long page_list[PAGES_NR];
        void *control_page;
index 6994c751590ec14ea31b7418bfd4659722466b2e..652fa5c38ebe34c0846fc56f0a8e0eb89e5f3c6a 100644 (file)
@@ -388,7 +388,6 @@ static int do_microcode_update (void)
        void *new_mc = NULL;
        int cpu;
        cpumask_t old;
-       cpumask_of_cpu_ptr_declare(newmask);
 
        old = current->cpus_allowed;
 
@@ -405,8 +404,7 @@ static int do_microcode_update (void)
 
                        if (!uci->valid)
                                continue;
-                       cpumask_of_cpu_ptr_next(newmask, cpu);
-                       set_cpus_allowed_ptr(current, newmask);
+                       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
                        error = get_maching_microcode(new_mc, cpu);
                        if (error < 0)
                                goto out;
@@ -576,7 +574,6 @@ static int apply_microcode_check_cpu(int cpu)
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
        cpumask_t old;
-       cpumask_of_cpu_ptr(newmask, cpu);
        unsigned int val[2];
        int err = 0;
 
@@ -585,7 +582,7 @@ static int apply_microcode_check_cpu(int cpu)
                return 0;
 
        old = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, newmask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
 
        /* Check if the microcode we have in memory matches the CPU */
        if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
@@ -623,12 +620,11 @@ static int apply_microcode_check_cpu(int cpu)
 static void microcode_init_cpu(int cpu, int resume)
 {
        cpumask_t old;
-       cpumask_of_cpu_ptr(newmask, cpu);
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
        old = current->cpus_allowed;
 
-       set_cpus_allowed_ptr(current, newmask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
        mutex_lock(&microcode_mutex);
        collect_cpu_info(cpu);
        if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
@@ -661,13 +657,10 @@ static ssize_t reload_store(struct sys_device *dev,
        if (end == buf)
                return -EINVAL;
        if (val == 1) {
-               cpumask_t old;
-               cpumask_of_cpu_ptr(newmask, cpu);
-
-               old = current->cpus_allowed;
+               cpumask_t old = current->cpus_allowed;
 
                get_online_cpus();
-               set_cpus_allowed_ptr(current, newmask);
+               set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
 
                mutex_lock(&microcode_mutex);
                if (uci->valid)
index 0e867676b5a57ebd14b063bf71cdac852e2b4089..6ba87830d4b130e6aac27eef6aa5442c2e1d1e40 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/bug.h>
 
index 0d71de9ff56dd9528660456f87f4eec7554afbd7..7faea1817d0556c493c1fbd2c76f527af49cb40f 100644 (file)
@@ -337,6 +337,10 @@ struct pv_cpu_ops pv_cpu_ops = {
        .write_ldt_entry = native_write_ldt_entry,
        .write_gdt_entry = native_write_gdt_entry,
        .write_idt_entry = native_write_idt_entry,
+
+       .alloc_ldt = paravirt_nop,
+       .free_ldt = paravirt_nop,
+
        .load_sp0 = native_load_sp0,
 
 #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
index 151f2d171f7c7386b7a14f574d4c7f34edfab0f3..b67a4b1d4eaefd1399ae3996932b061a12357fc7 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
+#include <linux/crash_dump.h>
 #include <linux/dma-mapping.h>
 #include <linux/bitops.h>
 #include <linux/pci_ids.h>
@@ -36,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/scatterlist.h>
 #include <linux/iommu-helper.h>
+
 #include <asm/iommu.h>
 #include <asm/calgary.h>
 #include <asm/tce.h>
@@ -167,6 +169,8 @@ static void calgary_dump_error_regs(struct iommu_table *tbl);
 static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev);
 static void calioc2_tce_cache_blast(struct iommu_table *tbl);
 static void calioc2_dump_error_regs(struct iommu_table *tbl);
+static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl);
+static void get_tce_space_from_tar(void);
 
 static struct cal_chipset_ops calgary_chip_ops = {
        .handle_quirks = calgary_handle_quirks,
@@ -410,22 +414,6 @@ static void calgary_unmap_sg(struct device *dev,
        }
 }
 
-static int calgary_nontranslate_map_sg(struct device* dev,
-       struct scatterlist *sg, int nelems, int direction)
-{
-       struct scatterlist *s;
-       int i;
-
-       for_each_sg(sg, s, nelems, i) {
-               struct page *p = sg_page(s);
-
-               BUG_ON(!p);
-               s->dma_address = virt_to_bus(sg_virt(s));
-               s->dma_length = s->length;
-       }
-       return nelems;
-}
-
 static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
        int nelems, int direction)
 {
@@ -436,9 +424,6 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
        unsigned long entry;
        int i;
 
-       if (!translation_enabled(tbl))
-               return calgary_nontranslate_map_sg(dev, sg, nelems, direction);
-
        for_each_sg(sg, s, nelems, i) {
                BUG_ON(!sg_page(s));
 
@@ -474,7 +459,6 @@ error:
 static dma_addr_t calgary_map_single(struct device *dev, phys_addr_t paddr,
        size_t size, int direction)
 {
-       dma_addr_t dma_handle = bad_dma_address;
        void *vaddr = phys_to_virt(paddr);
        unsigned long uaddr;
        unsigned int npages;
@@ -483,12 +467,7 @@ static dma_addr_t calgary_map_single(struct device *dev, phys_addr_t paddr,
        uaddr = (unsigned long)vaddr;
        npages = num_dma_pages(uaddr, size);
 
-       if (translation_enabled(tbl))
-               dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction);
-       else
-               dma_handle = virt_to_bus(vaddr);
-
-       return dma_handle;
+       return iommu_alloc(dev, tbl, vaddr, npages, direction);
 }
 
 static void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
@@ -497,9 +476,6 @@ static void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
        struct iommu_table *tbl = find_iommu_table(dev);
        unsigned int npages;
 
-       if (!translation_enabled(tbl))
-               return;
-
        npages = num_dma_pages(dma_handle, size);
        iommu_free(tbl, dma_handle, npages);
 }
@@ -522,18 +498,12 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size,
                goto error;
        memset(ret, 0, size);
 
-       if (translation_enabled(tbl)) {
-               /* set up tces to cover the allocated range */
-               mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL);
-               if (mapping == bad_dma_address)
-                       goto free;
-
-               *dma_handle = mapping;
-       } else /* non translated slot */
-               *dma_handle = virt_to_bus(ret);
-
+       /* set up tces to cover the allocated range */
+       mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL);
+       if (mapping == bad_dma_address)
+               goto free;
+       *dma_handle = mapping;
        return ret;
-
 free:
        free_pages((unsigned long)ret, get_order(size));
        ret = NULL;
@@ -541,7 +511,7 @@ error:
        return ret;
 }
 
-static const struct dma_mapping_ops calgary_dma_ops = {
+static struct dma_mapping_ops calgary_dma_ops = {
        .alloc_coherent = calgary_alloc_coherent,
        .map_single = calgary_map_single,
        .unmap_single = calgary_unmap_single,
@@ -830,7 +800,11 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
 
        tbl = pci_iommu(dev->bus);
        tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space;
-       tce_free(tbl, 0, tbl->it_size);
+
+       if (is_kdump_kernel())
+               calgary_init_bitmap_from_tce_table(tbl);
+       else
+               tce_free(tbl, 0, tbl->it_size);
 
        if (is_calgary(dev->device))
                tbl->chip_ops = &calgary_chip_ops;
@@ -1209,6 +1183,10 @@ static int __init calgary_init(void)
        if (ret)
                return ret;
 
+       /* Purely for kdump kernel case */
+       if (is_kdump_kernel())
+               get_tce_space_from_tar();
+
        do {
                dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_ANY_ID, dev);
                if (!dev)
@@ -1230,6 +1208,16 @@ static int __init calgary_init(void)
                        goto error;
        } while (1);
 
+       dev = NULL;
+       for_each_pci_dev(dev) {
+               struct iommu_table *tbl;
+
+               tbl = find_iommu_table(&dev->dev);
+
+               if (translation_enabled(tbl))
+                       dev->dev.archdata.dma_ops = &calgary_dma_ops;
+       }
+
        return ret;
 
 error:
@@ -1251,6 +1239,7 @@ error:
                calgary_disable_translation(dev);
                calgary_free_bus(dev);
                pci_dev_put(dev); /* Undo calgary_init_one()'s pci_dev_get() */
+               dev->dev.archdata.dma_ops = NULL;
        } while (1);
 
        return ret;
@@ -1339,6 +1328,61 @@ static int __init calgary_bus_has_devices(int bus, unsigned short pci_dev)
        return (val != 0xffffffff);
 }
 
+/*
+ * calgary_init_bitmap_from_tce_table():
+ * Funtion for kdump case. In the second/kdump kernel initialize
+ * the bitmap based on the tce table entries obtained from first kernel
+ */
+static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl)
+{
+       u64 *tp;
+       unsigned int index;
+       tp = ((u64 *)tbl->it_base);
+       for (index = 0 ; index < tbl->it_size; index++) {
+               if (*tp != 0x0)
+                       set_bit(index, tbl->it_map);
+               tp++;
+       }
+}
+
+/*
+ * get_tce_space_from_tar():
+ * Function for kdump case. Get the tce tables from first kernel
+ * by reading the contents of the base adress register of calgary iommu
+ */
+static void get_tce_space_from_tar()
+{
+       int bus;
+       void __iomem *target;
+       unsigned long tce_space;
+
+       for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
+               struct calgary_bus_info *info = &bus_info[bus];
+               unsigned short pci_device;
+               u32 val;
+
+               val = read_pci_config(bus, 0, 0, 0);
+               pci_device = (val & 0xFFFF0000) >> 16;
+
+               if (!is_cal_pci_dev(pci_device))
+                       continue;
+               if (info->translation_disabled)
+                       continue;
+
+               if (calgary_bus_has_devices(bus, pci_device) ||
+                                               translate_empty_slots) {
+                       target = calgary_reg(bus_info[bus].bbar,
+                                               tar_offset(bus));
+                       tce_space = be64_to_cpu(readq(target));
+                       tce_space = tce_space & TAR_SW_BITS;
+
+                       tce_space = tce_space & (~specified_table_size);
+                       info->tce_space = (u64 *)__va(tce_space);
+               }
+       }
+       return;
+}
+
 void __init detect_calgary(void)
 {
        int bus;
@@ -1394,7 +1438,8 @@ void __init detect_calgary(void)
                return;
        }
 
-       specified_table_size = determine_tce_table_size(max_pfn * PAGE_SIZE);
+       specified_table_size = determine_tce_table_size((is_kdump_kernel() ?
+                                       saved_max_pfn : max_pfn) * PAGE_SIZE);
 
        for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
                struct calgary_bus_info *info = &bus_info[bus];
@@ -1412,10 +1457,16 @@ void __init detect_calgary(void)
 
                if (calgary_bus_has_devices(bus, pci_device) ||
                    translate_empty_slots) {
-                       tbl = alloc_tce_table();
-                       if (!tbl)
-                               goto cleanup;
-                       info->tce_space = tbl;
+                       /*
+                        * If it is kdump kernel, find and use tce tables
+                        * from first kernel, else allocate tce tables here
+                        */
+                       if (!is_kdump_kernel()) {
+                               tbl = alloc_tce_table();
+                               if (!tbl)
+                                       goto cleanup;
+                               info->tce_space = tbl;
+                       }
                        calgary_found = 1;
                }
        }
@@ -1430,6 +1481,10 @@ void __init detect_calgary(void)
                printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d, "
                       "CONFIG_IOMMU_DEBUG is %s.\n", specified_table_size,
                       debugging ? "enabled" : "disabled");
+
+               /* swiotlb for devices that aren't behind the Calgary. */
+               if (max_pfn > MAX_DMA32_PFN)
+                       swiotlb = 1;
        }
        return;
 
@@ -1446,7 +1501,7 @@ int __init calgary_iommu_init(void)
 {
        int ret;
 
-       if (no_iommu || swiotlb)
+       if (no_iommu || (swiotlb && !calgary_detected))
                return -ENODEV;
 
        if (!calgary_detected)
@@ -1459,15 +1514,14 @@ int __init calgary_iommu_init(void)
        if (ret) {
                printk(KERN_ERR "PCI-DMA: Calgary init failed %d, "
                       "falling back to no_iommu\n", ret);
-               if (max_pfn > MAX_DMA32_PFN)
-                       printk(KERN_ERR "WARNING more than 4GB of memory, "
-                                       "32bit PCI may malfunction.\n");
                return ret;
        }
 
        force_iommu = 1;
        bad_dma_address = 0x0;
-       dma_ops = &calgary_dma_ops;
+       /* dma_ops is set to swiotlb or nommu */
+       if (!dma_ops)
+               dma_ops = &nommu_dma_ops;
 
        return 0;
 }
index cbecb05551bbcefeb68e6048bd1dd5aeab5376f7..8dbffb846de9b66c5a1aec5cc542dc959acfa924 100644 (file)
@@ -11,7 +11,7 @@
 
 static int forbid_dac __read_mostly;
 
-const struct dma_mapping_ops *dma_ops;
+struct dma_mapping_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
 static int iommu_sac_force __read_mostly;
@@ -192,126 +192,10 @@ static __init int iommu_setup(char *p)
 }
 early_param("iommu", iommu_setup);
 
-#ifdef CONFIG_X86_32
-int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
-                               dma_addr_t device_addr, size_t size, int flags)
-{
-       void __iomem *mem_base = NULL;
-       int pages = size >> PAGE_SHIFT;
-       int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
-
-       if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
-               goto out;
-       if (!size)
-               goto out;
-       if (dev->dma_mem)
-               goto out;
-
-       /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
-
-       mem_base = ioremap(bus_addr, size);
-       if (!mem_base)
-               goto out;
-
-       dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
-       if (!dev->dma_mem)
-               goto out;
-       dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-       if (!dev->dma_mem->bitmap)
-               goto free1_out;
-
-       dev->dma_mem->virt_base = mem_base;
-       dev->dma_mem->device_base = device_addr;
-       dev->dma_mem->size = pages;
-       dev->dma_mem->flags = flags;
-
-       if (flags & DMA_MEMORY_MAP)
-               return DMA_MEMORY_MAP;
-
-       return DMA_MEMORY_IO;
-
- free1_out:
-       kfree(dev->dma_mem);
- out:
-       if (mem_base)
-               iounmap(mem_base);
-       return 0;
-}
-EXPORT_SYMBOL(dma_declare_coherent_memory);
-
-void dma_release_declared_memory(struct device *dev)
-{
-       struct dma_coherent_mem *mem = dev->dma_mem;
-
-       if (!mem)
-               return;
-       dev->dma_mem = NULL;
-       iounmap(mem->virt_base);
-       kfree(mem->bitmap);
-       kfree(mem);
-}
-EXPORT_SYMBOL(dma_release_declared_memory);
-
-void *dma_mark_declared_memory_occupied(struct device *dev,
-                                       dma_addr_t device_addr, size_t size)
-{
-       struct dma_coherent_mem *mem = dev->dma_mem;
-       int pos, err;
-       int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
-
-       pages >>= PAGE_SHIFT;
-
-       if (!mem)
-               return ERR_PTR(-EINVAL);
-
-       pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
-       err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
-       if (err != 0)
-               return ERR_PTR(err);
-       return mem->virt_base + (pos << PAGE_SHIFT);
-}
-EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
-
-static int dma_alloc_from_coherent_mem(struct device *dev, ssize_t size,
-                                      dma_addr_t *dma_handle, void **ret)
-{
-       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
-       int order = get_order(size);
-
-       if (mem) {
-               int page = bitmap_find_free_region(mem->bitmap, mem->size,
-                                                    order);
-               if (page >= 0) {
-                       *dma_handle = mem->device_base + (page << PAGE_SHIFT);
-                       *ret = mem->virt_base + (page << PAGE_SHIFT);
-                       memset(*ret, 0, size);
-               }
-               if (mem->flags & DMA_MEMORY_EXCLUSIVE)
-                       *ret = NULL;
-       }
-       return (mem != NULL);
-}
-
-static int dma_release_coherent(struct device *dev, int order, void *vaddr)
-{
-       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
-
-       if (mem && vaddr >= mem->virt_base && vaddr <
-                  (mem->virt_base + (mem->size << PAGE_SHIFT))) {
-               int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
-
-               bitmap_release_region(mem->bitmap, page, order);
-               return 1;
-       }
-       return 0;
-}
-#else
-#define dma_alloc_from_coherent_mem(dev, size, handle, ret) (0)
-#define dma_release_coherent(dev, order, vaddr) (0)
-#endif /* CONFIG_X86_32 */
-
 int dma_supported(struct device *dev, u64 mask)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(dev);
+
 #ifdef CONFIG_PCI
        if (mask > 0xffffffff && forbid_dac > 0) {
                dev_info(dev, "PCI: Disallowing DAC for device\n");
@@ -319,8 +203,8 @@ int dma_supported(struct device *dev, u64 mask)
        }
 #endif
 
-       if (dma_ops->dma_supported)
-               return dma_ops->dma_supported(dev, mask);
+       if (ops->dma_supported)
+               return ops->dma_supported(dev, mask);
 
        /* Copied from i386. Doesn't make much sense, because it will
           only work for pci_alloc_coherent.
@@ -367,6 +251,7 @@ void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
                   gfp_t gfp)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(dev);
        void *memory = NULL;
        struct page *page;
        unsigned long dma_mask = 0;
@@ -376,7 +261,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
        /* ignore region specifiers */
        gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
 
-       if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory))
+       if (dma_alloc_from_coherent(dev, size, dma_handle, &memory))
                return memory;
 
        if (!dev) {
@@ -435,8 +320,8 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
                        /* Let low level make its own zone decisions */
                        gfp &= ~(GFP_DMA32|GFP_DMA);
 
-                       if (dma_ops->alloc_coherent)
-                               return dma_ops->alloc_coherent(dev, size,
+                       if (ops->alloc_coherent)
+                               return ops->alloc_coherent(dev, size,
                                                           dma_handle, gfp);
                        return NULL;
                }
@@ -448,14 +333,14 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
                }
        }
 
-       if (dma_ops->alloc_coherent) {
+       if (ops->alloc_coherent) {
                free_pages((unsigned long)memory, get_order(size));
                gfp &= ~(GFP_DMA|GFP_DMA32);
-               return dma_ops->alloc_coherent(dev, size, dma_handle, gfp);
+               return ops->alloc_coherent(dev, size, dma_handle, gfp);
        }
 
-       if (dma_ops->map_simple) {
-               *dma_handle = dma_ops->map_simple(dev, virt_to_phys(memory),
+       if (ops->map_simple) {
+               *dma_handle = ops->map_simple(dev, virt_to_phys(memory),
                                              size,
                                              PCI_DMA_BIDIRECTIONAL);
                if (*dma_handle != bad_dma_address)
@@ -477,12 +362,14 @@ EXPORT_SYMBOL(dma_alloc_coherent);
 void dma_free_coherent(struct device *dev, size_t size,
                         void *vaddr, dma_addr_t bus)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(dev);
+
        int order = get_order(size);
        WARN_ON(irqs_disabled());       /* for portability */
-       if (dma_release_coherent(dev, order, vaddr))
+       if (dma_release_from_coherent(dev, order, vaddr))
                return;
-       if (dma_ops->unmap_single)
-               dma_ops->unmap_single(dev, bus, size, 0);
+       if (ops->unmap_single)
+               ops->unmap_single(dev, bus, size, 0);
        free_pages((unsigned long)vaddr, order);
 }
 EXPORT_SYMBOL(dma_free_coherent);
index df5f142657d27352a9e3c1bbd911fd89f677c1fa..49285f8fd4d54005d5efb9a9fad6bc498420e6d6 100644 (file)
@@ -67,9 +67,6 @@ static u32 gart_unmapped_entry;
        (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT)
 #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28))
 
-#define to_pages(addr, size) \
-       (round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT)
-
 #define EMERGENCY_PAGES 32 /* = 128KB */
 
 #ifdef CONFIG_AGP
@@ -241,7 +238,7 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
 static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
                                size_t size, int dir)
 {
-       unsigned long npages = to_pages(phys_mem, size);
+       unsigned long npages = iommu_num_pages(phys_mem, size);
        unsigned long iommu_page = alloc_iommu(dev, npages);
        int i;
 
@@ -304,7 +301,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
                return;
 
        iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;
-       npages = to_pages(dma_addr, size);
+       npages = iommu_num_pages(dma_addr, size);
        for (i = 0; i < npages; i++) {
                iommu_gatt_base[iommu_page + i] = gart_unmapped_entry;
                CLEAR_LEAK(iommu_page + i);
@@ -387,7 +384,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start,
                }
 
                addr = phys_addr;
-               pages = to_pages(s->offset, s->length);
+               pages = iommu_num_pages(s->offset, s->length);
                while (pages--) {
                        iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr);
                        SET_LEAK(iommu_page);
@@ -470,7 +467,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
 
                seg_size += s->length;
                need = nextneed;
-               pages += to_pages(s->offset, s->length);
+               pages += iommu_num_pages(s->offset, s->length);
                ps = s;
        }
        if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
@@ -692,8 +689,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
 
 extern int agp_amd64_init(void);
 
-static const struct dma_mapping_ops gart_dma_ops = {
-       .mapping_error                  = NULL,
+static struct dma_mapping_ops gart_dma_ops = {
        .map_single                     = gart_map_single,
        .map_simple                     = gart_map_simple,
        .unmap_single                   = gart_unmap_single,
index 792b9179eff315ecf3ae26e7e1635073e1a42c26..3f91f71cdc3eac766be0891511afd738001c6918 100644 (file)
@@ -72,21 +72,9 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
        return nents;
 }
 
-/* Make sure we keep the same behaviour */
-static int nommu_mapping_error(dma_addr_t dma_addr)
-{
-#ifdef CONFIG_X86_32
-       return 0;
-#else
-       return (dma_addr == bad_dma_address);
-#endif
-}
-
-
-const struct dma_mapping_ops nommu_dma_ops = {
+struct dma_mapping_ops nommu_dma_ops = {
        .map_single = nommu_map_single,
        .map_sg = nommu_map_sg,
-       .mapping_error = nommu_mapping_error,
        .is_phys = 1,
 };
 
index 20df839b9c2012c12fa082c7b42ada6e63879a87..c4ce0332759ee08413e78e6623b5a023f6404fc7 100644 (file)
@@ -18,7 +18,7 @@ swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size,
        return swiotlb_map_single(hwdev, phys_to_virt(paddr), size, direction);
 }
 
-const struct dma_mapping_ops swiotlb_dma_ops = {
+struct dma_mapping_ops swiotlb_dma_ops = {
        .mapping_error = swiotlb_dma_mapping_error,
        .alloc_coherent = swiotlb_alloc_coherent,
        .free_coherent = swiotlb_free_coherent,
index 0c3927accb0054b71c7de9eb828a93559232737e..53bc653ed5ca52bab902dde3d9efbc0e1630eb6c 100644 (file)
@@ -128,7 +128,7 @@ void cpu_idle(void)
 
        /* endless idle loop with no priority at all */
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched()) {
 
                        check_pgt_cache();
index e8a8e1b998176fba76076a6a9b0c9d432f6f3922..3fb62a7d9a16250092a9827a66af062be4824513 100644 (file)
@@ -120,7 +120,7 @@ void cpu_idle(void)
        current_thread_info()->status |= TS_POLLING;
        /* endless idle loop with no priority at all */
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched()) {
 
                        rmb();
index 06a9f643817ee0310d1dce58da6a86f30b5c23cd..724adfc63cb9a7b60d6ee5c82efd919fe237f69c 100644 (file)
@@ -414,25 +414,20 @@ void native_machine_shutdown(void)
 
        /* The boot cpu is always logical cpu 0 */
        int reboot_cpu_id = 0;
-       cpumask_of_cpu_ptr(newmask, reboot_cpu_id);
 
 #ifdef CONFIG_X86_32
        /* See if there has been given a command line override */
        if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
-               cpu_online(reboot_cpu)) {
+               cpu_online(reboot_cpu))
                reboot_cpu_id = reboot_cpu;
-               cpumask_of_cpu_ptr_next(newmask, reboot_cpu_id);
-       }
 #endif
 
        /* Make certain the cpu I'm about to reboot on is online */
-       if (!cpu_online(reboot_cpu_id)) {
+       if (!cpu_online(reboot_cpu_id))
                reboot_cpu_id = smp_processor_id();
-               cpumask_of_cpu_ptr_next(newmask, reboot_cpu_id);
-       }
 
        /* Make certain I only run on the appropriate processor */
-       set_cpus_allowed_ptr(current, newmask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id));
 
        /* O.K Now that I'm on the appropriate processor,
         * stop all of the others.
index c30fe25d470d8ff63cd0abe40353f6577c12fab4..703310a990239d686516fbcccfc5ede3d05c0cda 100644 (file)
 #define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define PAE_PGD_ATTR (_PAGE_PRESENT)
 
+/* control_page + PAGE_SIZE/2 ~ control_page + PAGE_SIZE * 3/4 are
+ * used to save some data for jumping back
+ */
+#define DATA(offset)           (PAGE_SIZE/2+(offset))
+
+/* Minimal CPU state */
+#define ESP                    DATA(0x0)
+#define CR0                    DATA(0x4)
+#define CR3                    DATA(0x8)
+#define CR4                    DATA(0xc)
+
+/* other data */
+#define CP_VA_CONTROL_PAGE     DATA(0x10)
+#define CP_PA_PGD              DATA(0x14)
+#define CP_PA_SWAP_PAGE                DATA(0x18)
+#define CP_PA_BACKUP_PAGES_MAP DATA(0x1c)
+
        .text
        .align PAGE_SIZE
        .globl relocate_kernel
 relocate_kernel:
-       movl    8(%esp), %ebp /* list of pages */
+       /* Save the CPU context, used for jumping back */
+
+       pushl   %ebx
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebp
+       pushf
+
+       movl    20+8(%esp), %ebp /* list of pages */
+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %edi
+       movl    %esp, ESP(%edi)
+       movl    %cr0, %eax
+       movl    %eax, CR0(%edi)
+       movl    %cr3, %eax
+       movl    %eax, CR3(%edi)
+       movl    %cr4, %eax
+       movl    %eax, CR4(%edi)
 
 #ifdef CONFIG_X86_PAE
        /* map the control page at its virtual address */
@@ -138,15 +171,25 @@ relocate_kernel:
 
 relocate_new_kernel:
        /* read the arguments and say goodbye to the stack */
-       movl  4(%esp), %ebx /* page_list */
-       movl  8(%esp), %ebp /* list of pages */
-       movl  12(%esp), %edx /* start address */
-       movl  16(%esp), %ecx /* cpu_has_pae */
+       movl  20+4(%esp), %ebx /* page_list */
+       movl  20+8(%esp), %ebp /* list of pages */
+       movl  20+12(%esp), %edx /* start address */
+       movl  20+16(%esp), %ecx /* cpu_has_pae */
+       movl  20+20(%esp), %esi /* preserve_context */
 
        /* zero out flags, and disable interrupts */
        pushl $0
        popfl
 
+       /* save some information for jumping back */
+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %edi
+       movl    %edi, CP_VA_CONTROL_PAGE(%edi)
+       movl    PTR(PA_PGD)(%ebp), %eax
+       movl    %eax, CP_PA_PGD(%edi)
+       movl    PTR(PA_SWAP_PAGE)(%ebp), %eax
+       movl    %eax, CP_PA_SWAP_PAGE(%edi)
+       movl    %ebx, CP_PA_BACKUP_PAGES_MAP(%edi)
+
        /* get physical address of control page now */
        /* this is impossible after page table switch */
        movl    PTR(PA_CONTROL_PAGE)(%ebp), %edi
@@ -197,8 +240,90 @@ identity_mapped:
        xorl    %eax, %eax
        movl    %eax, %cr3
 
+       movl    CP_PA_SWAP_PAGE(%edi), %eax
+       pushl   %eax
+       pushl   %ebx
+       call    swap_pages
+       addl    $8, %esp
+
+       /* To be certain of avoiding problems with self-modifying code
+        * I need to execute a serializing instruction here.
+        * So I flush the TLB, it's handy, and not processor dependent.
+        */
+       xorl    %eax, %eax
+       movl    %eax, %cr3
+
+       /* set all of the registers to known values */
+       /* leave %esp alone */
+
+       testl   %esi, %esi
+       jnz 1f
+       xorl    %edi, %edi
+       xorl    %eax, %eax
+       xorl    %ebx, %ebx
+       xorl    %ecx, %ecx
+       xorl    %edx, %edx
+       xorl    %esi, %esi
+       xorl    %ebp, %ebp
+       ret
+1:
+       popl    %edx
+       movl    CP_PA_SWAP_PAGE(%edi), %esp
+       addl    $PAGE_SIZE, %esp
+2:
+       call    *%edx
+
+       /* get the re-entry point of the peer system */
+       movl    0(%esp), %ebp
+       call    1f
+1:
+       popl    %ebx
+       subl    $(1b - relocate_kernel), %ebx
+       movl    CP_VA_CONTROL_PAGE(%ebx), %edi
+       lea     PAGE_SIZE(%ebx), %esp
+       movl    CP_PA_SWAP_PAGE(%ebx), %eax
+       movl    CP_PA_BACKUP_PAGES_MAP(%ebx), %edx
+       pushl   %eax
+       pushl   %edx
+       call    swap_pages
+       addl    $8, %esp
+       movl    CP_PA_PGD(%ebx), %eax
+       movl    %eax, %cr3
+       movl    %cr0, %eax
+       orl     $(1<<31), %eax
+       movl    %eax, %cr0
+       lea     PAGE_SIZE(%edi), %esp
+       movl    %edi, %eax
+       addl    $(virtual_mapped - relocate_kernel), %eax
+       pushl   %eax
+       ret
+
+virtual_mapped:
+       movl    CR4(%edi), %eax
+       movl    %eax, %cr4
+       movl    CR3(%edi), %eax
+       movl    %eax, %cr3
+       movl    CR0(%edi), %eax
+       movl    %eax, %cr0
+       movl    ESP(%edi), %esp
+       movl    %ebp, %eax
+
+       popf
+       popl    %ebp
+       popl    %edi
+       popl    %esi
+       popl    %ebx
+       ret
+
        /* Do the copies */
-       movl    %ebx, %ecx
+swap_pages:
+       movl    8(%esp), %edx
+       movl    4(%esp), %ecx
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edi
+       pushl   %esi
+       movl    %ecx, %ebx
        jmp     1f
 
 0:     /* top, read another word from the indirection page */
@@ -226,27 +351,28 @@ identity_mapped:
        movl    %ecx,   %esi /* For every source page do a copy */
        andl    $0xfffff000, %esi
 
+       movl    %edi, %eax
+       movl    %esi, %ebp
+
+       movl    %edx, %edi
        movl    $1024, %ecx
        rep ; movsl
-       jmp     0b
 
-3:
-
-       /* To be certain of avoiding problems with self-modifying code
-        * I need to execute a serializing instruction here.
-        * So I flush the TLB, it's handy, and not processor dependent.
-        */
-       xorl    %eax, %eax
-       movl    %eax, %cr3
+       movl    %ebp, %edi
+       movl    %eax, %esi
+       movl    $1024, %ecx
+       rep ; movsl
 
-       /* set all of the registers to known values */
-       /* leave %esp alone */
+       movl    %eax, %edi
+       movl    %edx, %esi
+       movl    $1024, %ecx
+       rep ; movsl
 
-       xorl    %eax, %eax
-       xorl    %ebx, %ebx
-       xorl    %ecx, %ecx
-       xorl    %edx, %edx
-       xorl    %esi, %esi
-       xorl    %edi, %edi
-       xorl    %ebp, %ebp
+       lea     PAGE_SIZE(%ebp), %esi
+       jmp     0b
+3:
+       popl    %esi
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
        ret
index b4aacb9f52e3e29295acd3e8920df9306a8e8308..b520dae02bf4806c6a9f79fd82bf444f24daba0c 100644 (file)
@@ -597,11 +597,11 @@ void __init setup_arch(char **cmdline_p)
        memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
        visws_early_detect();
        pre_setup_arch_hook();
-       early_cpu_init();
 #else
        printk(KERN_INFO "Command line: %s\n", boot_command_line);
 #endif
 
+       early_cpu_init();
        early_ioremap_init();
 
        ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
@@ -665,9 +665,6 @@ void __init setup_arch(char **cmdline_p)
        bss_resource.start = virt_to_phys(&__bss_start);
        bss_resource.end = virt_to_phys(&__bss_stop)-1;
 
-#ifdef CONFIG_X86_64
-       early_cpu_init();
-#endif
        strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
        *cmdline_p = command_line;
 
index f7745f94c0061236b8b224afd44d3a19eb63f3d1..76e305e064f96f9f7ece081665de18e7fb189e9a 100644 (file)
@@ -80,24 +80,6 @@ static void __init setup_per_cpu_maps(void)
 #endif
 }
 
-#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
-cpumask_t *cpumask_of_cpu_map __read_mostly;
-EXPORT_SYMBOL(cpumask_of_cpu_map);
-
-/* requires nr_cpu_ids to be initialized */
-static void __init setup_cpumask_of_cpu(void)
-{
-       int i;
-
-       /* alloc_bootmem zeroes memory */
-       cpumask_of_cpu_map = alloc_bootmem_low(sizeof(cpumask_t) * nr_cpu_ids);
-       for (i = 0; i < nr_cpu_ids; i++)
-               cpu_set(i, cpumask_of_cpu_map[i]);
-}
-#else
-static inline void setup_cpumask_of_cpu(void) { }
-#endif
-
 #ifdef CONFIG_X86_32
 /*
  * Great future not-so-futuristic plan: make i386 and x86_64 do it
@@ -197,9 +179,6 @@ void __init setup_per_cpu_areas(void)
 
        /* Setup node to cpumask map */
        setup_node_to_cpumask_map();
-
-       /* Setup cpumask_of_cpu map */
-       setup_cpumask_of_cpu();
 }
 
 #endif
index 47c3d249e638efdf72395cb2f269f8bcf63a5576..b45ef8ddd6510901ab3d089e1ca21f36a90167d7 100644 (file)
@@ -53,6 +53,59 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
        return do_sigaltstack(uss, uoss, regs->sp);
 }
 
+/*
+ * Signal frame handlers.
+ */
+
+static inline int save_i387(struct _fpstate __user *buf)
+{
+       struct task_struct *tsk = current;
+       int err = 0;
+
+       BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
+                       sizeof(tsk->thread.xstate->fxsave));
+
+       if ((unsigned long)buf % 16)
+               printk("save_i387: bad fpstate %p\n", buf);
+
+       if (!used_math())
+               return 0;
+       clear_used_math(); /* trigger finit */
+       if (task_thread_info(tsk)->status & TS_USEDFPU) {
+               err = save_i387_checking((struct i387_fxsave_struct __user *)
+                                        buf);
+               if (err)
+                       return err;
+               task_thread_info(tsk)->status &= ~TS_USEDFPU;
+               stts();
+       } else {
+               if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
+                                  sizeof(struct i387_fxsave_struct)))
+                       return -1;
+       }
+       return 1;
+}
+
+/*
+ * This restores directly out of user space. Exceptions are handled.
+ */
+static inline int restore_i387(struct _fpstate __user *buf)
+{
+       struct task_struct *tsk = current;
+       int err;
+
+       if (!used_math()) {
+               err = init_fpu(tsk);
+               if (err)
+                       return err;
+       }
+
+       if (!(task_thread_info(current)->status & TS_USEDFPU)) {
+               clts();
+               task_thread_info(current)->status |= TS_USEDFPU;
+       }
+       return restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
+}
 
 /*
  * Do a signal return; undo the signal stack.
index adff5562f5fd4bbc40965ba8eb5f33d433f9f776..d44395ff34c34f99d91726b975961503c6f7380b 100644 (file)
@@ -326,3 +326,9 @@ ENTRY(sys_call_table)
        .long sys_fallocate
        .long sys_timerfd_settime       /* 325 */
        .long sys_timerfd_gettime
+       .long sys_signalfd4
+       .long sys_eventfd2
+       .long sys_epoll_create1
+       .long sys_dup3                  /* 330 */
+       .long sys_pipe2
+       .long sys_inotify_init1
index 8d45fabc5f3baf556b1da2558a42df183ab09e80..ce3251ce5504e478ff65f936608245be3df7312e 100644 (file)
@@ -21,6 +21,7 @@ config KVM
        tristate "Kernel-based Virtual Machine (KVM) support"
        depends on HAVE_KVM
        select PREEMPT_NOTIFIERS
+       select MMU_NOTIFIER
        select ANON_INODES
        ---help---
          Support hosting fully virtualized guest machines using hardware
index b0e4ddca6c1856a2441fe9641ae46cc71ab39724..2fa231923cf7e90d9e969478f22207ba0040cd57 100644 (file)
@@ -1814,6 +1814,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
        spin_unlock(&vcpu->kvm->mmu_lock);
        return r;
 }
+EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt);
 
 void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
 {
@@ -1870,6 +1871,12 @@ void kvm_enable_tdp(void)
 }
 EXPORT_SYMBOL_GPL(kvm_enable_tdp);
 
+void kvm_disable_tdp(void)
+{
+       tdp_enabled = false;
+}
+EXPORT_SYMBOL_GPL(kvm_disable_tdp);
+
 static void free_mmu_pages(struct kvm_vcpu *vcpu)
 {
        struct kvm_mmu_page *sp;
index b756e876dce391b222c6e4ec84c7dd6447e738de..e2ee264740c7dbb6ea6717b3aa7617c393fd4831 100644 (file)
@@ -453,7 +453,8 @@ static __init int svm_hardware_setup(void)
        if (npt_enabled) {
                printk(KERN_INFO "kvm: Nested Paging enabled\n");
                kvm_enable_tdp();
-       }
+       } else
+               kvm_disable_tdp();
 
        return 0;
 
@@ -1007,10 +1008,13 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
        struct kvm *kvm = svm->vcpu.kvm;
        u64 fault_address;
        u32 error_code;
+       bool event_injection = false;
 
        if (!irqchip_in_kernel(kvm) &&
-               is_external_interrupt(exit_int_info))
+           is_external_interrupt(exit_int_info)) {
+               event_injection = true;
                push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
+       }
 
        fault_address  = svm->vmcb->control.exit_info_2;
        error_code = svm->vmcb->control.exit_info_1;
@@ -1024,6 +1028,8 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
                            (u32)fault_address, (u32)(fault_address >> 32),
                            handler);
 
+       if (event_injection)
+               kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
        return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
 }
 
index 0cac63701719c9dd265cb7ca2078c97379e9f235..2a69773e3b26235f3261aea232ef5fe17411d6cb 100644 (file)
@@ -2298,6 +2298,8 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                cr2 = vmcs_readl(EXIT_QUALIFICATION);
                KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
                            (u32)((u64)cr2 >> 32), handler);
+               if (vect_info & VECTORING_INFO_VALID_MASK)
+                       kvm_mmu_unprotect_page_virt(vcpu, cr2);
                return kvm_mmu_page_fault(vcpu, cr2, error_code);
        }
 
@@ -3116,15 +3118,6 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
                return ERR_PTR(-ENOMEM);
 
        allocate_vpid(vmx);
-       if (id == 0 && vm_need_ept()) {
-               kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
-                       VMX_EPT_WRITABLE_MASK |
-                       VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
-               kvm_mmu_set_mask_ptes(0ull, VMX_EPT_FAKE_ACCESSED_MASK,
-                               VMX_EPT_FAKE_DIRTY_MASK, 0ull,
-                               VMX_EPT_EXECUTABLE_MASK);
-               kvm_enable_tdp();
-       }
 
        err = kvm_vcpu_init(&vmx->vcpu, kvm, id);
        if (err)
@@ -3303,8 +3296,17 @@ static int __init vmx_init(void)
        vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP);
        vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP);
 
-       if (cpu_has_vmx_ept())
+       if (vm_need_ept()) {
                bypass_guest_pf = 0;
+               kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
+                       VMX_EPT_WRITABLE_MASK |
+                       VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
+               kvm_mmu_set_mask_ptes(0ull, VMX_EPT_FAKE_ACCESSED_MASK,
+                               VMX_EPT_FAKE_DIRTY_MASK, 0ull,
+                               VMX_EPT_EXECUTABLE_MASK);
+               kvm_enable_tdp();
+       } else
+               kvm_disable_tdp();
 
        if (bypass_guest_pf)
                kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull);
index 9f1cdb011cfff3d93b4cf8fe1f64349768183742..5916191420c714d7e9b43ca9b1bf995672f88eab 100644 (file)
@@ -3184,6 +3184,10 @@ static void seg_desct_to_kvm_desct(struct desc_struct *seg_desc, u16 selector,
        kvm_desct->base |= seg_desc->base2 << 24;
        kvm_desct->limit = seg_desc->limit0;
        kvm_desct->limit |= seg_desc->limit << 16;
+       if (seg_desc->g) {
+               kvm_desct->limit <<= 12;
+               kvm_desct->limit |= 0xfff;
+       }
        kvm_desct->selector = selector;
        kvm_desct->type = seg_desc->type;
        kvm_desct->present = seg_desc->p;
@@ -3223,6 +3227,7 @@ static void get_segment_descritptor_dtable(struct kvm_vcpu *vcpu,
 static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
                                         struct desc_struct *seg_desc)
 {
+       gpa_t gpa;
        struct descriptor_table dtable;
        u16 index = selector >> 3;
 
@@ -3232,13 +3237,16 @@ static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
                kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc);
                return 1;
        }
-       return kvm_read_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8);
+       gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, dtable.base);
+       gpa += index * 8;
+       return kvm_read_guest(vcpu->kvm, gpa, seg_desc, 8);
 }
 
 /* allowed just for 8 bytes segments */
 static int save_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
                                         struct desc_struct *seg_desc)
 {
+       gpa_t gpa;
        struct descriptor_table dtable;
        u16 index = selector >> 3;
 
@@ -3246,7 +3254,9 @@ static int save_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
 
        if (dtable.limit < index * 8 + 7)
                return 1;
-       return kvm_write_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8);
+       gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, dtable.base);
+       gpa += index * 8;
+       return kvm_write_guest(vcpu->kvm, gpa, seg_desc, 8);
 }
 
 static u32 get_tss_base_addr(struct kvm_vcpu *vcpu,
@@ -3258,55 +3268,7 @@ static u32 get_tss_base_addr(struct kvm_vcpu *vcpu,
        base_addr |= (seg_desc->base1 << 16);
        base_addr |= (seg_desc->base2 << 24);
 
-       return base_addr;
-}
-
-static int load_tss_segment32(struct kvm_vcpu *vcpu,
-                             struct desc_struct *seg_desc,
-                             struct tss_segment_32 *tss)
-{
-       u32 base_addr;
-
-       base_addr = get_tss_base_addr(vcpu, seg_desc);
-
-       return kvm_read_guest(vcpu->kvm, base_addr, tss,
-                             sizeof(struct tss_segment_32));
-}
-
-static int save_tss_segment32(struct kvm_vcpu *vcpu,
-                             struct desc_struct *seg_desc,
-                             struct tss_segment_32 *tss)
-{
-       u32 base_addr;
-
-       base_addr = get_tss_base_addr(vcpu, seg_desc);
-
-       return kvm_write_guest(vcpu->kvm, base_addr, tss,
-                              sizeof(struct tss_segment_32));
-}
-
-static int load_tss_segment16(struct kvm_vcpu *vcpu,
-                             struct desc_struct *seg_desc,
-                             struct tss_segment_16 *tss)
-{
-       u32 base_addr;
-
-       base_addr = get_tss_base_addr(vcpu, seg_desc);
-
-       return kvm_read_guest(vcpu->kvm, base_addr, tss,
-                             sizeof(struct tss_segment_16));
-}
-
-static int save_tss_segment16(struct kvm_vcpu *vcpu,
-                             struct desc_struct *seg_desc,
-                             struct tss_segment_16 *tss)
-{
-       u32 base_addr;
-
-       base_addr = get_tss_base_addr(vcpu, seg_desc);
-
-       return kvm_write_guest(vcpu->kvm, base_addr, tss,
-                              sizeof(struct tss_segment_16));
+       return vcpu->arch.mmu.gva_to_gpa(vcpu, base_addr);
 }
 
 static u16 get_segment_selector(struct kvm_vcpu *vcpu, int seg)
@@ -3466,20 +3428,26 @@ static int load_state_from_tss16(struct kvm_vcpu *vcpu,
 }
 
 static int kvm_task_switch_16(struct kvm_vcpu *vcpu, u16 tss_selector,
-                      struct desc_struct *cseg_desc,
+                      u32 old_tss_base,
                       struct desc_struct *nseg_desc)
 {
        struct tss_segment_16 tss_segment_16;
        int ret = 0;
 
-       if (load_tss_segment16(vcpu, cseg_desc, &tss_segment_16))
+       if (kvm_read_guest(vcpu->kvm, old_tss_base, &tss_segment_16,
+                          sizeof tss_segment_16))
                goto out;
 
        save_state_to_tss16(vcpu, &tss_segment_16);
-       save_tss_segment16(vcpu, cseg_desc, &tss_segment_16);
 
-       if (load_tss_segment16(vcpu, nseg_desc, &tss_segment_16))
+       if (kvm_write_guest(vcpu->kvm, old_tss_base, &tss_segment_16,
+                           sizeof tss_segment_16))
                goto out;
+
+       if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
+                          &tss_segment_16, sizeof tss_segment_16))
+               goto out;
+
        if (load_state_from_tss16(vcpu, &tss_segment_16))
                goto out;
 
@@ -3489,20 +3457,26 @@ out:
 }
 
 static int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector,
-                      struct desc_struct *cseg_desc,
+                      u32 old_tss_base,
                       struct desc_struct *nseg_desc)
 {
        struct tss_segment_32 tss_segment_32;
        int ret = 0;
 
-       if (load_tss_segment32(vcpu, cseg_desc, &tss_segment_32))
+       if (kvm_read_guest(vcpu->kvm, old_tss_base, &tss_segment_32,
+                          sizeof tss_segment_32))
                goto out;
 
        save_state_to_tss32(vcpu, &tss_segment_32);
-       save_tss_segment32(vcpu, cseg_desc, &tss_segment_32);
 
-       if (load_tss_segment32(vcpu, nseg_desc, &tss_segment_32))
+       if (kvm_write_guest(vcpu->kvm, old_tss_base, &tss_segment_32,
+                           sizeof tss_segment_32))
+               goto out;
+
+       if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
+                          &tss_segment_32, sizeof tss_segment_32))
                goto out;
+
        if (load_state_from_tss32(vcpu, &tss_segment_32))
                goto out;
 
@@ -3517,16 +3491,20 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
        struct desc_struct cseg_desc;
        struct desc_struct nseg_desc;
        int ret = 0;
+       u32 old_tss_base = get_segment_base(vcpu, VCPU_SREG_TR);
+       u16 old_tss_sel = get_segment_selector(vcpu, VCPU_SREG_TR);
 
-       kvm_get_segment(vcpu, &tr_seg, VCPU_SREG_TR);
+       old_tss_base = vcpu->arch.mmu.gva_to_gpa(vcpu, old_tss_base);
 
+       /* FIXME: Handle errors. Failure to read either TSS or their
+        * descriptors should generate a pagefault.
+        */
        if (load_guest_segment_descriptor(vcpu, tss_selector, &nseg_desc))
                goto out;
 
-       if (load_guest_segment_descriptor(vcpu, tr_seg.selector, &cseg_desc))
+       if (load_guest_segment_descriptor(vcpu, old_tss_sel, &cseg_desc))
                goto out;
 
-
        if (reason != TASK_SWITCH_IRET) {
                int cpl;
 
@@ -3544,8 +3522,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
 
        if (reason == TASK_SWITCH_IRET || reason == TASK_SWITCH_JMP) {
                cseg_desc.type &= ~(1 << 1); //clear the B flag
-               save_guest_segment_descriptor(vcpu, tr_seg.selector,
-                                             &cseg_desc);
+               save_guest_segment_descriptor(vcpu, old_tss_sel, &cseg_desc);
        }
 
        if (reason == TASK_SWITCH_IRET) {
@@ -3557,10 +3534,10 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
        kvm_x86_ops->cache_regs(vcpu);
 
        if (nseg_desc.type & 8)
-               ret = kvm_task_switch_32(vcpu, tss_selector, &cseg_desc,
+               ret = kvm_task_switch_32(vcpu, tss_selector, old_tss_base,
                                         &nseg_desc);
        else
-               ret = kvm_task_switch_16(vcpu, tss_selector, &cseg_desc,
+               ret = kvm_task_switch_16(vcpu, tss_selector, old_tss_base,
                                         &nseg_desc);
 
        if (reason == TASK_SWITCH_CALL || reason == TASK_SWITCH_GATE) {
index 0313a5eec4125620016299cca616400821f7bd41..d9249a882aa5b0c2204fc16724e0848e8184d543 100644 (file)
@@ -1014,6 +1014,9 @@ __init void lguest_init(void)
        init_pg_tables_start = __pa(pg0);
        init_pg_tables_end = __pa(pg0);
 
+       /* As described in head_32.S, we map the first 128M of memory. */
+       max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT;
+
        /* Load the %fs segment register (the per-cpu segment register) with
         * the normal data segment to get through booting. */
        asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory");
index 1fbb844c3d7afdc0b35723d96ba6578c09584de1..2977ea37791f3ca3ec53efb8a2984fc17d866d30 100644 (file)
@@ -1,6 +1,7 @@
 obj-y  :=  init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \
            pat.o pgtable.o
 
+obj-$(CONFIG_HAVE_GET_USER_PAGES_FAST) += gup.o
 obj-$(CONFIG_X86_32)           += pgtable_32.o
 
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
index 5dfef9fa061a653669c79bdd69382169dc68561c..62fa440678d88268ba9456150eb023c3b7f735d7 100644 (file)
@@ -42,7 +42,6 @@
 
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
-static bootmem_data_t node0_bdata;
 
 /*
  * numa interface - we expect the numa architecture specific code to have
@@ -385,7 +384,7 @@ void __init initmem_init(unsigned long start_pfn,
        for_each_online_node(nid)
                memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
-       NODE_DATA(0)->bdata = &node0_bdata;
+       NODE_DATA(0)->bdata = &bootmem_node_data[0];
        setup_bootmem_allocator();
 }
 
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
new file mode 100644 (file)
index 0000000..007bb06
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Lockless get_user_pages_fast for x86
+ *
+ * Copyright (C) 2008 Nick Piggin
+ * Copyright (C) 2008 Novell Inc.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/vmstat.h>
+#include <linux/highmem.h>
+
+#include <asm/pgtable.h>
+
+static inline pte_t gup_get_pte(pte_t *ptep)
+{
+#ifndef CONFIG_X86_PAE
+       return *ptep;
+#else
+       /*
+        * With get_user_pages_fast, we walk down the pagetables without taking
+        * any locks.  For this we would like to load the pointers atoimcally,
+        * but that is not possible (without expensive cmpxchg8b) on PAE.  What
+        * we do have is the guarantee that a pte will only either go from not
+        * present to present, or present to not present or both -- it will not
+        * switch to a completely different present page without a TLB flush in
+        * between; something that we are blocking by holding interrupts off.
+        *
+        * Setting ptes from not present to present goes:
+        * ptep->pte_high = h;
+        * smp_wmb();
+        * ptep->pte_low = l;
+        *
+        * And present to not present goes:
+        * ptep->pte_low = 0;
+        * smp_wmb();
+        * ptep->pte_high = 0;
+        *
+        * We must ensure here that the load of pte_low sees l iff pte_high
+        * sees h. We load pte_high *after* loading pte_low, which ensures we
+        * don't see an older value of pte_high.  *Then* we recheck pte_low,
+        * which ensures that we haven't picked up a changed pte high. We might
+        * have got rubbish values from pte_low and pte_high, but we are
+        * guaranteed that pte_low will not have the present bit set *unless*
+        * it is 'l'. And get_user_pages_fast only operates on present ptes, so
+        * we're safe.
+        *
+        * gup_get_pte should not be used or copied outside gup.c without being
+        * very careful -- it does not atomically load the pte or anything that
+        * is likely to be useful for you.
+        */
+       pte_t pte;
+
+retry:
+       pte.pte_low = ptep->pte_low;
+       smp_rmb();
+       pte.pte_high = ptep->pte_high;
+       smp_rmb();
+       if (unlikely(pte.pte_low != ptep->pte_low))
+               goto retry;
+
+       return pte;
+#endif
+}
+
+/*
+ * The performance critical leaf functions are made noinline otherwise gcc
+ * inlines everything into a single function which results in too much
+ * register pressure.
+ */
+static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
+               unsigned long end, int write, struct page **pages, int *nr)
+{
+       unsigned long mask;
+       pte_t *ptep;
+
+       mask = _PAGE_PRESENT|_PAGE_USER;
+       if (write)
+               mask |= _PAGE_RW;
+
+       ptep = pte_offset_map(&pmd, addr);
+       do {
+               pte_t pte = gup_get_pte(ptep);
+               struct page *page;
+
+               if ((pte_val(pte) & (mask | _PAGE_SPECIAL)) != mask) {
+                       pte_unmap(ptep);
+                       return 0;
+               }
+               VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
+               page = pte_page(pte);
+               get_page(page);
+               pages[*nr] = page;
+               (*nr)++;
+
+       } while (ptep++, addr += PAGE_SIZE, addr != end);
+       pte_unmap(ptep - 1);
+
+       return 1;
+}
+
+static inline void get_head_page_multiple(struct page *page, int nr)
+{
+       VM_BUG_ON(page != compound_head(page));
+       VM_BUG_ON(page_count(page) == 0);
+       atomic_add(nr, &page->_count);
+}
+
+static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
+               unsigned long end, int write, struct page **pages, int *nr)
+{
+       unsigned long mask;
+       pte_t pte = *(pte_t *)&pmd;
+       struct page *head, *page;
+       int refs;
+
+       mask = _PAGE_PRESENT|_PAGE_USER;
+       if (write)
+               mask |= _PAGE_RW;
+       if ((pte_val(pte) & mask) != mask)
+               return 0;
+       /* hugepages are never "special" */
+       VM_BUG_ON(pte_val(pte) & _PAGE_SPECIAL);
+       VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
+
+       refs = 0;
+       head = pte_page(pte);
+       page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
+       do {
+               VM_BUG_ON(compound_head(page) != head);
+               pages[*nr] = page;
+               (*nr)++;
+               page++;
+               refs++;
+       } while (addr += PAGE_SIZE, addr != end);
+       get_head_page_multiple(head, refs);
+
+       return 1;
+}
+
+static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
+               int write, struct page **pages, int *nr)
+{
+       unsigned long next;
+       pmd_t *pmdp;
+
+       pmdp = pmd_offset(&pud, addr);
+       do {
+               pmd_t pmd = *pmdp;
+
+               next = pmd_addr_end(addr, end);
+               if (pmd_none(pmd))
+                       return 0;
+               if (unlikely(pmd_large(pmd))) {
+                       if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))
+                               return 0;
+               } else {
+                       if (!gup_pte_range(pmd, addr, next, write, pages, nr))
+                               return 0;
+               }
+       } while (pmdp++, addr = next, addr != end);
+
+       return 1;
+}
+
+static noinline int gup_huge_pud(pud_t pud, unsigned long addr,
+               unsigned long end, int write, struct page **pages, int *nr)
+{
+       unsigned long mask;
+       pte_t pte = *(pte_t *)&pud;
+       struct page *head, *page;
+       int refs;
+
+       mask = _PAGE_PRESENT|_PAGE_USER;
+       if (write)
+               mask |= _PAGE_RW;
+       if ((pte_val(pte) & mask) != mask)
+               return 0;
+       /* hugepages are never "special" */
+       VM_BUG_ON(pte_val(pte) & _PAGE_SPECIAL);
+       VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
+
+       refs = 0;
+       head = pte_page(pte);
+       page = head + ((addr & ~PUD_MASK) >> PAGE_SHIFT);
+       do {
+               VM_BUG_ON(compound_head(page) != head);
+               pages[*nr] = page;
+               (*nr)++;
+               page++;
+               refs++;
+       } while (addr += PAGE_SIZE, addr != end);
+       get_head_page_multiple(head, refs);
+
+       return 1;
+}
+
+static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
+                       int write, struct page **pages, int *nr)
+{
+       unsigned long next;
+       pud_t *pudp;
+
+       pudp = pud_offset(&pgd, addr);
+       do {
+               pud_t pud = *pudp;
+
+               next = pud_addr_end(addr, end);
+               if (pud_none(pud))
+                       return 0;
+               if (unlikely(pud_large(pud))) {
+                       if (!gup_huge_pud(pud, addr, next, write, pages, nr))
+                               return 0;
+               } else {
+                       if (!gup_pmd_range(pud, addr, next, write, pages, nr))
+                               return 0;
+               }
+       } while (pudp++, addr = next, addr != end);
+
+       return 1;
+}
+
+int get_user_pages_fast(unsigned long start, int nr_pages, int write,
+                       struct page **pages)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long addr, len, end;
+       unsigned long next;
+       pgd_t *pgdp;
+       int nr = 0;
+
+       start &= PAGE_MASK;
+       addr = start;
+       len = (unsigned long) nr_pages << PAGE_SHIFT;
+       end = start + len;
+       if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
+                                       start, len)))
+               goto slow_irqon;
+
+       /*
+        * XXX: batch / limit 'nr', to avoid large irq off latency
+        * needs some instrumenting to determine the common sizes used by
+        * important workloads (eg. DB2), and whether limiting the batch size
+        * will decrease performance.
+        *
+        * It seems like we're in the clear for the moment. Direct-IO is
+        * the main guy that batches up lots of get_user_pages, and even
+        * they are limited to 64-at-a-time which is not so many.
+        */
+       /*
+        * This doesn't prevent pagetable teardown, but does prevent
+        * the pagetables and pages from being freed on x86.
+        *
+        * So long as we atomically load page table pointers versus teardown
+        * (which we do on x86, with the above PAE exception), we can follow the
+        * address down to the the page and take a ref on it.
+        */
+       local_irq_disable();
+       pgdp = pgd_offset(mm, addr);
+       do {
+               pgd_t pgd = *pgdp;
+
+               next = pgd_addr_end(addr, end);
+               if (pgd_none(pgd))
+                       goto slow;
+               if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
+                       goto slow;
+       } while (pgdp++, addr = next, addr != end);
+       local_irq_enable();
+
+       VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
+       return nr;
+
+       {
+               int ret;
+
+slow:
+               local_irq_enable();
+slow_irqon:
+               /* Try to get the remaining pages with get_user_pages */
+               start += nr << PAGE_SHIFT;
+               pages += nr;
+
+               down_read(&mm->mmap_sem);
+               ret = get_user_pages(current, mm, start,
+                       (end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
+               up_read(&mm->mmap_sem);
+
+               /* Have to be a bit careful with return values */
+               if (nr > 0) {
+                       if (ret < 0)
+                               ret = nr;
+                       else
+                               ret += nr;
+               }
+
+               return ret;
+       }
+}
index 0b3d567e686df15c1b042deb388091ab78a6ae25..8f307d914c2ec860c3b9093796362e9c4719ab41 100644 (file)
@@ -124,7 +124,8 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
        return 1;
 }
 
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+                       unsigned long addr, unsigned long sz)
 {
        pgd_t *pgd;
        pud_t *pud;
@@ -133,9 +134,14 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        pgd = pgd_offset(mm, addr);
        pud = pud_alloc(mm, pgd, addr);
        if (pud) {
-               if (pud_none(*pud))
-                       huge_pmd_share(mm, addr, pud);
-               pte = (pte_t *) pmd_alloc(mm, pud, addr);
+               if (sz == PUD_SIZE) {
+                       pte = (pte_t *)pud;
+               } else {
+                       BUG_ON(sz != PMD_SIZE);
+                       if (pud_none(*pud))
+                               huge_pmd_share(mm, addr, pud);
+                       pte = (pte_t *) pmd_alloc(mm, pud, addr);
+               }
        }
        BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
 
@@ -151,8 +157,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
        pgd = pgd_offset(mm, addr);
        if (pgd_present(*pgd)) {
                pud = pud_offset(pgd, addr);
-               if (pud_present(*pud))
+               if (pud_present(*pud)) {
+                       if (pud_large(*pud))
+                               return (pte_t *)pud;
                        pmd = pmd_offset(pud, addr);
+               }
        }
        return (pte_t *) pmd;
 }
@@ -188,6 +197,11 @@ int pmd_huge(pmd_t pmd)
        return 0;
 }
 
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
+
 struct page *
 follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                pmd_t *pmd, int write)
@@ -208,6 +222,11 @@ int pmd_huge(pmd_t pmd)
        return !!(pmd_val(pmd) & _PAGE_PSE);
 }
 
+int pud_huge(pud_t pud)
+{
+       return !!(pud_val(pud) & _PAGE_PSE);
+}
+
 struct page *
 follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                pmd_t *pmd, int write)
@@ -216,9 +235,22 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
 
        page = pte_page(*(pte_t *)pmd);
        if (page)
-               page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT);
+               page += ((address & ~PMD_MASK) >> PAGE_SHIFT);
+       return page;
+}
+
+struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+               pud_t *pud, int write)
+{
+       struct page *page;
+
+       page = pte_page(*(pte_t *)pud);
+       if (page)
+               page += ((address & ~PUD_MASK) >> PAGE_SHIFT);
        return page;
 }
+
 #endif
 
 /* x86_64 also uses this file */
@@ -228,6 +260,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
                unsigned long addr, unsigned long len,
                unsigned long pgoff, unsigned long flags)
 {
+       struct hstate *h = hstate_file(file);
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        unsigned long start_addr;
@@ -240,7 +273,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
        }
 
 full_search:
-       addr = ALIGN(start_addr, HPAGE_SIZE);
+       addr = ALIGN(start_addr, huge_page_size(h));
 
        for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
                /* At this point:  (!vma || addr < vma->vm_end). */
@@ -262,7 +295,7 @@ full_search:
                }
                if (addr + mm->cached_hole_size < vma->vm_start)
                        mm->cached_hole_size = vma->vm_start - addr;
-               addr = ALIGN(vma->vm_end, HPAGE_SIZE);
+               addr = ALIGN(vma->vm_end, huge_page_size(h));
        }
 }
 
@@ -270,6 +303,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
                unsigned long addr0, unsigned long len,
                unsigned long pgoff, unsigned long flags)
 {
+       struct hstate *h = hstate_file(file);
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma, *prev_vma;
        unsigned long base = mm->mmap_base, addr = addr0;
@@ -290,7 +324,7 @@ try_again:
                goto fail;
 
        /* either no address requested or cant fit in requested address hole */
-       addr = (mm->free_area_cache - len) & HPAGE_MASK;
+       addr = (mm->free_area_cache - len) & huge_page_mask(h);
        do {
                /*
                 * Lookup failure means no vma is above this address,
@@ -321,7 +355,7 @@ try_again:
                        largest_hole = vma->vm_start - addr;
 
                /* try just below the current vma->vm_start */
-               addr = (vma->vm_start - len) & HPAGE_MASK;
+               addr = (vma->vm_start - len) & huge_page_mask(h);
        } while (len <= vma->vm_start);
 
 fail:
@@ -359,22 +393,23 @@ unsigned long
 hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                unsigned long len, unsigned long pgoff, unsigned long flags)
 {
+       struct hstate *h = hstate_file(file);
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
 
-       if (len & ~HPAGE_MASK)
+       if (len & ~huge_page_mask(h))
                return -EINVAL;
        if (len > TASK_SIZE)
                return -ENOMEM;
 
        if (flags & MAP_FIXED) {
-               if (prepare_hugepage_range(addr, len))
+               if (prepare_hugepage_range(file, addr, len))
                        return -EINVAL;
                return addr;
        }
 
        if (addr) {
-               addr = ALIGN(addr, HPAGE_SIZE);
+               addr = ALIGN(addr, huge_page_size(h));
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
                    (!vma || addr + len <= vma->vm_start))
@@ -390,3 +425,20 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
 
 #endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/
 
+#ifdef CONFIG_X86_64
+static __init int setup_hugepagesz(char *opt)
+{
+       unsigned long ps = memparse(opt, &opt);
+       if (ps == PMD_SIZE) {
+               hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
+       } else if (ps == PUD_SIZE && cpu_has_gbpages) {
+               hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+       } else {
+               printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n",
+                       ps >> 20);
+               return 0;
+       }
+       return 1;
+}
+__setup("hugepagesz=", setup_hugepagesz);
+#endif
index ec37121f67092b8c996b9b99e104d17e642dc650..129618ca0ea274a980ba414b30e604e67c3217fd 100644 (file)
@@ -86,43 +86,6 @@ early_param("gbpages", parse_direct_gbpages_on);
  * around without checking the pgd every time.
  */
 
-void show_mem(void)
-{
-       long i, total = 0, reserved = 0;
-       long shared = 0, cached = 0;
-       struct page *page;
-       pg_data_t *pgdat;
-
-       printk(KERN_INFO "Mem-info:\n");
-       show_free_areas();
-       for_each_online_pgdat(pgdat) {
-               for (i = 0; i < pgdat->node_spanned_pages; ++i) {
-                       /*
-                        * This loop can take a while with 256 GB and
-                        * 4k pages so defer the NMI watchdog:
-                        */
-                       if (unlikely(i % MAX_ORDER_NR_PAGES == 0))
-                               touch_nmi_watchdog();
-
-                       if (!pfn_valid(pgdat->node_start_pfn + i))
-                               continue;
-
-                       page = pfn_to_page(pgdat->node_start_pfn + i);
-                       total++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
-               }
-       }
-       printk(KERN_INFO "%lu pages of RAM\n",          total);
-       printk(KERN_INFO "%lu reserved pages\n",        reserved);
-       printk(KERN_INFO "%lu pages shared\n",          shared);
-       printk(KERN_INFO "%lu pages swap cached\n",     cached);
-}
-
 int after_bootmem;
 
 static __init void *spp_getpage(void)
index 24c1d3c30186c893c400eff0942b857207a833fa..016f335bbeea34035ed329450d48697cca85de30 100644 (file)
@@ -330,6 +330,14 @@ static void __iomem *ioremap_default(resource_size_t phys_addr,
        return (void __iomem *)ret;
 }
 
+void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
+                               unsigned long prot_val)
+{
+       return __ioremap_caller(phys_addr, size, (prot_val & _PAGE_CACHE_MASK),
+                               __builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_prot);
+
 /**
  * iounmap - Free a IO remapping
  * @addr: virtual address from ioremap_*
index 9782f42dd319801ebe870f5b1d75cc8480df0143..a4dd793d6003e6074e12d40441bd2dcb524297ee 100644 (file)
@@ -23,8 +23,6 @@
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 
-static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
-
 struct memnode memnode;
 
 s16 apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
@@ -198,7 +196,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
                nodedata_phys + pgdat_size - 1);
 
        memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
-       NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid];
+       NODE_DATA(nodeid)->bdata = &bootmem_node_data[nodeid];
        NODE_DATA(nodeid)->node_start_pfn = start_pfn;
        NODE_DATA(nodeid)->node_spanned_pages = last_pfn - start_pfn;
 
index b4becbf8c570cfae3d140cbceef0cb74ac7fa2a3..cab0abbd1ebe6c42a9adfb46306220a893f86541 100644 (file)
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
-void show_mem(void)
-{
-       int total = 0, reserved = 0;
-       int shared = 0, cached = 0;
-       int highmem = 0;
-       struct page *page;
-       pg_data_t *pgdat;
-       unsigned long i;
-       unsigned long flags;
-
-       printk(KERN_INFO "Mem-info:\n");
-       show_free_areas();
-       for_each_online_pgdat(pgdat) {
-               pgdat_resize_lock(pgdat, &flags);
-               for (i = 0; i < pgdat->node_spanned_pages; ++i) {
-                       if (unlikely(i % MAX_ORDER_NR_PAGES == 0))
-                               touch_nmi_watchdog();
-                       page = pgdat_page_nr(pgdat, i);
-                       total++;
-                       if (PageHighMem(page))
-                               highmem++;
-                       if (PageReserved(page))
-                               reserved++;
-                       else if (PageSwapCache(page))
-                               cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
-               }
-               pgdat_resize_unlock(pgdat, &flags);
-       }
-       printk(KERN_INFO "%d pages of RAM\n", total);
-       printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
-       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 "%lu pages dirty\n", global_page_state(NR_FILE_DIRTY));
-       printk(KERN_INFO "%lu pages writeback\n",
-                                       global_page_state(NR_WRITEBACK));
-       printk(KERN_INFO "%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
-       printk(KERN_INFO "%lu pages slab\n",
-               global_page_state(NR_SLAB_RECLAIMABLE) +
-               global_page_state(NR_SLAB_UNRECLAIMABLE));
-       printk(KERN_INFO "%lu pages pagetables\n",
-                                       global_page_state(NR_PAGETABLE));
-}
-
 /*
  * Associate a virtual page frame with a given physical page frame 
  * and protection flags for that frame.
index 7f3329b55d2e3b76eb60886844d7ee846b7a0c60..3f90289410e6fbfc81fa1b350f7d6fdce4ecd18c 100644 (file)
@@ -369,20 +369,34 @@ static int __init ppro_init(char **cpu_type)
 {
        __u8 cpu_model = boot_cpu_data.x86_model;
 
-       if (cpu_model == 14)
+       switch (cpu_model) {
+       case 0 ... 2:
+               *cpu_type = "i386/ppro";
+               break;
+       case 3 ... 5:
+               *cpu_type = "i386/pii";
+               break;
+       case 6 ... 8:
+               *cpu_type = "i386/piii";
+               break;
+       case 9:
+               *cpu_type = "i386/p6_mobile";
+               break;
+       case 10 ... 13:
+               *cpu_type = "i386/p6";
+               break;
+       case 14:
                *cpu_type = "i386/core";
-       else if (cpu_model == 15 || cpu_model == 23)
+               break;
+       case 15: case 23:
+               *cpu_type = "i386/core_2";
+               break;
+       case 26:
                *cpu_type = "i386/core_2";
-       else if (cpu_model > 0xd)
+               break;
+       default:
+               /* Unknown */
                return 0;
-       else if (cpu_model == 9) {
-               *cpu_type = "i386/p6_mobile";
-       } else if (cpu_model > 5) {
-               *cpu_type = "i386/piii";
-       } else if (cpu_model > 2) {
-               *cpu_type = "i386/pii";
-       } else {
-               *cpu_type = "i386/ppro";
        }
 
        model = &op_ppro_spec;
index ff3a6a33634231514c945a66f15328a6a8ce534a..4bdaa590375dd302bac474145f6614924a7a6387 100644 (file)
@@ -23,7 +23,8 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
                pci_read_config_byte(d, reg++, &busno);
                pci_read_config_byte(d, reg++, &suba);
                pci_read_config_byte(d, reg++, &subb);
-               DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
+               dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno,
+                       suba, subb);
                if (busno)
                        pci_scan_bus_with_sysdata(busno);       /* Bus A */
                if (suba < subb)
index 2aafb67dc5f1df254de17ff64a1523283c341f32..5807d1bc73f74639c81cf4dec9255ec26e076c73 100644 (file)
@@ -128,10 +128,8 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
                                pr = pci_find_parent_resource(dev, r);
                                if (!r->start || !pr ||
                                    request_resource(pr, r) < 0) {
-                                       printk(KERN_ERR "PCI: Cannot allocate "
-                                               "resource region %d "
-                                               "of bridge %s\n",
-                                               idx, pci_name(dev));
+                                       dev_err(&dev->dev, "BAR %d: can't "
+                                               "allocate resource\n", idx);
                                        /*
                                         * Something is wrong with the region.
                                         * Invalidate the resource to prevent
@@ -166,15 +164,15 @@ static void __init pcibios_allocate_resources(int pass)
                        else
                                disabled = !(command & PCI_COMMAND_MEMORY);
                        if (pass == disabled) {
-                               DBG("PCI: Resource %08lx-%08lx "
-                                   "(f=%lx, d=%d, p=%d)\n",
-                                   r->start, r->end, r->flags, disabled, pass);
+                               dev_dbg(&dev->dev, "resource %#08llx-%#08llx "
+                                       "(f=%lx, d=%d, p=%d)\n",
+                                       (unsigned long long) r->start,
+                                       (unsigned long long) r->end,
+                                       r->flags, disabled, pass);
                                pr = pci_find_parent_resource(dev, r);
                                if (!pr || request_resource(pr, r) < 0) {
-                                       printk(KERN_ERR "PCI: Cannot allocate "
-                                               "resource region %d "
-                                               "of device %s\n",
-                                               idx, pci_name(dev));
+                                       dev_err(&dev->dev, "BAR %d: can't "
+                                               "allocate resource\n", idx);
                                        /* We'll assign a new address later */
                                        r->end -= r->start;
                                        r->start = 0;
@@ -187,8 +185,7 @@ static void __init pcibios_allocate_resources(int pass)
                                /* Turn the ROM off, leave the resource region,
                                 * but keep it unregistered. */
                                u32 reg;
-                               DBG("PCI: Switching off ROM of %s\n",
-                                       pci_name(dev));
+                               dev_dbg(&dev->dev, "disabling ROM\n");
                                r->flags &= ~IORESOURCE_ROM_ENABLE;
                                pci_read_config_dword(dev,
                                                dev->rom_base_reg, &reg);
@@ -257,8 +254,7 @@ void pcibios_set_master(struct pci_dev *dev)
                lat = pcibios_max_latency;
        else
                return;
-       printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n",
-               pci_name(dev), lat);
+       dev_printk(KERN_DEBUG, &dev->dev, "setting latency timer to %d\n", lat);
        pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
 
@@ -280,6 +276,7 @@ static void pci_track_mmap_page_range(struct vm_area_struct *vma)
 static struct vm_operations_struct pci_mmap_ops = {
        .open  = pci_track_mmap_page_range,
        .close = pci_unmap_page_range,
+       .access = generic_access_phys,
 };
 
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
index 6a06a2eb05973c5e2f129de7a9d1bbcdefc6564a..fec0123b33a9dde965e42caf9ae1e3ab23cb118c 100644 (file)
@@ -436,7 +436,7 @@ static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
        WARN_ON_ONCE(pirq >= 9);
        if (pirq > 8) {
-               printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
+               dev_info(&dev->dev, "VLSI router PIRQ escape (%d)\n", pirq);
                return 0;
        }
        return read_config_nybble(router, 0x74, pirq-1);
@@ -446,7 +446,7 @@ static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
 {
        WARN_ON_ONCE(pirq >= 9);
        if (pirq > 8) {
-               printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
+               dev_info(&dev->dev, "VLSI router PIRQ escape (%d)\n", pirq);
                return 0;
        }
        write_config_nybble(router, 0x74, pirq-1, irq);
@@ -492,15 +492,17 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq
        irq = 0;
        if (pirq <= 4)
                irq = read_config_nybble(router, 0x56, pirq - 1);
-       printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
-               dev->vendor, dev->device, pirq, irq);
+       dev_info(&dev->dev,
+                "AMD756: dev [%04x/%04x], router PIRQ %d get IRQ %d\n",
+                dev->vendor, dev->device, pirq, irq);
        return irq;
 }
 
 static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-       printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n",
-               dev->vendor, dev->device, pirq, irq);
+       dev_info(&dev->dev,
+                "AMD756: dev [%04x/%04x], router PIRQ %d set IRQ %d\n",
+                dev->vendor, dev->device, pirq, irq);
        if (pirq <= 4)
                write_config_nybble(router, 0x56, pirq - 1, irq);
        return 1;
@@ -730,7 +732,6 @@ static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router,
        switch (device) {
        case PCI_DEVICE_ID_AL_M1533:
        case PCI_DEVICE_ID_AL_M1563:
-               printk(KERN_DEBUG "PCI: Using ALI IRQ Router\n");
                r->name = "ALI";
                r->get = pirq_ali_get;
                r->set = pirq_ali_set;
@@ -840,11 +841,9 @@ static void __init pirq_find_router(struct irq_router *r)
                        h->probe(r, pirq_router_dev, pirq_router_dev->device))
                        break;
        }
-       printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
-               pirq_router.name,
-               pirq_router_dev->vendor,
-               pirq_router_dev->device,
-               pci_name(pirq_router_dev));
+       dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x/%04x]\n",
+                pirq_router.name,
+                pirq_router_dev->vendor, pirq_router_dev->device);
 
        /* The device remains referenced for the kernel lifetime */
 }
@@ -877,7 +876,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
        /* Find IRQ pin */
        pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
        if (!pin) {
-               DBG(KERN_DEBUG " -> no interrupt pin\n");
+               dev_dbg(&dev->dev, "no interrupt pin\n");
                return 0;
        }
        pin = pin - 1;
@@ -887,20 +886,20 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
        if (!pirq_table)
                return 0;
 
-       DBG(KERN_DEBUG "IRQ for %s[%c]", pci_name(dev), 'A' + pin);
        info = pirq_get_info(dev);
        if (!info) {
-               DBG(" -> not found in routing table\n" KERN_DEBUG);
+               dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n",
+                       'A' + pin);
                return 0;
        }
        pirq = info->irq[pin].link;
        mask = info->irq[pin].bitmap;
        if (!pirq) {
-               DBG(" -> not routed\n" KERN_DEBUG);
+               dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin);
                return 0;
        }
-       DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask,
-               pirq_table->exclusive_irqs);
+       dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x",
+               'A' + pin, pirq, mask, pirq_table->exclusive_irqs);
        mask &= pcibios_irq_mask;
 
        /* Work around broken HP Pavilion Notebooks which assign USB to
@@ -930,10 +929,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
                if (pci_probe & PCI_USE_PIRQ_MASK)
                        newirq = 0;
                else
-                       printk("\n" KERN_WARNING
-                               "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n"
-                               KERN_DEBUG, newirq,
-                               pci_name(dev));
+                       dev_warn(&dev->dev, "IRQ %d doesn't match PIRQ mask "
+                                "%#x; try pci=usepirqmask\n", newirq, mask);
        }
        if (!newirq && assign) {
                for (i = 0; i < 16; i++) {
@@ -944,39 +941,35 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
                                newirq = i;
                }
        }
-       DBG(" -> newirq=%d", newirq);
+       dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin, newirq);
 
        /* Check if it is hardcoded */
        if ((pirq & 0xf0) == 0xf0) {
                irq = pirq & 0xf;
-               DBG(" -> hardcoded IRQ %d\n", irq);
-               msg = "Hardcoded";
+               msg = "hardcoded";
        } else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
        ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask))) {
-               DBG(" -> got IRQ %d\n", irq);
-               msg = "Found";
+               msg = "found";
                eisa_set_level_irq(irq);
        } else if (newirq && r->set &&
                (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
-               DBG(" -> assigning IRQ %d", newirq);
                if (r->set(pirq_router_dev, dev, pirq, newirq)) {
                        eisa_set_level_irq(newirq);
-                       DBG(" ... OK\n");
-                       msg = "Assigned";
+                       msg = "assigned";
                        irq = newirq;
                }
        }
 
        if (!irq) {
-               DBG(" ... failed\n");
                if (newirq && mask == (1 << newirq)) {
-                       msg = "Guessed";
+                       msg = "guessed";
                        irq = newirq;
-               } else
+               } else {
+                       dev_dbg(&dev->dev, "can't route interrupt\n");
                        return 0;
+               }
        }
-       printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq,
-               pci_name(dev));
+       dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin, irq);
 
        /* Update IRQ for all devices with the same pirq value */
        while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
@@ -996,17 +989,17 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
                        (!(pci_probe & PCI_USE_PIRQ_MASK) || \
                        ((1 << dev2->irq) & mask))) {
 #ifndef CONFIG_PCI_MSI
-                               printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
-                                      pci_name(dev2), dev2->irq, irq);
+                               dev_info(&dev2->dev, "IRQ routing conflict: "
+                                        "have IRQ %d, want IRQ %d\n",
+                                        dev2->irq, irq);
 #endif
                                continue;
                        }
                        dev2->irq = irq;
                        pirq_penalty[irq]++;
                        if (dev != dev2)
-                               printk(KERN_INFO
-                                       "PCI: Sharing IRQ %d with %s\n",
-                                       irq, pci_name(dev2));
+                               dev_info(&dev->dev, "sharing IRQ %d with %s\n",
+                                        irq, pci_name(dev2));
                }
        }
        return 1;
@@ -1025,8 +1018,7 @@ static void __init pcibios_fixup_irqs(void)
                 * already in use.
                 */
                if (dev->irq >= 16) {
-                       DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n",
-                               pci_name(dev), dev->irq);
+                       dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", dev->irq);
                        dev->irq = 0;
                }
                /*
@@ -1070,12 +1062,12 @@ static void __init pcibios_fixup_irqs(void)
                                        irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
                                                        PCI_SLOT(bridge->devfn), pin);
                                        if (irq >= 0)
-                                               printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
-                                                       pci_name(bridge), 'A' + pin, irq);
+                                               dev_warn(&dev->dev, "using bridge %s INT %c to get IRQ %d\n",
+                                                        pci_name(bridge),
+                                                        'A' + pin, irq);
                                }
                                if (irq >= 0) {
-                                       printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
-                                               pci_name(dev), 'A' + pin, irq);
+                                       dev_info(&dev->dev, "PCI->APIC IRQ transform: INT %c -> IRQ %d\n", 'A' + pin, irq);
                                        dev->irq = irq;
                                }
                        }
@@ -1231,25 +1223,24 @@ static int pirq_enable_irq(struct pci_dev *dev)
                                irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
                                                PCI_SLOT(bridge->devfn), pin);
                                if (irq >= 0)
-                                       printk(KERN_WARNING
-                                               "PCI: using PPB %s[%c] to get irq %d\n",
-                                               pci_name(bridge),
-                                               'A' + pin, irq);
+                                       dev_warn(&dev->dev, "using bridge %s "
+                                                "INT %c to get IRQ %d\n",
+                                                pci_name(bridge), 'A' + pin,
+                                                irq);
                                dev = bridge;
                        }
                        dev = temp_dev;
                        if (irq >= 0) {
-                               printk(KERN_INFO
-                                       "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
-                                       pci_name(dev), 'A' + pin, irq);
+                               dev_info(&dev->dev, "PCI->APIC IRQ transform: "
+                                        "INT %c -> IRQ %d\n", 'A' + pin, irq);
                                dev->irq = irq;
                                return 0;
                        } else
-                               msg = " Probably buggy MP table.";
+                               msg = "; probably buggy MP table";
                } else if (pci_probe & PCI_BIOS_IRQ_SCAN)
                        msg = "";
                else
-                       msg = " Please try using pci=biosirq.";
+                       msg = "; please try using pci=biosirq";
 
                /*
                 * With IDE legacy devices the IRQ lookup failure is not
@@ -1259,9 +1250,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
                                !(dev->class & 0x5))
                        return 0;
 
-               printk(KERN_WARNING
-                       "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
-                       'A' + pin, pci_name(dev), msg);
+               dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n",
+                        'A' + pin, msg);
        }
        return 0;
 }
index f4b16dc11dad17371056924331653ac48a224838..1177845d31863602e9bf0dbf8bc4e031db3f6487 100644 (file)
@@ -131,13 +131,14 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
        u8 busno, suba, subb;
        int quad = BUS2QUAD(d->bus->number);
 
-       printk("PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
+       dev_info(&d->dev, "searching for i450NX host bridges\n");
        reg = 0xd0;
        for(pxb=0; pxb<2; pxb++) {
                pci_read_config_byte(d, reg++, &busno);
                pci_read_config_byte(d, reg++, &suba);
                pci_read_config_byte(d, reg++, &subb);
-               DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
+               dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n",
+                       pxb, busno, suba, subb);
                if (busno) {
                        /* Bus A */
                        pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
index 9ff6e3cbf08feaf41c36d9a48c46ae45a105174e..b795470ec06919da489b2260c49c67e42ae0abcd 100644 (file)
@@ -325,6 +325,57 @@ static unsigned long xen_store_tr(void)
        return 0;
 }
 
+/*
+ * If 'v' is a vmalloc mapping, then find the linear mapping of the
+ * page (if any) and also set its protections to match:
+ */
+static void set_aliased_prot(void *v, pgprot_t prot)
+{
+       int level;
+       pte_t *ptep;
+       pte_t pte;
+       unsigned long pfn;
+       struct page *page;
+
+       ptep = lookup_address((unsigned long)v, &level);
+       BUG_ON(ptep == NULL);
+
+       pfn = pte_pfn(*ptep);
+       page = pfn_to_page(pfn);
+
+       pte = pfn_pte(pfn, prot);
+
+       if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
+               BUG();
+
+       if (!PageHighMem(page)) {
+               void *av = __va(PFN_PHYS(pfn));
+
+               if (av != v)
+                       if (HYPERVISOR_update_va_mapping((unsigned long)av, pte, 0))
+                               BUG();
+       } else
+               kmap_flush_unused();
+}
+
+static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
+{
+       const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
+       int i;
+
+       for(i = 0; i < entries; i += entries_per_page)
+               set_aliased_prot(ldt + i, PAGE_KERNEL_RO);
+}
+
+static void xen_free_ldt(struct desc_struct *ldt, unsigned entries)
+{
+       const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
+       int i;
+
+       for(i = 0; i < entries; i += entries_per_page)
+               set_aliased_prot(ldt + i, PAGE_KERNEL);
+}
+
 static void xen_set_ldt(const void *addr, unsigned entries)
 {
        struct mmuext_op *op;
@@ -426,7 +477,7 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
                                const void *ptr)
 {
        unsigned long lp = (unsigned long)&dt[entrynum];
-       xmaddr_t mach_lp = virt_to_machine(lp);
+       xmaddr_t mach_lp = arbitrary_virt_to_machine(lp);
        u64 entry = *(u64 *)ptr;
 
        preempt_disable();
@@ -559,7 +610,7 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
 }
 
 static void xen_load_sp0(struct tss_struct *tss,
-                         struct thread_struct *thread)
+                        struct thread_struct *thread)
 {
        struct multicall_space mcs = xen_mc_entry(0);
        MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0);
@@ -803,6 +854,19 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
                        ret = -EFAULT;
                break;
 #endif
+
+       case MSR_STAR:
+       case MSR_CSTAR:
+       case MSR_LSTAR:
+       case MSR_SYSCALL_MASK:
+       case MSR_IA32_SYSENTER_CS:
+       case MSR_IA32_SYSENTER_ESP:
+       case MSR_IA32_SYSENTER_EIP:
+               /* Fast syscall setup is all done in hypercalls, so
+                  these are all ignored.  Stub them out here to stop
+                  Xen console noise. */
+               break;
+
        default:
                ret = native_write_msr_safe(msr, low, high);
        }
@@ -1220,6 +1284,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
        .load_gs_index = xen_load_gs_index,
 #endif
 
+       .alloc_ldt = xen_alloc_ldt,
+       .free_ldt = xen_free_ldt,
+
        .store_gdt = native_store_gdt,
        .store_idt = native_store_idt,
        .store_tr = xen_store_tr,
@@ -1324,7 +1391,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
        .ptep_modify_prot_commit = __ptep_modify_prot_commit,
 
        .pte_val = xen_pte_val,
-       .pte_flags = native_pte_val,
+       .pte_flags = native_pte_flags,
        .pgd_val = xen_pgd_val,
 
        .make_pte = xen_make_pte,
index 4038cbfe33319ac954b83437d45b9c189af052da..7f58304fafb3098fc68d35be4d9c02206077e8cb 100644 (file)
@@ -173,7 +173,7 @@ ENTRY(xen_sysexit)
        pushq $__USER32_CS
        pushq %rdx
 
-       pushq $VGCF_in_syscall
+       pushq $0
 1:     jmp hypercall_iret
 ENDPATCH(xen_sysexit)
 RELOC(xen_sysexit, 1b+1)
index 5e6d75c9f92b33c9a7a210c12333852710350e70..a00359e8f7a8f06c14bfbff198e34d4bc5d5d5ea 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/screen_info.h>
 #include <linux/bootmem.h>
index f3e16efcd47a23bb16fdeaedb9dcf865a573de37..ac15ecbdf9199871f3e31ef7e013fd62e1ce3b06 100644 (file)
@@ -49,7 +49,7 @@ asmlinkage long xtensa_pipe(int __user *userfds)
        int fd[2];
        int error;
 
-       error = do_pipe(fd);
+       error = do_pipe_flags(fd, 0);
        if (!error) {
                if (copy_to_user(userfds, fd, 2 * sizeof(int)))
                        error = -EFAULT;
index 81d0560eaea207a3cd6a66c0ee40ed21089658b9..34163cfaaffca3b329fcf3f33fa7e2b4a377928c 100644 (file)
@@ -280,36 +280,9 @@ void free_initmem(void)
               (&__init_end - &__init_begin) >> 10);
 }
 
-void show_mem(void)
-{
-       int i, free = 0, total = 0, reserved = 0;
-       int shared = 0, cached = 0;
-
-       printk("Mem-info:\n");
-       show_free_areas();
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-       i = max_mapnr;
-       while (i-- > 0) {
-               total++;
-               if (PageReserved(mem_map+i))
-                       reserved++;
-               else if (PageSwapCache(mem_map+i))
-                       cached++;
-               else if (!page_count(mem_map + i))
-                       free++;
-               else
-                       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("%d free pages\n", free);
-}
-
 struct kmem_cache *pgtable_cache __read_mostly;
 
-static void pgd_ctor(struct kmem_cache *cache, void* addr)
+static void pgd_ctor(void* addr)
 {
        pte_t* ptep = (pte_t*)addr;
        int i;
index 9735acb5b4f51544b831ecb07bd037f88d99090f..cf4eb0eefbbf5ce9a6c13f765780149c62a1ef68 100644 (file)
@@ -837,8 +837,7 @@ static void as_completed_request(struct request_queue *q, struct request *rq)
        WARN_ON(!list_empty(&rq->queuelist));
 
        if (RQ_STATE(rq) != AS_RQ_REMOVED) {
-               printk("rq->state %d\n", RQ_STATE(rq));
-               WARN_ON(1);
+               WARN(1, "rq->state %d\n", RQ_STATE(rq));
                goto out;
        }
 
index ddd96fb11a7d71638a32e3e9060aac1f1adac808..af37e4ae62f5933db45692c81258e5af84c632b4 100644 (file)
@@ -269,7 +269,6 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
        int reading = rq_data_dir(rq) == READ;
        int do_copy = 0;
        struct bio *bio;
-       unsigned long stack_mask = ~(THREAD_SIZE - 1);
 
        if (len > (q->max_hw_sectors << 9))
                return -EINVAL;
@@ -278,11 +277,8 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
 
        kaddr = (unsigned long)kbuf;
        alignment = queue_dma_alignment(q) | q->dma_pad_mask;
-       do_copy = ((kaddr & alignment) || (len & alignment));
-
-       if (!((kaddr & stack_mask) ^
-             ((unsigned long)current->stack & stack_mask)))
-               do_copy = 1;
+       do_copy = ((kaddr & alignment) || (len & alignment) ||
+                  object_is_on_stack(kbuf));
 
        if (do_copy)
                bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading);
index 52d6385216ad43d1c76c88adae613b7513efa6b5..77185e5c026a659e300c69b276de3c5ccbb7327b 100644 (file)
@@ -17,6 +17,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
        long long start, length;
        int part;
        int i;
+       int err;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
@@ -61,9 +62,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                                }
                        }
                        /* all seems OK */
-                       add_partition(disk, part, start, length, ADDPART_FLAG_NONE);
+                       err = add_partition(disk, part, start, length, ADDPART_FLAG_NONE);
                        mutex_unlock(&bdev->bd_mutex);
-                       return 0;
+                       return err;
                case BLKPG_DEL_PARTITION:
                        if (!disk->part[part-1])
                                return -ENXIO;
index 808e0ae66aa80cfeead838ea27731457177a22a7..54ec5e718c0e32296ea0c78e515930713f05c811 100644 (file)
@@ -5,7 +5,7 @@
 # Rewritten to use lists instead of if-statements.
 #
 
-obj-$(CONFIG_HAVE_GPIO_LIB)    += gpio/
+obj-y                          += gpio/
 obj-$(CONFIG_PCI)              += pci/
 obj-$(CONFIG_PARISC)           += parisc/
 obj-$(CONFIG_RAPIDIO)          += rapidio/
index cffef1bcbdbc3dde9db746c19be2314a6bc67d0c..549db42f16cf5b8d4354db7c9ba386f466ff1c36 100644 (file)
@@ -137,6 +137,10 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
        /* Calculate required buffer size based on depth below root */
 
        size = acpi_ns_get_pathname_length(node);
+       if (!size) {
+               ACPI_ERROR((AE_INFO, "Invalid node failure"));
+               return_PTR(NULL);
+       }
 
        /* Allocate a buffer to be returned to caller */
 
@@ -229,6 +233,10 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
        /* Determine size required for the caller buffer */
 
        required_size = acpi_ns_get_pathname_length(node);
+       if (!required_size) {
+               ACPI_ERROR((AE_INFO, "Invalid node failure"));
+               return_ACPI_STATUS(AE_ERROR);
+       }
 
        /* Validate/Allocate/Clear caller buffer */
 
index 233c40c5168412da11e3bd826a7d3a3fadd0691d..89f3b2abfdc7b9f15f65513cdb1d852712735c8f 100644 (file)
@@ -113,20 +113,23 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
 
        switch (resource->type) {
        case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+       case ACPI_RESOURCE_TYPE_END_TAG:
                return AE_OK;
        case ACPI_RESOURCE_TYPE_IRQ:
                {
                        struct acpi_resource_irq *p = &resource->data.irq;
                        if (!p || !p->interrupt_count) {
-                               printk(KERN_WARNING PREFIX "Blank IRQ resource\n");
+                               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                                 "Blank _PRS IRQ resource\n"));
                                return AE_OK;
                        }
                        for (i = 0;
                             (i < p->interrupt_count
                              && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
                                if (!p->interrupts[i]) {
-                                       printk(KERN_WARNING PREFIX "Invalid IRQ %d\n",
-                                                     p->interrupts[i]);
+                                       printk(KERN_WARNING PREFIX
+                                              "Invalid _PRS IRQ %d\n",
+                                              p->interrupts[i]);
                                        continue;
                                }
                                link->irq.possible[i] = p->interrupts[i];
@@ -143,15 +146,16 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
                            &resource->data.extended_irq;
                        if (!p || !p->interrupt_count) {
                                printk(KERN_WARNING PREFIX
-                                             "Blank EXT IRQ resource\n");
+                                             "Blank _PRS EXT IRQ resource\n");
                                return AE_OK;
                        }
                        for (i = 0;
                             (i < p->interrupt_count
                              && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
                                if (!p->interrupts[i]) {
-                                       printk(KERN_WARNING PREFIX "Invalid IRQ %d\n",
-                                                     p->interrupts[i]);
+                                       printk(KERN_WARNING PREFIX
+                                              "Invalid _PRS IRQ %d\n",
+                                              p->interrupts[i]);
                                        continue;
                                }
                                link->irq.possible[i] = p->interrupts[i];
@@ -163,7 +167,8 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
                        break;
                }
        default:
-               printk(KERN_ERR PREFIX "Resource is not an IRQ entry\n");
+               printk(KERN_ERR PREFIX "_PRS resource type 0x%x isn't an IRQ\n",
+                      resource->type);
                return AE_OK;
        }
 
@@ -199,6 +204,9 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
 
 
        switch (resource->type) {
+       case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+       case ACPI_RESOURCE_TYPE_END_TAG:
+               return AE_OK;
        case ACPI_RESOURCE_TYPE_IRQ:
                {
                        struct acpi_resource_irq *p = &resource->data.irq;
@@ -208,7 +216,7 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
                                 * particularly those those w/ _STA disabled
                                 */
                                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                                 "Blank IRQ resource\n"));
+                                                 "Blank _CRS IRQ resource\n"));
                                return AE_OK;
                        }
                        *irq = p->interrupts[0];
@@ -224,7 +232,7 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
                                 * return at least 1 IRQ
                                 */
                                printk(KERN_WARNING PREFIX
-                                             "Blank EXT IRQ resource\n");
+                                             "Blank _CRS EXT IRQ resource\n");
                                return AE_OK;
                        }
                        *irq = p->interrupts[0];
@@ -232,10 +240,11 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
                }
                break;
        default:
-               printk(KERN_ERR PREFIX "Resource %d isn't an IRQ\n", resource->type);
-       case ACPI_RESOURCE_TYPE_END_TAG:
+               printk(KERN_ERR PREFIX "_CRS resource type 0x%x isn't an IRQ\n",
+                      resource->type);
                return AE_OK;
        }
+
        return AE_CTRL_TERMINATE;
 }
 
index b9ab030a52d50843b0319fb25875f7c965b72ce0..d5b4ef898879dd913853feb588c5c802f7425266 100644 (file)
@@ -6,8 +6,8 @@
  *  Thanks to Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> for code
  *  review and fixes.
  *
- *  Copyright (C) 2007 Alex Chiang <achiang@hp.com>
- *  Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ *  Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P.
+ *     Alex Chiang <achiang@hp.com>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
@@ -76,9 +76,9 @@ static struct acpi_pci_driver acpi_pci_slot_driver = {
 };
 
 static int
-check_slot(acpi_handle handle, int *device, unsigned long *sun)
+check_slot(acpi_handle handle, unsigned long *sun)
 {
-       int retval = 0;
+       int device = -1;
        unsigned long adr, sta;
        acpi_status status;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -89,32 +89,27 @@ check_slot(acpi_handle handle, int *device, unsigned long *sun)
        if (check_sta_before_sun) {
                /* If SxFy doesn't have _STA, we just assume it's there */
                status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-               if (ACPI_SUCCESS(status) && !(sta & ACPI_STA_DEVICE_PRESENT)) {
-                       retval = -1;
+               if (ACPI_SUCCESS(status) && !(sta & ACPI_STA_DEVICE_PRESENT))
                        goto out;
-               }
        }
 
        status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
        if (ACPI_FAILURE(status)) {
                dbg("_ADR returned %d on %s\n", status, (char *)buffer.pointer);
-               retval = -1;
                goto out;
        }
 
-       *device = (adr >> 16) & 0xffff;
-
        /* No _SUN == not a slot == bail */
        status = acpi_evaluate_integer(handle, "_SUN", NULL, sun);
        if (ACPI_FAILURE(status)) {
                dbg("_SUN returned %d on %s\n", status, (char *)buffer.pointer);
-               retval = -1;
                goto out;
        }
 
+       device = (adr >> 16) & 0xffff;
 out:
        kfree(buffer.pointer);
-       return retval;
+       return device;
 }
 
 struct callback_args {
@@ -144,7 +139,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        struct callback_args *parent_context = context;
        struct pci_bus *pci_bus = parent_context->pci_bus;
 
-       if (check_slot(handle, &device, &sun))
+       device = check_slot(handle, &sun);
+       if (device < 0)
                return AE_OK;
 
        slot = kmalloc(sizeof(*slot), GFP_KERNEL);
@@ -158,6 +154,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        if (IS_ERR(pci_slot)) {
                err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot));
                kfree(slot);
+               return AE_OK;
        }
 
        slot->root_handle = parent_context->root_handle;
index d592dbb1d12acb04b029c1357b1516715890cefe..283c08f5f4d4390bfd12a7bfd820787a1344dbde 100644 (file)
@@ -272,6 +272,8 @@ static atomic_t c3_cpu_count;
 /* Common C-state entry for C2, C3, .. */
 static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
 {
+       /* Don't trace irqs off for idle */
+       stop_critical_timings();
        if (cstate->entry_method == ACPI_CSTATE_FFH) {
                /* Call into architectural FFH based C-state */
                acpi_processor_ffh_cstate_enter(cstate);
@@ -284,6 +286,7 @@ static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
                   gets asserted in time to freeze execution properly. */
                unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
        }
+       start_critical_timings();
 }
 #endif /* !CONFIG_CPU_IDLE */
 
@@ -1329,9 +1332,15 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
        if (!pr->flags.power_setup_done)
                return -ENODEV;
 
-       /* Fall back to the default idle loop */
-       pm_idle = pm_idle_save;
-       synchronize_sched();    /* Relies on interrupts forcing exit from idle. */
+       /*
+        * Fall back to the default idle loop, when pm_idle_save had
+        * been initialized.
+        */
+       if (pm_idle_save) {
+               pm_idle = pm_idle_save;
+               /* Relies on interrupts forcing exit from idle. */
+               synchronize_sched();
+       }
 
        pr->flags.power = 0;
        result = acpi_processor_get_power_info(pr);
@@ -1418,6 +1427,8 @@ static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr,
  */
 static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
 {
+       /* Don't trace irqs off for idle */
+       stop_critical_timings();
        if (cx->entry_method == ACPI_CSTATE_FFH) {
                /* Call into architectural FFH based C-state */
                acpi_processor_ffh_cstate_enter(cx);
@@ -1432,6 +1443,7 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
                   gets asserted in time to freeze execution properly. */
                unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
        }
+       start_critical_timings();
 }
 
 /**
@@ -1890,7 +1902,8 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
 
        /* Unregister the idle handler when processor #0 is removed. */
        if (pr->id == 0) {
-               pm_idle = pm_idle_save;
+               if (pm_idle_save)
+                       pm_idle = pm_idle_save;
 
                /*
                 * We are about to unload the current idle thread pm callback
index a2c3f9cfa5490fe5fef15c4c0e48676ad22f837a..a56fc6c4394bb1dab26cb06527d3f89239333683 100644 (file)
@@ -827,7 +827,6 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
 static int acpi_processor_get_throttling(struct acpi_processor *pr)
 {
        cpumask_t saved_mask;
-       cpumask_of_cpu_ptr_declare(new_mask);
        int ret;
 
        if (!pr)
@@ -839,8 +838,7 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
         * Migrate task to the cpu pointed by pr.
         */
        saved_mask = current->cpus_allowed;
-       cpumask_of_cpu_ptr_next(new_mask, pr->id);
-       set_cpus_allowed_ptr(current, new_mask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
        ret = pr->throttling.acpi_processor_get_throttling(pr);
        /* restore the previous state */
        set_cpus_allowed_ptr(current, &saved_mask);
@@ -989,7 +987,6 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
 int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
 {
        cpumask_t saved_mask;
-       cpumask_of_cpu_ptr_declare(new_mask);
        int ret = 0;
        unsigned int i;
        struct acpi_processor *match_pr;
@@ -1028,8 +1025,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
         * it can be called only for the cpu pointed by pr.
         */
        if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
-               cpumask_of_cpu_ptr_next(new_mask, pr->id);
-               set_cpus_allowed_ptr(current, new_mask);
+               set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
                ret = p_throttling->acpi_processor_set_throttling(pr,
                                                t_state.target_state);
        } else {
@@ -1060,8 +1056,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
                                continue;
                        }
                        t_state.cpu = i;
-                       cpumask_of_cpu_ptr_next(new_mask, i);
-                       set_cpus_allowed_ptr(current, new_mask);
+                       set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
                        ret = match_pr->throttling.
                                acpi_processor_set_throttling(
                                match_pr, t_state.target_state);
index 0489a7d1d42c91dcf404c50c56e07c722a41ea1f..d13194a031bfbe0d1f9de3c83cd25471c10eda7a 100644 (file)
@@ -280,9 +280,36 @@ static struct platform_suspend_ops acpi_suspend_ops_old = {
        .end = acpi_pm_end,
        .recover = acpi_pm_finish,
 };
+
+static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
+{
+       old_suspend_ordering = true;
+       return 0;
+}
+
+static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "Abit KN9 (nForce4 variant)",
+       .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
+               DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
+               },
+       },
+       {},
+};
 #endif /* CONFIG_SUSPEND */
 
 #ifdef CONFIG_HIBERNATION
+static unsigned long s4_hardware_signature;
+static struct acpi_table_facs *facs;
+static bool nosigcheck;
+
+void __init acpi_no_s4_hw_signature(void)
+{
+       nosigcheck = true;
+}
+
 static int acpi_hibernation_begin(void)
 {
        acpi_target_sleep_state = ACPI_STATE_S4;
@@ -316,6 +343,12 @@ static void acpi_hibernation_leave(void)
        acpi_enable();
        /* Reprogram control registers and execute _BFS */
        acpi_leave_sleep_state_prep(ACPI_STATE_S4);
+       /* Check the hardware signature */
+       if (facs && s4_hardware_signature != facs->hardware_signature) {
+               printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
+                       "cannot resume!\n");
+               panic("ACPI S4 hardware signature mismatch");
+       }
 }
 
 static void acpi_pm_enable_gpes(void)
@@ -516,6 +549,8 @@ int __init acpi_sleep_init(void)
        u8 type_a, type_b;
 #ifdef CONFIG_SUSPEND
        int i = 0;
+
+       dmi_check_system(acpisleep_dmi_table);
 #endif
 
        if (acpi_disabled)
@@ -544,6 +579,13 @@ int __init acpi_sleep_init(void)
                        &acpi_hibernation_ops_old : &acpi_hibernation_ops);
                sleep_states[ACPI_STATE_S4] = 1;
                printk(" S4");
+               if (!nosigcheck) {
+                       acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
+                               (struct acpi_table_header **)&facs);
+                       if (facs)
+                               s4_hardware_signature =
+                                       facs->hardware_signature;
+               }
        }
 #endif
        status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
index d8e3f153b29587dc144fc1e77f639242b2aa9a00..91dec448b3edcd5055112a892f1c368433bc6281 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
+#include <linux/string.h>
 #include <asm/uaccess.h>
 
 #include <acpi/acpi_drivers.h>
index ccb5b64bbef3396036796509da86ba4b52efc6cd..a4a41ba2484b93404ae948e3d50e5dcff81577a1 100644 (file)
@@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
 
 static void inline
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
-                            u8 byte_width, u64 address)
+                            u8 bit_width, u64 address)
 {
 
        /*
@@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
        /* All other fields are byte-wide */
 
        generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
-       generic_address->bit_width = byte_width << 3;
+       generic_address->bit_width = bit_width;
        generic_address->bit_offset = 0;
        generic_address->access_width = 0;
 }
@@ -343,11 +343,9 @@ static void acpi_tb_convert_fadt(void)
         *
         * The PM event blocks are split into two register blocks, first is the
         * PM Status Register block, followed immediately by the PM Enable Register
-        * block. Each is of length (xpm1x_event_block.bit_width/2)
+        * block. Each is of length (pm1_event_length/2)
         */
-       WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1a_event_block.bit_width));
-       pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
-                                              .xpm1a_event_block.bit_width);
+       pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
 
        /* The PM1A register block is required */
 
@@ -362,17 +360,14 @@ static void acpi_tb_convert_fadt(void)
        /* The PM1B register block is optional, ignore if not present */
 
        if (acpi_gbl_FADT.xpm1b_event_block.address) {
-               WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1b_event_block.bit_width));
-               pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
-                                                      .xpm1b_event_block
-                                                      .bit_width);
                acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
                                             pm1_register_length,
                                             (acpi_gbl_FADT.xpm1b_event_block.
                                              address + pm1_register_length));
                /* Don't forget to copy space_id of the GAS */
                acpi_gbl_xpm1b_enable.space_id =
-                   acpi_gbl_FADT.xpm1b_event_block.space_id;
+                   acpi_gbl_FADT.xpm1a_event_block.space_id;
+
        }
 }
 
index 30a3413379334e9ee24071f8d704dc3156bc118c..912703691d36306b0d2256ba345570cab139f688 100644 (file)
@@ -769,6 +769,47 @@ static void acpi_thermal_run(unsigned long data)
                acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data);
 }
 
+static void acpi_thermal_active_off(void *data)
+{
+       int result = 0;
+       struct acpi_thermal *tz = data;
+       int i = 0;
+       int j = 0;
+       struct acpi_thermal_active *active = NULL;
+
+       if (!tz) {
+               printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
+               return;
+       }
+
+       result = acpi_thermal_get_temperature(tz);
+       if (result)
+               return;
+
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               active = &(tz->trips.active[i]);
+               if (!active || !active->flags.valid)
+                       break;
+               if (tz->temperature >= active->temperature) {
+                       /*
+                        * If the thermal temperature is greater than the
+                        * active threshod, unnecessary to turn off the
+                        * the active cooling device.
+                        */
+                       continue;
+               }
+               /*
+                * Below Threshold?
+                * ----------------
+                * Turn OFF all cooling devices associated with this
+                * threshold.
+                */
+               for (j = 0; j < active->devices.count; j++)
+                       result = acpi_bus_set_power(active->devices.handles[j],
+                                                   ACPI_STATE_D3);
+       }
+}
+
 static void acpi_thermal_check(void *data)
 {
        int result = 0;
@@ -1624,6 +1665,8 @@ static int acpi_thermal_add(struct acpi_device *device)
 
        init_timer(&tz->timer);
 
+       acpi_thermal_active_off(tz);
+
        acpi_thermal_check(tz);
 
        status = acpi_install_notify_handler(device->handle,
index 3dfb8a442b2604e4186c2dd901efb4ef67bfd2b3..e7bf34a7b1d29aa6819ddbfe62403012ca48551e 100644 (file)
@@ -242,6 +242,10 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
 {
        acpi_status status = AE_OK;
 
+       if (!required_length) {
+               WARN_ON(1);
+               return AE_ERROR;
+       }
        switch (buffer->length) {
        case ACPI_NO_BUFFER:
 
index 37b9e16710d60596442c780e683d24441e797a61..e8a51a1700f710ca45d7ceba5a22429f7d348fbe 100644 (file)
@@ -741,7 +741,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
        max_level = acpi_video_init_brightness(device);
 
-       if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
+       if (device->cap._BCL && device->cap._BCM && max_level > 0) {
                int result;
                static int count = 0;
                char *name;
@@ -753,7 +753,17 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                device->backlight = backlight_device_register(name,
                        NULL, device, &acpi_backlight_ops);
                device->backlight->props.max_brightness = device->brightness->count-3;
-               device->backlight->props.brightness = acpi_video_get_brightness(device->backlight);
+               /*
+                * If there exists the _BQC object, the _BQC object will be
+                * called to get the current backlight brightness. Otherwise
+                * the brightness will be set to the maximum.
+                */
+               if (device->cap._BQC)
+                       device->backlight->props.brightness =
+                               acpi_video_get_brightness(device->backlight);
+               else
+                       device->backlight->props.brightness =
+                               device->backlight->props.max_brightness;
                backlight_update_status(device->backlight);
                kfree(name);
 
index dc7596f028b69437d8e833a688e15142c97675c8..ef3e5522e1a4a41979ff5ec56b72ed860d004275 100644 (file)
@@ -1273,7 +1273,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
        void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
        u32 em_ctl;
        u32 message[] = {0, 0};
-       unsigned int flags;
+       unsigned long flags;
        int pmp;
        struct ahci_em_priv *emp;
 
index de8d186f5abf01ba6c2e6dccfd0477e0e9fb4619..2014253f6c8842981b6d6b2f34ca8a52144ccbe4 100644 (file)
@@ -169,7 +169,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
 
        irq = platform_get_irq(pdev, 0);
        if (irq)
-               set_irq_type(irq, IRQT_RISING);
+               set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
 
        /* Setup expansion bus chip selects */
        *data->cs0_cfg = data->cs0_bits;
index d5c1bbfbe79d0379cafddc6a4c048bbe552060e1..73338d231db9f232c90a5fcbbbe432ad50687044 100644 (file)
@@ -2562,7 +2562,8 @@ fore200e_load_and_start_fw(struct fore200e* fore200e)
     const struct firmware *firmware;
     struct device *device;
     struct fw_header *fw_header;
-    u32 *fw_data, fw_size;
+    const __le32 *fw_data;
+    u32 fw_size;
     u32 __iomem *load_addr;
     char buf[48];
     int err = -ENODEV;
@@ -2582,7 +2583,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e)
        return err;
     }
 
-    fw_data = (u32 *) firmware->data;
+    fw_data = (__le32 *) firmware->data;
     fw_size = firmware->size / sizeof(u32);
     fw_header = (struct fw_header *) firmware->data;
     load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset);
@@ -3199,6 +3200,14 @@ static const struct fore200e_bus fore200e_bus[] = {
     {}
 };
 
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");
+#ifdef CONFIG_PCI
+#ifdef __LITTLE_ENDIAN__
+MODULE_FIRMWARE("pca200e.bin");
+#else
+MODULE_FIRMWARE("pca200e_ecd.bin2");
+#endif
+#endif /* CONFIG_PCI */
+#ifdef CONFIG_SBUS
+MODULE_FIRMWARE("sba200e_ecd.bin2");
 #endif
index 683509f013abaabdc1711e3436dc94474cd1429c..eacb175f6bd37a4e5c4314c65a039a1fb04b91d8 100644 (file)
@@ -336,16 +336,9 @@ static int __init cfag12864b_init(void)
                        "ks0108 is not initialized\n");
                goto none;
        }
+       BUILD_BUG_ON(PAGE_SIZE < CFAG12864B_SIZE);
 
-       if (PAGE_SIZE < CFAG12864B_SIZE) {
-               printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
-                       "page size (%i) < cfag12864b size (%i)\n",
-                       (unsigned int)PAGE_SIZE, CFAG12864B_SIZE);
-               ret = -ENOMEM;
-               goto none;
-       }
-
-       cfag12864b_buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
+       cfag12864b_buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL);
        if (cfag12864b_buffer == NULL) {
                printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
                        "can't get a free page\n");
@@ -367,8 +360,6 @@ static int __init cfag12864b_init(void)
        if (cfag12864b_workqueue == NULL)
                goto cachealloced;
 
-       memset(cfag12864b_buffer, 0, CFAG12864B_SIZE);
-
        cfag12864b_clear();
        cfag12864b_on();
 
index 7d5c63c81a599fb220b0b2f831c95afaa454caed..068aa1c9538c99d54a47603e25f69544f084f537 100644 (file)
@@ -116,12 +116,10 @@ static void device_release(struct kobject *kobj)
                dev->type->release(dev);
        else if (dev->class && dev->class->dev_release)
                dev->class->dev_release(dev);
-       else {
-               printk(KERN_ERR "Device '%s' does not have a release() "
+       else
+               WARN(1, KERN_ERR "Device '%s' does not have a release() "
                        "function, it is broken and must be fixed.\n",
                        dev->bus_id);
-               WARN_ON(1);
-       }
 }
 
 static struct kobj_type device_ktype = {
index b0be1d18fee23d5c25d865bba20c0a3560546195..c9c92b00fd555768730b731695bdbac1deeab1e9 100644 (file)
@@ -184,7 +184,7 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
        struct device *dev = to_dev(kobj);
        struct firmware_priv *fw_priv = dev_get_drvdata(dev);
        struct firmware *fw;
-       ssize_t ret_count = count;
+       ssize_t ret_count;
 
        mutex_lock(&fw_lock);
        fw = fw_priv->fw;
@@ -192,14 +192,8 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
                ret_count = -ENODEV;
                goto out;
        }
-       if (offset > fw->size) {
-               ret_count = 0;
-               goto out;
-       }
-       if (offset + ret_count > fw->size)
-               ret_count = fw->size - offset;
-
-       memcpy(buffer, fw->data + offset, ret_count);
+       ret_count = memory_read_from_buffer(buffer, count, &offset,
+                                               fw->data, fw->size);
 out:
        mutex_unlock(&fw_lock);
        return ret_count;
index d2222397a401ca42f80986b4852e688e5267d6eb..efd5775749485d8ec6bfafa998cd9c6fff53f812 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/dma-mapping.h>
 #include <linux/isa.h>
 
 static struct device isa_bus = {
@@ -141,6 +142,9 @@ int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev)
                isa_dev->dev.release            = isa_dev_release;
                isa_dev->id                     = id;
 
+               isa_dev->dev.coherent_dma_mask = DMA_24BIT_MASK;
+               isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask;
+
                error = device_register(&isa_dev->dev);
                if (error) {
                        put_device(&isa_dev->dev);
index 4d4e0e7b6e925e656c8346d63671f0179bca880e..af0d175c025dcd168c5a6de866351fd0b1f83d5a 100644 (file)
@@ -100,6 +100,22 @@ static ssize_t show_mem_phys_index(struct sys_device *dev,
        return sprintf(buf, "%08lx\n", mem->phys_index);
 }
 
+/*
+ * Show whether the section of memory is likely to be hot-removable
+ */
+static ssize_t show_mem_removable(struct sys_device *dev,
+                       struct sysdev_attribute *attr, char *buf)
+{
+       unsigned long start_pfn;
+       int ret;
+       struct memory_block *mem =
+               container_of(dev, struct memory_block, sysdev);
+
+       start_pfn = section_nr_to_pfn(mem->phys_index);
+       ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION);
+       return sprintf(buf, "%d\n", ret);
+}
+
 /*
  * online, offline, going offline, etc.
  */
@@ -189,9 +205,8 @@ memory_block_action(struct memory_block *mem, unsigned long action)
                        }
                        break;
                default:
-                       printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
+                       WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
                                        __func__, mem, action, action);
-                       WARN_ON(1);
                        ret = -EINVAL;
        }
 
@@ -262,6 +277,7 @@ static ssize_t show_phys_device(struct sys_device *dev,
 static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
 static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
 static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
+static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
 
 #define mem_create_simple_file(mem, attr_name) \
        sysdev_create_file(&mem->sysdev, &attr_##attr_name)
@@ -350,6 +366,8 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
                ret = mem_create_simple_file(mem, state);
        if (!ret)
                ret = mem_create_simple_file(mem, phys_device);
+       if (!ret)
+               ret = mem_create_simple_file(mem, removable);
 
        return ret;
 }
@@ -394,6 +412,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
        mem_remove_simple_file(mem, phys_index);
        mem_remove_simple_file(mem, state);
        mem_remove_simple_file(mem, phys_device);
+       mem_remove_simple_file(mem, removable);
        unregister_memory(mem, section);
 
        return 0;
index 40fc14f035402ec70de718977e309932dce7b576..75dd6e22faff531cf8d136223bdf379102c299f6 100644 (file)
@@ -168,19 +168,16 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
        int err = 0;
 
        if (!cls) {
-               printk(KERN_WARNING "sysdev: invalid class passed to "
+               WARN(1, KERN_WARNING "sysdev: invalid class passed to "
                        "sysdev_driver_register!\n");
-               WARN_ON(1);
                return -EINVAL;
        }
 
        /* Check whether this driver has already been added to a class. */
-       if (drv->entry.next && !list_empty(&drv->entry)) {
-               printk(KERN_WARNING "sysdev: class %s: driver (%p) has already"
+       if (drv->entry.next && !list_empty(&drv->entry))
+               WARN(1, KERN_WARNING "sysdev: class %s: driver (%p) has already"
                        " been registered to a class, something is wrong, but "
                        "will forge on!\n", cls->name, drv);
-               WARN_ON(1);
-       }
 
        mutex_lock(&sysdev_drivers_lock);
        if (cls && kset_get(&cls->kset)) {
@@ -194,8 +191,7 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
                }
        } else {
                err = -EINVAL;
-               printk(KERN_ERR "%s: invalid device class\n", __func__);
-               WARN_ON(1);
+               WARN(1, KERN_ERR "%s: invalid device class\n", __func__);
        }
        mutex_unlock(&sysdev_drivers_lock);
        return err;
index c04440cd6a32d5bc5031aed5ec4fe50c4d50dd67..181ebb85f0be582e95206aa144c04ee26ff016bc 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/hdreg.h>
 #include <linux/blkdev.h>
+#include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
 #include "aoe.h"
@@ -36,7 +37,7 @@ struct ErrMsg {
 
 static struct ErrMsg emsgs[NMSG];
 static int emsgs_head_idx, emsgs_tail_idx;
-static struct semaphore emsgs_sema;
+static struct completion emsgs_comp;
 static spinlock_t emsgs_lock;
 static int nblocked_emsgs_readers;
 static struct class *aoe_class;
@@ -141,7 +142,7 @@ bail:               spin_unlock_irqrestore(&emsgs_lock, flags);
        spin_unlock_irqrestore(&emsgs_lock, flags);
 
        if (nblocked_emsgs_readers)
-               up(&emsgs_sema);
+               complete(&emsgs_comp);
 }
 
 static ssize_t
@@ -221,7 +222,7 @@ aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
 
                spin_unlock_irqrestore(&emsgs_lock, flags);
 
-               n = down_interruptible(&emsgs_sema);
+               n = wait_for_completion_interruptible(&emsgs_comp);
 
                spin_lock_irqsave(&emsgs_lock, flags);
 
@@ -269,7 +270,7 @@ aoechr_init(void)
                printk(KERN_ERR "aoe: can't register char device\n");
                return n;
        }
-       sema_init(&emsgs_sema, 0);
+       init_completion(&emsgs_comp);
        spin_lock_init(&emsgs_lock);
        aoe_class = class_create(THIS_MODULE, "aoe");
        if (IS_ERR(aoe_class)) {
index dd7ea203f940dc664a9ac74ef9fa157ac3a36b5b..42251095134fa7746e8748150089c2dd570d21d8 100644 (file)
@@ -196,6 +196,7 @@ static int virtblk_probe(struct virtio_device *vdev)
        int err;
        u64 cap;
        u32 v;
+       u32 blk_size;
 
        if (index_to_minor(index) >= 1 << MINORBITS)
                return -ENOSPC;
@@ -290,6 +291,13 @@ static int virtblk_probe(struct virtio_device *vdev)
        if (!err)
                blk_queue_max_hw_segments(vblk->disk->queue, v);
 
+       /* Host can optionally specify the block size of the device */
+       err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE,
+                               offsetof(struct virtio_blk_config, blk_size),
+                               &blk_size);
+       if (!err)
+               blk_queue_hardsect_size(vblk->disk->queue, blk_size);
+
        add_disk(vblk->disk);
        return 0;
 
@@ -330,7 +338,7 @@ static struct virtio_device_id id_table[] = {
 
 static unsigned int features[] = {
        VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
-       VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO,
+       VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
 };
 
 static struct virtio_driver virtio_blk = {
index e0bbbfb6a36bd2b98092a641ef1b496f3a6b9e07..d0ac944e16961775d5bb428e851ab0ea0e4d7494 100644 (file)
@@ -36,6 +36,14 @@ config VT
          If unsure, say Y, or else you won't be able to do much with your new
          shiny Linux system :-)
 
+config CONSOLE_TRANSLATIONS
+       depends on VT
+       default y
+       bool "Enable character translations in console" if EMBEDDED
+       ---help---
+         This enables support for font mapping and Unicode translation
+         on virtual consoles.
+
 config VT_CONSOLE
        bool "Support for console on virtual terminal" if EMBEDDED
        depends on VT
@@ -578,11 +586,14 @@ config HVC_DRIVER
          It will automatically be selected if one of the back-end console drivers
          is selected.
 
+config HVC_IRQ
+       bool
 
 config HVC_CONSOLE
        bool "pSeries Hypervisor Virtual Console support"
        depends on PPC_PSERIES
        select HVC_DRIVER
+       select HVC_IRQ
        help
          pSeries machines when partitioned support a hypervisor virtual
          console. This driver allows each pSeries partition to have a console
@@ -593,6 +604,7 @@ config HVC_ISERIES
        depends on PPC_ISERIES
        default y
        select HVC_DRIVER
+       select HVC_IRQ
        help
          iSeries machines support a hypervisor virtual console.
 
@@ -614,13 +626,18 @@ config HVC_XEN
        bool "Xen Hypervisor Console support"
        depends on XEN
        select HVC_DRIVER
+       select HVC_IRQ
        default y
        help
          Xen virtual console device driver
 
 config VIRTIO_CONSOLE
-       bool
+       tristate "Virtio console"
+       depends on VIRTIO
        select HVC_DRIVER
+       help
+         Virtio console for use with lguest and other hypervisors.
+
 
 config HVCS
        tristate "IBM Hypervisor Virtual Console Server support"
@@ -857,13 +874,6 @@ config DS1302
 
 endif # RTC_LIB
 
-config COBALT_LCD
-       bool "Support for Cobalt LCD"
-       depends on MIPS_COBALT
-       help
-         This option enables support for the LCD display and buttons found
-         on Cobalt systems through a misc device.
-
 config DTLK
        tristate "Double Talk PC internal speech card support"
        depends on ISA
index dc5a327d72d5782ade03eece6a5f128ada9d2329..8a161c30e1dc1670ebd5576ccc7669fdc857aaf7 100644 (file)
@@ -12,8 +12,8 @@ obj-y  += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o
 obj-$(CONFIG_LEGACY_PTYS)      += pty.o
 obj-$(CONFIG_UNIX98_PTYS)      += pty.o
 obj-y                          += misc.o
-obj-$(CONFIG_VT)               += vt_ioctl.o vc_screen.o consolemap.o \
-                                  consolemap_deftbl.o selection.o keyboard.o
+obj-$(CONFIG_VT)               += vt_ioctl.o vc_screen.o selection.o keyboard.o
+obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
 obj-$(CONFIG_HW_CONSOLE)       += vt.o defkeymap.o
 obj-$(CONFIG_AUDIT)            += tty_audit.o
 obj-$(CONFIG_MAGIC_SYSRQ)      += sysrq.o
@@ -48,6 +48,7 @@ obj-$(CONFIG_HVC_ISERIES)     += hvc_iseries.o
 obj-$(CONFIG_HVC_RTAS)         += hvc_rtas.o
 obj-$(CONFIG_HVC_BEAT)         += hvc_beat.o
 obj-$(CONFIG_HVC_DRIVER)       += hvc_console.o
+obj-$(CONFIG_HVC_IRQ)          += hvc_irq.o
 obj-$(CONFIG_HVC_XEN)          += hvc_xen.o
 obj-$(CONFIG_VIRTIO_CONSOLE)   += virtio_console.o
 obj-$(CONFIG_RAW_DRIVER)       += raw.o
@@ -63,7 +64,6 @@ obj-$(CONFIG_BRIQ_PANEL)      += briq_panel.o
 obj-$(CONFIG_BFIN_OTP)         += bfin-otp.o
 
 obj-$(CONFIG_PRINTER)          += lp.o
-obj-$(CONFIG_TIPAR)            += tipar.o
 
 obj-$(CONFIG_APM_EMULATION)    += apm-emulation.o
 
@@ -88,7 +88,6 @@ obj-$(CONFIG_TOSHIBA)         += toshiba.o
 obj-$(CONFIG_I8K)              += i8k.o
 obj-$(CONFIG_DS1620)           += ds1620.o
 obj-$(CONFIG_HW_RANDOM)                += hw_random/
-obj-$(CONFIG_COBALT_LCD)       += lcd.o
 obj-$(CONFIG_PPDEV)            += ppdev.o
 obj-$(CONFIG_NWBUTTON)         += nwbutton.o
 obj-$(CONFIG_NWFLASH)          += nwflash.o
index fada6ddefbae0bf45138f9bfc5167dab29265945..c5e67a623951bbc89f05cb7f9b5ade1530866fc1 100644 (file)
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
 #include <linux/bcd.h>
+#include <linux/smp_lock.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 
-#include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/io.h>
 #include <asm/rtc.h>
 #if defined(CONFIG_M32R)
 #include <asm/m32r.h>
@@ -153,9 +154,7 @@ static unsigned char days_in_mo[] =
 
 /* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */
 
-static int
-rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-         unsigned long arg)
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        unsigned long flags;
 
@@ -165,7 +164,9 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        struct rtc_time rtc_tm;
 
                        memset(&rtc_tm, 0, sizeof (struct rtc_time));
+                       lock_kernel();
                        get_rtc_time(&rtc_tm);
+                       unlock_kernel();
                        if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
                                return -EFAULT;
                        return 0;
@@ -217,6 +218,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        BIN_TO_BCD(mon);
                        BIN_TO_BCD(yrs);
 
+                       lock_kernel();
                        local_irq_save(flags);
                        CMOS_WRITE(yrs, RTC_YEAR);
                        CMOS_WRITE(mon, RTC_MONTH);
@@ -225,6 +227,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        CMOS_WRITE(min, RTC_MINUTES);
                        CMOS_WRITE(sec, RTC_SECONDS);
                        local_irq_restore(flags);
+                       unlock_kernel();
 
                        /* Notice that at this point, the RTC is updated but
                         * the kernel is still running with the old time.
@@ -244,8 +247,10 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
                                return -EFAULT;
 
+                       lock_kernel();
                        tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
                        ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
+                       unlock_kernel();
                        return 0;
                }
                default:
@@ -282,7 +287,7 @@ get_rtc_status(char *buf)
 
 static const struct file_operations rtc_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = rtc_ioctl,
+       .unlocked_ioctl = rtc_ioctl,
 };
 
 /* Probe for the chip by writing something to its RAM and try reading it back. */
index 33c466a4888f092c15475601b503a473808a20fc..ca7c72a486b2f1391d57b07621c19e28cb37d65d 100644 (file)
 #include <linux/smp_lock.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/uaccess.h>     /* For put_user and get_user */
 
 #include <asm/atarihw.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>       /* For put_user and get_user */
 
 #include <asm/dsp56k.h>
 
@@ -303,10 +303,10 @@ static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t co
        }
 }
 
-static int dsp56k_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
+static long dsp56k_ioctl(struct file *file, unsigned int cmd,
+                        unsigned long arg)
 {
-       int dev = iminor(inode) & 0x0f;
+       int dev = iminor(file->f_path.dentry->d_inode) & 0x0f;
        void __user *argp = (void __user *)arg;
 
        switch(dev)
@@ -331,8 +331,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
                        if (len > DSP56K_MAX_BINARY_LENGTH) {
                                return -EINVAL;
                        }
-    
+                       lock_kernel();
                        r = dsp56k_upload(bin, len);
+                       unlock_kernel();
                        if (r < 0) {
                                return r;
                        }
@@ -342,12 +343,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
                case DSP56K_SET_TX_WSIZE:
                        if (arg > 4 || arg < 1)
                                return -EINVAL;
+                       lock_kernel();
                        dsp56k.tx_wsize = (int) arg;
+                       unlock_kernel();
                        break;
                case DSP56K_SET_RX_WSIZE:
                        if (arg > 4 || arg < 1)
                                return -EINVAL;
+                       lock_kernel();
                        dsp56k.rx_wsize = (int) arg;
+                       unlock_kernel();
                        break;
                case DSP56K_HOST_FLAGS:
                {
@@ -359,6 +364,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
                        if(get_user(out, &hf->out) < 0)
                                return -EFAULT;
 
+                       lock_kernel();
                        if ((dir & 0x1) && (out & 0x1))
                                dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
                        else if (dir & 0x1)
@@ -373,14 +379,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
                        if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2;
                        if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4;
                        if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8;
-
+                       unlock_kernel();
                        return put_user(status, &hf->status);
                }
                case DSP56K_HOST_CMD:
                        if (arg > 31 || arg < 0)
                                return -EINVAL;
+                       lock_kernel();
                        dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
                                                             DSP56K_CVR_HC);
+                       unlock_kernel();
                        break;
                default:
                        return -EINVAL;
@@ -472,7 +480,7 @@ static const struct file_operations dsp56k_fops = {
        .owner          = THIS_MODULE,
        .read           = dsp56k_read,
        .write          = dsp56k_write,
-       .ioctl          = dsp56k_ioctl,
+       .unlocked_ioctl = dsp56k_ioctl,
        .open           = dsp56k_open,
        .release        = dsp56k_release,
 };
index d57ca3e4e5343311f43acbf8b35021ed16ee3fe4..67fbd7aab5dbfa9b73396808cd6feaa1a7369791 100644 (file)
@@ -37,8 +37,9 @@
 #include <linux/rtc.h>
 #include <linux/proc_fs.h>
 #include <linux/efi.h>
+#include <linux/smp_lock.h>
+#include <linux/uaccess.h>
 
-#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define EFI_RTC_VERSION                "0.4"
@@ -51,8 +52,8 @@
 
 static DEFINE_SPINLOCK(efi_rtc_lock);
 
-static int efi_rtc_ioctl(struct inode *inode, struct file *file,
-                    unsigned int cmd, unsigned long arg);
+static long efi_rtc_ioctl(struct file *file, unsigned int cmd,
+                                                       unsigned long arg);
 
 #define is_leap(year) \
           ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
@@ -146,9 +147,8 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
        }
 }
 
-static int
-efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-                    unsigned long arg)
+static long efi_rtc_ioctl(struct file *file, unsigned int cmd,
+                                                       unsigned long arg)
 {
 
        efi_status_t    status;
@@ -175,13 +175,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        return -EINVAL;
 
                case RTC_RD_TIME:
-
+                       lock_kernel();
                        spin_lock_irqsave(&efi_rtc_lock, flags);
 
                        status = efi.get_time(&eft, &cap);
 
                        spin_unlock_irqrestore(&efi_rtc_lock,flags);
-
+                       unlock_kernel();
                        if (status != EFI_SUCCESS) {
                                /* should never happen */
                                printk(KERN_ERR "efitime: can't read time\n");
@@ -203,11 +203,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                        convert_to_efi_time(&wtime, &eft);
 
+                       lock_kernel();
                        spin_lock_irqsave(&efi_rtc_lock, flags);
 
                        status = efi.set_time(&eft);
 
                        spin_unlock_irqrestore(&efi_rtc_lock,flags);
+                       unlock_kernel();
 
                        return status == EFI_SUCCESS ? 0 : -EINVAL;
 
@@ -223,6 +225,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                        convert_to_efi_time(&wtime, &eft);
 
+                       lock_kernel();
                        spin_lock_irqsave(&efi_rtc_lock, flags);
                        /*
                         * XXX Fixme:
@@ -233,16 +236,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        status = efi.set_wakeup_time((efi_bool_t)enabled, &eft);
 
                        spin_unlock_irqrestore(&efi_rtc_lock,flags);
+                       unlock_kernel();
 
                        return status == EFI_SUCCESS ? 0 : -EINVAL;
 
                case RTC_WKALM_RD:
 
+                       lock_kernel();
                        spin_lock_irqsave(&efi_rtc_lock, flags);
 
                        status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft);
 
                        spin_unlock_irqrestore(&efi_rtc_lock,flags);
+                       unlock_kernel();
 
                        if (status != EFI_SUCCESS) return -EINVAL;
 
@@ -256,7 +262,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        return copy_to_user(&ewp->time, &wtime,
                                            sizeof(struct rtc_time)) ? -EFAULT : 0;
        }
-       return -EINVAL;
+       return -ENOTTY;
 }
 
 /*
@@ -265,8 +271,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
  *     up things on a close.
  */
 
-static int
-efi_rtc_open(struct inode *inode, struct file *file)
+static int efi_rtc_open(struct inode *inode, struct file *file)
 {
        /*
         * nothing special to do here
@@ -277,8 +282,7 @@ efi_rtc_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int
-efi_rtc_close(struct inode *inode, struct file *file)
+static int efi_rtc_close(struct inode *inode, struct file *file)
 {
        return 0;
 }
@@ -289,13 +293,12 @@ efi_rtc_close(struct inode *inode, struct file *file)
 
 static const struct file_operations efi_rtc_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = efi_rtc_ioctl,
+       .unlocked_ioctl = efi_rtc_ioctl,
        .open           = efi_rtc_open,
        .release        = efi_rtc_close,
 };
 
-static struct miscdevice efi_rtc_dev=
-{
+static struct miscdevice efi_rtc_dev= {
        EFI_RTC_MINOR,
        "efirtc",
        &efi_rtc_fops
index fb0a85a1eb36a71abcb9455048fb502c0b0d52ed..b3f5dbc6d8807c7a51cf352118bf5ea08e35d635 100644 (file)
@@ -623,6 +623,7 @@ static inline int hpet_tpcheck(struct hpet_task *tp)
        return -ENXIO;
 }
 
+#if 0
 int hpet_unregister(struct hpet_task *tp)
 {
        struct hpet_dev *devp;
@@ -652,6 +653,7 @@ int hpet_unregister(struct hpet_task *tp)
 
        return 0;
 }
+#endif  /*  0  */
 
 static ctl_table hpet_table[] = {
        {
index 2f9759d625cc520b02c78d4605bbb594c4765f7e..02aac104842d91033077da4488926fccfc7daa3d 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/init.h>
 #include <linux/kbd_kern.h>
 #include <linux/kernel.h>
-#include <linux/kref.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -75,23 +74,6 @@ static int hvc_init(void);
 static int sysrq_pressed;
 #endif
 
-struct hvc_struct {
-       spinlock_t lock;
-       int index;
-       struct tty_struct *tty;
-       unsigned int count;
-       int do_wakeup;
-       char *outbuf;
-       int outbuf_size;
-       int n_outbuf;
-       uint32_t vtermno;
-       struct hv_ops *ops;
-       int irq_requested;
-       int irq;
-       struct list_head next;
-       struct kref kref; /* ref count & hvc_struct lifetime */
-};
-
 /* dynamic list of hvc_struct instances */
 static LIST_HEAD(hvc_structs);
 
@@ -298,27 +280,15 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(hvc_instantiate);
 
 /* Wake the sleeping khvcd */
-static void hvc_kick(void)
+void hvc_kick(void)
 {
        hvc_kicked = 1;
        wake_up_process(hvc_task);
 }
-
-static int hvc_poll(struct hvc_struct *hp);
-
-/*
- * NOTE: This API isn't used if the console adapter doesn't support interrupts.
- * In this case the console is poll driven.
- */
-static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance)
-{
-       /* if hvc_poll request a repoll, then kick the hvcd thread */
-       if (hvc_poll(dev_instance))
-               hvc_kick();
-       return IRQ_HANDLED;
-}
+EXPORT_SYMBOL_GPL(hvc_kick);
 
 static void hvc_unthrottle(struct tty_struct *tty)
 {
@@ -333,7 +303,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
 {
        struct hvc_struct *hp;
        unsigned long flags;
-       int irq = 0;
        int rc = 0;
 
        /* Auto increments kref reference if found. */
@@ -352,18 +321,15 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
        tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */
 
        hp->tty = tty;
-       /* Save for request_irq outside of spin_lock. */
-       irq = hp->irq;
-       if (irq)
-               hp->irq_requested = 1;
+
+       if (hp->ops->notifier_add)
+               rc = hp->ops->notifier_add(hp, hp->data);
 
        spin_unlock_irqrestore(&hp->lock, flags);
-       /* check error, fallback to non-irq */
-       if (irq)
-               rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp);
+
 
        /*
-        * If the request_irq() fails and we return an error.  The tty layer
+        * If the notifier fails we return an error.  The tty layer
         * will call hvc_close() after a failed open but we don't want to clean
         * up there so we'll clean up here and clear out the previously set
         * tty fields and return the kref reference.
@@ -371,7 +337,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
        if (rc) {
                spin_lock_irqsave(&hp->lock, flags);
                hp->tty = NULL;
-               hp->irq_requested = 0;
                spin_unlock_irqrestore(&hp->lock, flags);
                tty->driver_data = NULL;
                kref_put(&hp->kref, destroy_hvc_struct);
@@ -386,7 +351,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
 static void hvc_close(struct tty_struct *tty, struct file * filp)
 {
        struct hvc_struct *hp;
-       int irq = 0;
        unsigned long flags;
 
        if (tty_hung_up_p(filp))
@@ -404,9 +368,8 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
        spin_lock_irqsave(&hp->lock, flags);
 
        if (--hp->count == 0) {
-               if (hp->irq_requested)
-                       irq = hp->irq;
-               hp->irq_requested = 0;
+               if (hp->ops->notifier_del)
+                       hp->ops->notifier_del(hp, hp->data);
 
                /* We are done with the tty pointer now. */
                hp->tty = NULL;
@@ -418,10 +381,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
                 * waking periodically to check chars_in_buffer().
                 */
                tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
-
-               if (irq)
-                       free_irq(irq, hp);
-
        } else {
                if (hp->count < 0)
                        printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
@@ -436,7 +395,6 @@ static void hvc_hangup(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
        unsigned long flags;
-       int irq = 0;
        int temp_open_count;
 
        if (!hp)
@@ -458,13 +416,12 @@ static void hvc_hangup(struct tty_struct *tty)
        hp->count = 0;
        hp->n_outbuf = 0;
        hp->tty = NULL;
-       if (hp->irq_requested)
-               /* Saved for use outside of spin_lock. */
-               irq = hp->irq;
-       hp->irq_requested = 0;
+
+       if (hp->ops->notifier_del)
+                       hp->ops->notifier_del(hp, hp->data);
+
        spin_unlock_irqrestore(&hp->lock, flags);
-       if (irq)
-               free_irq(irq, hp);
+
        while(temp_open_count) {
                --temp_open_count;
                kref_put(&hp->kref, destroy_hvc_struct);
@@ -575,7 +532,7 @@ static u32 timeout = MIN_TIMEOUT;
 #define HVC_POLL_READ  0x00000001
 #define HVC_POLL_WRITE 0x00000002
 
-static int hvc_poll(struct hvc_struct *hp)
+int hvc_poll(struct hvc_struct *hp)
 {
        struct tty_struct *tty;
        int i, n, poll_mask = 0;
@@ -602,10 +559,10 @@ static int hvc_poll(struct hvc_struct *hp)
        if (test_bit(TTY_THROTTLED, &tty->flags))
                goto throttled;
 
-       /* If we aren't interrupt driven and aren't throttled, we always
+       /* If we aren't notifier driven and aren't throttled, we always
         * request a reschedule
         */
-       if (hp->irq == 0)
+       if (!hp->irq_requested)
                poll_mask |= HVC_POLL_READ;
 
        /* Read data if any */
@@ -674,6 +631,7 @@ static int hvc_poll(struct hvc_struct *hp)
 
        return poll_mask;
 }
+EXPORT_SYMBOL_GPL(hvc_poll);
 
 /*
  * This kthread is either polling or interrupt driven.  This is determined by
@@ -733,7 +691,7 @@ static const struct tty_operations hvc_ops = {
        .chars_in_buffer = hvc_chars_in_buffer,
 };
 
-struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
+struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data,
                                        struct hv_ops *ops, int outbuf_size)
 {
        struct hvc_struct *hp;
@@ -754,7 +712,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
        memset(hp, 0x00, sizeof(*hp));
 
        hp->vtermno = vtermno;
-       hp->irq = irq;
+       hp->data = data;
        hp->ops = ops;
        hp->outbuf_size = outbuf_size;
        hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
@@ -784,6 +742,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
 
        return hp;
 }
+EXPORT_SYMBOL_GPL(hvc_alloc);
 
 int __devexit hvc_remove(struct hvc_struct *hp)
 {
index 42ffb17e15df7d4f038f483cc16da4b1a42baf3f..d9ce10915625db733c5f7aecb3ffd4679c94de08 100644 (file)
@@ -26,6 +26,7 @@
 
 #ifndef HVC_CONSOLE_H
 #define HVC_CONSOLE_H
+#include <linux/kref.h>
 
 /*
  * This is the max number of console adapters that can/will be found as
  */
 #define HVC_ALLOC_TTY_ADAPTERS 8
 
+struct hvc_struct {
+       spinlock_t lock;
+       int index;
+       struct tty_struct *tty;
+       unsigned int count;
+       int do_wakeup;
+       char *outbuf;
+       int outbuf_size;
+       int n_outbuf;
+       uint32_t vtermno;
+       struct hv_ops *ops;
+       int irq_requested;
+       int data;
+       struct list_head next;
+       struct kref kref; /* ref count & hvc_struct lifetime */
+};
 
 /* implemented by a low level driver */
 struct hv_ops {
        int (*get_chars)(uint32_t vtermno, char *buf, int count);
        int (*put_chars)(uint32_t vtermno, const char *buf, int count);
-};
 
-struct hvc_struct;
+       /* Callbacks for notification. Called in open and close */
+       int (*notifier_add)(struct hvc_struct *hp, int irq);
+       void (*notifier_del)(struct hvc_struct *hp, int irq);
+};
 
 /* Register a vterm and a slot index for use as a console (console_init) */
 extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
 
 /* register a vterm for hvc tty operation (module_init or hotplug add) */
-extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
+extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data,
                                struct hv_ops *ops, int outbuf_size);
-/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
+/* remove a vterm from hvc tty operation (module_exit or hotplug remove) */
 extern int __devexit hvc_remove(struct hvc_struct *hp);
 
+/* data available */
+int hvc_poll(struct hvc_struct *hp);
+void hvc_kick(void);
+
+/* default notifier for irq based notification */
+extern int notifier_add_irq(struct hvc_struct *hp, int data);
+extern void notifier_del_irq(struct hvc_struct *hp, int data);
+
 
 #if defined(CONFIG_XMON) && defined(CONFIG_SMP)
 #include <asm/xmon.h>
diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c
new file mode 100644 (file)
index 0000000..73a59cd
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright IBM Corp. 2001,2008
+ *
+ * This file contains the IRQ specific code for hvc_console
+ *
+ */
+
+#include <linux/interrupt.h>
+
+#include "hvc_console.h"
+
+static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance)
+{
+       /* if hvc_poll request a repoll, then kick the hvcd thread */
+       if (hvc_poll(dev_instance))
+               hvc_kick();
+       return IRQ_HANDLED;
+}
+
+/*
+ * For IRQ based systems these callbacks can be used
+ */
+int notifier_add_irq(struct hvc_struct *hp, int irq)
+{
+       int rc;
+
+       if (!irq) {
+               hp->irq_requested = 0;
+               return 0;
+       }
+       rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED,
+                          "hvc_console", hp);
+       if (!rc)
+               hp->irq_requested = 1;
+       return rc;
+}
+
+void notifier_del_irq(struct hvc_struct *hp, int irq)
+{
+       if (!irq)
+               return;
+       free_irq(irq, hp);
+       hp->irq_requested = 0;
+}
index a08f8f981c11c8446176e8e588c0d917562dfcfb..b71c610fe5ae0584092b8badbc4c9c93fe52f117 100644 (file)
@@ -200,6 +200,8 @@ done:
 static struct hv_ops hvc_get_put_ops = {
        .get_chars = get_chars,
        .put_chars = put_chars,
+       .notifier_add = notifier_add_irq,
+       .notifier_del = notifier_del_irq,
 };
 
 static int __devinit hvc_vio_probe(struct vio_dev *vdev,
index 79711aa4b41d4ae85de49cf8bddad9a0c50ded18..93f3840c1682e53e9f2e20c2f21330ba4a9a71e5 100644 (file)
@@ -80,6 +80,8 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
 static struct hv_ops hvc_get_put_ops = {
        .get_chars = filtered_get_chars,
        .put_chars = hvc_put_chars,
+       .notifier_add = notifier_add_irq,
+       .notifier_del = notifier_del_irq,
 };
 
 static int __devinit hvc_vio_probe(struct vio_dev *vdev,
index db2ae4216279377e7cc092a63ff2e5c0e6db691b..6b70aa66a587883bf56f4ca3163ac7828afc3eae 100644 (file)
@@ -100,6 +100,8 @@ static int read_console(uint32_t vtermno, char *buf, int len)
 static struct hv_ops hvc_ops = {
        .get_chars = read_console,
        .put_chars = write_console,
+       .notifier_add = notifier_add_irq,
+       .notifier_del = notifier_del_irq,
 };
 
 static int __init xen_init(void)
index 27fdc0866496344d4fca2a3b43a6de48ad143f2b..8a2fce0756ec71af923091486c094c9e1c2eb792 100644 (file)
@@ -241,7 +241,7 @@ static int __init intel_rng_hw_init(void *_intel_rng_hw)
        struct intel_rng_hw *intel_rng_hw = _intel_rng_hw;
        u8 mfc, dvc;
 
-       /* interrupts disabled in stop_machine_run call */
+       /* interrupts disabled in stop_machine call */
 
        if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK))
                pci_write_config_byte(intel_rng_hw->dev,
@@ -365,10 +365,10 @@ static int __init mod_init(void)
         * location with the Read ID command, all activity on the system
         * must be stopped until the state is back to normal.
         *
-        * Use stop_machine_run because IPIs can be blocked by disabling
+        * Use stop_machine because IPIs can be blocked by disabling
         * interrupts.
         */
-       err = stop_machine_run(intel_rng_hw_init, intel_rng_hw, NR_CPUS);
+       err = stop_machine(intel_rng_hw_init, intel_rng_hw, NULL);
        pci_dev_put(dev);
        iounmap(intel_rng_hw->mem);
        kfree(intel_rng_hw);
index 9cb48fcd316c775007e596dc66a6adb0494ddfd9..689f9dcd3b866f1bd6ca9e3a0f707f7b2de9cb39 100644 (file)
@@ -203,7 +203,7 @@ static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
 
 static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *);
 static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *);
-static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG);
+static long ip2_ipl_ioctl(struct file *, UINT, ULONG);
 static int ip2_ipl_open(struct inode *, struct file *);
 
 static int DumpTraceBuffer(char __user *, int);
@@ -236,7 +236,7 @@ static const struct file_operations ip2_ipl = {
        .owner          = THIS_MODULE,
        .read           = ip2_ipl_read,
        .write          = ip2_ipl_write,
-       .ioctl          = ip2_ipl_ioctl,
+       .unlocked_ioctl = ip2_ipl_ioctl,
        .open           = ip2_ipl_open,
 }; 
 
@@ -2845,10 +2845,10 @@ ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t
 /*                                                                            */
 /*                                                                            */
 /******************************************************************************/
-static int
-ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
+static long
+ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
 {
-       unsigned int iplminor = iminor(pInode);
+       unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode);
        int rc = 0;
        void __user *argp = (void __user *)arg;
        ULONG __user *pIndex = argp;
@@ -2859,6 +2859,8 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
        printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
 #endif
 
+       lock_kernel();
+
        switch ( iplminor ) {
        case 0:     // IPL device
                rc = -EINVAL;
@@ -2919,6 +2921,7 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
                rc = -ENODEV;
                break;
        }
+       unlock_kernel();
        return rc;
 }
 
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
deleted file mode 100644 (file)
index 1c29b20..0000000
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * LCD, LED and Button interface for Cobalt
- *
- * 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) 1996, 1997 by Andrew Bose
- *
- * Linux kernel version history:
- *       March 2001: Ported from 2.0.34  by Liam Davies
- *
- */
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/mc146818rtc.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include "lcd.h"
-
-static int lcd_ioctl(struct inode *inode, struct file *file,
-                    unsigned int cmd, unsigned long arg);
-
-static unsigned int lcd_present = 1;
-
-/* used in arch/mips/cobalt/reset.c */
-int led_state = 0;
-
-#if defined(CONFIG_TULIP) && 0
-
-#define MAX_INTERFACES 8
-static linkcheck_func_t linkcheck_callbacks[MAX_INTERFACES];
-static void *linkcheck_cookies[MAX_INTERFACES];
-
-int lcd_register_linkcheck_func(int iface_num, void *func, void *cookie)
-{
-       if (iface_num < 0 ||
-           iface_num >= MAX_INTERFACES ||
-           linkcheck_callbacks[iface_num] != NULL)
-               return -1;
-       linkcheck_callbacks[iface_num] = (linkcheck_func_t) func;
-       linkcheck_cookies[iface_num] = cookie;
-       return 0;
-}
-#endif
-
-static int lcd_ioctl(struct inode *inode, struct file *file,
-                    unsigned int cmd, unsigned long arg)
-{
-       struct lcd_display button_display;
-       unsigned long address, a;
-
-       switch (cmd) {
-       case LCD_On:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x0F);
-               break;
-
-       case LCD_Off:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x08);
-               break;
-
-       case LCD_Reset:
-               udelay(150);
-               LCDWriteInst(0x3F);
-               udelay(150);
-               LCDWriteInst(0x3F);
-               udelay(150);
-               LCDWriteInst(0x3F);
-               udelay(150);
-               LCDWriteInst(0x3F);
-               udelay(150);
-               LCDWriteInst(0x01);
-               udelay(150);
-               LCDWriteInst(0x06);
-               break;
-
-       case LCD_Clear:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x01);
-               break;
-
-       case LCD_Cursor_Left:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x10);
-               break;
-
-       case LCD_Cursor_Right:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x14);
-               break;
-
-       case LCD_Cursor_Off:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x0C);
-               break;
-
-       case LCD_Cursor_On:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x0F);
-               break;
-
-       case LCD_Blink_Off:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x0E);
-               break;
-
-       case LCD_Get_Cursor_Pos:{
-                       struct lcd_display display;
-
-                       udelay(150);
-                       BusyCheck();
-                       display.cursor_address = (LCDReadInst);
-                       display.cursor_address =
-                           (display.cursor_address & 0x07F);
-                       if (copy_to_user
-                           ((struct lcd_display *) arg, &display,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-
-                       break;
-               }
-
-
-       case LCD_Set_Cursor_Pos:{
-                       struct lcd_display display;
-
-                       if (copy_from_user
-                           (&display, (struct lcd_display *) arg,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-
-                       a = (display.cursor_address | kLCD_Addr);
-
-                       udelay(150);
-                       BusyCheck();
-                       LCDWriteInst(a);
-
-                       break;
-               }
-
-       case LCD_Get_Cursor:{
-                       struct lcd_display display;
-
-                       udelay(150);
-                       BusyCheck();
-                       display.character = LCDReadData;
-
-                       if (copy_to_user
-                           ((struct lcd_display *) arg, &display,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-                       udelay(150);
-                       BusyCheck();
-                       LCDWriteInst(0x10);
-
-                       break;
-               }
-
-       case LCD_Set_Cursor:{
-                       struct lcd_display display;
-
-                       if (copy_from_user
-                           (&display, (struct lcd_display *) arg,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-
-                       udelay(150);
-                       BusyCheck();
-                       LCDWriteData(display.character);
-                       udelay(150);
-                       BusyCheck();
-                       LCDWriteInst(0x10);
-
-                       break;
-               }
-
-
-       case LCD_Disp_Left:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x18);
-               break;
-
-       case LCD_Disp_Right:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x1C);
-               break;
-
-       case LCD_Home:
-               udelay(150);
-               BusyCheck();
-               LCDWriteInst(0x02);
-               break;
-
-       case LCD_Write:{
-                       struct lcd_display display;
-                       unsigned int index;
-
-
-                       if (copy_from_user
-                           (&display, (struct lcd_display *) arg,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-
-                       udelay(150);
-                       BusyCheck();
-                       LCDWriteInst(0x80);
-                       udelay(150);
-                       BusyCheck();
-
-                       for (index = 0; index < (display.size1); index++) {
-                               udelay(150);
-                               BusyCheck();
-                               LCDWriteData(display.line1[index]);
-                               BusyCheck();
-                       }
-
-                       udelay(150);
-                       BusyCheck();
-                       LCDWriteInst(0xC0);
-                       udelay(150);
-                       BusyCheck();
-                       for (index = 0; index < (display.size2); index++) {
-                               udelay(150);
-                               BusyCheck();
-                               LCDWriteData(display.line2[index]);
-                       }
-
-                       break;
-               }
-
-       case LCD_Read:{
-                       struct lcd_display display;
-
-                       BusyCheck();
-                       for (address = kDD_R00; address <= kDD_R01;
-                            address++) {
-                               a = (address | kLCD_Addr);
-
-                               udelay(150);
-                               BusyCheck();
-                               LCDWriteInst(a);
-                               udelay(150);
-                               BusyCheck();
-                               display.line1[address] = LCDReadData;
-                       }
-
-                       display.line1[0x27] = '\0';
-
-                       for (address = kDD_R10; address <= kDD_R11;
-                            address++) {
-                               a = (address | kLCD_Addr);
-
-                               udelay(150);
-                               BusyCheck();
-                               LCDWriteInst(a);
-
-                               udelay(150);
-                               BusyCheck();
-                               display.line2[address - 0x40] =
-                                   LCDReadData;
-                       }
-
-                       display.line2[0x27] = '\0';
-
-                       if (copy_to_user
-                           ((struct lcd_display *) arg, &display,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-                       break;
-               }
-
-//  set all GPIO leds to led_display.leds
-
-       case LED_Set:{
-                       struct lcd_display led_display;
-
-
-                       if (copy_from_user
-                           (&led_display, (struct lcd_display *) arg,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-
-                       led_state = led_display.leds;
-                       LEDSet(led_state);
-
-                       break;
-               }
-
-
-//  set only bit led_display.leds
-
-       case LED_Bit_Set:{
-                       unsigned int i;
-                       int bit = 1;
-                       struct lcd_display led_display;
-
-
-                       if (copy_from_user
-                           (&led_display, (struct lcd_display *) arg,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-
-                       for (i = 0; i < (int) led_display.leds; i++) {
-                               bit = 2 * bit;
-                       }
-
-                       led_state = led_state | bit;
-                       LEDSet(led_state);
-                       break;
-               }
-
-//  clear only bit led_display.leds
-
-       case LED_Bit_Clear:{
-                       unsigned int i;
-                       int bit = 1;
-                       struct lcd_display led_display;
-
-
-                       if (copy_from_user
-                           (&led_display, (struct lcd_display *) arg,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-
-                       for (i = 0; i < (int) led_display.leds; i++) {
-                               bit = 2 * bit;
-                       }
-
-                       led_state = led_state & ~bit;
-                       LEDSet(led_state);
-                       break;
-               }
-
-
-       case BUTTON_Read:{
-                       button_display.buttons = GPIRead;
-                       if (copy_to_user
-                           ((struct lcd_display *) arg, &button_display,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-                       break;
-               }
-
-       case LINK_Check:{
-                       button_display.buttons =
-                           *((volatile unsigned long *) (0xB0100060));
-                       if (copy_to_user
-                           ((struct lcd_display *) arg, &button_display,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-                       break;
-               }
-
-       case LINK_Check_2:{
-                       int iface_num;
-
-                       /* panel-utils should pass in the desired interface status is wanted for
-                        * in "buttons" of the structure.  We will set this to non-zero if the
-                        * link is in fact up for the requested interface.  --DaveM
-                        */
-                       if (copy_from_user
-                           (&button_display, (struct lcd_display *) arg,
-                            sizeof(button_display)))
-                               return -EFAULT;
-                       iface_num = button_display.buttons;
-#if defined(CONFIG_TULIP) && 0
-                       if (iface_num >= 0 &&
-                           iface_num < MAX_INTERFACES &&
-                           linkcheck_callbacks[iface_num] != NULL) {
-                               button_display.buttons =
-                                   linkcheck_callbacks[iface_num]
-                                   (linkcheck_cookies[iface_num]);
-                       } else
-#endif
-                               button_display.buttons = 0;
-
-                       if (__copy_to_user
-                           ((struct lcd_display *) arg, &button_display,
-                            sizeof(struct lcd_display)))
-                               return -EFAULT;
-                       break;
-               }
-
-       default:
-               return -EINVAL;
-
-       }
-
-       return 0;
-
-}
-
-static int lcd_open(struct inode *inode, struct file *file)
-{
-       cycle_kernel_lock();
-
-       if (!lcd_present)
-               return -ENXIO;
-       else
-               return 0;
-}
-
-/* Only RESET or NEXT counts as button pressed */
-
-static inline int button_pressed(void)
-{
-       unsigned long buttons = GPIRead;
-
-       if ((buttons == BUTTON_Next) || (buttons == BUTTON_Next_B)
-           || (buttons == BUTTON_Reset_B))
-               return buttons;
-       return 0;
-}
-
-/* LED daemon sits on this and we wake him up once a key is pressed. */
-
-static int lcd_waiters = 0;
-
-static ssize_t lcd_read(struct file *file, char *buf,
-                    size_t count, loff_t *ofs)
-{
-       long buttons_now;
-
-       if (lcd_waiters > 0)
-               return -EINVAL;
-
-       lcd_waiters++;
-       while (((buttons_now = (long) button_pressed()) == 0) &&
-              !(signal_pending(current))) {
-               msleep_interruptible(2000);
-       }
-       lcd_waiters--;
-
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-       return buttons_now;
-}
-
-/*
- *     The various file operations we support.
- */
-
-static const struct file_operations lcd_fops = {
-       .read = lcd_read,
-       .ioctl = lcd_ioctl,
-       .open = lcd_open,
-};
-
-static struct miscdevice lcd_dev = {
-       MISC_DYNAMIC_MINOR,
-       "lcd",
-       &lcd_fops
-};
-
-static int lcd_init(void)
-{
-       int ret;
-       unsigned long data;
-
-       pr_info("%s\n", LCD_DRIVER);
-       ret = misc_register(&lcd_dev);
-       if (ret) {
-               printk(KERN_WARNING LCD "Unable to register misc device.\n");
-               return ret;
-       }
-
-       /* Check region? Naaah! Just snarf it up. */
-/*     request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/
-
-       udelay(150);
-       data = LCDReadData;
-       if ((data & 0x000000FF) == (0x00)) {
-               lcd_present = 0;
-               pr_info(LCD "LCD Not Present\n");
-       } else {
-               lcd_present = 1;
-               WRITE_GAL(kGal_DevBank2PReg, kGal_DevBank2Cfg);
-               WRITE_GAL(kGal_DevBank3PReg, kGal_DevBank3Cfg);
-       }
-
-       return 0;
-}
-
-static void __exit lcd_exit(void)
-{
-       misc_deregister(&lcd_dev);
-}
-
-module_init(lcd_init);
-module_exit(lcd_exit);
-
-MODULE_AUTHOR("Andrew Bose");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h
deleted file mode 100644 (file)
index 290b3ff..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * LED, LCD and Button panel driver for Cobalt
- *
- * 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) 1996, 1997 by Andrew Bose
- *
- * Linux kernel version history:
- *       March 2001: Ported from 2.0.34  by Liam Davies
- *
- */
-
-// function headers
-
-#define LCD_CHARS_PER_LINE 40
-#define MAX_IDLE_TIME 120
-
-struct lcd_display {
-        unsigned buttons;
-        int size1;
-        int size2;
-        unsigned char line1[LCD_CHARS_PER_LINE];
-        unsigned char line2[LCD_CHARS_PER_LINE];
-        unsigned char cursor_address;
-        unsigned char character;
-        unsigned char leds;
-        unsigned char *RomImage;
-};
-
-
-
-#define LCD_DRIVER     "Cobalt LCD Driver v2.10"
-
-#define LCD            "lcd: "
-
-#define kLCD_IR                0x0F000000
-#define kLCD_DR                0x0F000010
-#define kGPI           0x0D000000
-#define kLED           0x0C000000
-
-#define kDD_R00         0x00
-#define kDD_R01         0x27
-#define kDD_R10         0x40
-#define kDD_R11         0x67
-
-#define kLCD_Addr       0x00000080
-
-#define LCDTimeoutValue        0xfff
-
-
-// Macros
-
-#define LCDWriteData(x)        outl((x << 24), kLCD_DR)
-#define LCDWriteInst(x)        outl((x << 24), kLCD_IR)
-
-#define LCDReadData    (inl(kLCD_DR) >> 24)
-#define LCDReadInst    (inl(kLCD_IR) >> 24)
-
-#define GPIRead                (inl(kGPI) >> 24)
-
-#define LEDSet(x)      outb((char)x, kLED)
-
-#define WRITE_GAL(x,y) outl(y, 0x04000000 | (x))
-#define BusyCheck()    while ((LCDReadInst & 0x80) == 0x80)
-
-
-
-/*
- * Function command codes for io_ctl.
- */
-#define LCD_On                 1
-#define LCD_Off                        2
-#define LCD_Clear              3
-#define LCD_Reset              4
-#define LCD_Cursor_Left                5
-#define LCD_Cursor_Right       6
-#define LCD_Disp_Left          7
-#define LCD_Disp_Right         8
-#define LCD_Get_Cursor         9
-#define LCD_Set_Cursor         10
-#define LCD_Home               11
-#define LCD_Read               12
-#define LCD_Write              13
-#define LCD_Cursor_Off         14
-#define LCD_Cursor_On          15
-#define LCD_Get_Cursor_Pos     16
-#define LCD_Set_Cursor_Pos     17
-#define LCD_Blink_Off           18
-
-#define LED_Set                        40
-#define LED_Bit_Set            41
-#define LED_Bit_Clear          42
-
-
-//  Button defs
-#define BUTTON_Read             50
-
-
-// Ethernet LINK check hackaroo
-#define LINK_Check              90
-#define LINK_Check_2           91
-
-//  Button patterns  _B - single layer lcd boards
-
-#define BUTTON_NONE               0x3F
-#define BUTTON_NONE_B             0xFE
-
-#define BUTTON_Left               0x3B
-#define BUTTON_Left_B             0xFA
-
-#define BUTTON_Right              0x37
-#define BUTTON_Right_B            0xDE
-
-#define BUTTON_Up                 0x2F
-#define BUTTON_Up_B               0xF6
-
-#define BUTTON_Down               0x1F
-#define BUTTON_Down_B             0xEE
-
-#define BUTTON_Next               0x3D
-#define BUTTON_Next_B             0x7E
-
-#define BUTTON_Enter              0x3E
-#define BUTTON_Enter_B            0xBE
-
-#define BUTTON_Reset_B            0xFC
-
-
-// debounce constants
-
-#define BUTTON_SENSE            160000
-#define BUTTON_DEBOUNCE                5000
-
-
-//  Galileo register stuff
-
-#define kGal_DevBank2Cfg        0x1466DB33
-#define kGal_DevBank2PReg       0x464
-#define kGal_DevBank3Cfg        0x146FDFFB
-#define kGal_DevBank3PReg       0x468
-
-// Network
-
-#define kIPADDR                        1
-#define kNETMASK               2
-#define kGATEWAY               3
-#define kDNS                   4
-
-#define kClassA                        5
-#define kClassB                        6
-#define kClassC                        7
-
index c2dba82eb5f7fa82bdb874b17f605ab01f80fb1f..672b08e694d05cd041e8a3bbac17264f3ca2fb4e 100644 (file)
@@ -327,7 +327,10 @@ static void mmap_mem_close(struct vm_area_struct *vma)
 
 static struct vm_operations_struct mmap_mem_ops = {
        .open  = mmap_mem_open,
-       .close = mmap_mem_close
+       .close = mmap_mem_close,
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+       .access = generic_access_phys
+#endif
 };
 
 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
index fe2a95b5d3c05e36121110de446e7309098d3f6b..30f095a8c2d4ff3932d7ad8db1d5ec462c33cd2d 100644 (file)
@@ -193,25 +193,23 @@ mspec_close(struct vm_area_struct *vma)
 }
 
 /*
- * mspec_nopfn
+ * mspec_fault
  *
  * Creates a mspec page and maps it to user space.
  */
-static unsigned long
-mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
+static int
+mspec_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        unsigned long paddr, maddr;
        unsigned long pfn;
-       int index;
+       pgoff_t index = vmf->pgoff;
        struct vma_data *vdata = vma->vm_private_data;
 
-       BUG_ON(address < vdata->vm_start || address >= vdata->vm_end);
-       index = (address - vdata->vm_start) >> PAGE_SHIFT;
        maddr = (volatile unsigned long) vdata->maddr[index];
        if (maddr == 0) {
                maddr = uncached_alloc_page(numa_node_id(), 1);
                if (maddr == 0)
-                       return NOPFN_OOM;
+                       return VM_FAULT_OOM;
 
                spin_lock(&vdata->lock);
                if (vdata->maddr[index] == 0) {
@@ -231,13 +229,20 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
 
        pfn = paddr >> PAGE_SHIFT;
 
-       return pfn;
+       /*
+        * vm_insert_pfn can fail with -EBUSY, but in that case it will
+        * be because another thread has installed the pte first, so it
+        * is no problem.
+        */
+       vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+
+       return VM_FAULT_NOPAGE;
 }
 
 static struct vm_operations_struct mspec_vm_ops = {
        .open = mspec_open,
        .close = mspec_close,
-       .nopfn = mspec_nopfn
+       .fault = mspec_fault,
 };
 
 /*
index 50243fcd87e882656069cce5492b92b53469d4f7..4f8d67fed292bfc6a9423a975fb08265dd78f69e 100644 (file)
@@ -86,8 +86,8 @@ module_param(mwave_uart_io, int, 0);
 
 static int mwave_open(struct inode *inode, struct file *file);
 static int mwave_close(struct inode *inode, struct file *file);
-static int mwave_ioctl(struct inode *inode, struct file *filp,
-                       unsigned int iocmd, unsigned long ioarg);
+static long mwave_ioctl(struct file *filp, unsigned int iocmd,
+                                                       unsigned long ioarg);
 
 MWAVE_DEVICE_DATA mwave_s_mdd;
 
@@ -119,16 +119,16 @@ static int mwave_close(struct inode *inode, struct file *file)
        return retval;
 }
 
-static int mwave_ioctl(struct inode *inode, struct file *file,
-                       unsigned int iocmd, unsigned long ioarg)
+static long mwave_ioctl(struct file *file, unsigned int iocmd,
+                                                       unsigned long ioarg)
 {
        unsigned int retval = 0;
        pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
        void __user *arg = (void __user *)ioarg;
 
-       PRINTK_5(TRACE_MWAVE,
-               "mwavedd::mwave_ioctl, entry inode %p file %p cmd %x arg %x\n",
-                inode,  file, iocmd, (int) ioarg);
+       PRINTK_4(TRACE_MWAVE,
+               "mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n",
+               file, iocmd, (int) ioarg);
 
        switch (iocmd) {
 
@@ -136,7 +136,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                        PRINTK_1(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_RESET"
                                " calling tp3780I_ResetDSP\n");
+                       lock_kernel();
                        retval = tp3780I_ResetDSP(&pDrvData->rBDData);
+                       unlock_kernel();
                        PRINTK_2(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_RESET"
                                " retval %x from tp3780I_ResetDSP\n",
@@ -147,7 +149,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                        PRINTK_1(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_RUN"
                                " calling tp3780I_StartDSP\n");
+                       lock_kernel();
                        retval = tp3780I_StartDSP(&pDrvData->rBDData);
+                       unlock_kernel();
                        PRINTK_2(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_RUN"
                                " retval %x from tp3780I_StartDSP\n",
@@ -161,8 +165,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                "mwavedd::mwave_ioctl,"
                                " IOCTL_MW_DSP_ABILITIES calling"
                                " tp3780I_QueryAbilities\n");
+                       lock_kernel();
                        retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
                                        &rAbilities);
+                       unlock_kernel();
                        PRINTK_2(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
                                " retval %x from tp3780I_QueryAbilities\n",
@@ -193,11 +199,13 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
                                " size %lx, ioarg %lx pusBuffer %p\n",
                                rReadData.ulDataLength, ioarg, pusBuffer);
+                       lock_kernel();
                        retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
                                        iocmd,
                                        pusBuffer,
                                        rReadData.ulDataLength,
                                        rReadData.usDspAddress);
+                       unlock_kernel();
                }
                        break;
        
@@ -215,10 +223,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                " size %lx, ioarg %lx pusBuffer %p\n",
                                rReadData.ulDataLength / 2, ioarg,
                                pusBuffer);
+                       lock_kernel();
                        retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
                                iocmd, pusBuffer,
                                rReadData.ulDataLength / 2,
                                rReadData.usDspAddress);
+                       unlock_kernel();
                }
                        break;
        
@@ -236,10 +246,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                " size %lx, ioarg %lx pusBuffer %p\n",
                                rWriteData.ulDataLength, ioarg,
                                pusBuffer);
+                       lock_kernel();
                        retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
                                        iocmd, pusBuffer,
                                        rWriteData.ulDataLength,
                                        rWriteData.usDspAddress);
+                       unlock_kernel();
                }
                        break;
        
@@ -257,10 +269,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                " size %lx, ioarg %lx pusBuffer %p\n",
                                rWriteData.ulDataLength, ioarg,
                                pusBuffer);
+                       lock_kernel();
                        retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
                                        iocmd, pusBuffer,
                                        rWriteData.ulDataLength,
                                        rWriteData.usDspAddress);
+                       unlock_kernel();
                }
                        break;
        
@@ -281,8 +295,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                                ipcnum);
                                return -EINVAL;
                        }
+                       lock_kernel();
                        pDrvData->IPCs[ipcnum].bIsHere = FALSE;
                        pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
+                       unlock_kernel();
        
                        PRINTK_2(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
@@ -307,6 +323,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                return -EINVAL;
                        }
        
+                       lock_kernel();
                        if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
                                DECLARE_WAITQUEUE(wait, current);
 
@@ -347,6 +364,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                        " processing\n",
                                        ipcnum);
                        }
+                       unlock_kernel();
                }
                        break;
        
@@ -365,19 +383,18 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                                ipcnum);
                                return -EINVAL;
                        }
+                       lock_kernel();
                        if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
                                pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
                                if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) {
                                        wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
                                }
                        }
+                       unlock_kernel();
                }
                        break;
        
                default:
-                       PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:"
-                                       " Error: Unrecognized iocmd %x\n",
-                                       iocmd);
                        return -ENOTTY;
                        break;
        } /* switch */
@@ -460,7 +477,7 @@ static const struct file_operations mwave_fops = {
        .owner          = THIS_MODULE,
        .read           = mwave_read,
        .write          = mwave_write,
-       .ioctl          = mwave_ioctl,
+       .unlocked_ioctl = mwave_ioctl,
        .open           = mwave_open,
        .release        = mwave_close
 };
index 8eca61e0a19c46a91f2e3d18328ca6a208677d77..7e0d530e2e07f151e93fa0a0b39fc9514a2b9b83 100644 (file)
@@ -147,4 +147,6 @@ typedef struct _MWAVE_DEVICE_DATA {
 
 } MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA;
 
+extern MWAVE_DEVICE_DATA mwave_s_mdd;
+
 #endif
index f282976daaacfe8e6da245071757c9d552f0fbad..c68969708068a0f8472b611af2bddb38a3411632 100644 (file)
@@ -57,8 +57,6 @@
 #include "3780i.h"
 #include "mwavepub.h"
 
-extern MWAVE_DEVICE_DATA mwave_s_mdd;
-
 static unsigned short s_ausThinkpadIrqToField[16] =
        { 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004,
        0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 };
index 4c756bbba94831aafa3895853394409688c896c6..e30575e87648d4efa42b18e444732820281ff71e 100644 (file)
@@ -16,7 +16,6 @@
  *     Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox
  *     <alan@redhat.com>. The original 1.8 code is available on www.moxa.com.
  *     - Fixed x86_64 cleanness
- *     - Fixed sleep with spinlock held in mxser_send_break
  */
 
 #include <linux/module.h>
 
 #define        MXSER_VERSION   "2.0.4"         /* 1.12 */
 #define        MXSERMAJOR       174
-#define        MXSERCUMAJOR     175
 
 #define MXSER_BOARDS           4       /* Max. boards */
 #define MXSER_PORTS_PER_BOARD  8       /* Max. ports per board */
 #define MXSER_PORTS            (MXSER_BOARDS * MXSER_PORTS_PER_BOARD)
 #define MXSER_ISR_PASS_LIMIT   100
 
-#define        MXSER_ERR_IOADDR        -1
-#define        MXSER_ERR_IRQ           -2
-#define        MXSER_ERR_IRQ_CONFLIT   -3
-#define        MXSER_ERR_VECTOR        -4
-
 /*CheckIsMoxaMust return value*/
 #define MOXA_OTHER_UART                0x00
 #define MOXA_MUST_MU150_HWID   0x01
@@ -179,14 +172,15 @@ static struct pci_device_id mxser_pcibrds[] = {
 };
 MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
 
-static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
+static unsigned long ioaddr[MXSER_BOARDS];
 static int ttymajor = MXSERMAJOR;
 
 /* Variables for insmod */
 
 MODULE_AUTHOR("Casper Yang");
 MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
-module_param_array(ioaddr, int, NULL, 0);
+module_param_array(ioaddr, ulong, NULL, 0);
+MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board");
 module_param(ttymajor, int, 0);
 MODULE_LICENSE("GPL");
 
@@ -196,7 +190,6 @@ struct mxser_log {
        unsigned long txcnt[MXSER_PORTS];
 };
 
-
 struct mxser_mon {
        unsigned long rxcnt;
        unsigned long txcnt;
@@ -287,19 +280,9 @@ struct mxser_mstatus {
        int dcd;
 };
 
-static struct mxser_mstatus GMStatus[MXSER_PORTS];
-
-static int mxserBoardCAP[MXSER_BOARDS] = {
-       0, 0, 0, 0
-       /*  0x180, 0x280, 0x200, 0x320 */
-};
-
 static struct mxser_board mxser_boards[MXSER_BOARDS];
 static struct tty_driver *mxvar_sdriver;
 static struct mxser_log mxvar_log;
-static int mxvar_diagflag;
-static unsigned char mxser_msr[MXSER_PORTS + 1];
-static struct mxser_mon_ext mon_data_ext;
 static int mxser_set_baud_method[MXSER_PORTS + 1];
 
 static void mxser_enable_must_enchance_mode(unsigned long baseio)
@@ -543,6 +526,7 @@ static void process_txrx_fifo(struct mxser_port *info)
 
 static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
 {
+       static unsigned char mxser_msr[MXSER_PORTS + 1];
        unsigned char status = 0;
 
        status = inb(baseaddr + UART_MSR);
@@ -1319,13 +1303,9 @@ static void mxser_flush_chars(struct tty_struct *tty)
        struct mxser_port *info = tty->driver_data;
        unsigned long flags;
 
-       if (info->xmit_cnt <= 0 ||
-                       tty->stopped ||
-                       !info->port.xmit_buf ||
-                       (tty->hw_stopped &&
-                        (info->type != PORT_16550A) &&
-                        (!info->board->chip_flag)
-                       ))
+       if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf ||
+                       (tty->hw_stopped && info->type != PORT_16550A &&
+                        !info->board->chip_flag))
                return;
 
        spin_lock_irqsave(&info->slock, flags);
@@ -1343,9 +1323,7 @@ static int mxser_write_room(struct tty_struct *tty)
        int ret;
 
        ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
-       if (ret < 0)
-               ret = 0;
-       return ret;
+       return ret < 0 ? 0 : ret;
 }
 
 static int mxser_chars_in_buffer(struct tty_struct *tty)
@@ -1634,6 +1612,8 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 
        switch (cmd) {
        case MOXA_GET_MAJOR:
+               printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl %x, fix "
+                               "your userspace\n", current->comm, cmd);
                return put_user(ttymajor, (int __user *)argp);
 
        case MOXA_CHKPORTENABLE:
@@ -1651,62 +1631,60 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
                        ret = -EFAULT;
                unlock_kernel();
                return ret;
-       case MOXA_GETMSTATUS:
+       case MOXA_GETMSTATUS: {
+               struct mxser_mstatus ms, __user *msu = argp;
                lock_kernel();
                for (i = 0; i < MXSER_BOARDS; i++)
                        for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
                                port = &mxser_boards[i].ports[j];
+                               memset(&ms, 0, sizeof(ms));
 
-                               GMStatus[i].ri = 0;
-                               if (!port->ioaddr) {
-                                       GMStatus[i].dcd = 0;
-                                       GMStatus[i].dsr = 0;
-                                       GMStatus[i].cts = 0;
-                                       continue;
-                               }
+                               if (!port->ioaddr)
+                                       goto copy;
 
                                if (!port->port.tty || !port->port.tty->termios)
-                                       GMStatus[i].cflag =
-                                               port->normal_termios.c_cflag;
+                                       ms.cflag = port->normal_termios.c_cflag;
                                else
-                                       GMStatus[i].cflag =
-                                               port->port.tty->termios->c_cflag;
+                                       ms.cflag = port->port.tty->termios->c_cflag;
 
                                status = inb(port->ioaddr + UART_MSR);
-                               if (status & 0x80 /*UART_MSR_DCD */ )
-                                       GMStatus[i].dcd = 1;
-                               else
-                                       GMStatus[i].dcd = 0;
-
-                               if (status & 0x20 /*UART_MSR_DSR */ )
-                                       GMStatus[i].dsr = 1;
-                               else
-                                       GMStatus[i].dsr = 0;
-
-
-                               if (status & 0x10 /*UART_MSR_CTS */ )
-                                       GMStatus[i].cts = 1;
-                               else
-                                       GMStatus[i].cts = 0;
+                               if (status & UART_MSR_DCD)
+                                       ms.dcd = 1;
+                               if (status & UART_MSR_DSR)
+                                       ms.dsr = 1;
+                               if (status & UART_MSR_CTS)
+                                       ms.cts = 1;
+                       copy:
+                               if (copy_to_user(msu, &ms, sizeof(ms))) {
+                                       unlock_kernel();
+                                       return -EFAULT;
+                               }
+                               msu++;
                        }
                unlock_kernel();
-               if (copy_to_user(argp, GMStatus,
-                               sizeof(struct mxser_mstatus) * MXSER_PORTS))
-                       return -EFAULT;
                return 0;
+       }
        case MOXA_ASPP_MON_EXT: {
-               int p, shiftbit;
-               unsigned long opmode;
-               unsigned cflag, iflag;
+               struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */
+               unsigned int cflag, iflag, p;
+               u8 opmode;
+
+               me = kzalloc(sizeof(*me), GFP_KERNEL);
+               if (!me)
+                       return -ENOMEM;
 
                lock_kernel();
-               for (i = 0; i < MXSER_BOARDS; i++) {
-                       for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
+               for (i = 0, p = 0; i < MXSER_BOARDS; i++) {
+                       for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) {
+                               if (p >= ARRAY_SIZE(me->rx_cnt)) {
+                                       i = MXSER_BOARDS;
+                                       break;
+                               }
                                port = &mxser_boards[i].ports[j];
                                if (!port->ioaddr)
                                        continue;
 
-                               status = mxser_get_msr(port->ioaddr, 0, i);
+                               status = mxser_get_msr(port->ioaddr, 0, p);
 
                                if (status & UART_MSR_TERI)
                                        port->icount.rng++;
@@ -1718,16 +1696,13 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
                                        port->icount.cts++;
 
                                port->mon_data.modem_status = status;
-                               mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt;
-                               mon_data_ext.tx_cnt[i] = port->mon_data.txcnt;
-                               mon_data_ext.up_rxcnt[i] =
-                                       port->mon_data.up_rxcnt;
-                               mon_data_ext.up_txcnt[i] =
-                                       port->mon_data.up_txcnt;
-                               mon_data_ext.modem_status[i] =
+                               me->rx_cnt[p] = port->mon_data.rxcnt;
+                               me->tx_cnt[p] = port->mon_data.txcnt;
+                               me->up_rxcnt[p] = port->mon_data.up_rxcnt;
+                               me->up_txcnt[p] = port->mon_data.up_txcnt;
+                               me->modem_status[p] =
                                        port->mon_data.modem_status;
-                               mon_data_ext.baudrate[i] =
-                                       tty_get_baud_rate(port->port.tty);
+                               me->baudrate[p] = tty_get_baud_rate(port->port.tty);
 
                                if (!port->port.tty || !port->port.tty->termios) {
                                        cflag = port->normal_termios.c_cflag;
@@ -1737,40 +1712,31 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
                                        iflag = port->port.tty->termios->c_iflag;
                                }
 
-                               mon_data_ext.databits[i] = cflag & CSIZE;
-
-                               mon_data_ext.stopbits[i] = cflag & CSTOPB;
-
-                               mon_data_ext.parity[i] =
-                                       cflag & (PARENB | PARODD | CMSPAR);
-
-                               mon_data_ext.flowctrl[i] = 0x00;
+                               me->databits[p] = cflag & CSIZE;
+                               me->stopbits[p] = cflag & CSTOPB;
+                               me->parity[p] = cflag & (PARENB | PARODD |
+                                               CMSPAR);
 
                                if (cflag & CRTSCTS)
-                                       mon_data_ext.flowctrl[i] |= 0x03;
+                                       me->flowctrl[p] |= 0x03;
 
                                if (iflag & (IXON | IXOFF))
-                                       mon_data_ext.flowctrl[i] |= 0x0C;
+                                       me->flowctrl[p] |= 0x0C;
 
                                if (port->type == PORT_16550A)
-                                       mon_data_ext.fifo[i] = 1;
-                               else
-                                       mon_data_ext.fifo[i] = 0;
+                                       me->fifo[p] = 1;
 
-                               p = i % 4;
-                               shiftbit = p * 2;
-                               opmode = inb(port->opmode_ioaddr) >> shiftbit;
+                               opmode = inb(port->opmode_ioaddr) >>
+                                               ((p % 4) * 2);
                                opmode &= OP_MODE_MASK;
-
-                               mon_data_ext.iftype[i] = opmode;
-
+                               me->iftype[p] = opmode;
                        }
                }
                unlock_kernel();
-               if (copy_to_user(argp, &mon_data_ext,
-                                       sizeof(mon_data_ext)))
-                       return -EFAULT;
-               return 0;
+               if (copy_to_user(argp, me, sizeof(*me)))
+                       ret = -EFAULT;
+               kfree(me);
+               return ret;
        }
        default:
                return -ENOIOCTLCMD;
@@ -1804,7 +1770,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
 {
        struct mxser_port *info = tty->driver_data;
        struct async_icount cnow;
-       struct serial_icounter_struct __user *p_cuser;
        unsigned long flags;
        void __user *argp = (void __user *)arg;
        int retval;
@@ -1884,30 +1849,26 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
         * NB: both 1->0 and 0->1 transitions are counted except for
         *     RI where only 0->1 is counted.
         */
-       case TIOCGICOUNT:
+       case TIOCGICOUNT: {
+               struct serial_icounter_struct icnt = { 0 };
                spin_lock_irqsave(&info->slock, flags);
                cnow = info->icount;
                spin_unlock_irqrestore(&info->slock, flags);
-               p_cuser = argp;
-               if (put_user(cnow.frame, &p_cuser->frame))
-                       return -EFAULT;
-               if (put_user(cnow.brk, &p_cuser->brk))
-                       return -EFAULT;
-               if (put_user(cnow.overrun, &p_cuser->overrun))
-                       return -EFAULT;
-               if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
-                       return -EFAULT;
-               if (put_user(cnow.parity, &p_cuser->parity))
-                       return -EFAULT;
-               if (put_user(cnow.rx, &p_cuser->rx))
-                       return -EFAULT;
-               if (put_user(cnow.tx, &p_cuser->tx))
-                       return -EFAULT;
-               put_user(cnow.cts, &p_cuser->cts);
-               put_user(cnow.dsr, &p_cuser->dsr);
-               put_user(cnow.rng, &p_cuser->rng);
-               put_user(cnow.dcd, &p_cuser->dcd);
-               return 0;
+
+               icnt.frame = cnow.frame;
+               icnt.brk = cnow.brk;
+               icnt.overrun = cnow.overrun;
+               icnt.buf_overrun = cnow.buf_overrun;
+               icnt.parity = cnow.parity;
+               icnt.rx = cnow.rx;
+               icnt.tx = cnow.tx;
+               icnt.cts = cnow.cts;
+               icnt.dsr = cnow.dsr;
+               icnt.rng = cnow.rng;
+               icnt.dcd = cnow.dcd;
+
+               return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
+       }
        case MOXA_HighSpeedOn:
                return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
        case MOXA_SDS_RSTICOUNTER:
@@ -2503,7 +2464,8 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
        unsigned int i;
        int retval;
 
-       printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud);
+       printk(KERN_INFO "mxser: max. baud rate = %d bps\n",
+                       brd->ports[0].max_baud);
 
        for (i = 0; i < brd->info->nports; i++) {
                info = &brd->ports[i];
@@ -2586,28 +2548,32 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
                irq = regs[9] & 0xF000;
                irq = irq | (irq >> 4);
                if (irq != (regs[9] & 0xFF00))
-                       return MXSER_ERR_IRQ_CONFLIT;
+                       goto err_irqconflict;
        } else if (brd->info->nports == 4) {
                irq = regs[9] & 0xF000;
                irq = irq | (irq >> 4);
                irq = irq | (irq >> 8);
                if (irq != regs[9])
-                       return MXSER_ERR_IRQ_CONFLIT;
+                       goto err_irqconflict;
        } else if (brd->info->nports == 8) {
                irq = regs[9] & 0xF000;
                irq = irq | (irq >> 4);
                irq = irq | (irq >> 8);
                if ((irq != regs[9]) || (irq != regs[10]))
-                       return MXSER_ERR_IRQ_CONFLIT;
+                       goto err_irqconflict;
        }
 
-       if (!irq)
-               return MXSER_ERR_IRQ;
+       if (!irq) {
+               printk(KERN_ERR "mxser: interrupt number unset\n");
+               return -EIO;
+       }
        brd->irq = ((int)(irq & 0xF000) >> 12);
        for (i = 0; i < 8; i++)
                brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8;
-       if ((regs[12] & 0x80) == 0)
-               return MXSER_ERR_VECTOR;
+       if ((regs[12] & 0x80) == 0) {
+               printk(KERN_ERR "mxser: invalid interrupt vector\n");
+               return -EIO;
+       }
        brd->vector = (int)regs[11];    /* interrupt vector */
        if (id == 1)
                brd->vector_mask = 0x00FF;
@@ -2634,13 +2600,26 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
        else
                brd->uart_type = PORT_16450;
        if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports,
-                       "mxser(IO)"))
-               return MXSER_ERR_IOADDR;
+                       "mxser(IO)")) {
+               printk(KERN_ERR "mxser: can't request ports I/O region: "
+                               "0x%.8lx-0x%.8lx\n",
+                               brd->ports[0].ioaddr, brd->ports[0].ioaddr +
+                               8 * brd->info->nports - 1);
+               return -EIO;
+       }
        if (!request_region(brd->vector, 1, "mxser(vector)")) {
                release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-               return MXSER_ERR_VECTOR;
+               printk(KERN_ERR "mxser: can't request interrupt vector region: "
+                               "0x%.8lx-0x%.8lx\n",
+                               brd->ports[0].ioaddr, brd->ports[0].ioaddr +
+                               8 * brd->info->nports - 1);
+               return -EIO;
        }
        return brd->info->nports;
+
+err_irqconflict:
+       printk(KERN_ERR "mxser: invalid interrupt number\n");
+       return -EIO;
 }
 
 static int __devinit mxser_probe(struct pci_dev *pdev,
@@ -2657,20 +2636,20 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
                        break;
 
        if (i >= MXSER_BOARDS) {
-               printk(KERN_ERR "Too many Smartio/Industio family boards found "
-                       "(maximum %d), board not configured\n", MXSER_BOARDS);
+               dev_err(&pdev->dev, "too many boards found (maximum %d), board "
+                               "not configured\n", MXSER_BOARDS);
                goto err;
        }
 
        brd = &mxser_boards[i];
        brd->idx = i * MXSER_PORTS_PER_BOARD;
-       printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n",
+       dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n",
                mxser_cards[ent->driver_data].name,
                pdev->bus->number, PCI_SLOT(pdev->devfn));
 
        retval = pci_enable_device(pdev);
        if (retval) {
-               printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n");
+               dev_err(&pdev->dev, "PCI enable failed\n");
                goto err;
        }
 
@@ -2772,11 +2751,8 @@ static struct pci_driver mxser_driver = {
 static int __init mxser_module_init(void)
 {
        struct mxser_board *brd;
-       unsigned long cap;
-       unsigned int i, m, isaloop;
-       int retval, b;
-
-       pr_debug("Loading module mxser ...\n");
+       unsigned int b, i, m;
+       int retval;
 
        mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
        if (!mxvar_sdriver)
@@ -2806,74 +2782,43 @@ static int __init mxser_module_init(void)
                goto err_put;
        }
 
-       mxvar_diagflag = 0;
-
-       m = 0;
        /* Start finding ISA boards here */
-       for (isaloop = 0; isaloop < 2; isaloop++)
-               for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
-                       if (!isaloop)
-                               cap = mxserBoardCAP[b]; /* predefined */
-                       else
-                               cap = ioaddr[b]; /* module param */
-
-                       if (!cap)
-                               continue;
+       for (m = 0, b = 0; b < MXSER_BOARDS; b++) {
+               if (!ioaddr[b])
+                       continue;
+
+               brd = &mxser_boards[m];
+               retval = mxser_get_ISA_conf(!ioaddr[b], brd);
+               if (retval <= 0) {
+                       brd->info = NULL;
+                       continue;
+               }
 
-                       brd = &mxser_boards[m];
-                       retval = mxser_get_ISA_conf(cap, brd);
-
-                       if (retval != 0)
-                               printk(KERN_INFO "Found MOXA %s board "
-                                       "(CAP=0x%x)\n",
-                                       brd->info->name, ioaddr[b]);
-
-                       if (retval <= 0) {
-                               if (retval == MXSER_ERR_IRQ)
-                                       printk(KERN_ERR "Invalid interrupt "
-                                               "number, board not "
-                                               "configured\n");
-                               else if (retval == MXSER_ERR_IRQ_CONFLIT)
-                                       printk(KERN_ERR "Invalid interrupt "
-                                               "number, board not "
-                                               "configured\n");
-                               else if (retval == MXSER_ERR_VECTOR)
-                                       printk(KERN_ERR "Invalid interrupt "
-                                               "vector, board not "
-                                               "configured\n");
-                               else if (retval == MXSER_ERR_IOADDR)
-                                       printk(KERN_ERR "Invalid I/O address, "
-                                               "board not configured\n");
-
-                               brd->info = NULL;
-                               continue;
-                       }
+               printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n",
+                               brd->info->name, ioaddr[b]);
 
-                       /* mxser_initbrd will hook ISR. */
-                       if (mxser_initbrd(brd, NULL) < 0) {
-                               brd->info = NULL;
-                               continue;
-                       }
+               /* mxser_initbrd will hook ISR. */
+               if (mxser_initbrd(brd, NULL) < 0) {
+                       brd->info = NULL;
+                       continue;
+               }
 
-                       brd->idx = m * MXSER_PORTS_PER_BOARD;
-                       for (i = 0; i < brd->info->nports; i++)
-                               tty_register_device(mxvar_sdriver, brd->idx + i,
-                                               NULL);
+               brd->idx = m * MXSER_PORTS_PER_BOARD;
+               for (i = 0; i < brd->info->nports; i++)
+                       tty_register_device(mxvar_sdriver, brd->idx + i, NULL);
 
-                       m++;
-               }
+               m++;
+       }
 
        retval = pci_register_driver(&mxser_driver);
        if (retval) {
-               printk(KERN_ERR "Can't register pci driver\n");
+               printk(KERN_ERR "mxser: can't register pci driver\n");
                if (!m) {
                        retval = -ENODEV;
                        goto err_unr;
                } /* else: we have some ISA cards under control */
        }
 
-       pr_debug("Done.\n");
-
        return 0;
 err_unr:
        tty_unregister_driver(mxvar_sdriver);
@@ -2886,8 +2831,6 @@ static void __exit mxser_module_exit(void)
 {
        unsigned int i, j;
 
-       pr_debug("Unloading module mxser ...\n");
-
        pci_unregister_driver(&mxser_driver);
 
        for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
@@ -2901,8 +2844,6 @@ static void __exit mxser_module_exit(void)
        for (i = 0; i < MXSER_BOARDS; i++)
                if (mxser_boards[i].info != NULL)
                        mxser_release_res(&mxser_boards[i], NULL, 1);
-
-       pr_debug("Done.\n");
 }
 
 module_init(mxser_module_init);
index ba012c2bdf7a3b8ceb136f32d0d24cede5037725..006be92ee3f3f9cf36ba5682c7819623aabef0f2 100644 (file)
@@ -122,35 +122,20 @@ static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cm
 static ssize_t flash_read(struct file *file, char __user *buf, size_t size,
                          loff_t *ppos)
 {
-       unsigned long p = *ppos;
-       unsigned int count = size;
-       int ret = 0;
+       ssize_t ret;
 
        if (flashdebug)
-               printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, "
-                      "buffer=%p, count=0x%X.\n", p, buf, count);
-
-       if (count)
-               ret = -ENXIO;
+               printk(KERN_DEBUG "flash_read: flash_read: offset=0x%llx, "
+                      "buffer=%p, count=0x%zx.\n", *ppos, buf, size);
+       /*
+        * We now lock against reads and writes. --rmk
+        */
+       if (mutex_lock_interruptible(&nwflash_mutex))
+               return -ERESTARTSYS;
 
-       if (p < gbFlashSize) {
-               if (count > gbFlashSize - p)
-                       count = gbFlashSize - p;
+       ret = simple_read_from_buffer(buf, size, ppos, (void *)FLASH_BASE, gbFlashSize);
+       mutex_unlock(&nwflash_mutex);
 
-               /*
-                * We now lock against reads and writes. --rmk
-                */
-               if (mutex_lock_interruptible(&nwflash_mutex))
-                       return -ERESTARTSYS;
-
-               ret = copy_to_user(buf, (void *)(FLASH_BASE + p), count);
-               if (ret == 0) {
-                       ret = count;
-                       *ppos += count;
-               } else
-                       ret = -EFAULT;
-               mutex_unlock(&nwflash_mutex);
-       }
        return ret;
 }
 
index 929101ecbae29c180889a1d10e8c7f0549bcd713..4c1820cad71230045624f002368c6c03efbd0061 100644 (file)
 static void ipw_send_setup_packet(struct ipw_hardware *hw);
 static void handle_received_SETUP_packet(struct ipw_hardware *ipw,
                                         unsigned int address,
-                                        unsigned char *data, int len,
+                                        const unsigned char *data, int len,
                                         int is_last);
 static void ipwireless_setup_timer(unsigned long data);
 static void handle_received_CTRL_packet(struct ipw_hardware *hw,
-               unsigned int channel_idx, unsigned char *data, int len);
+               unsigned int channel_idx, const unsigned char *data, int len);
 
 /*#define TIMING_DIAGNOSTICS*/
 
@@ -79,8 +79,7 @@ static void report_timing(void)
                timing_stats.last_report_time = jiffies;
                if (!first)
                        printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-                              ": %u us elapsed - read %lu bytes in %u us, "
-                              "wrote %lu bytes in %u us\n",
+                              ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n",
                               jiffies_to_usecs(since),
                               timing_stats.read_bytes,
                               jiffies_to_usecs(timing_stats.read_time),
@@ -133,29 +132,17 @@ enum {
 #define NL_FOLLOWING_PACKET_HEADER_SIZE    1
 
 struct nl_first_packet_header {
-#if defined(__BIG_ENDIAN_BITFIELD)
-       unsigned char packet_rank:2;
-       unsigned char address:3;
-       unsigned char protocol:3;
-#else
        unsigned char protocol:3;
        unsigned char address:3;
        unsigned char packet_rank:2;
-#endif
        unsigned char length_lsb;
        unsigned char length_msb;
 };
 
 struct nl_packet_header {
-#if defined(__BIG_ENDIAN_BITFIELD)
-       unsigned char packet_rank:2;
-       unsigned char address:3;
-       unsigned char protocol:3;
-#else
        unsigned char protocol:3;
        unsigned char address:3;
        unsigned char packet_rank:2;
-#endif
 };
 
 /* Value of 'packet_rank' above */
@@ -227,15 +214,12 @@ struct MEMINFREG {
        unsigned short memreg_tx_new;   /* TX2 (new) Register (R/W) */
 };
 
-#define IODMADPR 0x00          /* DMA Data Port Register (R/W) */
-
 #define CARD_PRESENT_VALUE (0xBEEFCAFEUL)
 
 #define MEMTX_TX                       0x0001
 #define MEMRX_RX                       0x0001
 #define MEMRX_RX_DONE                  0x0001
 #define MEMRX_PCINTACKK                0x0001
-#define MEMRX_MEMSPURIOUSINT           0x0001
 
 #define NL_NUM_OF_PRIORITIES       3
 #define NL_NUM_OF_PROTOCOLS        3
@@ -245,7 +229,7 @@ struct ipw_hardware {
        unsigned int base_port;
        short hw_version;
        unsigned short ll_mtu;
-       spinlock_t spinlock;
+       spinlock_t lock;
 
        int initializing;
        int init_loops;
@@ -386,26 +370,52 @@ static void dump_data_bytes(const char *type, const unsigned char *data,
                        length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES);
 }
 
-static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data,
+static void swap_packet_bitfield_to_le(unsigned char *data)
+{
+#ifdef __BIG_ENDIAN_BITFIELD
+       unsigned char tmp = *data, ret = 0;
+
+       /*
+        * transform bits from aa.bbb.ccc to ccc.bbb.aa
+        */
+       ret |= tmp & 0xc0 >> 6;
+       ret |= tmp & 0x38 >> 1;
+       ret |= tmp & 0x07 << 5;
+       *data = ret & 0xff;
+#endif
+}
+
+static void swap_packet_bitfield_from_le(unsigned char *data)
+{
+#ifdef __BIG_ENDIAN_BITFIELD
+       unsigned char tmp = *data, ret = 0;
+
+       /*
+        * transform bits from ccc.bbb.aa to aa.bbb.ccc
+        */
+       ret |= tmp & 0xe0 >> 5;
+       ret |= tmp & 0x1c << 1;
+       ret |= tmp & 0x03 << 6;
+       *data = ret & 0xff;
+#endif
+}
+
+static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data,
                            unsigned length)
 {
-       int i;
+       unsigned i;
        unsigned long flags;
 
        start_timing();
-
-       if (length == 0)
-               return 0;
-
-       if (length > hw->ll_mtu)
-               return -1;
+       BUG_ON(length > hw->ll_mtu);
 
        if (ipwireless_debug)
                dump_data_bytes("send", data, length);
 
-       spin_lock_irqsave(&hw->spinlock, flags);
+       spin_lock_irqsave(&hw->lock, flags);
 
        hw->tx_ready = 0;
+       swap_packet_bitfield_to_le(data);
 
        if (hw->hw_version == HW_VERSION_1) {
                outw((unsigned short) length, hw->base_port + IODWR);
@@ -414,7 +424,7 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data,
                        unsigned short d = data[i];
                        __le16 raw_data;
 
-                       if (likely(i + 1 < length))
+                       if (i + 1 < length)
                                d |= data[i + 1] << 8;
                        raw_data = cpu_to_le16(d);
                        outw(raw_data, hw->base_port + IODWR);
@@ -422,32 +432,30 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data,
 
                outw(DCR_TXDONE, hw->base_port + IODCR);
        } else if (hw->hw_version == HW_VERSION_2) {
-               outw((unsigned short) length, hw->base_port + IODMADPR);
+               outw((unsigned short) length, hw->base_port);
 
                for (i = 0; i < length; i += 2) {
                        unsigned short d = data[i];
                        __le16 raw_data;
 
-                       if ((i + 1 < length))
+                       if (i + 1 < length)
                                d |= data[i + 1] << 8;
                        raw_data = cpu_to_le16(d);
-                       outw(raw_data, hw->base_port + IODMADPR);
+                       outw(raw_data, hw->base_port);
                }
                while ((i & 3) != 2) {
-                       outw((unsigned short) 0xDEAD, hw->base_port + IODMADPR);
+                       outw((unsigned short) 0xDEAD, hw->base_port);
                        i += 2;
                }
                writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx);
        }
 
-       spin_unlock_irqrestore(&hw->spinlock, flags);
+       spin_unlock_irqrestore(&hw->lock, flags);
 
        end_write_timing(length);
-
-       return 0;
 }
 
-static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
+static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
 {
        unsigned short fragment_data_len;
        unsigned short data_left = packet->length - packet->offset;
@@ -462,6 +470,10 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
        if (data_left < fragment_data_len)
                fragment_data_len = data_left;
 
+       /*
+        * hdr_first is now in machine bitfield order, which will be swapped
+        * to le just before it goes to hw
+        */
        pkt.hdr_first.protocol = packet->protocol;
        pkt.hdr_first.address = packet->dest_addr;
        pkt.hdr_first.packet_rank = 0;
@@ -493,25 +505,23 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
                 */
                unsigned long flags;
 
-               spin_lock_irqsave(&hw->spinlock, flags);
+               spin_lock_irqsave(&hw->lock, flags);
                list_add(&packet->queue, &hw->tx_queue[0]);
                hw->tx_queued++;
-               spin_unlock_irqrestore(&hw->spinlock, flags);
+               spin_unlock_irqrestore(&hw->lock, flags);
        } else {
                if (packet->packet_callback)
                        packet->packet_callback(packet->callback_data,
                                        packet->length);
                kfree(packet);
        }
-
-       return 0;
 }
 
 static void ipw_setup_hardware(struct ipw_hardware *hw)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&hw->spinlock, flags);
+       spin_lock_irqsave(&hw->lock, flags);
        if (hw->hw_version == HW_VERSION_1) {
                /* Reset RX FIFO */
                outw(DCR_RXRESET, hw->base_port + IODCR);
@@ -530,7 +540,7 @@ static void ipw_setup_hardware(struct ipw_hardware *hw)
                csr |= 1;
                writew(csr, &hw->memregs_CCR->reg_config_and_status);
        }
-       spin_unlock_irqrestore(&hw->spinlock, flags);
+       spin_unlock_irqrestore(&hw->lock, flags);
 }
 
 /*
@@ -549,28 +559,23 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw,
        if (!packet) {
                unsigned long flags;
 
-               /*
-                * If this is the first fragment, then we will need to fetch a
-                * packet to put it in.
-                */
-               spin_lock_irqsave(&hw->spinlock, flags);
-               /* If we have one in our pool, then pull it out. */
+               spin_lock_irqsave(&hw->lock, flags);
                if (!list_empty(&hw->rx_pool)) {
                        packet = list_first_entry(&hw->rx_pool,
                                        struct ipw_rx_packet, queue);
-                       list_del(&packet->queue);
                        hw->rx_pool_size--;
-                       spin_unlock_irqrestore(&hw->spinlock, flags);
+                       spin_unlock_irqrestore(&hw->lock, flags);
+                       list_del(&packet->queue);
                } else {
-                       /* Otherwise allocate a new one. */
-                       static int min_capacity = 256;
+                       const int min_capacity =
+                               ipwireless_ppp_mru(hw->network) + 2;
                        int new_capacity;
 
-                       spin_unlock_irqrestore(&hw->spinlock, flags);
+                       spin_unlock_irqrestore(&hw->lock, flags);
                        new_capacity =
-                           minimum_free_space > min_capacity
-                           ? minimum_free_space
-                           : min_capacity;
+                               (minimum_free_space > min_capacity
+                                ? minimum_free_space
+                                : min_capacity);
                        packet = kmalloc(sizeof(struct ipw_rx_packet)
                                        + new_capacity, GFP_ATOMIC);
                        if (!packet)
@@ -580,10 +585,6 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw,
                packet->length = 0;
        }
 
-       /*
-        * If this packet does not have sufficient capacity for the data we
-        * want to add, then make it bigger.
-        */
        if (packet->length + minimum_free_space > packet->capacity) {
                struct ipw_rx_packet *old_packet = packet;
 
@@ -610,13 +611,15 @@ static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet)
                kfree(packet);
        else {
                hw->rx_pool_size++;
-               list_add_tail(&packet->queue, &hw->rx_pool);
+               list_add(&packet->queue, &hw->rx_pool);
        }
 }
 
 static void queue_received_packet(struct ipw_hardware *hw,
-                                 unsigned int protocol, unsigned int address,
-                                 unsigned char *data, int length, int is_last)
+                                 unsigned int protocol,
+                                 unsigned int address,
+                                 const unsigned char *data, int length,
+                                 int is_last)
 {
        unsigned int channel_idx = address - 1;
        struct ipw_rx_packet *packet = NULL;
@@ -658,9 +661,9 @@ static void queue_received_packet(struct ipw_hardware *hw,
                        packet = *assem;
                        *assem = NULL;
                        /* Count queued DATA bytes only */
-                       spin_lock_irqsave(&hw->spinlock, flags);
+                       spin_lock_irqsave(&hw->lock, flags);
                        hw->rx_bytes_queued += packet->length;
-                       spin_unlock_irqrestore(&hw->spinlock, flags);
+                       spin_unlock_irqrestore(&hw->lock, flags);
                }
        } else {
                /* If it's a CTRL packet, don't assemble, just queue it. */
@@ -682,13 +685,13 @@ static void queue_received_packet(struct ipw_hardware *hw,
         * network layer.
         */
        if (packet) {
-               spin_lock_irqsave(&hw->spinlock, flags);
+               spin_lock_irqsave(&hw->lock, flags);
                list_add_tail(&packet->queue, &hw->rx_queue);
                /* Block reception of incoming packets if queue is full. */
                hw->blocking_rx =
-                       hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE;
+                       (hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE);
 
-               spin_unlock_irqrestore(&hw->spinlock, flags);
+               spin_unlock_irqrestore(&hw->lock, flags);
                schedule_work(&hw->work_rx);
        }
 }
@@ -702,7 +705,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx)
            container_of(work_rx, struct ipw_hardware, work_rx);
        unsigned long flags;
 
-       spin_lock_irqsave(&hw->spinlock, flags);
+       spin_lock_irqsave(&hw->lock, flags);
        while (!list_empty(&hw->rx_queue)) {
                struct ipw_rx_packet *packet =
                        list_first_entry(&hw->rx_queue,
@@ -720,7 +723,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx)
                if (packet->protocol == TL_PROTOCOLID_COM_DATA) {
                        if (hw->network != NULL) {
                                /* If the network hasn't been disconnected. */
-                               spin_unlock_irqrestore(&hw->spinlock, flags);
+                               spin_unlock_irqrestore(&hw->lock, flags);
                                /*
                                 * This must run unlocked due to tty processing
                                 * and mutex locking
@@ -731,7 +734,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx)
                                                (unsigned char *)packet
                                                + sizeof(struct ipw_rx_packet),
                                                packet->length);
-                               spin_lock_irqsave(&hw->spinlock, flags);
+                               spin_lock_irqsave(&hw->lock, flags);
                        }
                        /* Count queued DATA bytes only */
                        hw->rx_bytes_queued -= packet->length;
@@ -755,15 +758,15 @@ static void ipw_receive_data_work(struct work_struct *work_rx)
                if (hw->shutting_down)
                        break;
        }
-       spin_unlock_irqrestore(&hw->spinlock, flags);
+       spin_unlock_irqrestore(&hw->lock, flags);
 }
 
 static void handle_received_CTRL_packet(struct ipw_hardware *hw,
                                        unsigned int channel_idx,
-                                       unsigned char *data, int len)
+                                       const unsigned char *data, int len)
 {
-       struct ipw_control_packet_body *body =
-               (struct ipw_control_packet_body *) data;
+       const struct ipw_control_packet_body *body =
+               (const struct ipw_control_packet_body *) data;
        unsigned int changed_mask;
 
        if (len != sizeof(struct ipw_control_packet_body)) {
@@ -805,13 +808,13 @@ static void handle_received_CTRL_packet(struct ipw_hardware *hw,
 }
 
 static void handle_received_packet(struct ipw_hardware *hw,
-                                  union nl_packet *packet,
+                                  const union nl_packet *packet,
                                   unsigned short len)
 {
        unsigned int protocol = packet->hdr.protocol;
        unsigned int address = packet->hdr.address;
        unsigned int header_length;
-       unsigned char *data;
+       const unsigned char *data;
        unsigned int data_len;
        int is_last = packet->hdr.packet_rank & NL_LAST_PACKET;
 
@@ -850,7 +853,7 @@ static void acknowledge_data_read(struct ipw_hardware *hw)
 static void do_receive_packet(struct ipw_hardware *hw)
 {
        unsigned len;
-       unsigned int i;
+       unsigned i;
        unsigned char pkt[LL_MTU_MAX];
 
        start_timing();
@@ -859,8 +862,7 @@ static void do_receive_packet(struct ipw_hardware *hw)
                len = inw(hw->base_port + IODRR);
                if (len > hw->ll_mtu) {
                        printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-                              ": received a packet of %u bytes - "
-                              "longer than the MTU!\n", len);
+                              ": received a packet of %u bytes - longer than the MTU!\n", len);
                        outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR);
                        return;
                }
@@ -873,18 +875,17 @@ static void do_receive_packet(struct ipw_hardware *hw)
                        pkt[i + 1] = (unsigned char) (data >> 8);
                }
        } else {
-               len = inw(hw->base_port + IODMADPR);
+               len = inw(hw->base_port);
                if (len > hw->ll_mtu) {
                        printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-                              ": received a packet of %u bytes - "
-                              "longer than the MTU!\n", len);
+                              ": received a packet of %u bytes - longer than the MTU!\n", len);
                        writew(MEMRX_PCINTACKK,
                                &hw->memory_info_regs->memreg_pc_interrupt_ack);
                        return;
                }
 
                for (i = 0; i < len; i += 2) {
-                       __le16 raw_data = inw(hw->base_port + IODMADPR);
+                       __le16 raw_data = inw(hw->base_port);
                        unsigned short data = le16_to_cpu(raw_data);
 
                        pkt[i] = (unsigned char) data;
@@ -892,13 +893,15 @@ static void do_receive_packet(struct ipw_hardware *hw)
                }
 
                while ((i & 3) != 2) {
-                       inw(hw->base_port + IODMADPR);
+                       inw(hw->base_port);
                        i += 2;
                }
        }
 
        acknowledge_data_read(hw);
 
+       swap_packet_bitfield_from_le(pkt);
+
        if (ipwireless_debug)
                dump_data_bytes("recv", pkt, len);
 
@@ -916,8 +919,7 @@ static int get_current_packet_priority(struct ipw_hardware *hw)
         * until setup is complete.
         */
        return (hw->to_setup || hw->initializing
-                       ? PRIO_SETUP + 1 :
-                       NL_NUM_OF_PRIORITIES);
+                       ? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES);
 }
 
 /*
@@ -928,17 +930,17 @@ static int get_packets_from_hw(struct ipw_hardware *hw)
        int received = 0;
        unsigned long flags;
 
-       spin_lock_irqsave(&hw->spinlock, flags);
+       spin_lock_irqsave(&hw->lock, flags);
        while (hw->rx_ready && !hw->blocking_rx) {
                received = 1;
                hw->rx_ready--;
-               spin_unlock_irqrestore(&hw->spinlock, flags);
+               spin_unlock_irqrestore(&hw->lock, flags);
 
                do_receive_packet(hw);
 
-               spin_lock_irqsave(&hw->spinlock, flags);
+               spin_lock_irqsave(&hw->lock, flags);
        }
-       spin_unlock_irqrestore(&hw->spinlock, flags);
+       spin_unlock_irqrestore(&hw->lock, flags);
 
        return received;
 }
@@ -954,7 +956,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
        int more_to_send = 0;
        unsigned long flags;
 
-       spin_lock_irqsave(&hw->spinlock, flags);
+       spin_lock_irqsave(&hw->lock, flags);
        if (hw->tx_queued && hw->tx_ready) {
                int priority;
                struct ipw_tx_packet *packet = NULL;
@@ -975,17 +977,17 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
                }
                if (!packet) {
                        hw->tx_queued = 0;
-                       spin_unlock_irqrestore(&hw->spinlock, flags);
+                       spin_unlock_irqrestore(&hw->lock, flags);
                        return 0;
                }
 
-               spin_unlock_irqrestore(&hw->spinlock, flags);
+               spin_unlock_irqrestore(&hw->lock, flags);
 
                /* Send */
                do_send_packet(hw, packet);
 
                /* Check if more to send */
-               spin_lock_irqsave(&hw->spinlock, flags);
+               spin_lock_irqsave(&hw->lock, flags);
                for (priority = 0; priority < priority_limit; priority++)
                        if (!list_empty(&hw->tx_queue[priority])) {
                                more_to_send = 1;
@@ -995,7 +997,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
                if (!more_to_send)
                        hw->tx_queued = 0;
        }
-       spin_unlock_irqrestore(&hw->spinlock, flags);
+       spin_unlock_irqrestore(&hw->lock, flags);
 
        return more_to_send;
 }
@@ -1008,9 +1010,9 @@ static void ipwireless_do_tasklet(unsigned long hw_)
        struct ipw_hardware *hw = (struct ipw_hardware *) hw_;
        unsigned long flags;
 
-       spin_lock_irqsave(&hw->spinlock, flags);
+       spin_lock_irqsave(&hw->lock, flags);
        if (hw->shutting_down) {
-               spin_unlock_irqrestore(&hw->spinlock, flags);
+               spin_unlock_irqrestore(&hw->lock, flags);
                return;
        }
 
@@ -1019,7 +1021,7 @@ static void ipwireless_do_tasklet(unsigned long hw_)
                 * Initial setup data sent to hardware
                 */
                hw->to_setup = 2;
-               spin_unlock_irqrestore(&hw->spinlock, flags);
+               spin_unlock_irqrestore(&hw->lock, flags);
 
                ipw_setup_hardware(hw);
                ipw_send_setup_packet(hw);
@@ -1030,7 +1032,7 @@ static void ipwireless_do_tasklet(unsigned long hw_)
                int priority_limit = get_current_packet_priority(hw);
                int again;
 
-               spin_unlock_irqrestore(&hw->spinlock, flags);
+               spin_unlock_irqrestore(&hw->lock, flags);
 
                do {
                        again = send_pending_packet(hw, priority_limit);
@@ -1068,16 +1070,16 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq,
                /* Transmit complete. */
                if (irqn & IR_TXINTR) {
                        ack |= IR_TXINTR;
-                       spin_lock_irqsave(&hw->spinlock, flags);
+                       spin_lock_irqsave(&hw->lock, flags);
                        hw->tx_ready = 1;
-                       spin_unlock_irqrestore(&hw->spinlock, flags);
+                       spin_unlock_irqrestore(&hw->lock, flags);
                }
                /* Received data */
                if (irqn & IR_RXINTR) {
                        ack |= IR_RXINTR;
-                       spin_lock_irqsave(&hw->spinlock, flags);
+                       spin_lock_irqsave(&hw->lock, flags);
                        hw->rx_ready++;
-                       spin_unlock_irqrestore(&hw->spinlock, flags);
+                       spin_unlock_irqrestore(&hw->lock, flags);
                }
                if (ack != 0) {
                        outw(ack, hw->base_port + IOIR);
@@ -1128,9 +1130,8 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
                        } else {
                                return IRQ_NONE;
                        }
-               } else {
+               } else
                        return IRQ_NONE;
-               }
        }
 
        /*
@@ -1149,9 +1150,9 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
                if (hw->serial_number_detected) {
                        if (memtx_serial != hw->last_memtx_serial) {
                                hw->last_memtx_serial = memtx_serial;
-                               spin_lock_irqsave(&hw->spinlock, flags);
+                               spin_lock_irqsave(&hw->lock, flags);
                                hw->rx_ready++;
-                               spin_unlock_irqrestore(&hw->spinlock, flags);
+                               spin_unlock_irqrestore(&hw->lock, flags);
                                rx = 1;
                        } else
                                /* Ignore 'Timer Recovery' duplicates. */
@@ -1166,18 +1167,18 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
                                printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
                                        ": memreg_tx serial num detected\n");
 
-                               spin_lock_irqsave(&hw->spinlock, flags);
+                               spin_lock_irqsave(&hw->lock, flags);
                                hw->rx_ready++;
-                               spin_unlock_irqrestore(&hw->spinlock, flags);
+                               spin_unlock_irqrestore(&hw->lock, flags);
                        }
                        rx = 1;
                }
        }
        if (memrxdone & MEMRX_RX_DONE) {
                writew(0, &hw->memory_info_regs->memreg_rx_done);
-               spin_lock_irqsave(&hw->spinlock, flags);
+               spin_lock_irqsave(&hw->lock, flags);
                hw->tx_ready = 1;
-               spin_unlock_irqrestore(&hw->spinlock, flags);
+               spin_unlock_irqrestore(&hw->lock, flags);
                tx = 1;
        }
        if (tx)
@@ -1195,8 +1196,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
                                        ": spurious interrupt - new_tx mode\n");
                        else {
                                printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
-                                       ": no valid memreg_tx value - "
-                                       "switching to the old memreg_tx\n");
+                                       ": no valid memreg_tx value - switching to the old memreg_tx\n");
                                hw->memreg_tx =
                                        &hw->memory_info_regs->memreg_tx_old;
                                try_mem_tx_old = 1;
@@ -1211,7 +1211,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
        return IRQ_HANDLED;
 }
 
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t ipwireless_interrupt(int irq, void *dev_id)
 {
        struct ipw_hardware *hw = dev_id;
 
@@ -1226,9 +1226,9 @@ static void flush_packets_to_hw(struct ipw_hardware *hw)
        int priority_limit;
        unsigned long flags;
 
-       spin_lock_irqsave(&hw->spinlock, flags);
+       spin_lock_irqsave(&hw->lock, flags);
        priority_limit = get_current_packet_priority(hw);
-       spin_unlock_irqrestore(&hw->spinlock, flags);
+       spin_unlock_irqrestore(&hw->lock, flags);
 
        while (send_pending_packet(hw, priority_limit));
 }
@@ -1238,10 +1238,10 @@ static void send_packet(struct ipw_hardware *hw, int priority,
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&hw->spinlock, flags);
+       spin_lock_irqsave(&hw->lock, flags);
        list_add_tail(&packet->queue, &hw->tx_queue[priority]);
        hw->tx_queued++;
-       spin_unlock_irqrestore(&hw->spinlock, flags);
+       spin_unlock_irqrestore(&hw->lock, flags);
 
        flush_packets_to_hw(hw);
 }
@@ -1291,21 +1291,20 @@ static void *alloc_ctrl_packet(int header_size,
 }
 
 int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx,
-                           unsigned char *data, unsigned int length,
+                           const unsigned char *data, unsigned int length,
                            void (*callback) (void *cb, unsigned int length),
                            void *callback_data)
 {
        struct ipw_tx_packet *packet;
 
-       packet = alloc_data_packet(length,
-                              (unsigned char) (channel_idx + 1),
-                              TL_PROTOCOLID_COM_DATA);
+       packet = alloc_data_packet(length, (channel_idx + 1),
+                       TL_PROTOCOLID_COM_DATA);
        if (!packet)
                return -ENOMEM;
        packet->packet_callback = callback;
        packet->callback_data = callback_data;
-       memcpy((unsigned char *) packet +
-                       sizeof(struct ipw_tx_packet), data, length);
+       memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data,
+                       length);
 
        send_packet(hw, PRIO_DATA, packet);
        return 0;
@@ -1321,12 +1320,11 @@ static int set_control_line(struct ipw_hardware *hw, int prio,
                protocolid = TL_PROTOCOLID_SETUP;
 
        packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet),
-                       (unsigned char) (channel_idx + 1),
-                       protocolid, line);
+                       (channel_idx + 1), protocolid, line);
        if (!packet)
                return -ENOMEM;
        packet->header.length = sizeof(struct ipw_control_packet_body);
-       packet->body.value = (unsigned char) (state == 0 ? 0 : 1);
+       packet->body.value = (state == 0 ? 0 : 1);
        send_packet(hw, prio, &packet->header);
        return 0;
 }
@@ -1504,8 +1502,7 @@ static void handle_setup_get_version_rsp(struct ipw_hardware *hw,
        if (vers_no == TL_SETUP_VERSION)
                __handle_setup_get_version_rsp(hw);
        else
-               printk(KERN_ERR
-                               IPWIRELESS_PCCARD_NAME
+               printk(KERN_ERR IPWIRELESS_PCCARD_NAME
                                ": invalid hardware version no %u\n",
                                (unsigned int) vers_no);
 }
@@ -1528,10 +1525,10 @@ static void ipw_send_setup_packet(struct ipw_hardware *hw)
 
 static void handle_received_SETUP_packet(struct ipw_hardware *hw,
                                         unsigned int address,
-                                        unsigned char *data, int len,
+                                        const unsigned char *data, int len,
                                         int is_last)
 {
-       union ipw_setup_rx_msg *rx_msg = (union ipw_setup_rx_msg *) data;
+       const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data;
 
        if (address != ADDR_SETUP_PROT) {
                printk(KERN_INFO IPWIRELESS_PCCARD_NAME
@@ -1629,7 +1626,7 @@ struct ipw_hardware *ipwireless_hardware_create(void)
 
        INIT_LIST_HEAD(&hw->rx_queue);
        INIT_LIST_HEAD(&hw->rx_pool);
-       spin_lock_init(&hw->spinlock);
+       spin_lock_init(&hw->lock);
        tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw);
        INIT_WORK(&hw->work_rx, ipw_receive_data_work);
        setup_timer(&hw->setup_timer, ipwireless_setup_timer,
@@ -1651,8 +1648,8 @@ void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
                enable_irq(hw->irq);
        }
        hw->base_port = base_port;
-       hw->hw_version = is_v2_card ? HW_VERSION_2 : HW_VERSION_1;
-       hw->ll_mtu = hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2;
+       hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1);
+       hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2);
        hw->memregs_CCR = (struct MEMCCR __iomem *)
                        ((unsigned short __iomem *) attr_memory + 0x200);
        hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory;
@@ -1695,10 +1692,10 @@ static void ipwireless_setup_timer(unsigned long data)
                if (is_card_present(hw)) {
                        unsigned long flags;
 
-                       spin_lock_irqsave(&hw->spinlock, flags);
+                       spin_lock_irqsave(&hw->lock, flags);
                        hw->to_setup = 1;
                        hw->tx_ready = 1;
-                       spin_unlock_irqrestore(&hw->spinlock, flags);
+                       spin_unlock_irqrestore(&hw->lock, flags);
                        tasklet_schedule(&hw->tasklet);
                }
 
index 19ce5eb266b19fcc5150c1b0d821547a493eda3d..90a8590e43b0b056ae86548b825dbdb6ad55c036 100644 (file)
@@ -34,14 +34,14 @@ struct ipw_network;
 
 struct ipw_hardware *ipwireless_hardware_create(void);
 void ipwireless_hardware_free(struct ipw_hardware *hw);
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t ipwireless_interrupt(int irq, void *dev_id);
 int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
                int state);
 int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
                int state);
 int ipwireless_send_packet(struct ipw_hardware *hw,
                            unsigned int channel_idx,
-                           unsigned char *data,
+                           const unsigned char *data,
                            unsigned int length,
                            void (*packet_sent_callback) (void *cb,
                                                          unsigned int length),
index cc7dcea2d2830599d05c955589456c14cf9aa37b..5eca7a99afe6c3daf1c793f4c0990e5125a72862 100644 (file)
@@ -49,7 +49,7 @@ static void ipwireless_detach(struct pcmcia_device *link);
 /* Debug mode: more verbose, print sent/recv bytes */
 int ipwireless_debug;
 int ipwireless_loopback;
-int ipwireless_out_queue = 1;
+int ipwireless_out_queue = 10;
 
 module_param_named(debug, ipwireless_debug, int, 0);
 module_param_named(loopback, ipwireless_loopback, int, 0);
@@ -57,7 +57,7 @@ module_param_named(out_queue, ipwireless_out_queue, int, 0);
 MODULE_PARM_DESC(debug, "switch on debug messages [0]");
 MODULE_PARM_DESC(loopback,
                "debug: enable ras_raw channel [0]");
-MODULE_PARM_DESC(out_queue, "debug: set size of outgoing queue [1]");
+MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]");
 
 /* Executes in process context. */
 static void signalled_reboot_work(struct work_struct *work_reboot)
@@ -88,8 +88,6 @@ static int config_ipwireless(struct ipw_dev *ipw)
        unsigned short buf[64];
        cisparse_t parse;
        unsigned short cor_value;
-       win_req_t request_attr_memory;
-       win_req_t request_common_memory;
        memreq_t memreq_attr_memory;
        memreq_t memreq_common_memory;
 
@@ -188,6 +186,9 @@ static int config_ipwireless(struct ipw_dev *ipw)
                goto exit0;
        }
 
+       request_region(link->io.BasePort1, link->io.NumPorts1,
+                       IPWIRELESS_PCCARD_NAME);
+
        /* memory settings */
 
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
@@ -214,16 +215,16 @@ static int config_ipwireless(struct ipw_dev *ipw)
        }
 
        if (parse.cftable_entry.mem.nwin > 0) {
-               request_common_memory.Attributes =
+               ipw->request_common_memory.Attributes =
                        WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-               request_common_memory.Base =
+               ipw->request_common_memory.Base =
                        parse.cftable_entry.mem.win[0].host_addr;
-               request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
-               if (request_common_memory.Size < 0x1000)
-                       request_common_memory.Size = 0x1000;
-               request_common_memory.AccessSpeed = 0;
+               ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
+               if (ipw->request_common_memory.Size < 0x1000)
+                       ipw->request_common_memory.Size = 0x1000;
+               ipw->request_common_memory.AccessSpeed = 0;
 
-               ret = pcmcia_request_window(&link, &request_common_memory,
+               ret = pcmcia_request_window(&link, &ipw->request_common_memory,
                                &ipw->handle_common_memory);
 
                if (ret != CS_SUCCESS) {
@@ -246,16 +247,18 @@ static int config_ipwireless(struct ipw_dev *ipw)
                ipw->is_v2_card =
                        parse.cftable_entry.mem.win[0].len == 0x100;
 
-               ipw->common_memory = ioremap(request_common_memory.Base,
-                               request_common_memory.Size);
+               ipw->common_memory = ioremap(ipw->request_common_memory.Base,
+                               ipw->request_common_memory.Size);
+               request_mem_region(ipw->request_common_memory.Base,
+                               ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME);
 
-               request_attr_memory.Attributes =
+               ipw->request_attr_memory.Attributes =
                        WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
-               request_attr_memory.Base = 0;
-               request_attr_memory.Size = 0;   /* this used to be 0x1000 */
-               request_attr_memory.AccessSpeed = 0;
+               ipw->request_attr_memory.Base = 0;
+               ipw->request_attr_memory.Size = 0;      /* this used to be 0x1000 */
+               ipw->request_attr_memory.AccessSpeed = 0;
 
-               ret = pcmcia_request_window(&link, &request_attr_memory,
+               ret = pcmcia_request_window(&link, &ipw->request_attr_memory,
                                &ipw->handle_attr_memory);
 
                if (ret != CS_SUCCESS) {
@@ -274,8 +277,10 @@ static int config_ipwireless(struct ipw_dev *ipw)
                        goto exit2;
                }
 
-               ipw->attr_memory = ioremap(request_attr_memory.Base,
-                               request_attr_memory.Size);
+               ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
+                               ipw->request_attr_memory.Size);
+               request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size,
+                               IPWIRELESS_PCCARD_NAME);
        }
 
        INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
@@ -311,14 +316,13 @@ static int config_ipwireless(struct ipw_dev *ipw)
                        (unsigned int) link->irq.AssignedIRQ);
        if (ipw->attr_memory && ipw->common_memory)
                printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-                               ": attr memory 0x%08lx-0x%08lx, "
-                               "common memory 0x%08lx-0x%08lx\n",
-                               request_attr_memory.Base,
-                               request_attr_memory.Base
-                               + request_attr_memory.Size - 1,
-                               request_common_memory.Base,
-                               request_common_memory.Base
-                               + request_common_memory.Size - 1);
+                       ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n",
+                       ipw->request_attr_memory.Base,
+                       ipw->request_attr_memory.Base
+                       + ipw->request_attr_memory.Size - 1,
+                       ipw->request_common_memory.Base,
+                       ipw->request_common_memory.Base
+                       + ipw->request_common_memory.Size - 1);
 
        ipw->network = ipwireless_network_create(ipw->hardware);
        if (!ipw->network)
@@ -350,12 +354,16 @@ exit4:
        pcmcia_disable_device(link);
 exit3:
        if (ipw->attr_memory) {
+               release_mem_region(ipw->request_attr_memory.Base,
+                               ipw->request_attr_memory.Size);
                iounmap(ipw->attr_memory);
                pcmcia_release_window(ipw->handle_attr_memory);
                pcmcia_disable_device(link);
        }
 exit2:
        if (ipw->common_memory) {
+               release_mem_region(ipw->request_common_memory.Base,
+                               ipw->request_common_memory.Size);
                iounmap(ipw->common_memory);
                pcmcia_release_window(ipw->handle_common_memory);
        }
@@ -367,19 +375,25 @@ exit0:
 
 static void release_ipwireless(struct ipw_dev *ipw)
 {
-       struct pcmcia_device *link = ipw->link;
-
-       pcmcia_disable_device(link);
+       pcmcia_disable_device(ipw->link);
 
-       if (ipw->common_memory)
+       if (ipw->common_memory) {
+               release_mem_region(ipw->request_common_memory.Base,
+                               ipw->request_common_memory.Size);
                iounmap(ipw->common_memory);
-       if (ipw->attr_memory)
+       }
+       if (ipw->attr_memory) {
+               release_mem_region(ipw->request_attr_memory.Base,
+                               ipw->request_attr_memory.Size);
                iounmap(ipw->attr_memory);
+       }
        if (ipw->common_memory)
                pcmcia_release_window(ipw->handle_common_memory);
        if (ipw->attr_memory)
                pcmcia_release_window(ipw->handle_attr_memory);
-       pcmcia_disable_device(link);
+
+       /* Break the link with Card Services */
+       pcmcia_disable_device(ipw->link);
 }
 
 /*
@@ -437,10 +451,6 @@ static void ipwireless_detach(struct pcmcia_device *link)
 
        release_ipwireless(ipw);
 
-       /* Break the link with Card Services */
-       if (link)
-               pcmcia_disable_device(link);
-
        if (ipw->tty != NULL)
                ipwireless_tty_free(ipw->tty);
        if (ipw->network != NULL)
index 1bfdcc8d47d63300398d325a00699b28d655a250..0e0363af9ab240f55ad34edc0cb1b672417d3b53 100644 (file)
@@ -45,10 +45,15 @@ struct ipw_tty;
 struct ipw_dev {
        struct pcmcia_device *link;
        int is_v2_card;
+
        window_handle_t handle_attr_memory;
        void __iomem *attr_memory;
+       win_req_t request_attr_memory;
+
        window_handle_t handle_common_memory;
        void __iomem *common_memory;
+       win_req_t request_common_memory;
+
        dev_node_t nodes[2];
        /* Reference to attribute memory, containing CIS data */
        void *attribute_memory;
index fe914d34f7f6f63e10e452c775d364b1d2ba1930..590762a7f21790d64ea2b65725ff2a88902b1946 100644 (file)
@@ -29,7 +29,6 @@
 #include "main.h"
 #include "tty.h"
 
-#define MAX_OUTGOING_PACKETS_QUEUED   ipwireless_out_queue
 #define MAX_ASSOCIATED_TTYS 2
 
 #define SC_RCV_BITS     (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
@@ -46,7 +45,7 @@ struct ipw_network {
        /* Number of packets queued up in hardware module. */
        int outgoing_packets_queued;
        /* Spinlock to avoid interrupts during shutdown */
-       spinlock_t spinlock;
+       spinlock_t lock;
        struct mutex close_lock;
 
        /* PPP ioctl data, not actually used anywere */
@@ -68,20 +67,20 @@ static void notify_packet_sent(void *callback_data, unsigned int packet_length)
        struct ipw_network *network = callback_data;
        unsigned long flags;
 
-       spin_lock_irqsave(&network->spinlock, flags);
+       spin_lock_irqsave(&network->lock, flags);
        network->outgoing_packets_queued--;
        if (network->ppp_channel != NULL) {
                if (network->ppp_blocked) {
                        network->ppp_blocked = 0;
-                       spin_unlock_irqrestore(&network->spinlock, flags);
+                       spin_unlock_irqrestore(&network->lock, flags);
                        ppp_output_wakeup(network->ppp_channel);
                        if (ipwireless_debug)
-                               printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+                               printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
                                       ": ppp unblocked\n");
                } else
-                       spin_unlock_irqrestore(&network->spinlock, flags);
+                       spin_unlock_irqrestore(&network->lock, flags);
        } else
-               spin_unlock_irqrestore(&network->spinlock, flags);
+               spin_unlock_irqrestore(&network->lock, flags);
 }
 
 /*
@@ -93,8 +92,8 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
        struct ipw_network *network = ppp_channel->private;
        unsigned long flags;
 
-       spin_lock_irqsave(&network->spinlock, flags);
-       if (network->outgoing_packets_queued < MAX_OUTGOING_PACKETS_QUEUED) {
+       spin_lock_irqsave(&network->lock, flags);
+       if (network->outgoing_packets_queued < ipwireless_out_queue) {
                unsigned char *buf;
                static unsigned char header[] = {
                        PPP_ALLSTATIONS, /* 0xff */
@@ -103,7 +102,7 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
                int ret;
 
                network->outgoing_packets_queued++;
-               spin_unlock_irqrestore(&network->spinlock, flags);
+               spin_unlock_irqrestore(&network->lock, flags);
 
                /*
                 * If we have the requested amount of headroom in the skb we
@@ -144,7 +143,9 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
                 * needs to be unblocked once we are ready to send.
                 */
                network->ppp_blocked = 1;
-               spin_unlock_irqrestore(&network->spinlock, flags);
+               spin_unlock_irqrestore(&network->lock, flags);
+               if (ipwireless_debug)
+                       printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n");
                return 0;
        }
 }
@@ -249,11 +250,11 @@ static void do_go_online(struct work_struct *work_go_online)
                                work_go_online);
        unsigned long flags;
 
-       spin_lock_irqsave(&network->spinlock, flags);
+       spin_lock_irqsave(&network->lock, flags);
        if (!network->ppp_channel) {
                struct ppp_channel *channel;
 
-               spin_unlock_irqrestore(&network->spinlock, flags);
+               spin_unlock_irqrestore(&network->lock, flags);
                channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
                if (!channel) {
                        printk(KERN_ERR IPWIRELESS_PCCARD_NAME
@@ -273,10 +274,10 @@ static void do_go_online(struct work_struct *work_go_online)
                network->xaccm[3] = 0x60000000U;
                network->raccm = ~0U;
                ppp_register_channel(channel);
-               spin_lock_irqsave(&network->spinlock, flags);
+               spin_lock_irqsave(&network->lock, flags);
                network->ppp_channel = channel;
        }
-       spin_unlock_irqrestore(&network->spinlock, flags);
+       spin_unlock_irqrestore(&network->lock, flags);
 }
 
 static void do_go_offline(struct work_struct *work_go_offline)
@@ -287,16 +288,16 @@ static void do_go_offline(struct work_struct *work_go_offline)
        unsigned long flags;
 
        mutex_lock(&network->close_lock);
-       spin_lock_irqsave(&network->spinlock, flags);
+       spin_lock_irqsave(&network->lock, flags);
        if (network->ppp_channel != NULL) {
                struct ppp_channel *channel = network->ppp_channel;
 
                network->ppp_channel = NULL;
-               spin_unlock_irqrestore(&network->spinlock, flags);
+               spin_unlock_irqrestore(&network->lock, flags);
                mutex_unlock(&network->close_lock);
                ppp_unregister_channel(channel);
        } else {
-               spin_unlock_irqrestore(&network->spinlock, flags);
+               spin_unlock_irqrestore(&network->lock, flags);
                mutex_unlock(&network->close_lock);
        }
 }
@@ -381,18 +382,18 @@ void ipwireless_network_packet_received(struct ipw_network *network,
                         * the PPP layer.
                         */
                        mutex_lock(&network->close_lock);
-                       spin_lock_irqsave(&network->spinlock, flags);
+                       spin_lock_irqsave(&network->lock, flags);
                        if (network->ppp_channel != NULL) {
                                struct sk_buff *skb;
 
-                               spin_unlock_irqrestore(&network->spinlock,
+                               spin_unlock_irqrestore(&network->lock,
                                                flags);
 
                                /* Send the data to the ppp_generic module. */
                                skb = ipw_packet_received_skb(data, length);
                                ppp_input(network->ppp_channel, skb);
                        } else
-                               spin_unlock_irqrestore(&network->spinlock,
+                               spin_unlock_irqrestore(&network->lock,
                                                flags);
                        mutex_unlock(&network->close_lock);
                }
@@ -410,7 +411,7 @@ struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
        if (!network)
                return NULL;
 
-       spin_lock_init(&network->spinlock);
+       spin_lock_init(&network->lock);
        mutex_init(&network->close_lock);
 
        network->hardware = hw;
@@ -478,10 +479,10 @@ int ipwireless_ppp_channel_index(struct ipw_network *network)
        int ret = -1;
        unsigned long flags;
 
-       spin_lock_irqsave(&network->spinlock, flags);
+       spin_lock_irqsave(&network->lock, flags);
        if (network->ppp_channel != NULL)
                ret = ppp_channel_index(network->ppp_channel);
-       spin_unlock_irqrestore(&network->spinlock, flags);
+       spin_unlock_irqrestore(&network->lock, flags);
 
        return ret;
 }
@@ -491,10 +492,15 @@ int ipwireless_ppp_unit_number(struct ipw_network *network)
        int ret = -1;
        unsigned long flags;
 
-       spin_lock_irqsave(&network->spinlock, flags);
+       spin_lock_irqsave(&network->lock, flags);
        if (network->ppp_channel != NULL)
                ret = ppp_unit_number(network->ppp_channel);
-       spin_unlock_irqrestore(&network->spinlock, flags);
+       spin_unlock_irqrestore(&network->lock, flags);
 
        return ret;
 }
+
+int ipwireless_ppp_mru(const struct ipw_network *network)
+{
+       return network->mru;
+}
index ccacd26fc7efdf3c9836e80aa3a536190359a809..561f765b333419fa1aa4a48095efe734b89efd8e 100644 (file)
@@ -48,5 +48,6 @@ void ipwireless_ppp_open(struct ipw_network *net);
 void ipwireless_ppp_close(struct ipw_network *net);
 int ipwireless_ppp_channel_index(struct ipw_network *net);
 int ipwireless_ppp_unit_number(struct ipw_network *net);
+int ipwireless_ppp_mru(const struct ipw_network *net);
 
 #endif
index 42f3815c5ce3cac25437c435519c2b61d87f0d8f..b1414507997c663db2c56afbeaaa338846ede37c 100644 (file)
@@ -259,7 +259,7 @@ static int ipw_write(struct tty_struct *linux_tty,
        }
 
        ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS,
-                              (unsigned char *) buf, count,
+                              buf, count,
                               ipw_write_packet_sent_callback, tty);
        if (ret == -1) {
                mutex_unlock(&tty->ipw_tty_mutex);
index 7af7a7e6b9c2e570ff53eff4152e5f61d6cf7738..bee39fdfba738de8a11429a1d2c57caa7b99cc26 100644 (file)
@@ -67,7 +67,7 @@
 #include <linux/major.h>
 #include <linux/ppdev.h>
 #include <linux/smp_lock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define PP_VERSION "ppdev: user-space parallel port driver"
 #define CHRDEV "ppdev"
@@ -328,10 +328,9 @@ static enum ieee1284_phase init_phase (int mode)
        return IEEE1284_PH_FWD_IDLE;
 }
 
-static int pp_ioctl(struct inode *inode, struct file *file,
-                   unsigned int cmd, unsigned long arg)
+static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       unsigned int minor = iminor(inode);
+       unsigned int minor = iminor(file->f_path.dentry->d_inode);
        struct pp_struct *pp = file->private_data;
        struct parport * port;
        void __user *argp = (void __user *)arg;
@@ -634,6 +633,15 @@ static int pp_ioctl(struct inode *inode, struct file *file,
        return 0;
 }
 
+static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       long ret;
+       lock_kernel();
+       ret = pp_do_ioctl(file, cmd, arg);
+       unlock_kernel();
+       return ret;
+}
+
 static int pp_open (struct inode * inode, struct file * file)
 {
        unsigned int minor = iminor(inode);
@@ -745,7 +753,7 @@ static const struct file_operations pp_fops = {
        .read           = pp_read,
        .write          = pp_write,
        .poll           = pp_poll,
-       .ioctl          = pp_ioctl,
+       .unlocked_ioctl = pp_ioctl,
        .open           = pp_open,
        .release        = pp_release,
 };
index 0cf98bd4f2d2438351357890a2cee00062b6c6da..e0d0e371909cd2f1c00d4e2f63fe8c8ae2c81bcc 100644 (file)
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/interrupt.h>
+#include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
 #include <linux/cryptohash.h>
index 0cdfee152916ffb7bab395049ca69fe47baea8ab..a8f68a3f14dd56e4beea33c06407f51d39cc62a1 100644 (file)
@@ -179,7 +179,7 @@ static int rio_set_real_termios(void *ptr);
 static void rio_hungup(void *ptr);
 static void rio_close(void *ptr);
 static int rio_chars_in_buffer(void *ptr);
-static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
+static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 static int rio_init_drivers(void);
 
 static void my_hd(void *addr, int len);
@@ -240,7 +240,7 @@ static struct real_driver rio_real_driver = {
 
 static const struct file_operations rio_fw_fops = {
        .owner = THIS_MODULE,
-       .ioctl = rio_fw_ioctl,
+       .unlocked_ioctl = rio_fw_ioctl,
 };
 
 static struct miscdevice rio_fw_device = {
@@ -560,13 +560,15 @@ static void rio_close(void *ptr)
 
 
 
-static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        int rc = 0;
        func_enter();
 
        /* The "dev" argument isn't used. */
+       lock_kernel();
        rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
+       unlock_kernel();
 
        func_exit();
        return rc;
index fa92a8af5a5a05fe62a98aadd327177006f52c16..d9799e2bcfbfb128dfc583866fbc40cfcc0d1184 100644 (file)
 #include <linux/wait.h>
 #include <linux/bcd.h>
 #include <linux/delay.h>
+#include <linux/smp_lock.h>
+#include <linux/uaccess.h>
 
 #include <asm/current.h>
-#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #ifdef CONFIG_X86
@@ -120,8 +121,6 @@ static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
        return 0;
 }
 #endif
-#else
-extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
 #endif
 
 /*
@@ -144,8 +143,8 @@ static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0);
 static ssize_t rtc_read(struct file *file, char __user *buf,
                        size_t count, loff_t *ppos);
 
-static int rtc_ioctl(struct inode *inode, struct file *file,
-                    unsigned int cmd, unsigned long arg);
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+static void rtc_get_rtc_time(struct rtc_time *rtc_tm);
 
 #ifdef RTC_IRQ
 static unsigned int rtc_poll(struct file *file, poll_table *wait);
@@ -237,7 +236,7 @@ static inline unsigned char rtc_is_updating(void)
  *     (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.)
  */
 
-irqreturn_t rtc_interrupt(int irq, void *dev_id)
+static irqreturn_t rtc_interrupt(int irq, void *dev_id)
 {
        /*
         *      Can be an alarm interrupt, update complete interrupt,
@@ -719,10 +718,13 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
                            &wtime, sizeof wtime) ? -EFAULT : 0;
 }
 
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-                    unsigned long arg)
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       return rtc_do_ioctl(cmd, arg, 0);
+       long ret;
+       lock_kernel();
+       ret = rtc_do_ioctl(cmd, arg, 0);
+       unlock_kernel();
+       return ret;
 }
 
 /*
@@ -915,7 +917,7 @@ static const struct file_operations rtc_fops = {
 #ifdef RTC_IRQ
        .poll           = rtc_poll,
 #endif
-       .ioctl          = rtc_ioctl,
+       .unlocked_ioctl = rtc_ioctl,
        .open           = rtc_open,
        .release        = rtc_release,
        .fasync         = rtc_fasync,
@@ -1302,7 +1304,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
 }
 #endif
 
-void rtc_get_rtc_time(struct rtc_time *rtc_tm)
+static void rtc_get_rtc_time(struct rtc_time *rtc_tm)
 {
        unsigned long uip_watchdog = jiffies, flags;
        unsigned char ctrl;
index 4ba3aec9e1cd0dc50444c05857467ade96a0fc4e..7b0c35207d9b4fb034b3414d6a9b4788830d7cac 100644 (file)
@@ -192,7 +192,7 @@ static inline void a2232_receive_char(struct a2232_port *port, int ch, int err)
        Maybe one could implement a more efficient version by not only
        transferring one character at a time.
 */
-       struct tty_struct *tty = port->gs.tty;
+       struct tty_struct *tty = port->gs.port.tty;
 
 #if 0
        switch(err) {
@@ -226,7 +226,7 @@ static void a2232_disable_tx_interrupts(void *ptr)
 
        /* Does this here really have to be? */
        local_irq_save(flags);
-       port->gs.flags &= ~GS_TX_INTEN;
+       port->gs.port.flags &= ~GS_TX_INTEN;
        local_irq_restore(flags);
 }
 
@@ -242,7 +242,7 @@ static void a2232_enable_tx_interrupts(void *ptr)
 
        /* Does this here really have to be? */
        local_irq_save(flags);
-       port->gs.flags |= GS_TX_INTEN;
+       port->gs.port.flags |= GS_TX_INTEN;
        local_irq_restore(flags);
 }
 
@@ -276,9 +276,9 @@ static void a2232_shutdown_port(void *ptr)
 
        local_irq_save(flags);
 
-       port->gs.flags &= ~GS_ACTIVE;
+       port->gs.port.flags &= ~GS_ACTIVE;
        
-       if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
+       if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) {
                /* Set DTR and RTS to Low, flush output.
                   The NetBSD driver "msc.c" does it this way. */
                stat->Command = (       (stat->Command & ~A2232CMD_CMask) | 
@@ -309,7 +309,7 @@ static int  a2232_set_real_termios(void *ptr)
        volatile struct a2232status *status;
        volatile struct a2232memory *mem;
 
-       if (!port->gs.tty || !port->gs.tty->termios) return 0;
+       if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
 
        status = a2232stat(port->which_a2232, port->which_port_on_a2232);
        mem = a2232mem(port->which_a2232);
@@ -345,7 +345,7 @@ static int  a2232_set_real_termios(void *ptr)
        }
        a2232_param |= rate;
 
-       cflag  = port->gs.tty->termios->c_cflag;
+       cflag  = port->gs.port.tty->termios->c_cflag;
 
        // get character size
        chsize = cflag & CSIZE;
@@ -382,7 +382,7 @@ static int  a2232_set_real_termios(void *ptr)
                the conventional way of inserting START/STOP characters
                by hand in throttle()/unthrottle().
        */
-       softflow = !!( port->gs.tty->termios->c_iflag & IXOFF );
+       softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF );
 
        // get Parity (Enabled/Disabled? If Enabled, Odd or Even?)
        parity = cflag & (PARENB | PARODD);
@@ -400,9 +400,9 @@ static int  a2232_set_real_termios(void *ptr)
        /*      Hmm. Maybe an own a2232_port structure
                member would be cleaner?        */
        if (cflag & CLOCAL)
-               port->gs.flags &= ~ASYNC_CHECK_CD;
+               port->gs.port.flags &= ~ASYNC_CHECK_CD;
        else
-               port->gs.flags |= ASYNC_CHECK_CD;
+               port->gs.port.flags |= ASYNC_CHECK_CD;
 
 
        /* Now we have all parameters and can go to set them: */
@@ -482,18 +482,18 @@ static int  a2232_open(struct tty_struct * tty, struct file * filp)
        port = &a2232_ports[line];
        
        tty->driver_data = port;
-       port->gs.tty = tty;
-       port->gs.count++;
+       port->gs.port.tty = tty;
+       port->gs.port.count++;
        retval = gs_init_port(&port->gs);
        if (retval) {
-               port->gs.count--;
+               port->gs.port.count--;
                return retval;
        }
-       port->gs.flags |= GS_ACTIVE;
+       port->gs.port.flags |= GS_ACTIVE;
        retval = gs_block_til_ready(port, filp);
 
        if (retval) {
-               port->gs.count--;
+               port->gs.port.count--;
                return retval;
        }
 
@@ -522,7 +522,7 @@ int ch, err, n, p;
                for (p = 0; p < NUMLINES; p++){ /* for every port on this board */
                        err = 0;
                        port = &a2232_ports[n*NUMLINES+p];
-                       if ( port->gs.flags & GS_ACTIVE ){ /* if the port is used */
+                       if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */
 
                                status = a2232stat(n,p);
 
@@ -577,8 +577,8 @@ int ch, err, n, p;
                                obuf = mem->OutBuf[p];
                                bufpos = status->OutHead;
                                while ( (port->gs.xmit_cnt > 0)         &&
-                                       (!port->gs.tty->stopped)        &&
-                                       (!port->gs.tty->hw_stopped) ){  /* While there are chars to transmit */
+                                       (!port->gs.port.tty->stopped)   &&
+                                       (!port->gs.port.tty->hw_stopped) ){     /* While there are chars to transmit */
                                        if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */
                                                ch = port->gs.xmit_buf[port->gs.xmit_tail];                                     /* get the next char to transmit */
                                                port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */
@@ -592,8 +592,8 @@ int ch, err, n, p;
                                status->OutHead = bufpos;
                                        
                                /* WakeUp if output buffer runs low */
-                               if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
-                                       tty_wakeup(port->gs.tty);
+                               if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
+                                       tty_wakeup(port->gs.port.tty);
                                }
                        } // if the port is used
                } // for every port on the board
@@ -613,16 +613,16 @@ int ch, err, n, p;
                                                struct a2232_port *port = &a2232_ports[n*7+p];
                                                port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */
 
-                                               if (!(port->gs.flags & ASYNC_CHECK_CD))
+                                               if (!(port->gs.port.flags & ASYNC_CHECK_CD))
                                                        ;       /* Don't report DCD changes */
                                                else if (port->cd_status) { // if DCD on: DCD went UP!
                                                        
                                                        /* Are we blocking in open?*/
-                                                       wake_up_interruptible(&port->gs.open_wait);
+                                                       wake_up_interruptible(&port->gs.port.open_wait);
                                                }
                                                else { // if DCD off: DCD went DOWN!
-                                                       if (port->gs.tty)
-                                                               tty_hangup (port->gs.tty);
+                                                       if (port->gs.port.tty)
+                                                               tty_hangup (port->gs.port.tty);
                                                }
                                                
                                        } // if CD changed for this port
@@ -655,8 +655,8 @@ static void a2232_init_portstructs(void)
 #ifdef NEW_WRITE_LOCKING
                mutex_init(&(port->gs.port_write_mutex));
 #endif
-               init_waitqueue_head(&port->gs.open_wait);
-               init_waitqueue_head(&port->gs.close_wait);
+               init_waitqueue_head(&port->gs.port.open_wait);
+               init_waitqueue_head(&port->gs.port.close_wait);
        }
 }
 
index b976248e10727dd7f8e8610dc02da65efa064828..19db1eb87c26fa22eb9e4f17d8b6ec384e6c021b 100644 (file)
@@ -1256,7 +1256,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
 static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct stlport  *portp;
-       unsigned int    ival;
        int             rc;
        void __user *argp = (void __user *)arg;
 
index 2162439bbe487544c589c6f0c054e6d849257a94..c385206f9db540caa925d615be1c1d4d566482f4 100644 (file)
@@ -286,8 +286,8 @@ static void sx_close(void *ptr);
 static int sx_chars_in_buffer(void *ptr);
 static int sx_init_board(struct sx_board *board);
 static int sx_init_portstructs(int nboards, int nports);
-static int sx_fw_ioctl(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg);
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
+                                               unsigned long arg);
 static int sx_init_drivers(void);
 
 static struct tty_driver *sx_driver;
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = {
 
 static const struct file_operations sx_fw_fops = {
        .owner = THIS_MODULE,
-       .ioctl = sx_fw_ioctl,
+       .unlocked_ioctl = sx_fw_ioctl,
 };
 
 static struct miscdevice sx_fw_device = {
@@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max)
 }
 #endif
 
-static int sx_fw_ioctl(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
+                                                       unsigned long arg)
 {
-       int rc = 0;
+       long rc = 0;
        int __user *descr = (int __user *)arg;
        int i;
        static struct sx_board *board = NULL;
@@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
 
        func_enter();
 
-#if 0
-       /* Removed superuser check: Sysops can use the permissions on the device
-          file to restrict access. Recommendation: Root only. (root.root 600) */
-       if (!capable(CAP_SYS_ADMIN)) {
+       if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
-       }
-#endif
+
+       lock_kernel();
 
        sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
 
@@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                for (i = 0; i < SX_NBOARDS; i++)
                        sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
                sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
+               unlock_kernel();
                return -EIO;
        }
 
        switch (cmd) {
        case SXIO_SET_BOARD:
                sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
+               rc = -EIO;
                if (arg >= SX_NBOARDS)
-                       return -EIO;
+                       break;
                sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
                if (!(boards[arg].flags & SX_BOARD_PRESENT))
-                       return -EIO;
+                       break;
                sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
                board = &boards[arg];
+               rc = 0;
+               /* FIXME: And this does ... nothing?? */
                break;
        case SXIO_GET_TYPE:
                rc = -ENOENT;   /* If we manage to miss one, return error. */
@@ -1746,7 +1747,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                        rc = SX_TYPE_SI;
                if (IS_EISA_BOARD(board))
                        rc = SX_TYPE_SI;
-               sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
+               sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
                break;
        case SXIO_DO_RAMTEST:
                if (sx_initialized)     /* Already initialized: better not ramtest the board.  */
@@ -1760,19 +1761,26 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                        rc = do_memtest(board, 0, 0x7ff8);
                        /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
                }
-               sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n",
-                          rc);
+               sx_dprintk(SX_DEBUG_FIRMWARE,
+                               "returning memtest result= %ld\n", rc);
                break;
        case SXIO_DOWNLOAD:
-               if (sx_initialized)     /* Already initialized */
-                       return -EEXIST;
-               if (!sx_reset(board))
-                       return -EIO;
+               if (sx_initialized) {/* Already initialized */
+                       rc = -EEXIST;
+                       break;
+               }
+               if (!sx_reset(board)) {
+                       rc = -EIO;
+                       break;
+               }
                sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
 
                tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
-               if (!tmp)
-                       return -ENOMEM;
+               if (!tmp) {
+                       rc = -ENOMEM;
+                       break;
+               }
+               /* FIXME: check returns */
                get_user(nbytes, descr++);
                get_user(offset, descr++);
                get_user(data, descr++);
@@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                                                (i + SX_CHUNK_SIZE > nbytes) ?
                                                nbytes - i : SX_CHUNK_SIZE)) {
                                        kfree(tmp);
-                                       return -EFAULT;
+                                       rc = -EFAULT;
+                                       break;
                                }
                                memcpy_toio(board->base2 + offset + i, tmp,
                                                (i + SX_CHUNK_SIZE > nbytes) ?
@@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                rc = sx_nports;
                break;
        case SXIO_INIT:
-               if (sx_initialized)     /* Already initialized */
-                       return -EEXIST;
+               if (sx_initialized) {   /* Already initialized */
+                       rc = -EEXIST;
+                       break;
+               }
                /* This is not allowed until all boards are initialized... */
                for (i = 0; i < SX_NBOARDS; i++) {
                        if ((boards[i].flags & SX_BOARD_PRESENT) &&
-                               !(boards[i].flags & SX_BOARD_INITIALIZED))
-                               return -EIO;
+                               !(boards[i].flags & SX_BOARD_INITIALIZED)) {
+                               rc = -EIO;
+                               break;
+                       }
                }
                for (i = 0; i < SX_NBOARDS; i++)
                        if (!(boards[i].flags & SX_BOARD_PRESENT))
@@ -1832,10 +1845,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                rc = sx_nports;
                break;
        default:
-               printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n",
-                               cmd);
+               rc = -ENOTTY;
                break;
        }
+       unlock_kernel();
        func_exit();
        return rc;
 }
index e1fc193d9396fc69c41ecd868fd2bd2d60ff73b7..ae766d868454406a6d32bbfc7422975d6a9ce550 100644 (file)
@@ -580,91 +580,133 @@ void tpm_continue_selftest(struct tpm_chip *chip)
 }
 EXPORT_SYMBOL_GPL(tpm_continue_selftest);
 
+#define  TPM_INTERNAL_RESULT_SIZE 200
+
 ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
                        char *buf)
 {
-       u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+       u8 *data;
        ssize_t rc;
 
        struct tpm_chip *chip = dev_get_drvdata(dev);
        if (chip == NULL)
                return -ENODEV;
 
+       data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        memcpy(data, tpm_cap, sizeof(tpm_cap));
        data[TPM_CAP_IDX] = TPM_CAP_FLAG;
        data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
 
-       rc = transmit_cmd(chip, data, sizeof(data),
-                       "attemtping to determine the permanent state");
-       if (rc)
+       rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
+                       "attemtping to determine the permanent enabled state");
+       if (rc) {
+               kfree(data);
                return 0;
-       return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
+       }
+
+       rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
+
+       kfree(data);
+       return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_enabled);
 
 ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
                        char *buf)
 {
-       u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+       u8 *data;
        ssize_t rc;
 
        struct tpm_chip *chip = dev_get_drvdata(dev);
        if (chip == NULL)
                return -ENODEV;
 
+       data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        memcpy(data, tpm_cap, sizeof(tpm_cap));
        data[TPM_CAP_IDX] = TPM_CAP_FLAG;
        data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
 
-       rc = transmit_cmd(chip, data, sizeof(data),
-                       "attemtping to determine the permanent state");
-       if (rc)
+       rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
+                       "attemtping to determine the permanent active state");
+       if (rc) {
+               kfree(data);
                return 0;
-       return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
+       }
+
+       rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
+
+       kfree(data);
+       return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_active);
 
 ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
                        char *buf)
 {
-       u8 data[sizeof(tpm_cap)];
+       u8 *data;
        ssize_t rc;
 
        struct tpm_chip *chip = dev_get_drvdata(dev);
        if (chip == NULL)
                return -ENODEV;
 
+       data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        memcpy(data, tpm_cap, sizeof(tpm_cap));
        data[TPM_CAP_IDX] = TPM_CAP_PROP;
        data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
 
-       rc = transmit_cmd(chip, data, sizeof(data),
+       rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
                        "attempting to determine the owner state");
-       if (rc)
+       if (rc) {
+               kfree(data);
                return 0;
-       return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
+       }
+
+       rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
+
+       kfree(data);
+       return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_owned);
 
 ssize_t tpm_show_temp_deactivated(struct device * dev,
                                struct device_attribute * attr, char *buf)
 {
-       u8 data[sizeof(tpm_cap)];
+       u8 *data;
        ssize_t rc;
 
        struct tpm_chip *chip = dev_get_drvdata(dev);
        if (chip == NULL)
                return -ENODEV;
 
+       data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        memcpy(data, tpm_cap, sizeof(tpm_cap));
        data[TPM_CAP_IDX] = TPM_CAP_FLAG;
        data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
 
-       rc = transmit_cmd(chip, data, sizeof(data),
+       rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
                        "attempting to determine the temporary state");
-       if (rc)
+       if (rc) {
+               kfree(data);
                return 0;
-       return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
+       }
+
+       rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
+
+       kfree(data);
+       return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
 
@@ -678,7 +720,7 @@ static const u8 pcrread[] = {
 ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
                      char *buf)
 {
-       u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)];
+       u8 *data;
        ssize_t rc;
        int i, j, num_pcrs;
        __be32 index;
@@ -688,21 +730,27 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
        if (chip == NULL)
                return -ENODEV;
 
+       data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        memcpy(data, tpm_cap, sizeof(tpm_cap));
        data[TPM_CAP_IDX] = TPM_CAP_PROP;
        data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
 
-       rc = transmit_cmd(chip, data, sizeof(data),
+       rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
                        "attempting to determine the number of PCRS");
-       if (rc)
+       if (rc) {
+               kfree(data);
                return 0;
+       }
 
        num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
        for (i = 0; i < num_pcrs; i++) {
                memcpy(data, pcrread, sizeof(pcrread));
                index = cpu_to_be32(i);
                memcpy(data + 10, &index, 4);
-               rc = transmit_cmd(chip, data, sizeof(data),
+               rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
                                "attempting to read a PCR");
                if (rc)
                        goto out;
@@ -712,6 +760,7 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
                str += sprintf(str, "\n");
        }
 out:
+       kfree(data);
        return str - buf;
 }
 EXPORT_SYMBOL_GPL(tpm_show_pcrs);
@@ -795,7 +844,7 @@ static const u8 cap_version[] = {
 ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
                      char *buf)
 {
-       u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
+       u8 *data;
        ssize_t rc;
        char *str = buf;
 
@@ -803,21 +852,27 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
        if (chip == NULL)
                return -ENODEV;
 
+       data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        memcpy(data, tpm_cap, sizeof(tpm_cap));
        data[TPM_CAP_IDX] = TPM_CAP_PROP;
        data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
 
-       rc = transmit_cmd(chip, data, sizeof(data),
+       rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
                        "attempting to determine the manufacturer");
-       if (rc)
+       if (rc) {
+               kfree(data);
                return 0;
+       }
 
        str += sprintf(str, "Manufacturer: 0x%x\n",
                       be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
 
        memcpy(data, cap_version, sizeof(cap_version));
        data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
-       rc = transmit_cmd(chip, data, sizeof(data),
+       rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE,
                        "attempting to determine the 1.1 version");
        if (rc)
                goto out;
@@ -828,6 +883,7 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
                       (int) data[17]);
 
 out:
+       kfree(data);
        return str - buf;
 }
 EXPORT_SYMBOL_GPL(tpm_show_caps);
@@ -835,7 +891,7 @@ EXPORT_SYMBOL_GPL(tpm_show_caps);
 ssize_t tpm_show_caps_1_2(struct device * dev,
                          struct device_attribute * attr, char *buf)
 {
-       u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
+       u8 *data;
        ssize_t len;
        char *str = buf;
 
@@ -843,15 +899,20 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
        if (chip == NULL)
                return -ENODEV;
 
+       data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        memcpy(data, tpm_cap, sizeof(tpm_cap));
        data[TPM_CAP_IDX] = TPM_CAP_PROP;
        data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
 
-       if ((len = tpm_transmit(chip, data, sizeof(data))) <=
-           TPM_ERROR_SIZE) {
+       len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE);
+       if (len <= TPM_ERROR_SIZE) {
                dev_dbg(chip->dev, "A TPM error (%d) occurred "
                        "attempting to determine the manufacturer\n",
                        be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+               kfree(data);
                return 0;
        }
 
@@ -861,8 +922,8 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
        memcpy(data, cap_version, sizeof(cap_version));
        data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
 
-       if ((len = tpm_transmit(chip, data, sizeof(data))) <=
-           TPM_ERROR_SIZE) {
+       len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE);
+       if (len <= TPM_ERROR_SIZE) {
                dev_err(chip->dev, "A TPM error (%d) occurred "
                        "attempting to determine the 1.2 version\n",
                        be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
@@ -874,6 +935,7 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
                       (int) data[19]);
 
 out:
+       kfree(data);
        return str - buf;
 }
 EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
@@ -966,7 +1028,7 @@ ssize_t tpm_write(struct file *file, const char __user *buf,
                  size_t size, loff_t *off)
 {
        struct tpm_chip *chip = file->private_data;
-       int in_size = size, out_size;
+       size_t in_size = size, out_size;
 
        /* cannot perform a write until the read has cleared
           either via tpm_read or a user_read_timer timeout */
@@ -1001,7 +1063,7 @@ ssize_t tpm_read(struct file *file, char __user *buf,
                 size_t size, loff_t *off)
 {
        struct tpm_chip *chip = file->private_data;
-       int ret_size;
+       ssize_t ret_size;
 
        del_singleshot_timer_sync(&chip->user_read_timer);
        flush_scheduled_work();
index 60a2d2630e368f4003dcb164ac437c7a2d52cfbd..68f052b42ed7807e9771761a171778bcd6fc3f1e 100644 (file)
@@ -448,7 +448,7 @@ out_free:
        goto out;
 }
 
-const struct file_operations tpm_ascii_bios_measurements_ops = {
+static const struct file_operations tpm_ascii_bios_measurements_ops = {
        .open = tpm_ascii_bios_measurements_open,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -486,7 +486,7 @@ out_free:
        goto out;
 }
 
-const struct file_operations tpm_binary_bios_measurements_ops = {
+static const struct file_operations tpm_binary_bios_measurements_ops = {
        .open = tpm_binary_bios_measurements_open,
        .read = seq_read,
        .llseek = seq_lseek,
index c7a977bc03e81e2b1f38830c62b2034672065538..ed1879c0dd8d1433a0e239631630ce55a971f8b8 100644 (file)
@@ -622,6 +622,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
        {"ATM1200", 0},         /* Atmel */
        {"IFX0102", 0},         /* Infineon */
        {"BCM0101", 0},         /* Broadcom */
+       {"BCM0102", 0},         /* Broadcom */
        {"NSC1200", 0},         /* National */
        {"ICO0102", 0},         /* Intel */
        /* Add new here */
index fa48dba5ba5e94ff5833f16c8e4e758bb1ffbd66..e1b46bc7e43cd245794f02610afe6c88d49eeb47 100644 (file)
@@ -1119,19 +1119,6 @@ int tty_hung_up_p(struct file *filp)
 
 EXPORT_SYMBOL(tty_hung_up_p);
 
-/**
- *     is_tty  -       checker whether file is a TTY
- *     @filp:          file handle that may be a tty
- *
- *     Check if the file handle is a tty handle.
- */
-
-int is_tty(struct file *filp)
-{
-       return filp->f_op->read == tty_read
-               || filp->f_op->read == hung_up_tty_read;
-}
-
 static void session_clear_tty(struct pid *session)
 {
        struct task_struct *p;
@@ -3593,7 +3580,6 @@ void proc_clear_tty(struct task_struct *p)
        p->signal->tty = NULL;
        spin_unlock_irq(&p->sighand->siglock);
 }
-EXPORT_SYMBOL(proc_clear_tty);
 
 /* Called under the sighand lock */
 
index dc17fe3a88bc48f2813ad5c3e5dd27efd00ff7d3..d0f4eb6fdb7fee27eca6cfec84ff8cf25af209e4 100644 (file)
@@ -46,6 +46,9 @@ static char *in, *inbuf;
 /* The operations for our console. */
 static struct hv_ops virtio_cons;
 
+/* The hvc device */
+static struct hvc_struct *hvc;
+
 /*D:310 The put_chars() callback is pretty straightforward.
  *
  * We turn the characters into a scatter-gather list, add it to the output
@@ -134,6 +137,27 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
        return hvc_instantiate(0, 0, &virtio_cons);
 }
 
+/*
+ * we support only one console, the hvc struct is a global var
+ * There is no need to do anything
+ */
+static int notifier_add_vio(struct hvc_struct *hp, int data)
+{
+       hp->irq_requested = 1;
+       return 0;
+}
+
+static void notifier_del_vio(struct hvc_struct *hp, int data)
+{
+       hp->irq_requested = 0;
+}
+
+static void hvc_handle_input(struct virtqueue *vq)
+{
+       if (hvc_poll(hvc))
+               hvc_kick();
+}
+
 /*D:370 Once we're further in boot, we get probed like any other virtio device.
  * At this stage we set up the output virtqueue.
  *
@@ -144,7 +168,6 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
 static int __devinit virtcons_probe(struct virtio_device *dev)
 {
        int err;
-       struct hvc_struct *hvc;
 
        vdev = dev;
 
@@ -158,7 +181,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev)
        /* Find the input queue. */
        /* FIXME: This is why we want to wean off hvc: we do nothing
         * when input comes in. */
-       in_vq = vdev->config->find_vq(vdev, 0, NULL);
+       in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input);
        if (IS_ERR(in_vq)) {
                err = PTR_ERR(in_vq);
                goto free;
@@ -173,15 +196,18 @@ static int __devinit virtcons_probe(struct virtio_device *dev)
        /* Start using the new console output. */
        virtio_cons.get_chars = get_chars;
        virtio_cons.put_chars = put_chars;
+       virtio_cons.notifier_add = notifier_add_vio;
+       virtio_cons.notifier_del = notifier_del_vio;
 
        /* The first argument of hvc_alloc() is the virtual console number, so
-        * we use zero.  The second argument is the interrupt number; we
-        * currently leave this as zero: it would be better not to use the
-        * hvc mechanism and fix this (FIXME!).
+        * we use zero.  The second argument is the parameter for the
+        * notification mechanism (like irq number). We currently leave this
+        * as zero, virtqueues have implicit notifications.
         *
         * The third argument is a "struct hv_ops" containing the put_chars()
-        * and get_chars() pointers.  The final argument is the output buffer
-        * size: we can do any size, so we put PAGE_SIZE here. */
+        * get_chars(), notifier_add() and notifier_del() pointers.
+        * The final argument is the output buffer size: we can do any size,
+        * so we put PAGE_SIZE here. */
        hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE);
        if (IS_ERR(hvc)) {
                err = PTR_ERR(hvc);
index 69c5afe97f19ef6e6fc932ceabcfc42420ff6d32..1718b3c481dbd944eb343b140801e930dd5cc355 100644 (file)
@@ -183,8 +183,8 @@ static void scc_init_portstructs(void)
 #ifdef NEW_WRITE_LOCKING
                port->gs.port_write_mutex = MUTEX;
 #endif
-               init_waitqueue_head(&port->gs.open_wait);
-               init_waitqueue_head(&port->gs.close_wait);
+               init_waitqueue_head(&port->gs.port.open_wait);
+               init_waitqueue_head(&port->gs.port.close_wait);
        }
 }
 
@@ -422,7 +422,7 @@ static irqreturn_t scc_rx_int(int irq, void *data)
 {
        unsigned char   ch;
        struct scc_port *port = data;
-       struct tty_struct *tty = port->gs.tty;
+       struct tty_struct *tty = port->gs.port.tty;
        SCC_ACCESS_INIT(port);
 
        ch = SCCread_NB(RX_DATA_REG);
@@ -453,7 +453,7 @@ static irqreturn_t scc_rx_int(int irq, void *data)
 static irqreturn_t scc_spcond_int(int irq, void *data)
 {
        struct scc_port *port = data;
-       struct tty_struct *tty = port->gs.tty;
+       struct tty_struct *tty = port->gs.port.tty;
        unsigned char   stat, ch, err;
        int             int_pending_mask = port->channel == CHANNEL_A ?
                                           IPR_A_RX : IPR_B_RX;
@@ -500,7 +500,7 @@ static irqreturn_t scc_tx_int(int irq, void *data)
        struct scc_port *port = data;
        SCC_ACCESS_INIT(port);
 
-       if (!port->gs.tty) {
+       if (!port->gs.port.tty) {
                printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
                SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
                SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
@@ -512,8 +512,9 @@ static irqreturn_t scc_tx_int(int irq, void *data)
                        SCCwrite(TX_DATA_REG, port->x_char);
                        port->x_char = 0;
                }
-               else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
-                               port->gs.tty->hw_stopped)
+               else if ((port->gs.xmit_cnt <= 0) ||
+                        port->gs.port.tty->stopped ||
+                        port->gs.port.tty->hw_stopped)
                        break;
                else {
                        SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
@@ -522,15 +523,15 @@ static irqreturn_t scc_tx_int(int irq, void *data)
                                break;
                }
        }
-       if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
-                       port->gs.tty->hw_stopped) {
+       if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped ||
+           port->gs.port.tty->hw_stopped) {
                /* disable tx interrupts */
                SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
                SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
-               port->gs.flags &= ~GS_TX_INTEN;
+               port->gs.port.flags &= ~GS_TX_INTEN;
        }
-       if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
-               tty_wakeup(port->gs.tty);
+       if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
+               tty_wakeup(port->gs.port.tty);
 
        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
        return IRQ_HANDLED;
@@ -550,14 +551,14 @@ static irqreturn_t scc_stat_int(int irq, void *data)
 
        if (changed & SR_DCD) {
                port->c_dcd = !!(sr & SR_DCD);
-               if (!(port->gs.flags & ASYNC_CHECK_CD))
+               if (!(port->gs.port.flags & ASYNC_CHECK_CD))
                        ;       /* Don't report DCD changes */
                else if (port->c_dcd) {
-                       wake_up_interruptible(&port->gs.open_wait);
+                       wake_up_interruptible(&port->gs.port.open_wait);
                }
                else {
-                       if (port->gs.tty)
-                               tty_hangup (port->gs.tty);
+                       if (port->gs.port.tty)
+                               tty_hangup (port->gs.port.tty);
                }
        }
        SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
@@ -578,7 +579,7 @@ static void scc_disable_tx_interrupts(void *ptr)
 
        local_irq_save(flags);
        SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-       port->gs.flags &= ~GS_TX_INTEN;
+       port->gs.port.flags &= ~GS_TX_INTEN;
        local_irq_restore(flags);
 }
 
@@ -636,8 +637,8 @@ static void scc_shutdown_port(void *ptr)
 {
        struct scc_port *port = ptr;
 
-       port->gs.flags &= ~ GS_ACTIVE;
-       if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
+       port->gs.port.flags &= ~ GS_ACTIVE;
+       if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) {
                scc_setsignals (port, 0, 0);
        }
 }
@@ -652,14 +653,14 @@ static int scc_set_real_termios (void *ptr)
        struct scc_port *port = ptr;
        SCC_ACCESS_INIT(port);
 
-       if (!port->gs.tty || !port->gs.tty->termios) return 0;
+       if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
 
        channel = port->channel;
 
        if (channel == CHANNEL_A)
                return 0;               /* Settings controlled by boot PROM */
 
-       cflag  = port->gs.tty->termios->c_cflag;
+       cflag  = port->gs.port.tty->termios->c_cflag;
        baud = port->gs.baud;
        chsize = (cflag & CSIZE) >> 4;
 
@@ -678,9 +679,9 @@ static int scc_set_real_termios (void *ptr)
        }
 
        if (cflag & CLOCAL)
-               port->gs.flags &= ~ASYNC_CHECK_CD;
+               port->gs.port.flags &= ~ASYNC_CHECK_CD;
        else
-               port->gs.flags |= ASYNC_CHECK_CD;
+               port->gs.port.flags |= ASYNC_CHECK_CD;
 
 #ifdef CONFIG_MVME147_SCC
        if (MACH_IS_MVME147)
@@ -856,7 +857,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
                { COMMAND_REG, CR_EXTSTAT_RESET },
        };
 #endif
-       if (!(port->gs.flags & ASYNC_INITIALIZED)) {
+       if (!(port->gs.port.flags & ASYNC_INITIALIZED)) {
                local_irq_save(flags);
 #if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
                if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
@@ -880,18 +881,18 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
        }
 
        tty->driver_data = port;
-       port->gs.tty = tty;
-       port->gs.count++;
+       port->gs.port.tty = tty;
+       port->gs.port.count++;
        retval = gs_init_port(&port->gs);
        if (retval) {
-               port->gs.count--;
+               port->gs.port.count--;
                return retval;
        }
-       port->gs.flags |= GS_ACTIVE;
+       port->gs.port.flags |= GS_ACTIVE;
        retval = gs_block_til_ready(port, filp);
 
        if (retval) {
-               port->gs.count--;
+               port->gs.port.count--;
                return retval;
        }
 
index e32a076d5f1f8f182025341d98d3a89f25a9f4f8..82a51f38a5469cd1a56637c6635b9c16f69f5f89 100644 (file)
@@ -261,7 +261,7 @@ static void notify_update(struct vc_data *vc)
 #ifdef VT_BUF_VRAM_ONLY
 #define DO_UPDATE(vc)  0
 #else
-#define DO_UPDATE(vc)  CON_IS_VISIBLE(vc)
+#define DO_UPDATE(vc)  (CON_IS_VISIBLE(vc) && !console_blanked)
 #endif
 
 static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
@@ -2211,7 +2211,7 @@ rescan_last_byte:
                        c = 0xfffd;
                    tc = c;
                } else {        /* no utf or alternate charset mode */
-                   tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
+                   tc = vc_translate(vc, c);
                }
 
                param.c = tc;
@@ -2749,8 +2749,8 @@ static int con_open(struct tty_struct *tty, struct file *filp)
                                tty->termios->c_iflag |= IUTF8;
                        else
                                tty->termios->c_iflag &= ~IUTF8;
-                       release_console_sem();
                        vcs_make_sysfs(tty);
+                       release_console_sem();
                        return ret;
                }
        }
@@ -2775,8 +2775,8 @@ static void con_close(struct tty_struct *tty, struct file *filp)
                if (vc)
                        vc->vc_tty = NULL;
                tty->driver_data = NULL;
-               release_console_sem();
                vcs_remove_sysfs(tty);
+               release_console_sem();
                mutex_unlock(&tty_mutex);
                /*
                 * tty_mutex is released, but we still hold BKL, so there is
index 51966ccf4ea3f56c4449f88c93906ab81e136111..8bfee5fb7223cd21e5dff7c0f4f62371f66fe963 100644 (file)
@@ -87,7 +87,6 @@
 #include <linux/mutex.h>
 #include <linux/smp_lock.h>
 #include <linux/sysctl.h>
-#include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/cdev.h>
 #include <linux/platform_device.h>
index 5405769020a1c13aa727e9a70e4e2dad99d1aef8..5ce07b517c5875def9106c5041402032c3f70fc1 100644 (file)
@@ -94,7 +94,7 @@ void cpuidle_install_idle_handler(void)
  */
 void cpuidle_uninstall_idle_handler(void)
 {
-       if (enabled_devices && (pm_idle != pm_idle_old)) {
+       if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) {
                pm_idle = pm_idle_old;
                cpuidle_kick_cpus();
        }
index b11943dadefd7a23d85d29f5908451859e397497..681c15f420834a545292b17974e523d387d2f243 100644 (file)
@@ -99,6 +99,9 @@ struct talitos_private {
        /* next channel to be assigned next incoming descriptor */
        atomic_t last_chan;
 
+       /* per-channel number of requests pending in channel h/w fifo */
+       atomic_t *submit_count;
+
        /* per-channel request fifo */
        struct talitos_request **fifo;
 
@@ -263,15 +266,15 @@ static int talitos_submit(struct device *dev, struct talitos_desc *desc,
 
        spin_lock_irqsave(&priv->head_lock[ch], flags);
 
-       head = priv->head[ch];
-       request = &priv->fifo[ch][head];
-
-       if (request->desc) {
-               /* request queue is full */
+       if (!atomic_inc_not_zero(&priv->submit_count[ch])) {
+               /* h/w fifo is full */
                spin_unlock_irqrestore(&priv->head_lock[ch], flags);
                return -EAGAIN;
        }
 
+       head = priv->head[ch];
+       request = &priv->fifo[ch][head];
+
        /* map descriptor and save caller data */
        request->dma_desc = dma_map_single(dev, desc, sizeof(*desc),
                                           DMA_BIDIRECTIONAL);
@@ -335,6 +338,9 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
                priv->tail[ch] = (tail + 1) & (priv->fifo_len - 1);
 
                spin_unlock_irqrestore(&priv->tail_lock[ch], flags);
+
+               atomic_dec(&priv->submit_count[ch]);
+
                saved_req.callback(dev, saved_req.desc, saved_req.context,
                                   status);
                /* channel may resume processing in single desc error case */
@@ -842,7 +848,7 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
 
        /* adjust (decrease) last one (or two) entry's len to cryptlen */
        link_tbl_ptr--;
-       while (link_tbl_ptr->len <= (-cryptlen)) {
+       while (be16_to_cpu(link_tbl_ptr->len) <= (-cryptlen)) {
                /* Empty this entry, and move to previous one */
                cryptlen += be16_to_cpu(link_tbl_ptr->len);
                link_tbl_ptr->len = 0;
@@ -874,7 +880,7 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
        unsigned int cryptlen = areq->cryptlen;
        unsigned int authsize = ctx->authsize;
        unsigned int ivsize;
-       int sg_count;
+       int sg_count, ret;
 
        /* hmac key */
        map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
@@ -978,7 +984,12 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
        map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 0,
                               DMA_FROM_DEVICE);
 
-       return talitos_submit(dev, desc, callback, areq);
+       ret = talitos_submit(dev, desc, callback, areq);
+       if (ret != -EINPROGRESS) {
+               ipsec_esp_unmap(dev, edesc, areq);
+               kfree(edesc);
+       }
+       return ret;
 }
 
 
@@ -1009,6 +1020,8 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
        struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
        struct ipsec_esp_edesc *edesc;
        int src_nents, dst_nents, alloc_len, dma_len;
+       gfp_t flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+                     GFP_ATOMIC;
 
        if (areq->cryptlen + ctx->authsize > TALITOS_MAX_DATA_LEN) {
                dev_err(ctx->dev, "cryptlen exceeds h/w max limit\n");
@@ -1022,7 +1035,7 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
                dst_nents = src_nents;
        } else {
                dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize);
-               dst_nents = (dst_nents == 1) ? 0 : src_nents;
+               dst_nents = (dst_nents == 1) ? 0 : dst_nents;
        }
 
        /*
@@ -1040,7 +1053,7 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
                alloc_len += icv_stashing ? ctx->authsize : 0;
        }
 
-       edesc = kmalloc(alloc_len, GFP_DMA);
+       edesc = kmalloc(alloc_len, GFP_DMA | flags);
        if (!edesc) {
                dev_err(ctx->dev, "could not allocate edescriptor\n");
                return ERR_PTR(-ENOMEM);
@@ -1337,6 +1350,7 @@ static int __devexit talitos_remove(struct of_device *ofdev)
        if (hw_supports(dev, DESC_HDR_SEL0_RNG))
                talitos_unregister_rng(dev);
 
+       kfree(priv->submit_count);
        kfree(priv->tail);
        kfree(priv->head);
 
@@ -1466,9 +1480,6 @@ static int talitos_probe(struct of_device *ofdev,
                goto err_out;
        }
 
-       of_node_put(np);
-       np = NULL;
-
        priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels,
                                  GFP_KERNEL);
        priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels,
@@ -1504,6 +1515,16 @@ static int talitos_probe(struct of_device *ofdev,
                }
        }
 
+       priv->submit_count = kmalloc(sizeof(atomic_t) * priv->num_channels,
+                                    GFP_KERNEL);
+       if (!priv->submit_count) {
+               dev_err(dev, "failed to allocate fifo submit count space\n");
+               err = -ENOMEM;
+               goto err_out;
+       }
+       for (i = 0; i < priv->num_channels; i++)
+               atomic_set(&priv->submit_count[i], -priv->chfifo_len);
+
        priv->head = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
        priv->tail = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
        if (!priv->head || !priv->tail) {
@@ -1559,8 +1580,6 @@ static int talitos_probe(struct of_device *ofdev,
 
 err_out:
        talitos_remove(ofdev);
-       if (np)
-               of_node_put(np);
 
        return err;
 }
index 6e6c3c4aea6b074d53c9824a1060bbfc38e88069..5a11e3cbcae26748ac75ac5e3e4e31a724d1fab8 100644 (file)
@@ -123,6 +123,13 @@ config EDAC_I5000
          Support for error detection and correction the Intel
          Greekcreek/Blackford chipsets.
 
+config EDAC_I5100
+       tristate "Intel San Clemente MCH"
+       depends on EDAC_MM_EDAC && X86 && PCI
+       help
+         Support for error detection and correction the Intel
+         San Clemente MCH.
+
 config EDAC_MPC85XX
        tristate "Freescale MPC85xx"
        depends on EDAC_MM_EDAC && FSL_SOC && MPC85xx
index 83807731d4a9782f673e7dd46ad9d6af183d4193..e5e9104b55204a1672f5bc7e8f5547b3079aed7d 100644 (file)
@@ -19,6 +19,7 @@ endif
 
 obj-$(CONFIG_EDAC_AMD76X)              += amd76x_edac.o
 obj-$(CONFIG_EDAC_I5000)               += i5000_edac.o
+obj-$(CONFIG_EDAC_I5100)               += i5100_edac.o
 obj-$(CONFIG_EDAC_E7XXX)               += e7xxx_edac.o
 obj-$(CONFIG_EDAC_E752X)               += e752x_edac.o
 obj-$(CONFIG_EDAC_I82443BXGX)          += i82443bxgx_edac.o
index c94a0eb492cb1eb2b01bfa5c8a5b47d7099c79a1..facfdb1fa71c5ece5c6f7d7f14acf17227ffefd1 100644 (file)
@@ -28,6 +28,7 @@
 #define E752X_REVISION " Ver: 2.0.2 " __DATE__
 #define EDAC_MOD_STR   "e752x_edac"
 
+static int report_non_memory_errors;
 static int force_function_unhide;
 static int sysbus_parity = -1;
 
@@ -117,7 +118,7 @@ static struct edac_pci_ctl_info *e752x_pci;
 #define E752X_BUF_FERR         0x70    /* Memory buffer first error reg (8b) */
 #define E752X_BUF_NERR         0x72    /* Memory buffer next error reg (8b) */
 #define E752X_BUF_ERRMASK      0x74    /* Memory buffer error mask reg (8b) */
-#define E752X_BUF_SMICMD       0x7A    /* Memory buffer SMI command reg (8b) */
+#define E752X_BUF_SMICMD       0x7A    /* Memory buffer SMI cmd reg (8b) */
 #define E752X_DRAM_FERR                0x80    /* DRAM first error register (16b) */
 #define E752X_DRAM_NERR                0x82    /* DRAM next error register (16b) */
 #define E752X_DRAM_ERRMASK     0x84    /* DRAM error mask register (8b) */
@@ -127,7 +128,7 @@ static struct edac_pci_ctl_info *e752x_pci;
                                        /*     error address register (32b) */
                                        /*
                                         * 31    Reserved
-                                        * 30:2  CE address (64 byte block 34:6)
+                                        * 30:2  CE address (64 byte block 34:6
                                         * 1     Reserved
                                         * 0     HiLoCS
                                         */
@@ -147,11 +148,11 @@ static struct edac_pci_ctl_info *e752x_pci;
                                         * 1     Reserved
                                         * 0     HiLoCS
                                         */
-#define E752X_DRAM_SCRB_ADD    0xA8    /* DRAM first uncorrectable scrub memory */
+#define E752X_DRAM_SCRB_ADD    0xA8    /* DRAM 1st uncorrectable scrub mem */
                                        /*     error address register (32b) */
                                        /*
                                         * 31    Reserved
-                                        * 30:2  CE address (64 byte block 34:6)
+                                        * 30:2  CE address (64 byte block 34:6
                                         * 1     Reserved
                                         * 0     HiLoCS
                                         */
@@ -394,9 +395,12 @@ static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
        struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info;
 
        error_1b = retry_add;
-       page = error_1b >> (PAGE_SHIFT - 4);    /* convert the addr to 4k page */
-       row = pvt->mc_symmetric ? ((page >> 1) & 3) :   /* chip select are bits 14 & 13 */
+       page = error_1b >> (PAGE_SHIFT - 4);  /* convert the addr to 4k page */
+
+       /* chip select are bits 14 & 13 */
+       row = pvt->mc_symmetric ? ((page >> 1) & 3) :
                edac_mc_find_csrow_by_page(mci, page);
+
        e752x_mc_printk(mci, KERN_WARNING,
                        "CE page 0x%lx, row %d : Memory read retry\n",
                        (long unsigned int)page, row);
@@ -422,12 +426,21 @@ static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
 }
 
 static char *global_message[11] = {
-       "PCI Express C1", "PCI Express C", "PCI Express B1",
-       "PCI Express B", "PCI Express A1", "PCI Express A",
-       "DMA Controler", "HUB or NS Interface", "System Bus",
-       "DRAM Controler", "Internal Buffer"
+       "PCI Express C1",
+       "PCI Express C",
+       "PCI Express B1",
+       "PCI Express B",
+       "PCI Express A1",
+       "PCI Express A",
+       "DMA Controller",
+       "HUB or NS Interface",
+       "System Bus",
+       "DRAM Controller",  /* 9th entry */
+       "Internal Buffer"
 };
 
+#define DRAM_ENTRY     9
+
 static char *fatal_message[2] = { "Non-Fatal ", "Fatal " };
 
 static void do_global_error(int fatal, u32 errors)
@@ -435,9 +448,16 @@ static void do_global_error(int fatal, u32 errors)
        int i;
 
        for (i = 0; i < 11; i++) {
-               if (errors & (1 << i))
-                       e752x_printk(KERN_WARNING, "%sError %s\n",
-                               fatal_message[fatal], global_message[i]);
+               if (errors & (1 << i)) {
+                       /* If the error is from DRAM Controller OR
+                        * we are to report ALL errors, then
+                        * report the error
+                        */
+                       if ((i == DRAM_ENTRY) || report_non_memory_errors)
+                               e752x_printk(KERN_WARNING, "%sError %s\n",
+                                       fatal_message[fatal],
+                                       global_message[i]);
+               }
        }
 }
 
@@ -1021,7 +1041,7 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx,
        struct pci_dev *dev;
 
        pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
-                                       pvt->dev_info->err_dev, pvt->bridge_ck);
+                               pvt->dev_info->err_dev, pvt->bridge_ck);
 
        if (pvt->bridge_ck == NULL)
                pvt->bridge_ck = pci_scan_single_device(pdev->bus,
@@ -1034,8 +1054,9 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx,
                return 1;
        }
 
-       dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev,
-                       NULL);
+       dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                               e752x_devs[dev_idx].ctl_dev,
+                               NULL);
 
        if (dev == NULL)
                goto fail;
@@ -1316,7 +1337,8 @@ MODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers");
 
 module_param(force_function_unhide, int, 0444);
 MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:"
-                " 1=force unhide and hope BIOS doesn't fight driver for Dev0:Fun1 access");
+                " 1=force unhide and hope BIOS doesn't fight driver for "
+               "Dev0:Fun1 access");
 
 module_param(edac_op_state, int, 0444);
 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
@@ -1324,3 +1346,6 @@ MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
 module_param(sysbus_parity, int, 0444);
 MODULE_PARM_DESC(sysbus_parity, "0=disable system bus parity checking,"
                " 1=enable system bus parity checking, default=auto-detect");
+module_param(report_non_memory_errors, int, 0644);
+MODULE_PARM_DESC(report_non_memory_errors, "0=disable non-memory error "
+               "reporting, 1=enable non-memory error reporting");
index 021d18795145cbc364e676d763ed8369ccea8ee1..ad218fe4942dfcf258273ee22f56776f3a0b23c2 100644 (file)
@@ -44,6 +44,25 @@ int edac_mc_get_poll_msec(void)
        return edac_mc_poll_msec;
 }
 
+static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
+{
+       long l;
+       int ret;
+
+       if (!val)
+               return -EINVAL;
+
+       ret = strict_strtol(val, 0, &l);
+       if (ret == -EINVAL || ((int)l != l))
+               return -EINVAL;
+       *((int *)kp->arg) = l;
+
+       /* notify edac_mc engine to reset the poll period */
+       edac_mc_reset_delay_period(l);
+
+       return 0;
+}
+
 /* Parameter declarations for above */
 module_param(edac_mc_panic_on_ue, int, 0644);
 MODULE_PARM_DESC(edac_mc_panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
@@ -53,7 +72,8 @@ MODULE_PARM_DESC(edac_mc_log_ue,
 module_param(edac_mc_log_ce, int, 0644);
 MODULE_PARM_DESC(edac_mc_log_ce,
                 "Log correctable error to console: 0=off 1=on");
-module_param(edac_mc_poll_msec, int, 0644);
+module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int,
+                 &edac_mc_poll_msec, 0644);
 MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds");
 
 /*
@@ -103,16 +123,6 @@ static const char *edac_caps[] = {
 
 
 
-/*
- * /sys/devices/system/edac/mc;
- *     data structures and methods
- */
-static ssize_t memctrl_int_show(void *ptr, char *buffer)
-{
-       int *value = (int *)ptr;
-       return sprintf(buffer, "%u\n", *value);
-}
-
 static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
 {
        int *value = (int *)ptr;
@@ -123,23 +133,6 @@ static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
        return count;
 }
 
-/*
- * mc poll_msec time value
- */
-static ssize_t poll_msec_int_store(void *ptr, const char *buffer, size_t count)
-{
-       int *value = (int *)ptr;
-
-       if (isdigit(*buffer)) {
-               *value = simple_strtoul(buffer, NULL, 0);
-
-               /* notify edac_mc engine to reset the poll period */
-               edac_mc_reset_delay_period(*value);
-       }
-
-       return count;
-}
-
 
 /* EDAC sysfs CSROW data structures and methods
  */
@@ -185,7 +178,11 @@ static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data,
 static ssize_t channel_dimm_label_show(struct csrow_info *csrow,
                                char *data, int channel)
 {
-       return snprintf(data, EDAC_MC_LABEL_LEN, "%s",
+       /* if field has not been initialized, there is nothing to send */
+       if (!csrow->channels[channel].label[0])
+               return 0;
+
+       return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
                        csrow->channels[channel].label);
 }
 
@@ -649,98 +646,10 @@ static struct kobj_type ktype_mci = {
        .default_attrs = (struct attribute **)mci_attr,
 };
 
-/* show/store, tables, etc for the MC kset */
-
-
-struct memctrl_dev_attribute {
-       struct attribute attr;
-       void *value;
-        ssize_t(*show) (void *, char *);
-        ssize_t(*store) (void *, const char *, size_t);
-};
-
-/* Set of show/store abstract level functions for memory control object */
-static ssize_t memctrl_dev_show(struct kobject *kobj,
-                               struct attribute *attr, char *buffer)
-{
-       struct memctrl_dev_attribute *memctrl_dev;
-       memctrl_dev = (struct memctrl_dev_attribute *)attr;
-
-       if (memctrl_dev->show)
-               return memctrl_dev->show(memctrl_dev->value, buffer);
-
-       return -EIO;
-}
-
-static ssize_t memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
-                                const char *buffer, size_t count)
-{
-       struct memctrl_dev_attribute *memctrl_dev;
-       memctrl_dev = (struct memctrl_dev_attribute *)attr;
-
-       if (memctrl_dev->store)
-               return memctrl_dev->store(memctrl_dev->value, buffer, count);
-
-       return -EIO;
-}
-
-static struct sysfs_ops memctrlfs_ops = {
-       .show = memctrl_dev_show,
-       .store = memctrl_dev_store
-};
-
-#define MEMCTRL_ATTR(_name, _mode, _show, _store)                      \
-static struct memctrl_dev_attribute attr_##_name = {                   \
-       .attr = {.name = __stringify(_name), .mode = _mode },   \
-       .value  = &_name,                                       \
-       .show   = _show,                                        \
-       .store  = _store,                                       \
-};
-
-#define MEMCTRL_STRING_ATTR(_name, _data, _mode, _show, _store)        \
-static struct memctrl_dev_attribute attr_##_name = {                   \
-       .attr = {.name = __stringify(_name), .mode = _mode },   \
-       .value  = _data,                                        \
-       .show   = _show,                                        \
-       .store  = _store,                                       \
-};
-
-/* csrow<id> control files */
-MEMCTRL_ATTR(edac_mc_panic_on_ue,
-       S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
-
-MEMCTRL_ATTR(edac_mc_log_ue,
-       S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
-
-MEMCTRL_ATTR(edac_mc_log_ce,
-       S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
-
-MEMCTRL_ATTR(edac_mc_poll_msec,
-       S_IRUGO | S_IWUSR, memctrl_int_show, poll_msec_int_store);
-
-/* Base Attributes of the memory ECC object */
-static struct memctrl_dev_attribute *memctrl_attr[] = {
-       &attr_edac_mc_panic_on_ue,
-       &attr_edac_mc_log_ue,
-       &attr_edac_mc_log_ce,
-       &attr_edac_mc_poll_msec,
-       NULL,
-};
-
-
-/* the ktype for the mc_kset internal kobj */
-static struct kobj_type ktype_mc_set_attribs = {
-       .sysfs_ops = &memctrlfs_ops,
-       .default_attrs = (struct attribute **)memctrl_attr,
-};
-
 /* EDAC memory controller sysfs kset:
  *     /sys/devices/system/edac/mc
  */
-static struct kset mc_kset = {
-       .kobj = {.ktype = &ktype_mc_set_attribs },
-};
-
+static struct kset *mc_kset;
 
 /*
  * edac_mc_register_sysfs_main_kobj
@@ -771,7 +680,7 @@ int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
        }
 
        /* this instance become part of the mc_kset */
-       kobj_mci->kset = &mc_kset;
+       kobj_mci->kset = mc_kset;
 
        /* register the mc<id> kobject to the mc_kset */
        err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL,
@@ -1001,12 +910,9 @@ int edac_sysfs_setup_mc_kset(void)
        }
 
        /* Init the MC's kobject */
-       kobject_set_name(&mc_kset.kobj, "mc");
-       mc_kset.kobj.parent = &edac_class->kset.kobj;
-
-       /* register the mc_kset */
-       err = kset_register(&mc_kset);
-       if (err) {
+       mc_kset = kset_create_and_add("mc", NULL, &edac_class->kset.kobj);
+       if (!mc_kset) {
+               err = -ENOMEM;
                debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
                goto fail_out;
        }
@@ -1028,6 +934,6 @@ fail_out:
  */
 void edac_sysfs_teardown_mc_kset(void)
 {
-       kset_unregister(&mc_kset);
+       kset_unregister(mc_kset);
 }
 
index 2c1fa1bb6df2fe87dbc96b3c511c24e509c43cf4..5c153dccc95e29ad2ac92658a5dec9a97da7d30a 100644 (file)
@@ -28,7 +28,7 @@ static int edac_pci_poll_msec = 1000; /* one second workq period */
 static atomic_t pci_parity_count = ATOMIC_INIT(0);
 static atomic_t pci_nonparity_count = ATOMIC_INIT(0);
 
-static struct kobject edac_pci_top_main_kobj;
+static struct kobject *edac_pci_top_main_kobj;
 static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0);
 
 /* getter functions for the data variables */
@@ -83,7 +83,7 @@ static void edac_pci_instance_release(struct kobject *kobj)
        pci = to_instance(kobj);
 
        /* decrement reference count on top main kobj */
-       kobject_put(&edac_pci_top_main_kobj);
+       kobject_put(edac_pci_top_main_kobj);
 
        kfree(pci);     /* Free the control struct */
 }
@@ -166,7 +166,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
         * track the number of PCI instances we have, and thus nest
         * properly on keeping the module loaded
         */
-       main_kobj = kobject_get(&edac_pci_top_main_kobj);
+       main_kobj = kobject_get(edac_pci_top_main_kobj);
        if (!main_kobj) {
                err = -ENODEV;
                goto error_out;
@@ -174,11 +174,11 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
 
        /* And now register this new kobject under the main kobj */
        err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance,
-                                  &edac_pci_top_main_kobj, "pci%d", idx);
+                                  edac_pci_top_main_kobj, "pci%d", idx);
        if (err != 0) {
                debugf2("%s() failed to register instance pci%d\n",
                        __func__, idx);
-               kobject_put(&edac_pci_top_main_kobj);
+               kobject_put(edac_pci_top_main_kobj);
                goto error_out;
        }
 
@@ -316,9 +316,10 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = {
  */
 static void edac_pci_release_main_kobj(struct kobject *kobj)
 {
-
        debugf0("%s() here to module_put(THIS_MODULE)\n", __func__);
 
+       kfree(kobj);
+
        /* last reference to top EDAC PCI kobject has been removed,
         * NOW release our ref count on the core module
         */
@@ -369,8 +370,16 @@ static int edac_pci_main_kobj_setup(void)
                goto decrement_count_fail;
        }
 
+       edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
+       if (!edac_pci_top_main_kobj) {
+               debugf1("Failed to allocate\n");
+               err = -ENOMEM;
+               goto kzalloc_fail;
+       }
+
        /* Instanstiate the pci object */
-       err = kobject_init_and_add(&edac_pci_top_main_kobj, &ktype_edac_pci_main_kobj,
+       err = kobject_init_and_add(edac_pci_top_main_kobj,
+                                  &ktype_edac_pci_main_kobj,
                                   &edac_class->kset.kobj, "pci");
        if (err) {
                debugf1("Failed to register '.../edac/pci'\n");
@@ -381,13 +390,16 @@ static int edac_pci_main_kobj_setup(void)
         * for EDAC PCI, then edac_pci_main_kobj_teardown()
         * must be used, for resources to be cleaned up properly
         */
-       kobject_uevent(&edac_pci_top_main_kobj, KOBJ_ADD);
+       kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD);
        debugf1("Registered '.../edac/pci' kobject\n");
 
        return 0;
 
        /* Error unwind statck */
 kobject_init_and_add_fail:
+       kfree(edac_pci_top_main_kobj);
+
+kzalloc_fail:
        module_put(THIS_MODULE);
 
 decrement_count_fail:
@@ -414,7 +426,7 @@ static void edac_pci_main_kobj_teardown(void)
        if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
                debugf0("%s() called kobject_put on main kobj\n",
                        __func__);
-               kobject_put(&edac_pci_top_main_kobj);
+               kobject_put(edac_pci_top_main_kobj);
        }
 }
 
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
new file mode 100644 (file)
index 0000000..22db05a
--- /dev/null
@@ -0,0 +1,981 @@
+/*
+ * Intel 5100 Memory Controllers kernel module
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * This module is based on the following document:
+ *
+ * Intel 5100X Chipset Memory Controller Hub (MCH) - Datasheet
+ *      http://download.intel.com/design/chipsets/datashts/318378.pdf
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/edac.h>
+#include <linux/delay.h>
+#include <linux/mmzone.h>
+
+#include "edac_core.h"
+
+/* register addresses */
+
+/* device 16, func 1 */
+#define I5100_MC               0x40    /* Memory Control Register */
+#define I5100_MS               0x44    /* Memory Status Register */
+#define I5100_SPDDATA          0x48    /* Serial Presence Detect Status Reg */
+#define I5100_SPDCMD           0x4c    /* Serial Presence Detect Command Reg */
+#define I5100_TOLM             0x6c    /* Top of Low Memory */
+#define I5100_MIR0             0x80    /* Memory Interleave Range 0 */
+#define I5100_MIR1             0x84    /* Memory Interleave Range 1 */
+#define I5100_AMIR_0           0x8c    /* Adjusted Memory Interleave Range 0 */
+#define I5100_AMIR_1           0x90    /* Adjusted Memory Interleave Range 1 */
+#define I5100_FERR_NF_MEM      0xa0    /* MC First Non Fatal Errors */
+#define                I5100_FERR_NF_MEM_M16ERR_MASK   (1 << 16)
+#define                I5100_FERR_NF_MEM_M15ERR_MASK   (1 << 15)
+#define                I5100_FERR_NF_MEM_M14ERR_MASK   (1 << 14)
+#define                I5100_FERR_NF_MEM_M12ERR_MASK   (1 << 12)
+#define                I5100_FERR_NF_MEM_M11ERR_MASK   (1 << 11)
+#define                I5100_FERR_NF_MEM_M10ERR_MASK   (1 << 10)
+#define                I5100_FERR_NF_MEM_M6ERR_MASK    (1 << 6)
+#define                I5100_FERR_NF_MEM_M5ERR_MASK    (1 << 5)
+#define                I5100_FERR_NF_MEM_M4ERR_MASK    (1 << 4)
+#define                I5100_FERR_NF_MEM_M1ERR_MASK    1
+#define                I5100_FERR_NF_MEM_ANY_MASK      \
+                       (I5100_FERR_NF_MEM_M16ERR_MASK | \
+                       I5100_FERR_NF_MEM_M15ERR_MASK | \
+                       I5100_FERR_NF_MEM_M14ERR_MASK | \
+                       I5100_FERR_NF_MEM_M12ERR_MASK | \
+                       I5100_FERR_NF_MEM_M11ERR_MASK | \
+                       I5100_FERR_NF_MEM_M10ERR_MASK | \
+                       I5100_FERR_NF_MEM_M6ERR_MASK | \
+                       I5100_FERR_NF_MEM_M5ERR_MASK | \
+                       I5100_FERR_NF_MEM_M4ERR_MASK | \
+                       I5100_FERR_NF_MEM_M1ERR_MASK)
+#define        I5100_NERR_NF_MEM       0xa4    /* MC Next Non-Fatal Errors */
+#define I5100_EMASK_MEM                0xa8    /* MC Error Mask Register */
+
+/* device 21 and 22, func 0 */
+#define I5100_MTR_0    0x154   /* Memory Technology Registers 0-3 */
+#define I5100_DMIR     0x15c   /* DIMM Interleave Range */
+#define        I5100_VALIDLOG  0x18c   /* Valid Log Markers */
+#define        I5100_NRECMEMA  0x190   /* Non-Recoverable Memory Error Log Reg A */
+#define        I5100_NRECMEMB  0x194   /* Non-Recoverable Memory Error Log Reg B */
+#define        I5100_REDMEMA   0x198   /* Recoverable Memory Data Error Log Reg A */
+#define        I5100_REDMEMB   0x19c   /* Recoverable Memory Data Error Log Reg B */
+#define        I5100_RECMEMA   0x1a0   /* Recoverable Memory Error Log Reg A */
+#define        I5100_RECMEMB   0x1a4   /* Recoverable Memory Error Log Reg B */
+#define I5100_MTR_4    0x1b0   /* Memory Technology Registers 4,5 */
+
+/* bit field accessors */
+
+static inline u32 i5100_mc_errdeten(u32 mc)
+{
+       return mc >> 5 & 1;
+}
+
+static inline u16 i5100_spddata_rdo(u16 a)
+{
+       return a >> 15 & 1;
+}
+
+static inline u16 i5100_spddata_sbe(u16 a)
+{
+       return a >> 13 & 1;
+}
+
+static inline u16 i5100_spddata_busy(u16 a)
+{
+       return a >> 12 & 1;
+}
+
+static inline u16 i5100_spddata_data(u16 a)
+{
+       return a & ((1 << 8) - 1);
+}
+
+static inline u32 i5100_spdcmd_create(u32 dti, u32 ckovrd, u32 sa, u32 ba,
+                                     u32 data, u32 cmd)
+{
+       return  ((dti & ((1 << 4) - 1))  << 28) |
+               ((ckovrd & 1)            << 27) |
+               ((sa & ((1 << 3) - 1))   << 24) |
+               ((ba & ((1 << 8) - 1))   << 16) |
+               ((data & ((1 << 8) - 1)) <<  8) |
+               (cmd & 1);
+}
+
+static inline u16 i5100_tolm_tolm(u16 a)
+{
+       return a >> 12 & ((1 << 4) - 1);
+}
+
+static inline u16 i5100_mir_limit(u16 a)
+{
+       return a >> 4 & ((1 << 12) - 1);
+}
+
+static inline u16 i5100_mir_way1(u16 a)
+{
+       return a >> 1 & 1;
+}
+
+static inline u16 i5100_mir_way0(u16 a)
+{
+       return a & 1;
+}
+
+static inline u32 i5100_ferr_nf_mem_chan_indx(u32 a)
+{
+       return a >> 28 & 1;
+}
+
+static inline u32 i5100_ferr_nf_mem_any(u32 a)
+{
+       return a & I5100_FERR_NF_MEM_ANY_MASK;
+}
+
+static inline u32 i5100_nerr_nf_mem_any(u32 a)
+{
+       return i5100_ferr_nf_mem_any(a);
+}
+
+static inline u32 i5100_dmir_limit(u32 a)
+{
+       return a >> 16 & ((1 << 11) - 1);
+}
+
+static inline u32 i5100_dmir_rank(u32 a, u32 i)
+{
+       return a >> (4 * i) & ((1 << 2) - 1);
+}
+
+static inline u16 i5100_mtr_present(u16 a)
+{
+       return a >> 10 & 1;
+}
+
+static inline u16 i5100_mtr_ethrottle(u16 a)
+{
+       return a >> 9 & 1;
+}
+
+static inline u16 i5100_mtr_width(u16 a)
+{
+       return a >> 8 & 1;
+}
+
+static inline u16 i5100_mtr_numbank(u16 a)
+{
+       return a >> 6 & 1;
+}
+
+static inline u16 i5100_mtr_numrow(u16 a)
+{
+       return a >> 2 & ((1 << 2) - 1);
+}
+
+static inline u16 i5100_mtr_numcol(u16 a)
+{
+       return a & ((1 << 2) - 1);
+}
+
+
+static inline u32 i5100_validlog_redmemvalid(u32 a)
+{
+       return a >> 2 & 1;
+}
+
+static inline u32 i5100_validlog_recmemvalid(u32 a)
+{
+       return a >> 1 & 1;
+}
+
+static inline u32 i5100_validlog_nrecmemvalid(u32 a)
+{
+       return a & 1;
+}
+
+static inline u32 i5100_nrecmema_merr(u32 a)
+{
+       return a >> 15 & ((1 << 5) - 1);
+}
+
+static inline u32 i5100_nrecmema_bank(u32 a)
+{
+       return a >> 12 & ((1 << 3) - 1);
+}
+
+static inline u32 i5100_nrecmema_rank(u32 a)
+{
+       return a >>  8 & ((1 << 3) - 1);
+}
+
+static inline u32 i5100_nrecmema_dm_buf_id(u32 a)
+{
+       return a & ((1 << 8) - 1);
+}
+
+static inline u32 i5100_nrecmemb_cas(u32 a)
+{
+       return a >> 16 & ((1 << 13) - 1);
+}
+
+static inline u32 i5100_nrecmemb_ras(u32 a)
+{
+       return a & ((1 << 16) - 1);
+}
+
+static inline u32 i5100_redmemb_ecc_locator(u32 a)
+{
+       return a & ((1 << 18) - 1);
+}
+
+static inline u32 i5100_recmema_merr(u32 a)
+{
+       return i5100_nrecmema_merr(a);
+}
+
+static inline u32 i5100_recmema_bank(u32 a)
+{
+       return i5100_nrecmema_bank(a);
+}
+
+static inline u32 i5100_recmema_rank(u32 a)
+{
+       return i5100_nrecmema_rank(a);
+}
+
+static inline u32 i5100_recmema_dm_buf_id(u32 a)
+{
+       return i5100_nrecmema_dm_buf_id(a);
+}
+
+static inline u32 i5100_recmemb_cas(u32 a)
+{
+       return i5100_nrecmemb_cas(a);
+}
+
+static inline u32 i5100_recmemb_ras(u32 a)
+{
+       return i5100_nrecmemb_ras(a);
+}
+
+/* some generic limits */
+#define I5100_MAX_RANKS_PER_CTLR       6
+#define I5100_MAX_CTLRS                        2
+#define I5100_MAX_RANKS_PER_DIMM       4
+#define I5100_DIMM_ADDR_LINES          (6 - 3) /* 64 bits / 8 bits per byte */
+#define I5100_MAX_DIMM_SLOTS_PER_CTLR  4
+#define I5100_MAX_RANK_INTERLEAVE      4
+#define I5100_MAX_DMIRS                        5
+
+struct i5100_priv {
+       /* ranks on each dimm -- 0 maps to not present -- obtained via SPD */
+       int dimm_numrank[I5100_MAX_CTLRS][I5100_MAX_DIMM_SLOTS_PER_CTLR];
+
+       /*
+        * mainboard chip select map -- maps i5100 chip selects to
+        * DIMM slot chip selects.  In the case of only 4 ranks per
+        * controller, the mapping is fairly obvious but not unique.
+        * we map -1 -> NC and assume both controllers use the same
+        * map...
+        *
+        */
+       int dimm_csmap[I5100_MAX_DIMM_SLOTS_PER_CTLR][I5100_MAX_RANKS_PER_DIMM];
+
+       /* memory interleave range */
+       struct {
+               u64      limit;
+               unsigned way[2];
+       } mir[I5100_MAX_CTLRS];
+
+       /* adjusted memory interleave range register */
+       unsigned amir[I5100_MAX_CTLRS];
+
+       /* dimm interleave range */
+       struct {
+               unsigned rank[I5100_MAX_RANK_INTERLEAVE];
+               u64      limit;
+       } dmir[I5100_MAX_CTLRS][I5100_MAX_DMIRS];
+
+       /* memory technology registers... */
+       struct {
+               unsigned present;       /* 0 or 1 */
+               unsigned ethrottle;     /* 0 or 1 */
+               unsigned width;         /* 4 or 8 bits  */
+               unsigned numbank;       /* 2 or 3 lines */
+               unsigned numrow;        /* 13 .. 16 lines */
+               unsigned numcol;        /* 11 .. 12 lines */
+       } mtr[I5100_MAX_CTLRS][I5100_MAX_RANKS_PER_CTLR];
+
+       u64 tolm;               /* top of low memory in bytes */
+       unsigned ranksperctlr;  /* number of ranks per controller */
+
+       struct pci_dev *mc;     /* device 16 func 1 */
+       struct pci_dev *ch0mm;  /* device 21 func 0 */
+       struct pci_dev *ch1mm;  /* device 22 func 0 */
+};
+
+/* map a rank/ctlr to a slot number on the mainboard */
+static int i5100_rank_to_slot(const struct mem_ctl_info *mci,
+                             int ctlr, int rank)
+{
+       const struct i5100_priv *priv = mci->pvt_info;
+       int i;
+
+       for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) {
+               int j;
+               const int numrank = priv->dimm_numrank[ctlr][i];
+
+               for (j = 0; j < numrank; j++)
+                       if (priv->dimm_csmap[i][j] == rank)
+                               return i * 2 + ctlr;
+       }
+
+       return -1;
+}
+
+static const char *i5100_err_msg(unsigned err)
+{
+       static const char *merrs[] = {
+               "unknown", /* 0 */
+               "uncorrectable data ECC on replay", /* 1 */
+               "unknown", /* 2 */
+               "unknown", /* 3 */
+               "aliased uncorrectable demand data ECC", /* 4 */
+               "aliased uncorrectable spare-copy data ECC", /* 5 */
+               "aliased uncorrectable patrol data ECC", /* 6 */
+               "unknown", /* 7 */
+               "unknown", /* 8 */
+               "unknown", /* 9 */
+               "non-aliased uncorrectable demand data ECC", /* 10 */
+               "non-aliased uncorrectable spare-copy data ECC", /* 11 */
+               "non-aliased uncorrectable patrol data ECC", /* 12 */
+               "unknown", /* 13 */
+               "correctable demand data ECC", /* 14 */
+               "correctable spare-copy data ECC", /* 15 */
+               "correctable patrol data ECC", /* 16 */
+               "unknown", /* 17 */
+               "SPD protocol error", /* 18 */
+               "unknown", /* 19 */
+               "spare copy initiated", /* 20 */
+               "spare copy completed", /* 21 */
+       };
+       unsigned i;
+
+       for (i = 0; i < ARRAY_SIZE(merrs); i++)
+               if (1 << i & err)
+                       return merrs[i];
+
+       return "none";
+}
+
+/* convert csrow index into a rank (per controller -- 0..5) */
+static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow)
+{
+       const struct i5100_priv *priv = mci->pvt_info;
+
+       return csrow % priv->ranksperctlr;
+}
+
+/* convert csrow index into a controller (0..1) */
+static int i5100_csrow_to_cntlr(const struct mem_ctl_info *mci, int csrow)
+{
+       const struct i5100_priv *priv = mci->pvt_info;
+
+       return csrow / priv->ranksperctlr;
+}
+
+static unsigned i5100_rank_to_csrow(const struct mem_ctl_info *mci,
+                                   int ctlr, int rank)
+{
+       const struct i5100_priv *priv = mci->pvt_info;
+
+       return ctlr * priv->ranksperctlr + rank;
+}
+
+static void i5100_handle_ce(struct mem_ctl_info *mci,
+                           int ctlr,
+                           unsigned bank,
+                           unsigned rank,
+                           unsigned long syndrome,
+                           unsigned cas,
+                           unsigned ras,
+                           const char *msg)
+{
+       const int csrow = i5100_rank_to_csrow(mci, ctlr, rank);
+
+       printk(KERN_ERR
+               "CE ctlr %d, bank %u, rank %u, syndrome 0x%lx, "
+               "cas %u, ras %u, csrow %u, label \"%s\": %s\n",
+               ctlr, bank, rank, syndrome, cas, ras,
+               csrow, mci->csrows[csrow].channels[0].label, msg);
+
+       mci->ce_count++;
+       mci->csrows[csrow].ce_count++;
+       mci->csrows[csrow].channels[0].ce_count++;
+}
+
+static void i5100_handle_ue(struct mem_ctl_info *mci,
+                           int ctlr,
+                           unsigned bank,
+                           unsigned rank,
+                           unsigned long syndrome,
+                           unsigned cas,
+                           unsigned ras,
+                           const char *msg)
+{
+       const int csrow = i5100_rank_to_csrow(mci, ctlr, rank);
+
+       printk(KERN_ERR
+               "UE ctlr %d, bank %u, rank %u, syndrome 0x%lx, "
+               "cas %u, ras %u, csrow %u, label \"%s\": %s\n",
+               ctlr, bank, rank, syndrome, cas, ras,
+               csrow, mci->csrows[csrow].channels[0].label, msg);
+
+       mci->ue_count++;
+       mci->csrows[csrow].ue_count++;
+}
+
+static void i5100_read_log(struct mem_ctl_info *mci, int ctlr,
+                          u32 ferr, u32 nerr)
+{
+       struct i5100_priv *priv = mci->pvt_info;
+       struct pci_dev *pdev = (ctlr) ? priv->ch1mm : priv->ch0mm;
+       u32 dw;
+       u32 dw2;
+       unsigned syndrome = 0;
+       unsigned ecc_loc = 0;
+       unsigned merr;
+       unsigned bank;
+       unsigned rank;
+       unsigned cas;
+       unsigned ras;
+
+       pci_read_config_dword(pdev, I5100_VALIDLOG, &dw);
+
+       if (i5100_validlog_redmemvalid(dw)) {
+               pci_read_config_dword(pdev, I5100_REDMEMA, &dw2);
+               syndrome = dw2;
+               pci_read_config_dword(pdev, I5100_REDMEMB, &dw2);
+               ecc_loc = i5100_redmemb_ecc_locator(dw2);
+       }
+
+       if (i5100_validlog_recmemvalid(dw)) {
+               const char *msg;
+
+               pci_read_config_dword(pdev, I5100_RECMEMA, &dw2);
+               merr = i5100_recmema_merr(dw2);
+               bank = i5100_recmema_bank(dw2);
+               rank = i5100_recmema_rank(dw2);
+
+               pci_read_config_dword(pdev, I5100_RECMEMB, &dw2);
+               cas = i5100_recmemb_cas(dw2);
+               ras = i5100_recmemb_ras(dw2);
+
+               /* FIXME:  not really sure if this is what merr is...
+                */
+               if (!merr)
+                       msg = i5100_err_msg(ferr);
+               else
+                       msg = i5100_err_msg(nerr);
+
+               i5100_handle_ce(mci, ctlr, bank, rank, syndrome, cas, ras, msg);
+       }
+
+       if (i5100_validlog_nrecmemvalid(dw)) {
+               const char *msg;
+
+               pci_read_config_dword(pdev, I5100_NRECMEMA, &dw2);
+               merr = i5100_nrecmema_merr(dw2);
+               bank = i5100_nrecmema_bank(dw2);
+               rank = i5100_nrecmema_rank(dw2);
+
+               pci_read_config_dword(pdev, I5100_NRECMEMB, &dw2);
+               cas = i5100_nrecmemb_cas(dw2);
+               ras = i5100_nrecmemb_ras(dw2);
+
+               /* FIXME:  not really sure if this is what merr is...
+                */
+               if (!merr)
+                       msg = i5100_err_msg(ferr);
+               else
+                       msg = i5100_err_msg(nerr);
+
+               i5100_handle_ue(mci, ctlr, bank, rank, syndrome, cas, ras, msg);
+       }
+
+       pci_write_config_dword(pdev, I5100_VALIDLOG, dw);
+}
+
+static void i5100_check_error(struct mem_ctl_info *mci)
+{
+       struct i5100_priv *priv = mci->pvt_info;
+       u32 dw;
+
+
+       pci_read_config_dword(priv->mc, I5100_FERR_NF_MEM, &dw);
+       if (i5100_ferr_nf_mem_any(dw)) {
+               u32 dw2;
+
+               pci_read_config_dword(priv->mc, I5100_NERR_NF_MEM, &dw2);
+               if (dw2)
+                       pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM,
+                                              dw2);
+               pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw);
+
+               i5100_read_log(mci, i5100_ferr_nf_mem_chan_indx(dw),
+                              i5100_ferr_nf_mem_any(dw),
+                              i5100_nerr_nf_mem_any(dw2));
+       }
+}
+
+static struct pci_dev *pci_get_device_func(unsigned vendor,
+                                          unsigned device,
+                                          unsigned func)
+{
+       struct pci_dev *ret = NULL;
+
+       while (1) {
+               ret = pci_get_device(vendor, device, ret);
+
+               if (!ret)
+                       break;
+
+               if (PCI_FUNC(ret->devfn) == func)
+                       break;
+       }
+
+       return ret;
+}
+
+static unsigned long __devinit i5100_npages(struct mem_ctl_info *mci,
+                                           int csrow)
+{
+       struct i5100_priv *priv = mci->pvt_info;
+       const unsigned ctlr_rank = i5100_csrow_to_rank(mci, csrow);
+       const unsigned ctlr = i5100_csrow_to_cntlr(mci, csrow);
+       unsigned addr_lines;
+
+       /* dimm present? */
+       if (!priv->mtr[ctlr][ctlr_rank].present)
+               return 0ULL;
+
+       addr_lines =
+               I5100_DIMM_ADDR_LINES +
+               priv->mtr[ctlr][ctlr_rank].numcol +
+               priv->mtr[ctlr][ctlr_rank].numrow +
+               priv->mtr[ctlr][ctlr_rank].numbank;
+
+       return (unsigned long)
+               ((unsigned long long) (1ULL << addr_lines) / PAGE_SIZE);
+}
+
+static void __devinit i5100_init_mtr(struct mem_ctl_info *mci)
+{
+       struct i5100_priv *priv = mci->pvt_info;
+       struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm };
+       int i;
+
+       for (i = 0; i < I5100_MAX_CTLRS; i++) {
+               int j;
+               struct pci_dev *pdev = mms[i];
+
+               for (j = 0; j < I5100_MAX_RANKS_PER_CTLR; j++) {
+                       const unsigned addr =
+                               (j < 4) ? I5100_MTR_0 + j * 2 :
+                                         I5100_MTR_4 + (j - 4) * 2;
+                       u16 w;
+
+                       pci_read_config_word(pdev, addr, &w);
+
+                       priv->mtr[i][j].present = i5100_mtr_present(w);
+                       priv->mtr[i][j].ethrottle = i5100_mtr_ethrottle(w);
+                       priv->mtr[i][j].width = 4 + 4 * i5100_mtr_width(w);
+                       priv->mtr[i][j].numbank = 2 + i5100_mtr_numbank(w);
+                       priv->mtr[i][j].numrow = 13 + i5100_mtr_numrow(w);
+                       priv->mtr[i][j].numcol = 10 + i5100_mtr_numcol(w);
+               }
+       }
+}
+
+/*
+ * FIXME: make this into a real i2c adapter (so that dimm-decode
+ * will work)?
+ */
+static int i5100_read_spd_byte(const struct mem_ctl_info *mci,
+                              u8 ch, u8 slot, u8 addr, u8 *byte)
+{
+       struct i5100_priv *priv = mci->pvt_info;
+       u16 w;
+       unsigned long et;
+
+       pci_read_config_word(priv->mc, I5100_SPDDATA, &w);
+       if (i5100_spddata_busy(w))
+               return -1;
+
+       pci_write_config_dword(priv->mc, I5100_SPDCMD,
+                              i5100_spdcmd_create(0xa, 1, ch * 4 + slot, addr,
+                                                  0, 0));
+
+       /* wait up to 100ms */
+       et = jiffies + HZ / 10;
+       udelay(100);
+       while (1) {
+               pci_read_config_word(priv->mc, I5100_SPDDATA, &w);
+               if (!i5100_spddata_busy(w))
+                       break;
+               udelay(100);
+       }
+
+       if (!i5100_spddata_rdo(w) || i5100_spddata_sbe(w))
+               return -1;
+
+       *byte = i5100_spddata_data(w);
+
+       return 0;
+}
+
+/*
+ * fill dimm chip select map
+ *
+ * FIXME:
+ *   o only valid for 4 ranks per controller
+ *   o not the only way to may chip selects to dimm slots
+ *   o investigate if there is some way to obtain this map from the bios
+ */
+static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci)
+{
+       struct i5100_priv *priv = mci->pvt_info;
+       int i;
+
+       WARN_ON(priv->ranksperctlr != 4);
+
+       for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) {
+               int j;
+
+               for (j = 0; j < I5100_MAX_RANKS_PER_DIMM; j++)
+                       priv->dimm_csmap[i][j] = -1; /* default NC */
+       }
+
+       /* only 2 chip selects per slot... */
+       priv->dimm_csmap[0][0] = 0;
+       priv->dimm_csmap[0][1] = 3;
+       priv->dimm_csmap[1][0] = 1;
+       priv->dimm_csmap[1][1] = 2;
+       priv->dimm_csmap[2][0] = 2;
+       priv->dimm_csmap[3][0] = 3;
+}
+
+static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev,
+                                            struct mem_ctl_info *mci)
+{
+       struct i5100_priv *priv = mci->pvt_info;
+       int i;
+
+       for (i = 0; i < I5100_MAX_CTLRS; i++) {
+               int j;
+
+               for (j = 0; j < I5100_MAX_DIMM_SLOTS_PER_CTLR; j++) {
+                       u8 rank;
+
+                       if (i5100_read_spd_byte(mci, i, j, 5, &rank) < 0)
+                               priv->dimm_numrank[i][j] = 0;
+                       else
+                               priv->dimm_numrank[i][j] = (rank & 3) + 1;
+               }
+       }
+
+       i5100_init_dimm_csmap(mci);
+}
+
+static void __devinit i5100_init_interleaving(struct pci_dev *pdev,
+                                             struct mem_ctl_info *mci)
+{
+       u16 w;
+       u32 dw;
+       struct i5100_priv *priv = mci->pvt_info;
+       struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm };
+       int i;
+
+       pci_read_config_word(pdev, I5100_TOLM, &w);
+       priv->tolm = (u64) i5100_tolm_tolm(w) * 256 * 1024 * 1024;
+
+       pci_read_config_word(pdev, I5100_MIR0, &w);
+       priv->mir[0].limit = (u64) i5100_mir_limit(w) << 28;
+       priv->mir[0].way[1] = i5100_mir_way1(w);
+       priv->mir[0].way[0] = i5100_mir_way0(w);
+
+       pci_read_config_word(pdev, I5100_MIR1, &w);
+       priv->mir[1].limit = (u64) i5100_mir_limit(w) << 28;
+       priv->mir[1].way[1] = i5100_mir_way1(w);
+       priv->mir[1].way[0] = i5100_mir_way0(w);
+
+       pci_read_config_word(pdev, I5100_AMIR_0, &w);
+       priv->amir[0] = w;
+       pci_read_config_word(pdev, I5100_AMIR_1, &w);
+       priv->amir[1] = w;
+
+       for (i = 0; i < I5100_MAX_CTLRS; i++) {
+               int j;
+
+               for (j = 0; j < 5; j++) {
+                       int k;
+
+                       pci_read_config_dword(mms[i], I5100_DMIR + j * 4, &dw);
+
+                       priv->dmir[i][j].limit =
+                               (u64) i5100_dmir_limit(dw) << 28;
+                       for (k = 0; k < I5100_MAX_RANKS_PER_DIMM; k++)
+                               priv->dmir[i][j].rank[k] =
+                                       i5100_dmir_rank(dw, k);
+               }
+       }
+
+       i5100_init_mtr(mci);
+}
+
+static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
+{
+       int i;
+       unsigned long total_pages = 0UL;
+       struct i5100_priv *priv = mci->pvt_info;
+
+       for (i = 0; i < mci->nr_csrows; i++) {
+               const unsigned long npages = i5100_npages(mci, i);
+               const unsigned cntlr = i5100_csrow_to_cntlr(mci, i);
+               const unsigned rank = i5100_csrow_to_rank(mci, i);
+
+               if (!npages)
+                       continue;
+
+               /*
+                * FIXME: these two are totally bogus -- I don't see how to
+                * map them correctly to this structure...
+                */
+               mci->csrows[i].first_page = total_pages;
+               mci->csrows[i].last_page = total_pages + npages - 1;
+               mci->csrows[i].page_mask = 0UL;
+
+               mci->csrows[i].nr_pages = npages;
+               mci->csrows[i].grain = 32;
+               mci->csrows[i].csrow_idx = i;
+               mci->csrows[i].dtype =
+                       (priv->mtr[cntlr][rank].width == 4) ? DEV_X4 : DEV_X8;
+               mci->csrows[i].ue_count = 0;
+               mci->csrows[i].ce_count = 0;
+               mci->csrows[i].mtype = MEM_RDDR2;
+               mci->csrows[i].edac_mode = EDAC_SECDED;
+               mci->csrows[i].mci = mci;
+               mci->csrows[i].nr_channels = 1;
+               mci->csrows[i].channels[0].chan_idx = 0;
+               mci->csrows[i].channels[0].ce_count = 0;
+               mci->csrows[i].channels[0].csrow = mci->csrows + i;
+               snprintf(mci->csrows[i].channels[0].label,
+                        sizeof(mci->csrows[i].channels[0].label),
+                        "DIMM%u", i5100_rank_to_slot(mci, cntlr, rank));
+
+               total_pages += npages;
+       }
+}
+
+static int __devinit i5100_init_one(struct pci_dev *pdev,
+                                   const struct pci_device_id *id)
+{
+       int rc;
+       struct mem_ctl_info *mci;
+       struct i5100_priv *priv;
+       struct pci_dev *ch0mm, *ch1mm;
+       int ret = 0;
+       u32 dw;
+       int ranksperch;
+
+       if (PCI_FUNC(pdev->devfn) != 1)
+               return -ENODEV;
+
+       rc = pci_enable_device(pdev);
+       if (rc < 0) {
+               ret = rc;
+               goto bail;
+       }
+
+       /* ECC enabled? */
+       pci_read_config_dword(pdev, I5100_MC, &dw);
+       if (!i5100_mc_errdeten(dw)) {
+               printk(KERN_INFO "i5100_edac: ECC not enabled.\n");
+               ret = -ENODEV;
+               goto bail_pdev;
+       }
+
+       /* figure out how many ranks, from strapped state of 48GB_Mode input */
+       pci_read_config_dword(pdev, I5100_MS, &dw);
+       ranksperch = !!(dw & (1 << 8)) * 2 + 4;
+
+       if (ranksperch != 4) {
+               /* FIXME: get 6 ranks / controller to work - need hw... */
+               printk(KERN_INFO "i5100_edac: unsupported configuration.\n");
+               ret = -ENODEV;
+               goto bail_pdev;
+       }
+
+       /* enable error reporting... */
+       pci_read_config_dword(pdev, I5100_EMASK_MEM, &dw);
+       dw &= ~I5100_FERR_NF_MEM_ANY_MASK;
+       pci_write_config_dword(pdev, I5100_EMASK_MEM, dw);
+
+       /* device 21, func 0, Channel 0 Memory Map, Error Flag/Mask, etc... */
+       ch0mm = pci_get_device_func(PCI_VENDOR_ID_INTEL,
+                                   PCI_DEVICE_ID_INTEL_5100_21, 0);
+       if (!ch0mm) {
+               ret = -ENODEV;
+               goto bail_pdev;
+       }
+
+       rc = pci_enable_device(ch0mm);
+       if (rc < 0) {
+               ret = rc;
+               goto bail_ch0;
+       }
+
+       /* device 22, func 0, Channel 1 Memory Map, Error Flag/Mask, etc... */
+       ch1mm = pci_get_device_func(PCI_VENDOR_ID_INTEL,
+                                   PCI_DEVICE_ID_INTEL_5100_22, 0);
+       if (!ch1mm) {
+               ret = -ENODEV;
+               goto bail_disable_ch0;
+       }
+
+       rc = pci_enable_device(ch1mm);
+       if (rc < 0) {
+               ret = rc;
+               goto bail_ch1;
+       }
+
+       mci = edac_mc_alloc(sizeof(*priv), ranksperch * 2, 1, 0);
+       if (!mci) {
+               ret = -ENOMEM;
+               goto bail_disable_ch1;
+       }
+
+       mci->dev = &pdev->dev;
+
+       priv = mci->pvt_info;
+       priv->ranksperctlr = ranksperch;
+       priv->mc = pdev;
+       priv->ch0mm = ch0mm;
+       priv->ch1mm = ch1mm;
+
+       i5100_init_dimm_layout(pdev, mci);
+       i5100_init_interleaving(pdev, mci);
+
+       mci->mtype_cap = MEM_FLAG_FB_DDR2;
+       mci->edac_ctl_cap = EDAC_FLAG_SECDED;
+       mci->edac_cap = EDAC_FLAG_SECDED;
+       mci->mod_name = "i5100_edac.c";
+       mci->mod_ver = "not versioned";
+       mci->ctl_name = "i5100";
+       mci->dev_name = pci_name(pdev);
+       mci->ctl_page_to_phys = NULL;
+
+       mci->edac_check = i5100_check_error;
+
+       i5100_init_csrows(mci);
+
+       /* this strange construction seems to be in every driver, dunno why */
+       switch (edac_op_state) {
+       case EDAC_OPSTATE_POLL:
+       case EDAC_OPSTATE_NMI:
+               break;
+       default:
+               edac_op_state = EDAC_OPSTATE_POLL;
+               break;
+       }
+
+       if (edac_mc_add_mc(mci)) {
+               ret = -ENODEV;
+               goto bail_mc;
+       }
+
+       return ret;
+
+bail_mc:
+       edac_mc_free(mci);
+
+bail_disable_ch1:
+       pci_disable_device(ch1mm);
+
+bail_ch1:
+       pci_dev_put(ch1mm);
+
+bail_disable_ch0:
+       pci_disable_device(ch0mm);
+
+bail_ch0:
+       pci_dev_put(ch0mm);
+
+bail_pdev:
+       pci_disable_device(pdev);
+
+bail:
+       return ret;
+}
+
+static void __devexit i5100_remove_one(struct pci_dev *pdev)
+{
+       struct mem_ctl_info *mci;
+       struct i5100_priv *priv;
+
+       mci = edac_mc_del_mc(&pdev->dev);
+
+       if (!mci)
+               return;
+
+       priv = mci->pvt_info;
+       pci_disable_device(pdev);
+       pci_disable_device(priv->ch0mm);
+       pci_disable_device(priv->ch1mm);
+       pci_dev_put(priv->ch0mm);
+       pci_dev_put(priv->ch1mm);
+
+       edac_mc_free(mci);
+}
+
+static const struct pci_device_id i5100_pci_tbl[] __devinitdata = {
+       /* Device 16, Function 0, Channel 0 Memory Map, Error Flag/Mask, ... */
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_16) },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, i5100_pci_tbl);
+
+static struct pci_driver i5100_driver = {
+       .name = KBUILD_BASENAME,
+       .probe = i5100_init_one,
+       .remove = __devexit_p(i5100_remove_one),
+       .id_table = i5100_pci_tbl,
+};
+
+static int __init i5100_init(void)
+{
+       int pci_rc;
+
+       pci_rc = pci_register_driver(&i5100_driver);
+
+       return (pci_rc < 0) ? pci_rc : 0;
+}
+
+static void __exit i5100_exit(void)
+{
+       pci_unregister_driver(&i5100_driver);
+}
+
+module_init(i5100_init);
+module_exit(i5100_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR
+    ("Arthur Jones <ajones@riverbed.com>");
+MODULE_DESCRIPTION("MC Driver for Intel I5100 memory controllers");
index d49361bfe670e09a4af2dfae7ec99d9646851716..2265d9ca1535652018fb9f28f87f3d7ba447231c 100644 (file)
@@ -195,14 +195,15 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev)
+static int __devinit mpc85xx_pci_err_probe(struct of_device *op,
+                                          const struct of_device_id *match)
 {
        struct edac_pci_ctl_info *pci;
        struct mpc85xx_pci_pdata *pdata;
-       struct resource *r;
+       struct resource r;
        int res = 0;
 
-       if (!devres_open_group(&pdev->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
+       if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
                return -ENOMEM;
 
        pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mpc85xx_pci_err");
@@ -212,34 +213,37 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev)
        pdata = pci->pvt_info;
        pdata->name = "mpc85xx_pci_err";
        pdata->irq = NO_IRQ;
-       platform_set_drvdata(pdev, pci);
-       pci->dev = &pdev->dev;
+       dev_set_drvdata(&op->dev, pci);
+       pci->dev = &op->dev;
        pci->mod_name = EDAC_MOD_STR;
        pci->ctl_name = pdata->name;
-       pci->dev_name = pdev->dev.bus_id;
+       pci->dev_name = op->dev.bus_id;
 
        if (edac_op_state == EDAC_OPSTATE_POLL)
                pci->edac_check = mpc85xx_pci_check;
 
        pdata->edac_idx = edac_pci_idx++;
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
+       res = of_address_to_resource(op->node, 0, &r);
+       if (res) {
                printk(KERN_ERR "%s: Unable to get resource for "
                       "PCI err regs\n", __func__);
                goto err;
        }
 
-       if (!devm_request_mem_region(&pdev->dev, r->start,
-                                    r->end - r->start + 1, pdata->name)) {
+       /* we only need the error registers */
+       r.start += 0xe00;
+
+       if (!devm_request_mem_region(&op->dev, r.start,
+                                       r.end - r.start + 1, pdata->name)) {
                printk(KERN_ERR "%s: Error while requesting mem region\n",
                       __func__);
                res = -EBUSY;
                goto err;
        }
 
-       pdata->pci_vbase = devm_ioremap(&pdev->dev, r->start,
-                                       r->end - r->start + 1);
+       pdata->pci_vbase = devm_ioremap(&op->dev, r.start,
+                                       r.end - r.start + 1);
        if (!pdata->pci_vbase) {
                printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
                res = -ENOMEM;
@@ -266,14 +270,15 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev)
        }
 
        if (edac_op_state == EDAC_OPSTATE_INT) {
-               pdata->irq = platform_get_irq(pdev, 0);
-               res = devm_request_irq(&pdev->dev, pdata->irq,
+               pdata->irq = irq_of_parse_and_map(op->node, 0);
+               res = devm_request_irq(&op->dev, pdata->irq,
                                       mpc85xx_pci_isr, IRQF_DISABLED,
                                       "[EDAC] PCI err", pci);
                if (res < 0) {
                        printk(KERN_ERR
                               "%s: Unable to requiest irq %d for "
                               "MPC85xx PCI err\n", __func__, pdata->irq);
+                       irq_dispose_mapping(pdata->irq);
                        res = -ENODEV;
                        goto err2;
                }
@@ -282,23 +287,23 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev)
                       pdata->irq);
        }
 
-       devres_remove_group(&pdev->dev, mpc85xx_pci_err_probe);
+       devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
        debugf3("%s(): success\n", __func__);
        printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n");
 
        return 0;
 
 err2:
-       edac_pci_del_device(&pdev->dev);
+       edac_pci_del_device(&op->dev);
 err:
        edac_pci_free_ctl_info(pci);
-       devres_release_group(&pdev->dev, mpc85xx_pci_err_probe);
+       devres_release_group(&op->dev, mpc85xx_pci_err_probe);
        return res;
 }
 
-static int mpc85xx_pci_err_remove(struct platform_device *pdev)
+static int mpc85xx_pci_err_remove(struct of_device *op)
 {
-       struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
+       struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev);
        struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
 
        debugf0("%s()\n", __func__);
@@ -318,12 +323,26 @@ static int mpc85xx_pci_err_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct platform_driver mpc85xx_pci_err_driver = {
+static struct of_device_id mpc85xx_pci_err_of_match[] = {
+       {
+        .compatible = "fsl,mpc8540-pcix",
+        },
+       {
+        .compatible = "fsl,mpc8540-pci",
+       },
+       {},
+};
+
+static struct of_platform_driver mpc85xx_pci_err_driver = {
+       .owner = THIS_MODULE,
+       .name = "mpc85xx_pci_err",
+       .match_table = mpc85xx_pci_err_of_match,
        .probe = mpc85xx_pci_err_probe,
        .remove = __devexit_p(mpc85xx_pci_err_remove),
        .driver = {
-               .name = "mpc85xx_pci_err",
-       }
+                  .name = "mpc85xx_pci_err",
+                  .owner = THIS_MODULE,
+                  },
 };
 
 #endif                         /* CONFIG_PCI */
@@ -1002,7 +1021,7 @@ static int __init mpc85xx_mc_init(void)
                printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
 
 #ifdef CONFIG_PCI
-       res = platform_driver_register(&mpc85xx_pci_err_driver);
+       res = of_register_platform_driver(&mpc85xx_pci_err_driver);
        if (res)
                printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
 #endif
@@ -1025,7 +1044,7 @@ static void __exit mpc85xx_mc_exit(void)
 {
        mtspr(SPRN_HID1, orig_hid1);
 #ifdef CONFIG_PCI
-       platform_driver_unregister(&mpc85xx_pci_err_driver);
+       of_unregister_platform_driver(&mpc85xx_pci_err_driver);
 #endif
        of_unregister_platform_driver(&mpc85xx_l2_err_driver);
        of_unregister_platform_driver(&mpc85xx_mc_err_driver);
index bf071f140a054c492e16321bdf33bd2c06f6599d..083ce8d0c63d78c009c45588e55ac9c85ac665c4 100644 (file)
@@ -71,6 +71,35 @@ static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+/*
+ * Bit 0 of MV64x60_PCIx_ERR_MASK does not exist on the 64360 and because of
+ * errata FEr-#11 and FEr-##16 for the 64460, it should be 0 on that chip as
+ * well.  IOW, don't set bit 0.
+ */
+
+/* Erratum FEr PCI-#16: clear bit 0 of PCI SERRn Mask reg. */
+static int __init mv64x60_pci_fixup(struct platform_device *pdev)
+{
+       struct resource *r;
+       void __iomem *pci_serr;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!r) {
+               printk(KERN_ERR "%s: Unable to get resource for "
+                      "PCI err regs\n", __func__);
+               return -ENOENT;
+       }
+
+       pci_serr = ioremap(r->start, r->end - r->start + 1);
+       if (!pci_serr)
+               return -ENOMEM;
+
+       out_le32(pci_serr, in_le32(pci_serr) & ~0x1);
+       iounmap(pci_serr);
+
+       return 0;
+}
+
 static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev)
 {
        struct edac_pci_ctl_info *pci;
@@ -128,6 +157,12 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev)
                goto err;
        }
 
+       res = mv64x60_pci_fixup(pdev);
+       if (res < 0) {
+               printk(KERN_ERR "%s: PCI fixup failed\n", __func__);
+               goto err;
+       }
+
        out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0);
        out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0);
        out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK,
@@ -612,7 +647,7 @@ static void get_total_mem(struct mv64x60_mc_pdata *pdata)
        if (!np)
                return;
 
-       reg = get_property(np, "reg", NULL);
+       reg = of_get_property(np, "reg", NULL);
 
        pdata->total_mem = reg[1];
 }
index 76f26710fc16393bbecb80310924789798d2f718..fa6d6abefd4d14d9bdb8c372118a1ddbcea7b2fb 100644 (file)
@@ -16,8 +16,13 @@ config FIREWIRE
          enable the new stack.
 
          To compile this driver as a module, say M here: the module will be
-         called firewire-core.  It functionally replaces ieee1394, raw1394,
-         and video1394.
+         called firewire-core.
+
+         This module functionally replaces ieee1394, raw1394, and video1394.
+         To access it from application programs, you generally need at least
+         libraw1394 version 2.  IIDC/DCAM applications also need libdc1394
+         version 2.  No libraries are required to access storage devices
+         through the firewire-sbp2 driver.
 
 config FIREWIRE_OHCI
        tristate "OHCI-1394 controllers"
index da873d795aad94bccf9e88a58a4b9bde9821daf1..bbd73a406e537106a2eeda4ba4a2ba1a543b030d 100644 (file)
@@ -539,7 +539,7 @@ fw_core_remove_card(struct fw_card *card)
        wait_for_completion(&card->done);
 
        cancel_delayed_work_sync(&card->work);
-       fw_flush_transactions(card);
+       WARN_ON(!list_empty(&card->transaction_list));
        del_timer_sync(&card->flush_timer);
 }
 EXPORT_SYMBOL(fw_core_remove_card);
index c639915fc3cbc8637c39d93927488b1350001cc6..bc81d6fcd2fd2bbc043f31d8707aaaaf3d34a01a 100644 (file)
@@ -382,9 +382,9 @@ complete_transaction(struct fw_card *card, int rcode,
 
        response->response.type   = FW_CDEV_EVENT_RESPONSE;
        response->response.rcode  = rcode;
-       queue_event(client, &response->event,
-                   &response->response, sizeof(response->response),
-                   response->response.data, response->response.length);
+       queue_event(client, &response->event, &response->response,
+                   sizeof(response->response) + response->response.length,
+                   NULL, 0);
 }
 
 static int ioctl_send_request(struct client *client, void *buffer)
index bcbe794a3ea5ca3198df3c1593ef696edf0f716c..e14c03dc006588d1b98d0b10ded8bd210d8fdb8d 100644 (file)
@@ -50,7 +50,7 @@ fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
 
                address = dma_map_page(card->device, buffer->pages[i],
                                       0, PAGE_SIZE, direction);
-               if (dma_mapping_error(address)) {
+               if (dma_mapping_error(card->device, address)) {
                        __free_page(buffer->pages[i]);
                        goto out_pages;
                }
index 333b12544dd1b0991bd9cc22ac079e2f3313210a..251416f2148f36c72cdd8afa0ac74a792c7db5fa 100644 (file)
@@ -171,7 +171,6 @@ struct iso_context {
 struct fw_ohci {
        struct fw_card card;
 
-       u32 version;
        __iomem char *registers;
        dma_addr_t self_id_bus;
        __le32 *self_id_cpu;
@@ -180,6 +179,8 @@ struct fw_ohci {
        int generation;
        int request_generation; /* for timestamping incoming requests */
        u32 bus_seconds;
+
+       bool use_dualbuffer;
        bool old_uninorth;
        bool bus_reset_packet_quirk;
 
@@ -953,7 +954,7 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
                payload_bus =
                        dma_map_single(ohci->card.device, packet->payload,
                                       packet->payload_length, DMA_TO_DEVICE);
-               if (dma_mapping_error(payload_bus)) {
+               if (dma_mapping_error(ohci->card.device, payload_bus)) {
                        packet->ack = RCODE_SEND_ERROR;
                        return -1;
                }
@@ -1885,7 +1886,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
        } else {
                mask = &ohci->ir_context_mask;
                list = ohci->ir_context_list;
-               if (ohci->version >= OHCI_VERSION_1_1)
+               if (ohci->use_dualbuffer)
                        callback = handle_ir_dualbuffer_packet;
                else
                        callback = handle_ir_packet_per_buffer;
@@ -1949,7 +1950,7 @@ static int ohci_start_iso(struct fw_iso_context *base,
        } else {
                index = ctx - ohci->ir_context_list;
                control = IR_CONTEXT_ISOCH_HEADER;
-               if (ohci->version >= OHCI_VERSION_1_1)
+               if (ohci->use_dualbuffer)
                        control |= IR_CONTEXT_DUAL_BUFFER_MODE;
                match = (tags << 28) | (sync << 8) | ctx->base.channel;
                if (cycle >= 0) {
@@ -2279,7 +2280,7 @@ ohci_queue_iso(struct fw_iso_context *base,
        spin_lock_irqsave(&ctx->context.ohci->lock, flags);
        if (base->type == FW_ISO_CONTEXT_TRANSMIT)
                retval = ohci_queue_iso_transmit(base, packet, buffer, payload);
-       else if (ctx->context.ohci->version >= OHCI_VERSION_1_1)
+       else if (ctx->context.ohci->use_dualbuffer)
                retval = ohci_queue_iso_receive_dualbuffer(base, packet,
                                                         buffer, payload);
        else
@@ -2341,7 +2342,7 @@ static int __devinit
 pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
        struct fw_ohci *ohci;
-       u32 bus_options, max_receive, link_speed;
+       u32 bus_options, max_receive, link_speed, version;
        u64 guid;
        int err;
        size_t size;
@@ -2366,12 +2367,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
        pci_set_drvdata(dev, ohci);
 
-#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
-       ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
-                            dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
-#endif
-       ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
-
        spin_lock_init(&ohci->lock);
 
        tasklet_init(&ohci->bus_reset_tasklet,
@@ -2390,6 +2385,23 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
                goto fail_iomem;
        }
 
+       version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
+       ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
+
+/* x86-32 currently doesn't use highmem for dma_alloc_coherent */
+#if !defined(CONFIG_X86_32)
+       /* dual-buffer mode is broken with descriptor addresses above 2G */
+       if (dev->vendor == PCI_VENDOR_ID_TI &&
+           dev->device == PCI_DEVICE_ID_TI_TSB43AB22)
+               ohci->use_dualbuffer = false;
+#endif
+
+#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
+       ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
+                            dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
+#endif
+       ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
+
        ar_context_init(&ohci->ar_request_ctx, ohci,
                        OHCI1394_AsReqRcvContextControlSet);
 
@@ -2441,9 +2453,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        if (err < 0)
                goto fail_self_id;
 
-       ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
        fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
-                 dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff);
+                 dev->dev.bus_id, version >> 16, version & 0xff);
        return 0;
 
  fail_self_id:
index 53fc5a641e6d85de37c5c40b3147d4df009b72a6..aaff50ebba1def2892a8945be8b9289d39921c4f 100644 (file)
@@ -543,7 +543,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
        orb->response_bus =
                dma_map_single(device->card->device, &orb->response,
                               sizeof(orb->response), DMA_FROM_DEVICE);
-       if (dma_mapping_error(orb->response_bus))
+       if (dma_mapping_error(device->card->device, orb->response_bus))
                goto fail_mapping_response;
 
        orb->request.response.high = 0;
@@ -577,7 +577,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
        orb->base.request_bus =
                dma_map_single(device->card->device, &orb->request,
                               sizeof(orb->request), DMA_TO_DEVICE);
-       if (dma_mapping_error(orb->base.request_bus))
+       if (dma_mapping_error(device->card->device, orb->base.request_bus))
                goto fail_mapping_request;
 
        sbp2_send_orb(&orb->base, lu, node_id, generation,
@@ -1424,7 +1424,7 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
        orb->page_table_bus =
                dma_map_single(device->card->device, orb->page_table,
                               sizeof(orb->page_table), DMA_TO_DEVICE);
-       if (dma_mapping_error(orb->page_table_bus))
+       if (dma_mapping_error(device->card->device, orb->page_table_bus))
                goto fail_page_table;
 
        /*
@@ -1509,7 +1509,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
        orb->base.request_bus =
                dma_map_single(device->card->device, &orb->request,
                               sizeof(orb->request), DMA_TO_DEVICE);
-       if (dma_mapping_error(orb->base.request_bus))
+       if (dma_mapping_error(device->card->device, orb->base.request_bus))
                goto out;
 
        sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, lu->generation,
index 213b0ff8f3d6dd55d5edf5af91efdc21a50b638b..c1b81077c4a82b6e15bc528b314dfa87a73e1c35 100644 (file)
@@ -510,8 +510,6 @@ fw_core_handle_bus_reset(struct fw_card *card,
        struct fw_node *local_node;
        unsigned long flags;
 
-       fw_flush_transactions(card);
-
        spin_lock_irqsave(&card->lock, flags);
 
        /*
index 40db8075227259c849007a92b4ea9c045745d9b2..e5d1a0b64fcf1b714a186d31a8b7aabf90e7aa97 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/kref.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
@@ -151,7 +152,7 @@ transmit_complete_callback(struct fw_packet *packet,
 
 static void
 fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
-               int node_id, int source_id, int generation, int speed,
+               int destination_id, int source_id, int generation, int speed,
                unsigned long long offset, void *payload, size_t length)
 {
        int ext_tcode;
@@ -166,7 +167,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
                HEADER_RETRY(RETRY_X) |
                HEADER_TLABEL(tlabel) |
                HEADER_TCODE(tcode) |
-               HEADER_DESTINATION(node_id);
+               HEADER_DESTINATION(destination_id);
        packet->header[1] =
                HEADER_OFFSET_HIGH(offset >> 32) | HEADER_SOURCE(source_id);
        packet->header[2] =
@@ -252,7 +253,7 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
                fw_transaction_callback_t callback, void *callback_data)
 {
        unsigned long flags;
-       int tlabel, source;
+       int tlabel;
 
        /*
         * Bump the flush timer up 100ms first of all so we
@@ -268,7 +269,6 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
 
        spin_lock_irqsave(&card->lock, flags);
 
-       source = card->node_id;
        tlabel = card->current_tlabel;
        if (card->tlabel_mask & (1 << tlabel)) {
                spin_unlock_irqrestore(&card->lock, flags);
@@ -279,77 +279,58 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
        card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
        card->tlabel_mask |= (1 << tlabel);
 
-       list_add_tail(&t->link, &card->transaction_list);
-
-       spin_unlock_irqrestore(&card->lock, flags);
-
-       /* Initialize rest of transaction, fill out packet and send it. */
        t->node_id = node_id;
        t->tlabel = tlabel;
        t->callback = callback;
        t->callback_data = callback_data;
 
-       fw_fill_request(&t->packet, tcode, t->tlabel,
-                       node_id, source, generation,
-                       speed, offset, payload, length);
+       fw_fill_request(&t->packet, tcode, t->tlabel, node_id, card->node_id,
+                       generation, speed, offset, payload, length);
        t->packet.callback = transmit_complete_callback;
 
+       list_add_tail(&t->link, &card->transaction_list);
+
+       spin_unlock_irqrestore(&card->lock, flags);
+
        card->driver->send_request(card, &t->packet);
 }
 EXPORT_SYMBOL(fw_send_request);
 
-struct fw_phy_packet {
-       struct fw_packet packet;
-       struct completion done;
-       struct kref kref;
-};
-
-static void phy_packet_release(struct kref *kref)
-{
-       struct fw_phy_packet *p =
-                       container_of(kref, struct fw_phy_packet, kref);
-       kfree(p);
-}
+static DEFINE_MUTEX(phy_config_mutex);
+static DECLARE_COMPLETION(phy_config_done);
 
 static void transmit_phy_packet_callback(struct fw_packet *packet,
                                         struct fw_card *card, int status)
 {
-       struct fw_phy_packet *p =
-                       container_of(packet, struct fw_phy_packet, packet);
-
-       complete(&p->done);
-       kref_put(&p->kref, phy_packet_release);
+       complete(&phy_config_done);
 }
 
+static struct fw_packet phy_config_packet = {
+       .header_length  = 8,
+       .payload_length = 0,
+       .speed          = SCODE_100,
+       .callback       = transmit_phy_packet_callback,
+};
+
 void fw_send_phy_config(struct fw_card *card,
                        int node_id, int generation, int gap_count)
 {
-       struct fw_phy_packet *p;
        long timeout = DIV_ROUND_UP(HZ, 10);
        u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
                   PHY_CONFIG_ROOT_ID(node_id) |
                   PHY_CONFIG_GAP_COUNT(gap_count);
 
-       p = kmalloc(sizeof(*p), GFP_KERNEL);
-       if (p == NULL)
-               return;
+       mutex_lock(&phy_config_mutex);
+
+       phy_config_packet.header[0] = data;
+       phy_config_packet.header[1] = ~data;
+       phy_config_packet.generation = generation;
+       INIT_COMPLETION(phy_config_done);
+
+       card->driver->send_request(card, &phy_config_packet);
+       wait_for_completion_timeout(&phy_config_done, timeout);
 
-       p->packet.header[0] = data;
-       p->packet.header[1] = ~data;
-       p->packet.header_length = 8;
-       p->packet.payload_length = 0;
-       p->packet.speed = SCODE_100;
-       p->packet.generation = generation;
-       p->packet.callback = transmit_phy_packet_callback;
-       init_completion(&p->done);
-       kref_set(&p->kref, 2);
-
-       card->driver->send_request(card, &p->packet);
-       timeout = wait_for_completion_timeout(&p->done, timeout);
-       kref_put(&p->kref, phy_packet_release);
-
-       /* will leak p if the callback is never executed */
-       WARN_ON(timeout == 0);
+       mutex_unlock(&phy_config_mutex);
 }
 
 void fw_flush_transactions(struct fw_card *card)
index 0b624e927a6fea8c4306949b85d28e0b5b980417..50a071f1c945c0c3d8079ffdf713c577315a8415 100644 (file)
@@ -152,20 +152,11 @@ static ssize_t smi_data_read(struct kobject *kobj,
                             struct bin_attribute *bin_attr,
                             char *buf, loff_t pos, size_t count)
 {
-       size_t max_read;
        ssize_t ret;
 
        mutex_lock(&smi_data_lock);
-
-       if (pos >= smi_data_buf_size) {
-               ret = 0;
-               goto out;
-       }
-
-       max_read = smi_data_buf_size - pos;
-       ret = min(max_read, count);
-       memcpy(buf, smi_data_buf + pos, ret);
-out:
+       ret = memory_read_from_buffer(buf, count, &pos, smi_data_buf,
+                                       smi_data_buf_size);
        mutex_unlock(&smi_data_lock);
        return ret;
 }
@@ -254,7 +245,6 @@ static ssize_t host_control_on_shutdown_store(struct device *dev,
 static int smi_request(struct smi_cmd *smi_cmd)
 {
        cpumask_t old_mask;
-       cpumask_of_cpu_ptr(new_mask, 0);
        int ret = 0;
 
        if (smi_cmd->magic != SMI_CMD_MAGIC) {
@@ -265,7 +255,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
 
        /* SMI requires CPU 0 */
        old_mask = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, new_mask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(0));
        if (smp_processor_id() != 0) {
                dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
                        __func__);
index 7430e218cda6d54546a72ada7871216ae4916e1c..13946ebd77d6dbfb904eeec75f647a4ceabdf057 100644 (file)
@@ -507,11 +507,6 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
 
 static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
 {
-       unsigned char *ptemp = NULL;
-       size_t bytes_left = 0;
-       size_t data_length = 0;
-       ssize_t ret_count = 0;
-
        /* check to see if we have something to return */
        if ((rbu_data.image_update_buffer == NULL) ||
                (rbu_data.bios_image_size == 0)) {
@@ -519,28 +514,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
                        "bios_image_size %lu\n",
                        rbu_data.image_update_buffer,
                        rbu_data.bios_image_size);
-               ret_count = -ENOMEM;
-               goto read_rbu_data_exit;
-       }
-
-       if (pos > rbu_data.bios_image_size) {
-               ret_count = 0;
-               goto read_rbu_data_exit;
+               return -ENOMEM;
        }
 
-       bytes_left = rbu_data.bios_image_size - pos;
-       data_length = min(bytes_left, count);
-
-       ptemp = rbu_data.image_update_buffer;
-       memcpy(buffer, (ptemp + pos), data_length);
-
-       if ((pos + count) > rbu_data.bios_image_size)
-               /* this was the last copy */
-               ret_count = bytes_left;
-       else
-               ret_count = count;
-      read_rbu_data_exit:
-       return ret_count;
+       return memory_read_from_buffer(buffer, count, &pos,
+                       rbu_data.image_update_buffer, rbu_data.bios_image_size);
 }
 
 static ssize_t read_rbu_data(struct kobject *kobj,
index e23399c7f7735ad8677d7f011821cc5d3fa56717..001622eb86f962d28f6b6842981817ddf7f14132 100644 (file)
@@ -153,12 +153,14 @@ int __init firmware_map_add_early(resource_size_t start, resource_size_t end,
 
 static ssize_t start_show(struct firmware_map_entry *entry, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "0x%llx\n", entry->start);
+       return snprintf(buf, PAGE_SIZE, "0x%llx\n",
+               (unsigned long long)entry->start);
 }
 
 static ssize_t end_show(struct firmware_map_entry *entry, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "0x%llx\n", entry->end);
+       return snprintf(buf, PAGE_SIZE, "0x%llx\n",
+               (unsigned long long)entry->end);
 }
 
 static ssize_t type_show(struct firmware_map_entry *entry, char *buf)
index fced1909cbba0dd055c2a01cd73fc5303138750b..dbd42d6c93a701b2a0e52ec4a118f36ed538701e 100644 (file)
@@ -2,15 +2,40 @@
 # GPIO infrastructure and expanders
 #
 
-config HAVE_GPIO_LIB
+config ARCH_WANT_OPTIONAL_GPIOLIB
        bool
+       help
+         Select this config option from the architecture Kconfig, if
+         it is possible to use gpiolib on the architecture, but let the
+         user decide whether to actually build it or not.
+         Select this instead of ARCH_REQUIRE_GPIOLIB, if your architecture does
+         not depend on GPIOs being available, but rather let the user
+         decide whether he needs it or not.
+
+config ARCH_REQUIRE_GPIOLIB
+       bool
+       select GPIOLIB
        help
          Platforms select gpiolib if they use this infrastructure
          for all their GPIOs, usually starting with ones integrated
          into SOC processors.
+         Selecting this from the architecture code will cause the gpiolib
+         code to always get built in.
+
+
+
+menuconfig GPIOLIB
+       bool "GPIO Support"
+       depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB
+       select GENERIC_GPIO
+       help
+         This enables GPIO support through the generic GPIO library.
+         You only need to enable this, if you also want to enable
+         one or more of the GPIO expansion card drivers below.
 
-menu "GPIO Support"
-       depends on HAVE_GPIO_LIB
+         If unsure, say N.
+
+if GPIOLIB
 
 config DEBUG_GPIO
        bool "Debug GPIO calls"
@@ -23,10 +48,44 @@ config DEBUG_GPIO
          slower.  The diagnostics help catch the type of setup errors
          that are most common when setting up new platforms or boards.
 
+config GPIO_SYSFS
+       bool "/sys/class/gpio/... (sysfs interface)"
+       depends on SYSFS && EXPERIMENTAL
+       help
+         Say Y here to add a sysfs interface for GPIOs.
+
+         This is mostly useful to work around omissions in a system's
+         kernel support.  Those are common in custom and semicustom
+         hardware assembled using standard kernels with a minimum of
+         custom patches.  In those cases, userspace code may import
+         a given GPIO from the kernel, if no kernel driver requested it.
+
+         Kernel drivers may also request that a particular GPIO be
+         exported to userspace; this can be useful when debugging.
+
 # put expanders in the right section, in alphabetical order
 
 comment "I2C GPIO expanders:"
 
+config GPIO_MAX732X
+       tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
+       depends on I2C
+       help
+         Say yes here to support the MAX7319, MAX7320-7327 series of I2C
+         Port Expanders. Each IO port on these chips has a fixed role of
+         Input (designated by 'I'), Push-Pull Output ('O'), or Open-Drain
+         Input and Output (designed by 'P'). The combinations are listed
+         below:
+
+         8 bits:       max7319 (8I), max7320 (8O), max7321 (8P),
+                       max7322 (4I4O), max7323 (4P4O)
+
+         16 bits:      max7324 (8I8O), max7325 (8P8O),
+                       max7326 (4I12O), max7327 (4P12O)
+
+         Board setup code must specify the model to use, and the start
+         number for these GPIOs.
+
 config GPIO_PCA953X
        tristate "PCA953x, PCA955x, and MAX7310 I/O ports"
        depends on I2C
@@ -68,6 +127,24 @@ config GPIO_PCF857X
          This driver provides an in-kernel interface to those GPIOs using
          platform-neutral GPIO calls.
 
+comment "PCI GPIO expanders:"
+
+config GPIO_BT8XX
+       tristate "BT8XX GPIO abuser"
+       depends on PCI && VIDEO_BT848=n
+       help
+         The BT8xx frame grabber chip has 24 GPIO pins than can be abused
+         as a cheap PCI GPIO card.
+
+         This chip can be found on Miro, Hauppauge and STB TV-cards.
+
+         The card needs to be physically altered for using it as a
+         GPIO card. For more information on how to build a GPIO card
+         from a BT8xx TV card, see the documentation file at
+         Documentation/bt8xxgpio.txt
+
+         If unsure, say N.
+
 comment "SPI GPIO expanders:"
 
 config GPIO_MAX7301
@@ -83,4 +160,4 @@ config GPIO_MCP23S08
          SPI driver for Microchip MCP23S08 I/O expander.  This provides
          a GPIO interface supporting inputs and outputs.
 
-endmenu
+endif
index 16e796dc5410fe8659466d54b250b357eee1a6ac..01b4bbde1956e48933d23d60c782ef94f8dff63e 100644 (file)
@@ -2,9 +2,11 @@
 
 ccflags-$(CONFIG_DEBUG_GPIO)   += -DDEBUG
 
-obj-$(CONFIG_HAVE_GPIO_LIB)    += gpiolib.o
+obj-$(CONFIG_GPIOLIB)          += gpiolib.o
 
 obj-$(CONFIG_GPIO_MAX7301)     += max7301.o
+obj-$(CONFIG_GPIO_MAX732X)     += max732x.o
 obj-$(CONFIG_GPIO_MCP23S08)    += mcp23s08.o
 obj-$(CONFIG_GPIO_PCA953X)     += pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)     += pcf857x.o
+obj-$(CONFIG_GPIO_BT8XX)       += bt8xxgpio.o
diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/bt8xxgpio.c
new file mode 100644 (file)
index 0000000..7a11682
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+
+    bt8xx GPIO abuser
+
+    Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
+
+    Please do _only_ contact the people listed _above_ with issues related to this driver.
+    All the other people listed below are not related to this driver. Their names
+    are only here, because this driver is derived from the bt848 driver.
+
+
+    Derived from the bt848 driver:
+
+    Copyright (C) 1996,97,98 Ralph  Metzler
+                          & Marcus Metzler
+    (c) 1999-2002 Gerd Knorr
+
+    some v4l2 code lines are taken from Justin's bttv2 driver which is
+    (c) 2000 Justin Schoeman
+
+    V4L1 removal from:
+    (c) 2005-2006 Nickolay V. Shmyrev
+
+    Fixes to be fully V4L2 compliant by
+    (c) 2006 Mauro Carvalho Chehab
+
+    Cropping and overscan support
+    Copyright (C) 2005, 2006 Michael H. Schimek
+    Sponsored by OPQ Systems AB
+
+    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/pci.h>
+#include <linux/spinlock.h>
+
+#include <asm/gpio.h>
+
+/* Steal the hardware definitions from the bttv driver. */
+#include "../media/video/bt8xx/bt848.h"
+
+
+#define BT8XXGPIO_NR_GPIOS             24 /* We have 24 GPIO pins */
+
+
+struct bt8xxgpio {
+       spinlock_t lock;
+
+       void __iomem *mmio;
+       struct pci_dev *pdev;
+       struct gpio_chip gpio;
+
+#ifdef CONFIG_PM
+       u32 saved_outen;
+       u32 saved_data;
+#endif
+};
+
+#define bgwrite(dat, adr)      writel((dat), bg->mmio+(adr))
+#define bgread(adr)            readl(bg->mmio+(adr))
+
+
+static int modparam_gpiobase = -1/* dynamic */;
+module_param_named(gpiobase, modparam_gpiobase, int, 0444);
+MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
+
+
+static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+       unsigned long flags;
+       u32 outen, data;
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       data = bgread(BT848_GPIO_DATA);
+       data &= ~(1 << nr);
+       bgwrite(data, BT848_GPIO_DATA);
+
+       outen = bgread(BT848_GPIO_OUT_EN);
+       outen &= ~(1 << nr);
+       bgwrite(outen, BT848_GPIO_OUT_EN);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       return 0;
+}
+
+static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+       unsigned long flags;
+       u32 val;
+
+       spin_lock_irqsave(&bg->lock, flags);
+       val = bgread(BT848_GPIO_DATA);
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       return !!(val & (1 << nr));
+}
+
+static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
+                                       unsigned nr, int val)
+{
+       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+       unsigned long flags;
+       u32 outen, data;
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       outen = bgread(BT848_GPIO_OUT_EN);
+       outen |= (1 << nr);
+       bgwrite(outen, BT848_GPIO_OUT_EN);
+
+       data = bgread(BT848_GPIO_DATA);
+       if (val)
+               data |= (1 << nr);
+       else
+               data &= ~(1 << nr);
+       bgwrite(data, BT848_GPIO_DATA);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       return 0;
+}
+
+static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
+                           unsigned nr, int val)
+{
+       struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+       unsigned long flags;
+       u32 data;
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       data = bgread(BT848_GPIO_DATA);
+       if (val)
+               data |= (1 << nr);
+       else
+               data &= ~(1 << nr);
+       bgwrite(data, BT848_GPIO_DATA);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+}
+
+static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
+{
+       struct gpio_chip *c = &bg->gpio;
+
+       c->label = bg->pdev->dev.bus_id;
+       c->owner = THIS_MODULE;
+       c->direction_input = bt8xxgpio_gpio_direction_input;
+       c->get = bt8xxgpio_gpio_get;
+       c->direction_output = bt8xxgpio_gpio_direction_output;
+       c->set = bt8xxgpio_gpio_set;
+       c->dbg_show = NULL;
+       c->base = modparam_gpiobase;
+       c->ngpio = BT8XXGPIO_NR_GPIOS;
+       c->can_sleep = 0;
+}
+
+static int bt8xxgpio_probe(struct pci_dev *dev,
+                       const struct pci_device_id *pci_id)
+{
+       struct bt8xxgpio *bg;
+       int err;
+
+       bg = kzalloc(sizeof(*bg), GFP_KERNEL);
+       if (!bg)
+               return -ENOMEM;
+
+       bg->pdev = dev;
+       spin_lock_init(&bg->lock);
+
+       err = pci_enable_device(dev);
+       if (err) {
+               printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
+               goto err_freebg;
+       }
+       if (!request_mem_region(pci_resource_start(dev, 0),
+                               pci_resource_len(dev, 0),
+                               "bt8xxgpio")) {
+               printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
+                      (unsigned long long)pci_resource_start(dev, 0));
+               err = -EBUSY;
+               goto err_disable;
+       }
+       pci_set_master(dev);
+       pci_set_drvdata(dev, bg);
+
+       bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
+       if (!bg->mmio) {
+               printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
+               err = -EIO;
+               goto err_release_mem;
+       }
+
+       /* Disable interrupts */
+       bgwrite(0, BT848_INT_MASK);
+
+       /* gpio init */
+       bgwrite(0, BT848_GPIO_DMA_CTL);
+       bgwrite(0, BT848_GPIO_REG_INP);
+       bgwrite(0, BT848_GPIO_OUT_EN);
+
+       bt8xxgpio_gpio_setup(bg);
+       err = gpiochip_add(&bg->gpio);
+       if (err) {
+               printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
+               goto err_release_mem;
+       }
+
+       printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
+              bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
+
+       return 0;
+
+err_release_mem:
+       release_mem_region(pci_resource_start(dev, 0),
+                          pci_resource_len(dev, 0));
+       pci_set_drvdata(dev, NULL);
+err_disable:
+       pci_disable_device(dev);
+err_freebg:
+       kfree(bg);
+
+       return err;
+}
+
+static void bt8xxgpio_remove(struct pci_dev *pdev)
+{
+       struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+
+       gpiochip_remove(&bg->gpio);
+
+       bgwrite(0, BT848_INT_MASK);
+       bgwrite(~0x0, BT848_INT_STAT);
+       bgwrite(0x0, BT848_GPIO_OUT_EN);
+
+       iounmap(bg->mmio);
+       release_mem_region(pci_resource_start(pdev, 0),
+                          pci_resource_len(pdev, 0));
+       pci_disable_device(pdev);
+
+       pci_set_drvdata(pdev, NULL);
+       kfree(bg);
+}
+
+#ifdef CONFIG_PM
+static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
+       bg->saved_data = bgread(BT848_GPIO_DATA);
+
+       bgwrite(0, BT848_INT_MASK);
+       bgwrite(~0x0, BT848_INT_STAT);
+       bgwrite(0x0, BT848_GPIO_OUT_EN);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int bt8xxgpio_resume(struct pci_dev *pdev)
+{
+       struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+       unsigned long flags;
+       int err;
+
+       pci_set_power_state(pdev, 0);
+       err = pci_enable_device(pdev);
+       if (err)
+               return err;
+       pci_restore_state(pdev);
+
+       spin_lock_irqsave(&bg->lock, flags);
+
+       bgwrite(0, BT848_INT_MASK);
+       bgwrite(0, BT848_GPIO_DMA_CTL);
+       bgwrite(0, BT848_GPIO_REG_INP);
+       bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
+       bgwrite(bg->saved_data & bg->saved_outen,
+               BT848_GPIO_DATA);
+
+       spin_unlock_irqrestore(&bg->lock, flags);
+
+       return 0;
+}
+#else
+#define bt8xxgpio_suspend NULL
+#define bt8xxgpio_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id bt8xxgpio_pci_tbl[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
+
+static struct pci_driver bt8xxgpio_pci_driver = {
+       .name           = "bt8xxgpio",
+       .id_table       = bt8xxgpio_pci_tbl,
+       .probe          = bt8xxgpio_probe,
+       .remove         = bt8xxgpio_remove,
+       .suspend        = bt8xxgpio_suspend,
+       .resume         = bt8xxgpio_resume,
+};
+
+static int bt8xxgpio_init(void)
+{
+       return pci_register_driver(&bt8xxgpio_pci_driver);
+}
+module_init(bt8xxgpio_init)
+
+static void bt8xxgpio_exit(void)
+{
+       pci_unregister_driver(&bt8xxgpio_pci_driver);
+}
+module_exit(bt8xxgpio_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
index beaf6b3a37dcefb0b2c1d8c8f79b7db2713dba45..8d2940517c99221c33e3bf200ac53a82214cebee 100644 (file)
@@ -2,8 +2,11 @@
 #include <linux/module.h>
 #include <linux/irq.h>
 #include <linux/spinlock.h>
-
-#include <asm/gpio.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/gpio.h>
 
 
 /* Optional implementation infrastructure for GPIO interfaces.
@@ -44,6 +47,8 @@ struct gpio_desc {
 #define FLAG_REQUESTED 0
 #define FLAG_IS_OUT    1
 #define FLAG_RESERVED  2
+#define FLAG_EXPORT    3       /* protected by sysfs_lock */
+#define FLAG_SYSFS     4       /* exported via /sys/class/gpio/control */
 
 #ifdef CONFIG_DEBUG_FS
        const char              *label;
@@ -151,6 +156,482 @@ err:
        return ret;
 }
 
+#ifdef CONFIG_GPIO_SYSFS
+
+/* lock protects against unexport_gpio() being called while
+ * sysfs files are active.
+ */
+static DEFINE_MUTEX(sysfs_lock);
+
+/*
+ * /sys/class/gpio/gpioN... only for GPIOs that are exported
+ *   /direction
+ *      * MAY BE OMITTED if kernel won't allow direction changes
+ *      * is read/write as "in" or "out"
+ *      * may also be written as "high" or "low", initializing
+ *        output value as specified ("out" implies "low")
+ *   /value
+ *      * always readable, subject to hardware behavior
+ *      * may be writable, as zero/nonzero
+ *
+ * REVISIT there will likely be an attribute for configuring async
+ * notifications, e.g. to specify polling interval or IRQ trigger type
+ * that would for example trigger a poll() on the "value".
+ */
+
+static ssize_t gpio_direction_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       const struct gpio_desc  *desc = dev_get_drvdata(dev);
+       ssize_t                 status;
+
+       mutex_lock(&sysfs_lock);
+
+       if (!test_bit(FLAG_EXPORT, &desc->flags))
+               status = -EIO;
+       else
+               status = sprintf(buf, "%s\n",
+                       test_bit(FLAG_IS_OUT, &desc->flags)
+                               ? "out" : "in");
+
+       mutex_unlock(&sysfs_lock);
+       return status;
+}
+
+static ssize_t gpio_direction_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       const struct gpio_desc  *desc = dev_get_drvdata(dev);
+       unsigned                gpio = desc - gpio_desc;
+       ssize_t                 status;
+
+       mutex_lock(&sysfs_lock);
+
+       if (!test_bit(FLAG_EXPORT, &desc->flags))
+               status = -EIO;
+       else if (sysfs_streq(buf, "high"))
+               status = gpio_direction_output(gpio, 1);
+       else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
+               status = gpio_direction_output(gpio, 0);
+       else if (sysfs_streq(buf, "in"))
+               status = gpio_direction_input(gpio);
+       else
+               status = -EINVAL;
+
+       mutex_unlock(&sysfs_lock);
+       return status ? : size;
+}
+
+static const DEVICE_ATTR(direction, 0644,
+               gpio_direction_show, gpio_direction_store);
+
+static ssize_t gpio_value_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       const struct gpio_desc  *desc = dev_get_drvdata(dev);
+       unsigned                gpio = desc - gpio_desc;
+       ssize_t                 status;
+
+       mutex_lock(&sysfs_lock);
+
+       if (!test_bit(FLAG_EXPORT, &desc->flags))
+               status = -EIO;
+       else
+               status = sprintf(buf, "%d\n", gpio_get_value_cansleep(gpio));
+
+       mutex_unlock(&sysfs_lock);
+       return status;
+}
+
+static ssize_t gpio_value_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       const struct gpio_desc  *desc = dev_get_drvdata(dev);
+       unsigned                gpio = desc - gpio_desc;
+       ssize_t                 status;
+
+       mutex_lock(&sysfs_lock);
+
+       if (!test_bit(FLAG_EXPORT, &desc->flags))
+               status = -EIO;
+       else if (!test_bit(FLAG_IS_OUT, &desc->flags))
+               status = -EPERM;
+       else {
+               long            value;
+
+               status = strict_strtol(buf, 0, &value);
+               if (status == 0) {
+                       gpio_set_value_cansleep(gpio, value != 0);
+                       status = size;
+               }
+       }
+
+       mutex_unlock(&sysfs_lock);
+       return status;
+}
+
+static /*const*/ DEVICE_ATTR(value, 0644,
+               gpio_value_show, gpio_value_store);
+
+static const struct attribute *gpio_attrs[] = {
+       &dev_attr_direction.attr,
+       &dev_attr_value.attr,
+       NULL,
+};
+
+static const struct attribute_group gpio_attr_group = {
+       .attrs = (struct attribute **) gpio_attrs,
+};
+
+/*
+ * /sys/class/gpio/gpiochipN/
+ *   /base ... matching gpio_chip.base (N)
+ *   /label ... matching gpio_chip.label
+ *   /ngpio ... matching gpio_chip.ngpio
+ */
+
+static ssize_t chip_base_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       const struct gpio_chip  *chip = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", chip->base);
+}
+static DEVICE_ATTR(base, 0444, chip_base_show, NULL);
+
+static ssize_t chip_label_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       const struct gpio_chip  *chip = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", chip->label ? : "");
+}
+static DEVICE_ATTR(label, 0444, chip_label_show, NULL);
+
+static ssize_t chip_ngpio_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       const struct gpio_chip  *chip = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%u\n", chip->ngpio);
+}
+static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
+
+static const struct attribute *gpiochip_attrs[] = {
+       &dev_attr_base.attr,
+       &dev_attr_label.attr,
+       &dev_attr_ngpio.attr,
+       NULL,
+};
+
+static const struct attribute_group gpiochip_attr_group = {
+       .attrs = (struct attribute **) gpiochip_attrs,
+};
+
+/*
+ * /sys/class/gpio/export ... write-only
+ *     integer N ... number of GPIO to export (full access)
+ * /sys/class/gpio/unexport ... write-only
+ *     integer N ... number of GPIO to unexport
+ */
+static ssize_t export_store(struct class *class, const char *buf, size_t len)
+{
+       long    gpio;
+       int     status;
+
+       status = strict_strtol(buf, 0, &gpio);
+       if (status < 0)
+               goto done;
+
+       /* No extra locking here; FLAG_SYSFS just signifies that the
+        * request and export were done by on behalf of userspace, so
+        * they may be undone on its behalf too.
+        */
+
+       status = gpio_request(gpio, "sysfs");
+       if (status < 0)
+               goto done;
+
+       status = gpio_export(gpio, true);
+       if (status < 0)
+               gpio_free(gpio);
+       else
+               set_bit(FLAG_SYSFS, &gpio_desc[gpio].flags);
+
+done:
+       if (status)
+               pr_debug("%s: status %d\n", __func__, status);
+       return status ? : len;
+}
+
+static ssize_t unexport_store(struct class *class, const char *buf, size_t len)
+{
+       long    gpio;
+       int     status;
+
+       status = strict_strtol(buf, 0, &gpio);
+       if (status < 0)
+               goto done;
+
+       status = -EINVAL;
+
+       /* reject bogus commands (gpio_unexport ignores them) */
+       if (!gpio_is_valid(gpio))
+               goto done;
+
+       /* No extra locking here; FLAG_SYSFS just signifies that the
+        * request and export were done by on behalf of userspace, so
+        * they may be undone on its behalf too.
+        */
+       if (test_and_clear_bit(FLAG_SYSFS, &gpio_desc[gpio].flags)) {
+               status = 0;
+               gpio_free(gpio);
+       }
+done:
+       if (status)
+               pr_debug("%s: status %d\n", __func__, status);
+       return status ? : len;
+}
+
+static struct class_attribute gpio_class_attrs[] = {
+       __ATTR(export, 0200, NULL, export_store),
+       __ATTR(unexport, 0200, NULL, unexport_store),
+       __ATTR_NULL,
+};
+
+static struct class gpio_class = {
+       .name =         "gpio",
+       .owner =        THIS_MODULE,
+
+       .class_attrs =  gpio_class_attrs,
+};
+
+
+/**
+ * gpio_export - export a GPIO through sysfs
+ * @gpio: gpio to make available, already requested
+ * @direction_may_change: true if userspace may change gpio direction
+ * Context: arch_initcall or later
+ *
+ * When drivers want to make a GPIO accessible to userspace after they
+ * have requested it -- perhaps while debugging, or as part of their
+ * public interface -- they may use this routine.  If the GPIO can
+ * change direction (some can't) and the caller allows it, userspace
+ * will see "direction" sysfs attribute which may be used to change
+ * the gpio's direction.  A "value" attribute will always be provided.
+ *
+ * Returns zero on success, else an error.
+ */
+int gpio_export(unsigned gpio, bool direction_may_change)
+{
+       unsigned long           flags;
+       struct gpio_desc        *desc;
+       int                     status = -EINVAL;
+
+       /* can't export until sysfs is available ... */
+       if (!gpio_class.p) {
+               pr_debug("%s: called too early!\n", __func__);
+               return -ENOENT;
+       }
+
+       if (!gpio_is_valid(gpio))
+               goto done;
+
+       mutex_lock(&sysfs_lock);
+
+       spin_lock_irqsave(&gpio_lock, flags);
+       desc = &gpio_desc[gpio];
+       if (test_bit(FLAG_REQUESTED, &desc->flags)
+                       && !test_bit(FLAG_EXPORT, &desc->flags)) {
+               status = 0;
+               if (!desc->chip->direction_input
+                               || !desc->chip->direction_output)
+                       direction_may_change = false;
+       }
+       spin_unlock_irqrestore(&gpio_lock, flags);
+
+       if (status == 0) {
+               struct device   *dev;
+
+               dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
+                                       desc, "gpio%d", gpio);
+               if (dev) {
+                       if (direction_may_change)
+                               status = sysfs_create_group(&dev->kobj,
+                                               &gpio_attr_group);
+                       else
+                               status = device_create_file(dev,
+                                               &dev_attr_value);
+                       if (status != 0)
+                               device_unregister(dev);
+               } else
+                       status = -ENODEV;
+               if (status == 0)
+                       set_bit(FLAG_EXPORT, &desc->flags);
+       }
+
+       mutex_unlock(&sysfs_lock);
+
+done:
+       if (status)
+               pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(gpio_export);
+
+static int match_export(struct device *dev, void *data)
+{
+       return dev_get_drvdata(dev) == data;
+}
+
+/**
+ * gpio_unexport - reverse effect of gpio_export()
+ * @gpio: gpio to make unavailable
+ *
+ * This is implicit on gpio_free().
+ */
+void gpio_unexport(unsigned gpio)
+{
+       struct gpio_desc        *desc;
+       int                     status = -EINVAL;
+
+       if (!gpio_is_valid(gpio))
+               goto done;
+
+       mutex_lock(&sysfs_lock);
+
+       desc = &gpio_desc[gpio];
+       if (test_bit(FLAG_EXPORT, &desc->flags)) {
+               struct device   *dev = NULL;
+
+               dev = class_find_device(&gpio_class, NULL, desc, match_export);
+               if (dev) {
+                       clear_bit(FLAG_EXPORT, &desc->flags);
+                       put_device(dev);
+                       device_unregister(dev);
+                       status = 0;
+               } else
+                       status = -ENODEV;
+       }
+
+       mutex_unlock(&sysfs_lock);
+done:
+       if (status)
+               pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
+}
+EXPORT_SYMBOL_GPL(gpio_unexport);
+
+static int gpiochip_export(struct gpio_chip *chip)
+{
+       int             status;
+       struct device   *dev;
+
+       /* Many systems register gpio chips for SOC support very early,
+        * before driver model support is available.  In those cases we
+        * export this later, in gpiolib_sysfs_init() ... here we just
+        * verify that _some_ field of gpio_class got initialized.
+        */
+       if (!gpio_class.p)
+               return 0;
+
+       /* use chip->base for the ID; it's already known to be unique */
+       mutex_lock(&sysfs_lock);
+       dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
+                               "gpiochip%d", chip->base);
+       if (dev) {
+               status = sysfs_create_group(&dev->kobj,
+                               &gpiochip_attr_group);
+       } else
+               status = -ENODEV;
+       chip->exported = (status == 0);
+       mutex_unlock(&sysfs_lock);
+
+       if (status) {
+               unsigned long   flags;
+               unsigned        gpio;
+
+               spin_lock_irqsave(&gpio_lock, flags);
+               gpio = chip->base;
+               while (gpio_desc[gpio].chip == chip)
+                       gpio_desc[gpio++].chip = NULL;
+               spin_unlock_irqrestore(&gpio_lock, flags);
+
+               pr_debug("%s: chip %s status %d\n", __func__,
+                               chip->label, status);
+       }
+
+       return status;
+}
+
+static void gpiochip_unexport(struct gpio_chip *chip)
+{
+       int                     status;
+       struct device           *dev;
+
+       mutex_lock(&sysfs_lock);
+       dev = class_find_device(&gpio_class, NULL, chip, match_export);
+       if (dev) {
+               put_device(dev);
+               device_unregister(dev);
+               chip->exported = 0;
+               status = 0;
+       } else
+               status = -ENODEV;
+       mutex_unlock(&sysfs_lock);
+
+       if (status)
+               pr_debug("%s: chip %s status %d\n", __func__,
+                               chip->label, status);
+}
+
+static int __init gpiolib_sysfs_init(void)
+{
+       int             status;
+       unsigned long   flags;
+       unsigned        gpio;
+
+       status = class_register(&gpio_class);
+       if (status < 0)
+               return status;
+
+       /* Scan and register the gpio_chips which registered very
+        * early (e.g. before the class_register above was called).
+        *
+        * We run before arch_initcall() so chip->dev nodes can have
+        * registered, and so arch_initcall() can always gpio_export().
+        */
+       spin_lock_irqsave(&gpio_lock, flags);
+       for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) {
+               struct gpio_chip        *chip;
+
+               chip = gpio_desc[gpio].chip;
+               if (!chip || chip->exported)
+                       continue;
+
+               spin_unlock_irqrestore(&gpio_lock, flags);
+               status = gpiochip_export(chip);
+               spin_lock_irqsave(&gpio_lock, flags);
+       }
+       spin_unlock_irqrestore(&gpio_lock, flags);
+
+
+       return status;
+}
+postcore_initcall(gpiolib_sysfs_init);
+
+#else
+static inline int gpiochip_export(struct gpio_chip *chip)
+{
+       return 0;
+}
+
+static inline void gpiochip_unexport(struct gpio_chip *chip)
+{
+}
+
+#endif /* CONFIG_GPIO_SYSFS */
+
 /**
  * gpiochip_add() - register a gpio_chip
  * @chip: the chip to register, with chip->base initialized
@@ -160,6 +641,11 @@ err:
  * because the chip->base is invalid or already associated with a
  * different chip.  Otherwise it returns zero as a success code.
  *
+ * When gpiochip_add() is called very early during boot, so that GPIOs
+ * can be freely used, the chip->dev device must be registered before
+ * the gpio framework's arch_initcall().  Otherwise sysfs initialization
+ * for GPIOs will fail rudely.
+ *
  * If chip->base is negative, this requests dynamic assignment of
  * a range of valid GPIOs.
  */
@@ -182,7 +668,7 @@ int gpiochip_add(struct gpio_chip *chip)
                base = gpiochip_find_base(chip->ngpio);
                if (base < 0) {
                        status = base;
-                       goto fail_unlock;
+                       goto unlock;
                }
                chip->base = base;
        }
@@ -197,12 +683,23 @@ int gpiochip_add(struct gpio_chip *chip)
        if (status == 0) {
                for (id = base; id < base + chip->ngpio; id++) {
                        gpio_desc[id].chip = chip;
-                       gpio_desc[id].flags = 0;
+
+                       /* REVISIT:  most hardware initializes GPIOs as
+                        * inputs (often with pullups enabled) so power
+                        * usage is minimized.  Linux code should set the
+                        * gpio direction first thing; but until it does,
+                        * we may expose the wrong direction in sysfs.
+                        */
+                       gpio_desc[id].flags = !chip->direction_input
+                               ? (1 << FLAG_IS_OUT)
+                               : 0;
                }
        }
 
-fail_unlock:
+unlock:
        spin_unlock_irqrestore(&gpio_lock, flags);
+       if (status == 0)
+               status = gpiochip_export(chip);
 fail:
        /* failures here can mean systems won't boot... */
        if (status)
@@ -239,6 +736,10 @@ int gpiochip_remove(struct gpio_chip *chip)
        }
 
        spin_unlock_irqrestore(&gpio_lock, flags);
+
+       if (status == 0)
+               gpiochip_unexport(chip);
+
        return status;
 }
 EXPORT_SYMBOL_GPL(gpiochip_remove);
@@ -296,6 +797,8 @@ void gpio_free(unsigned gpio)
                return;
        }
 
+       gpio_unexport(gpio);
+
        spin_lock_irqsave(&gpio_lock, flags);
 
        desc = &gpio_desc[gpio];
@@ -534,10 +1037,6 @@ EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
 
 #ifdef CONFIG_DEBUG_FS
 
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-
 static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
        unsigned                i;
@@ -614,17 +1113,28 @@ static int gpiolib_show(struct seq_file *s, void *unused)
        /* REVISIT this isn't locked against gpio_chip removal ... */
 
        for (gpio = 0; gpio_is_valid(gpio); gpio++) {
+               struct device *dev;
+
                if (chip == gpio_desc[gpio].chip)
                        continue;
                chip = gpio_desc[gpio].chip;
                if (!chip)
                        continue;
 
-               seq_printf(s, "%sGPIOs %d-%d, %s%s:\n",
+               seq_printf(s, "%sGPIOs %d-%d",
                                started ? "\n" : "",
-                               chip->base, chip->base + chip->ngpio - 1,
-                               chip->label ? : "generic",
-                               chip->can_sleep ? ", can sleep" : "");
+                               chip->base, chip->base + chip->ngpio - 1);
+               dev = chip->dev;
+               if (dev)
+                       seq_printf(s, ", %s/%s",
+                               dev->bus ? dev->bus->name : "no-bus",
+                               dev->bus_id);
+               if (chip->label)
+                       seq_printf(s, ", %s", chip->label);
+               if (chip->can_sleep)
+                       seq_printf(s, ", can sleep");
+               seq_printf(s, ":\n");
+
                started = 1;
                if (chip->dbg_show)
                        chip->dbg_show(s, chip);
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c
new file mode 100644 (file)
index 0000000..b51c813
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ *  max732x.c - I2C Port Expander with 8/16 I/O
+ *
+ *  Copyright (C) 2007 Marvell International Ltd.
+ *  Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>
+ *  Copyright (C) 2008 Eric Miao <eric.miao@marvell.com>
+ *
+ *  Derived from drivers/gpio/pca953x.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 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c/max732x.h>
+
+
+/*
+ * Each port of MAX732x (including MAX7319) falls into one of the
+ * following three types:
+ *
+ *   - Push Pull Output
+ *   - Input
+ *   - Open Drain I/O
+ *
+ * designated by 'O', 'I' and 'P' individually according to MAXIM's
+ * datasheets.
+ *
+ * There are two groups of I/O ports, each group usually includes
+ * up to 8 I/O ports, and is accessed by a specific I2C address:
+ *
+ *   - Group A : by I2C address 0b'110xxxx
+ *   - Group B : by I2C address 0b'101xxxx
+ *
+ * where 'xxxx' is decided by the connections of pin AD2/AD0.  The
+ * address used also affects the initial state of output signals.
+ *
+ * Within each group of ports, there are five known combinations of
+ * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for
+ * the detailed organization of these ports.
+ *
+ * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16',
+ * and GPIOs from GROUP_A are numbered before those from GROUP_B
+ * (if there are two groups).
+ *
+ * NOTE: MAX7328/MAX7329 are drop-in replacements for PCF8574/a, so
+ * they are not supported by this driver.
+ */
+
+#define PORT_NONE      0x0     /* '/' No Port */
+#define PORT_OUTPUT    0x1     /* 'O' Push-Pull, Output Only */
+#define PORT_INPUT     0x2     /* 'I' Input Only */
+#define PORT_OPENDRAIN 0x3     /* 'P' Open-Drain, I/O */
+
+#define IO_4I4O                0x5AA5  /* O7 O6 I5 I4 I3 I2 O1 O0 */
+#define IO_4P4O                0x5FF5  /* O7 O6 P5 P4 P3 P2 O1 O0 */
+#define IO_8I          0xAAAA  /* I7 I6 I5 I4 I3 I2 I1 I0 */
+#define IO_8P          0xFFFF  /* P7 P6 P5 P4 P3 P2 P1 P0 */
+#define IO_8O          0x5555  /* O7 O6 O5 O4 O3 O2 O1 O0 */
+
+#define GROUP_A(x)     ((x) & 0xffff)  /* I2C Addr: 0b'110xxxx */
+#define GROUP_B(x)     ((x) << 16)     /* I2C Addr: 0b'101xxxx */
+
+static const struct i2c_device_id max732x_id[] = {
+       { "max7319", GROUP_A(IO_8I) },
+       { "max7320", GROUP_B(IO_8O) },
+       { "max7321", GROUP_A(IO_8P) },
+       { "max7322", GROUP_A(IO_4I4O) },
+       { "max7323", GROUP_A(IO_4P4O) },
+       { "max7324", GROUP_A(IO_8I) | GROUP_B(IO_8O) },
+       { "max7325", GROUP_A(IO_8P) | GROUP_B(IO_8O) },
+       { "max7326", GROUP_A(IO_4I4O) | GROUP_B(IO_8O) },
+       { "max7327", GROUP_A(IO_4P4O) | GROUP_B(IO_8O) },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, max732x_id);
+
+struct max732x_chip {
+       struct gpio_chip gpio_chip;
+
+       struct i2c_client *client;      /* "main" client */
+       struct i2c_client *client_dummy;
+       struct i2c_client *client_group_a;
+       struct i2c_client *client_group_b;
+
+       unsigned int    mask_group_a;
+       unsigned int    dir_input;
+       unsigned int    dir_output;
+
+       struct mutex    lock;
+       uint8_t         reg_out[2];
+};
+
+static int max732x_write(struct max732x_chip *chip, int group_a, uint8_t val)
+{
+       struct i2c_client *client;
+       int ret;
+
+       client = group_a ? chip->client_group_a : chip->client_group_b;
+       ret = i2c_smbus_write_byte(client, val);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed writing\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int max732x_read(struct max732x_chip *chip, int group_a, uint8_t *val)
+{
+       struct i2c_client *client;
+       int ret;
+
+       client = group_a ? chip->client_group_a : chip->client_group_b;
+       ret = i2c_smbus_read_byte(client);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed reading\n");
+               return ret;
+       }
+
+       *val = (uint8_t)ret;
+       return 0;
+}
+
+static inline int is_group_a(struct max732x_chip *chip, unsigned off)
+{
+       return (1u << off) & chip->mask_group_a;
+}
+
+static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+       struct max732x_chip *chip;
+       uint8_t reg_val;
+       int ret;
+
+       chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+       ret = max732x_read(chip, is_group_a(chip, off), &reg_val);
+       if (ret < 0)
+               return 0;
+
+       return reg_val & (1u << (off & 0x7));
+}
+
+static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+       struct max732x_chip *chip;
+       uint8_t reg_out, mask = 1u << (off & 0x7);
+       int ret;
+
+       chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+       mutex_lock(&chip->lock);
+
+       reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0];
+       reg_out = (val) ? reg_out | mask : reg_out & ~mask;
+
+       ret = max732x_write(chip, is_group_a(chip, off), reg_out);
+       if (ret < 0)
+               goto out;
+
+       /* update the shadow register then */
+       if (off > 7)
+               chip->reg_out[1] = reg_out;
+       else
+               chip->reg_out[0] = reg_out;
+out:
+       mutex_unlock(&chip->lock);
+}
+
+static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+       struct max732x_chip *chip;
+       unsigned int mask = 1u << off;
+
+       chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+       if ((mask & chip->dir_input) == 0) {
+               dev_dbg(&chip->client->dev, "%s port %d is output only\n",
+                       chip->client->name, off);
+               return -EACCES;
+       }
+
+       return 0;
+}
+
+static int max732x_gpio_direction_output(struct gpio_chip *gc,
+               unsigned off, int val)
+{
+       struct max732x_chip *chip;
+       unsigned int mask = 1u << off;
+
+       chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+       if ((mask & chip->dir_output) == 0) {
+               dev_dbg(&chip->client->dev, "%s port %d is input only\n",
+                       chip->client->name, off);
+               return -EACCES;
+       }
+
+       max732x_gpio_set_value(gc, off, val);
+       return 0;
+}
+
+static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
+                                       const struct i2c_device_id *id,
+                                       unsigned gpio_start)
+{
+       struct gpio_chip *gc = &chip->gpio_chip;
+       uint32_t id_data = id->driver_data;
+       int i, port = 0;
+
+       for (i = 0; i < 16; i++, id_data >>= 2) {
+               unsigned int mask = 1 << port;
+
+               switch (id_data & 0x3) {
+               case PORT_OUTPUT:
+                       chip->dir_output |= mask;
+                       break;
+               case PORT_INPUT:
+                       chip->dir_input |= mask;
+                       break;
+               case PORT_OPENDRAIN:
+                       chip->dir_output |= mask;
+                       chip->dir_input |= mask;
+                       break;
+               default:
+                       continue;
+               }
+
+               if (i < 8)
+                       chip->mask_group_a |= mask;
+               port++;
+       }
+
+       if (chip->dir_input)
+               gc->direction_input = max732x_gpio_direction_input;
+       if (chip->dir_output) {
+               gc->direction_output = max732x_gpio_direction_output;
+               gc->set = max732x_gpio_set_value;
+       }
+       gc->get = max732x_gpio_get_value;
+       gc->can_sleep = 1;
+
+       gc->base = gpio_start;
+       gc->ngpio = port;
+       gc->label = chip->client->name;
+       gc->owner = THIS_MODULE;
+
+       return port;
+}
+
+static int __devinit max732x_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
+{
+       struct max732x_platform_data *pdata;
+       struct max732x_chip *chip;
+       struct i2c_client *c;
+       uint16_t addr_a, addr_b;
+       int ret, nr_port;
+
+       pdata = client->dev.platform_data;
+       if (pdata == NULL)
+               return -ENODEV;
+
+       chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+       chip->client = client;
+
+       nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base);
+
+       addr_a = (client->addr & 0x0f) | 0x60;
+       addr_b = (client->addr & 0x0f) | 0x50;
+
+       switch (client->addr & 0x70) {
+       case 0x60:
+               chip->client_group_a = client;
+               if (nr_port > 7) {
+                       c = i2c_new_dummy(client->adapter, addr_b);
+                       chip->client_group_b = chip->client_dummy = c;
+               }
+               break;
+       case 0x50:
+               chip->client_group_b = client;
+               if (nr_port > 7) {
+                       c = i2c_new_dummy(client->adapter, addr_a);
+                       chip->client_group_a = chip->client_dummy = c;
+               }
+               break;
+       default:
+               dev_err(&client->dev, "invalid I2C address specified %02x\n",
+                               client->addr);
+               ret = -EINVAL;
+               goto out_failed;
+       }
+
+       mutex_init(&chip->lock);
+
+       max732x_read(chip, is_group_a(chip, 0), &chip->reg_out[0]);
+       if (nr_port > 7)
+               max732x_read(chip, is_group_a(chip, 8), &chip->reg_out[1]);
+
+       ret = gpiochip_add(&chip->gpio_chip);
+       if (ret)
+               goto out_failed;
+
+       if (pdata->setup) {
+               ret = pdata->setup(client, chip->gpio_chip.base,
+                               chip->gpio_chip.ngpio, pdata->context);
+               if (ret < 0)
+                       dev_warn(&client->dev, "setup failed, %d\n", ret);
+       }
+
+       i2c_set_clientdata(client, chip);
+       return 0;
+
+out_failed:
+       kfree(chip);
+       return ret;
+}
+
+static int __devexit max732x_remove(struct i2c_client *client)
+{
+       struct max732x_platform_data *pdata = client->dev.platform_data;
+       struct max732x_chip *chip = i2c_get_clientdata(client);
+       int ret;
+
+       if (pdata->teardown) {
+               ret = pdata->teardown(client, chip->gpio_chip.base,
+                               chip->gpio_chip.ngpio, pdata->context);
+               if (ret < 0) {
+                       dev_err(&client->dev, "%s failed, %d\n",
+                                       "teardown", ret);
+                       return ret;
+               }
+       }
+
+       ret = gpiochip_remove(&chip->gpio_chip);
+       if (ret) {
+               dev_err(&client->dev, "%s failed, %d\n",
+                               "gpiochip_remove()", ret);
+               return ret;
+       }
+
+       /* unregister any dummy i2c_client */
+       if (chip->client_dummy)
+               i2c_unregister_device(chip->client_dummy);
+
+       kfree(chip);
+       return 0;
+}
+
+static struct i2c_driver max732x_driver = {
+       .driver = {
+               .name   = "max732x",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = max732x_probe,
+       .remove         = __devexit_p(max732x_remove),
+       .id_table       = max732x_id,
+};
+
+static int __init max732x_init(void)
+{
+       return i2c_add_driver(&max732x_driver);
+}
+module_init(max732x_init);
+
+static void __exit max732x_exit(void)
+{
+       i2c_del_driver(&max732x_driver);
+}
+module_exit(max732x_exit);
+
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_DESCRIPTION("GPIO expander driver for MAX732X");
+MODULE_LICENSE("GPL");
index 7f92fdd5f0e2888b2c719e67873a5a7f0b435267..8a1b405fefda040f0001a5799299eefbe55f5768 100644 (file)
@@ -40,15 +40,26 @@ struct mcp23s08 {
        struct spi_device       *spi;
        u8                      addr;
 
+       u8                      cache[11];
        /* lock protects the cached values */
        struct mutex            lock;
-       u8                      cache[11];
 
        struct gpio_chip        chip;
 
        struct work_struct      work;
 };
 
+/* A given spi_device can represent up to four mcp23s08 chips
+ * sharing the same chipselect but using different addresses
+ * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
+ * Driver data holds all the per-chip data.
+ */
+struct mcp23s08_driver_data {
+       unsigned                ngpio;
+       struct mcp23s08         *mcp[4];
+       struct mcp23s08         chip[];
+};
+
 static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
 {
        u8      tx[2], rx[1];
@@ -208,25 +219,18 @@ done:
 
 /*----------------------------------------------------------------------*/
 
-static int mcp23s08_probe(struct spi_device *spi)
+static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
+               unsigned base, unsigned pullups)
 {
-       struct mcp23s08                 *mcp;
-       struct mcp23s08_platform_data   *pdata;
+       struct mcp23s08_driver_data     *data = spi_get_drvdata(spi);
+       struct mcp23s08                 *mcp = data->mcp[addr];
        int                             status;
        int                             do_update = 0;
 
-       pdata = spi->dev.platform_data;
-       if (!pdata || pdata->slave > 3 || !pdata->base)
-               return -ENODEV;
-
-       mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
-       if (!mcp)
-               return -ENOMEM;
-
        mutex_init(&mcp->lock);
 
        mcp->spi = spi;
-       mcp->addr = 0x40 | (pdata->slave << 1);
+       mcp->addr = 0x40 | (addr << 1);
 
        mcp->chip.label = "mcp23s08",
 
@@ -236,26 +240,28 @@ static int mcp23s08_probe(struct spi_device *spi)
        mcp->chip.set = mcp23s08_set;
        mcp->chip.dbg_show = mcp23s08_dbg_show;
 
-       mcp->chip.base = pdata->base;
+       mcp->chip.base = base;
        mcp->chip.ngpio = 8;
        mcp->chip.can_sleep = 1;
+       mcp->chip.dev = &spi->dev;
        mcp->chip.owner = THIS_MODULE;
 
-       spi_set_drvdata(spi, mcp);
-
-       /* verify MCP_IOCON.SEQOP = 0, so sequential reads work */
+       /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
+        * and MCP_IOCON.HAEN = 1, so we work with all chips.
+        */
        status = mcp23s08_read(mcp, MCP_IOCON);
        if (status < 0)
                goto fail;
-       if (status & IOCON_SEQOP) {
+       if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
                status &= ~IOCON_SEQOP;
+               status |= IOCON_HAEN;
                status = mcp23s08_write(mcp, MCP_IOCON, (u8) status);
                if (status < 0)
                        goto fail;
        }
 
        /* configure ~100K pullups */
-       status = mcp23s08_write(mcp, MCP_GPPU, pdata->pullups);
+       status = mcp23s08_write(mcp, MCP_GPPU, pullups);
        if (status < 0)
                goto fail;
 
@@ -282,11 +288,58 @@ static int mcp23s08_probe(struct spi_device *spi)
                tx[1] = MCP_IPOL;
                memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2);
                status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
-
-               /* FIXME check status... */
+               if (status < 0)
+                       goto fail;
        }
 
        status = gpiochip_add(&mcp->chip);
+fail:
+       if (status < 0)
+               dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n",
+                               addr, status);
+       return status;
+}
+
+static int mcp23s08_probe(struct spi_device *spi)
+{
+       struct mcp23s08_platform_data   *pdata;
+       unsigned                        addr;
+       unsigned                        chips = 0;
+       struct mcp23s08_driver_data     *data;
+       int                             status;
+       unsigned                        base;
+
+       pdata = spi->dev.platform_data;
+       if (!pdata || !gpio_is_valid(pdata->base))
+               return -ENODEV;
+
+       for (addr = 0; addr < 4; addr++) {
+               if (!pdata->chip[addr].is_present)
+                       continue;
+               chips++;
+       }
+       if (!chips)
+               return -ENODEV;
+
+       data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
+                       GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       spi_set_drvdata(spi, data);
+
+       base = pdata->base;
+       for (addr = 0; addr < 4; addr++) {
+               if (!pdata->chip[addr].is_present)
+                       continue;
+               chips--;
+               data->mcp[addr] = &data->chip[chips];
+               status = mcp23s08_probe_one(spi, addr, base,
+                               pdata->chip[addr].pullups);
+               if (status < 0)
+                       goto fail;
+               base += 8;
+       }
+       data->ngpio = base - pdata->base;
 
        /* NOTE:  these chips have a relatively sane IRQ framework, with
         * per-signal masking and level/edge triggering.  It's not yet
@@ -294,8 +347,9 @@ static int mcp23s08_probe(struct spi_device *spi)
         */
 
        if (pdata->setup) {
-               status = pdata->setup(spi, mcp->chip.base,
-                               mcp->chip.ngpio, pdata->context);
+               status = pdata->setup(spi,
+                               pdata->base, data->ngpio,
+                               pdata->context);
                if (status < 0)
                        dev_dbg(&spi->dev, "setup --> %d\n", status);
        }
@@ -303,19 +357,29 @@ static int mcp23s08_probe(struct spi_device *spi)
        return 0;
 
 fail:
-       kfree(mcp);
+       for (addr = 0; addr < 4; addr++) {
+               int tmp;
+
+               if (!data->mcp[addr])
+                       continue;
+               tmp = gpiochip_remove(&data->mcp[addr]->chip);
+               if (tmp < 0)
+                       dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+       }
+       kfree(data);
        return status;
 }
 
 static int mcp23s08_remove(struct spi_device *spi)
 {
-       struct mcp23s08                 *mcp = spi_get_drvdata(spi);
+       struct mcp23s08_driver_data     *data = spi_get_drvdata(spi);
        struct mcp23s08_platform_data   *pdata = spi->dev.platform_data;
+       unsigned                        addr;
        int                             status = 0;
 
        if (pdata->teardown) {
                status = pdata->teardown(spi,
-                               mcp->chip.base, mcp->chip.ngpio,
+                               pdata->base, data->ngpio,
                                pdata->context);
                if (status < 0) {
                        dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
@@ -323,11 +387,20 @@ static int mcp23s08_remove(struct spi_device *spi)
                }
        }
 
-       status = gpiochip_remove(&mcp->chip);
+       for (addr = 0; addr < 4; addr++) {
+               int tmp;
+
+               if (!data->mcp[addr])
+                       continue;
+
+               tmp = gpiochip_remove(&data->mcp[addr]->chip);
+               if (tmp < 0) {
+                       dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+                       status = tmp;
+               }
+       }
        if (status == 0)
-               kfree(mcp);
-       else
-               dev_err(&spi->dev, "%s --> %d\n", "remove", status);
+               kfree(data);
        return status;
 }
 
@@ -355,4 +428,3 @@ static void __exit mcp23s08_exit(void)
 module_exit(mcp23s08_exit);
 
 MODULE_LICENSE("GPL");
-
index a380730b61abe49800af8e655eaf5735d0524ad0..cc8468692ae0967b295e196c5073fb102c4894c7 100644 (file)
@@ -188,6 +188,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
        gc->base = chip->gpio_start;
        gc->ngpio = gpios;
        gc->label = chip->client->name;
+       gc->dev = &chip->client->dev;
        gc->owner = THIS_MODULE;
 }
 
index d25d356c4f200c9a197a5ac84373f7441e415e3a..fc9c6ae739ee74f8f77b8836bd5e7894001e5d9d 100644 (file)
@@ -200,6 +200,7 @@ static int pcf857x_probe(struct i2c_client *client,
 
        gpio->chip.base = pdata->gpio_base;
        gpio->chip.can_sleep = 1;
+       gpio->chip.dev = &client->dev;
        gpio->chip.owner = THIS_MODULE;
 
        /* NOTE:  the OnSemi jlc1562b is also largely compatible with
index 564138714bb5c6045755bb5db176af55a7c79bee..452c2d866ec566e7355d065f7065518444ae289f 100644 (file)
@@ -318,7 +318,7 @@ static void drm_cleanup(struct drm_device * dev)
                DRM_ERROR("Cannot unload module\n");
 }
 
-int drm_minors_cleanup(int id, void *ptr, void *data)
+static int drm_minors_cleanup(int id, void *ptr, void *data)
 {
        struct drm_minor *minor = ptr;
        struct drm_device *dev;
index 48d084bdf7c8e1d590b18130882c39bc44e3d038..3c855ff2992f0ad513500c9820b6e0a03eaa0719 100644 (file)
@@ -49,6 +49,8 @@ struct bfin_twi_iface {
        struct i2c_msg          *pmsg;
        int                     msg_num;
        int                     cur_msg;
+       u16                     saved_clkdiv;
+       u16                     saved_control;
        void __iomem            *regs_base;
 };
 
@@ -565,32 +567,43 @@ static u32 bfin_twi_functionality(struct i2c_adapter *adap)
               I2C_FUNC_I2C;
 }
 
-
 static struct i2c_algorithm bfin_twi_algorithm = {
        .master_xfer   = bfin_twi_master_xfer,
        .smbus_xfer    = bfin_twi_smbus_xfer,
        .functionality = bfin_twi_functionality,
 };
 
-
-static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
+static int i2c_bfin_twi_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct bfin_twi_iface *iface = platform_get_drvdata(dev);
+       struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
+
+       iface->saved_clkdiv = read_CLKDIV(iface);
+       iface->saved_control = read_CONTROL(iface);
+
+       free_irq(iface->irq, iface);
 
        /* Disable TWI */
-       write_CONTROL(iface, read_CONTROL(iface) & ~TWI_ENA);
-       SSYNC();
+       write_CONTROL(iface, iface->saved_control & ~TWI_ENA);
 
        return 0;
 }
 
-static int i2c_bfin_twi_resume(struct platform_device *dev)
+static int i2c_bfin_twi_resume(struct platform_device *pdev)
 {
-       struct bfin_twi_iface *iface = platform_get_drvdata(dev);
+       struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
 
-       /* Enable TWI */
-       write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
-       SSYNC();
+       int rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
+               IRQF_DISABLED, pdev->name, iface);
+       if (rc) {
+               dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
+               return -ENODEV;
+       }
+
+       /* Resume TWI interface clock as specified */
+       write_CLKDIV(iface, iface->saved_clkdiv);
+
+       /* Resume TWI */
+       write_CONTROL(iface, iface->saved_control);
 
        return 0;
 }
index 79b455a1f090587c4c63d5b29b76d8474c81b122..32104eac8d3db3d61e12907558262f1fe4ecffed 100644 (file)
@@ -77,7 +77,7 @@ static int i2c_gpio_getscl(void *data)
        return gpio_get_value(pdata->scl_pin);
 }
 
-static int __init i2c_gpio_probe(struct platform_device *pdev)
+static int __devinit i2c_gpio_probe(struct platform_device *pdev)
 {
        struct i2c_gpio_platform_data *pdata;
        struct i2c_algo_bit_data *bit_data;
@@ -174,7 +174,7 @@ err_alloc_adap:
        return ret;
 }
 
-static int __exit i2c_gpio_remove(struct platform_device *pdev)
+static int __devexit i2c_gpio_remove(struct platform_device *pdev)
 {
        struct i2c_gpio_platform_data *pdata;
        struct i2c_adapter *adap;
@@ -196,14 +196,15 @@ static struct platform_driver i2c_gpio_driver = {
                .name   = "i2c-gpio",
                .owner  = THIS_MODULE,
        },
-       .remove         = __exit_p(i2c_gpio_remove),
+       .probe          = i2c_gpio_probe,
+       .remove         = __devexit_p(i2c_gpio_remove),
 };
 
 static int __init i2c_gpio_init(void)
 {
        int ret;
 
-       ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe);
+       ret = platform_driver_register(&i2c_gpio_driver);
        if (ret)
                printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
 
index 007390ad9810555b0fe7f2ba6077445601ec919b..4864723c74257b6e63e2d25d6c4d3ae8676f1675 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/cpufreq.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -64,6 +65,7 @@ struct s3c24xx_i2c {
        unsigned int            tx_setup;
 
        enum s3c24xx_i2c_state  state;
+       unsigned long           clkrate;
 
        void __iomem            *regs;
        struct clk              *clk;
@@ -71,6 +73,10 @@ struct s3c24xx_i2c {
        struct resource         *irq;
        struct resource         *ioarea;
        struct i2c_adapter      adap;
+
+#ifdef CONFIG_CPU_FREQ
+       struct notifier_block   freq_transition;
+#endif
 };
 
 /* default platform data to use if not supplied in the platform_device
@@ -501,6 +507,9 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
        unsigned long timeout;
        int ret;
 
+       if (!readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN)
+               return -EIO;
+
        ret = s3c24xx_i2c_set_master(i2c);
        if (ret != 0) {
                dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
@@ -636,27 +645,28 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
        return (diff >= -2 && diff <= 2);
 }
 
-/* s3c24xx_i2c_getdivisor
+/* s3c24xx_i2c_clockrate
  *
  * work out a divisor for the user requested frequency setting,
  * either by the requested frequency, or scanning the acceptable
  * range of frequencies until something is found
 */
 
-static int s3c24xx_i2c_getdivisor(struct s3c24xx_i2c *i2c,
-                                 struct s3c2410_platform_i2c *pdata,
-                                 unsigned long *iicon,
-                                 unsigned int *got)
+static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
 {
+       struct s3c2410_platform_i2c *pdata;
        unsigned long clkin = clk_get_rate(i2c->clk);
-       
        unsigned int divs, div1;
+       u32 iiccon;
        int freq;
        int start, end;
 
+       i2c->clkrate = clkin;
+
+       pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
        clkin /= 1000;          /* clkin now in KHz */
      
-       dev_dbg(i2c->dev,  "pdata %p, freq %lu %lu..%lu\n",
+       dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n",
                 pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq);
 
        if (pdata->bus_freq != 0) {
@@ -688,11 +698,79 @@ static int s3c24xx_i2c_getdivisor(struct s3c24xx_i2c *i2c,
 
  found:
        *got = freq;
-       *iicon |= (divs-1);
-       *iicon |= (div1 == 512) ? S3C2410_IICCON_TXDIV_512 : 0;
+
+       iiccon = readl(i2c->regs + S3C2410_IICCON);
+       iiccon &= ~(S3C2410_IICCON_SCALEMASK | S3C2410_IICCON_TXDIV_512);
+       iiccon |= (divs-1);
+
+       if (div1 == 512)
+               iiccon |= S3C2410_IICCON_TXDIV_512;
+
+       writel(iiccon, i2c->regs + S3C2410_IICCON);
+
+       return 0;
+}
+
+#ifdef CONFIG_CPU_FREQ
+
+#define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition)
+
+static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
+                                         unsigned long val, void *data)
+{
+       struct s3c24xx_i2c *i2c = freq_to_i2c(nb);
+       unsigned long flags;
+       unsigned int got;
+       int delta_f;
+       int ret;
+
+       delta_f = clk_get_rate(i2c->clk) - i2c->clkrate;
+
+       /* if we're post-change and the input clock has slowed down
+        * or at pre-change and the clock is about to speed up, then
+        * adjust our clock rate. <0 is slow, >0 speedup.
+        */
+
+       if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
+           (val == CPUFREQ_PRECHANGE && delta_f > 0)) {
+               spin_lock_irqsave(&i2c->lock, flags);
+               ret = s3c24xx_i2c_clockrate(i2c, &got);
+               spin_unlock_irqrestore(&i2c->lock, flags);
+
+               if (ret < 0)
+                       dev_err(i2c->dev, "cannot find frequency\n");
+               else
+                       dev_info(i2c->dev, "setting freq %d\n", got);
+       }
+
+       return 0;
+}
+
+static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c)
+{
+       i2c->freq_transition.notifier_call = s3c24xx_i2c_cpufreq_transition;
+
+       return cpufreq_register_notifier(&i2c->freq_transition,
+                                        CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
+{
+       cpufreq_unregister_notifier(&i2c->freq_transition,
+                                   CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c)
+{
        return 0;
 }
 
+static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
+{
+}
+#endif
+
 /* s3c24xx_i2c_init
  *
  * initialise the controller, set the IO lines and frequency 
@@ -719,9 +797,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
 
        dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
 
+       writel(iicon, i2c->regs + S3C2410_IICCON);
+
        /* we need to work out the divisors for the clock... */
 
-       if (s3c24xx_i2c_getdivisor(i2c, pdata, &iicon, &freq) != 0) {
+       if (s3c24xx_i2c_clockrate(i2c, &freq) != 0) {
+               writel(0, i2c->regs + S3C2410_IICCON);
                dev_err(i2c->dev, "cannot meet bus frequency required\n");
                return -EINVAL;
        }
@@ -730,8 +811,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
 
        dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
        dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
-       
-       writel(iicon, i2c->regs + S3C2410_IICCON);
 
        /* check for s3c2440 i2c controller  */
 
@@ -752,9 +831,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
 static int s3c24xx_i2c_probe(struct platform_device *pdev)
 {
        struct s3c24xx_i2c *i2c = &s3c24xx_i2c;
+       struct s3c2410_platform_i2c *pdata;
        struct resource *res;
        int ret;
 
+       pdata = s3c24xx_i2c_get_platformdata(&pdev->dev);
+
        /* find the clock and enable it */
 
        i2c->dev = &pdev->dev;
@@ -832,17 +914,34 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res,
                (unsigned long)res->start);
 
-       ret = i2c_add_adapter(&i2c->adap);
+       ret = s3c24xx_i2c_register_cpufreq(i2c);
        if (ret < 0) {
-               dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+               dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
                goto err_irq;
        }
 
+       /* Note, previous versions of the driver used i2c_add_adapter()
+        * to add the bus at any number. We now pass the bus number via
+        * the platform data, so if unset it will now default to always
+        * being bus 0.
+        */
+
+       i2c->adap.nr = pdata->bus_num;
+
+       ret = i2c_add_numbered_adapter(&i2c->adap);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+               goto err_cpufreq;
+       }
+
        platform_set_drvdata(pdev, i2c);
 
        dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
        return 0;
 
+ err_cpufreq:
+       s3c24xx_i2c_deregister_cpufreq(i2c);
+
  err_irq:
        free_irq(i2c->irq->start, i2c);
 
@@ -870,6 +969,8 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
 {
        struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
 
+       s3c24xx_i2c_deregister_cpufreq(i2c);
+
        i2c_del_adapter(&i2c->adap);
        free_irq(i2c->irq->start, i2c);
 
index 50e0a465374193d6f93d4ceb3e74367c0a0b2ec7..a95cb9465d656949bed4429279a75c35fb547b23 100644 (file)
@@ -126,7 +126,7 @@ config ISP1301_OMAP
 
 config TPS65010
        tristate "TPS6501x Power Management chips"
-       depends on HAVE_GPIO_LIB
+       depends on GPIOLIB
        default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
        help
          If you say yes here you get support for the TPS6501x series of
index 85949685191bb3218e75cb5547aab3750b7e291d..cf02e8fceb42a7a1ef4ee91c42d0fb8cfdd14ecb 100644 (file)
@@ -636,6 +636,8 @@ static int tps65010_probe(struct i2c_client *client,
                tps->outmask = board->outmask;
 
                tps->chip.label = client->name;
+               tps->chip.dev = &client->dev;
+               tps->chip.owner = THIS_MODULE;
 
                tps->chip.set = tps65010_gpio_set;
                tps->chip.direction_output = tps65010_output;
index 04d9c4d459d00f61e77efcee48ea91797dc0e0a0..130ef64b44f75b847469bcc0a22f684243e974e1 100644 (file)
@@ -314,7 +314,7 @@ comment "IDE chipset support/bugfixes"
 
 config IDE_GENERIC
        tristate "generic/default IDE chipset support"
-       depends on ALPHA || X86 || IA64 || M32R || MIPS || PPC32
+       depends on ALPHA || X86 || IA64 || M32R || MIPS
        help
          If unsure, say N.
 
index 5d414e301a5a9c319a23e9da0463ca0231035e5c..64e0ecdc4ed5dab46c7b07b1a5ae7b903f2d6416 100644 (file)
@@ -1,13 +1,6 @@
 #
-# Makefile for the kernel ata, atapi, and ide block device drivers.
-#
-# 12 September 2000, Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
-# Rewritten to use lists instead of if-statements.
-#
-# Note : at this point, these files are compiled on all systems.
-# In the future, some of these should be built conditionally.
-#
 # link order is important here
+#
 
 EXTRA_CFLAGS                           += -Idrivers/ide
 
index f575e8341aec8f3e2580486e6f0432045bb73bbc..df4af40839541e5b0d3fd3b1621591f33c13f852 100644 (file)
@@ -710,8 +710,14 @@ static int __init icside_init(void)
        return ecard_register_driver(&icside_driver);
 }
 
+static void __exit icside_exit(void);
+{
+       ecard_unregister_driver(&icside_driver);
+}
+
 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("ICS IDE driver");
 
 module_init(icside_init);
+module_exit(icside_exit);
index 65bb4b8fd57086946e02c2c09bf907fa9909980b..3e842d60eae94804c3cc53328a39b007171245e8 100644 (file)
@@ -82,6 +82,7 @@ static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
        {100, 120},             /* UDMA Mode 2 */
        {100, 90},              /* UDMA Mode 3 */
        {100, 60},              /* UDMA Mode 4 */
+       {85,  40},              /* UDMA Mode 5 */
 };
 
 static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
@@ -334,12 +335,11 @@ static const struct ide_port_ops palm_bk3710_ports_ops = {
        .cable_detect           = palm_bk3710_cable_detect,
 };
 
-static const struct ide_port_info __devinitdata palm_bk3710_port_info = {
+static struct ide_port_info __devinitdata palm_bk3710_port_info = {
        .init_dma               = palm_bk3710_init_dma,
        .port_ops               = &palm_bk3710_ports_ops,
        .host_flags             = IDE_HFLAG_MMIO,
        .pio_mask               = ATA_PIO4,
-       .udma_mask              = ATA_UDMA4,    /* (input clk 99MHz) */
        .mwdma_mask             = ATA_MWDMA2,
 };
 
@@ -352,7 +352,7 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
        int i, rc;
        hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
-       clk = clk_get(NULL, "IDECLK");
+       clk = clk_get(&pdev->dev, "IDECLK");
        if (IS_ERR(clk))
                return -ENODEV;
 
@@ -392,6 +392,9 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
        hw.irq = irq->start;
        hw.chipset = ide_palm3710;
 
+       palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
+                                                            ATA_UDMA5;
+
        rc = ide_host_add(&palm_bk3710_port_info, hws, NULL);
        if (rc)
                goto out;
index 2bdd8b734afb6221aed29958c9a696e4f341614b..78d27d9ae4303ab6ee1dd4d2860445b80ea69a2d 100644 (file)
@@ -95,7 +95,13 @@ static int __init rapide_init(void)
        return ecard_register_driver(&rapide_driver);
 }
 
+static void __exit rapide_exit(void)
+{
+       ecard_unregister_driver(&rapide_driver);
+}
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Yellowstone RAPIDE driver");
 
 module_init(rapide_init);
+module_exit(rapide_exit);
index 4e73aeee40534f553c65075c6b1b4730c2253123..e617cf08aef67b882370f3f596694df2f465e3f4 100644 (file)
@@ -57,23 +57,29 @@ static DEFINE_MUTEX(idecd_ref_mutex);
 #define ide_cd_g(disk) \
        container_of((disk)->private_data, struct cdrom_info, driver)
 
+static void ide_cd_release(struct kref *);
+
 static struct cdrom_info *ide_cd_get(struct gendisk *disk)
 {
        struct cdrom_info *cd = NULL;
 
        mutex_lock(&idecd_ref_mutex);
        cd = ide_cd_g(disk);
-       if (cd)
+       if (cd) {
                kref_get(&cd->kref);
+               if (ide_device_get(cd->drive)) {
+                       kref_put(&cd->kref, ide_cd_release);
+                       cd = NULL;
+               }
+       }
        mutex_unlock(&idecd_ref_mutex);
        return cd;
 }
 
-static void ide_cd_release(struct kref *);
-
 static void ide_cd_put(struct cdrom_info *cd)
 {
        mutex_lock(&idecd_ref_mutex);
+       ide_device_put(cd->drive);
        kref_put(&cd->kref, ide_cd_release);
        mutex_unlock(&idecd_ref_mutex);
 }
@@ -1305,13 +1311,30 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
 
        stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0,
                               REQ_QUIET);
-       if (stat == 0) {
-               *capacity = 1 + be32_to_cpu(capbuf.lba);
-               *sectors_per_frame =
-                       be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
+       if (stat)
+               return stat;
+
+       /*
+        * Sanity check the given block size
+        */
+       switch (capbuf.blocklen) {
+       case __constant_cpu_to_be32(512):
+       case __constant_cpu_to_be32(1024):
+       case __constant_cpu_to_be32(2048):
+       case __constant_cpu_to_be32(4096):
+               break;
+       default:
+               printk(KERN_ERR "%s: weird block size %u\n",
+                       drive->name, capbuf.blocklen);
+               printk(KERN_ERR "%s: default to 2kb block size\n",
+                       drive->name);
+               capbuf.blocklen = __constant_cpu_to_be32(2048);
+               break;
        }
 
-       return stat;
+       *capacity = 1 + be32_to_cpu(capbuf.lba);
+       *sectors_per_frame = be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
+       return 0;
 }
 
 static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
index df5fe5756871ca31b135a736dfc64f9d1097bec6..28d85b410f7ce03361ddec4c957c930a9aa08518 100644 (file)
@@ -56,23 +56,29 @@ static DEFINE_MUTEX(idedisk_ref_mutex);
 #define ide_disk_g(disk) \
        container_of((disk)->private_data, struct ide_disk_obj, driver)
 
+static void ide_disk_release(struct kref *);
+
 static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
 {
        struct ide_disk_obj *idkp = NULL;
 
        mutex_lock(&idedisk_ref_mutex);
        idkp = ide_disk_g(disk);
-       if (idkp)
+       if (idkp) {
                kref_get(&idkp->kref);
+               if (ide_device_get(idkp->drive)) {
+                       kref_put(&idkp->kref, ide_disk_release);
+                       idkp = NULL;
+               }
+       }
        mutex_unlock(&idedisk_ref_mutex);
        return idkp;
 }
 
-static void ide_disk_release(struct kref *);
-
 static void ide_disk_put(struct ide_disk_obj *idkp)
 {
        mutex_lock(&idedisk_ref_mutex);
+       ide_device_put(idkp->drive);
        kref_put(&idkp->kref, ide_disk_release);
        mutex_unlock(&idedisk_ref_mutex);
 }
index be99d463dcc7dfa0265498280e103715ee61bf61..71c377a7bcf2dd4f5f69af951fe5b10602d6bf82 100644 (file)
@@ -173,7 +173,7 @@ EXPORT_SYMBOL_GPL(ide_build_sglist);
 int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
 {
        ide_hwif_t *hwif        = HWIF(drive);
-       unsigned int *table     = hwif->dmatable_cpu;
+       __le32 *table = (__le32 *)hwif->dmatable_cpu;
        unsigned int is_trm290  = (hwif->chipset == ide_trm290) ? 1 : 0;
        unsigned int count = 0;
        int i;
index 3d8e6dd0f41e11f031e7dad1a1be1c434430cbf0..ca11a26746f16a95fa83d6d99288d42c01281a1c 100644 (file)
@@ -158,23 +158,29 @@ static DEFINE_MUTEX(idefloppy_ref_mutex);
 #define ide_floppy_g(disk) \
        container_of((disk)->private_data, struct ide_floppy_obj, driver)
 
+static void idefloppy_cleanup_obj(struct kref *);
+
 static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
 {
        struct ide_floppy_obj *floppy = NULL;
 
        mutex_lock(&idefloppy_ref_mutex);
        floppy = ide_floppy_g(disk);
-       if (floppy)
+       if (floppy) {
                kref_get(&floppy->kref);
+               if (ide_device_get(floppy->drive)) {
+                       kref_put(&floppy->kref, idefloppy_cleanup_obj);
+                       floppy = NULL;
+               }
+       }
        mutex_unlock(&idefloppy_ref_mutex);
        return floppy;
 }
 
-static void idefloppy_cleanup_obj(struct kref *);
-
 static void ide_floppy_put(struct ide_floppy_obj *floppy)
 {
        mutex_lock(&idefloppy_ref_mutex);
+       ide_device_put(floppy->drive);
        kref_put(&floppy->kref, idefloppy_cleanup_obj);
        mutex_unlock(&idefloppy_ref_mutex);
 }
index 31d98fec775f32e1732d13970a304fa7012a7e95..8fe8b5b9cf7d7a1e6c7b70e60ed293d2178d57d2 100644 (file)
 #include <linux/module.h>
 #include <linux/ide.h>
 
+/* FIXME: convert m32r to use ide_platform host driver */
+#ifdef CONFIG_M32R
+#include <asm/m32r.h>
+#endif
+
 #define DRV_NAME       "ide_generic"
 
 static int probe_mask = 0x03;
@@ -80,6 +85,21 @@ static int __init ide_generic_sysfs_init(void)
        return 0;
 }
 
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \
+       || defined(CONFIG_PLAT_OPSPUT)
+static const u16 legacy_bases[] = { 0x1f0 };
+static const int legacy_irqs[]  = { PLD_IRQ_CFIREQ };
+#elif defined(CONFIG_PLAT_MAPPI3)
+static const u16 legacy_bases[] = { 0x1f0, 0x170 };
+static const int legacy_irqs[]  = { PLD_IRQ_CFIREQ, PLD_IRQ_IDEIREQ };
+#elif defined(CONFIG_ALPHA)
+static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168 };
+static const int legacy_irqs[]  = { 14, 15, 11, 10 };
+#else
+static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
+static const int legacy_irqs[]  = { 14, 15, 11, 10, 8, 12 };
+#endif
+
 static int __init ide_generic_init(void)
 {
        hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS];
@@ -87,11 +107,17 @@ static int __init ide_generic_init(void)
        unsigned long io_addr;
        int i, rc;
 
+#ifdef CONFIG_MIPS
+       if (!ide_probe_legacy())
+               return -ENODEV;
+#endif
        printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module "
                         "parameter for probing all legacy ISA IDE ports\n");
 
-       for (i = 0; i < MAX_HWIFS; i++) {
-               io_addr = ide_default_io_base(i);
+       memset(hws, 0, sizeof(hw_regs_t *) * MAX_HWIFS);
+
+       for (i = 0; i < ARRAY_SIZE(legacy_bases); i++) {
+               io_addr = legacy_bases[i];
 
                hws[i] = NULL;
 
@@ -113,7 +139,11 @@ static int __init ide_generic_init(void)
 
                        memset(&hw[i], 0, sizeof(hw[i]));
                        ide_std_init_ports(&hw[i], io_addr, io_addr + 0x206);
-                       hw[i].irq = ide_default_irq(io_addr);
+#ifdef CONFIG_IA64
+                       hw[i].irq = isa_irq_to_vector(legacy_irqs[i]);
+#else
+                       hw[i].irq = legacy_irqs[i];
+#endif
                        hw[i].chipset = ide_generic;
 
                        hws[i] = &hw[i];
index 07da5fb9eaff0d760e93c5736b1b3dedb19f58de..8aae91764513afeaf71021bc5d32974683e8163d 100644 (file)
@@ -510,10 +510,8 @@ void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
 
        if (byteswap) {
                /* convert from big-endian to host byte order */
-               for (p = end ; p != s;) {
-                       unsigned short *pp = (unsigned short *) (p -= 2);
-                       *pp = ntohs(*pp);
-               }
+               for (p = end ; p != s;)
+                       be16_to_cpus((u16 *)(p -= 2));
        }
        /* strip leading blanks */
        while (s != end && *s == ' ')
index 4aa76c45375562450dfe836d955dcddf9e27e799..994e41099b42e5e95ed08cce0154bb89b6e727b0 100644 (file)
@@ -134,18 +134,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
 #endif
        ide_fix_driveid(id);
 
-#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
-       /*
-        * EATA SCSI controllers do a hardware ATA emulation:
-        * Ignore them if there is a driver for them available.
-        */
-       if ((id->model[0] == 'P' && id->model[1] == 'M') ||
-           (id->model[0] == 'S' && id->model[1] == 'K')) {
-               printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
-               goto err_misc;
-       }
-#endif /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */
-
        /*
         *  WIN_IDENTIFY returns little-endian info,
         *  WIN_PIDENTIFY *usually* returns little-endian info.
@@ -167,7 +155,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
        if (strstr(id->model, "E X A B Y T E N E S T"))
                goto err_misc;
 
-       printk("%s: %s, ", drive->name, id->model);
+       printk(KERN_INFO "%s: %s, ", drive->name, id->model);
+
        drive->present = 1;
        drive->dead = 0;
 
@@ -176,16 +165,17 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
         */
        if (cmd == WIN_PIDENTIFY) {
                u8 type = (id->config >> 8) & 0x1f;
-               printk("ATAPI ");
+
+               printk(KERN_CONT "ATAPI ");
                switch (type) {
                        case ide_floppy:
                                if (!strstr(id->model, "CD-ROM")) {
                                        if (!strstr(id->model, "oppy") &&
                                            !strstr(id->model, "poyp") &&
                                            !strstr(id->model, "ZIP"))
-                                               printk("cdrom or floppy?, assuming ");
+                                               printk(KERN_CONT "cdrom or floppy?, assuming ");
                                        if (drive->media != ide_cdrom) {
-                                               printk ("FLOPPY");
+                                               printk(KERN_CONT "FLOPPY");
                                                drive->removable = 1;
                                                break;
                                        }
@@ -198,25 +188,25 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
                                /* kludge for Apple PowerBook internal zip */
                                if (!strstr(id->model, "CD-ROM") &&
                                    strstr(id->model, "ZIP")) {
-                                       printk ("FLOPPY");
+                                       printk(KERN_CONT "FLOPPY");
                                        type = ide_floppy;
                                        break;
                                }
 #endif
-                               printk ("CD/DVD-ROM");
+                               printk(KERN_CONT "CD/DVD-ROM");
                                break;
                        case ide_tape:
-                               printk ("TAPE");
+                               printk(KERN_CONT "TAPE");
                                break;
                        case ide_optical:
-                               printk ("OPTICAL");
+                               printk(KERN_CONT "OPTICAL");
                                drive->removable = 1;
                                break;
                        default:
-                               printk("UNKNOWN (type %d)", type);
+                               printk(KERN_CONT "UNKNOWN (type %d)", type);
                                break;
                }
-               printk (" drive\n");
+               printk(KERN_CONT " drive\n");
                drive->media = type;
                /* an ATAPI device ignores DRDY */
                drive->ready_stat = 0;
@@ -236,7 +226,9 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
                drive->removable = 1;
 
        drive->media = ide_disk;
-       printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
+
+       printk(KERN_CONT "%s DISK drive\n",
+               (id->config == 0x848a) ? "CFA" : "ATA");
 
        return;
 
@@ -387,7 +379,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
                                /* Mmmm.. multiple IRQs..
                                 * don't know which was ours
                                 */
-                               printk("%s: IRQ probe failed (0x%lx)\n",
+                               printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n",
                                        drive->name, cookie);
                        }
                }
@@ -456,7 +448,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
                        return 4;
        }
 #ifdef DEBUG
-       printk("probing for %s: present=%d, media=%d, probetype=%s\n",
+       printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n",
                drive->name, drive->present, drive->media,
                (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
 #endif
@@ -534,7 +526,8 @@ static void enable_nest (ide_drive_t *drive)
        const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        u8 stat;
 
-       printk("%s: enabling %s -- ", hwif->name, drive->id->model);
+       printk(KERN_INFO "%s: enabling %s -- ", hwif->name, drive->id->model);
+
        SELECT_DRIVE(drive);
        msleep(50);
        tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST);
@@ -883,7 +876,7 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
        if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
                if (!new->hwgroup)
                        return;
-               printk("%s: potential irq problem with %s and %s\n",
+               printk(KERN_WARNING "%s: potential IRQ problem with %s and %s\n",
                        hwif->name, new->name, m->name);
        }
        if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
@@ -1142,17 +1135,17 @@ static int init_irq (ide_hwif_t *hwif)
        }
 
 #if !defined(__mc68000__)
-       printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
+       printk(KERN_INFO "%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
                io_ports->data_addr, io_ports->status_addr,
                io_ports->ctl_addr, hwif->irq);
 #else
-       printk("%s at 0x%08lx on irq %d", hwif->name,
+       printk(KERN_INFO "%s at 0x%08lx on irq %d", hwif->name,
                io_ports->data_addr, hwif->irq);
 #endif /* __mc68000__ */
        if (match)
-               printk(" (%sed with %s)",
+               printk(KERN_CONT " (%sed with %s)",
                        hwif->sharing_irq ? "shar" : "serializ", match->name);
-       printk("\n");
+       printk(KERN_CONT "\n");
 
        mutex_unlock(&ide_cfg_mtx);
        return 0;
@@ -1287,7 +1280,7 @@ static int hwif_init(ide_hwif_t *hwif)
        if (!hwif->irq) {
                hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
                if (!hwif->irq) {
-                       printk("%s: DISABLED, NO IRQ\n", hwif->name);
+                       printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name);
                        return 0;
                }
        }
@@ -1317,16 +1310,16 @@ static int hwif_init(ide_hwif_t *hwif)
         */
        hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
        if (!hwif->irq) {
-               printk("%s: Disabled unable to get IRQ %d.\n",
+               printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n",
                        hwif->name, old_irq);
                goto out;
        }
        if (init_irq(hwif)) {
-               printk("%s: probed IRQ %d and default IRQ %d failed.\n",
+               printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n",
                        hwif->name, old_irq, hwif->irq);
                goto out;
        }
-       printk("%s: probed IRQ %d failed, using default.\n",
+       printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n",
                hwif->name, hwif->irq);
 
 done:
@@ -1595,6 +1588,8 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
 
                ide_init_port_data(hwif, idx);
 
+               hwif->host = host;
+
                host->ports[i] = hwif;
                host->n_ports++;
        }
@@ -1604,6 +1599,12 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
                return NULL;
        }
 
+       if (hws[0])
+               host->dev[0] = hws[0]->dev;
+
+       if (d)
+               host->host_flags = d->host_flags;
+
        return host;
 }
 EXPORT_SYMBOL_GPL(ide_host_alloc_all);
index 151c91e933dab156adb2606f4a55384fc4866ad0..f66c9c3f6fc6686d56479a56a902f88822544db3 100644 (file)
@@ -105,7 +105,7 @@ static int proc_ide_read_identify
        len = sprintf(page, "\n");
 
        if (drive) {
-               unsigned short *val = (unsigned short *) page;
+               __le16 *val = (__le16 *)page;
 
                err = taskfile_lib_get_identify(drive, page);
                if (!err) {
@@ -113,7 +113,7 @@ static int proc_ide_read_identify
                        page = out;
                        do {
                                out += sprintf(out, "%04x%c",
-                                       le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+                                       le16_to_cpup(val), (++i & 7) ? ' ' : '\n');
                                val += 1;
                        } while (i < (SECTOR_WORDS * 2));
                        len = out - page;
index 6962ca4891a134517774fa9dbf7ec533ee938b5b..82c2afe4d28a3a081a30fd5755de01fb17fc2e44 100644 (file)
@@ -322,23 +322,29 @@ static struct class *idetape_sysfs_class;
 #define ide_tape_g(disk) \
        container_of((disk)->private_data, struct ide_tape_obj, driver)
 
+static void ide_tape_release(struct kref *);
+
 static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
 {
        struct ide_tape_obj *tape = NULL;
 
        mutex_lock(&idetape_ref_mutex);
        tape = ide_tape_g(disk);
-       if (tape)
+       if (tape) {
                kref_get(&tape->kref);
+               if (ide_device_get(tape->drive)) {
+                       kref_put(&tape->kref, ide_tape_release);
+                       tape = NULL;
+               }
+       }
        mutex_unlock(&idetape_ref_mutex);
        return tape;
 }
 
-static void ide_tape_release(struct kref *);
-
 static void ide_tape_put(struct ide_tape_obj *tape)
 {
        mutex_lock(&idetape_ref_mutex);
+       ide_device_put(tape->drive);
        kref_put(&tape->kref, ide_tape_release);
        mutex_unlock(&idetape_ref_mutex);
 }
@@ -649,10 +655,10 @@ static void ide_tape_callback(ide_drive_t *drive)
                        uptodate = 0;
                } else {
                        debug_log(DBG_SENSE, "Block Location - %u\n",
-                                       be32_to_cpu(*(u32 *)&readpos[4]));
+                                       be32_to_cpup((__be32 *)&readpos[4]));
 
                        tape->partition = readpos[1];
-                       tape->first_frame = be32_to_cpu(*(u32 *)&readpos[4]);
+                       tape->first_frame = be32_to_cpup((__be32 *)&readpos[4]);
                        set_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
                }
        }
@@ -2375,23 +2381,23 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
        caps = pc.buf + 4 + pc.buf[3];
 
        /* convert to host order and save for later use */
-       speed = be16_to_cpu(*(u16 *)&caps[14]);
-       max_speed = be16_to_cpu(*(u16 *)&caps[8]);
+       speed = be16_to_cpup((__be16 *)&caps[14]);
+       max_speed = be16_to_cpup((__be16 *)&caps[8]);
 
-       put_unaligned(max_speed, (u16 *)&caps[8]);
-       put_unaligned(be16_to_cpu(*(u16 *)&caps[12]), (u16 *)&caps[12]);
-       put_unaligned(speed, (u16 *)&caps[14]);
-       put_unaligned(be16_to_cpu(*(u16 *)&caps[16]), (u16 *)&caps[16]);
+       *(u16 *)&caps[8] = max_speed;
+       *(u16 *)&caps[12] = be16_to_cpup((__be16 *)&caps[12]);
+       *(u16 *)&caps[14] = speed;
+       *(u16 *)&caps[16] = be16_to_cpup((__be16 *)&caps[16]);
 
        if (!speed) {
                printk(KERN_INFO "ide-tape: %s: invalid tape speed "
                                "(assuming 650KB/sec)\n", drive->name);
-               put_unaligned(650, (u16 *)&caps[14]);
+               *(u16 *)&caps[14] = 650;
        }
        if (!max_speed) {
                printk(KERN_INFO "ide-tape: %s: invalid max_speed "
                                "(assuming 650KB/sec)\n", drive->name);
-               put_unaligned(650, (u16 *)&caps[8]);
+               *(u16 *)&caps[8] = 650;
        }
 
        memcpy(&tape->caps, caps, 20);
index aeddbbd69e862e6526ee25d7a83e6143e1c5468f..7fb6f1c86272d215f65678adeb2b9d3daf26e3a0 100644 (file)
@@ -126,7 +126,10 @@ EXPORT_SYMBOL_GPL(do_rw_taskfile);
 static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       u8 stat = hwif->tp_ops->read_status(hwif);
+       u8 stat;
+
+       local_irq_enable_in_hardirq();
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (OK_STAT(stat, READY_STAT, BAD_STAT))
                drive->mult_count = drive->mult_req;
@@ -147,6 +150,8 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
        int retries = 5;
        u8 stat;
 
+       local_irq_enable_in_hardirq();
+
        while (1) {
                stat = hwif->tp_ops->read_status(hwif);
                if ((stat & BUSY_STAT) == 0 || retries-- == 0)
@@ -170,7 +175,10 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
 static ide_startstop_t recal_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       u8 stat = hwif->tp_ops->read_status(hwif);
+       u8 stat;
+
+       local_irq_enable_in_hardirq();
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (!OK_STAT(stat, READY_STAT, BAD_STAT))
                return ide_error(drive, "recal_intr", stat);
index 60f0ca66aa93735d68f27478888cf01132457d47..772451600e4d96064b57f8732a7579481ee2b3a1 100644 (file)
@@ -618,6 +618,53 @@ set_val:
 
 EXPORT_SYMBOL(generic_ide_ioctl);
 
+/**
+ * ide_device_get      -       get an additional reference to a ide_drive_t
+ * @drive:     device to get a reference to
+ *
+ * Gets a reference to the ide_drive_t and increments the use count of the
+ * underlying LLDD module.
+ */
+int ide_device_get(ide_drive_t *drive)
+{
+       struct device *host_dev;
+       struct module *module;
+
+       if (!get_device(&drive->gendev))
+               return -ENXIO;
+
+       host_dev = drive->hwif->host->dev[0];
+       module = host_dev ? host_dev->driver->owner : NULL;
+
+       if (module && !try_module_get(module)) {
+               put_device(&drive->gendev);
+               return -ENXIO;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ide_device_get);
+
+/**
+ * ide_device_put      -       release a reference to a ide_drive_t
+ * @drive:     device to release a reference on
+ *
+ * Release a reference to the ide_drive_t and decrements the use count of
+ * the underlying LLDD module.
+ */
+void ide_device_put(ide_drive_t *drive)
+{
+#ifdef CONFIG_MODULE_UNLOAD
+       struct device *host_dev = drive->hwif->host->dev[0];
+       struct module *module = host_dev ? host_dev->driver->owner : NULL;
+
+       if (module)
+               module_put(module);
+#endif
+       put_device(&drive->gendev);
+}
+EXPORT_SYMBOL_GPL(ide_device_put);
+
 static int ide_bus_match(struct device *dev, struct device_driver *drv)
 {
        return 1;
index dd5c467d8dd0582ac454bfd8796f2332a4a777b1..51ba085d7aa8a42d34420591cac7df3a0b5ca65b 100644 (file)
@@ -127,7 +127,7 @@ static int __init gayle_init(void)
     unsigned long phys_base, res_start, res_n;
     unsigned long base, ctrlport, irqport;
     ide_ack_intr_t *ack_intr;
-    int a4000, i;
+    int a4000, i, rc;
     hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
 
     if (!MACH_IS_AMIGA)
@@ -179,7 +179,11 @@ found:
        hws[i] = &hw[i];
     }
 
-    return ide_host_add(NULL, hws, NULL);
+    rc = ide_host_add(NULL, hws, NULL);
+    if (rc)
+       release_mem_region(res_start, res_n);
+
+    return rc;
 }
 
 module_init(gayle_init);
index 7bc8fd59ea9ee336dbcab2a5981c0bf696df6401..98f7c95e39ed4fd0e9f89244b5cb7a2edbde6e4d 100644 (file)
@@ -3,34 +3,12 @@
  */
 
 /*
- *
- *  Version 0.01        Initial version hacked out of ide.c
- *
- *  Version 0.02        Added support for PIO modes, auto-tune
- *
- *  Version 0.03        Some cleanups
- *
- *  Version 0.05        PIO mode cycle timings auto-tune using bus-speed
- *
- *  Version 0.06        Prefetch mode now defaults no OFF. To set
- *                      prefetch mode OFF/ON use "hdparm -p8/-p9".
- *                      Unmask irq is disabled when prefetch mode
- *                      is enabled.
- *
- *  Version 0.07        Trying to fix CD-ROM detection problem.
- *                      "Prefetch" mode bit OFF for ide disks and
- *                      ON for anything else.
- *
- *  Version 0.08        Need to force prefetch for CDs and other non-disk
- *                      devices. (not sure which devices exactly need
- *                      prefetch)
- *
  *  HT-6560B EIDE-controller support
  *  To activate controller support use kernel parameter "ide0=ht6560b".
  *  Use hdparm utility to enable PIO mode support.
  *
  *  Author:    Mikko Ala-Fossi            <maf@iki.fi>
- *             Jan Evert van Grootheest   <janevert@caiway.nl>
+ *             Jan Evert van Grootheest   <j.e.van.grootheest@caiway.nl>
  *
  *  Try:  http://www.maf.iki.fi/~maf/ht6560b/
  */
index fbc43e121e6b19856f4ceb528c299d5dd682656e..e0c8fe7d9fea9facda5be76db1821100d4a4c201 100644 (file)
@@ -13,6 +13,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "aec62xx"
+
 struct chipset_bus_clock_list_entry {
        u8 xfer_speed;
        u8 chipset_settings;
@@ -59,10 +61,6 @@ static const struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
        {       0,              0x00,   0x00    }
 };
 
-#define BUSCLOCK(D)    \
-       ((struct chipset_bus_clock_list_entry *) pci_get_drvdata((D)))
-
-
 /*
  * TO DO: active tuning and correction of cards without a bios.
  */
@@ -88,6 +86,8 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
        u16 d_conf              = 0;
        u8 ultra = 0, ultra_conf = 0;
        u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
@@ -96,7 +96,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
        local_irq_save(flags);
        /* 0x40|(2*drive->dn): Active, 0x41|(2*drive->dn): Recovery */
        pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
-       tmp0 = pci_bus_clock_list(speed, BUSCLOCK(dev));
+       tmp0 = pci_bus_clock_list(speed, bus_clock);
        d_conf = ((tmp0 & 0xf0) << 4) | (tmp0 & 0xf);
        pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
 
@@ -104,7 +104,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
        tmp2 = 0x00;
        pci_read_config_byte(dev, 0x54, &ultra);
        tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
-       ultra_conf = pci_bus_clock_list_ultra(speed, BUSCLOCK(dev));
+       ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
        tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
        pci_write_config_byte(dev, 0x54, tmp2);
        local_irq_restore(flags);
@@ -114,6 +114,8 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
        u8 unit         = (drive->select.b.unit & 0x01);
        u8 tmp1 = 0, tmp2 = 0;
        u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
@@ -122,12 +124,12 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
        local_irq_save(flags);
        /* high 4-bits: Active, low 4-bits: Recovery */
        pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
-       drive_conf = pci_bus_clock_list(speed, BUSCLOCK(dev));
+       drive_conf = pci_bus_clock_list(speed, bus_clock);
        pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
 
        pci_read_config_byte(dev, (0x44|hwif->channel), &ultra);
        tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
-       ultra_conf = pci_bus_clock_list_ultra(speed, BUSCLOCK(dev));
+       ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
        tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
        pci_write_config_byte(dev, (0x44|hwif->channel), tmp2);
        local_irq_restore(flags);
@@ -138,15 +140,8 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
        drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
 }
 
-static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev)
 {
-       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
-
-       if (bus_speed <= 33)
-               pci_set_drvdata(dev, (void *) aec6xxx_33_base);
-       else
-               pci_set_drvdata(dev, (void *) aec6xxx_34_base);
-
        /* These are necessary to get AEC6280 Macintosh cards to work */
        if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
            (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) {
@@ -187,8 +182,8 @@ static const struct ide_port_ops atp86x_port_ops = {
 };
 
 static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
-       {       /* 0 */
-               .name           = "AEC6210",
+       {       /* 0: AEC6210 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_aec62xx,
                .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
                .port_ops       = &atp850_port_ops,
@@ -199,8 +194,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA2,
-       },{     /* 1 */
-               .name           = "AEC6260",
+       },
+       {       /* 1: AEC6260 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_aec62xx,
                .port_ops       = &atp86x_port_ops,
                .host_flags     = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
@@ -208,8 +204,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA4,
-       },{     /* 2 */
-               .name           = "AEC6260R",
+       },
+       {       /* 2: AEC6260R */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_aec62xx,
                .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
                .port_ops       = &atp86x_port_ops,
@@ -218,8 +215,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA4,
-       },{     /* 3 */
-               .name           = "AEC6280",
+       },
+       {       /* 3: AEC6280 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_aec62xx,
                .port_ops       = &atp86x_port_ops,
                .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
@@ -227,8 +225,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
-       },{     /* 4 */
-               .name           = "AEC6280R",
+       },
+       {       /* 4: AEC6280R */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_aec62xx,
                .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
                .port_ops       = &atp86x_port_ops,
@@ -254,10 +253,17 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
 
 static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
+       const struct chipset_bus_clock_list_entry *bus_clock;
        struct ide_port_info d;
        u8 idx = id->driver_data;
+       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
        int err;
 
+       if (bus_speed <= 33)
+               bus_clock = aec6xxx_33_base;
+       else
+               bus_clock = aec6xxx_34_base;
+
        err = pci_enable_device(dev);
        if (err)
                return err;
@@ -268,18 +274,25 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi
                unsigned long dma_base = pci_resource_start(dev, 4);
 
                if (inb(dma_base + 2) & 0x10) {
-                       d.name = (idx == 4) ? "AEC6880R" : "AEC6880";
+                       printk(KERN_INFO DRV_NAME " %s: AEC6880%s card detected"
+                               "\n", pci_name(dev), (idx == 4) ? "R" : "");
                        d.udma_mask = ATA_UDMA6;
                }
        }
 
-       err = ide_setup_pci_device(dev, &d);
+       err = ide_pci_init_one(dev, &d, (void *)bus_clock);
        if (err)
                pci_disable_device(dev);
 
        return err;
 }
 
+static void __devexit aec62xx_remove(struct pci_dev *dev)
+{
+       ide_pci_remove(dev);
+       pci_disable_device(dev);
+}
+
 static const struct pci_device_id aec62xx_pci_tbl[] = {
        { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 },
        { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860),   1 },
@@ -294,6 +307,7 @@ static struct pci_driver driver = {
        .name           = "AEC62xx_IDE",
        .id_table       = aec62xx_pci_tbl,
        .probe          = aec62xx_init_one,
+       .remove         = aec62xx_remove,
 };
 
 static int __init aec62xx_ide_init(void)
@@ -301,7 +315,13 @@ static int __init aec62xx_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit aec62xx_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(aec62xx_ide_init);
+module_exit(aec62xx_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for ARTOP AEC62xx IDE");
index 5ef7817ac64f852e5042f45a281ea243bcf4a802..b582687e0cd472a2b33a9ce825bc5b251ab4917b 100644 (file)
@@ -38,6 +38,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "alim15x3"
+
 /*
  * Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking
  * (this is DANGEROUS and could result in data corruption).
@@ -207,13 +209,12 @@ static int ali15x3_dma_setup(ide_drive_t *drive)
 /**
  *     init_chipset_ali15x3    -       Initialise an ALi IDE controller
  *     @dev: PCI device
- *     @name: Name of the controller
  *
  *     This function initializes the ALI IDE controller and where 
  *     appropriate also sets up the 1533 southbridge.
  */
-  
-static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const char *name)
+
+static unsigned int __devinit init_chipset_ali15x3(struct pci_dev *dev)
 {
        unsigned long flags;
        u8 tmpbyte;
@@ -515,7 +516,7 @@ static const struct ide_dma_ops ali_dma_ops = {
 };
 
 static const struct ide_port_info ali15x3_chipset __devinitdata = {
-       .name           = "ALI15X3",
+       .name           = DRV_NAME,
        .init_chipset   = init_chipset_ali15x3,
        .init_hwif      = init_hwif_ali15x3,
        .init_dma       = init_dma_ali15x3,
@@ -565,7 +566,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
        if (idx == 0)
                d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
 
-       return ide_setup_pci_device(dev, &d);
+       return ide_pci_init_one(dev, &d, NULL);
 }
 
 
@@ -580,6 +581,7 @@ static struct pci_driver driver = {
        .name           = "ALI15x3_IDE",
        .id_table       = alim15x3_pci_tbl,
        .probe          = alim15x3_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init ali15x3_ide_init(void)
@@ -587,7 +589,13 @@ static int __init ali15x3_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit ali15x3_ide_exit(void)
+{
+       return pci_unregister_driver(&driver);
+}
+
 module_init(ali15x3_ide_init);
+module_exit(ali15x3_ide_exit);
 
 MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
 MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");
index ef7d971031eee6bad1aef03c49aedec4e6369c78..2cea7bf51a0fe94412a581028ef4f63dea76af14 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/init.h>
 #include <linux/ide.h>
 
+#define DRV_NAME "amd74xx"
+
 enum {
        AMD_IDE_CONFIG          = 0x41,
        AMD_CABLE_DETECT        = 0x42,
@@ -110,15 +112,13 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
        amd_set_drive(drive, XFER_PIO_0 + pio);
 }
 
-static void __devinit amd7409_cable_detect(struct pci_dev *dev,
-                                          const char *name)
+static void __devinit amd7409_cable_detect(struct pci_dev *dev)
 {
        /* no host side cable detection */
        amd_80w = 0x03;
 }
 
-static void __devinit amd7411_cable_detect(struct pci_dev *dev,
-                                          const char *name)
+static void __devinit amd7411_cable_detect(struct pci_dev *dev)
 {
        int i;
        u32 u = 0;
@@ -129,9 +129,9 @@ static void __devinit amd7411_cable_detect(struct pci_dev *dev,
        amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
        for (i = 24; i >= 0; i -= 8)
                if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
-                       printk(KERN_WARNING "%s: BIOS didn't set cable bits "
-                                           "correctly. Enabling workaround.\n",
-                                           name);
+                       printk(KERN_WARNING DRV_NAME " %s: BIOS didn't set "
+                               "cable bits correctly. Enabling workaround.\n",
+                               pci_name(dev));
                        amd_80w |= (1 << (1 - (i >> 4)));
                }
 }
@@ -140,8 +140,7 @@ static void __devinit amd7411_cable_detect(struct pci_dev *dev,
  * The initialization callback.  Initialize drive independent registers.
  */
 
-static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
-                                                  const char *name)
+static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev)
 {
        u8 t = 0, offset = amd_offset(dev);
 
@@ -154,9 +153,9 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
                ; /* no UDMA > 2 */
        else if (dev->vendor == PCI_VENDOR_ID_AMD &&
                 dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
-               amd7409_cable_detect(dev, name);
+               amd7409_cable_detect(dev);
        else
-               amd7411_cable_detect(dev, name);
+               amd7411_cable_detect(dev);
 
 /*
  * Take care of prefetch & postwrite.
@@ -173,24 +172,6 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
                t |= 0xf0;
        pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
 
-/*
- * Determine the system bus clock.
- */
-
-       amd_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
-
-       switch (amd_clock) {
-               case 33000: amd_clock = 33333; break;
-               case 37000: amd_clock = 37500; break;
-               case 41000: amd_clock = 41666; break;
-       }
-
-       if (amd_clock < 20000 || amd_clock > 50000) {
-               printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
-                                   name, amd_clock);
-               amd_clock = 33333;
-       }
-
        return dev->irq;
 }
 
@@ -222,9 +203,9 @@ static const struct ide_port_ops amd_port_ops = {
         IDE_HFLAG_IO_32BIT | \
         IDE_HFLAG_UNMASK_IRQS)
 
-#define DECLARE_AMD_DEV(name_str, swdma, udma)                         \
+#define DECLARE_AMD_DEV(swdma, udma)                           \
        {                                                               \
-               .name           = name_str,                             \
+               .name           = DRV_NAME,                             \
                .init_chipset   = init_chipset_amd74xx,                 \
                .init_hwif      = init_hwif_amd74xx,                    \
                .enablebits     = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
@@ -236,9 +217,9 @@ static const struct ide_port_ops amd_port_ops = {
                .udma_mask      = udma,                                 \
        }
 
-#define DECLARE_NV_DEV(name_str, udma)                                 \
+#define DECLARE_NV_DEV(udma)                                   \
        {                                                               \
-               .name           = name_str,                             \
+               .name           = DRV_NAME,                             \
                .init_chipset   = init_chipset_amd74xx,                 \
                .init_hwif      = init_hwif_amd74xx,                    \
                .enablebits     = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
@@ -251,31 +232,15 @@ static const struct ide_port_ops amd_port_ops = {
        }
 
 static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
-       /*  0 */ DECLARE_AMD_DEV("AMD7401",       0x00, ATA_UDMA2),
-       /*  1 */ DECLARE_AMD_DEV("AMD7409", ATA_SWDMA2, ATA_UDMA4),
-       /*  2 */ DECLARE_AMD_DEV("AMD7411", ATA_SWDMA2, ATA_UDMA5),
-       /*  3 */ DECLARE_AMD_DEV("AMD7441", ATA_SWDMA2, ATA_UDMA5),
-       /*  4 */ DECLARE_AMD_DEV("AMD8111", ATA_SWDMA2, ATA_UDMA6),
-
-       /*  5 */ DECLARE_NV_DEV("NFORCE",               ATA_UDMA5),
-       /*  6 */ DECLARE_NV_DEV("NFORCE2",              ATA_UDMA6),
-       /*  7 */ DECLARE_NV_DEV("NFORCE2-U400R",        ATA_UDMA6),
-       /*  8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA",   ATA_UDMA6),
-       /*  9 */ DECLARE_NV_DEV("NFORCE3-150",          ATA_UDMA6),
-       /* 10 */ DECLARE_NV_DEV("NFORCE3-250",          ATA_UDMA6),
-       /* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA",     ATA_UDMA6),
-       /* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2",    ATA_UDMA6),
-       /* 13 */ DECLARE_NV_DEV("NFORCE-CK804",         ATA_UDMA6),
-       /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04",         ATA_UDMA6),
-       /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51",         ATA_UDMA6),
-       /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55",         ATA_UDMA6),
-       /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61",         ATA_UDMA6),
-       /* 18 */ DECLARE_NV_DEV("NFORCE-MCP65",         ATA_UDMA6),
-       /* 19 */ DECLARE_NV_DEV("NFORCE-MCP67",         ATA_UDMA6),
-       /* 20 */ DECLARE_NV_DEV("NFORCE-MCP73",         ATA_UDMA6),
-       /* 21 */ DECLARE_NV_DEV("NFORCE-MCP77",         ATA_UDMA6),
-
-       /* 22 */ DECLARE_AMD_DEV("AMD5536", ATA_SWDMA2, ATA_UDMA5),
+       /* 0: AMD7401 */        DECLARE_AMD_DEV(0x00, ATA_UDMA2),
+       /* 1: AMD7409 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4),
+       /* 2: AMD7411/7441 */   DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
+       /* 3: AMD8111 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA6),
+
+       /* 4: NFORCE */         DECLARE_NV_DEV(ATA_UDMA5),
+       /* 5: >= NFORCE2 */     DECLARE_NV_DEV(ATA_UDMA6),
+
+       /* 6: AMD5536 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
 };
 
 static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -292,47 +257,64 @@ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_
                if (dev->revision <= 7)
                        d.swdma_mask = 0;
                d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
-       } else if (idx == 4) {
+       } else if (idx == 3) {
                if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
                    dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
                        d.udma_mask = ATA_UDMA5;
        }
 
-       printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
-                        d.name, pci_name(dev), dev->revision,
-                        amd_dma[fls(d.udma_mask) - 1]);
+       printk(KERN_INFO "%s %s: UDMA%s controller\n",
+               d.name, pci_name(dev), amd_dma[fls(d.udma_mask) - 1]);
+
+       /*
+       * Determine the system bus clock.
+       */
+       amd_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
+
+       switch (amd_clock) {
+       case 33000: amd_clock = 33333; break;
+       case 37000: amd_clock = 37500; break;
+       case 41000: amd_clock = 41666; break;
+       }
+
+       if (amd_clock < 20000 || amd_clock > 50000) {
+               printk(KERN_WARNING "%s: User given PCI clock speed impossible"
+                                   " (%d), using 33 MHz instead.\n",
+                                   d.name, amd_clock);
+               amd_clock = 33333;
+       }
 
-       return ide_setup_pci_device(dev, &d);
+       return ide_pci_init_one(dev, &d, NULL);
 }
 
 static const struct pci_device_id amd74xx_pci_tbl[] = {
        { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_COBRA_7401),           0 },
        { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_VIPER_7409),           1 },
        { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_VIPER_7411),           2 },
-       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_OPUS_7441),            3 },
-       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_8111_IDE),             4 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_IDE),        5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE),       6 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE),      7 },
+       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_OPUS_7441),            2 },
+       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_8111_IDE),             3 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_IDE),        4 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE),       5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE),      5 },
 #ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA),     8 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA),     5 },
 #endif
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE),       9 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE),     10 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE),       5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE),      5 },
 #ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA),    11 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2),   12 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA),     5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2),    5 },
 #endif
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE), 13 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE), 14 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE), 15 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE), 16 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 17 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 18 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 19 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 20 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 21 },
-       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_CS5536_IDE),          22 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE),  5 },
+       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_CS5536_IDE),           6 },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
@@ -341,6 +323,7 @@ static struct pci_driver driver = {
        .name           = "AMD_IDE",
        .id_table       = amd74xx_pci_tbl,
        .probe          = amd74xx_probe,
+       .remove         = ide_pci_remove,
 };
 
 static int __init amd74xx_ide_init(void)
@@ -348,7 +331,13 @@ static int __init amd74xx_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit amd74xx_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(amd74xx_ide_init);
+module_exit(amd74xx_ide_exit);
 
 MODULE_AUTHOR("Vojtech Pavlik");
 MODULE_DESCRIPTION("AMD PCI IDE driver");
index 8b637181681ad2d6d4cfcbf30c39d6e6044b9bc6..332f08f43b56f4933bab37b8bf44fb787ac705e6 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
+#define DRV_NAME "atiixp"
+
 #define ATIIXP_IDE_PIO_TIMING          0x40
 #define ATIIXP_IDE_MDMA_TIMING         0x44
 #define ATIIXP_IDE_PIO_CONTROL         0x48
@@ -137,16 +139,17 @@ static const struct ide_port_ops atiixp_port_ops = {
 };
 
 static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
-       {       /* 0 */
-               .name           = "ATIIXP",
+       {       /* 0: IXP200/300/400/700 */
+               .name           = DRV_NAME,
                .enablebits     = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
                .port_ops       = &atiixp_port_ops,
                .host_flags     = IDE_HFLAG_LEGACY_IRQS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
-       },{     /* 1 */
-               .name           = "SB600_PATA",
+       },
+       {       /* 1: IXP600 */
+               .name           = DRV_NAME,
                .enablebits     = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
                .port_ops       = &atiixp_port_ops,
                .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
@@ -167,7 +170,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
 
 static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &atiixp_pci_info[id->driver_data]);
+       return ide_pci_init_one(dev, &atiixp_pci_info[id->driver_data], NULL);
 }
 
 static const struct pci_device_id atiixp_pci_tbl[] = {
@@ -184,6 +187,7 @@ static struct pci_driver driver = {
        .name           = "ATIIXP_IDE",
        .id_table       = atiixp_pci_tbl,
        .probe          = atiixp_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init atiixp_ide_init(void)
@@ -191,7 +195,13 @@ static int __init atiixp_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit atiixp_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(atiixp_ide_init);
+module_exit(atiixp_ide_exit);
 
 MODULE_AUTHOR("HUI YU");
 MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
index ce58bfcdb3c6c645c51b70321d799dfa0157524b..1360b4fa9fd36048d4c2da94318e3f9655dcad5a 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "cmd64x"
+
 #define CMD_DEBUG 0
 
 #if CMD_DEBUG
@@ -330,28 +332,10 @@ static int cmd646_1_dma_end(ide_drive_t *drive)
        return (dma_stat & 7) != 4;
 }
 
-static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev)
 {
        u8 mrdmode = 0;
 
-       if (dev->device == PCI_DEVICE_ID_CMD_646) {
-
-               switch (dev->revision) {
-               case 0x07:
-               case 0x05:
-                       printk("%s: UltraDMA capable\n", name);
-                       break;
-               case 0x03:
-               default:
-                       printk("%s: MultiWord DMA force limited\n", name);
-                       break;
-               case 0x01:
-                       printk("%s: MultiWord DMA limited, "
-                              "IRQ workaround enabled\n", name);
-                       break;
-               }
-       }
-
        /* Set a good latency timer and cache line size value. */
        (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
        /* FIXME: pci_set_master() to ensure a good latency timer value */
@@ -425,8 +409,8 @@ static const struct ide_dma_ops cmd648_dma_ops = {
 };
 
 static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
-       {       /* 0 */
-               .name           = "CMD643",
+       {       /* 0: CMD643 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_cmd64x,
                .enablebits     = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
                .port_ops       = &cmd64x_port_ops,
@@ -436,8 +420,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = 0x00, /* no udma */
-       },{     /* 1 */
-               .name           = "CMD646",
+       },
+       {       /* 1: CMD646 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
                .chipset        = ide_cmd646,
@@ -447,8 +432,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA2,
-       },{     /* 2 */
-               .name           = "CMD648",
+       },
+       {       /* 2: CMD648 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
                .port_ops       = &cmd64x_port_ops,
@@ -457,8 +443,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA4,
-       },{     /* 3 */
-               .name           = "CMD649",
+       },
+       {       /* 3: CMD649 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
                .port_ops       = &cmd64x_port_ops,
@@ -507,7 +494,7 @@ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_devic
                }
        }
 
-       return ide_setup_pci_device(dev, &d);
+       return ide_pci_init_one(dev, &d, NULL);
 }
 
 static const struct pci_device_id cmd64x_pci_tbl[] = {
@@ -523,6 +510,7 @@ static struct pci_driver driver = {
        .name           = "CMD64x_IDE",
        .id_table       = cmd64x_pci_tbl,
        .probe          = cmd64x_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init cmd64x_ide_init(void)
@@ -530,7 +518,13 @@ static int __init cmd64x_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit cmd64x_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(cmd64x_ide_init);
+module_exit(cmd64x_ide_exit);
 
 MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
index b03d8ae947e6fc10c6682d8944cae1dea4f5f4f9..c0364b287f1765124eb7b8b2ce5cfc191ec69e74 100644 (file)
@@ -41,6 +41,8 @@
 #include <linux/ide.h>
 #include <linux/dma-mapping.h>
 
+#define DRV_NAME "cs5520"
+
 struct pio_clocks
 {
        int address;
@@ -92,18 +94,11 @@ static const struct ide_port_ops cs5520_port_ops = {
        .set_dma_mode           = cs5520_set_dma_mode,
 };
 
-#define DECLARE_CS_DEV(name_str)                               \
-       {                                                       \
-               .name           = name_str,                     \
-               .port_ops       = &cs5520_port_ops,             \
-               .host_flags     = IDE_HFLAG_ISA_PORTS |         \
-                                 IDE_HFLAG_CS5520,             \
-               .pio_mask       = ATA_PIO4,                     \
-       }
-
-static const struct ide_port_info cyrix_chipsets[] __devinitdata = {
-       /* 0 */ DECLARE_CS_DEV("Cyrix 5510"),
-       /* 1 */ DECLARE_CS_DEV("Cyrix 5520")
+static const struct ide_port_info cyrix_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .port_ops       = &cs5520_port_ops,
+       .host_flags     = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_CS5520,
+       .pio_mask       = ATA_PIO4,
 };
 
 /*
@@ -114,7 +109,7 @@ static const struct ide_port_info cyrix_chipsets[] __devinitdata = {
  
 static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       const struct ide_port_info *d = &cyrix_chipsets[id->driver_data];
+       const struct ide_port_info *d = &cyrix_chipset;
        hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
 
        ide_setup_pci_noise(dev, d);
@@ -128,7 +123,8 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
        }
        pci_set_master(dev);
        if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
-               printk(KERN_WARNING "cs5520: No suitable DMA available.\n");
+               printk(KERN_WARNING "%s: No suitable DMA available.\n",
+                       d->name);
                return -ENODEV;
        }
 
index f5534c1ff349841b10ace33856a5b587b2e19860..f235db8c678b5faa326b293899f98f9cb3899a71 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "cs5530"
+
 /*
  * Here are the standard PIO mode 0-4 timings for each "format".
  * Format-0 uses fast data reg timings, with slower command reg timings.
@@ -127,12 +129,11 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
 /**
  *     init_chipset_5530       -       set up 5530 bridge
  *     @dev: PCI device
- *     @name: device name
  *
  *     Initialize the cs5530 bridge for reliable IDE DMA operation.
  */
 
-static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_cs5530(struct pci_dev *dev)
 {
        struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
 
@@ -151,11 +152,11 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch
                }
        }
        if (!master_0) {
-               printk(KERN_ERR "%s: unable to locate PCI MASTER function\n", name);
+               printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n");
                goto out;
        }
        if (!cs5530_0) {
-               printk(KERN_ERR "%s: unable to locate CS5530 LEGACY function\n", name);
+               printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n");
                goto out;
        }
 
@@ -243,7 +244,7 @@ static const struct ide_port_ops cs5530_port_ops = {
 };
 
 static const struct ide_port_info cs5530_chipset __devinitdata = {
-       .name           = "CS5530",
+       .name           = DRV_NAME,
        .init_chipset   = init_chipset_cs5530,
        .init_hwif      = init_hwif_cs5530,
        .port_ops       = &cs5530_port_ops,
@@ -256,7 +257,7 @@ static const struct ide_port_info cs5530_chipset __devinitdata = {
 
 static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &cs5530_chipset);
+       return ide_pci_init_one(dev, &cs5530_chipset, NULL);
 }
 
 static const struct pci_device_id cs5530_pci_tbl[] = {
@@ -269,6 +270,7 @@ static struct pci_driver driver = {
        .name           = "CS5530 IDE",
        .id_table       = cs5530_pci_tbl,
        .probe          = cs5530_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init cs5530_ide_init(void)
@@ -276,7 +278,13 @@ static int __init cs5530_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit cs5530_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(cs5530_ide_init);
+module_exit(cs5530_ide_exit);
 
 MODULE_AUTHOR("Mark Lord");
 MODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE");
index 5404fe4f701d79cc4bc651c99548ce35da9d4c67..f7b50cdeefa68861b261bf2bd6c9222ba13cac5b 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/pci.h>
 #include <linux/ide.h>
 
+#define DRV_NAME "cs5535"
+
 #define MSR_ATAC_BASE          0x51300000
 #define ATAC_GLD_MSR_CAP       (MSR_ATAC_BASE+0)
 #define ATAC_GLD_MSR_CONFIG    (MSR_ATAC_BASE+0x01)
@@ -169,7 +171,7 @@ static const struct ide_port_ops cs5535_port_ops = {
 };
 
 static const struct ide_port_info cs5535_chipset __devinitdata = {
-       .name           = "CS5535",
+       .name           = DRV_NAME,
        .port_ops       = &cs5535_port_ops,
        .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
        .pio_mask       = ATA_PIO4,
@@ -180,7 +182,7 @@ static const struct ide_port_info cs5535_chipset __devinitdata = {
 static int __devinit cs5535_init_one(struct pci_dev *dev,
                                        const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &cs5535_chipset);
+       return ide_pci_init_one(dev, &cs5535_chipset, NULL);
 }
 
 static const struct pci_device_id cs5535_pci_tbl[] = {
@@ -194,6 +196,7 @@ static struct pci_driver driver = {
        .name       = "CS5535_IDE",
        .id_table   = cs5535_pci_tbl,
        .probe      = cs5535_init_one,
+       .remove     = ide_pci_remove,
 };
 
 static int __init cs5535_ide_init(void)
@@ -201,7 +204,13 @@ static int __init cs5535_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit cs5535_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(cs5535_ide_init);
+module_exit(cs5535_ide_exit);
 
 MODULE_AUTHOR("AMD");
 MODULE_DESCRIPTION("PCI driver module for AMD/NS CS5535 IDE");
index e14ad5530fa4b0c1e1369387d43e4e73d8ac8b7b..bfae2f882f48d48ec75ab4fb304ac5aa4321892c 100644 (file)
@@ -48,6 +48,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "cy82c693"
+
 /* the current version */
 #define CY82_VERSION   "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)"
 
@@ -330,7 +332,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
 /*
  * this function is called during init and is used to setup the cy82c693 chip
  */
-static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev)
 {
        if (PCI_FUNC(dev->devfn) != 1)
                return 0;
@@ -349,8 +351,8 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
        data = inb(CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO
-       printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n",
-               name, data);
+       printk(KERN_INFO DRV_NAME ": Peripheral Configuration Register: 0x%X\n",
+               data);
 #endif /* CY82C693_DEBUG_INFO */
 
        /*
@@ -371,8 +373,8 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
        outb(data, CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO
-       printk(KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
-               name, data);
+       printk(KERN_INFO ": New Peripheral Configuration Register: 0x%X\n",
+               data);
 #endif /* CY82C693_DEBUG_INFO */
 
 #endif /* CY82C693_SETDMA_CLOCK */
@@ -398,7 +400,7 @@ static const struct ide_port_ops cy82c693_port_ops = {
 };
 
 static const struct ide_port_info cy82c693_chipset __devinitdata = {
-       .name           = "CY82C693",
+       .name           = DRV_NAME,
        .init_chipset   = init_chipset_cy82c693,
        .init_iops      = init_iops_cy82c693,
        .port_ops       = &cy82c693_port_ops,
@@ -419,12 +421,22 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
        if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
            PCI_FUNC(dev->devfn) == 1) {
                dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
-               ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
-               /* We leak pci refs here but thats ok - we can't be unloaded */
+               ret = ide_pci_init_two(dev, dev2, &cy82c693_chipset, NULL);
+               if (ret)
+                       pci_dev_put(dev2);
        }
        return ret;
 }
 
+static void __devexit cy82c693_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+       ide_pci_remove(dev);
+       pci_dev_put(dev2);
+}
+
 static const struct pci_device_id cy82c693_pci_tbl[] = {
        { PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 },
        { 0, },
@@ -435,6 +447,7 @@ static struct pci_driver driver = {
        .name           = "Cypress_IDE",
        .id_table       = cy82c693_pci_tbl,
        .probe          = cy82c693_init_one,
+       .remove         = cy82c693_remove,
 };
 
 static int __init cy82c693_ide_init(void)
@@ -442,7 +455,13 @@ static int __init cy82c693_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit cy82c693_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(cy82c693_ide_init);
+module_exit(cy82c693_ide_exit);
 
 MODULE_AUTHOR("Andreas Krebs, Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
index 041720e22762840aefbad8a151d5c0ed7e5159f1..b07d4f4273b33d2970ceb9f2d7ea0b40af7860b0 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
+#define DRV_NAME "ide_pci_generic"
+
 static int ide_generic_all;            /* Set to claim all devices */
 
 module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
@@ -34,9 +36,9 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
 
 #define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS)
 
-#define DECLARE_GENERIC_PCI_DEV(name_str, extra_flags) \
+#define DECLARE_GENERIC_PCI_DEV(extra_flags) \
        { \
-               .name           = name_str, \
+               .name           = DRV_NAME, \
                .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
                                  extra_flags, \
                .swdma_mask     = ATA_SWDMA2, \
@@ -45,10 +47,11 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
        }
 
 static const struct ide_port_info generic_chipsets[] __devinitdata = {
-       /*  0 */ DECLARE_GENERIC_PCI_DEV("Unknown",     0),
+       /*  0: Unknown */
+       DECLARE_GENERIC_PCI_DEV(0),
 
-       {       /* 1 */
-               .name           = "NS87410",
+       {       /* 1: NS87410 */
+               .name           = DRV_NAME,
                .enablebits     = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
                .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
                .swdma_mask     = ATA_SWDMA2,
@@ -56,17 +59,15 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
                .udma_mask      = ATA_UDMA6,
        },
 
-       /*  2 */ DECLARE_GENERIC_PCI_DEV("SAMURAI",     0),
-       /*  3 */ DECLARE_GENERIC_PCI_DEV("HT6565",      0),
-       /*  4 */ DECLARE_GENERIC_PCI_DEV("UM8673F",     IDE_HFLAGS_UMC),
-       /*  5 */ DECLARE_GENERIC_PCI_DEV("UM8886A",     IDE_HFLAGS_UMC),
-       /*  6 */ DECLARE_GENERIC_PCI_DEV("UM8886BF",    IDE_HFLAGS_UMC),
-       /*  7 */ DECLARE_GENERIC_PCI_DEV("HINT_IDE",    0),
-       /*  8 */ DECLARE_GENERIC_PCI_DEV("VIA_IDE",     IDE_HFLAG_NO_AUTODMA),
-       /*  9 */ DECLARE_GENERIC_PCI_DEV("OPTI621V",    IDE_HFLAG_NO_AUTODMA),
-
-       {       /* 10 */
-               .name           = "VIA8237SATA",
+       /*  2: SAMURAI / HT6565 / HINT_IDE */
+       DECLARE_GENERIC_PCI_DEV(0),
+       /*  3: UM8673F / UM8886A / UM8886BF */
+       DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC),
+       /*  4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */
+       DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA),
+
+       {       /* 5: VIA8237SATA */
+               .name           = DRV_NAME,
                .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
                                  IDE_HFLAG_OFF_BOARD,
                .swdma_mask     = ATA_SWDMA2,
@@ -74,12 +75,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
                .udma_mask      = ATA_UDMA6,
        },
 
-       /* 11 */ DECLARE_GENERIC_PCI_DEV("Piccolo0102", IDE_HFLAG_NO_AUTODMA),
-       /* 12 */ DECLARE_GENERIC_PCI_DEV("Piccolo0103", IDE_HFLAG_NO_AUTODMA),
-       /* 13 */ DECLARE_GENERIC_PCI_DEV("Piccolo0105", IDE_HFLAG_NO_AUTODMA),
-
-       {       /* 14 */
-               .name           = "Revolution",
+       {       /* 6: Revolution */
+               .name           = DRV_NAME,
                .host_flags     = IDE_HFLAG_CLEAR_SIMPLEX |
                                  IDE_HFLAG_TRUST_BIOS_FOR_DMA |
                                  IDE_HFLAG_OFF_BOARD,
@@ -134,12 +131,12 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi
                u16 command;
                pci_read_config_word(dev, PCI_COMMAND, &command);
                if (!(command & PCI_COMMAND_IO)) {
-                       printk(KERN_INFO "Skipping disabled %s IDE "
-                                       "controller.\n", d->name);
+                       printk(KERN_INFO "%s %s: skipping disabled "
+                               "controller\n", d->name, pci_name(dev));
                        goto out;
                }
        }
-       ret = ide_setup_pci_device(dev, d);
+       ret = ide_pci_init_one(dev, d, NULL);
 out:
        return ret;
 }
@@ -147,20 +144,20 @@ out:
 static const struct pci_device_id generic_pci_tbl[] = {
        { PCI_VDEVICE(NS,       PCI_DEVICE_ID_NS_87410),                 1 },
        { PCI_VDEVICE(PCTECH,   PCI_DEVICE_ID_PCTECH_SAMURAI_IDE),       2 },
-       { PCI_VDEVICE(HOLTEK,   PCI_DEVICE_ID_HOLTEK_6565),              3 },
-       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8673F),              4 },
-       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8886A),              5 },
-       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8886BF),             6 },
-       { PCI_VDEVICE(HINT,     PCI_DEVICE_ID_HINT_VXPROII_IDE),         7 },
-       { PCI_VDEVICE(VIA,      PCI_DEVICE_ID_VIA_82C561),               8 },
-       { PCI_VDEVICE(OPTI,     PCI_DEVICE_ID_OPTI_82C558),              9 },
+       { PCI_VDEVICE(HOLTEK,   PCI_DEVICE_ID_HOLTEK_6565),              2 },
+       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8673F),              3 },
+       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8886A),              3 },
+       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8886BF),             3 },
+       { PCI_VDEVICE(HINT,     PCI_DEVICE_ID_HINT_VXPROII_IDE),         2 },
+       { PCI_VDEVICE(VIA,      PCI_DEVICE_ID_VIA_82C561),               4 },
+       { PCI_VDEVICE(OPTI,     PCI_DEVICE_ID_OPTI_82C558),              4 },
 #ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VDEVICE(VIA,      PCI_DEVICE_ID_VIA_8237_SATA),           10 },
+       { PCI_VDEVICE(VIA,      PCI_DEVICE_ID_VIA_8237_SATA),            5 },
 #endif
-       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO),         11 },
-       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO_1),       12 },
-       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),       13 },
-       { PCI_VDEVICE(NETCELL,  PCI_DEVICE_ID_REVOLUTION),              14 },
+       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO),          4 },
+       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO_1),        4 },
+       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),        4 },
+       { PCI_VDEVICE(NETCELL,  PCI_DEVICE_ID_REVOLUTION),               6 },
        /*
         * Must come last.  If you add entries adjust
         * this table and generic_chipsets[] appropriately.
@@ -174,6 +171,7 @@ static struct pci_driver driver = {
        .name           = "PCI_IDE",
        .id_table       = generic_pci_tbl,
        .probe          = generic_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init generic_ide_init(void)
@@ -181,7 +179,13 @@ static int __init generic_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit generic_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(generic_ide_init);
+module_exit(generic_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for generic PCI IDE");
index 9e1d1c4741da5567509c28a671ea9e82aa410139..6009b0b9655dda42c4ad08e40011a898fc89daee 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/init.h>
 #include <linux/ide.h>
 
+#define DRV_NAME "hpt34x"
+
 #define HPT343_DEBUG_DRIVE_INFO                0
 
 static void hpt34x_set_mode(ide_drive_t *drive, const u8 speed)
@@ -77,7 +79,7 @@ static void hpt34x_set_pio_mode(ide_drive_t *drive, const u8 pio)
  */
 #define        HPT34X_PCI_INIT_REG             0x80
 
-static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev)
 {
        int i = 0;
        unsigned long hpt34xIoBase = pci_resource_start(dev, 4);
@@ -126,15 +128,15 @@ static const struct ide_port_ops hpt34x_port_ops = {
         IDE_HFLAG_NO_AUTODMA)
 
 static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
-       { /* 0 */
-               .name           = "HPT343",
+       { /* 0: HPT343 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_hpt34x,
                .port_ops       = &hpt34x_port_ops,
                .host_flags     = IDE_HFLAGS_HPT34X | IDE_HFLAG_NON_BOOTABLE,
                .pio_mask       = ATA_PIO5,
        },
-       { /* 1 */
-               .name           = "HPT345",
+       { /* 1: HPT345 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_hpt34x,
                .port_ops       = &hpt34x_port_ops,
                .host_flags     = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
@@ -156,7 +158,7 @@ static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_devic
 
        d = &hpt34x_chipsets[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0];
 
-       return ide_setup_pci_device(dev, d);
+       return ide_pci_init_one(dev, d, NULL);
 }
 
 static const struct pci_device_id hpt34x_pci_tbl[] = {
@@ -169,6 +171,7 @@ static struct pci_driver driver = {
        .name           = "HPT34x_IDE",
        .id_table       = hpt34x_pci_tbl,
        .probe          = hpt34x_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init hpt34x_ide_init(void)
@@ -176,7 +179,13 @@ static int __init hpt34x_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit hpt34x_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(hpt34x_ide_init);
+module_exit(hpt34x_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for Highpoint 34x IDE");
index 1f1135ce7cd6616f9626c062013168e6d5b3af9c..5271b246b88c92d99ad13f83724f0d9b07657fdc 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
+#define DRV_NAME "hpt366"
+
 /* various tuning parameters */
 #define HPT_RESET_STATE_ENGINE
 #undef HPT_DELAY_INTERRUPT
@@ -620,7 +622,8 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       struct hpt_info *info   = pci_get_drvdata(dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct hpt_info *info   = host->host_priv + (hwif->dev == host->dev[1]);
        u8 mask                 = hwif->ultra_mask;
 
        switch (info->chip_type) {
@@ -660,7 +663,8 @@ static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       struct hpt_info *info   = pci_get_drvdata(dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct hpt_info *info   = host->host_priv + (hwif->dev == host->dev[1]);
 
        switch (info->chip_type) {
        case HPT372 :
@@ -694,8 +698,10 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info)
 
 static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
 {
-       struct pci_dev  *dev    = to_pci_dev(drive->hwif->dev);
-       struct hpt_info *info   = pci_get_drvdata(dev);
+       ide_hwif_t *hwif        = drive->hwif;
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct hpt_info *info   = host->host_priv + (hwif->dev == host->dev[1]);
        struct hpt_timings *t   = info->timings;
        u8  itr_addr            = 0x40 + (drive->dn * 4);
        u32 old_itr             = 0;
@@ -738,7 +744,8 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev  *dev    = to_pci_dev(hwif->dev);
-       struct hpt_info *info   = pci_get_drvdata(dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct hpt_info *info   = host->host_priv + (hwif->dev == host->dev[1]);
 
        if (drive->quirk_list) {
                if (info->chip_type >= HPT370) {
@@ -963,24 +970,16 @@ static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f
        return 1;
 }
 
-static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev)
 {
-       struct hpt_info *info   = kmalloc(sizeof(struct hpt_info), GFP_KERNEL);
        unsigned long io_base   = pci_resource_start(dev, 4);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct hpt_info *info   = host->host_priv + (&dev->dev == host->dev[1]);
+       const char *name        = DRV_NAME;
        u8 pci_clk,  dpll_clk   = 0;    /* PCI and DPLL clock in MHz */
        u8 chip_type;
        enum ata_clock  clock;
 
-       if (info == NULL) {
-               printk(KERN_ERR "%s: out of memory!\n", name);
-               return -ENOMEM;
-       }
-
-       /*
-        * Copy everything from a static "template" structure
-        * to just allocated per-chip hpt_info structure.
-        */
-       memcpy(info, pci_get_drvdata(dev), sizeof(struct hpt_info));
        chip_type = info->chip_type;
 
        pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
@@ -1048,8 +1047,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
                if ((temp & 0xFFFFF000) != 0xABCDE000) {
                        int i;
 
-                       printk(KERN_WARNING "%s: no clock data saved by BIOS\n",
-                              name);
+                       printk(KERN_WARNING "%s %s: no clock data saved by "
+                               "BIOS\n", name, pci_name(dev));
 
                        /* Calculate the average value of f_CNT. */
                        for (temp = i = 0; i < 128; i++) {
@@ -1074,8 +1073,9 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
                else
                        pci_clk = 66;
 
-               printk(KERN_INFO "%s: DPLL base: %d MHz, f_CNT: %d, "
-                      "assuming %d MHz PCI\n", name, dpll_clk, f_cnt, pci_clk);
+               printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, "
+                       "assuming %d MHz PCI\n", name, pci_name(dev),
+                       dpll_clk, f_cnt, pci_clk);
        } else {
                u32 itr1 = 0;
 
@@ -1141,8 +1141,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
                }
 
                if (info->timings->clock_table[clock] == NULL) {
-                       printk(KERN_ERR "%s: unknown bus timing!\n", name);
-                       kfree(info);
+                       printk(KERN_ERR "%s %s: unknown bus timing!\n",
+                               name, pci_name(dev));
                        return -EIO;
                }
 
@@ -1168,17 +1168,19 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
                                f_low += adjust >> 1;
                }
                if (adjust == 8) {
-                       printk(KERN_ERR "%s: DPLL did not stabilize!\n", name);
-                       kfree(info);
+                       printk(KERN_ERR "%s %s: DPLL did not stabilize!\n",
+                               name, pci_name(dev));
                        return -EIO;
                }
 
-               printk("%s: using %d MHz DPLL clock\n", name, dpll_clk);
+               printk(KERN_INFO "%s %s: using %d MHz DPLL clock\n",
+                       name, pci_name(dev), dpll_clk);
        } else {
                /* Mark the fact that we're not using the DPLL. */
                dpll_clk = 0;
 
-               printk("%s: using %d MHz PCI clock\n", name, pci_clk);
+               printk(KERN_INFO "%s %s: using %d MHz PCI clock\n",
+                       name, pci_name(dev), pci_clk);
        }
 
        /* Store the clock frequencies. */
@@ -1186,9 +1188,6 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
        info->pci_clk   = pci_clk;
        info->clock     = clock;
 
-       /* Point to this chip's own instance of the hpt_info structure. */
-       pci_set_drvdata(dev, info);
-
        if (chip_type >= HPT370) {
                u8  mcr1, mcr4;
 
@@ -1218,7 +1217,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
 static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev  *dev    = to_pci_dev(hwif->dev);
-       struct hpt_info *info   = pci_get_drvdata(dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct hpt_info *info   = host->host_priv + (hwif->dev == host->dev[1]);
        u8 chip_type            = info->chip_type;
        u8 scr1 = 0, ata66      = hwif->channel ? 0x01 : 0x02;
 
@@ -1262,7 +1262,8 @@ static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif)
 static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
 {
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       struct hpt_info *info   = pci_get_drvdata(dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct hpt_info *info   = host->host_priv + (hwif->dev == host->dev[1]);
        int serialize           = HPT_SERIALIZE_IO;
        u8  chip_type           = info->chip_type;
        u8  new_mcr, old_mcr    = 0;
@@ -1364,7 +1365,8 @@ static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
        if (dev2->irq != dev->irq) {
                /* FIXME: we need a core pci_set_interrupt() */
                dev2->irq = dev->irq;
-               printk(KERN_INFO "HPT374: PCI config space interrupt fixed\n");
+               printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt "
+                       "fixed\n", pci_name(dev2));
        }
 }
 
@@ -1399,8 +1401,8 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
        pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
 
        if (pin1 != pin2 && dev->irq == dev2->irq) {
-               printk(KERN_INFO "HPT36x: onboard version of chipset, "
-                                "pin1=%d pin2=%d\n", pin1, pin2);
+               printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, "
+                       "pin1=%d pin2=%d\n", pci_name(dev), pin1, pin2);
                return 1;
        }
 
@@ -1455,8 +1457,8 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
 };
 
 static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
-       {       /* 0 */
-               .name           = "HPT36x",
+       {       /* 0: HPT36x */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_hpt366,
                .init_hwif      = init_hwif_hpt366,
                .init_dma       = init_dma_hpt366,
@@ -1472,53 +1474,9 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
                .host_flags     = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
-       },{     /* 1 */
-               .name           = "HPT372A",
-               .init_chipset   = init_chipset_hpt366,
-               .init_hwif      = init_hwif_hpt366,
-               .init_dma       = init_dma_hpt366,
-               .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
-               .port_ops       = &hpt3xx_port_ops,
-               .dma_ops        = &hpt37x_dma_ops,
-               .host_flags     = IDE_HFLAGS_HPT3XX,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-       },{     /* 2 */
-               .name           = "HPT302",
-               .init_chipset   = init_chipset_hpt366,
-               .init_hwif      = init_hwif_hpt366,
-               .init_dma       = init_dma_hpt366,
-               .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
-               .port_ops       = &hpt3xx_port_ops,
-               .dma_ops        = &hpt37x_dma_ops,
-               .host_flags     = IDE_HFLAGS_HPT3XX,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-       },{     /* 3 */
-               .name           = "HPT371",
-               .init_chipset   = init_chipset_hpt366,
-               .init_hwif      = init_hwif_hpt366,
-               .init_dma       = init_dma_hpt366,
-               .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
-               .port_ops       = &hpt3xx_port_ops,
-               .dma_ops        = &hpt37x_dma_ops,
-               .host_flags     = IDE_HFLAGS_HPT3XX,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-       },{     /* 4 */
-               .name           = "HPT374",
-               .init_chipset   = init_chipset_hpt366,
-               .init_hwif      = init_hwif_hpt366,
-               .init_dma       = init_dma_hpt366,
-               .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
-               .udma_mask      = ATA_UDMA5,
-               .port_ops       = &hpt3xx_port_ops,
-               .dma_ops        = &hpt37x_dma_ops,
-               .host_flags     = IDE_HFLAGS_HPT3XX,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-       },{     /* 5 */
-               .name           = "HPT372N",
+       },
+       {       /* 1: HPT3xx */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_hpt366,
                .init_hwif      = init_hwif_hpt366,
                .init_dma       = init_dma_hpt366,
@@ -1542,10 +1500,12 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
 static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        const struct hpt_info *info = NULL;
+       struct hpt_info *dyn_info;
        struct pci_dev *dev2 = NULL;
        struct ide_port_info d;
        u8 idx = id->driver_data;
        u8 rev = dev->revision;
+       int ret;
 
        if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1))
                return -ENODEV;
@@ -1582,24 +1542,35 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
                break;
        }
 
-       d = hpt366_chipsets[idx];
+       printk(KERN_INFO DRV_NAME ": %s chipset detected\n", info->chip_name);
+
+       d = hpt366_chipsets[min_t(u8, idx, 1)];
 
-       d.name = info->chip_name;
        d.udma_mask = info->udma_mask;
 
        /* fixup ->dma_ops for HPT370/HPT370A */
        if (info == &hpt370 || info == &hpt370a)
                d.dma_ops = &hpt370_dma_ops;
 
-       pci_set_drvdata(dev, (void *)info);
-
        if (info == &hpt36x || info == &hpt374)
                dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
 
-       if (dev2) {
-               int ret;
+       dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL);
+       if (dyn_info == NULL) {
+               printk(KERN_ERR "%s %s: out of memory!\n",
+                       d.name, pci_name(dev));
+               pci_dev_put(dev2);
+               return -ENOMEM;
+       }
+
+       /*
+        * Copy everything from a static "template" structure
+        * to just allocated per-chip hpt_info structure.
+        */
+       memcpy(dyn_info, info, sizeof(*dyn_info));
 
-               pci_set_drvdata(dev2, (void *)info);
+       if (dev2) {
+               memcpy(dyn_info + 1, info, sizeof(*dyn_info));
 
                if (info == &hpt374)
                        hpt374_init(dev, dev2);
@@ -1608,13 +1579,30 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
                                d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
                }
 
-               ret = ide_setup_pci_devices(dev, dev2, &d);
-               if (ret < 0)
+               ret = ide_pci_init_two(dev, dev2, &d, dyn_info);
+               if (ret < 0) {
                        pci_dev_put(dev2);
+                       kfree(dyn_info);
+               }
                return ret;
        }
 
-       return ide_setup_pci_device(dev, &d);
+       ret = ide_pci_init_one(dev, &d, dyn_info);
+       if (ret < 0)
+               kfree(dyn_info);
+
+       return ret;
+}
+
+static void __devexit hpt366_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct ide_info *info = host->host_priv;
+       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+       ide_pci_remove(dev);
+       pci_dev_put(dev2);
+       kfree(info);
 }
 
 static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
@@ -1632,6 +1620,7 @@ static struct pci_driver driver = {
        .name           = "HPT366_IDE",
        .id_table       = hpt366_pci_tbl,
        .probe          = hpt366_init_one,
+       .remove         = hpt366_remove,
 };
 
 static int __init hpt366_ide_init(void)
@@ -1639,7 +1628,13 @@ static int __init hpt366_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit hpt366_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(hpt366_ide_init);
+module_exit(hpt366_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
index 2b71bdf74e73a2557c1f2c033bfb5306c684cbdc..6eba8f188264be200593779bb7128490a2d3d686 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
+#define DRV_NAME "it8213"
+
 /**
  *     it8213_set_pio_mode     -       set host controller for PIO mode
  *     @drive: drive
@@ -155,23 +157,17 @@ static const struct ide_port_ops it8213_port_ops = {
        .cable_detect           = it8213_cable_detect,
 };
 
-#define DECLARE_ITE_DEV(name_str)                      \
-       {                                               \
-               .name           = name_str,             \
-               .enablebits     = { {0x41, 0x80, 0x80} }, \
-               .port_ops       = &it8213_port_ops,     \
-               .host_flags     = IDE_HFLAG_SINGLE,     \
-               .pio_mask       = ATA_PIO4,             \
-               .swdma_mask     = ATA_SWDMA2_ONLY,      \
-               .mwdma_mask     = ATA_MWDMA12_ONLY,     \
-               .udma_mask      = ATA_UDMA6,            \
-       }
-
-static const struct ide_port_info it8213_chipsets[] __devinitdata = {
-       /* 0 */ DECLARE_ITE_DEV("IT8213"),
+static const struct ide_port_info it8213_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .enablebits     = { {0x41, 0x80, 0x80} },
+       .port_ops       = &it8213_port_ops,
+       .host_flags     = IDE_HFLAG_SINGLE,
+       .pio_mask       = ATA_PIO4,
+       .swdma_mask     = ATA_SWDMA2_ONLY,
+       .mwdma_mask     = ATA_MWDMA12_ONLY,
+       .udma_mask      = ATA_UDMA6,
 };
 
-
 /**
  *     it8213_init_one -       pci layer discovery entry
  *     @dev: PCI device
@@ -184,7 +180,7 @@ static const struct ide_port_info it8213_chipsets[] __devinitdata = {
 
 static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]);
+       return ide_pci_init_one(dev, &it8213_chipset, NULL);
 }
 
 static const struct pci_device_id it8213_pci_tbl[] = {
@@ -198,6 +194,7 @@ static struct pci_driver driver = {
        .name           = "ITE8213_IDE",
        .id_table       = it8213_pci_tbl,
        .probe          = it8213_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init it8213_ide_init(void)
@@ -205,7 +202,13 @@ static int __init it8213_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit it8213_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(it8213_ide_init);
+module_exit(it8213_ide_exit);
 
 MODULE_AUTHOR("Jack Lee, Alan Cox");
 MODULE_DESCRIPTION("PCI driver module for the ITE 8213");
index cbf647202994d2c273fd8a3d9d6cf38eac29fe54..e16a1d113a2a62e49ca6ade760c899ae1a2bfe06 100644 (file)
@@ -67,6 +67,8 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
+#define DRV_NAME "it821x"
+
 struct it821x_dev
 {
        unsigned int smart:1,           /* Are we in smart raid mode */
@@ -534,8 +536,9 @@ static struct ide_dma_ops it821x_pass_through_dma_ops = {
 static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct it821x_dev **itdevs = (struct it821x_dev **)pci_get_drvdata(dev);
-       struct it821x_dev *idev = itdevs[hwif->channel];
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct it821x_dev *itdevs = host->host_priv;
+       struct it821x_dev *idev = itdevs + hwif->channel;
        u8 conf;
 
        ide_set_hwifdata(hwif, idev);
@@ -568,7 +571,8 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
                idev->timing10 = 1;
                hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
                if (idev->smart == 0)
-                       printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n");
+                       printk(KERN_WARNING DRV_NAME " %s: revision 0x10, "
+                               "workarounds activated\n", pci_name(dev));
        }
 
        if (idev->smart == 0) {
@@ -601,18 +605,20 @@ static void __devinit it8212_disable_raid(struct pci_dev *dev)
        pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
 }
 
-static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev)
 {
        u8 conf;
        static char *mode[2] = { "pass through", "smart" };
 
        /* Force the card into bypass mode if so requested */
        if (it8212_noraid) {
-               printk(KERN_INFO "it8212: forcing bypass mode.\n");
+               printk(KERN_INFO DRV_NAME " %s: forcing bypass mode\n",
+                       pci_name(dev));
                it8212_disable_raid(dev);
        }
        pci_read_config_byte(dev, 0x50, &conf);
-       printk(KERN_INFO "it821x: controller in %s mode.\n", mode[conf & 1]);
+       printk(KERN_INFO DRV_NAME " %s: controller in %s mode\n",
+               pci_name(dev), mode[conf & 1]);
        return 0;
 }
 
@@ -624,17 +630,12 @@ static const struct ide_port_ops it821x_port_ops = {
        .cable_detect           = it821x_cable_detect,
 };
 
-#define DECLARE_ITE_DEV(name_str)                      \
-       {                                               \
-               .name           = name_str,             \
-               .init_chipset   = init_chipset_it821x,  \
-               .init_hwif      = init_hwif_it821x,     \
-               .port_ops       = &it821x_port_ops,     \
-               .pio_mask       = ATA_PIO4,             \
-       }
-
-static const struct ide_port_info it821x_chipsets[] __devinitdata = {
-       /* 0 */ DECLARE_ITE_DEV("IT8212"),
+static const struct ide_port_info it821x_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_chipset   = init_chipset_it821x,
+       .init_hwif      = init_hwif_it821x,
+       .port_ops       = &it821x_port_ops,
+       .pio_mask       = ATA_PIO4,
 };
 
 /**
@@ -648,23 +649,29 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
 
 static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       struct it821x_dev *itdevs[2] = { NULL, NULL} , *itdev;
-       unsigned int i;
-
-       for (i = 0; i < 2; i++) {
-               itdev = kzalloc(sizeof(*itdev), GFP_KERNEL);
-               if (itdev == NULL) {
-                       kfree(itdevs[0]);
-                       printk(KERN_ERR "it821x: out of memory\n");
-                       return -ENOMEM;
-               }
+       struct it821x_dev *itdevs;
+       int rc;
 
-               itdevs[i] = itdev;
+       itdevs = kzalloc(2 * sizeof(*itdevs), GFP_KERNEL);
+       if (itdevs == NULL) {
+               printk(KERN_ERR DRV_NAME " %s: out of memory\n", pci_name(dev));
+               return -ENOMEM;
        }
 
-       pci_set_drvdata(dev, itdevs);
+       rc = ide_pci_init_one(dev, &it821x_chipset, itdevs);
+       if (rc)
+               kfree(itdevs);
 
-       return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
+       return rc;
+}
+
+static void __devexit it821x_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct it821x_dev *itdevs = host->host_priv;
+
+       ide_pci_remove(dev);
+       kfree(itdevs);
 }
 
 static const struct pci_device_id it821x_pci_tbl[] = {
@@ -679,6 +686,7 @@ static struct pci_driver driver = {
        .name           = "ITE821x IDE",
        .id_table       = it821x_pci_tbl,
        .probe          = it821x_init_one,
+       .remove         = it821x_remove,
 };
 
 static int __init it821x_ide_init(void)
@@ -686,7 +694,13 @@ static int __init it821x_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit it821x_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(it821x_ide_init);
+module_exit(it821x_ide_exit);
 
 module_param_named(noraid, it8212_noraid, int, S_IRUGO);
 MODULE_PARM_DESC(noraid, "Force card into bypass mode");
index 96ef7394f28395b5646bee8f3ae9e319be3dcc90..545b6e172d9bcc74b712789edc375d6fd31f6195 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
+#define DRV_NAME "jmicron"
+
 typedef enum {
        PORT_PATA0 = 0,
        PORT_PATA1 = 1,
@@ -102,7 +104,7 @@ static const struct ide_port_ops jmicron_port_ops = {
 };
 
 static const struct ide_port_info jmicron_chipset __devinitdata = {
-       .name           = "JMB",
+       .name           = DRV_NAME,
        .enablebits     = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
        .port_ops       = &jmicron_port_ops,
        .pio_mask       = ATA_PIO5,
@@ -121,7 +123,7 @@ static const struct ide_port_info jmicron_chipset __devinitdata = {
 
 static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &jmicron_chipset);
+       return ide_pci_init_one(dev, &jmicron_chipset, NULL);
 }
 
 /* All JMB PATA controllers have and will continue to have the same
@@ -152,6 +154,7 @@ static struct pci_driver driver = {
        .name           = "JMicron IDE",
        .id_table       = jmicron_pci_tbl,
        .probe          = jmicron_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init jmicron_ide_init(void)
@@ -159,7 +162,13 @@ static int __init jmicron_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit jmicron_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(jmicron_ide_init);
+module_exit(jmicron_ide_exit);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("PCI driver module for the JMicron in legacy modes");
index 5cd2b32ff0ef000d61a06047bddb19f9a911c342..ffefcd15196c709b690bc8348eb2950b5c71e7ea 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "ns87415"
+
 #ifdef CONFIG_SUPERIO
 /* SUPERIO 87560 is a PoS chip that NatSem denies exists.
  * Unfortunately, it's built-in on all Astro-based PA-RISC workstations
@@ -305,7 +307,7 @@ static const struct ide_dma_ops ns87415_dma_ops = {
 };
 
 static const struct ide_port_info ns87415_chipset __devinitdata = {
-       .name           = "NS87415",
+       .name           = DRV_NAME,
        .init_hwif      = init_hwif_ns87415,
        .port_ops       = &ns87415_port_ops,
        .dma_ops        = &ns87415_dma_ops,
@@ -324,7 +326,7 @@ static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_devi
                d.tp_ops = &superio_tp_ops;
        }
 #endif
-       return ide_setup_pci_device(dev, &d);
+       return ide_pci_init_one(dev, &d, NULL);
 }
 
 static const struct pci_device_id ns87415_pci_tbl[] = {
@@ -337,6 +339,7 @@ static struct pci_driver driver = {
        .name           = "NS87415_IDE",
        .id_table       = ns87415_pci_tbl,
        .probe          = ns87415_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init ns87415_ide_init(void)
@@ -344,7 +347,13 @@ static int __init ns87415_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit ns87415_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(ns87415_ide_init);
+module_exit(ns87415_ide_exit);
 
 MODULE_AUTHOR("Mark Lord, Eddie Dost, Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for NS87415 IDE");
index 725c80508d909b593ba2fea5580d9f15de225ff9..e28e672ddafcf9dd5cd940792f4961cc82f179c5 100644 (file)
@@ -90,6 +90,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "opti621"
+
 #define READ_REG 0     /* index of Read cycle timing register */
 #define WRITE_REG 1    /* index of Write cycle timing register */
 #define CNTRL_REG 3    /* index of Control register */
@@ -200,7 +202,7 @@ static const struct ide_port_ops opti621_port_ops = {
 };
 
 static const struct ide_port_info opti621_chipset __devinitdata = {
-       .name           = "OPTI621/X",
+       .name           = DRV_NAME,
        .enablebits     = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
        .port_ops       = &opti621_port_ops,
        .host_flags     = IDE_HFLAG_NO_DMA,
@@ -209,7 +211,7 @@ static const struct ide_port_info opti621_chipset __devinitdata = {
 
 static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &opti621_chipset);
+       return ide_pci_init_one(dev, &opti621_chipset, NULL);
 }
 
 static const struct pci_device_id opti621_pci_tbl[] = {
@@ -223,6 +225,7 @@ static struct pci_driver driver = {
        .name           = "Opti621_IDE",
        .id_table       = opti621_pci_tbl,
        .probe          = opti621_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init opti621_ide_init(void)
@@ -230,7 +233,13 @@ static int __init opti621_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit opti621_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(opti621_ide_init);
+module_exit(opti621_ide_exit);
 
 MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord");
 MODULE_DESCRIPTION("PCI driver module for Opti621 IDE");
index 070df8ab3b218946ac69b2804bb9ebafce7a48de..998615fa285fc0f294dc91c5719aebd18830b97f 100644 (file)
@@ -31,6 +31,8 @@
 #include <asm/pci-bridge.h>
 #endif
 
+#define DRV_NAME "pdc202xx_new"
+
 #undef DEBUG
 
 #ifdef DEBUG
@@ -324,8 +326,9 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev)
 }
 #endif /* CONFIG_PPC_PMAC */
 
-static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev)
 {
+       const char *name = DRV_NAME;
        unsigned long dma_base = pci_resource_start(dev, 4);
        unsigned long sec_dma_base = dma_base + 0x08;
        long pll_input, pll_output, ratio;
@@ -358,12 +361,13 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
         * registers setting.
         */
        pll_input = detect_pll_input_clock(dma_base);
-       printk("%s: PLL input clock is %ld kHz\n", name, pll_input / 1000);
+       printk(KERN_INFO "%s %s: PLL input clock is %ld kHz\n",
+               name, pci_name(dev), pll_input / 1000);
 
        /* Sanity check */
        if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) {
-               printk(KERN_ERR "%s: Bad PLL input clock %ld Hz, giving up!\n",
-                      name, pll_input);
+               printk(KERN_ERR "%s %s: Bad PLL input clock %ld Hz, giving up!"
+                       "\n", name, pci_name(dev), pll_input);
                goto out;
        }
 
@@ -399,7 +403,8 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
                r = 0x00;
        } else {
                /* Invalid ratio */
-               printk(KERN_ERR "%s: Bad ratio %ld, giving up!\n", name, ratio);
+               printk(KERN_ERR "%s %s: Bad ratio %ld, giving up!\n",
+                       name, pci_name(dev), ratio);
                goto out;
        }
 
@@ -409,7 +414,8 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
 
        if (unlikely(f < 0 || f > 127)) {
                /* Invalid F */
-               printk(KERN_ERR "%s: F[%d] invalid!\n", name, f);
+               printk(KERN_ERR "%s %s: F[%d] invalid!\n",
+                       name, pci_name(dev), f);
                goto out;
        }
 
@@ -455,8 +461,8 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
 
                if (dev2->irq != dev->irq) {
                        dev2->irq = dev->irq;
-                       printk(KERN_INFO "PDC20270: PCI config space "
-                                        "interrupt fixed\n");
+                       printk(KERN_INFO DRV_NAME " %s: PCI config space "
+                               "interrupt fixed\n", pci_name(dev));
                }
 
                return dev2;
@@ -473,9 +479,9 @@ static const struct ide_port_ops pdcnew_port_ops = {
        .cable_detect           = pdcnew_cable_detect,
 };
 
-#define DECLARE_PDCNEW_DEV(name_str, udma) \
+#define DECLARE_PDCNEW_DEV(udma) \
        { \
-               .name           = name_str, \
+               .name           = DRV_NAME, \
                .init_chipset   = init_chipset_pdcnew, \
                .port_ops       = &pdcnew_port_ops, \
                .host_flags     = IDE_HFLAG_POST_SET_MODE | \
@@ -487,13 +493,8 @@ static const struct ide_port_ops pdcnew_port_ops = {
        }
 
 static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
-       /* 0 */ DECLARE_PDCNEW_DEV("PDC20268", ATA_UDMA5),
-       /* 1 */ DECLARE_PDCNEW_DEV("PDC20269", ATA_UDMA6),
-       /* 2 */ DECLARE_PDCNEW_DEV("PDC20270", ATA_UDMA5),
-       /* 3 */ DECLARE_PDCNEW_DEV("PDC20271", ATA_UDMA6),
-       /* 4 */ DECLARE_PDCNEW_DEV("PDC20275", ATA_UDMA6),
-       /* 5 */ DECLARE_PDCNEW_DEV("PDC20276", ATA_UDMA6),
-       /* 6 */ DECLARE_PDCNEW_DEV("PDC20277", ATA_UDMA6),
+       /* 0: PDC202{68,70} */          DECLARE_PDCNEW_DEV(ATA_UDMA5),
+       /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6),
 };
 
 /**
@@ -507,13 +508,10 @@ static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
  
 static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       const struct ide_port_info *d;
+       const struct ide_port_info *d = &pdcnew_chipsets[id->driver_data];
        struct pci_dev *bridge = dev->bus->self;
-       u8 idx = id->driver_data;
-
-       d = &pdcnew_chipsets[idx];
 
-       if (idx == 2 && bridge &&
+       if (dev->device == PCI_DEVICE_ID_PROMISE_20270 && bridge &&
            bridge->vendor == PCI_VENDOR_ID_DEC &&
            bridge->device == PCI_DEVICE_ID_DEC_21150) {
                struct pci_dev *dev2;
@@ -524,33 +522,42 @@ static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_de
                dev2 = pdc20270_get_dev2(dev);
 
                if (dev2) {
-                       int ret = ide_setup_pci_devices(dev, dev2, d);
+                       int ret = ide_pci_init_two(dev, dev2, d, NULL);
                        if (ret < 0)
                                pci_dev_put(dev2);
                        return ret;
                }
        }
 
-       if (idx == 5 && bridge &&
+       if (dev->device == PCI_DEVICE_ID_PROMISE_20276 && bridge &&
            bridge->vendor == PCI_VENDOR_ID_INTEL &&
            (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
             bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
-               printk(KERN_INFO "PDC20276: attached to I2O RAID controller, "
-                                "skipping\n");
+               printk(KERN_INFO DRV_NAME " %s: attached to I2O RAID controller,"
+                       " skipping\n", pci_name(dev));
                return -ENODEV;
        }
 
-       return ide_setup_pci_device(dev, d);
+       return ide_pci_init_one(dev, d, NULL);
+}
+
+static void __devexit pdc202new_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+       ide_pci_remove(dev);
+       pci_dev_put(dev2);
 }
 
 static const struct pci_device_id pdc202new_pci_tbl[] = {
        { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), 0 },
        { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), 1 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 2 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 3 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 4 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 5 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 6 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 0 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 1 },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
@@ -559,6 +566,7 @@ static struct pci_driver driver = {
        .name           = "Promise_IDE",
        .id_table       = pdc202new_pci_tbl,
        .probe          = pdc202new_init_one,
+       .remove         = pdc202new_remove,
 };
 
 static int __init pdc202new_ide_init(void)
@@ -566,7 +574,13 @@ static int __init pdc202new_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit pdc202new_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(pdc202new_ide_init);
+module_exit(pdc202new_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
 MODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher");
index e54dc653b8c4aa609edbb6d16a0ab85e0bfa034b..6ff2def58da09841090081079a73f3761cd16681 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "pdc202xx_old"
+
 #define PDC202XX_DEBUG_DRIVE_INFO      0
 
 static const char *pdc_quirk_drives[] = {
@@ -263,8 +265,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
        ide_dma_timeout(drive);
 }
 
-static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
-                                                   const char *name)
+static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev)
 {
        unsigned long dmabase = pci_resource_start(dev, 4);
        u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
@@ -304,8 +305,8 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
                if (irq != irq2) {
                        pci_write_config_byte(dev,
                                (PCI_INTERRUPT_LINE)|0x80, irq);     /* 0xbc */
-                       printk(KERN_INFO "%s: PCI config space interrupt "
-                                        "mirror fixed\n", name);
+                       printk(KERN_INFO "%s %s: PCI config space interrupt "
+                               "mirror fixed\n", name, pci_name(dev));
                }
        }
 }
@@ -350,9 +351,9 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
        .dma_timeout            = pdc202xx_dma_timeout,
 };
 
-#define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
+#define DECLARE_PDC2026X_DEV(udma, extra_flags) \
        { \
-               .name           = name_str, \
+               .name           = DRV_NAME, \
                .init_chipset   = init_chipset_pdc202xx, \
                .port_ops       = &pdc2026x_port_ops, \
                .dma_ops        = &pdc2026x_dma_ops, \
@@ -363,8 +364,8 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
        }
 
 static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
-       {       /* 0 */
-               .name           = "PDC20246",
+       {       /* 0: PDC20246 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_pdc202xx,
                .port_ops       = &pdc20246_port_ops,
                .dma_ops        = &pdc20246_dma_ops,
@@ -374,10 +375,10 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
                .udma_mask      = ATA_UDMA2,
        },
 
-       /* 1 */ DECLARE_PDC2026X_DEV("PDC20262", ATA_UDMA4, 0),
-       /* 2 */ DECLARE_PDC2026X_DEV("PDC20263", ATA_UDMA4, 0),
-       /* 3 */ DECLARE_PDC2026X_DEV("PDC20265", ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
-       /* 4 */ DECLARE_PDC2026X_DEV("PDC20267", ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
+       /* 1: PDC2026{2,3} */
+       DECLARE_PDC2026X_DEV(ATA_UDMA4, 0),
+       /* 2: PDC2026{5,7} */
+       DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
 };
 
 /**
@@ -396,31 +397,32 @@ static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_dev
 
        d = &pdc202xx_chipsets[idx];
 
-       if (idx < 3)
+       if (idx < 2)
                pdc202ata4_fixup_irq(dev, d->name);
 
-       if (idx == 3) {
+       if (dev->vendor == PCI_DEVICE_ID_PROMISE_20265) {
                struct pci_dev *bridge = dev->bus->self;
 
                if (bridge &&
                    bridge->vendor == PCI_VENDOR_ID_INTEL &&
                    (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
                     bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
-                       printk(KERN_INFO "ide: Skipping Promise PDC20265 "
-                               "attached to I2O RAID controller\n");
+                       printk(KERN_INFO DRV_NAME " %s: skipping Promise "
+                               "PDC20265 attached to I2O RAID controller\n",
+                               pci_name(dev));
                        return -ENODEV;
                }
        }
 
-       return ide_setup_pci_device(dev, d);
+       return ide_pci_init_one(dev, d, NULL);
 }
 
 static const struct pci_device_id pdc202xx_pci_tbl[] = {
        { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 },
        { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 2 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 3 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 4 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
@@ -429,6 +431,7 @@ static struct pci_driver driver = {
        .name           = "Promise_Old_IDE",
        .id_table       = pdc202xx_pci_tbl,
        .probe          = pdc202xx_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init pdc202xx_ide_init(void)
@@ -436,7 +439,13 @@ static int __init pdc202xx_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit pdc202xx_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(pdc202xx_ide_init);
+module_exit(pdc202xx_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
 MODULE_DESCRIPTION("PCI driver module for older Promise IDE");
index 0ce41b4dddafc543855f7c491c8fcf6599b666d2..7fc3022dcf684edb037c9e0649f655bbc7ae96b0 100644 (file)
@@ -54,6 +54,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "piix"
+
 static int no_piix_dma;
 
 /**
@@ -198,13 +200,12 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
 /**
  *     init_chipset_ich        -       set up the ICH chipset
  *     @dev: PCI device to set up
- *     @name: Name of the device
  *
  *     Initialize the PCI device as required.  For the ICH this turns
  *     out to be nice and simple.
  */
 
-static unsigned int __devinit init_chipset_ich(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_ich(struct pci_dev *dev)
 {
        u32 extra = 0;
 
@@ -314,9 +315,9 @@ static const struct ide_port_ops piix_port_ops = {
  #define IDE_HFLAGS_PIIX 0
 #endif
 
-#define DECLARE_PIIX_DEV(name_str, udma) \
+#define DECLARE_PIIX_DEV(udma) \
        {                                               \
-               .name           = name_str,             \
+               .name           = DRV_NAME,             \
                .init_hwif      = init_hwif_piix,       \
                .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
                .port_ops       = &piix_port_ops,       \
@@ -327,9 +328,9 @@ static const struct ide_port_ops piix_port_ops = {
                .udma_mask      = udma,                 \
        }
 
-#define DECLARE_ICH_DEV(name_str, udma) \
+#define DECLARE_ICH_DEV(udma) \
        { \
-               .name           = name_str, \
+               .name           = DRV_NAME, \
                .init_chipset   = init_chipset_ich, \
                .init_hwif      = init_hwif_ich, \
                .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
@@ -342,45 +343,31 @@ static const struct ide_port_ops piix_port_ops = {
        }
 
 static const struct ide_port_info piix_pci_info[] __devinitdata = {
-       /*  0 */ DECLARE_PIIX_DEV("PIIXa",      0x00),  /* no udma */
-       /*  1 */ DECLARE_PIIX_DEV("PIIXb",      0x00),  /* no udma */
-
-       /*  2 */
+       /* 0: MPIIX */
        {       /*
                 * MPIIX actually has only a single IDE channel mapped to
                 * the primary or secondary ports depending on the value
                 * of the bit 14 of the IDETIM register at offset 0x6c
                 */
-               .name           = "MPIIX",
+               .name           = DRV_NAME,
                .enablebits     = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}},
                .host_flags     = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA |
                                  IDE_HFLAGS_PIIX,
                .pio_mask       = ATA_PIO4,
                /* This is a painful system best to let it self tune for now */
        },
-
-       /*  3 */ DECLARE_PIIX_DEV("PIIX3",      0x00),  /* no udma */
-       /*  4 */ DECLARE_PIIX_DEV("PIIX4",      ATA_UDMA2),
-       /*  5 */ DECLARE_ICH_DEV("ICH0",        ATA_UDMA2),
-       /*  6 */ DECLARE_PIIX_DEV("PIIX4",      ATA_UDMA2),
-       /*  7 */ DECLARE_ICH_DEV("ICH",         ATA_UDMA4),
-       /*  8 */ DECLARE_PIIX_DEV("PIIX4",      ATA_UDMA4),
-       /*  9 */ DECLARE_PIIX_DEV("PIIX4",      ATA_UDMA2),
-       /* 10 */ DECLARE_ICH_DEV("ICH2",        ATA_UDMA5),
-       /* 11 */ DECLARE_ICH_DEV("ICH2M",       ATA_UDMA5),
-       /* 12 */ DECLARE_ICH_DEV("ICH3M",       ATA_UDMA5),
-       /* 13 */ DECLARE_ICH_DEV("ICH3",        ATA_UDMA5),
-       /* 14 */ DECLARE_ICH_DEV("ICH4",        ATA_UDMA5),
-       /* 15 */ DECLARE_ICH_DEV("ICH5",        ATA_UDMA5),
-       /* 16 */ DECLARE_ICH_DEV("C-ICH",       ATA_UDMA5),
-       /* 17 */ DECLARE_ICH_DEV("ICH4",        ATA_UDMA5),
-       /* 18 */ DECLARE_ICH_DEV("ICH5-SATA",   ATA_UDMA5),
-       /* 19 */ DECLARE_ICH_DEV("ICH5",        ATA_UDMA5),
-       /* 20 */ DECLARE_ICH_DEV("ICH6",        ATA_UDMA5),
-       /* 21 */ DECLARE_ICH_DEV("ICH7",        ATA_UDMA5),
-       /* 22 */ DECLARE_ICH_DEV("ICH4",        ATA_UDMA5),
-       /* 23 */ DECLARE_ICH_DEV("ESB2",        ATA_UDMA5),
-       /* 24 */ DECLARE_ICH_DEV("ICH8M",       ATA_UDMA5),
+       /* 1: PIIXa/PIIXb/PIIX3 */
+       DECLARE_PIIX_DEV(0x00), /* no udma */
+       /* 2: PIIX4 */
+       DECLARE_PIIX_DEV(ATA_UDMA2),
+       /* 3: ICH0 */
+       DECLARE_ICH_DEV(ATA_UDMA2),
+       /* 4: ICH */
+       DECLARE_ICH_DEV(ATA_UDMA4),
+       /* 5: PIIX4 */
+       DECLARE_PIIX_DEV(ATA_UDMA4),
+       /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
+       DECLARE_ICH_DEV(ATA_UDMA5),
 };
 
 /**
@@ -394,7 +381,7 @@ static const struct ide_port_info piix_pci_info[] __devinitdata = {
  
 static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &piix_pci_info[id->driver_data]);
+       return ide_pci_init_one(dev, &piix_pci_info[id->driver_data], NULL);
 }
 
 /**
@@ -421,39 +408,39 @@ static void __devinit piix_check_450nx(void)
                        no_piix_dma = 2;
        }
        if(no_piix_dma)
-               printk(KERN_WARNING "piix: 450NX errata present, disabling IDE DMA.\n");
+               printk(KERN_WARNING DRV_NAME ": 450NX errata present, disabling IDE DMA.\n");
        if(no_piix_dma == 2)
-               printk(KERN_WARNING "piix: A BIOS update may resolve this.\n");
+               printk(KERN_WARNING DRV_NAME ": A BIOS update may resolve this.\n");
 }              
 
 static const struct pci_device_id piix_pci_tbl[] = {
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0),   0 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1),   1 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX),     2 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1),   3 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB),     4 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1),   5 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1),   6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1),   7 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1),   8 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX),     9 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9),  10 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8),  11 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 12 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 13 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 14 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 15 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11),  16 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 17 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0),  1 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1),  1 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX),    0 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1),  1 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB),    2 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1),  3 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1),  2 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1),  4 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1),  5 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX),    2 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9),  6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8),  6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11),  6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 6 },
 #ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1),  18 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1),  6 },
 #endif
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2),      19 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19),    20 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    21 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1),  22 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    23 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6),     24 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2),      6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1),  6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6),     6 },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
@@ -462,6 +449,7 @@ static struct pci_driver driver = {
        .name           = "PIIX_IDE",
        .id_table       = piix_pci_tbl,
        .probe          = piix_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init piix_ide_init(void)
@@ -470,7 +458,13 @@ static int __init piix_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit piix_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(piix_ide_init);
+module_exit(piix_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz");
 MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE");
index 532154adba2945738d27cb30066c292f2a09c05f..8d11ee838a2a825702f31a56429a1f25dd663010 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
+#define DRV_NAME "rz1000"
+
 static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -40,7 +42,7 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
 }
 
 static const struct ide_port_info rz1000_chipset __devinitdata = {
-       .name           = "RZ100x",
+       .name           = DRV_NAME,
        .init_hwif      = init_hwif_rz1000,
        .chipset        = ide_rz1000,
        .host_flags     = IDE_HFLAG_NO_DMA,
@@ -48,7 +50,7 @@ static const struct ide_port_info rz1000_chipset __devinitdata = {
 
 static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &rz1000_chipset);
+       return ide_pci_init_one(dev, &rz1000_chipset, NULL);
 }
 
 static const struct pci_device_id rz1000_pci_tbl[] = {
@@ -62,6 +64,7 @@ static struct pci_driver driver = {
        .name           = "RZ1000_IDE",
        .id_table       = rz1000_pci_tbl,
        .probe          = rz1000_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init rz1000_ide_init(void)
@@ -69,7 +72,13 @@ static int __init rz1000_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit rz1000_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(rz1000_ide_init);
+module_exit(rz1000_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for RZ1000 IDE");
index 14c787b5d95f89c8fd6406d22cd82ef72d4322bb..8efaed16fea31d5b5f14b65e1716114d3ac20c50 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "sc1200"
+
 #define SC1200_REV_A   0x00
 #define SC1200_REV_B1  0x01
 #define SC1200_REV_B3  0x02
@@ -234,20 +236,10 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
         * we only save state when going from full power to less
         */
        if (state.event == PM_EVENT_ON) {
-               struct sc1200_saved_state *ss;
+               struct ide_host *host = pci_get_drvdata(dev);
+               struct sc1200_saved_state *ss = host->host_priv;
                unsigned int r;
 
-               /*
-                * allocate a permanent save area, if not already allocated
-                */
-               ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
-               if (ss == NULL) {
-                       ss = kmalloc(sizeof(*ss), GFP_KERNEL);
-                       if (ss == NULL)
-                               return -ENOMEM;
-                       pci_set_drvdata(dev, ss);
-               }
-
                /*
                 * save timing registers
                 * (this may be unnecessary if BIOS also does it)
@@ -263,7 +255,8 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
 
 static int sc1200_resume (struct pci_dev *dev)
 {
-       struct sc1200_saved_state *ss;
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct sc1200_saved_state *ss = host->host_priv;
        unsigned int r;
        int i;
 
@@ -271,16 +264,12 @@ static int sc1200_resume (struct pci_dev *dev)
        if (i)
                return i;
 
-       ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
-
        /*
         * restore timing registers
         * (this may be unnecessary if BIOS also does it)
         */
-       if (ss) {
-               for (r = 0; r < 8; r++)
-                       pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
-       }
+       for (r = 0; r < 8; r++)
+               pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
 
        return 0;
 }
@@ -304,7 +293,7 @@ static const struct ide_dma_ops sc1200_dma_ops = {
 };
 
 static const struct ide_port_info sc1200_chipset __devinitdata = {
-       .name           = "SC1200",
+       .name           = DRV_NAME,
        .port_ops       = &sc1200_port_ops,
        .dma_ops        = &sc1200_dma_ops,
        .host_flags     = IDE_HFLAG_SERIALIZE |
@@ -317,7 +306,19 @@ static const struct ide_port_info sc1200_chipset __devinitdata = {
 
 static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &sc1200_chipset);
+       struct sc1200_saved_state *ss = NULL;
+       int rc;
+
+#ifdef CONFIG_PM
+       ss = kmalloc(sizeof(*ss), GFP_KERNEL);
+       if (ss == NULL)
+               return -ENOMEM;
+#endif
+       rc = ide_pci_init_one(dev, &sc1200_chipset, ss);
+       if (rc)
+               kfree(ss);
+
+       return rc;
 }
 
 static const struct pci_device_id sc1200_pci_tbl[] = {
@@ -330,6 +331,7 @@ static struct pci_driver driver = {
        .name           = "SC1200_IDE",
        .id_table       = sc1200_pci_tbl,
        .probe          = sc1200_init_one,
+       .remove         = ide_pci_remove,
 #ifdef CONFIG_PM
        .suspend        = sc1200_suspend,
        .resume         = sc1200_resume,
@@ -341,7 +343,13 @@ static int __init sc1200_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit sc1200_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(sc1200_ide_init);
+module_exit(sc1200_ide_exit);
 
 MODULE_AUTHOR("Mark Lord");
 MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE");
index 127ccb45e261c23cb799bcb1e886141155f4b779..d173f2937722074e99bfbda0cdce5e437b4ab698 100644 (file)
@@ -38,6 +38,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "serverworks"
+
 #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) */
 
@@ -172,7 +174,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
        pci_write_config_byte(dev, 0x54, ultra_enable);
 }
 
-static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_svwks(struct pci_dev *dev)
 {
        unsigned int reg;
        u8 btr;
@@ -188,7 +190,8 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
                        pci_read_config_dword(isa_dev, 0x64, &reg);
                        reg &= ~0x00002000; /* disable 600ns interrupt mask */
                        if(!(reg & 0x00004000))
-                               printk(KERN_DEBUG "%s: UDMA not BIOS enabled.\n", name);
+                               printk(KERN_DEBUG DRV_NAME " %s: UDMA not BIOS "
+                                       "enabled.\n", pci_name(dev));
                        reg |=  0x00004000; /* enable UDMA/33 support */
                        pci_write_config_dword(isa_dev, 0x64, reg);
                }
@@ -352,40 +355,44 @@ static const struct ide_port_ops svwks_port_ops = {
 #define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS
 
 static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
-       {       /* 0 */
-               .name           = "SvrWks OSB4",
+       {       /* 0: OSB4 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_svwks,
                .port_ops       = &osb4_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = 0x00, /* UDMA is problematic on OSB4 */
-       },{     /* 1 */
-               .name           = "SvrWks CSB5",
+       },
+       {       /* 1: CSB5 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_svwks,
                .port_ops       = &svwks_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
-       },{     /* 2 */
-               .name           = "SvrWks CSB6",
+       },
+       {       /* 2: CSB6 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_svwks,
                .port_ops       = &svwks_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
-       },{     /* 3 */
-               .name           = "SvrWks CSB6",
+       },
+       {       /* 3: CSB6-2 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_svwks,
                .port_ops       = &svwks_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
-       },{     /* 4 */
-               .name           = "SvrWks HT1000",
+       },
+       {       /* 4: HT1000 */
+               .name           = DRV_NAME,
                .init_chipset   = init_chipset_svwks,
                .port_ops       = &svwks_port_ops,
                .host_flags     = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
@@ -422,7 +429,7 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
                        d.host_flags &= ~IDE_HFLAG_SINGLE;
        }
 
-       return ide_setup_pci_device(dev, &d);
+       return ide_pci_init_one(dev, &d, NULL);
 }
 
 static const struct pci_device_id svwks_pci_tbl[] = {
@@ -439,6 +446,7 @@ static struct pci_driver driver = {
        .name           = "Serverworks_IDE",
        .id_table       = svwks_pci_tbl,
        .probe          = svwks_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init svwks_ide_init(void)
@@ -446,7 +454,13 @@ static int __init svwks_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit svwks_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(svwks_ide_init);
+module_exit(svwks_ide_exit);
 
 MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE");
index 5965a35d94ae75a7c64c57fb0def8e5aed27ef0f..b8ad9ad6cf0dd69db049b99edfda2f2b5be1f2e8 100644 (file)
@@ -44,6 +44,8 @@
 #include <linux/init.h>
 #include <linux/io.h>
 
+#define DRV_NAME "siimage"
+
 /**
  *     pdev_is_sata            -       check if device is SATA
  *     @pdev:  PCI device to check
@@ -127,9 +129,10 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
 
 static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
 {
+       struct ide_host *host = pci_get_drvdata(dev);
        u8 tmp = 0;
 
-       if (pci_get_drvdata(dev))
+       if (host->host_priv)
                tmp = readb((void __iomem *)addr);
        else
                pci_read_config_byte(dev, addr, &tmp);
@@ -139,9 +142,10 @@ static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
 
 static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
 {
+       struct ide_host *host = pci_get_drvdata(dev);
        u16 tmp = 0;
 
-       if (pci_get_drvdata(dev))
+       if (host->host_priv)
                tmp = readw((void __iomem *)addr);
        else
                pci_read_config_word(dev, addr, &tmp);
@@ -151,7 +155,9 @@ static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
 
 static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
 {
-       if (pci_get_drvdata(dev))
+       struct ide_host *host = pci_get_drvdata(dev);
+
+       if (host->host_priv)
                writeb(val, (void __iomem *)addr);
        else
                pci_write_config_byte(dev, addr, val);
@@ -159,7 +165,9 @@ static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
 
 static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
 {
-       if (pci_get_drvdata(dev))
+       struct ide_host *host = pci_get_drvdata(dev);
+
+       if (host->host_priv)
                writew(val, (void __iomem *)addr);
        else
                pci_write_config_word(dev, addr, val);
@@ -167,7 +175,9 @@ static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
 
 static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr)
 {
-       if (pci_get_drvdata(dev))
+       struct ide_host *host = pci_get_drvdata(dev);
+
+       if (host->host_priv)
                writel(val, (void __iomem *)addr);
        else
                pci_write_config_dword(dev, addr, val);
@@ -444,67 +454,25 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
        }
 }
 
-/**
- *     setup_mmio_siimage      -       switch controller into MMIO mode
- *     @dev: PCI device we are configuring
- *     @name: device name
- *
- *     Attempt to put the device into MMIO mode. There are some slight
- *     complications here with certain systems where the MMIO BAR isn't
- *     mapped, so we have to be sure that we can fall back to I/O.
- */
-
-static unsigned int setup_mmio_siimage(struct pci_dev *dev, const char *name)
-{
-       resource_size_t bar5    = pci_resource_start(dev, 5);
-       unsigned long barsize   = pci_resource_len(dev, 5);
-       void __iomem *ioaddr;
-
-       /*
-        *      Drop back to PIO if we can't map the MMIO. Some systems
-        *      seem to get terminally confused in the PCI spaces.
-        */
-       if (!request_mem_region(bar5, barsize, name)) {
-               printk(KERN_WARNING "siimage: IDE controller MMIO ports not "
-                                   "available.\n");
-               return 0;
-       }
-
-       ioaddr = ioremap(bar5, barsize);
-       if (ioaddr == NULL) {
-               release_mem_region(bar5, barsize);
-               return 0;
-       }
-
-       pci_set_master(dev);
-       pci_set_drvdata(dev, (void *) ioaddr);
-
-       return 1;
-}
-
 /**
  *     init_chipset_siimage    -       set up an SI device
  *     @dev: PCI device
- *     @name: device name
  *
  *     Perform the initial PCI set up for this device. Attempt to switch
  *     to 133 MHz clocking if the system isn't already set up to do it.
  */
 
-static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
-                                                  const char *name)
+static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev)
 {
+       struct ide_host *host = pci_get_drvdata(dev);
+       void __iomem *ioaddr = host->host_priv;
        unsigned long base, scsc_addr;
-       void __iomem *ioaddr = NULL;
-       u8 rev = dev->revision, tmp, BA5_EN;
+       u8 rev = dev->revision, tmp;
 
        pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
 
-       pci_read_config_byte(dev, 0x8A, &BA5_EN);
-
-       if ((BA5_EN & 0x01) || pci_resource_start(dev, 5))
-               if (setup_mmio_siimage(dev, name))
-                       ioaddr = pci_get_drvdata(dev);
+       if (ioaddr)
+               pci_set_master(dev);
 
        base = (unsigned long)ioaddr;
 
@@ -571,7 +539,8 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
                        { "== 100", "== 133", "== 2X PCI", "DISABLED!" };
 
                tmp >>= 4;
-               printk(KERN_INFO "%s: BASE CLOCK %s\n", name, clk_str[tmp & 3]);
+               printk(KERN_INFO DRV_NAME " %s: BASE CLOCK %s\n",
+                       pci_name(dev), clk_str[tmp & 3]);
        }
 
        return 0;
@@ -592,7 +561,8 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
 static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
 {
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       void *addr              = pci_get_drvdata(dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       void *addr              = host->host_priv;
        u8 ch                   = hwif->channel;
        struct ide_io_ports *io_ports = &hwif->io_ports;
        unsigned long base;
@@ -691,16 +661,15 @@ static void __devinit sil_quirkproc(ide_drive_t *drive)
 static void __devinit init_iops_siimage(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct ide_host *host = pci_get_drvdata(dev);
 
        hwif->hwif_data = NULL;
 
        /* Pessimal until we finish probing */
        hwif->rqsize = 15;
 
-       if (pci_get_drvdata(dev) == NULL)
-               return;
-
-       init_mmio_iops_siimage(hwif);
+       if (host->host_priv)
+               init_mmio_iops_siimage(hwif);
 }
 
 /**
@@ -748,9 +717,9 @@ static const struct ide_dma_ops sil_dma_ops = {
        .dma_lost_irq           = ide_dma_lost_irq,
 };
 
-#define DECLARE_SII_DEV(name_str, p_ops)               \
+#define DECLARE_SII_DEV(p_ops)                         \
        {                                               \
-               .name           = name_str,             \
+               .name           = DRV_NAME,             \
                .init_chipset   = init_chipset_siimage, \
                .init_iops      = init_iops_siimage,    \
                .port_ops       = p_ops,                \
@@ -761,9 +730,8 @@ static const struct ide_dma_ops sil_dma_ops = {
        }
 
 static const struct ide_port_info siimage_chipsets[] __devinitdata = {
-       /* 0 */ DECLARE_SII_DEV("SiI680",               &sil_pata_port_ops),
-       /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA",   &sil_sata_port_ops),
-       /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA",   &sil_sata_port_ops)
+       /* 0: SiI680 */  DECLARE_SII_DEV(&sil_pata_port_ops),
+       /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
 };
 
 /**
@@ -778,8 +746,13 @@ static const struct ide_port_info siimage_chipsets[] __devinitdata = {
 static int __devinit siimage_init_one(struct pci_dev *dev,
                                      const struct pci_device_id *id)
 {
+       void __iomem *ioaddr = NULL;
+       resource_size_t bar5 = pci_resource_start(dev, 5);
+       unsigned long barsize = pci_resource_len(dev, 5);
+       int rc;
        struct ide_port_info d;
        u8 idx = id->driver_data;
+       u8 BA5_EN;
 
        d = siimage_chipsets[idx];
 
@@ -787,7 +760,7 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
                static int first = 1;
 
                if (first) {
-                       printk(KERN_INFO "siimage: For full SATA support you "
+                       printk(KERN_INFO DRV_NAME ": For full SATA support you "
                                "should use the libata sata_sil module.\n");
                        first = 0;
                }
@@ -795,14 +768,61 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
                d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
        }
 
-       return ide_setup_pci_device(dev, &d);
+       rc = pci_enable_device(dev);
+       if (rc)
+               return rc;
+
+       pci_read_config_byte(dev, 0x8A, &BA5_EN);
+       if ((BA5_EN & 0x01) || bar5) {
+               /*
+               * Drop back to PIO if we can't map the MMIO. Some systems
+               * seem to get terminally confused in the PCI spaces.
+               */
+               if (!request_mem_region(bar5, barsize, d.name)) {
+                       printk(KERN_WARNING DRV_NAME " %s: MMIO ports not "
+                               "available\n", pci_name(dev));
+               } else {
+                       ioaddr = ioremap(bar5, barsize);
+                       if (ioaddr == NULL)
+                               release_mem_region(bar5, barsize);
+               }
+       }
+
+       rc = ide_pci_init_one(dev, &d, ioaddr);
+       if (rc) {
+               if (ioaddr) {
+                       iounmap(ioaddr);
+                       release_mem_region(bar5, barsize);
+               }
+               pci_disable_device(dev);
+       }
+
+       return rc;
+}
+
+static void __devexit siimage_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       void __iomem *ioaddr = host->host_priv;
+
+       ide_pci_remove(dev);
+
+       if (ioaddr) {
+               resource_size_t bar5 = pci_resource_start(dev, 5);
+               unsigned long barsize = pci_resource_len(dev, 5);
+
+               iounmap(ioaddr);
+               release_mem_region(bar5, barsize);
+       }
+
+       pci_disable_device(dev);
 }
 
 static const struct pci_device_id siimage_pci_tbl[] = {
        { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680),    0 },
 #ifdef CONFIG_BLK_DEV_IDE_SATA
        { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112),   1 },
-       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 2 },
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 1 },
 #endif
        { 0, },
 };
@@ -812,6 +832,7 @@ static struct pci_driver driver = {
        .name           = "SiI_IDE",
        .id_table       = siimage_pci_tbl,
        .probe          = siimage_init_one,
+       .remove         = siimage_remove,
 };
 
 static int __init siimage_ide_init(void)
@@ -819,7 +840,13 @@ static int __init siimage_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit siimage_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(siimage_ide_init);
+module_exit(siimage_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick, Alan Cox");
 MODULE_DESCRIPTION("PCI driver module for SiI IDE");
index 2389945ca95d0c2a86b22ef90d5b8a2743fc6585..cc95f90b53b706c70f48584c69fcff2f5efc27b6 100644 (file)
@@ -52,6 +52,8 @@
 #include <linux/init.h>
 #include <linux/ide.h>
 
+#define DRV_NAME "sis5513"
+
 /* registers layout and init values are chipset family dependant */
 
 #define ATA_16         0x01
@@ -380,8 +382,9 @@ static int __devinit sis_find_family(struct pci_dev *dev)
                }
                pci_dev_put(host);
 
-               printk(KERN_INFO "SIS5513: %s %s controller\n",
-                        SiSHostChipInfo[i].name, chipset_capability[chipset_family]);
+               printk(KERN_INFO DRV_NAME " %s: %s %s controller\n",
+                       pci_name(dev), SiSHostChipInfo[i].name,
+                       chipset_capability[chipset_family]);
        }
 
        if (!chipset_family) { /* Belongs to pci-quirks */
@@ -396,7 +399,8 @@ static int __devinit sis_find_family(struct pci_dev *dev)
                        pci_write_config_dword(dev, 0x54, idemisc);
 
                        if (trueid == 0x5518) {
-                               printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n");
+                               printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n",
+                                       pci_name(dev));
                                chipset_family = ATA_133;
 
                                /* Check for 5513 compability mapping
@@ -405,7 +409,8 @@ static int __devinit sis_find_family(struct pci_dev *dev)
                                 */
                                if ((idemisc & 0x40000000) == 0) {
                                        pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
-                                       printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
+                                       printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n",
+                                               pci_name(dev));
                                }
                        }
        }
@@ -429,10 +434,12 @@ static int __devinit sis_find_family(struct pci_dev *dev)
                                pci_dev_put(lpc_bridge);
 
                                if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
-                                       printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");
+                                       printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n",
+                                               pci_name(dev));
                                        chipset_family = ATA_133a;
                                } else {
-                                       printk(KERN_INFO "SIS5513: SiS 961 MuTIOL IDE UDMA100 controller\n");
+                                       printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n",
+                                               pci_name(dev));
                                        chipset_family = ATA_100;
                                }
                        }
@@ -441,8 +448,7 @@ static int __devinit sis_find_family(struct pci_dev *dev)
        return chipset_family;
 }
 
-static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev,
-                                                  const char *name)
+static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev)
 {
        /* Make general config ops here
           1/ tell IDE channels to operate in Compatibility mode only
@@ -555,7 +561,7 @@ static const struct ide_port_ops sis_ata133_port_ops = {
 };
 
 static const struct ide_port_info sis5513_chipset __devinitdata = {
-       .name           = "SIS5513",
+       .name           = DRV_NAME,
        .init_chipset   = init_chipset_sis5513,
        .enablebits     = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
        .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
@@ -583,7 +589,13 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi
 
        d.udma_mask = udma_rates[chipset_family];
 
-       return ide_setup_pci_device(dev, &d);
+       return ide_pci_init_one(dev, &d, NULL);
+}
+
+static void __devexit sis5513_remove(struct pci_dev *dev)
+{
+       ide_pci_remove(dev);
+       pci_disable_device(dev);
 }
 
 static const struct pci_device_id sis5513_pci_tbl[] = {
@@ -598,6 +610,7 @@ static struct pci_driver driver = {
        .name           = "SIS_IDE",
        .id_table       = sis5513_pci_tbl,
        .probe          = sis5513_init_one,
+       .remove         = sis5513_remove,
 };
 
 static int __init sis5513_ide_init(void)
@@ -605,7 +618,13 @@ static int __init sis5513_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit sis5513_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(sis5513_ide_init);
+module_exit(sis5513_ide_exit);
 
 MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");
 MODULE_DESCRIPTION("PCI driver module for SIS IDE");
index f82a6502c1b721069bc1cadbeff89028dc97fc77..73905bcc08fbb0616dca5a5f0fd906ff33069653 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <asm/io.h>
 
+#define DRV_NAME "sl82c105"
+
 #undef DEBUG
 
 #ifdef DEBUG
@@ -270,7 +272,7 @@ static u8 sl82c105_bridge_revision(struct pci_dev *dev)
  * channel 0 here at least, but channel 1 has to be enabled by
  * firmware or arch code. We still set both to 16 bits mode.
  */
-static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const char *msg)
+static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev)
 {
        u32 val;
 
@@ -301,7 +303,7 @@ static const struct ide_dma_ops sl82c105_dma_ops = {
 };
 
 static const struct ide_port_info sl82c105_chipset __devinitdata = {
-       .name           = "W82C105",
+       .name           = DRV_NAME,
        .init_chipset   = init_chipset_sl82c105,
        .enablebits     = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
        .port_ops       = &sl82c105_port_ops,
@@ -328,14 +330,14 @@ static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_dev
                 * Never ever EVER under any circumstances enable
                 * DMA when the bridge is this old.
                 */
-               printk(KERN_INFO "W82C105_IDE: Winbond W83C553 bridge "
+               printk(KERN_INFO DRV_NAME ": Winbond W83C553 bridge "
                                 "revision %d, BM-DMA disabled\n", rev);
                d.dma_ops = NULL;
                d.mwdma_mask = 0;
                d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA;
        }
 
-       return ide_setup_pci_device(dev, &d);
+       return ide_pci_init_one(dev, &d, NULL);
 }
 
 static const struct pci_device_id sl82c105_pci_tbl[] = {
@@ -348,6 +350,7 @@ static struct pci_driver driver = {
        .name           = "W82C105_IDE",
        .id_table       = sl82c105_pci_tbl,
        .probe          = sl82c105_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init sl82c105_ide_init(void)
@@ -355,7 +358,13 @@ static int __init sl82c105_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit sl82c105_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(sl82c105_ide_init);
+module_exit(sl82c105_ide_exit);
 
 MODULE_DESCRIPTION("PCI driver module for W82C105 IDE");
 MODULE_LICENSE("GPL");
index dae6e2c94d865dbdef0d8df0710ccdfe90854f53..13d1fa491f26148a9650d960e441a3a6345a8261 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
+#define DRV_NAME "slc90e66"
+
 static DEFINE_SPINLOCK(slc90e66_lock);
 
 static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
@@ -132,7 +134,7 @@ static const struct ide_port_ops slc90e66_port_ops = {
 };
 
 static const struct ide_port_info slc90e66_chipset __devinitdata = {
-       .name           = "SLC90E66",
+       .name           = DRV_NAME,
        .enablebits     = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
        .port_ops       = &slc90e66_port_ops,
        .host_flags     = IDE_HFLAG_LEGACY_IRQS,
@@ -144,7 +146,7 @@ static const struct ide_port_info slc90e66_chipset __devinitdata = {
 
 static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &slc90e66_chipset);
+       return ide_pci_init_one(dev, &slc90e66_chipset, NULL);
 }
 
 static const struct pci_device_id slc90e66_pci_tbl[] = {
@@ -157,6 +159,7 @@ static struct pci_driver driver = {
        .name           = "SLC90e66_IDE",
        .id_table       = slc90e66_pci_tbl,
        .probe          = slc90e66_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init slc90e66_ide_init(void)
@@ -164,7 +167,13 @@ static int __init slc90e66_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit slc90e66_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(slc90e66_ide_init);
+module_exit(slc90e66_ide_exit);
 
 MODULE_AUTHOR("Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE");
index 477e1979010230d4f1662af093b535520d9ccd95..b1cb8a9ce5a92fc9f6a5711b4cb143b24ea2a285 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/pci.h>
 #include <linux/ide.h>
 
+#define DRV_NAME "tc86c001"
+
 static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
 {
        ide_hwif_t *hwif        = HWIF(drive);
@@ -173,16 +175,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
        hwif->rqsize     = 0xffff;
 }
 
-static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
-                                                       const char *name)
-{
-       int err = pci_request_region(dev, 5, name);
-
-       if (err)
-               printk(KERN_ERR "%s: system control regs already in use", name);
-       return err;
-}
-
 static const struct ide_port_ops tc86c001_port_ops = {
        .set_pio_mode           = tc86c001_set_pio_mode,
        .set_dma_mode           = tc86c001_set_mode,
@@ -201,8 +193,7 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
 };
 
 static const struct ide_port_info tc86c001_chipset __devinitdata = {
-       .name           = "TC86C001",
-       .init_chipset   = init_chipset_tc86c001,
+       .name           = DRV_NAME,
        .init_hwif      = init_hwif_tc86c001,
        .port_ops       = &tc86c001_port_ops,
        .dma_ops        = &tc86c001_dma_ops,
@@ -215,7 +206,37 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = {
 static int __devinit tc86c001_init_one(struct pci_dev *dev,
                                       const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &tc86c001_chipset);
+       int rc;
+
+       rc = pci_enable_device(dev);
+       if (rc)
+               goto out;
+
+       rc = pci_request_region(dev, 5, DRV_NAME);
+       if (rc) {
+               printk(KERN_ERR DRV_NAME ": system control regs already in use");
+               goto out_disable;
+       }
+
+       rc = ide_pci_init_one(dev, &tc86c001_chipset, NULL);
+       if (rc)
+               goto out_release;
+
+       goto out;
+
+out_release:
+       pci_release_region(dev, 5);
+out_disable:
+       pci_disable_device(dev);
+out:
+       return rc;
+}
+
+static void __devexit tc86c001_remove(struct pci_dev *dev)
+{
+       ide_pci_remove(dev);
+       pci_release_region(dev, 5);
+       pci_disable_device(dev);
 }
 
 static const struct pci_device_id tc86c001_pci_tbl[] = {
@@ -227,14 +248,22 @@ MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
 static struct pci_driver driver = {
        .name           = "TC86C001",
        .id_table       = tc86c001_pci_tbl,
-       .probe          = tc86c001_init_one
+       .probe          = tc86c001_init_one,
+       .remove         = tc86c001_remove,
 };
 
 static int __init tc86c001_ide_init(void)
 {
        return ide_pci_register_driver(&driver);
 }
+
+static void __exit tc86c001_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(tc86c001_ide_init);
+module_exit(tc86c001_ide_exit);
 
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
 MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE");
index db65a558d4eca62b26bff026d5c6fa3682d69555..b77ec35151b34dec10d691fa57f780faacef1430 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
+#define DRV_NAME "triflex"
+
 static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
 {
        ide_hwif_t *hwif = HWIF(drive);
@@ -93,7 +95,7 @@ static const struct ide_port_ops triflex_port_ops = {
 };
 
 static const struct ide_port_info triflex_device __devinitdata = {
-       .name           = "TRIFLEX",
+       .name           = DRV_NAME,
        .enablebits     = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
        .port_ops       = &triflex_port_ops,
        .pio_mask       = ATA_PIO4,
@@ -104,7 +106,7 @@ static const struct ide_port_info triflex_device __devinitdata = {
 static int __devinit triflex_init_one(struct pci_dev *dev, 
                const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &triflex_device);
+       return ide_pci_init_one(dev, &triflex_device, NULL);
 }
 
 static const struct pci_device_id triflex_pci_tbl[] = {
@@ -117,6 +119,7 @@ static struct pci_driver driver = {
        .name           = "TRIFLEX_IDE",
        .id_table       = triflex_pci_tbl,
        .probe          = triflex_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init triflex_ide_init(void)
@@ -124,7 +127,13 @@ static int __init triflex_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit triflex_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(triflex_ide_init);
+module_exit(triflex_ide_exit);
 
 MODULE_AUTHOR("Torben Mathiasen");
 MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
index a8a3138682eff4841ac9784a4cce9d46f3ba1a89..fd28b49977fd1e34d5fc9489bb4247e571857dd7 100644 (file)
 
 #include <asm/io.h>
 
+#define DRV_NAME "trm290"
+
 static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 {
        ide_hwif_t *hwif = HWIF(drive);
@@ -245,10 +247,10 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
        u8 reg = 0;
 
        if ((dev->class & 5) && cfg_base)
-               printk(KERN_INFO "TRM290: chip");
+               printk(KERN_INFO DRV_NAME " %s: chip", pci_name(dev));
        else {
                cfg_base = 0x3df0;
-               printk(KERN_INFO "TRM290: using default");
+               printk(KERN_INFO DRV_NAME " %s: using default", pci_name(dev));
        }
        printk(KERN_CONT " config base at 0x%04x\n", cfg_base);
        hwif->config_data = cfg_base;
@@ -325,7 +327,7 @@ static struct ide_dma_ops trm290_dma_ops = {
 };
 
 static const struct ide_port_info trm290_chipset __devinitdata = {
-       .name           = "TRM290",
+       .name           = DRV_NAME,
        .init_hwif      = init_hwif_trm290,
        .chipset        = ide_trm290,
        .port_ops       = &trm290_port_ops,
@@ -340,7 +342,7 @@ static const struct ide_port_info trm290_chipset __devinitdata = {
 
 static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &trm290_chipset);
+       return ide_pci_init_one(dev, &trm290_chipset, NULL);
 }
 
 static const struct pci_device_id trm290_pci_tbl[] = {
@@ -353,6 +355,7 @@ static struct pci_driver driver = {
        .name           = "TRM290_IDE",
        .id_table       = trm290_pci_tbl,
        .probe          = trm290_init_one,
+       .remove         = ide_pci_remove,
 };
 
 static int __init trm290_ide_init(void)
@@ -360,7 +363,13 @@ static int __init trm290_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit trm290_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(trm290_ide_init);
+module_exit(trm290_ide_exit);
 
 MODULE_AUTHOR("Mark Lord");
 MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE");
index 09dc4803ef9d282c528240dee980f4d55f080a79..454d2bf62dce90c498caf03b6fe22477dcf7a51d 100644 (file)
@@ -35,6 +35,8 @@
 #include <asm/processor.h>
 #endif
 
+#define DRV_NAME "via82cxxx"
+
 #define VIA_IDE_ENABLE         0x40
 #define VIA_IDE_CONFIG         0x41
 #define VIA_FIFO_CONFIG                0x43
@@ -113,7 +115,8 @@ struct via82cxxx_dev
 static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct via82cxxx_dev *vdev = host->host_priv;
        u8 t;
 
        if (~vdev->via_config->flags & VIA_BAD_AST) {
@@ -153,7 +156,8 @@ static void via_set_drive(ide_drive_t *drive, const u8 speed)
        ide_hwif_t *hwif = drive->hwif;
        ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct via82cxxx_dev *vdev = host->host_priv;
        struct ide_timing t, p;
        unsigned int T, UT;
 
@@ -258,37 +262,19 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
 /**
  *     init_chipset_via82cxxx  -       initialization handler
  *     @dev: PCI device
- *     @name: Name of interface
  *
  *     The initialization callback. Here we determine the IDE chip type
  *     and initialize its drive independent registers.
  */
 
-static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev)
 {
-       struct pci_dev *isa = NULL;
-       struct via82cxxx_dev *vdev;
-       struct via_isa_bridge *via_config;
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct via82cxxx_dev *vdev = host->host_priv;
+       struct via_isa_bridge *via_config = vdev->via_config;
        u8 t, v;
        u32 u;
 
-       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
-       if (!vdev) {
-               printk(KERN_ERR "VP_IDE: out of memory :(\n");
-               return -ENOMEM;
-       }
-       pci_set_drvdata(dev, vdev);
-
-       /*
-        * Find the ISA bridge to see how good the IDE is.
-        */
-       vdev->via_config = via_config = via_config_find(&isa);
-
-       /* We checked this earlier so if it fails here deeep badness
-          is involved */
-
-       BUG_ON(!via_config->id);
-
        /*
         * Detect cable and configure Clk66
         */
@@ -334,39 +320,6 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
 
        pci_write_config_byte(dev, VIA_FIFO_CONFIG, t);
 
-       /*
-        * Determine system bus clock.
-        */
-
-       via_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
-
-       switch (via_clock) {
-               case 33000: via_clock = 33333; break;
-               case 37000: via_clock = 37500; break;
-               case 41000: via_clock = 41666; break;
-       }
-
-       if (via_clock < 20000 || via_clock > 50000) {
-               printk(KERN_WARNING "VP_IDE: User given PCI clock speed "
-                       "impossible (%d), using 33 MHz instead.\n", via_clock);
-               printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want "
-                       "to assume 80-wire cable.\n");
-               via_clock = 33333;
-       }
-
-       /*
-        * Print the boot message.
-        */
-
-       printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %sDMA%s "
-               "controller on pci%s\n",
-               via_config->name, isa->revision,
-               via_config->udma_mask ? "U" : "MW",
-               via_dma[via_config->udma_mask ?
-                       (fls(via_config->udma_mask) - 1) : 0],
-               pci_name(dev));
-
-       pci_dev_put(isa);
        return 0;
 }
 
@@ -402,7 +355,8 @@ static int via_cable_override(struct pci_dev *pdev)
 static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev *pdev = to_pci_dev(hwif->dev);
-       struct via82cxxx_dev *vdev = pci_get_drvdata(pdev);
+       struct ide_host *host = pci_get_drvdata(pdev);
+       struct via82cxxx_dev *vdev = host->host_priv;
 
        if (via_cable_override(pdev))
                return ATA_CBL_PATA40_SHORT;
@@ -420,7 +374,7 @@ static const struct ide_port_ops via_port_ops = {
 };
 
 static const struct ide_port_info via82cxxx_chipset __devinitdata = {
-       .name           = "VP_IDE",
+       .name           = DRV_NAME,
        .init_chipset   = init_chipset_via82cxxx,
        .enablebits     = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
        .port_ops       = &via_port_ops,
@@ -436,6 +390,8 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
 {
        struct pci_dev *isa = NULL;
        struct via_isa_bridge *via_config;
+       struct via82cxxx_dev *vdev;
+       int rc;
        u8 idx = id->driver_data;
        struct ide_port_info d;
 
@@ -445,12 +401,42 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
         * Find the ISA bridge and check we know what it is.
         */
        via_config = via_config_find(&isa);
-       pci_dev_put(isa);
        if (!via_config->id) {
-               printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n");
+               printk(KERN_WARNING DRV_NAME " %s: unknown chipset, skipping\n",
+                       pci_name(dev));
                return -ENODEV;
        }
 
+       /*
+        * Print the boot message.
+        */
+       printk(KERN_INFO DRV_NAME " %s: VIA %s (rev %02x) IDE %sDMA%s\n",
+               pci_name(dev), via_config->name, isa->revision,
+               via_config->udma_mask ? "U" : "MW",
+               via_dma[via_config->udma_mask ?
+                       (fls(via_config->udma_mask) - 1) : 0]);
+
+       pci_dev_put(isa);
+
+       /*
+        * Determine system bus clock.
+        */
+       via_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
+
+       switch (via_clock) {
+       case 33000: via_clock = 33333; break;
+       case 37000: via_clock = 37500; break;
+       case 41000: via_clock = 41666; break;
+       }
+
+       if (via_clock < 20000 || via_clock > 50000) {
+               printk(KERN_WARNING DRV_NAME ": User given PCI clock speed "
+                       "impossible (%d), using 33 MHz instead.\n", via_clock);
+               printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want "
+                       "to assume 80-wire cable.\n");
+               via_clock = 33333;
+       }
+
        if (idx == 0)
                d.host_flags |= IDE_HFLAG_NO_AUTODMA;
        else
@@ -466,7 +452,29 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
 
        d.udma_mask = via_config->udma_mask;
 
-       return ide_setup_pci_device(dev, &d);
+       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+       if (!vdev) {
+               printk(KERN_ERR DRV_NAME " %s: out of memory :(\n",
+                       pci_name(dev));
+               return -ENOMEM;
+       }
+
+       vdev->via_config = via_config;
+
+       rc = ide_pci_init_one(dev, &d, vdev);
+       if (rc)
+               kfree(vdev);
+
+       return rc;
+}
+
+static void __devexit via_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct via82cxxx_dev *vdev = host->host_priv;
+
+       ide_pci_remove(dev);
+       kfree(vdev);
 }
 
 static const struct pci_device_id via_pci_tbl[] = {
@@ -483,6 +491,7 @@ static struct pci_driver driver = {
        .name           = "VIA_IDE",
        .id_table       = via_pci_tbl,
        .probe          = via_init_one,
+       .remove         = via_remove,
 };
 
 static int __init via_ide_init(void)
@@ -490,7 +499,13 @@ static int __init via_ide_init(void)
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit via_ide_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
 module_init(via_ide_init);
+module_exit(via_ide_exit);
 
 MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for VIA IDE");
index b15cad58dc81ea781b4ac7b366759d6ab3de20e8..a8e9e8a69a525a2b3f162b32348c44577ad83125 100644 (file)
@@ -39,17 +39,18 @@ static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
        if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
                         (progif & 5) != 5) {
                if ((progif & 0xa) != 0xa) {
-                       printk(KERN_INFO "%s: device not capable of full "
-                               "native PCI mode\n", name);
+                       printk(KERN_INFO "%s %s: device not capable of full "
+                               "native PCI mode\n", name, pci_name(dev));
                        return -EOPNOTSUPP;
                }
-               printk("%s: placing both ports into native PCI mode\n", name);
+               printk(KERN_INFO "%s %s: placing both ports into native PCI "
+                       "mode\n", name, pci_name(dev));
                (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
                if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
                    (progif & 5) != 5) {
-                       printk(KERN_ERR "%s: rewrite of PROGIF failed, wanted "
-                               "0x%04x, got 0x%04x\n",
-                               name, progif|5, progif);
+                       printk(KERN_ERR "%s %s: rewrite of PROGIF failed, "
+                               "wanted 0x%04x, got 0x%04x\n",
+                               name, pci_name(dev), progif | 5, progif);
                        return -EOPNOTSUPP;
                }
        }
@@ -57,14 +58,14 @@ static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
+static int ide_pci_clear_simplex(unsigned long dma_base, const char *name)
 {
        u8 dma_stat = inb(dma_base + 2);
 
        outb(dma_stat & 0x60, dma_base + 2);
        dma_stat = inb(dma_base + 2);
-       if (dma_stat & 0x80)
-               printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
+
+       return (dma_stat & 0x80) ? 1 : 0;
 }
 
 /**
@@ -91,7 +92,8 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
                dma_base = pci_resource_start(dev, baridx);
 
                if (dma_base == 0) {
-                       printk(KERN_ERR "%s: DMA base is invalid\n", d->name);
+                       printk(KERN_ERR "%s %s: DMA base is invalid\n",
+                               d->name, pci_name(dev));
                        return 0;
                }
        }
@@ -105,13 +107,16 @@ EXPORT_SYMBOL_GPL(ide_pci_dma_base);
 
 int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
        u8 dma_stat;
 
        if (d->host_flags & (IDE_HFLAG_MMIO | IDE_HFLAG_CS5520))
                goto out;
 
        if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
-               ide_pci_clear_simplex(hwif->dma_base, d->name);
+               if (ide_pci_clear_simplex(hwif->dma_base, d->name))
+                       printk(KERN_INFO "%s %s: simplex device: DMA forced\n",
+                               d->name, pci_name(dev));
                goto out;
        }
 
@@ -127,7 +132,8 @@ int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d)
         */
        dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
        if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
-               printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
+               printk(KERN_INFO "%s %s: simplex device: DMA disabled\n",
+                       d->name, pci_name(dev));
                return -1;
        }
 out:
@@ -149,8 +155,8 @@ int ide_pci_set_master(struct pci_dev *dev, const char *name)
 
                if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) ||
                    (pcicmd & PCI_COMMAND_MASTER) == 0) {
-                       printk(KERN_ERR "%s: error updating PCICMD on %s\n",
-                                       name, pci_name(dev));
+                       printk(KERN_ERR "%s %s: error updating PCICMD\n",
+                               name, pci_name(dev));
                        return -EIO;
                }
        }
@@ -162,9 +168,9 @@ EXPORT_SYMBOL_GPL(ide_pci_set_master);
 
 void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
 {
-       printk(KERN_INFO "%s: IDE controller (0x%04x:0x%04x rev 0x%02x) at "
-                        " PCI slot %s\n", d->name, dev->vendor, dev->device,
-                        dev->revision, pci_name(dev));
+       printk(KERN_INFO "%s %s: IDE controller (0x%04x:0x%04x rev 0x%02x)\n",
+               d->name, pci_name(dev),
+               dev->vendor, dev->device, dev->revision);
 }
 EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
 
@@ -189,11 +195,12 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
        if (pci_enable_device(dev)) {
                ret = pci_enable_device_io(dev);
                if (ret < 0) {
-                       printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
-                               "Could not enable device.\n", d->name);
+                       printk(KERN_WARNING "%s %s: couldn't enable device\n",
+                               d->name, pci_name(dev));
                        goto out;
                }
-               printk(KERN_WARNING "%s: BIOS configuration fixed.\n", d->name);
+               printk(KERN_WARNING "%s %s: BIOS configuration fixed\n",
+                       d->name, pci_name(dev));
        }
 
        /*
@@ -203,7 +210,8 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
         */
        ret = pci_set_dma_mask(dev, DMA_32BIT_MASK);
        if (ret < 0) {
-               printk(KERN_ERR "%s: can't set dma mask\n", d->name);
+               printk(KERN_ERR "%s %s: can't set DMA mask\n",
+                       d->name, pci_name(dev));
                goto out;
        }
 
@@ -221,7 +229,8 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
 
        ret = pci_request_selected_regions(dev, bars, d->name);
        if (ret < 0)
-               printk(KERN_ERR "%s: can't reserve resources\n", d->name);
+               printk(KERN_ERR "%s %s: can't reserve resources\n",
+                       d->name, pci_name(dev));
 out:
        return ret;
 }
@@ -247,15 +256,18 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
         */
        if (ide_setup_pci_baseregs(dev, d->name) ||
            pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
-               printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name);
+               printk(KERN_INFO "%s %s: device disabled (BIOS)\n",
+                       d->name, pci_name(dev));
                return -ENODEV;
        }
        if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
-               printk(KERN_ERR "%s: error accessing PCI regs\n", d->name);
+               printk(KERN_ERR "%s %s: error accessing PCI regs\n",
+                       d->name, pci_name(dev));
                return -EIO;
        }
        if (!(pcicmd & PCI_COMMAND_IO)) {
-               printk(KERN_ERR "%s: unable to enable IDE controller\n", d->name);
+               printk(KERN_ERR "%s %s: unable to enable IDE controller\n",
+                       d->name, pci_name(dev));
                return -ENXIO;
        }
        return 0;
@@ -311,8 +323,9 @@ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
        if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
                if (ide_pci_check_iomem(dev, d, 2 * port) ||
                    ide_pci_check_iomem(dev, d, 2 * port + 1)) {
-                       printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported "
-                                       "as MEM for port %d!\n", d->name, port);
+                       printk(KERN_ERR "%s %s: I/O baseregs (BIOS) are "
+                               "reported as MEM for port %d!\n",
+                               d->name, pci_name(dev), port);
                        return -EINVAL;
                }
 
@@ -325,8 +338,8 @@ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
        }
 
        if (!base || !ctl) {
-               printk(KERN_ERR "%s: bad PCI BARs for port %d, skipping\n",
-                               d->name, port);
+               printk(KERN_ERR "%s %s: bad PCI BARs for port %d, skipping\n",
+                       d->name, pci_name(dev), port);
                return -EINVAL;
        }
 
@@ -393,14 +406,14 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
  *     @dev: PCI device
  *     @d: IDE port info
  *     @noisy: verbose flag
- *     @config: returned as 1 if we configured the hardware
  *
  *     Set up the PCI and controller side of the IDE interface. This brings
  *     up the PCI side of the device, checks that the device is enabled
  *     and enables it if need be
  */
 
-static int ide_setup_pci_controller(struct pci_dev *dev, const struct ide_port_info *d, int noisy, int *config)
+static int ide_setup_pci_controller(struct pci_dev *dev,
+                                   const struct ide_port_info *d, int noisy)
 {
        int ret;
        u16 pcicmd;
@@ -414,15 +427,16 @@ static int ide_setup_pci_controller(struct pci_dev *dev, const struct ide_port_i
 
        ret = pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
        if (ret < 0) {
-               printk(KERN_ERR "%s: error accessing PCI regs\n", d->name);
+               printk(KERN_ERR "%s %s: error accessing PCI regs\n",
+                       d->name, pci_name(dev));
                goto out;
        }
        if (!(pcicmd & PCI_COMMAND_IO)) {       /* is device disabled? */
                ret = ide_pci_configure(dev, d);
                if (ret < 0)
                        goto out;
-               *config = 1;
-               printk(KERN_INFO "%s: device enabled (Linux)\n", d->name);
+               printk(KERN_INFO "%s %s: device enabled (Linux)\n",
+                       d->name, pci_name(dev));
        }
 
 out:
@@ -461,7 +475,8 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
 
                if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
                    (tmp & e->mask) != e->val)) {
-                       printk(KERN_INFO "%s: IDE port disabled\n", d->name);
+                       printk(KERN_INFO "%s %s: IDE port disabled\n",
+                               d->name, pci_name(dev));
                        continue;       /* port not enabled */
                }
 
@@ -487,51 +502,35 @@ static int do_ide_setup_pci_device(struct pci_dev *dev,
                                   const struct ide_port_info *d,
                                   u8 noisy)
 {
-       int tried_config = 0;
        int pciirq, ret;
 
-       ret = ide_setup_pci_controller(dev, d, noisy, &tried_config);
-       if (ret < 0)
-               goto out;
-
        /*
         * Can we trust the reported IRQ?
         */
        pciirq = dev->irq;
 
+       /*
+        * This allows offboard ide-pci cards the enable a BIOS,
+        * verify interrupt settings of split-mirror pci-config
+        * space, place chipset into init-mode, and/or preserve
+        * an interrupt if the card is not native ide support.
+        */
+       ret = d->init_chipset ? d->init_chipset(dev) : 0;
+       if (ret < 0)
+               goto out;
+
        /* Is it an "IDE storage" device in non-PCI mode? */
        if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 5) != 5) {
                if (noisy)
-                       printk(KERN_INFO "%s: not 100%% native mode: "
-                               "will probe irqs later\n", d->name);
-               /*
-                * This allows offboard ide-pci cards the enable a BIOS,
-                * verify interrupt settings of split-mirror pci-config
-                * space, place chipset into init-mode, and/or preserve
-                * an interrupt if the card is not native ide support.
-                */
-               ret = d->init_chipset ? d->init_chipset(dev, d->name) : 0;
-               if (ret < 0)
-                       goto out;
+                       printk(KERN_INFO "%s %s: not 100%% native mode: will "
+                               "probe irqs later\n", d->name, pci_name(dev));
                pciirq = ret;
-       } else if (tried_config) {
-               if (noisy)
-                       printk(KERN_INFO "%s: will probe irqs later\n", d->name);
-               pciirq = 0;
-       } else if (!pciirq) {
-               if (noisy)
-                       printk(KERN_WARNING "%s: bad irq (%d): will probe later\n",
-                               d->name, pciirq);
-               pciirq = 0;
-       } else {
-               if (d->init_chipset) {
-                       ret = d->init_chipset(dev, d->name);
-                       if (ret < 0)
-                               goto out;
-               }
-               if (noisy)
-                       printk(KERN_INFO "%s: 100%% native mode on irq %d\n",
-                               d->name, pciirq);
+       } else if (!pciirq && noisy) {
+               printk(KERN_WARNING "%s %s: bad irq (%d): will probe later\n",
+                       d->name, pci_name(dev), pciirq);
+       } else if (noisy) {
+               printk(KERN_INFO "%s %s: 100%% native mode on irq %d\n",
+                       d->name, pci_name(dev), pciirq);
        }
 
        ret = pciirq;
@@ -539,31 +538,76 @@ out:
        return ret;
 }
 
-int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
+int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d,
+                    void *priv)
 {
+       struct ide_host *host;
        hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
        int ret;
 
-       ret = do_ide_setup_pci_device(dev, d, 1);
+       ret = ide_setup_pci_controller(dev, d, 1);
+       if (ret < 0)
+               goto out;
 
-       if (ret >= 0) {
-               /* FIXME: silent failure can happen */
-               ide_pci_setup_ports(dev, d, ret, &hw[0], &hws[0]);
+       ide_pci_setup_ports(dev, d, 0, &hw[0], &hws[0]);
 
-               ret = ide_host_add(d, hws, NULL);
+       host = ide_host_alloc(d, hws);
+       if (host == NULL) {
+               ret = -ENOMEM;
+               goto out;
        }
 
+       host->dev[0] = &dev->dev;
+
+       host->host_priv = priv;
+
+       pci_set_drvdata(dev, host);
+
+       ret = do_ide_setup_pci_device(dev, d, 1);
+       if (ret < 0)
+               goto out;
+
+       /* fixup IRQ */
+       hw[1].irq = hw[0].irq = ret;
+
+       ret = ide_host_register(host, d, hws);
+       if (ret)
+               ide_host_free(host);
+out:
        return ret;
 }
-EXPORT_SYMBOL_GPL(ide_setup_pci_device);
+EXPORT_SYMBOL_GPL(ide_pci_init_one);
 
-int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
-                         const struct ide_port_info *d)
+int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
+                    const struct ide_port_info *d, void *priv)
 {
        struct pci_dev *pdev[] = { dev1, dev2 };
+       struct ide_host *host;
        int ret, i;
        hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
 
+       for (i = 0; i < 2; i++) {
+               ret = ide_setup_pci_controller(pdev[i], d, !i);
+               if (ret < 0)
+                       goto out;
+
+               ide_pci_setup_ports(pdev[i], d, 0, &hw[i*2], &hws[i*2]);
+       }
+
+       host = ide_host_alloc(d, hws);
+       if (host == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       host->dev[0] = &dev1->dev;
+       host->dev[1] = &dev2->dev;
+
+       host->host_priv = priv;
+
+       pci_set_drvdata(pdev[0], host);
+       pci_set_drvdata(pdev[1], host);
+
        for (i = 0; i < 2; i++) {
                ret = do_ide_setup_pci_device(pdev[i], d, !i);
 
@@ -574,12 +618,44 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
                if (ret < 0)
                        goto out;
 
-               /* FIXME: silent failure can happen */
-               ide_pci_setup_ports(pdev[i], d, ret, &hw[i*2], &hws[i*2]);
+               /* fixup IRQ */
+               hw[i*2 + 1].irq = hw[i*2].irq = ret;
        }
 
-       ret = ide_host_add(d, hws, NULL);
+       ret = ide_host_register(host, d, hws);
+       if (ret)
+               ide_host_free(host);
 out:
        return ret;
 }
-EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
+EXPORT_SYMBOL_GPL(ide_pci_init_two);
+
+void ide_pci_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+       int bars;
+
+       if (host->host_flags & IDE_HFLAG_SINGLE)
+               bars = (1 << 2) - 1;
+       else
+               bars = (1 << 4) - 1;
+
+       if ((host->host_flags & IDE_HFLAG_NO_DMA) == 0) {
+               if (host->host_flags & IDE_HFLAG_CS5520)
+                       bars |= (1 << 2);
+               else
+                       bars |= (1 << 4);
+       }
+
+       ide_host_remove(host);
+
+       if (dev2)
+               pci_release_selected_regions(dev2, bars);
+       pci_release_selected_regions(dev, bars);
+
+       if (dev2)
+               pci_disable_device(dev2);
+       pci_disable_device(dev);
+}
+EXPORT_SYMBOL_GPL(ide_pci_remove);
index 07ca35c98f96f8557b222db17763b03083f2e849..1cf6487b65ba8ce9c2b042d0dc5bcbcf03369f50 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/pci.h>
 #include <linux/sched.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
 
 #include "hosts.h"
index ae11d5cc74d07f099cca4951b471c0850d39b126..e980ff3335db6470fe0c0f2c2b0c17f9fbe1d401 100644 (file)
@@ -168,6 +168,12 @@ struct cma_work {
        struct rdma_cm_event    event;
 };
 
+struct cma_ndev_work {
+       struct work_struct      work;
+       struct rdma_id_private  *id;
+       struct rdma_cm_event    event;
+};
+
 union cma_ip_addr {
        struct in6_addr ip6;
        struct {
@@ -914,7 +920,10 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
        struct rdma_cm_event event;
        int ret = 0;
 
-       if (cma_disable_callback(id_priv, CMA_CONNECT))
+       if ((ib_event->event != IB_CM_TIMEWAIT_EXIT &&
+               cma_disable_callback(id_priv, CMA_CONNECT)) ||
+           (ib_event->event == IB_CM_TIMEWAIT_EXIT &&
+               cma_disable_callback(id_priv, CMA_DISCONNECT)))
                return 0;
 
        memset(&event, 0, sizeof event);
@@ -950,6 +959,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
                event.event = RDMA_CM_EVENT_DISCONNECTED;
                break;
        case IB_CM_TIMEWAIT_EXIT:
+               event.event = RDMA_CM_EVENT_TIMEWAIT_EXIT;
+               break;
        case IB_CM_MRA_RECEIVED:
                /* ignore event */
                goto out;
@@ -1598,6 +1609,30 @@ out:
        kfree(work);
 }
 
+static void cma_ndev_work_handler(struct work_struct *_work)
+{
+       struct cma_ndev_work *work = container_of(_work, struct cma_ndev_work, work);
+       struct rdma_id_private *id_priv = work->id;
+       int destroy = 0;
+
+       mutex_lock(&id_priv->handler_mutex);
+       if (id_priv->state == CMA_DESTROYING ||
+           id_priv->state == CMA_DEVICE_REMOVAL)
+               goto out;
+
+       if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
+               cma_exch(id_priv, CMA_DESTROYING);
+               destroy = 1;
+       }
+
+out:
+       mutex_unlock(&id_priv->handler_mutex);
+       cma_deref_id(id_priv);
+       if (destroy)
+               rdma_destroy_id(&id_priv->id);
+       kfree(work);
+}
+
 static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
 {
        struct rdma_route *route = &id_priv->id.route;
@@ -2723,6 +2758,65 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
 }
 EXPORT_SYMBOL(rdma_leave_multicast);
 
+static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id_priv)
+{
+       struct rdma_dev_addr *dev_addr;
+       struct cma_ndev_work *work;
+
+       dev_addr = &id_priv->id.route.addr.dev_addr;
+
+       if ((dev_addr->src_dev == ndev) &&
+           memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) {
+               printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
+                      ndev->name, &id_priv->id);
+               work = kzalloc(sizeof *work, GFP_KERNEL);
+               if (!work)
+                       return -ENOMEM;
+
+               INIT_WORK(&work->work, cma_ndev_work_handler);
+               work->id = id_priv;
+               work->event.event = RDMA_CM_EVENT_ADDR_CHANGE;
+               atomic_inc(&id_priv->refcount);
+               queue_work(cma_wq, &work->work);
+       }
+
+       return 0;
+}
+
+static int cma_netdev_callback(struct notifier_block *self, unsigned long event,
+                              void *ctx)
+{
+       struct net_device *ndev = (struct net_device *)ctx;
+       struct cma_device *cma_dev;
+       struct rdma_id_private *id_priv;
+       int ret = NOTIFY_DONE;
+
+       if (dev_net(ndev) != &init_net)
+               return NOTIFY_DONE;
+
+       if (event != NETDEV_BONDING_FAILOVER)
+               return NOTIFY_DONE;
+
+       if (!(ndev->flags & IFF_MASTER) || !(ndev->priv_flags & IFF_BONDING))
+               return NOTIFY_DONE;
+
+       mutex_lock(&lock);
+       list_for_each_entry(cma_dev, &dev_list, list)
+               list_for_each_entry(id_priv, &cma_dev->id_list, list) {
+                       ret = cma_netdev_change(ndev, id_priv);
+                       if (ret)
+                               goto out;
+               }
+
+out:
+       mutex_unlock(&lock);
+       return ret;
+}
+
+static struct notifier_block cma_nb = {
+       .notifier_call = cma_netdev_callback
+};
+
 static void cma_add_one(struct ib_device *device)
 {
        struct cma_device *cma_dev;
@@ -2831,6 +2925,7 @@ static int cma_init(void)
 
        ib_sa_register_client(&sa_client);
        rdma_addr_register_client(&addr_client);
+       register_netdevice_notifier(&cma_nb);
 
        ret = ib_register_client(&cma_client);
        if (ret)
@@ -2838,6 +2933,7 @@ static int cma_init(void)
        return 0;
 
 err:
+       unregister_netdevice_notifier(&cma_nb);
        rdma_addr_unregister_client(&addr_client);
        ib_sa_unregister_client(&sa_client);
        destroy_workqueue(cma_wq);
@@ -2847,6 +2943,7 @@ err:
 static void cma_cleanup(void)
 {
        ib_unregister_client(&cma_client);
+       unregister_netdevice_notifier(&cma_nb);
        rdma_addr_unregister_client(&addr_client);
        ib_sa_unregister_client(&sa_client);
        destroy_workqueue(cma_wq);
index 81c9195b512a1e5d63ae610bb3961e14a097f49e..8f9509e1ebf76494217b7d48f6b7bdef307ac3b4 100644 (file)
@@ -942,8 +942,7 @@ static int iwcm_init_qp_init_attr(struct iwcm_id_private *cm_id_priv,
        case IW_CM_STATE_CONN_RECV:
        case IW_CM_STATE_ESTABLISHED:
                *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
-               qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
-                                          IB_ACCESS_REMOTE_WRITE|
+               qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE|
                                           IB_ACCESS_REMOTE_READ;
                ret = 0;
                break;
index 1341de793e51d0694d45501c9e54bf4128ba982e..7863a50d56f25cd8a465fcff0b4ebef6581a675f 100644 (file)
@@ -1064,7 +1064,8 @@ static void ib_sa_remove_one(struct ib_device *device)
 
        for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
                ib_unregister_mad_agent(sa_dev->port[i].agent);
-               kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+               if (sa_dev->port[i].sm_ah)
+                       kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
        }
 
        kfree(sa_dev);
index 9494005d1c9a62fe1463c94320af061f6ee1e40e..e603736682bfc6e52fbc6f4802375bd329aa7850 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/cdev.h>
 #include <linux/idr.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 
@@ -1154,11 +1153,18 @@ static unsigned int ib_ucm_poll(struct file *filp,
        return mask;
 }
 
+/*
+ * ib_ucm_open() does not need the BKL:
+ *
+ *  - no global state is referred to;
+ *  - there is no ioctl method to race against;
+ *  - no further module initialization is required for open to work
+ *    after the device is registered.
+ */
 static int ib_ucm_open(struct inode *inode, struct file *filp)
 {
        struct ib_ucm_file *file;
 
-       cycle_kernel_lock();
        file = kmalloc(sizeof(*file), GFP_KERNEL);
        if (!file)
                return -ENOMEM;
index 195f97302fe5243575d42abe3c990bdb4fa7d106..b41dd26bbfa1e1b83654c487d1ff16482bf3746d 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
 
 #include <rdma/rdma_user_cm.h>
 #include <rdma/ib_marshall.h>
@@ -1149,6 +1148,14 @@ static unsigned int ucma_poll(struct file *filp, struct poll_table_struct *wait)
        return mask;
 }
 
+/*
+ * ucma_open() does not need the BKL:
+ *
+ *  - no global state is referred to;
+ *  - there is no ioctl method to race against;
+ *  - no further module initialization is required for open to work
+ *    after the device is registered.
+ */
 static int ucma_open(struct inode *inode, struct file *filp)
 {
        struct ucma_file *file;
@@ -1157,7 +1164,6 @@ static int ucma_open(struct inode *inode, struct file *filp)
        if (!file)
                return -ENOMEM;
 
-       lock_kernel();
        INIT_LIST_HEAD(&file->event_list);
        INIT_LIST_HEAD(&file->ctx_list);
        init_waitqueue_head(&file->poll_wait);
@@ -1165,7 +1171,6 @@ static int ucma_open(struct inode *inode, struct file *filp)
 
        filp->private_data = file;
        file->filp = filp;
-       unlock_kernel();
        return 0;
 }
 
index 1e9e99a13933bd7dfa671cc8a125c9abddb526fc..0b0618edd64528b363fe7acb85fd2388adf8f812 100644 (file)
@@ -194,6 +194,7 @@ struct ehca_qp {
        u32 packet_count;
        atomic_t nr_events; /* events seen */
        wait_queue_head_t wait_completion;
+       int mig_armed;
 };
 
 #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
index bc3b37d2070f338b6a41003ad1e6a6c125e1d555..46288220cfbb1cc1d90916bdf9670316552e7c31 100644 (file)
@@ -114,7 +114,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
        }
 
        props->max_pkeys           = 16;
-       props->local_ca_ack_delay  = min_t(u8, rblock->local_ca_ack_delay, 255);
+       /* Some FW versions say 0 here; insert sensible value in that case */
+       props->local_ca_ack_delay  = rblock->local_ca_ack_delay ?
+               min_t(u8, rblock->local_ca_ack_delay, 255) : 12;
        props->max_raw_ipv6_qp     = limit_uint(rblock->max_raw_ipv6_qp);
        props->max_raw_ethy_qp     = limit_uint(rblock->max_raw_ethy_qp);
        props->max_mcast_grp       = limit_uint(rblock->max_mcast_grp);
index 7a64aa9b51b6e6bf3866ac72fba4899bb9fcd348..cb55be04442c615796fe67c78a822658c8aa0104 100644 (file)
@@ -178,6 +178,10 @@ static void dispatch_qp_event(struct ehca_shca *shca, struct ehca_qp *qp,
 {
        struct ib_event event;
 
+       /* PATH_MIG without the QP ever having been armed is false alarm */
+       if (event_type == IB_EVENT_PATH_MIG && !qp->mig_armed)
+               return;
+
        event.device = &shca->ib_device;
        event.event = event_type;
 
index 3f59587338ea5fc03a2404500f0d9633a468439f..ea13efddf175b818747af7db1f024da9e2384639 100644 (file)
@@ -1460,6 +1460,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
                        goto modify_qp_exit2;
                }
                mqpcb->path_migration_state = attr->path_mig_state + 1;
+               if (attr->path_mig_state == IB_MIG_REARM)
+                       my_qp->mig_armed = 1;
                update_mask |=
                        EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1);
        }
index 661f8db62706f32d71388d14fc9d977973ec9f69..c3a32846543127f67d740bb539aa265d3ab436f6 100644 (file)
@@ -163,6 +163,7 @@ static int alloc_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd)
 
 out:
        ehca_err(pd->ib_pd.device, "failed to allocate small queue page");
+       mutex_unlock(&pd->lock);
        return 0;
 }
 
index eaba03273e4febd20ca45ce88e3b63fbd7e83f40..284c9bca517e3bc7f55bd7661c3cb2a0ab7bfa7e 100644 (file)
@@ -698,7 +698,7 @@ retry:
 
        addr = dma_map_single(&dd->pcidev->dev, tx->txreq.map_addr,
                              tx->map_len, DMA_TO_DEVICE);
-       if (dma_mapping_error(addr)) {
+       if (dma_mapping_error(&dd->pcidev->dev, addr)) {
                ret = -EIO;
                goto unlock;
        }
index 86e016916cd1d473d60f74fe5be5544d89897e0e..82d9a0b5ca2fb06039398164f52d46efa1d8082d 100644 (file)
@@ -206,7 +206,7 @@ static int ipath_user_sdma_coalesce(const struct ipath_devdata *dd,
 
        dma_addr = dma_map_page(&dd->pcidev->dev, page, 0, len,
                                DMA_TO_DEVICE);
-       if (dma_mapping_error(dma_addr)) {
+       if (dma_mapping_error(&dd->pcidev->dev, dma_addr)) {
                ret = -ENOMEM;
                goto free_unmap;
        }
@@ -301,7 +301,7 @@ static int ipath_user_sdma_pin_pages(const struct ipath_devdata *dd,
                                     pages[j], 0, flen, DMA_TO_DEVICE);
                unsigned long fofs = addr & ~PAGE_MASK;
 
-               if (dma_mapping_error(dma_addr)) {
+               if (dma_mapping_error(&dd->pcidev->dev, dma_addr)) {
                        ret = -ENOMEM;
                        goto done;
                }
@@ -508,7 +508,7 @@ static int ipath_user_sdma_queue_pkts(const struct ipath_devdata *dd,
                if (page) {
                        dma_addr = dma_map_page(&dd->pcidev->dev,
                                                page, 0, len, DMA_TO_DEVICE);
-                       if (dma_mapping_error(dma_addr)) {
+                       if (dma_mapping_error(&dd->pcidev->dev, dma_addr)) {
                                ret = -ENOMEM;
                                goto free_pbc;
                        }
index 299f20832ab64aaed174b67b3047710e74d95354..a1464574bfdde532d8f6e19c6818fdc68d4f0876 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -637,6 +638,7 @@ repoll:
                case MLX4_OPCODE_SEND_IMM:
                        wc->wc_flags |= IB_WC_WITH_IMM;
                case MLX4_OPCODE_SEND:
+               case MLX4_OPCODE_SEND_INVAL:
                        wc->opcode    = IB_WC_SEND;
                        break;
                case MLX4_OPCODE_RDMA_READ:
@@ -657,6 +659,12 @@ repoll:
                case MLX4_OPCODE_LSO:
                        wc->opcode    = IB_WC_LSO;
                        break;
+               case MLX4_OPCODE_FMR:
+                       wc->opcode    = IB_WC_FAST_REG_MR;
+                       break;
+               case MLX4_OPCODE_LOCAL_INVAL:
+                       wc->opcode    = IB_WC_LOCAL_INV;
+                       break;
                }
        } else {
                wc->byte_len = be32_to_cpu(cqe->byte_cnt);
@@ -667,6 +675,11 @@ repoll:
                        wc->wc_flags    = IB_WC_WITH_IMM;
                        wc->ex.imm_data = cqe->immed_rss_invalid;
                        break;
+               case MLX4_RECV_OPCODE_SEND_INVAL:
+                       wc->opcode      = IB_WC_RECV;
+                       wc->wc_flags    = IB_WC_WITH_INVALIDATE;
+                       wc->ex.invalidate_rkey = be32_to_cpu(cqe->immed_rss_invalid);
+                       break;
                case MLX4_RECV_OPCODE_SEND:
                        wc->opcode   = IB_WC_RECV;
                        wc->wc_flags = 0;
index bcf50648fa18631e77ae0e80d50846dcabd31ad3..a3c2851c0545dcaf44eab62e9e7e4ed0bf4674e4 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -104,6 +105,12 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
                props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
        if (dev->dev->caps.max_gso_sz)
                props->device_cap_flags |= IB_DEVICE_UD_TSO;
+       if (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_RESERVED_LKEY)
+               props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY;
+       if ((dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_LOCAL_INV) &&
+           (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
+           (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
+               props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
 
        props->vendor_id           = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
                0xffffff;
@@ -127,6 +134,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
        props->max_srq             = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs;
        props->max_srq_wr          = dev->dev->caps.max_srq_wqes - 1;
        props->max_srq_sge         = dev->dev->caps.max_srq_sge;
+       props->max_fast_reg_page_list_len = PAGE_SIZE / sizeof (u64);
        props->local_ca_ack_delay  = dev->dev->caps.local_ca_ack_delay;
        props->atomic_cap          = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ?
                IB_ATOMIC_HCA : IB_ATOMIC_NONE;
@@ -565,6 +573,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX);
        ibdev->ib_dev.owner             = THIS_MODULE;
        ibdev->ib_dev.node_type         = RDMA_NODE_IB_CA;
+       ibdev->ib_dev.local_dma_lkey    = dev->caps.reserved_lkey;
        ibdev->ib_dev.phys_port_cnt     = dev->caps.num_ports;
        ibdev->ib_dev.num_comp_vectors  = 1;
        ibdev->ib_dev.dma_device        = &dev->pdev->dev;
@@ -627,6 +636,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        ibdev->ib_dev.get_dma_mr        = mlx4_ib_get_dma_mr;
        ibdev->ib_dev.reg_user_mr       = mlx4_ib_reg_user_mr;
        ibdev->ib_dev.dereg_mr          = mlx4_ib_dereg_mr;
+       ibdev->ib_dev.alloc_fast_reg_mr = mlx4_ib_alloc_fast_reg_mr;
+       ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list;
+       ibdev->ib_dev.free_fast_reg_page_list  = mlx4_ib_free_fast_reg_page_list;
        ibdev->ib_dev.attach_mcast      = mlx4_ib_mcg_attach;
        ibdev->ib_dev.detach_mcast      = mlx4_ib_mcg_detach;
        ibdev->ib_dev.process_mad       = mlx4_ib_process_mad;
index c4cf5b69eefa3662096348f30a31f5fcbd2a87c8..6e2b0dc21b614dd2b89171c1de04bc6cb133de90 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006, 2007 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -83,6 +84,11 @@ struct mlx4_ib_mr {
        struct ib_umem         *umem;
 };
 
+struct mlx4_ib_fast_reg_page_list {
+       struct ib_fast_reg_page_list    ibfrpl;
+       dma_addr_t                      map;
+};
+
 struct mlx4_ib_fmr {
        struct ib_fmr           ibfmr;
        struct mlx4_fmr         mfmr;
@@ -199,6 +205,11 @@ static inline struct mlx4_ib_mr *to_mmr(struct ib_mr *ibmr)
        return container_of(ibmr, struct mlx4_ib_mr, ibmr);
 }
 
+static inline struct mlx4_ib_fast_reg_page_list *to_mfrpl(struct ib_fast_reg_page_list *ibfrpl)
+{
+       return container_of(ibfrpl, struct mlx4_ib_fast_reg_page_list, ibfrpl);
+}
+
 static inline struct mlx4_ib_fmr *to_mfmr(struct ib_fmr *ibfmr)
 {
        return container_of(ibfmr, struct mlx4_ib_fmr, ibfmr);
@@ -239,6 +250,11 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
                                  u64 virt_addr, int access_flags,
                                  struct ib_udata *udata);
 int mlx4_ib_dereg_mr(struct ib_mr *mr);
+struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd,
+                                       int max_page_list_len);
+struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
+                                                              int page_list_len);
+void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list);
 
 int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
 int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata);
index 68e92485fc76f132ea079110691b1c283cd337e0..a4cdb465cd1d6c2b49ada47998fd0f59d5624a30 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -183,6 +184,76 @@ int mlx4_ib_dereg_mr(struct ib_mr *ibmr)
        return 0;
 }
 
+struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd,
+                                       int max_page_list_len)
+{
+       struct mlx4_ib_dev *dev = to_mdev(pd->device);
+       struct mlx4_ib_mr *mr;
+       int err;
+
+       mr = kmalloc(sizeof *mr, GFP_KERNEL);
+       if (!mr)
+               return ERR_PTR(-ENOMEM);
+
+       err = mlx4_mr_alloc(dev->dev, to_mpd(pd)->pdn, 0, 0, 0,
+                           max_page_list_len, 0, &mr->mmr);
+       if (err)
+               goto err_free;
+
+       err = mlx4_mr_enable(dev->dev, &mr->mmr);
+       if (err)
+               goto err_mr;
+
+       return &mr->ibmr;
+
+err_mr:
+       mlx4_mr_free(dev->dev, &mr->mmr);
+
+err_free:
+       kfree(mr);
+       return ERR_PTR(err);
+}
+
+struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
+                                                              int page_list_len)
+{
+       struct mlx4_ib_dev *dev = to_mdev(ibdev);
+       struct mlx4_ib_fast_reg_page_list *mfrpl;
+       int size = page_list_len * sizeof (u64);
+
+       if (size > PAGE_SIZE)
+               return ERR_PTR(-EINVAL);
+
+       mfrpl = kmalloc(sizeof *mfrpl, GFP_KERNEL);
+       if (!mfrpl)
+               return ERR_PTR(-ENOMEM);
+
+       mfrpl->ibfrpl.page_list = dma_alloc_coherent(&dev->dev->pdev->dev,
+                                                    size, &mfrpl->map,
+                                                    GFP_KERNEL);
+       if (!mfrpl->ibfrpl.page_list)
+               goto err_free;
+
+       WARN_ON(mfrpl->map & 0x3f);
+
+       return &mfrpl->ibfrpl;
+
+err_free:
+       kfree(mfrpl);
+       return ERR_PTR(-ENOMEM);
+}
+
+void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
+{
+       struct mlx4_ib_dev *dev = to_mdev(page_list->device);
+       struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(page_list);
+       int size = page_list->max_page_list_len * sizeof (u64);
+
+       dma_free_coherent(&dev->dev->pdev->dev, size, page_list->page_list,
+                         mfrpl->map);
+       kfree(mfrpl);
+}
+
 struct ib_fmr *mlx4_ib_fmr_alloc(struct ib_pd *pd, int acc,
                                 struct ib_fmr_attr *fmr_attr)
 {
index 89eb6cbe592ef5487a822808a192ae516827769d..f7bc7dd8578a558704d32846cc2f24b99dfe0304 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -78,6 +79,9 @@ static const __be32 mlx4_ib_opcode[] = {
        [IB_WR_RDMA_READ]               = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_READ),
        [IB_WR_ATOMIC_CMP_AND_SWP]      = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_CS),
        [IB_WR_ATOMIC_FETCH_AND_ADD]    = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_FA),
+       [IB_WR_SEND_WITH_INV]           = __constant_cpu_to_be32(MLX4_OPCODE_SEND_INVAL),
+       [IB_WR_LOCAL_INV]               = __constant_cpu_to_be32(MLX4_OPCODE_LOCAL_INVAL),
+       [IB_WR_FAST_REG_MR]             = __constant_cpu_to_be32(MLX4_OPCODE_FMR),
 };
 
 static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp)
@@ -976,6 +980,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
        context->pd         = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
        context->params1    = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
 
+       /* Set "fast registration enabled" for all kernel QPs */
+       if (!qp->ibqp.uobject)
+               context->params1 |= cpu_to_be32(1 << 11);
+
        if (attr_mask & IB_QP_RNR_RETRY) {
                context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
                optpar |= MLX4_QP_OPTPAR_RNR_RETRY;
@@ -1322,6 +1330,38 @@ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq
        return cur + nreq >= wq->max_post;
 }
 
+static __be32 convert_access(int acc)
+{
+       return (acc & IB_ACCESS_REMOTE_ATOMIC ? cpu_to_be32(MLX4_WQE_FMR_PERM_ATOMIC)       : 0) |
+              (acc & IB_ACCESS_REMOTE_WRITE  ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_WRITE) : 0) |
+              (acc & IB_ACCESS_REMOTE_READ   ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_READ)  : 0) |
+              (acc & IB_ACCESS_LOCAL_WRITE   ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE)  : 0) |
+               cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ);
+}
+
+static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr)
+{
+       struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list);
+
+       fseg->flags             = convert_access(wr->wr.fast_reg.access_flags);
+       fseg->mem_key           = cpu_to_be32(wr->wr.fast_reg.rkey);
+       fseg->buf_list          = cpu_to_be64(mfrpl->map);
+       fseg->start_addr        = cpu_to_be64(wr->wr.fast_reg.iova_start);
+       fseg->reg_len           = cpu_to_be64(wr->wr.fast_reg.length);
+       fseg->offset            = 0; /* XXX -- is this just for ZBVA? */
+       fseg->page_size         = cpu_to_be32(wr->wr.fast_reg.page_shift);
+       fseg->reserved[0]       = 0;
+       fseg->reserved[1]       = 0;
+}
+
+static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey)
+{
+       iseg->flags     = 0;
+       iseg->mem_key   = cpu_to_be32(rkey);
+       iseg->guest_id  = 0;
+       iseg->pa        = 0;
+}
+
 static __always_inline void set_raddr_seg(struct mlx4_wqe_raddr_seg *rseg,
                                          u64 remote_addr, u32 rkey)
 {
@@ -1395,7 +1435,7 @@ static void __set_data_seg(struct mlx4_wqe_data_seg *dseg, struct ib_sge *sg)
        dseg->addr       = cpu_to_be64(sg->addr);
 }
 
-static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
+static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
                         struct mlx4_ib_qp *qp, unsigned *lso_seg_len)
 {
        unsigned halign = ALIGN(sizeof *wqe + wr->wr.ud.hlen, 16);
@@ -1423,6 +1463,21 @@ static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
        return 0;
 }
 
+static __be32 send_ieth(struct ib_send_wr *wr)
+{
+       switch (wr->opcode) {
+       case IB_WR_SEND_WITH_IMM:
+       case IB_WR_RDMA_WRITE_WITH_IMM:
+               return wr->ex.imm_data;
+
+       case IB_WR_SEND_WITH_INV:
+               return cpu_to_be32(wr->ex.invalidate_rkey);
+
+       default:
+               return 0;
+       }
+}
+
 int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                      struct ib_send_wr **bad_wr)
 {
@@ -1469,11 +1524,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                                     MLX4_WQE_CTRL_TCP_UDP_CSUM) : 0) |
                        qp->sq_signal_bits;
 
-               if (wr->opcode == IB_WR_SEND_WITH_IMM ||
-                   wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
-                       ctrl->imm = wr->ex.imm_data;
-               else
-                       ctrl->imm = 0;
+               ctrl->imm = send_ieth(wr);
 
                wqe += sizeof *ctrl;
                size = sizeof *ctrl / 16;
@@ -1505,6 +1556,18 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                                size += sizeof (struct mlx4_wqe_raddr_seg) / 16;
                                break;
 
+                       case IB_WR_LOCAL_INV:
+                               set_local_inv_seg(wqe, wr->ex.invalidate_rkey);
+                               wqe  += sizeof (struct mlx4_wqe_local_inval_seg);
+                               size += sizeof (struct mlx4_wqe_local_inval_seg) / 16;
+                               break;
+
+                       case IB_WR_FAST_REG_MR:
+                               set_fmr_seg(wqe, wr);
+                               wqe  += sizeof (struct mlx4_wqe_fmr_seg);
+                               size += sizeof (struct mlx4_wqe_fmr_seg) / 16;
+                               break;
+
                        default:
                                /* No extra segments required for sends */
                                break;
index 12d6bc6f8007da0ced4158b1a956c7da52bf56c0..d42565258fb7f0c2e0dc8053e62855a1887b87e4 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index e2d11be4525c805a5d643f5335a17cdf273a7e67..13beedeeef9f7aebfb805b4d405490614c019e76 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index ee4d073c889fae7c96933ae3e2a7b3d0cfae9e32..252590116df559cac09002d94bd5f6ed795299ef 100644 (file)
@@ -202,6 +202,7 @@ struct mthca_pd_table {
 
 struct mthca_buddy {
        unsigned long **bits;
+       int            *num_free;
        int             max_order;
        spinlock_t      lock;
 };
index 4e36aa7cb3d2f7cfc9eba226b0315f9a30083939..cc6858f0b65bb1d6b6d168cb2ad8aa73315fb817 100644 (file)
@@ -780,7 +780,7 @@ int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
                return -ENOMEM;
        dev->eq_table.icm_dma  = pci_map_page(dev->pdev, dev->eq_table.icm_page, 0,
                                              PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-       if (pci_dma_mapping_error(dev->eq_table.icm_dma)) {
+       if (pci_dma_mapping_error(dev->pdev, dev->eq_table.icm_dma)) {
                __free_page(dev->eq_table.icm_page);
                return -ENOMEM;
        }
index 8489b1e81c0f2b2643569d08b802df43150631e9..882e6b73591591213f211928be33da0b58ef8901 100644 (file)
@@ -89,23 +89,26 @@ static u32 mthca_buddy_alloc(struct mthca_buddy *buddy, int order)
 
        spin_lock(&buddy->lock);
 
-       for (o = order; o <= buddy->max_order; ++o) {
-               m = 1 << (buddy->max_order - o);
-               seg = find_first_bit(buddy->bits[o], m);
-               if (seg < m)
-                       goto found;
-       }
+       for (o = order; o <= buddy->max_order; ++o)
+               if (buddy->num_free[o]) {
+                       m = 1 << (buddy->max_order - o);
+                       seg = find_first_bit(buddy->bits[o], m);
+                       if (seg < m)
+                               goto found;
+               }
 
        spin_unlock(&buddy->lock);
        return -1;
 
  found:
        clear_bit(seg, buddy->bits[o]);
+       --buddy->num_free[o];
 
        while (o > order) {
                --o;
                seg <<= 1;
                set_bit(seg ^ 1, buddy->bits[o]);
+               ++buddy->num_free[o];
        }
 
        spin_unlock(&buddy->lock);
@@ -123,11 +126,13 @@ static void mthca_buddy_free(struct mthca_buddy *buddy, u32 seg, int order)
 
        while (test_bit(seg ^ 1, buddy->bits[order])) {
                clear_bit(seg ^ 1, buddy->bits[order]);
+               --buddy->num_free[order];
                seg >>= 1;
                ++order;
        }
 
        set_bit(seg, buddy->bits[order]);
+       ++buddy->num_free[order];
 
        spin_unlock(&buddy->lock);
 }
@@ -141,7 +146,9 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
 
        buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
                              GFP_KERNEL);
-       if (!buddy->bits)
+       buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+                                 GFP_KERNEL);
+       if (!buddy->bits || !buddy->num_free)
                goto err_out;
 
        for (i = 0; i <= buddy->max_order; ++i) {
@@ -154,6 +161,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
        }
 
        set_bit(0, buddy->bits[buddy->max_order]);
+       buddy->num_free[buddy->max_order] = 1;
 
        return 0;
 
@@ -161,9 +169,10 @@ err_out_free:
        for (i = 0; i <= buddy->max_order; ++i)
                kfree(buddy->bits[i]);
 
+err_out:
        kfree(buddy->bits);
+       kfree(buddy->num_free);
 
-err_out:
        return -ENOMEM;
 }
 
@@ -175,6 +184,7 @@ static void mthca_buddy_cleanup(struct mthca_buddy *buddy)
                kfree(buddy->bits[i]);
 
        kfree(buddy->bits);
+       kfree(buddy->num_free);
 }
 
 static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order,
index d2884e7780987c2a9f5ee9ad409086100127ba25..b0cab64e5e3db0b45e6837a98a9bcfef6fe8e4c4 100644 (file)
@@ -276,6 +276,7 @@ static void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct nes_cqp_r
        }
        nes_free_resource(nesadapter, nesadapter->allocated_qps, nesqp->hwqp.qp_id);
 
+       nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL;
        kfree(nesqp->allocated_buffer);
 
 }
@@ -289,7 +290,6 @@ void nes_rem_ref(struct ib_qp *ibqp)
        struct nes_qp *nesqp;
        struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
        struct nes_device *nesdev = nesvnic->nesdev;
-       struct nes_adapter *nesadapter = nesdev->nesadapter;
        struct nes_hw_cqp_wqe *cqp_wqe;
        struct nes_cqp_request *cqp_request;
        u32 opcode;
@@ -303,8 +303,6 @@ void nes_rem_ref(struct ib_qp *ibqp)
        }
 
        if (atomic_dec_and_test(&nesqp->refcount)) {
-               nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL;
-
                /* Destroy the QP */
                cqp_request = nes_get_cqp_request(nesdev);
                if (cqp_request == NULL) {
index 6aa531d5276dfd969114d07ebcc4c871e611e79d..9f0b964b2c9932af7567dcae6efc7d98c6c01728 100644 (file)
@@ -74,36 +74,59 @@ atomic_t cm_nodes_destroyed;
 atomic_t cm_accel_dropped_pkts;
 atomic_t cm_resets_recvd;
 
-static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *);
+static inline int mini_cm_accelerated(struct nes_cm_core *,
+       struct nes_cm_node *);
 static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
-               struct nes_vnic *, struct nes_cm_info *);
-static int add_ref_cm_node(struct nes_cm_node *);
-static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
+       struct nes_vnic *, struct nes_cm_info *);
 static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
-static struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *,
-                                    void *, u32, void *, u32, u8);
-static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node);
-
 static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *,
-                                          struct nes_vnic *,
-                                          struct ietf_mpa_frame *,
-                                          struct nes_cm_info *);
+       struct nes_vnic *, u16, void *, struct nes_cm_info *);
+static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
 static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
-                         struct nes_cm_node *);
+       struct nes_cm_node *);
 static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
-                         struct nes_cm_node *);
-static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
-static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
-                           struct sk_buff *);
+       struct nes_cm_node *);
+static void mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
+       struct sk_buff *);
 static int mini_cm_dealloc_core(struct nes_cm_core *);
 static int mini_cm_get(struct nes_cm_core *);
 static int mini_cm_set(struct nes_cm_core *, u32, u32);
+
+static struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *,
+       void *, u32, void *, u32, u8);
+static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node);
+static int add_ref_cm_node(struct nes_cm_node *);
+static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
+
 static int nes_cm_disconn_true(struct nes_qp *);
 static int nes_cm_post_event(struct nes_cm_event *event);
 static int nes_disconnect(struct nes_qp *nesqp, int abrupt);
 static void nes_disconnect_worker(struct work_struct *work);
-static int send_ack(struct nes_cm_node *cm_node);
+
+static int send_mpa_request(struct nes_cm_node *, struct sk_buff *);
+static int send_syn(struct nes_cm_node *, u32, struct sk_buff *);
+static int send_reset(struct nes_cm_node *, struct sk_buff *);
+static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);
 static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb);
+static void process_packet(struct nes_cm_node *, struct sk_buff *,
+       struct nes_cm_core *);
+
+static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);
+static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);
+static void cleanup_retrans_entry(struct nes_cm_node *);
+static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *,
+       enum nes_cm_event_type);
+static void free_retrans_entry(struct nes_cm_node *cm_node);
+static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
+       struct sk_buff *skb, int optionsize, int passive);
+
+/* CM event handler functions */
+static void cm_event_connected(struct nes_cm_event *);
+static void cm_event_connect_error(struct nes_cm_event *);
+static void cm_event_reset(struct nes_cm_event *);
+static void cm_event_mpa_req(struct nes_cm_event *);
+
+static void print_core(struct nes_cm_core *core);
 
 /* External CM API Interface */
 /* instance of function pointers for client API */
@@ -158,11 +181,11 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
        event->cm_info.loc_port = cm_node->loc_port;
        event->cm_info.cm_id = cm_node->cm_id;
 
-       nes_debug(NES_DBG_CM, "Created event=%p, type=%u, dst_addr=%08x[%x],"
-                       " src_addr=%08x[%x]\n",
-                       event, type,
-                       event->cm_info.loc_addr, event->cm_info.loc_port,
-                       event->cm_info.rem_addr, event->cm_info.rem_port);
+       nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, "
+               "dst_addr=%08x[%x], src_addr=%08x[%x]\n",
+               cm_node, event, type, event->cm_info.loc_addr,
+               event->cm_info.loc_port, event->cm_info.rem_addr,
+               event->cm_info.rem_port);
 
        nes_cm_post_event(event);
        return event;
@@ -172,14 +195,11 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
 /**
  * send_mpa_request
  */
-static int send_mpa_request(struct nes_cm_node *cm_node)
+static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
 {
-       struct sk_buff *skb;
        int ret;
-
-       skb = get_free_pkt(cm_node);
        if (!skb) {
-               nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
+               nes_debug(NES_DBG_CM, "skb set to NULL\n");
                return -1;
        }
 
@@ -188,9 +208,8 @@ static int send_mpa_request(struct nes_cm_node *cm_node)
                        cm_node->mpa_frame_size, SET_ACK);
 
        ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
-       if (ret < 0) {
+       if (ret < 0)
                return ret;
-       }
 
        return 0;
 }
@@ -228,47 +247,13 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 len)
 }
 
 
-/**
- * handle_exception_pkt - process an exception packet.
- * We have been in a TSA state, and we have now received SW
- * TCP/IP traffic should be a FIN request or IP pkt with options
- */
-static int handle_exception_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb)
-{
-       int ret = 0;
-       struct tcphdr *tcph = tcp_hdr(skb);
-
-       /* first check to see if this a FIN pkt */
-       if (tcph->fin) {
-               /* we need to ACK the FIN request */
-               send_ack(cm_node);
-
-               /* check which side we are (client/server) and set next state accordingly */
-               if (cm_node->tcp_cntxt.client)
-                       cm_node->state = NES_CM_STATE_CLOSING;
-               else {
-                       /* we are the server side */
-                       cm_node->state = NES_CM_STATE_CLOSE_WAIT;
-                       /* since this is a self contained CM we don't wait for */
-                       /* an APP to close us, just send final FIN immediately */
-                       ret = send_fin(cm_node, NULL);
-                       cm_node->state = NES_CM_STATE_LAST_ACK;
-               }
-       } else {
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-
 /**
  * form_cm_frame - get a free packet and build empty frame Use
  * node info to build.
  */
-static struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm_node,
-                                    void *options, u32 optionsize, void *data,
-                                    u32 datasize, u8 flags)
+static struct sk_buff *form_cm_frame(struct sk_buff *skb,
+       struct nes_cm_node *cm_node, void *options, u32 optionsize,
+       void *data, u32 datasize, u8 flags)
 {
        struct tcphdr *tcph;
        struct iphdr *iph;
@@ -332,10 +317,12 @@ static struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm
                cm_node->tcp_cntxt.loc_seq_num++;
                tcph->syn = 1;
        } else
-               cm_node->tcp_cntxt.loc_seq_num += datasize;     /* data (no headers) */
+               cm_node->tcp_cntxt.loc_seq_num += datasize;
 
-       if (flags & SET_FIN)
+       if (flags & SET_FIN) {
+               cm_node->tcp_cntxt.loc_seq_num++;
                tcph->fin = 1;
+       }
 
        if (flags & SET_RST)
                tcph->rst = 1;
@@ -389,7 +376,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
                int close_when_complete)
 {
        unsigned long  flags;
-       struct nes_cm_core *cm_core;
+       struct nes_cm_core *cm_core = cm_node->cm_core;
        struct nes_timer_entry *new_send;
        int ret = 0;
        u32 was_timer_set;
@@ -411,7 +398,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
        new_send->close_when_complete = close_when_complete;
 
        if (type == NES_TIMER_TYPE_CLOSE) {
-               new_send->timetosend += (HZ/2); /* TODO: decide on the correct value here */
+               new_send->timetosend += (HZ/10);
                spin_lock_irqsave(&cm_node->recv_list_lock, flags);
                list_add_tail(&new_send->list, &cm_node->recv_list);
                spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
@@ -420,36 +407,28 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
        if (type == NES_TIMER_TYPE_SEND) {
                new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
                atomic_inc(&new_send->skb->users);
+               spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
+               cm_node->send_entry = new_send;
+               add_ref_cm_node(cm_node);
+               spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
+               new_send->timetosend = jiffies + NES_RETRY_TIMEOUT;
 
                ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);
                if (ret != NETDEV_TX_OK) {
-                       nes_debug(NES_DBG_CM, "Error sending packet %p (jiffies = %lu)\n",
-                                       new_send, jiffies);
+                       nes_debug(NES_DBG_CM, "Error sending packet %p "
+                               "(jiffies = %lu)\n", new_send, jiffies);
                        atomic_dec(&new_send->skb->users);
                        new_send->timetosend = jiffies;
                } else {
                        cm_packets_sent++;
                        if (!send_retrans) {
+                               cleanup_retrans_entry(cm_node);
                                if (close_when_complete)
-                                       rem_ref_cm_node(cm_node->cm_core, cm_node);
-                               dev_kfree_skb_any(new_send->skb);
-                               kfree(new_send);
+                                       rem_ref_cm_node(cm_core, cm_node);
                                return ret;
                        }
-                       new_send->timetosend = jiffies + NES_RETRY_TIMEOUT;
                }
-               spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
-               list_add_tail(&new_send->list, &cm_node->retrans_list);
-               spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
-       }
-       if (type == NES_TIMER_TYPE_RECV) {
-               new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
-               new_send->timetosend = jiffies;
-               spin_lock_irqsave(&cm_node->recv_list_lock, flags);
-               list_add_tail(&new_send->list, &cm_node->recv_list);
-               spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
        }
-       cm_core = cm_node->cm_core;
 
        was_timer_set = timer_pending(&cm_core->tcp_timer);
 
@@ -476,23 +455,27 @@ static void nes_cm_timer_tick(unsigned long pass)
        struct list_head *list_node, *list_node_temp;
        struct nes_cm_core *cm_core = g_cm_core;
        struct nes_qp *nesqp;
-       struct sk_buff *skb;
        u32 settimer = 0;
        int ret = NETDEV_TX_OK;
-       int    node_done;
+       enum nes_cm_node_state last_state;
 
        spin_lock_irqsave(&cm_core->ht_lock, flags);
 
-       list_for_each_safe(list_node, list_core_temp, &cm_core->connected_nodes) {
+       list_for_each_safe(list_node, list_core_temp,
+               &cm_core->connected_nodes) {
                cm_node = container_of(list_node, struct nes_cm_node, list);
                add_ref_cm_node(cm_node);
                spin_unlock_irqrestore(&cm_core->ht_lock, flags);
                spin_lock_irqsave(&cm_node->recv_list_lock, flags);
-               list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) {
-                       recv_entry = container_of(list_core, struct nes_timer_entry, list);
-                       if ((time_after(recv_entry->timetosend, jiffies)) &&
-                                       (recv_entry->type == NES_TIMER_TYPE_CLOSE)) {
-                               if (nexttimeout > recv_entry->timetosend || !settimer) {
+               list_for_each_safe(list_core, list_node_temp,
+                       &cm_node->recv_list) {
+                       recv_entry = container_of(list_core,
+                               struct nes_timer_entry, list);
+                       if (!recv_entry)
+                               break;
+                       if (time_after(recv_entry->timetosend, jiffies)) {
+                               if (nexttimeout > recv_entry->timetosend ||
+                                       !settimer) {
                                        nexttimeout = recv_entry->timetosend;
                                        settimer = 1;
                                }
@@ -501,157 +484,143 @@ static void nes_cm_timer_tick(unsigned long pass)
                        list_del(&recv_entry->list);
                        cm_id = cm_node->cm_id;
                        spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
-                       if (recv_entry->type == NES_TIMER_TYPE_CLOSE) {
-                               nesqp = (struct nes_qp *)recv_entry->skb;
-                               spin_lock_irqsave(&nesqp->lock, qplockflags);
-                               if (nesqp->cm_id) {
-                                       nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, refcount = %d: "
-                                                       "****** HIT A NES_TIMER_TYPE_CLOSE"
-                                                       " with something to do!!! ******\n",
-                                                       nesqp->hwqp.qp_id, cm_id,
-                                                       atomic_read(&nesqp->refcount));
-                                       nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
-                                       nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
-                                       nesqp->ibqp_state = IB_QPS_ERR;
-                                       spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                       nes_cm_disconn(nesqp);
-                               } else {
-                                       spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                       nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, refcount = %d:"
-                                                       " ****** HIT A NES_TIMER_TYPE_CLOSE"
-                                                       " with nothing to do!!! ******\n",
-                                                       nesqp->hwqp.qp_id, cm_id,
-                                                       atomic_read(&nesqp->refcount));
-                                       nes_rem_ref(&nesqp->ibqp);
-                               }
-                               if (cm_id)
-                                       cm_id->rem_ref(cm_id);
+                       nesqp = (struct nes_qp *)recv_entry->skb;
+                       spin_lock_irqsave(&nesqp->lock, qplockflags);
+                       if (nesqp->cm_id) {
+                               nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
+                                       "refcount = %d: HIT A "
+                                       "NES_TIMER_TYPE_CLOSE with something "
+                                       "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+                                       atomic_read(&nesqp->refcount));
+                               nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
+                               nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
+                               nesqp->ibqp_state = IB_QPS_ERR;
+                               spin_unlock_irqrestore(&nesqp->lock,
+                                       qplockflags);
+                               nes_cm_disconn(nesqp);
+                       } else {
+                               spin_unlock_irqrestore(&nesqp->lock,
+                                       qplockflags);
+                               nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
+                                       "refcount = %d: HIT A "
+                                       "NES_TIMER_TYPE_CLOSE with nothing "
+                                       "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+                                       atomic_read(&nesqp->refcount));
                        }
+                       if (cm_id)
+                               cm_id->rem_ref(cm_id);
+
                        kfree(recv_entry);
                        spin_lock_irqsave(&cm_node->recv_list_lock, flags);
                }
                spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
 
                spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
-               node_done = 0;
-               list_for_each_safe(list_core, list_node_temp, &cm_node->retrans_list) {
-                       if (node_done) {
-                               break;
-                       }
-                       send_entry = container_of(list_core, struct nes_timer_entry, list);
+               do {
+                       send_entry = cm_node->send_entry;
+                       if (!send_entry)
+                               continue;
                        if (time_after(send_entry->timetosend, jiffies)) {
                                if (cm_node->state != NES_CM_STATE_TSA) {
-                                       if ((nexttimeout > send_entry->timetosend) || !settimer) {
-                                               nexttimeout = send_entry->timetosend;
+                                       if ((nexttimeout >
+                                               send_entry->timetosend) ||
+                                               !settimer) {
+                                               nexttimeout =
+                                                       send_entry->timetosend;
                                                settimer = 1;
+                                               continue;
                                        }
-                                       node_done = 1;
-                                       continue;
                                } else {
-                                       list_del(&send_entry->list);
-                                       skb = send_entry->skb;
-                                       spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
-                                       dev_kfree_skb_any(skb);
-                                       kfree(send_entry);
-                                       spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
+                                       free_retrans_entry(cm_node);
                                        continue;
                                }
                        }
-                       if (send_entry->type == NES_TIMER_NODE_CLEANUP) {
-                               list_del(&send_entry->list);
-                               spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
-                               kfree(send_entry);
-                               spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
-                               continue;
-                       }
-                       if ((send_entry->seq_num < cm_node->tcp_cntxt.rem_ack_num) ||
-                                       (cm_node->state == NES_CM_STATE_TSA) ||
-                                       (cm_node->state == NES_CM_STATE_CLOSED)) {
-                               skb = send_entry->skb;
-                               list_del(&send_entry->list);
-                               spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
-                               kfree(send_entry);
-                               dev_kfree_skb_any(skb);
-                               spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
+
+                       if ((cm_node->state == NES_CM_STATE_TSA) ||
+                               (cm_node->state == NES_CM_STATE_CLOSED)) {
+                               free_retrans_entry(cm_node);
                                continue;
                        }
 
-                       if (!send_entry->retranscount || !send_entry->retrycount) {
+                       if (!send_entry->retranscount ||
+                               !send_entry->retrycount) {
                                cm_packets_dropped++;
-                               skb = send_entry->skb;
-                               list_del(&send_entry->list);
-                               spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
-                               dev_kfree_skb_any(skb);
-                               kfree(send_entry);
-                               if (cm_node->state == NES_CM_STATE_SYN_RCVD) {
-                                       /* this node never even generated an indication up to the cm */
+                               last_state = cm_node->state;
+                               cm_node->state = NES_CM_STATE_CLOSED;
+                               free_retrans_entry(cm_node);
+                               spin_unlock_irqrestore(
+                                       &cm_node->retrans_list_lock, flags);
+                               if (last_state == NES_CM_STATE_SYN_RCVD)
                                        rem_ref_cm_node(cm_core, cm_node);
-                               } else {
-                                       cm_node->state = NES_CM_STATE_CLOSED;
-                                       create_event(cm_node, NES_CM_EVENT_ABORTED);
-                               }
-                               spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
+                               else
+                                       create_event(cm_node,
+                                               NES_CM_EVENT_ABORTED);
+                               spin_lock_irqsave(&cm_node->retrans_list_lock,
+                                       flags);
                                continue;
                        }
-                       /* this seems like the correct place, but leave send entry unprotected */
-                       /* spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); */
                        atomic_inc(&send_entry->skb->users);
                        cm_packets_retrans++;
-                       nes_debug(NES_DBG_CM, "Retransmitting send_entry %p for node %p,"
-                                       " jiffies = %lu, time to send =  %lu, retranscount = %u, "
-                                       "send_entry->seq_num = 0x%08X, cm_node->tcp_cntxt.rem_ack_num = 0x%08X\n",
-                                       send_entry, cm_node, jiffies, send_entry->timetosend, send_entry->retranscount,
-                                       send_entry->seq_num, cm_node->tcp_cntxt.rem_ack_num);
-
-                       spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
+                       nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
+                               "for node %p, jiffies = %lu, time to send = "
+                               "%lu, retranscount = %u, send_entry->seq_num = "
+                               "0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
+                               "0x%08X\n", send_entry, cm_node, jiffies,
+                               send_entry->timetosend,
+                               send_entry->retranscount,
+                               send_entry->seq_num,
+                               cm_node->tcp_cntxt.rem_ack_num);
+
+                       spin_unlock_irqrestore(&cm_node->retrans_list_lock,
+                               flags);
                        ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev);
+                       spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
                        if (ret != NETDEV_TX_OK) {
+                               nes_debug(NES_DBG_CM, "rexmit failed for "
+                                       "node=%p\n", cm_node);
                                cm_packets_bounced++;
                                atomic_dec(&send_entry->skb->users);
                                send_entry->retrycount--;
                                nexttimeout = jiffies + NES_SHORT_TIME;
                                settimer = 1;
-                               node_done = 1;
-                               spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
                                continue;
                        } else {
                                cm_packets_sent++;
                        }
-                       spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
-                       list_del(&send_entry->list);
-                       nes_debug(NES_DBG_CM, "Packet Sent: retrans count = %u, retry count = %u.\n",
-                                       send_entry->retranscount, send_entry->retrycount);
+                       nes_debug(NES_DBG_CM, "Packet Sent: retrans count = "
+                               "%u, retry count = %u.\n",
+                               send_entry->retranscount,
+                               send_entry->retrycount);
                        if (send_entry->send_retrans) {
                                send_entry->retranscount--;
-                               send_entry->timetosend = jiffies + NES_RETRY_TIMEOUT;
-                               if (nexttimeout > send_entry->timetosend || !settimer) {
+                               send_entry->timetosend = jiffies +
+                                       NES_RETRY_TIMEOUT;
+                               if (nexttimeout > send_entry->timetosend ||
+                                       !settimer) {
                                        nexttimeout = send_entry->timetosend;
                                        settimer = 1;
                                }
-                               list_add(&send_entry->list, &cm_node->retrans_list);
-                               continue;
                        } else {
                                int close_when_complete;
-                               skb = send_entry->skb;
-                               close_when_complete = send_entry->close_when_complete;
-                               spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
-                               if (close_when_complete) {
-                                       BUG_ON(atomic_read(&cm_node->ref_count) == 1);
-                                       rem_ref_cm_node(cm_core, cm_node);
-                               }
-                               dev_kfree_skb_any(skb);
-                               kfree(send_entry);
-                               spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
-                               continue;
+                               close_when_complete =
+                                       send_entry->close_when_complete;
+                               nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n",
+                                       cm_node, cm_node->state);
+                               free_retrans_entry(cm_node);
+                               if (close_when_complete)
+                                       rem_ref_cm_node(cm_node->cm_core,
+                                               cm_node);
                        }
-               }
-               spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
-
-               rem_ref_cm_node(cm_core, cm_node);
+               } while (0);
 
+               spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
+               rem_ref_cm_node(cm_node->cm_core, cm_node);
                spin_lock_irqsave(&cm_core->ht_lock, flags);
-               if (ret != NETDEV_TX_OK)
+               if (ret != NETDEV_TX_OK) {
+                       nes_debug(NES_DBG_CM, "rexmit failed for cm_node=%p\n",
+                               cm_node);
                        break;
+               }
        }
        spin_unlock_irqrestore(&cm_core->ht_lock, flags);
 
@@ -667,14 +636,14 @@ static void nes_cm_timer_tick(unsigned long pass)
 /**
  * send_syn
  */
-static int send_syn(struct nes_cm_node *cm_node, u32 sendack)
+static int send_syn(struct nes_cm_node *cm_node, u32 sendack,
+       struct sk_buff *skb)
 {
        int ret;
        int flags = SET_SYN;
-       struct sk_buff *skb;
        char optionsbuffer[sizeof(struct option_mss) +
-                       sizeof(struct option_windowscale) +
-                       sizeof(struct option_base) + 1];
+               sizeof(struct option_windowscale) + sizeof(struct option_base) +
+               TCP_OPTIONS_PADDING];
 
        int optionssize = 0;
        /* Sending MSS option */
@@ -695,8 +664,7 @@ static int send_syn(struct nes_cm_node *cm_node, u32 sendack)
        options->as_windowscale.shiftcount = cm_node->tcp_cntxt.rcv_wscale;
        optionssize += sizeof(struct option_windowscale);
 
-       if (sendack && !(NES_DRV_OPT_SUPRESS_OPTION_BC & nes_drv_opt)
-                       ) {
+       if (sendack && !(NES_DRV_OPT_SUPRESS_OPTION_BC & nes_drv_opt)) {
                options = (union all_known_options *)&optionsbuffer[optionssize];
                options->as_base.optionnum = OPTION_NUMBER_WRITE0;
                options->as_base.length = sizeof(struct option_base);
@@ -714,7 +682,8 @@ static int send_syn(struct nes_cm_node *cm_node, u32 sendack)
        options->as_end = OPTION_NUMBER_END;
        optionssize += 1;
 
-       skb = get_free_pkt(cm_node);
+       if (!skb)
+               skb = get_free_pkt(cm_node);
        if (!skb) {
                nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
                return -1;
@@ -733,18 +702,18 @@ static int send_syn(struct nes_cm_node *cm_node, u32 sendack)
 /**
  * send_reset
  */
-static int send_reset(struct nes_cm_node *cm_node)
+static int send_reset(struct nes_cm_node *cm_node, struct sk_buff *skb)
 {
        int ret;
-       struct sk_buff *skb = get_free_pkt(cm_node);
        int flags = SET_RST | SET_ACK;
 
+       if (!skb)
+               skb = get_free_pkt(cm_node);
        if (!skb) {
                nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
                return -1;
        }
 
-       add_ref_cm_node(cm_node);
        form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, flags);
        ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 0, 1);
 
@@ -755,10 +724,12 @@ static int send_reset(struct nes_cm_node *cm_node)
 /**
  * send_ack
  */
-static int send_ack(struct nes_cm_node *cm_node)
+static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb)
 {
        int ret;
-       struct sk_buff *skb = get_free_pkt(cm_node);
+
+       if (!skb)
+               skb = get_free_pkt(cm_node);
 
        if (!skb) {
                nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
@@ -922,7 +893,8 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node
        if (!cm_node || !cm_core)
                return -EINVAL;
 
-       nes_debug(NES_DBG_CM, "Adding Node to Active Connection HT\n");
+       nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n",
+               cm_node);
 
        /* first, make an index into our hash table */
        hashkey = make_hashkey(cm_node->loc_port, cm_node->loc_addr,
@@ -946,10 +918,35 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node
  * mini_cm_dec_refcnt_listen
  */
 static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
-               struct nes_cm_listener *listener, int free_hanging_nodes)
+       struct nes_cm_listener *listener, int free_hanging_nodes)
 {
        int ret = 1;
        unsigned long flags;
+       struct list_head *list_pos = NULL;
+       struct list_head *list_temp = NULL;
+       struct nes_cm_node *cm_node = NULL;
+
+       nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, "
+               "refcnt=%d\n", listener, free_hanging_nodes,
+               atomic_read(&listener->ref_count));
+       /* free non-accelerated child nodes for this listener */
+       if (free_hanging_nodes) {
+               spin_lock_irqsave(&cm_core->ht_lock, flags);
+               list_for_each_safe(list_pos, list_temp,
+                       &g_cm_core->connected_nodes) {
+                       cm_node = container_of(list_pos, struct nes_cm_node,
+                               list);
+                       if ((cm_node->listener == listener) &&
+                               (!cm_node->accelerated)) {
+                               cleanup_retrans_entry(cm_node);
+                               spin_unlock_irqrestore(&cm_core->ht_lock,
+                                       flags);
+                               send_reset(cm_node, NULL);
+                               spin_lock_irqsave(&cm_core->ht_lock, flags);
+                       }
+               }
+               spin_unlock_irqrestore(&cm_core->ht_lock, flags);
+       }
        spin_lock_irqsave(&cm_core->listen_list_lock, flags);
        if (!atomic_dec_return(&listener->ref_count)) {
                list_del(&listener->list);
@@ -1067,18 +1064,18 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
        cm_node->loc_port = cm_info->loc_port;
        cm_node->rem_port = cm_info->rem_port;
        cm_node->send_write0 = send_first;
-       nes_debug(NES_DBG_CM, "Make node addresses : loc = " NIPQUAD_FMT ":%x, rem = " NIPQUAD_FMT ":%x\n",
-                 HIPQUAD(cm_node->loc_addr), cm_node->loc_port,
-                 HIPQUAD(cm_node->rem_addr), cm_node->rem_port);
+       nes_debug(NES_DBG_CM, "Make node addresses : loc = " NIPQUAD_FMT
+                       ":%x, rem = " NIPQUAD_FMT ":%x\n",
+                       HIPQUAD(cm_node->loc_addr), cm_node->loc_port,
+                       HIPQUAD(cm_node->rem_addr), cm_node->rem_port);
        cm_node->listener = listener;
        cm_node->netdev = nesvnic->netdev;
        cm_node->cm_id = cm_info->cm_id;
        memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN);
 
-       nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n",
-                       cm_node->listener, cm_node->cm_id);
+       nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener,
+                       cm_node->cm_id);
 
-       INIT_LIST_HEAD(&cm_node->retrans_list);
        spin_lock_init(&cm_node->retrans_list_lock);
        INIT_LIST_HEAD(&cm_node->recv_list);
        spin_lock_init(&cm_node->recv_list_lock);
@@ -1142,10 +1139,9 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node)
  * rem_ref_cm_node - destroy an instance of a cm node
  */
 static int rem_ref_cm_node(struct nes_cm_core *cm_core,
-               struct nes_cm_node *cm_node)
+       struct nes_cm_node *cm_node)
 {
        unsigned long flags, qplockflags;
-       struct nes_timer_entry *send_entry;
        struct nes_timer_entry *recv_entry;
        struct iw_cm_id *cm_id;
        struct list_head *list_core, *list_node_temp;
@@ -1169,48 +1165,33 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
                atomic_dec(&cm_node->listener->pend_accepts_cnt);
                BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
        }
-
-       spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
-       list_for_each_safe(list_core, list_node_temp, &cm_node->retrans_list) {
-               send_entry = container_of(list_core, struct nes_timer_entry, list);
-               list_del(&send_entry->list);
-               spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
-               dev_kfree_skb_any(send_entry->skb);
-               kfree(send_entry);
-               spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
-               continue;
-       }
-       spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
-
+       BUG_ON(cm_node->send_entry);
        spin_lock_irqsave(&cm_node->recv_list_lock, flags);
        list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) {
-               recv_entry = container_of(list_core, struct nes_timer_entry, list);
+               recv_entry = container_of(list_core, struct nes_timer_entry,
+                               list);
                list_del(&recv_entry->list);
                cm_id = cm_node->cm_id;
                spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
-               if (recv_entry->type == NES_TIMER_TYPE_CLOSE) {
-                       nesqp = (struct nes_qp *)recv_entry->skb;
-                       spin_lock_irqsave(&nesqp->lock, qplockflags);
-                       if (nesqp->cm_id) {
-                               nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE"
-                                               " with something to do!!! ******\n",
-                                               nesqp->hwqp.qp_id, cm_id);
-                               nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
-                               nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
-                               nesqp->ibqp_state = IB_QPS_ERR;
-                               spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                               nes_cm_disconn(nesqp);
-                       } else {
-                               spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                               nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE"
-                                               " with nothing to do!!! ******\n",
-                                               nesqp->hwqp.qp_id, cm_id);
-                               nes_rem_ref(&nesqp->ibqp);
-                       }
-                       cm_id->rem_ref(cm_id);
-               } else if (recv_entry->type == NES_TIMER_TYPE_RECV) {
-                       dev_kfree_skb_any(recv_entry->skb);
+               nesqp = (struct nes_qp *)recv_entry->skb;
+               spin_lock_irqsave(&nesqp->lock, qplockflags);
+               if (nesqp->cm_id) {
+                       nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A "
+                               "NES_TIMER_TYPE_CLOSE with something to do!\n",
+                               nesqp->hwqp.qp_id, cm_id);
+                       nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
+                       nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
+                       nesqp->ibqp_state = IB_QPS_ERR;
+                       spin_unlock_irqrestore(&nesqp->lock, qplockflags);
+                       nes_cm_disconn(nesqp);
+               } else {
+                       spin_unlock_irqrestore(&nesqp->lock, qplockflags);
+                       nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A "
+                               "NES_TIMER_TYPE_CLOSE with nothing to do!\n",
+                               nesqp->hwqp.qp_id, cm_id);
                }
+               cm_id->rem_ref(cm_id);
+
                kfree(recv_entry);
                spin_lock_irqsave(&cm_node->recv_list_lock, flags);
        }
@@ -1221,23 +1202,31 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
        } else {
                if (cm_node->apbvt_set && cm_node->nesvnic) {
                        nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port,
-                                       PCI_FUNC(cm_node->nesvnic->nesdev->pcidev->devfn),
-                                       NES_MANAGE_APBVT_DEL);
+                               PCI_FUNC(
+                               cm_node->nesvnic->nesdev->pcidev->devfn),
+                               NES_MANAGE_APBVT_DEL);
                }
        }
 
-       kfree(cm_node);
        atomic_dec(&cm_core->node_cnt);
        atomic_inc(&cm_nodes_destroyed);
+       nesqp = cm_node->nesqp;
+       if (nesqp) {
+               nesqp->cm_node = NULL;
+               nes_rem_ref(&nesqp->ibqp);
+               cm_node->nesqp = NULL;
+       }
 
+       cm_node->freed = 1;
+       kfree(cm_node);
        return 0;
 }
 
-
 /**
  * process_options
  */
-static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 optionsize, u32 syn_packet)
+static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
+       u32 optionsize, u32 syn_packet)
 {
        u32 tmp;
        u32 offset = 0;
@@ -1247,35 +1236,37 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 opti
        while (offset < optionsize) {
                all_options = (union all_known_options *)(optionsloc + offset);
                switch (all_options->as_base.optionnum) {
-                       case OPTION_NUMBER_END:
-                               offset = optionsize;
-                               break;
-                       case OPTION_NUMBER_NONE:
-                               offset += 1;
-                               continue;
-                       case OPTION_NUMBER_MSS:
-                               nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d Size: %d\n",
-                                               __func__,
-                                               all_options->as_mss.length, offset, optionsize);
-                               got_mss_option = 1;
-                               if (all_options->as_mss.length != 4) {
-                                       return 1;
-                               } else {
-                                       tmp = ntohs(all_options->as_mss.mss);
-                                       if (tmp > 0 && tmp < cm_node->tcp_cntxt.mss)
-                                               cm_node->tcp_cntxt.mss = tmp;
-                               }
-                               break;
-                       case OPTION_NUMBER_WINDOW_SCALE:
-                               cm_node->tcp_cntxt.snd_wscale = all_options->as_windowscale.shiftcount;
-                               break;
-                       case OPTION_NUMBER_WRITE0:
-                               cm_node->send_write0 = 1;
-                               break;
-                       default:
-                               nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n",
-                                               all_options->as_base.optionnum);
-                               break;
+               case OPTION_NUMBER_END:
+                       offset = optionsize;
+                       break;
+               case OPTION_NUMBER_NONE:
+                       offset += 1;
+                       continue;
+               case OPTION_NUMBER_MSS:
+                       nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d "
+                               "Size: %d\n", __func__,
+                               all_options->as_mss.length, offset, optionsize);
+                       got_mss_option = 1;
+                       if (all_options->as_mss.length != 4) {
+                               return 1;
+                       } else {
+                               tmp = ntohs(all_options->as_mss.mss);
+                               if (tmp > 0 && tmp <
+                                       cm_node->tcp_cntxt.mss)
+                                       cm_node->tcp_cntxt.mss = tmp;
+                       }
+                       break;
+               case OPTION_NUMBER_WINDOW_SCALE:
+                       cm_node->tcp_cntxt.snd_wscale =
+                               all_options->as_windowscale.shiftcount;
+                       break;
+               case OPTION_NUMBER_WRITE0:
+                       cm_node->send_write0 = 1;
+                       break;
+               default:
+                       nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n",
+                               all_options->as_base.optionnum);
+                       break;
                }
                offset += all_options->as_base.length;
        }
@@ -1284,300 +1275,491 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 opti
        return 0;
 }
 
+static void drop_packet(struct sk_buff *skb)
+{
+       atomic_inc(&cm_accel_dropped_pkts);
+       dev_kfree_skb_any(skb);
+}
 
-/**
- * process_packet
- */
-static int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
-                         struct nes_cm_core *cm_core)
+static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
+       struct tcphdr *tcph)
 {
-       int optionsize;
-       int datasize;
-       int ret = 0;
-       struct tcphdr *tcph = tcp_hdr(skb);
-       u32 inc_sequence;
-       if (cm_node->state == NES_CM_STATE_SYN_SENT && tcph->syn) {
-               inc_sequence = ntohl(tcph->seq);
-               cm_node->tcp_cntxt.rcv_nxt = inc_sequence;
+       atomic_inc(&cm_resets_recvd);
+       nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
+               "refcnt=%d\n", cm_node, cm_node->state,
+               atomic_read(&cm_node->ref_count));
+       cm_node->tcp_cntxt.rcv_nxt++;
+       cleanup_retrans_entry(cm_node);
+       switch (cm_node->state) {
+       case NES_CM_STATE_SYN_RCVD:
+       case NES_CM_STATE_SYN_SENT:
+       case NES_CM_STATE_ESTABLISHED:
+       case NES_CM_STATE_MPAREQ_SENT:
+               cm_node->state = NES_CM_STATE_LAST_ACK;
+               send_fin(cm_node, skb);
+               break;
+       case NES_CM_STATE_FIN_WAIT1:
+               cm_node->state = NES_CM_STATE_CLOSING;
+               send_ack(cm_node, skb);
+               break;
+       case NES_CM_STATE_FIN_WAIT2:
+               cm_node->state = NES_CM_STATE_TIME_WAIT;
+               send_ack(cm_node, skb);
+               cm_node->state = NES_CM_STATE_CLOSED;
+               break;
+       case NES_CM_STATE_TSA:
+       default:
+               nes_debug(NES_DBG_CM, "Error Rcvd FIN for node-%p state = %d\n",
+                       cm_node, cm_node->state);
+               drop_packet(skb);
+               break;
        }
+}
 
-       if ((!tcph) || (cm_node->state == NES_CM_STATE_TSA)) {
-               BUG_ON(!tcph);
-               atomic_inc(&cm_accel_dropped_pkts);
-               return -1;
-       }
 
-       if (tcph->rst) {
-               atomic_inc(&cm_resets_recvd);
-               nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u. refcnt=%d\n",
-                               cm_node, cm_node->state, atomic_read(&cm_node->ref_count));
-               switch (cm_node->state) {
-                       case NES_CM_STATE_LISTENING:
-                               rem_ref_cm_node(cm_core, cm_node);
-                               break;
-                       case NES_CM_STATE_TSA:
-                       case NES_CM_STATE_CLOSED:
-                               break;
-                       case NES_CM_STATE_SYN_RCVD:
-                                       nes_debug(NES_DBG_CM, "Received a reset for local 0x%08X:%04X,"
-                                                       " remote 0x%08X:%04X, node state = %u\n",
-                                                       cm_node->loc_addr, cm_node->loc_port,
-                                                       cm_node->rem_addr, cm_node->rem_port,
-                                                       cm_node->state);
-                               rem_ref_cm_node(cm_core, cm_node);
-                               break;
-                       case NES_CM_STATE_ONE_SIDE_ESTABLISHED:
-                       case NES_CM_STATE_ESTABLISHED:
-                       case NES_CM_STATE_MPAREQ_SENT:
-                       default:
-                                       nes_debug(NES_DBG_CM, "Received a reset for local 0x%08X:%04X,"
-                                                       " remote 0x%08X:%04X, node state = %u refcnt=%d\n",
-                                                       cm_node->loc_addr, cm_node->loc_port,
-                                                       cm_node->rem_addr, cm_node->rem_port,
-                                                       cm_node->state, atomic_read(&cm_node->ref_count));
-                               /* create event */
-                               cm_node->state = NES_CM_STATE_CLOSED;
+static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
+       struct tcphdr *tcph)
+{
 
-                               create_event(cm_node, NES_CM_EVENT_ABORTED);
-                               break;
+       int     reset = 0;      /* whether to send reset in case of err.. */
+       atomic_inc(&cm_resets_recvd);
+       nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u."
+                       " refcnt=%d\n", cm_node, cm_node->state,
+                       atomic_read(&cm_node->ref_count));
+       cleanup_retrans_entry(cm_node);
+       switch (cm_node->state) {
+       case NES_CM_STATE_SYN_SENT:
+       case NES_CM_STATE_MPAREQ_SENT:
+               nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
+                       "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+                       cm_node->listener, cm_node->state);
+               active_open_err(cm_node, skb, reset);
+               break;
+       /* For PASSIVE open states, remove the cm_node event */
+       case NES_CM_STATE_ESTABLISHED:
+       case NES_CM_STATE_SYN_RCVD:
+       case NES_CM_STATE_LISTENING:
+               nes_debug(NES_DBG_CM, "Bad state %s[%u]\n", __func__, __LINE__);
+               passive_open_err(cm_node, skb, reset);
+               break;
+       case NES_CM_STATE_TSA:
+       default:
+               break;
+       }
+}
 
+static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb,
+       enum nes_cm_event_type type)
+{
+
+       int     ret;
+       int datasize = skb->len;
+       u8 *dataloc = skb->data;
+       ret = parse_mpa(cm_node, dataloc, datasize);
+       if (ret < 0) {
+               nes_debug(NES_DBG_CM, "didn't like MPA Request\n");
+               if (type == NES_CM_EVENT_CONNECTED) {
+                       nes_debug(NES_DBG_CM, "%s[%u] create abort for "
+                               "cm_node=%p listener=%p state=%d\n", __func__,
+                               __LINE__, cm_node, cm_node->listener,
+                               cm_node->state);
+                       active_open_err(cm_node, skb, 1);
+               } else {
+                       passive_open_err(cm_node, skb, 1);
                }
-               return -1;
+       } else {
+               cleanup_retrans_entry(cm_node);
+               dev_kfree_skb_any(skb);
+               if (type == NES_CM_EVENT_CONNECTED)
+                       cm_node->state = NES_CM_STATE_TSA;
+               create_event(cm_node, type);
+
+       }
+       return ;
+}
+
+static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)
+{
+       switch (cm_node->state) {
+       case NES_CM_STATE_SYN_SENT:
+       case NES_CM_STATE_MPAREQ_SENT:
+               nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
+                       "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+                       cm_node->listener, cm_node->state);
+               active_open_err(cm_node, skb, 1);
+               break;
+       case NES_CM_STATE_ESTABLISHED:
+       case NES_CM_STATE_SYN_RCVD:
+               passive_open_err(cm_node, skb, 1);
+               break;
+       case NES_CM_STATE_TSA:
+       default:
+               drop_packet(skb);
        }
+}
+
+static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,
+       struct sk_buff *skb)
+{
+       int err;
+
+       err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num))? 0 : 1;
+       if (err)
+               active_open_err(cm_node, skb, 1);
+
+       return err;
+}
+
+static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
+       struct sk_buff *skb)
+{
+       int err = 0;
+       u32 seq;
+       u32 ack_seq;
+       u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num;
+       u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt;
+       u32 rcv_wnd;
+       seq = ntohl(tcph->seq);
+       ack_seq = ntohl(tcph->ack_seq);
+       rcv_wnd = cm_node->tcp_cntxt.rcv_wnd;
+       if (ack_seq != loc_seq_num)
+               err = 1;
+       else if ((seq + rcv_wnd) < rcv_nxt)
+               err = 1;
+       if (err) {
+               nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
+                       "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+                       cm_node->listener, cm_node->state);
+               indicate_pkt_err(cm_node, skb);
+               nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X "
+                       "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
+                       rcv_wnd);
+       }
+       return err;
+}
+
+/*
+ * handle_syn_pkt() is for Passive node. The syn packet is received when a node
+ * is created with a listener or it may comein as rexmitted packet which in
+ * that case will be just dropped.
+ */
+
+static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
+       struct tcphdr *tcph)
+{
+       int ret;
+       u32 inc_sequence;
+       int optionsize;
 
        optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
+       skb_pull(skb, tcph->doff << 2);
+       inc_sequence = ntohl(tcph->seq);
 
-       skb_pull(skb, ip_hdr(skb)->ihl << 2);
+       switch (cm_node->state) {
+       case NES_CM_STATE_SYN_SENT:
+       case NES_CM_STATE_MPAREQ_SENT:
+               /* Rcvd syn on active open connection*/
+               active_open_err(cm_node, skb, 1);
+               break;
+       case NES_CM_STATE_LISTENING:
+               /* Passive OPEN */
+               cm_node->accept_pend = 1;
+               atomic_inc(&cm_node->listener->pend_accepts_cnt);
+               if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
+                               cm_node->listener->backlog) {
+                       nes_debug(NES_DBG_CM, "drop syn due to backlog "
+                               "pressure \n");
+                       cm_backlog_drops++;
+                       passive_open_err(cm_node, skb, 0);
+                       break;
+               }
+               ret = handle_tcp_options(cm_node, tcph, skb, optionsize,
+                       1);
+               if (ret) {
+                       passive_open_err(cm_node, skb, 0);
+                       /* drop pkt */
+                       break;
+               }
+               cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1;
+               BUG_ON(cm_node->send_entry);
+               cm_node->state = NES_CM_STATE_SYN_RCVD;
+               send_syn(cm_node, 1, skb);
+               break;
+       case NES_CM_STATE_TSA:
+       case NES_CM_STATE_ESTABLISHED:
+       case NES_CM_STATE_FIN_WAIT1:
+       case NES_CM_STATE_FIN_WAIT2:
+       case NES_CM_STATE_MPAREQ_RCVD:
+       case NES_CM_STATE_LAST_ACK:
+       case NES_CM_STATE_CLOSING:
+       case NES_CM_STATE_UNKNOWN:
+       case NES_CM_STATE_CLOSED:
+       default:
+               drop_packet(skb);
+               break;
+       }
+}
+
+static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
+       struct tcphdr *tcph)
+{
+
+       int ret;
+       u32 inc_sequence;
+       int optionsize;
+
+       optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
        skb_pull(skb, tcph->doff << 2);
+       inc_sequence = ntohl(tcph->seq);
+       switch (cm_node->state) {
+       case NES_CM_STATE_SYN_SENT:
+               /* active open */
+               if (check_syn(cm_node, tcph, skb))
+                       return;
+               cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
+               /* setup options */
+               ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0);
+               if (ret) {
+                       nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n",
+                               cm_node);
+                       break;
+               }
+               cleanup_retrans_entry(cm_node);
+               cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1;
+               send_mpa_request(cm_node, skb);
+               cm_node->state = NES_CM_STATE_MPAREQ_SENT;
+               break;
+       case NES_CM_STATE_MPAREQ_RCVD:
+               /* passive open, so should not be here */
+               passive_open_err(cm_node, skb, 1);
+               break;
+       case NES_CM_STATE_ESTABLISHED:
+       case NES_CM_STATE_FIN_WAIT1:
+       case NES_CM_STATE_FIN_WAIT2:
+       case NES_CM_STATE_LAST_ACK:
+       case NES_CM_STATE_TSA:
+       case NES_CM_STATE_CLOSING:
+       case NES_CM_STATE_UNKNOWN:
+       case NES_CM_STATE_CLOSED:
+       case NES_CM_STATE_MPAREQ_SENT:
+       default:
+               drop_packet(skb);
+               break;
+       }
+}
 
-       datasize = skb->len;
+static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
+       struct tcphdr *tcph)
+{
+       int datasize = 0;
+       u32 inc_sequence;
+       u32 rem_seq_ack;
+       u32 rem_seq;
+       if (check_seq(cm_node, tcph, skb))
+               return;
+
+       skb_pull(skb, tcph->doff << 2);
        inc_sequence = ntohl(tcph->seq);
-       nes_debug(NES_DBG_CM, "datasize = %u, sequence = 0x%08X, ack_seq = 0x%08X,"
-                       " rcv_nxt = 0x%08X Flags: %s %s.\n",
-                       datasize, inc_sequence, ntohl(tcph->ack_seq),
-                       cm_node->tcp_cntxt.rcv_nxt, (tcph->syn ? "SYN":""),
-                       (tcph->ack ? "ACK":""));
-
-       if (!tcph->syn && (inc_sequence != cm_node->tcp_cntxt.rcv_nxt)
-               ) {
-               nes_debug(NES_DBG_CM, "dropping packet, datasize = %u, sequence = 0x%08X,"
-                               " ack_seq = 0x%08X, rcv_nxt = 0x%08X Flags: %s.\n",
-                               datasize, inc_sequence, ntohl(tcph->ack_seq),
-                               cm_node->tcp_cntxt.rcv_nxt, (tcph->ack ? "ACK":""));
-               if (cm_node->state == NES_CM_STATE_LISTENING) {
-                       rem_ref_cm_node(cm_core, cm_node);
+       rem_seq = ntohl(tcph->seq);
+       rem_seq_ack =  ntohl(tcph->ack_seq);
+       datasize = skb->len;
+
+       switch (cm_node->state) {
+       case NES_CM_STATE_SYN_RCVD:
+               /* Passive OPEN */
+               cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
+               cm_node->state = NES_CM_STATE_ESTABLISHED;
+               if (datasize) {
+                       cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
+                       cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
+                       handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_MPA_REQ);
+                } else { /* rcvd ACK only */
+                       dev_kfree_skb_any(skb);
+                       cleanup_retrans_entry(cm_node);
+                }
+               break;
+       case NES_CM_STATE_ESTABLISHED:
+               /* Passive OPEN */
+               /* We expect mpa frame to be received only */
+               if (datasize) {
+                       cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
+                       cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
+                       handle_rcv_mpa(cm_node, skb,
+                               NES_CM_EVENT_MPA_REQ);
+               } else
+                       drop_packet(skb);
+               break;
+       case NES_CM_STATE_MPAREQ_SENT:
+               cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
+               if (datasize) {
+                       cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
+                       handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_CONNECTED);
+               } else { /* Could be just an ack pkt.. */
+                       cleanup_retrans_entry(cm_node);
+                       dev_kfree_skb_any(skb);
                }
-               return -1;
+               break;
+       case NES_CM_STATE_FIN_WAIT1:
+       case NES_CM_STATE_SYN_SENT:
+       case NES_CM_STATE_FIN_WAIT2:
+       case NES_CM_STATE_TSA:
+       case NES_CM_STATE_CLOSED:
+       case NES_CM_STATE_MPAREQ_RCVD:
+       case NES_CM_STATE_LAST_ACK:
+       case NES_CM_STATE_CLOSING:
+       case NES_CM_STATE_UNKNOWN:
+       default:
+               drop_packet(skb);
+               break;
        }
+}
 
-               cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 
 
+static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
+       struct sk_buff *skb, int optionsize, int passive)
+{
+       u8 *optionsloc = (u8 *)&tcph[1];
        if (optionsize) {
-               u8 *optionsloc = (u8 *)&tcph[1];
-               if (process_options(cm_node, optionsloc, optionsize, (u32)tcph->syn)) {
-                       nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", __func__, cm_node);
-                       send_reset(cm_node);
-                       if (cm_node->state != NES_CM_STATE_SYN_SENT)
-                       rem_ref_cm_node(cm_core, cm_node);
-                       return 0;
+               if (process_options(cm_node, optionsloc, optionsize,
+                       (u32)tcph->syn)) {
+                       nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n",
+                               __func__, cm_node);
+                       if (passive)
+                               passive_open_err(cm_node, skb, 0);
+                       else
+                               active_open_err(cm_node, skb, 0);
+                       return 1;
                }
-       } else if (tcph->syn)
-               cm_node->tcp_cntxt.mss = NES_CM_DEFAULT_MSS;
+       }
 
        cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) <<
                        cm_node->tcp_cntxt.snd_wscale;
 
-       if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd) {
+       if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd)
                cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd;
-       }
+       return 0;
+}
 
-       if (tcph->ack) {
-               cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
-               switch (cm_node->state) {
-                       case NES_CM_STATE_SYN_RCVD:
-                       case NES_CM_STATE_SYN_SENT:
-                               /* read and stash current sequence number */
-                               if (cm_node->tcp_cntxt.rem_ack_num != cm_node->tcp_cntxt.loc_seq_num) {
-                                       nes_debug(NES_DBG_CM, "ERROR - cm_node->tcp_cntxt.rem_ack_num !="
-                                                       " cm_node->tcp_cntxt.loc_seq_num\n");
-                                       send_reset(cm_node);
-                                       return 0;
-                               }
-                               if (cm_node->state == NES_CM_STATE_SYN_SENT)
-                                       cm_node->state = NES_CM_STATE_ONE_SIDE_ESTABLISHED;
-                               else {
-                                               cm_node->state = NES_CM_STATE_ESTABLISHED;
-                               }
-                               break;
-                       case NES_CM_STATE_LAST_ACK:
-                               cm_node->state = NES_CM_STATE_CLOSED;
-                               break;
-                       case NES_CM_STATE_FIN_WAIT1:
-                               cm_node->state = NES_CM_STATE_FIN_WAIT2;
-                               break;
-                       case NES_CM_STATE_CLOSING:
-                               cm_node->state = NES_CM_STATE_TIME_WAIT;
-                               /* need to schedule this to happen in 2MSL timeouts */
-                               cm_node->state = NES_CM_STATE_CLOSED;
-                               break;
-                       case NES_CM_STATE_ONE_SIDE_ESTABLISHED:
-                       case NES_CM_STATE_ESTABLISHED:
-                       case NES_CM_STATE_MPAREQ_SENT:
-                       case NES_CM_STATE_CLOSE_WAIT:
-                       case NES_CM_STATE_TIME_WAIT:
-                       case NES_CM_STATE_CLOSED:
-                               break;
-                       case NES_CM_STATE_LISTENING:
-                               nes_debug(NES_DBG_CM, "Received an ACK on a listening port (SYN %d)\n", tcph->syn);
-                               cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
-                               send_reset(cm_node);
-                               /* send_reset bumps refcount, this should have been a new node */
-                               rem_ref_cm_node(cm_core, cm_node);
-                               return -1;
-                               break;
-                       case NES_CM_STATE_TSA:
-                               nes_debug(NES_DBG_CM, "Received a packet with the ack bit set while in TSA state\n");
-                               break;
-                       case NES_CM_STATE_UNKNOWN:
-                       case NES_CM_STATE_INITED:
-                       case NES_CM_STATE_ACCEPTING:
-                       case NES_CM_STATE_FIN_WAIT2:
-                       default:
-                               nes_debug(NES_DBG_CM, "Received ack from unknown state: %x\n",
-                                               cm_node->state);
-                               send_reset(cm_node);
-                               break;
-               }
-       }
+/*
+ * active_open_err() will send reset() if flag set..
+ * It will also send ABORT event.
+ */
 
-       if (tcph->syn) {
-               if (cm_node->state == NES_CM_STATE_LISTENING) {
-                       /* do not exceed backlog */
-                       atomic_inc(&cm_node->listener->pend_accepts_cnt);
-                       if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
-                                       cm_node->listener->backlog) {
-                               nes_debug(NES_DBG_CM, "drop syn due to backlog pressure \n");
-                               cm_backlog_drops++;
-                               atomic_dec(&cm_node->listener->pend_accepts_cnt);
-                               rem_ref_cm_node(cm_core, cm_node);
-                               return 0;
-                       }
-                       cm_node->accept_pend = 1;
+static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
+       int reset)
+{
+       cleanup_retrans_entry(cm_node);
+       if (reset) {
+               nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, "
+                               "state=%d\n", cm_node, cm_node->state);
+               add_ref_cm_node(cm_node);
+               send_reset(cm_node, skb);
+       } else
+               dev_kfree_skb_any(skb);
 
-               }
-               if (datasize == 0)
-                       cm_node->tcp_cntxt.rcv_nxt ++;
+       cm_node->state = NES_CM_STATE_CLOSED;
+       create_event(cm_node, NES_CM_EVENT_ABORTED);
+}
 
-               if (cm_node->state == NES_CM_STATE_LISTENING) {
-                       cm_node->state = NES_CM_STATE_SYN_RCVD;
-                       send_syn(cm_node, 1);
-               }
-               if (cm_node->state == NES_CM_STATE_ONE_SIDE_ESTABLISHED) {
-                       cm_node->state = NES_CM_STATE_ESTABLISHED;
-                       /* send final handshake ACK */
-                       ret = send_ack(cm_node);
-                       if (ret < 0)
-                               return ret;
+/*
+ * passive_open_err() will either do a reset() or will free up the skb and
+ * remove the cm_node.
+ */
 
-                               cm_node->state = NES_CM_STATE_MPAREQ_SENT;
-                               ret = send_mpa_request(cm_node);
-                               if (ret < 0)
-                                       return ret;
-               }
+static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
+       int reset)
+{
+       cleanup_retrans_entry(cm_node);
+       cm_node->state = NES_CM_STATE_CLOSED;
+       if (reset) {
+               nes_debug(NES_DBG_CM, "passive_open_err sending RST for "
+                       "cm_node=%p state =%d\n", cm_node, cm_node->state);
+               send_reset(cm_node, skb);
+       } else {
+               dev_kfree_skb_any(skb);
+               rem_ref_cm_node(cm_node->cm_core, cm_node);
        }
+}
 
-       if (tcph->fin) {
-               cm_node->tcp_cntxt.rcv_nxt++;
-               switch (cm_node->state) {
-                       case NES_CM_STATE_SYN_RCVD:
-                       case NES_CM_STATE_SYN_SENT:
-                       case NES_CM_STATE_ONE_SIDE_ESTABLISHED:
-                       case NES_CM_STATE_ESTABLISHED:
-                       case NES_CM_STATE_ACCEPTING:
-                       case NES_CM_STATE_MPAREQ_SENT:
-                               cm_node->state = NES_CM_STATE_CLOSE_WAIT;
-                               cm_node->state = NES_CM_STATE_LAST_ACK;
-                               ret = send_fin(cm_node, NULL);
-                               break;
-                       case NES_CM_STATE_FIN_WAIT1:
-                               cm_node->state = NES_CM_STATE_CLOSING;
-                               ret = send_ack(cm_node);
-                               break;
-                       case NES_CM_STATE_FIN_WAIT2:
-                               cm_node->state = NES_CM_STATE_TIME_WAIT;
-                               cm_node->tcp_cntxt.loc_seq_num ++;
-                               ret = send_ack(cm_node);
-                               /* need to schedule this to happen in 2MSL timeouts */
-                               cm_node->state = NES_CM_STATE_CLOSED;
-                               break;
-                       case NES_CM_STATE_CLOSE_WAIT:
-                       case NES_CM_STATE_LAST_ACK:
-                       case NES_CM_STATE_CLOSING:
-                       case NES_CM_STATE_TSA:
-                       default:
-                               nes_debug(NES_DBG_CM, "Received a fin while in %x state\n",
-                                               cm_node->state);
-                               ret = -EINVAL;
-                               break;
-               }
+/*
+ * free_retrans_entry() routines assumes that the retrans_list_lock has
+ * been acquired before calling.
+ */
+static void free_retrans_entry(struct nes_cm_node *cm_node)
+{
+       struct nes_timer_entry *send_entry;
+       send_entry = cm_node->send_entry;
+       if (send_entry) {
+               cm_node->send_entry = NULL;
+               dev_kfree_skb_any(send_entry->skb);
+               kfree(send_entry);
+               rem_ref_cm_node(cm_node->cm_core, cm_node);
        }
+}
 
-       if (datasize) {
-               u8 *dataloc = skb->data;
-               /* figure out what state we are in and handle transition to next state */
-               switch (cm_node->state) {
-                       case NES_CM_STATE_LISTENING:
-                       case NES_CM_STATE_SYN_RCVD:
-                       case NES_CM_STATE_SYN_SENT:
-                       case NES_CM_STATE_FIN_WAIT1:
-                       case NES_CM_STATE_FIN_WAIT2:
-                       case NES_CM_STATE_CLOSE_WAIT:
-                       case NES_CM_STATE_LAST_ACK:
-                       case NES_CM_STATE_CLOSING:
-                               break;
-                       case  NES_CM_STATE_MPAREQ_SENT:
-                               /* recv the mpa res frame, ret=frame len (incl priv data) */
-                               ret = parse_mpa(cm_node, dataloc, datasize);
-                               if (ret < 0)
-                                       break;
-                               /* set the req frame payload len in skb */
-                               /* we are done handling this state, set node to a TSA state */
-                               cm_node->state = NES_CM_STATE_TSA;
-                               send_ack(cm_node);
-                               create_event(cm_node, NES_CM_EVENT_CONNECTED);
-                               break;
-
-                       case  NES_CM_STATE_ESTABLISHED:
-                               /* we are expecting an MPA req frame */
-                               ret = parse_mpa(cm_node, dataloc, datasize);
-                               if (ret < 0) {
-                                       break;
-                               }
-                               cm_node->state = NES_CM_STATE_TSA;
-                               send_ack(cm_node);
-                               /* we got a valid MPA request, create an event */
-                               create_event(cm_node, NES_CM_EVENT_MPA_REQ);
-                               break;
-                       case  NES_CM_STATE_TSA:
-                               handle_exception_pkt(cm_node, skb);
-                               break;
-                       case NES_CM_STATE_UNKNOWN:
-                       case NES_CM_STATE_INITED:
-                       default:
-                               ret = -1;
-               }
-       }
+static void cleanup_retrans_entry(struct nes_cm_node *cm_node)
+{
+       unsigned long flags;
 
-       return ret;
+       spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
+       free_retrans_entry(cm_node);
+       spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
 }
 
+/**
+ * process_packet
+ * Returns skb if to be freed, else it will return NULL if already used..
+ */
+static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
+       struct nes_cm_core *cm_core)
+{
+       enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
+       struct tcphdr *tcph = tcp_hdr(skb);
+       skb_pull(skb, ip_hdr(skb)->ihl << 2);
+
+       nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
+               "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
+               tcph->ack, tcph->rst, tcph->fin);
+
+       if (tcph->rst)
+               pkt_type = NES_PKT_TYPE_RST;
+       else if (tcph->syn) {
+               pkt_type = NES_PKT_TYPE_SYN;
+               if (tcph->ack)
+                       pkt_type = NES_PKT_TYPE_SYNACK;
+       } else if (tcph->fin)
+               pkt_type = NES_PKT_TYPE_FIN;
+       else if (tcph->ack)
+               pkt_type = NES_PKT_TYPE_ACK;
+
+       switch (pkt_type) {
+       case NES_PKT_TYPE_SYN:
+               handle_syn_pkt(cm_node, skb, tcph);
+               break;
+       case NES_PKT_TYPE_SYNACK:
+               handle_synack_pkt(cm_node, skb, tcph);
+               break;
+       case NES_PKT_TYPE_ACK:
+               handle_ack_pkt(cm_node, skb, tcph);
+               break;
+       case NES_PKT_TYPE_RST:
+               handle_rst_pkt(cm_node, skb, tcph);
+               break;
+       case NES_PKT_TYPE_FIN:
+               handle_fin_pkt(cm_node, skb, tcph);
+               break;
+       default:
+               drop_packet(skb);
+               break;
+       }
+}
 
 /**
  * mini_cm_listen - create a listen node with params
  */
 static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
-               struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
+       struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
 {
        struct nes_cm_listener *listener;
        unsigned long flags;
@@ -1644,37 +1826,36 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
 /**
  * mini_cm_connect - make a connection node with params
  */
-static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
-                                          struct nes_vnic *nesvnic,
-                                          struct ietf_mpa_frame *mpa_frame,
-                                          struct nes_cm_info *cm_info)
+struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
+       struct nes_vnic *nesvnic, u16 private_data_len,
+       void *private_data, struct nes_cm_info *cm_info)
 {
        int ret = 0;
        struct nes_cm_node *cm_node;
        struct nes_cm_listener *loopbackremotelistener;
        struct nes_cm_node *loopbackremotenode;
        struct nes_cm_info loopback_cm_info;
-
-       u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) +
-                       ntohs(mpa_frame->priv_data_len);
-
-       cm_info->loc_addr = htonl(cm_info->loc_addr);
-       cm_info->rem_addr = htonl(cm_info->rem_addr);
-       cm_info->loc_port = htons(cm_info->loc_port);
-       cm_info->rem_port = htons(cm_info->rem_port);
+       u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + private_data_len;
+       struct ietf_mpa_frame *mpa_frame = NULL;
 
        /* create a CM connection node */
        cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL);
        if (!cm_node)
                return NULL;
+       mpa_frame = &cm_node->mpa_frame;
+       strcpy(mpa_frame->key, IEFT_MPA_KEY_REQ);
+       mpa_frame->flags = IETF_MPA_FLAGS_CRC;
+       mpa_frame->rev =  IETF_MPA_VERSION;
+       mpa_frame->priv_data_len = htons(private_data_len);
 
        /* set our node side to client (active) side */
        cm_node->tcp_cntxt.client = 1;
        cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
 
        if (cm_info->loc_addr == cm_info->rem_addr) {
-               loopbackremotelistener = find_listener(cm_core, cm_node->rem_addr,
-                               cm_node->rem_port, NES_CM_LISTENER_ACTIVE_STATE);
+               loopbackremotelistener = find_listener(cm_core,
+                               ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
+                               NES_CM_LISTENER_ACTIVE_STATE);
                if (loopbackremotelistener == NULL) {
                        create_event(cm_node, NES_CM_EVENT_ABORTED);
                } else {
@@ -1683,26 +1864,35 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
                        loopback_cm_info.loc_port = cm_info->rem_port;
                        loopback_cm_info.rem_port = cm_info->loc_port;
                        loopback_cm_info.cm_id = loopbackremotelistener->cm_id;
-                       loopbackremotenode = make_cm_node(cm_core, nesvnic, &loopback_cm_info,
-                                       loopbackremotelistener);
+                       loopbackremotenode = make_cm_node(cm_core, nesvnic,
+                               &loopback_cm_info, loopbackremotelistener);
                        loopbackremotenode->loopbackpartner = cm_node;
-                       loopbackremotenode->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
+                       loopbackremotenode->tcp_cntxt.rcv_wscale =
+                               NES_CM_DEFAULT_RCV_WND_SCALE;
                        cm_node->loopbackpartner = loopbackremotenode;
-                       memcpy(loopbackremotenode->mpa_frame_buf, &mpa_frame->priv_data,
-                                       mpa_frame_size);
-                       loopbackremotenode->mpa_frame_size = mpa_frame_size -
-                                       sizeof(struct ietf_mpa_frame);
+                       memcpy(loopbackremotenode->mpa_frame_buf, private_data,
+                               private_data_len);
+                       loopbackremotenode->mpa_frame_size = private_data_len;
 
-                       /* we are done handling this state, set node to a TSA state */
+                       /* we are done handling this state. */
+                       /* set node to a TSA state */
                        cm_node->state = NES_CM_STATE_TSA;
-                       cm_node->tcp_cntxt.rcv_nxt = loopbackremotenode->tcp_cntxt.loc_seq_num;
-                       loopbackremotenode->tcp_cntxt.rcv_nxt = cm_node->tcp_cntxt.loc_seq_num;
-                       cm_node->tcp_cntxt.max_snd_wnd = loopbackremotenode->tcp_cntxt.rcv_wnd;
-                       loopbackremotenode->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.rcv_wnd;
-                       cm_node->tcp_cntxt.snd_wnd = loopbackremotenode->tcp_cntxt.rcv_wnd;
-                       loopbackremotenode->tcp_cntxt.snd_wnd = cm_node->tcp_cntxt.rcv_wnd;
-                       cm_node->tcp_cntxt.snd_wscale = loopbackremotenode->tcp_cntxt.rcv_wscale;
-                       loopbackremotenode->tcp_cntxt.snd_wscale = cm_node->tcp_cntxt.rcv_wscale;
+                       cm_node->tcp_cntxt.rcv_nxt =
+                               loopbackremotenode->tcp_cntxt.loc_seq_num;
+                       loopbackremotenode->tcp_cntxt.rcv_nxt =
+                               cm_node->tcp_cntxt.loc_seq_num;
+                       cm_node->tcp_cntxt.max_snd_wnd =
+                               loopbackremotenode->tcp_cntxt.rcv_wnd;
+                       loopbackremotenode->tcp_cntxt.max_snd_wnd =
+                               cm_node->tcp_cntxt.rcv_wnd;
+                       cm_node->tcp_cntxt.snd_wnd =
+                               loopbackremotenode->tcp_cntxt.rcv_wnd;
+                       loopbackremotenode->tcp_cntxt.snd_wnd =
+                               cm_node->tcp_cntxt.rcv_wnd;
+                       cm_node->tcp_cntxt.snd_wscale =
+                               loopbackremotenode->tcp_cntxt.rcv_wscale;
+                       loopbackremotenode->tcp_cntxt.snd_wscale =
+                               cm_node->tcp_cntxt.rcv_wscale;
 
                        create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ);
                }
@@ -1712,16 +1902,29 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
        /* set our node side to client (active) side */
        cm_node->tcp_cntxt.client = 1;
        /* init our MPA frame ptr */
-       memcpy(&cm_node->mpa_frame, mpa_frame, mpa_frame_size);
+       memcpy(mpa_frame->priv_data, private_data, private_data_len);
+
        cm_node->mpa_frame_size = mpa_frame_size;
 
        /* send a syn and goto syn sent state */
        cm_node->state = NES_CM_STATE_SYN_SENT;
-       ret = send_syn(cm_node, 0);
+       ret = send_syn(cm_node, 0, NULL);
+
+       if (ret) {
+               /* error in sending the syn free up the cm_node struct */
+               nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest "
+                       "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
+                       cm_node->rem_addr, cm_node->rem_port, cm_node,
+                       cm_node->cm_id);
+               rem_ref_cm_node(cm_node->cm_core, cm_node);
+               cm_node = NULL;
+       }
 
-       nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X, port=0x%04x,"
-                       " cm_node=%p, cm_id = %p.\n",
-                       cm_node->rem_addr, cm_node->rem_port, cm_node, cm_node->cm_id);
+       if (cm_node)
+               nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X,"
+                       "port=0x%04x, cm_node=%p, cm_id = %p.\n",
+                       cm_node->rem_addr, cm_node->rem_port, cm_node,
+                       cm_node->cm_id);
 
        return cm_node;
 }
@@ -1731,8 +1934,8 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
  * mini_cm_accept - accept a connection
  * This function is never called
  */
-static int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame,
-                         struct nes_cm_node *cm_node)
+static int mini_cm_accept(struct nes_cm_core *cm_core,
+       struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
 {
        return 0;
 }
@@ -1742,32 +1945,26 @@ static int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mp
  * mini_cm_reject - reject and teardown a connection
  */
 static int mini_cm_reject(struct nes_cm_core *cm_core,
-                         struct ietf_mpa_frame *mpa_frame,
-                         struct nes_cm_node *cm_node)
+       struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
 {
        int ret = 0;
-       struct sk_buff *skb;
-       u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) +
-                       ntohs(mpa_frame->priv_data_len);
 
-       skb = get_free_pkt(cm_node);
-       if (!skb) {
-               nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
-               return -1;
-       }
-
-       /* send an MPA Request frame */
-       form_cm_frame(skb, cm_node, NULL, 0, mpa_frame, mpa_frame_size, SET_ACK | SET_FIN);
-       ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
+       nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n",
+               __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
 
+       if (cm_node->tcp_cntxt.client)
+               return ret;
+       cleanup_retrans_entry(cm_node);
        cm_node->state = NES_CM_STATE_CLOSED;
        ret = send_fin(cm_node, NULL);
 
-       if (ret < 0) {
-               printk(KERN_INFO PFX "failed to send MPA Reply (reject)\n");
-               return ret;
+       if (cm_node->accept_pend) {
+               BUG_ON(!cm_node->listener);
+               atomic_dec(&cm_node->listener->pend_accepts_cnt);
+               BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
        }
 
+       ret = send_reset(cm_node, NULL);
        return ret;
 }
 
@@ -1783,35 +1980,39 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
                return -EINVAL;
 
        switch (cm_node->state) {
-               /* if passed in node is null, create a reference key node for node search */
-               /* check if we found an owner node for this pkt */
-               case NES_CM_STATE_SYN_RCVD:
-               case NES_CM_STATE_SYN_SENT:
-               case NES_CM_STATE_ONE_SIDE_ESTABLISHED:
-               case NES_CM_STATE_ESTABLISHED:
-               case NES_CM_STATE_ACCEPTING:
-               case NES_CM_STATE_MPAREQ_SENT:
-                       cm_node->state = NES_CM_STATE_FIN_WAIT1;
-                       send_fin(cm_node, NULL);
-                       break;
-               case NES_CM_STATE_CLOSE_WAIT:
-                       cm_node->state = NES_CM_STATE_LAST_ACK;
-                       send_fin(cm_node, NULL);
-                       break;
-               case NES_CM_STATE_FIN_WAIT1:
-               case NES_CM_STATE_FIN_WAIT2:
-               case NES_CM_STATE_LAST_ACK:
-               case NES_CM_STATE_TIME_WAIT:
-               case NES_CM_STATE_CLOSING:
-                       ret = -1;
-                       break;
-               case NES_CM_STATE_LISTENING:
-               case NES_CM_STATE_UNKNOWN:
-               case NES_CM_STATE_INITED:
-               case NES_CM_STATE_CLOSED:
-               case NES_CM_STATE_TSA:
-                       ret = rem_ref_cm_node(cm_core, cm_node);
-                       break;
+       case NES_CM_STATE_SYN_RCVD:
+       case NES_CM_STATE_SYN_SENT:
+       case NES_CM_STATE_ONE_SIDE_ESTABLISHED:
+       case NES_CM_STATE_ESTABLISHED:
+       case NES_CM_STATE_ACCEPTING:
+       case NES_CM_STATE_MPAREQ_SENT:
+       case NES_CM_STATE_MPAREQ_RCVD:
+               cleanup_retrans_entry(cm_node);
+               send_reset(cm_node, NULL);
+               break;
+       case NES_CM_STATE_CLOSE_WAIT:
+               cm_node->state = NES_CM_STATE_LAST_ACK;
+               send_fin(cm_node, NULL);
+               break;
+       case NES_CM_STATE_FIN_WAIT1:
+       case NES_CM_STATE_FIN_WAIT2:
+       case NES_CM_STATE_LAST_ACK:
+       case NES_CM_STATE_TIME_WAIT:
+       case NES_CM_STATE_CLOSING:
+               ret = -1;
+               break;
+       case NES_CM_STATE_LISTENING:
+       case NES_CM_STATE_UNKNOWN:
+       case NES_CM_STATE_INITED:
+       case NES_CM_STATE_CLOSED:
+               ret = rem_ref_cm_node(cm_core, cm_node);
+               break;
+       case NES_CM_STATE_TSA:
+               if (cm_node->send_entry)
+                       printk(KERN_ERR "ERROR Close got called from STATE_TSA "
+                               "send_entry=%p\n", cm_node->send_entry);
+               ret = rem_ref_cm_node(cm_core, cm_node);
+               break;
        }
        cm_node->cm_id = NULL;
        return ret;
@@ -1822,25 +2023,30 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
  * recv_pkt - recv an ETHERNET packet, and process it through CM
  * node state machine
  */
-static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic,
-                           struct sk_buff *skb)
+static void mini_cm_recv_pkt(struct nes_cm_core *cm_core,
+       struct nes_vnic *nesvnic, struct sk_buff *skb)
 {
        struct nes_cm_node *cm_node = NULL;
        struct nes_cm_listener *listener = NULL;
        struct iphdr *iph;
        struct tcphdr *tcph;
        struct nes_cm_info nfo;
-       int ret = 0;
 
-       if (!skb || skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
-               ret = -EINVAL;
-               goto out;
+       if (!skb)
+               return;
+       if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
+               dev_kfree_skb_any(skb);
+               return;
        }
 
        iph = (struct iphdr *)skb->data;
        tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
        skb_reset_network_header(skb);
        skb_set_transport_header(skb, sizeof(*tcph));
+       if (!tcph) {
+               dev_kfree_skb_any(skb);
+               return;
+       }
        skb->len = ntohs(iph->tot_len);
 
        nfo.loc_addr = ntohl(iph->daddr);
@@ -1853,61 +2059,60 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvni
                  NIPQUAD(iph->daddr), tcph->dest,
                  NIPQUAD(iph->saddr), tcph->source);
 
-       /* note: this call is going to increment cm_node ref count */
-       cm_node = find_node(cm_core,
+       do {
+               cm_node = find_node(cm_core,
                        nfo.rem_port, nfo.rem_addr,
                        nfo.loc_port, nfo.loc_addr);
 
-       if (!cm_node) {
-               listener = find_listener(cm_core, nfo.loc_addr, nfo.loc_port,
-                               NES_CM_LISTENER_ACTIVE_STATE);
-               if (listener) {
-                       nfo.cm_id = listener->cm_id;
-                       nfo.conn_type = listener->conn_type;
-               } else {
-                       nfo.cm_id = NULL;
-                       nfo.conn_type = 0;
-               }
-
-               cm_node = make_cm_node(cm_core, nesvnic, &nfo, listener);
                if (!cm_node) {
-                       nes_debug(NES_DBG_CM, "Unable to allocate node\n");
+                       /* Only type of packet accepted are for */
+                       /* the PASSIVE open (syn only) */
+                       if ((!tcph->syn) || (tcph->ack)) {
+                               cm_packets_dropped++;
+                               break;
+                       }
+                       listener = find_listener(cm_core, nfo.loc_addr,
+                               nfo.loc_port,
+                               NES_CM_LISTENER_ACTIVE_STATE);
                        if (listener) {
-                               nes_debug(NES_DBG_CM, "unable to allocate node and decrementing listener refcount\n");
+                               nfo.cm_id = listener->cm_id;
+                               nfo.conn_type = listener->conn_type;
+                       } else {
+                               nes_debug(NES_DBG_CM, "Unable to find listener "
+                                       "for the pkt\n");
+                               cm_packets_dropped++;
+                               dev_kfree_skb_any(skb);
+                               break;
+                       }
+
+                       cm_node = make_cm_node(cm_core, nesvnic, &nfo,
+                               listener);
+                       if (!cm_node) {
+                               nes_debug(NES_DBG_CM, "Unable to allocate "
+                                       "node\n");
+                               cm_packets_dropped++;
                                atomic_dec(&listener->ref_count);
+                               dev_kfree_skb_any(skb);
+                               break;
                        }
-                       ret = -1;
-                       goto out;
-               }
-               if (!listener) {
-                       nes_debug(NES_DBG_CM, "Packet found for unknown port %x refcnt=%d\n",
-                                       nfo.loc_port, atomic_read(&cm_node->ref_count));
-                       if (!tcph->rst) {
-                               nes_debug(NES_DBG_CM, "Packet found for unknown port=%d"
-                                               " rem_port=%d refcnt=%d\n",
-                                               nfo.loc_port, nfo.rem_port, atomic_read(&cm_node->ref_count));
-
-                               cm_node->tcp_cntxt.rcv_nxt = ntohl(tcph->seq);
-                               cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
-                               send_reset(cm_node);
+                       if (!tcph->rst && !tcph->fin) {
+                               cm_node->state = NES_CM_STATE_LISTENING;
+                       } else {
+                               cm_packets_dropped++;
+                               rem_ref_cm_node(cm_core, cm_node);
+                               dev_kfree_skb_any(skb);
+                               break;
                        }
+                       add_ref_cm_node(cm_node);
+               } else if (cm_node->state == NES_CM_STATE_TSA) {
                        rem_ref_cm_node(cm_core, cm_node);
-                       ret = -1;
-                       goto out;
+                       atomic_inc(&cm_accel_dropped_pkts);
+                       dev_kfree_skb_any(skb);
+                       break;
                }
-               add_ref_cm_node(cm_node);
-               cm_node->state = NES_CM_STATE_LISTENING;
-       }
-
-       nes_debug(NES_DBG_CM, "Processing Packet for node %p, data = (%p):\n",
-                       cm_node, skb->data);
-       process_packet(cm_node, skb, cm_core);
-
-       rem_ref_cm_node(cm_core, cm_node);
-       out:
-       if (skb)
-               dev_kfree_skb_any(skb);
-       return ret;
+               process_packet(cm_node, skb, cm_core);
+               rem_ref_cm_node(cm_core, cm_node);
+       } while (0);
 }
 
 
@@ -2107,15 +2312,12 @@ int nes_cm_disconn(struct nes_qp *nesqp)
        if (nesqp->disconn_pending == 0) {
                nesqp->disconn_pending++;
                spin_unlock_irqrestore(&nesqp->lock, flags);
-               /* nes_add_ref(&nesqp->ibqp); */
                /* init our disconnect work element, to */
                INIT_WORK(&nesqp->disconn_work, nes_disconnect_worker);
 
                queue_work(g_cm_core->disconn_wq, &nesqp->disconn_work);
-       } else {
+       } else
                spin_unlock_irqrestore(&nesqp->lock, flags);
-               nes_rem_ref(&nesqp->ibqp);
-       }
 
        return 0;
 }
@@ -2161,7 +2363,6 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
                nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n",
                                nesqp->hwqp.qp_id);
                spin_unlock_irqrestore(&nesqp->lock, flags);
-               nes_rem_ref(&nesqp->ibqp);
                return -1;
        }
 
@@ -2182,30 +2383,31 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
                        atomic_inc(&cm_disconnects);
                        cm_event.event = IW_CM_EVENT_DISCONNECT;
                        if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) {
-                               issued_disconnect_reset = 1;
                                cm_event.status = IW_CM_EVENT_STATUS_RESET;
-                               nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event (status reset) for "
-                                               " QP%u, cm_id = %p. \n",
-                                               nesqp->hwqp.qp_id, cm_id);
-                       } else {
+                               nes_debug(NES_DBG_CM, "Generating a CM "
+                                       "Disconnect Event (status reset) for "
+                                       "QP%u, cm_id = %p. \n",
+                                       nesqp->hwqp.qp_id, cm_id);
+                       } else
                                cm_event.status = IW_CM_EVENT_STATUS_OK;
-                       }
 
                        cm_event.local_addr = cm_id->local_addr;
                        cm_event.remote_addr = cm_id->remote_addr;
                        cm_event.private_data = NULL;
                        cm_event.private_data_len = 0;
 
-                       nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event for "
-                                       " QP%u, SQ Head = %u, SQ Tail = %u. cm_id = %p, refcount = %u.\n",
-                                       nesqp->hwqp.qp_id,
-                                       nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail, cm_id,
-                                       atomic_read(&nesqp->refcount));
+                       nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event"
+                               " for  QP%u, SQ Head = %u, SQ Tail = %u. "
+                               "cm_id = %p, refcount = %u.\n",
+                               nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
+                               nesqp->hwqp.sq_tail, cm_id,
+                               atomic_read(&nesqp->refcount));
 
                        spin_unlock_irqrestore(&nesqp->lock, flags);
                        ret = cm_id->event_handler(cm_id, &cm_event);
                        if (ret)
-                               nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
+                               nes_debug(NES_DBG_CM, "OFA CM event_handler "
+                                       "returned, ret=%d\n", ret);
                        spin_lock_irqsave(&nesqp->lock, flags);
                }
 
@@ -2247,31 +2449,24 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
                        if (nesqp->flush_issued == 0) {
                                nesqp->flush_issued = 1;
                                spin_unlock_irqrestore(&nesqp->lock, flags);
-                               flush_wqes(nesvnic->nesdev, nesqp, NES_CQP_FLUSH_RQ, 1);
-                       } else {
+                               flush_wqes(nesvnic->nesdev, nesqp,
+                                       NES_CQP_FLUSH_RQ, 1);
+                       } else
                                spin_unlock_irqrestore(&nesqp->lock, flags);
-                       }
-
-                       /* This reference is from either ModifyQP or the AE processing,
-                                       there is still a race here with modifyqp */
-                       nes_rem_ref(&nesqp->ibqp);
-
                } else {
                        cm_id = nesqp->cm_id;
                        spin_unlock_irqrestore(&nesqp->lock, flags);
                        /* check to see if the inbound reset beat the outbound reset */
                        if ((!cm_id) && (last_ae==NES_AEQE_AEID_RESET_SENT)) {
-                               nes_debug(NES_DBG_CM, "QP%u: Decing refcount due to inbound reset"
-                                               " beating the outbound reset.\n",
-                                               nesqp->hwqp.qp_id);
-                               nes_rem_ref(&nesqp->ibqp);
+                               nes_debug(NES_DBG_CM, "QP%u: Decing refcount "
+                                       "due to inbound reset beating the "
+                                       "outbound reset.\n", nesqp->hwqp.qp_id);
                        }
                }
        } else {
                nesqp->disconn_pending = 0;
                spin_unlock_irqrestore(&nesqp->lock, flags);
        }
-       nes_rem_ref(&nesqp->ibqp);
 
        return 0;
 }
@@ -2349,71 +2544,82 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        nesdev = nesvnic->nesdev;
        adapter = nesdev->nesadapter;
 
-       nes_debug(NES_DBG_CM, "nesvnic=%p, netdev=%p, %s\n",
-                       nesvnic, nesvnic->netdev, nesvnic->netdev->name);
-
-       /* since this is from a listen, we were able to put node handle into cm_id */
        cm_node = (struct nes_cm_node *)cm_id->provider_data;
+       nes_debug(NES_DBG_CM, "nes_accept: cm_node= %p nesvnic=%p, netdev=%p,"
+               "%s\n", cm_node, nesvnic, nesvnic->netdev,
+               nesvnic->netdev->name);
 
        /* associate the node with the QP */
        nesqp->cm_node = (void *)cm_node;
+       cm_node->nesqp = nesqp;
+       nes_add_ref(&nesqp->ibqp);
 
-       nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu\n",
-                       nesqp->hwqp.qp_id, cm_node, jiffies);
+       nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu listener = %p\n",
+               nesqp->hwqp.qp_id, cm_node, jiffies, cm_node->listener);
        atomic_inc(&cm_accepts);
 
        nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
                        atomic_read(&nesvnic->netdev->refcnt));
 
-               /* allocate the ietf frame and space for private data */
-               nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
-                               sizeof(struct ietf_mpa_frame) + conn_param->private_data_len,
-                               &nesqp->ietf_frame_pbase);
-
-               if (!nesqp->ietf_frame) {
-                       nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n");
-                       return -ENOMEM;
-               }
+       /* allocate the ietf frame and space for private data */
+       nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
+               sizeof(struct ietf_mpa_frame) + conn_param->private_data_len,
+               &nesqp->ietf_frame_pbase);
 
+       if (!nesqp->ietf_frame) {
+               nes_debug(NES_DBG_CM, "Unable to allocate memory for private "
+                       "data\n");
+               return -ENOMEM;
+       }
 
-               /* setup the MPA frame */
-               nesqp->private_data_len = conn_param->private_data_len;
-               memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
 
-               memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
-                               conn_param->private_data_len);
+       /* setup the MPA frame */
+       nesqp->private_data_len = conn_param->private_data_len;
+       memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
 
-               nesqp->ietf_frame->priv_data_len = cpu_to_be16(conn_param->private_data_len);
-               nesqp->ietf_frame->rev = mpa_version;
-               nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
+       memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
+                       conn_param->private_data_len);
 
-               /* setup our first outgoing iWarp send WQE (the IETF frame response) */
-               wqe = &nesqp->hwqp.sq_vbase[0];
+       nesqp->ietf_frame->priv_data_len =
+               cpu_to_be16(conn_param->private_data_len);
+       nesqp->ietf_frame->rev = mpa_version;
+       nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
 
-               if (cm_id->remote_addr.sin_addr.s_addr != cm_id->local_addr.sin_addr.s_addr) {
-                       u64temp = (unsigned long)nesqp;
-                       u64temp |= NES_SW_CONTEXT_ALIGN>>1;
-                       set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
-                                           u64temp);
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
-                                       cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING | NES_IWARP_SQ_WQE_WRPDU);
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] =
-                                       cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame));
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] =
-                                       cpu_to_le32((u32)nesqp->ietf_frame_pbase);
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] =
-                                       cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32));
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] =
-                                       cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame));
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
-
-                       nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(
-                                       NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | NES_QPCONTEXT_ORDIRD_WRPDU);
-               } else {
-                       nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
-                                       NES_QPCONTEXT_ORDIRD_WRPDU | NES_QPCONTEXT_ORDIRD_ALSMM));
-               }
-               nesqp->skip_lsmm = 1;
+       /* setup our first outgoing iWarp send WQE (the IETF frame response) */
+       wqe = &nesqp->hwqp.sq_vbase[0];
+
+       if (cm_id->remote_addr.sin_addr.s_addr !=
+                       cm_id->local_addr.sin_addr.s_addr) {
+               u64temp = (unsigned long)nesqp;
+               u64temp |= NES_SW_CONTEXT_ALIGN>>1;
+               set_wqe_64bit_value(wqe->wqe_words,
+                       NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
+                       u64temp);
+               wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+                       cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING |
+                       NES_IWARP_SQ_WQE_WRPDU);
+               wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] =
+                       cpu_to_le32(conn_param->private_data_len +
+                       sizeof(struct ietf_mpa_frame));
+               wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] =
+                       cpu_to_le32((u32)nesqp->ietf_frame_pbase);
+               wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] =
+                       cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32));
+               wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] =
+                       cpu_to_le32(conn_param->private_data_len +
+                       sizeof(struct ietf_mpa_frame));
+               wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+
+               nesqp->nesqp_context->ird_ord_sizes |=
+                       cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
+                       NES_QPCONTEXT_ORDIRD_WRPDU);
+       } else {
+               nesqp->nesqp_context->ird_ord_sizes |=
+                       cpu_to_le32((NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
+                       NES_QPCONTEXT_ORDIRD_WRPDU |
+                       NES_QPCONTEXT_ORDIRD_ALSMM));
+       }
+       nesqp->skip_lsmm = 1;
 
 
        /* Cache the cm_id in the qp */
@@ -2424,55 +2630,75 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        cm_id->provider_data = nesqp;
        nesqp->active_conn   = 0;
 
+       if (cm_node->state == NES_CM_STATE_TSA)
+               nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n",
+                       cm_node);
+
        nes_cm_init_tsa_conn(nesqp, cm_node);
 
-       nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(cm_id->local_addr.sin_port));
-       nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(cm_id->remote_addr.sin_port));
-       nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
+       nesqp->nesqp_context->tcpPorts[0] =
+               cpu_to_le16(ntohs(cm_id->local_addr.sin_port));
+       nesqp->nesqp_context->tcpPorts[1] =
+               cpu_to_le16(ntohs(cm_id->remote_addr.sin_port));
+
+       if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr))
+               nesqp->nesqp_context->ip0 =
+                       cpu_to_le32(ntohl(nesvnic->local_ipaddr));
+       else
+               nesqp->nesqp_context->ip0 =
+                       cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
 
        nesqp->nesqp_context->misc2 |= cpu_to_le32(
-                       (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
+                       (u32)PCI_FUNC(nesdev->pcidev->devfn) <<
+                       NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
 
-       nesqp->nesqp_context->arp_index_vlan |= cpu_to_le32(
-                       nes_arp_table(nesdev, le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
+       nesqp->nesqp_context->arp_index_vlan |=
+               cpu_to_le32(nes_arp_table(nesdev,
+                       le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
                        NES_ARP_RESOLVE) << 16);
 
        nesqp->nesqp_context->ts_val_delta = cpu_to_le32(
-                       jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
+               jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
 
        nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id);
 
        nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(
-                       ((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT));
-       nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
+               ((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT));
+       nesqp->nesqp_context->ird_ord_sizes |=
+               cpu_to_le32((u32)conn_param->ord);
 
        memset(&nes_quad, 0, sizeof(nes_quad));
-       nes_quad.DstIpAdrIndex = cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
-       nes_quad.SrcIpadr      = cm_id->remote_addr.sin_addr.s_addr;
-       nes_quad.TcpPorts[0]   = cm_id->remote_addr.sin_port;
-       nes_quad.TcpPorts[1]   = cm_id->local_addr.sin_port;
+       nes_quad.DstIpAdrIndex =
+               cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
+       if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr))
+               nes_quad.SrcIpadr = nesvnic->local_ipaddr;
+       else
+               nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr;
+       nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port;
+       nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port;
 
        /* Produce hash key */
        crc_value = get_crc_value(&nes_quad);
        nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
        nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n",
-                       nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
+               nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
 
        nesqp->hte_index &= adapter->hte_index_mask;
        nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
 
        cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
 
-       nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X,"
-                       " rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + private data length=%zu.\n",
-                       nesqp->hwqp.qp_id,
+       nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = "
+                       "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
+                       "private data length=%zu.\n", nesqp->hwqp.qp_id,
                        ntohl(cm_id->remote_addr.sin_addr.s_addr),
                        ntohs(cm_id->remote_addr.sin_port),
                        ntohl(cm_id->local_addr.sin_addr.s_addr),
                        ntohs(cm_id->local_addr.sin_port),
                        le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
                        le32_to_cpu(nesqp->nesqp_context->snd_nxt),
-                       conn_param->private_data_len+sizeof(struct ietf_mpa_frame));
+                       conn_param->private_data_len +
+                       sizeof(struct ietf_mpa_frame));
 
        attr.qp_state = IB_QPS_RTS;
        nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
@@ -2489,15 +2715,16 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        cm_event.private_data_len = 0;
        ret = cm_id->event_handler(cm_id, &cm_event);
        if (cm_node->loopbackpartner) {
-               cm_node->loopbackpartner->mpa_frame_size = nesqp->private_data_len;
+               cm_node->loopbackpartner->mpa_frame_size =
+                       nesqp->private_data_len;
                /* copy entire MPA frame to our cm_node's frame */
-               memcpy(cm_node->loopbackpartner->mpa_frame_buf, nesqp->ietf_frame->priv_data,
-                          nesqp->private_data_len);
+               memcpy(cm_node->loopbackpartner->mpa_frame_buf,
+                       nesqp->ietf_frame->priv_data, nesqp->private_data_len);
                create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED);
        }
        if (ret)
-               printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
-                               __func__, __LINE__, ret);
+               printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
+                       "ret=%d\n", __func__, __LINE__, ret);
 
        return 0;
 }
@@ -2555,74 +2782,61 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        if (!nesdev)
                return -EINVAL;
 
-       atomic_inc(&cm_connects);
-
-       nesqp->ietf_frame = kzalloc(sizeof(struct ietf_mpa_frame) +
-                       conn_param->private_data_len, GFP_KERNEL);
-       if (!nesqp->ietf_frame)
-               return -ENOMEM;
+       nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = "
+               "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
+               ntohl(nesvnic->local_ipaddr),
+               ntohl(cm_id->remote_addr.sin_addr.s_addr),
+               ntohs(cm_id->remote_addr.sin_port),
+               ntohl(cm_id->local_addr.sin_addr.s_addr),
+               ntohs(cm_id->local_addr.sin_port));
 
-       /* set qp as having an active connection */
+       atomic_inc(&cm_connects);
        nesqp->active_conn = 1;
 
-       nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X.\n",
-                       nesqp->hwqp.qp_id,
-                       ntohl(cm_id->remote_addr.sin_addr.s_addr),
-                       ntohs(cm_id->remote_addr.sin_port),
-                       ntohl(cm_id->local_addr.sin_addr.s_addr),
-                       ntohs(cm_id->local_addr.sin_port));
-
        /* cache the cm_id in the qp */
        nesqp->cm_id = cm_id;
 
        cm_id->provider_data = nesqp;
 
-       /* copy the private data */
-       if (conn_param->private_data_len) {
-               memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
-                               conn_param->private_data_len);
-       }
-
        nesqp->private_data_len = conn_param->private_data_len;
        nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
        nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord);
-       nes_debug(NES_DBG_CM, "mpa private data len =%u\n", conn_param->private_data_len);
-
-       strcpy(&nesqp->ietf_frame->key[0], IEFT_MPA_KEY_REQ);
-       nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
-       nesqp->ietf_frame->rev = IETF_MPA_VERSION;
-       nesqp->ietf_frame->priv_data_len = htons(conn_param->private_data_len);
+       nes_debug(NES_DBG_CM, "mpa private data len =%u\n",
+               conn_param->private_data_len);
 
-       if (cm_id->local_addr.sin_addr.s_addr != cm_id->remote_addr.sin_addr.s_addr)
+       if (cm_id->local_addr.sin_addr.s_addr !=
+               cm_id->remote_addr.sin_addr.s_addr)
                nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
-                               PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
+                       PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
 
        /* set up the connection params for the node */
-       cm_info.loc_addr = (cm_id->local_addr.sin_addr.s_addr);
-       cm_info.loc_port = (cm_id->local_addr.sin_port);
-       cm_info.rem_addr = (cm_id->remote_addr.sin_addr.s_addr);
-       cm_info.rem_port = (cm_id->remote_addr.sin_port);
+       cm_info.loc_addr = htonl(cm_id->local_addr.sin_addr.s_addr);
+       cm_info.loc_port = htons(cm_id->local_addr.sin_port);
+       cm_info.rem_addr = htonl(cm_id->remote_addr.sin_addr.s_addr);
+       cm_info.rem_port = htons(cm_id->remote_addr.sin_port);
        cm_info.cm_id = cm_id;
        cm_info.conn_type = NES_CM_IWARP_CONN_TYPE;
 
        cm_id->add_ref(cm_id);
-       nes_add_ref(&nesqp->ibqp);
 
        /* create a connect CM node connection */
-       cm_node = g_cm_core->api->connect(g_cm_core, nesvnic, nesqp->ietf_frame, &cm_info);
+       cm_node = g_cm_core->api->connect(g_cm_core, nesvnic,
+               conn_param->private_data_len, (void *)conn_param->private_data,
+               &cm_info);
        if (!cm_node) {
-               if (cm_id->local_addr.sin_addr.s_addr != cm_id->remote_addr.sin_addr.s_addr)
+               if (cm_id->local_addr.sin_addr.s_addr !=
+                               cm_id->remote_addr.sin_addr.s_addr)
                        nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
-                                       PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
-               nes_rem_ref(&nesqp->ibqp);
-               kfree(nesqp->ietf_frame);
-               nesqp->ietf_frame = NULL;
+                               PCI_FUNC(nesdev->pcidev->devfn),
+                               NES_MANAGE_APBVT_DEL);
+
                cm_id->rem_ref(cm_id);
                return -ENOMEM;
        }
 
        cm_node->apbvt_set = 1;
        nesqp->cm_node = cm_node;
+       cm_node->nesqp = nesqp;
 
        return 0;
 }
@@ -2664,7 +2878,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
 
        cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);
        if (!cm_node) {
-               printk("%s[%u] Error returned from listen API call\n",
+               printk(KERN_ERR "%s[%u] Error returned from listen API call\n",
                                __func__, __LINE__);
                return -ENOMEM;
        }
@@ -2672,10 +2886,13 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
        cm_id->provider_data = cm_node;
 
        if (!cm_node->reused_node) {
-               err = nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
-                               PCI_FUNC(nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
+               err = nes_manage_apbvt(nesvnic,
+                       ntohs(cm_id->local_addr.sin_port),
+                       PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
+                       NES_MANAGE_APBVT_ADD);
                if (err) {
-                       printk("nes_manage_apbvt call returned %d.\n", err);
+                       printk(KERN_ERR "nes_manage_apbvt call returned %d.\n",
+                               err);
                        g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);
                        return err;
                }
@@ -2795,53 +3012,70 @@ static void cm_event_connected(struct nes_cm_event *event)
        nes_cm_init_tsa_conn(nesqp, cm_node);
 
        /* set the QP tsa context */
-       nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(cm_id->local_addr.sin_port));
-       nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(cm_id->remote_addr.sin_port));
-       nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
+       nesqp->nesqp_context->tcpPorts[0] =
+               cpu_to_le16(ntohs(cm_id->local_addr.sin_port));
+       nesqp->nesqp_context->tcpPorts[1] =
+               cpu_to_le16(ntohs(cm_id->remote_addr.sin_port));
+       if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr))
+               nesqp->nesqp_context->ip0 =
+                       cpu_to_le32(ntohl(nesvnic->local_ipaddr));
+       else
+               nesqp->nesqp_context->ip0 =
+                       cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
 
        nesqp->nesqp_context->misc2 |= cpu_to_le32(
-                       (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
+                       (u32)PCI_FUNC(nesdev->pcidev->devfn) <<
+                       NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
        nesqp->nesqp_context->arp_index_vlan |= cpu_to_le32(
-                       nes_arp_table(nesdev, le32_to_cpu(nesqp->nesqp_context->ip0),
+                       nes_arp_table(nesdev,
+                       le32_to_cpu(nesqp->nesqp_context->ip0),
                        NULL, NES_ARP_RESOLVE) << 16);
        nesqp->nesqp_context->ts_val_delta = cpu_to_le32(
                        jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
        nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id);
        nesqp->nesqp_context->ird_ord_sizes |=
-                       cpu_to_le32((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT);
+                       cpu_to_le32((u32)1 <<
+                       NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT);
 
        /* Adjust tail for not having a LSMM */
        nesqp->hwqp.sq_tail = 1;
 
 #if defined(NES_SEND_FIRST_WRITE)
-               if (cm_node->send_write0) {
-                       nes_debug(NES_DBG_CM, "Sending first write.\n");
-                       wqe = &nesqp->hwqp.sq_vbase[0];
-                       u64temp = (unsigned long)nesqp;
-                       u64temp |= NES_SW_CONTEXT_ALIGN>>1;
-                       set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
-                                           u64temp);
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
-                       wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
-
-                       /* use the reserved spot on the WQ for the extra first WQE */
-                       nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
-                                       NES_QPCONTEXT_ORDIRD_WRPDU | NES_QPCONTEXT_ORDIRD_ALSMM));
-                       nesqp->skip_lsmm = 1;
-                       nesqp->hwqp.sq_tail = 0;
-                       nes_write32(nesdev->regs + NES_WQE_ALLOC,
-                                       (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
-               }
+       if (cm_node->send_write0) {
+               nes_debug(NES_DBG_CM, "Sending first write.\n");
+               wqe = &nesqp->hwqp.sq_vbase[0];
+               u64temp = (unsigned long)nesqp;
+               u64temp |= NES_SW_CONTEXT_ALIGN>>1;
+               set_wqe_64bit_value(wqe->wqe_words,
+                               NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
+               wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+                       cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
+               wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
+               wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
+               wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
+               wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
+               wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+
+               /* use the reserved spot on the WQ for the extra first WQE */
+               nesqp->nesqp_context->ird_ord_sizes &=
+                       cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
+                                               NES_QPCONTEXT_ORDIRD_WRPDU |
+                                               NES_QPCONTEXT_ORDIRD_ALSMM));
+               nesqp->skip_lsmm = 1;
+               nesqp->hwqp.sq_tail = 0;
+               nes_write32(nesdev->regs + NES_WQE_ALLOC,
+                               (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
+       }
 #endif
 
        memset(&nes_quad, 0, sizeof(nes_quad));
 
-       nes_quad.DstIpAdrIndex = cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
-       nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr;
+       nes_quad.DstIpAdrIndex =
+               cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
+       if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr))
+               nes_quad.SrcIpadr = nesvnic->local_ipaddr;
+       else
+               nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr;
        nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port;
        nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port;
 
@@ -2858,10 +3092,6 @@ static void cm_event_connected(struct nes_cm_event *event)
        nesqp->private_data_len = (u8) cm_node->mpa_frame_size;
        cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
 
-       /* modify QP state to rts */
-       attr.qp_state = IB_QPS_RTS;
-       nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
-
        /* notify OF layer we successfully created the requested connection */
        cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
        cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED;
@@ -2870,20 +3100,21 @@ static void cm_event_connected(struct nes_cm_event *event)
        cm_event.local_addr.sin_port = cm_id->local_addr.sin_port;
        cm_event.remote_addr = cm_id->remote_addr;
 
-               cm_event.private_data = (void *)event->cm_node->mpa_frame_buf;
-               cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size;
+       cm_event.private_data = (void *)event->cm_node->mpa_frame_buf;
+       cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size;
 
        cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr;
        ret = cm_id->event_handler(cm_id, &cm_event);
        nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
 
        if (ret)
-               printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
-                               __func__, __LINE__, ret);
-       nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = %lu\n",
-                       nesqp->hwqp.qp_id, jiffies );
+               printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
+                       "ret=%d\n", __func__, __LINE__, ret);
+       attr.qp_state = IB_QPS_RTS;
+       nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
 
-       nes_rem_ref(&nesqp->ibqp);
+       nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = "
+               "%lu\n", nesqp->hwqp.qp_id, jiffies);
 
        return;
 }
@@ -2927,17 +3158,19 @@ static void cm_event_connect_error(struct nes_cm_event *event)
        cm_event.private_data = NULL;
        cm_event.private_data_len = 0;
 
-       nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, remove_addr=%08x\n",
-                       cm_event.local_addr.sin_addr.s_addr, cm_event.remote_addr.sin_addr.s_addr);
+       nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, "
+               "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
+               cm_event.remote_addr.sin_addr.s_addr);
 
        ret = cm_id->event_handler(cm_id, &cm_event);
        nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
        if (ret)
-               printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
-                               __func__, __LINE__, ret);
+               printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
+                       "ret=%d\n", __func__, __LINE__, ret);
        nes_rem_ref(&nesqp->ibqp);
-               cm_id->rem_ref(cm_id);
+       cm_id->rem_ref(cm_id);
 
+       rem_ref_cm_node(event->cm_node->cm_core, event->cm_node);
        return;
 }
 
@@ -3040,7 +3273,8 @@ static int nes_cm_post_event(struct nes_cm_event *event)
        add_ref_cm_node(event->cm_node);
        event->cm_info.cm_id->add_ref(event->cm_info.cm_id);
        INIT_WORK(&event->event_work, nes_cm_event_handler);
-       nes_debug(NES_DBG_CM, "queue_work, event=%p\n", event);
+       nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n",
+               event->cm_node, event);
 
        queue_work(event->cm_node->cm_core->event_wq, &event->event_work);
 
@@ -3056,46 +3290,48 @@ static int nes_cm_post_event(struct nes_cm_event *event)
  */
 static void nes_cm_event_handler(struct work_struct *work)
 {
-       struct nes_cm_event *event = container_of(work, struct nes_cm_event, event_work);
+       struct nes_cm_event *event = container_of(work, struct nes_cm_event,
+                       event_work);
        struct nes_cm_core *cm_core;
 
-       if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core)) {
+       if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core))
                return;
-       }
+
        cm_core = event->cm_node->cm_core;
        nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n",
-                       event, event->type, atomic_read(&cm_core->events_posted));
+               event, event->type, atomic_read(&cm_core->events_posted));
 
        switch (event->type) {
-               case NES_CM_EVENT_MPA_REQ:
-                       cm_event_mpa_req(event);
-                       nes_debug(NES_DBG_CM, "CM Event: MPA REQUEST\n");
-                       break;
-               case NES_CM_EVENT_RESET:
-                       nes_debug(NES_DBG_CM, "CM Event: RESET\n");
-                       cm_event_reset(event);
-                       break;
-               case NES_CM_EVENT_CONNECTED:
-                       if ((!event->cm_node->cm_id) ||
-                               (event->cm_node->state != NES_CM_STATE_TSA)) {
-                               break;
-                       }
-                       cm_event_connected(event);
-                       nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
+       case NES_CM_EVENT_MPA_REQ:
+               cm_event_mpa_req(event);
+               nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n",
+                       event->cm_node);
+               break;
+       case NES_CM_EVENT_RESET:
+               nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n",
+                       event->cm_node);
+               cm_event_reset(event);
+               break;
+       case NES_CM_EVENT_CONNECTED:
+               if ((!event->cm_node->cm_id) ||
+                       (event->cm_node->state != NES_CM_STATE_TSA))
                        break;
-               case NES_CM_EVENT_ABORTED:
-                       if ((!event->cm_node->cm_id) || (event->cm_node->state == NES_CM_STATE_TSA)) {
-                               break;
-                       }
-                       cm_event_connect_error(event);
-                       nes_debug(NES_DBG_CM, "CM Event: ABORTED\n");
-                       break;
-               case NES_CM_EVENT_DROPPED_PKT:
-                       nes_debug(NES_DBG_CM, "CM Event: DROPPED PKT\n");
-                       break;
-               default:
-                       nes_debug(NES_DBG_CM, "CM Event: UNKNOWN EVENT TYPE\n");
+               cm_event_connected(event);
+               nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
+               break;
+       case NES_CM_EVENT_ABORTED:
+               if ((!event->cm_node->cm_id) ||
+                       (event->cm_node->state == NES_CM_STATE_TSA))
                        break;
+               cm_event_connect_error(event);
+               nes_debug(NES_DBG_CM, "CM Event: ABORTED\n");
+               break;
+       case NES_CM_EVENT_DROPPED_PKT:
+               nes_debug(NES_DBG_CM, "CM Event: DROPPED PKT\n");
+               break;
+       default:
+               nes_debug(NES_DBG_CM, "CM Event: UNKNOWN EVENT TYPE\n");
+               break;
        }
 
        atomic_dec(&cm_core->events_posted);
index 7717cb2ab50057e959095fb6a1047a8b3785a20b..367b3d29014074252424c798f110821b5ce0c7c4 100644 (file)
@@ -83,6 +83,8 @@ enum nes_timer_type {
 #define SET_FIN 4
 #define SET_RST 8
 
+#define TCP_OPTIONS_PADDING    3
+
 struct option_base {
        u8 optionnum;
        u8 length;
@@ -177,6 +179,7 @@ enum nes_cm_node_state {
        NES_CM_STATE_ESTABLISHED,
        NES_CM_STATE_ACCEPTING,
        NES_CM_STATE_MPAREQ_SENT,
+       NES_CM_STATE_MPAREQ_RCVD,
        NES_CM_STATE_TSA,
        NES_CM_STATE_FIN_WAIT1,
        NES_CM_STATE_FIN_WAIT2,
@@ -187,6 +190,16 @@ enum nes_cm_node_state {
        NES_CM_STATE_CLOSED
 };
 
+enum nes_tcpip_pkt_type {
+       NES_PKT_TYPE_UNKNOWN,
+       NES_PKT_TYPE_SYN,
+       NES_PKT_TYPE_SYNACK,
+       NES_PKT_TYPE_ACK,
+       NES_PKT_TYPE_FIN,
+       NES_PKT_TYPE_RST
+};
+
+
 /* type of nes connection */
 enum nes_cm_conn_type {
        NES_CM_IWARP_CONN_TYPE,
@@ -257,7 +270,9 @@ struct nes_cm_node {
        struct net_device         *netdev;
 
        struct nes_cm_node        *loopbackpartner;
-       struct list_head          retrans_list;
+
+       struct nes_timer_entry  *send_entry;
+
        spinlock_t                retrans_list_lock;
        struct list_head          recv_list;
        spinlock_t                recv_list_lock;
@@ -276,6 +291,8 @@ struct nes_cm_node {
        struct nes_vnic           *nesvnic;
        int                       apbvt_set;
        int                       accept_pend;
+       int                     freed;
+       struct nes_qp           *nesqp;
 };
 
 /* structure for client or CM to fill when making CM api calls. */
@@ -366,14 +383,14 @@ struct nes_cm_ops {
                        struct nes_cm_info *);
        int (*stop_listener)(struct nes_cm_core *, struct nes_cm_listener *);
        struct nes_cm_node * (*connect)(struct nes_cm_core *,
-                       struct nes_vnic *, struct ietf_mpa_frame *,
+                       struct nes_vnic *, u16, void *,
                        struct nes_cm_info *);
        int (*close)(struct nes_cm_core *, struct nes_cm_node *);
        int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *,
                        struct nes_cm_node *);
        int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *,
                        struct nes_cm_node *);
-       int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
+       void (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
                        struct sk_buff *);
        int (*destroy_cm_core)(struct nes_cm_core *);
        int (*get)(struct nes_cm_core *);
index 85f26d19a32b26187a9289a90fa6c600e33fc0b3..1513d4066f1b965b2dc55a878f7cb28353c3e91f 100644 (file)
@@ -2814,7 +2814,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                        nesqp = *((struct nes_qp **)&context);
                        if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
                                nesqp->cm_id->add_ref(nesqp->cm_id);
-                               nes_add_ref(&nesqp->ibqp);
                                schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,
                                                NES_TIMER_TYPE_CLOSE, 1, 0);
                                nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d),"
@@ -2838,7 +2837,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                        if (async_event_id == NES_AEQE_AEID_RESET_SENT) {
                                tcp_state = NES_AEQE_TCP_STATE_CLOSED;
                        }
-                       nes_add_ref(&nesqp->ibqp);
                        spin_lock_irqsave(&nesqp->lock, flags);
                        nesqp->hw_iwarp_state = iwarp_state;
                        nesqp->hw_tcp_state = tcp_state;
@@ -2876,7 +2874,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                }
                                spin_unlock_irqrestore(&nesqp->lock, flags);
                                if (next_iwarp_state) {
-                                       nes_add_ref(&nesqp->ibqp);
                                        nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
                                                        " also added another reference\n",
                                                        nesqp->hwqp.qp_id, next_iwarp_state);
@@ -2888,7 +2885,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                        /* FIN Received but ib state not RTS,
                                                        close complete will be on its way */
                                        spin_unlock_irqrestore(&nesqp->lock, flags);
-                                       nes_rem_ref(&nesqp->ibqp);
                                        return;
                                }
                                spin_unlock_irqrestore(&nesqp->lock, flags);
@@ -2922,7 +2918,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                        if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
                                        ((nesqp->ibqp_state == IB_QPS_RTS)&&
                                        (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
-                               nes_add_ref(&nesqp->ibqp);
                                nes_cm_disconn(nesqp);
                        } else {
                                nesqp->in_disconnect = 0;
@@ -2931,7 +2926,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                        break;
                case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES:
                        nesqp = *((struct nes_qp **)&context);
-                       nes_add_ref(&nesqp->ibqp);
                        spin_lock_irqsave(&nesqp->lock, flags);
                        nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR;
                        nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
@@ -3042,7 +3036,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
                        }
                        /* tell cm to disconnect, cm will queue work to thread */
-                       nes_add_ref(&nesqp->ibqp);
                        nes_cm_disconn(nesqp);
                        break;
                case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
@@ -3062,7 +3055,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
                        }
                        /* tell cm to disconnect, cm will queue work to thread */
-                       nes_add_ref(&nesqp->ibqp);
                        nes_cm_disconn(nesqp);
                        break;
                case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
@@ -3082,7 +3074,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
                        }
                        /* tell cm to disconnect, cm will queue work to thread */
-                       nes_add_ref(&nesqp->ibqp);
                        nes_cm_disconn(nesqp);
                        break;
                        /* TODO: additional AEs need to be here */
index e3939d13484ef4358453c25127d8e26134c47ec6..d79942e849799341e8f676f2436dacd6be2bd793 100644 (file)
@@ -2867,7 +2867,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                        nesqp->hwqp.qp_id, attr->qp_state, nesqp->ibqp_state,
                        nesqp->iwarp_state, atomic_read(&nesqp->refcount));
 
-       nes_add_ref(&nesqp->ibqp);
        spin_lock_irqsave(&nesqp->lock, qplockflags);
 
        nes_debug(NES_DBG_MOD_QP, "QP%u: hw_iwarp_state=0x%X, hw_tcp_state=0x%X,"
@@ -2882,7 +2881,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                                nesqp->hwqp.qp_id);
                                if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_IDLE) {
                                        spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                       nes_rem_ref(&nesqp->ibqp);
                                        return -EINVAL;
                                }
                                next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE;
@@ -2893,7 +2891,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                                nesqp->hwqp.qp_id);
                                if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_IDLE) {
                                        spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                       nes_rem_ref(&nesqp->ibqp);
                                        return -EINVAL;
                                }
                                next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE;
@@ -2904,14 +2901,12 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                                nesqp->hwqp.qp_id);
                                if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_RTS) {
                                        spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                       nes_rem_ref(&nesqp->ibqp);
                                        return -EINVAL;
                                }
                                if (nesqp->cm_id == NULL) {
                                        nes_debug(NES_DBG_MOD_QP, "QP%u: Failing attempt to move QP to RTS without a CM_ID. \n",
                                                        nesqp->hwqp.qp_id );
                                        spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                       nes_rem_ref(&nesqp->ibqp);
                                        return -EINVAL;
                                }
                                next_iwarp_state = NES_CQP_QP_IWARP_STATE_RTS;
@@ -2929,7 +2924,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                                nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail);
                                if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_CLOSING) {
                                        spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                       nes_rem_ref(&nesqp->ibqp);
                                        return 0;
                                } else {
                                        if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_CLOSING) {
@@ -2937,7 +2931,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                                                " ignored due to current iWARP state\n",
                                                                nesqp->hwqp.qp_id);
                                                spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                               nes_rem_ref(&nesqp->ibqp);
                                                return -EINVAL;
                                        }
                                        if (nesqp->hw_iwarp_state != NES_AEQE_IWARP_STATE_RTS) {
@@ -2969,7 +2962,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                                nesqp->hwqp.qp_id);
                                if (nesqp->iwarp_state>=(u32)NES_CQP_QP_IWARP_STATE_TERMINATE) {
                                        spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                       nes_rem_ref(&nesqp->ibqp);
                                        return -EINVAL;
                                }
                                /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */
@@ -2982,7 +2974,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                        case IB_QPS_RESET:
                                if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_ERROR) {
                                        spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                                       nes_rem_ref(&nesqp->ibqp);
                                        return -EINVAL;
                                }
                                nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n",
@@ -3008,7 +2999,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                break;
                        default:
                                spin_unlock_irqrestore(&nesqp->lock, qplockflags);
-                               nes_rem_ref(&nesqp->ibqp);
                                return -EINVAL;
                                break;
                }
@@ -3088,7 +3078,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                                        nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
                                                        original_last_aeq, nesqp->last_aeq);
                                        /* this one is for the cm_disconnect thread */
-                                       nes_add_ref(&nesqp->ibqp);
                                        spin_lock_irqsave(&nesqp->lock, qplockflags);
                                        nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
                                        nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
@@ -3097,14 +3086,12 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                } else {
                                        nes_debug(NES_DBG_MOD_QP, "QP%u No fake disconnect, QP refcount=%d\n",
                                                        nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
-                                       nes_rem_ref(&nesqp->ibqp);
                                }
                        } else {
                                spin_lock_irqsave(&nesqp->lock, qplockflags);
                                if (nesqp->cm_id) {
                                        /* These two are for the timer thread */
                                        if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
-                                               nes_add_ref(&nesqp->ibqp);
                                                nesqp->cm_id->add_ref(nesqp->cm_id);
                                                nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"
                                                                " need ae to finish up, original_last_aeq = 0x%04X."
@@ -3128,14 +3115,12 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                        " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
                                        nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
                                        original_last_aeq, nesqp->last_aeq);
-                       nes_rem_ref(&nesqp->ibqp);
                }
        } else {
                nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up,"
                                " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
                                nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
                                original_last_aeq, nesqp->last_aeq);
-               nes_rem_ref(&nesqp->ibqp);
        }
 
        err = 0;
index 691525cf394a34f4b2e4f68bf9ee5ee0f6b1cb85..9d9a9dc51f18141227cc097ee63477e75235ac48 100644 (file)
@@ -11,16 +11,17 @@ config INFINIBAND_IPOIB
 
 config INFINIBAND_IPOIB_CM
        bool "IP-over-InfiniBand Connected Mode support"
-       depends on INFINIBAND_IPOIB && EXPERIMENTAL
+       depends on INFINIBAND_IPOIB
        default n
        ---help---
-         This option enables experimental support for IPoIB connected mode.
-         After enabling this option, you need to switch to connected mode through
-         /sys/class/net/ibXXX/mode to actually create connections, and then increase
-         the interface MTU with e.g. ifconfig ib0 mtu 65520.
+         This option enables support for IPoIB connected mode.  After
+         enabling this option, you need to switch to connected mode
+         through /sys/class/net/ibXXX/mode to actually create
+         connections, and then increase the interface MTU with
+         e.g. ifconfig ib0 mtu 65520.
 
-         WARNING: Enabling connected mode will trigger some
-         packet drops for multicast and UD mode traffic from this interface,
+         WARNING: Enabling connected mode will trigger some packet
+         drops for multicast and UD mode traffic from this interface,
          unless you limit mtu for these destinations to 2044.
 
 config INFINIBAND_IPOIB_DEBUG
@@ -33,9 +34,10 @@ config INFINIBAND_IPOIB_DEBUG
          debug_level and mcast_debug_level module parameters (which
          can also be set after the driver is loaded through sysfs).
 
-         This option also creates an "ipoib_debugfs," which can be
-         mounted to expose debugging information about IB multicast
-         groups used by the IPoIB driver.
+         This option also creates a directory tree under ipoib/ in
+         debugfs, which contains files that expose debugging
+         information about IB multicast groups used by the IPoIB
+         driver.
 
 config INFINIBAND_IPOIB_DEBUG_DATA
        bool "IP-over-InfiniBand data path debugging"
index 8be9ea0436e6bf4751042a644bb78912a319627b..f51201b17bfd3048ddbd66fd4edadb41b310cdb0 100644 (file)
@@ -548,7 +548,7 @@ static int path_rec_start(struct net_device *dev,
                                   path_rec_completion,
                                   path, &path->query);
        if (path->query_id < 0) {
-               ipoib_warn(priv, "ib_sa_path_rec_get failed\n");
+               ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id);
                path->query = NULL;
                return path->query_id;
        }
index 3a917c1f796fe7d3931f43dec8e15c4716042ccf..63462ecca147ccfa9e0b40e2070d49412592ba67 100644 (file)
@@ -483,6 +483,7 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
                break;
        case RDMA_CM_EVENT_DISCONNECTED:
        case RDMA_CM_EVENT_DEVICE_REMOVAL:
+       case RDMA_CM_EVENT_ADDR_CHANGE:
                iser_disconnected_handler(cma_id);
                break;
        default:
index adbf29f0169d81f1f5a740243ade99756fc798cb..71c1971abf80873ba4a2a46590483b72428c4098 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/semaphore.h>
 #include <linux/slab.h>
 #include <linux/pci_ids.h>
 
index 8486abc457edd02c982cde57319388711cddc694..c600ab7f93e8029b2b00923d445745db9e7059ff 100644 (file)
@@ -158,25 +158,18 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev)
        memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata));
        pdata = &priv->pdata;
 
-       res = request_mem_region(res->start, res_size(res), pdev->name);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to request I/O memory\n");
-               error = -EBUSY;
-               goto err1;
-       }
-
        priv->iomem_base = ioremap_nocache(res->start, res_size(res));
        if (priv->iomem_base == NULL) {
                dev_err(&pdev->dev, "failed to remap I/O memory\n");
                error = -ENXIO;
-               goto err2;
+               goto err1;
        }
 
        priv->input = input_allocate_device();
        if (!priv->input) {
                dev_err(&pdev->dev, "failed to allocate input device\n");
                error = -ENOMEM;
-               goto err3;
+               goto err2;
        }
 
        input = priv->input;
@@ -194,7 +187,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev)
        error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev);
        if (error) {
                dev_err(&pdev->dev, "failed to request IRQ\n");
-               goto err4;
+               goto err3;
        }
 
        for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
@@ -206,7 +199,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev)
        error = input_register_device(input);
        if (error) {
                dev_err(&pdev->dev, "failed to register input device\n");
-               goto err5;
+               goto err4;
        }
 
        iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) |
@@ -214,14 +207,12 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev)
        iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
        iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS);
        return 0;
- err5:
-       free_irq(irq, pdev);
  err4:
-       input_free_device(input);
+       free_irq(irq, pdev);
  err3:
-       iounmap(priv->iomem_base);
+       input_free_device(input);
  err2:
-       release_mem_region(res->start, res_size(res));
+       iounmap(priv->iomem_base);
  err1:
        platform_set_drvdata(pdev, NULL);
        kfree(priv);
@@ -232,7 +223,6 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev)
 static int __devexit sh_keysc_remove(struct platform_device *pdev)
 {
        struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
-       struct resource *res;
 
        iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
 
@@ -240,9 +230,6 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev)
        free_irq(platform_get_irq(pdev, 0), pdev);
        iounmap(priv->iomem_base);
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, res_size(res));
-
        platform_set_drvdata(pdev, NULL);
        kfree(priv);
        return 0;
index 49d8abfe38fe01c3db1fe0702d125daaf4605e00..daa9d4220331b06e68b9100caad9c5e98065a48f 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/proc_fs.h>
 #include <linux/poll.h>
 #include <linux/rtc.h>
+#include <linux/semaphore.h>
 
 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
 MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver");
index 2bcfa0b3506145951f9fb53d85cf0bcaea739e94..223d56d5555b345e9068e9d7957e8843f980c032 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/uinput.h>
-#include <linux/smp_lock.h>
 
 static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
index 7b233a492ad5165aa358f2f63b67831c54a09f7e..0d395979b2d19c2a35ddb31e6d8c915c363fcfd9 100644 (file)
@@ -67,9 +67,9 @@
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/time.h>
+#include <linux/semaphore.h>
 #include <linux/slab.h>
 #include <linux/hil.h>
-#include <linux/semaphore.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
index 78f2abb5c11be1ddf38bc812b5200b2ae20299b5..2f12d60eee3b4e61f4b93363f5458189d471b0c1 100644 (file)
@@ -63,8 +63,9 @@ static LIST_HEAD(serio_list);
 static struct bus_type serio_bus;
 
 static void serio_add_port(struct serio *serio);
-static void serio_reconnect_port(struct serio *serio);
+static int serio_reconnect_port(struct serio *serio);
 static void serio_disconnect_port(struct serio *serio);
+static void serio_reconnect_chain(struct serio *serio);
 static void serio_attach_driver(struct serio_driver *drv);
 
 static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
@@ -161,6 +162,7 @@ static void serio_find_driver(struct serio *serio)
 enum serio_event_type {
        SERIO_RESCAN_PORT,
        SERIO_RECONNECT_PORT,
+       SERIO_RECONNECT_CHAIN,
        SERIO_REGISTER_PORT,
        SERIO_ATTACH_DRIVER,
 };
@@ -315,6 +317,10 @@ static void serio_handle_event(void)
                                serio_find_driver(event->object);
                                break;
 
+                       case SERIO_RECONNECT_CHAIN:
+                               serio_reconnect_chain(event->object);
+                               break;
+
                        case SERIO_ATTACH_DRIVER:
                                serio_attach_driver(event->object);
                                break;
@@ -470,7 +476,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
        if (!strncmp(buf, "none", count)) {
                serio_disconnect_port(serio);
        } else if (!strncmp(buf, "reconnect", count)) {
-               serio_reconnect_port(serio);
+               serio_reconnect_chain(serio);
        } else if (!strncmp(buf, "rescan", count)) {
                serio_disconnect_port(serio);
                serio_find_driver(serio);
@@ -619,15 +625,31 @@ static void serio_destroy_port(struct serio *serio)
        put_device(&serio->dev);
 }
 
+/*
+ * Reconnect serio port (re-initialize attached device).
+ * If reconnect fails (old device is no longer attached or
+ * there was no device to begin with) we do full rescan in
+ * hope of finding a driver for the port.
+ */
+static int serio_reconnect_port(struct serio *serio)
+{
+       int error = serio_reconnect_driver(serio);
+
+       if (error) {
+               serio_disconnect_port(serio);
+               serio_find_driver(serio);
+       }
+
+       return error;
+}
+
 /*
  * Reconnect serio port and all its children (re-initialize attached devices)
  */
-static void serio_reconnect_port(struct serio *serio)
+static void serio_reconnect_chain(struct serio *serio)
 {
        do {
-               if (serio_reconnect_driver(serio)) {
-                       serio_disconnect_port(serio);
-                       serio_find_driver(serio);
+               if (serio_reconnect_port(serio)) {
                        /* Ok, old children are now gone, we are done */
                        break;
                }
@@ -673,7 +695,7 @@ void serio_rescan(struct serio *serio)
 
 void serio_reconnect(struct serio *serio)
 {
-       serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT);
+       serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN);
 }
 
 /*
@@ -927,19 +949,16 @@ static int serio_suspend(struct device *dev, pm_message_t state)
 
 static int serio_resume(struct device *dev)
 {
-       struct serio *serio = to_serio_port(dev);
-
-       if (dev->power.power_state.event != PM_EVENT_ON &&
-           serio_reconnect_driver(serio)) {
-               /*
-                * Driver re-probing can take a while, so better let kseriod
-                * deal with it.
-                */
-               serio_rescan(serio);
+       /*
+        * Driver reconnect can take a while, so better let kseriod
+        * deal with it.
+        */
+       if (dev->power.power_state.event != PM_EVENT_ON) {
+               dev->power.power_state = PMSG_ON;
+               serio_queue_event(to_serio_port(dev), NULL,
+                                 SERIO_RECONNECT_PORT);
        }
 
-       dev->power.power_state = PMSG_ON;
-
        return 0;
 }
 #endif /* CONFIG_PM */
index e5736652157269804fbbd3a512691be496257867..6e60a97a234c108540d68ca9ddedf22167b4318e 100644 (file)
@@ -205,6 +205,18 @@ config TOUCHSCREEN_TOUCHWIN
          To compile this driver as a module, choose M here: the
          module will be called touchwin.
 
+config TOUCHSCREEN_ATMEL_TSADCC
+       tristate "Atmel Touchscreen Interface"
+       depends on ARCH_AT91SAM9RL
+       help
+         Say Y here if you have a 4-wire touchscreen connected to the
+          ADC Controller on your Atmel SoC (such as the AT91SAM9RL).
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called atmel_tsadcc.
+
 config TOUCHSCREEN_UCB1400
        tristate "Philips UCB1400 touchscreen"
        select AC97_BUS
index 39a804cd80f1428613bc929c7856ead0cdf12bc7..15cf2907948952df00b961ad2f0d97407b4a2faa 100644 (file)
@@ -7,6 +7,7 @@
 wm97xx-ts-y := wm97xx-core.o
 
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)      += ads7846.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)                += h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_CORGI)                += corgi_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)                += gunze.o
index 907a45fe9d40f5a828bd002ecd8d05d1562d353a..ce6f48c695f553a703a9c9af3c739996bc2c971c 100644 (file)
@@ -517,7 +517,9 @@ static void ads7846_rx(void *ads)
        if (x == MAX_12BIT)
                x = 0;
 
-       if (likely(x && z1)) {
+       if (ts->model == 7843) {
+               Rt = ts->pressure_max / 2;
+       } else if (likely(x && z1)) {
                /* compute touch pressure resistance using equation #2 */
                Rt = z2;
                Rt -= z1;
@@ -525,11 +527,9 @@ static void ads7846_rx(void *ads)
                Rt *= ts->x_plate_ohms;
                Rt /= z1;
                Rt = (Rt + 2047) >> 12;
-       } else
+       } else {
                Rt = 0;
-
-       if (ts->model == 7843)
-               Rt = ts->pressure_max / 2;
+       }
 
        /* Sample found inconsistent by debouncing or pressure is beyond
         * the maximum. Don't report it to user space, repeat at least
@@ -633,19 +633,17 @@ static void ads7846_rx_val(void *ads)
        struct ads7846 *ts = ads;
        struct spi_message *m;
        struct spi_transfer *t;
-       u16 *rx_val;
        int val;
        int action;
        int status;
 
        m = &ts->msg[ts->msg_idx];
        t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
-       rx_val = t->rx_buf;
 
        /* adjust:  on-wire is a must-ignore bit, a BE12 value, then padding;
         * built from two 8 bit values written msb-first.
         */
-       val = be16_to_cpu(*rx_val) >> 3;
+       val = be16_to_cpup((__be16 *)t->rx_buf) >> 3;
 
        action = ts->filter(ts->filter_data, ts->msg_idx, &val);
        switch (action) {
@@ -659,7 +657,7 @@ static void ads7846_rx_val(void *ads)
                m = ts->last_msg;
                break;
        case ADS7846_FILTER_OK:
-               *rx_val = val;
+               *(u16 *)t->rx_buf = val;
                ts->tc.ignore = 0;
                m = &ts->msg[++ts->msg_idx];
                break;
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
new file mode 100644 (file)
index 0000000..eee126b
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ *  Atmel Touch Screen Driver
+ *
+ *  Copyright (c) 2008 ATMEL
+ *  Copyright (c) 2008 Dan Liang
+ *  Copyright (c) 2008 TimeSys Corporation
+ *  Copyright (c) 2008 Justin Waters
+ *
+ *  Based on touchscreen code from Atmel Corporation.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */
+
+#define ATMEL_TSADCC_CR                0x00    /* Control register */
+#define   ATMEL_TSADCC_SWRST   (1 << 0)        /* Software Reset*/
+#define          ATMEL_TSADCC_START    (1 << 1)        /* Start conversion */
+
+#define ATMEL_TSADCC_MR                0x04    /* Mode register */
+#define          ATMEL_TSADCC_TSAMOD   (3    <<  0)    /* ADC mode */
+#define            ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE   (0x0)   /* ADC Mode */
+#define            ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE    (0x1)   /* Touch Screen Only Mode */
+#define          ATMEL_TSADCC_LOWRES   (1    <<  4)    /* Resolution selection */
+#define          ATMEL_TSADCC_SLEEP    (1    <<  5)    /* Sleep mode */
+#define          ATMEL_TSADCC_PENDET   (1    <<  6)    /* Pen Detect selection */
+#define          ATMEL_TSADCC_PRESCAL  (0x3f <<  8)    /* Prescalar Rate Selection */
+#define          ATMEL_TSADCC_STARTUP  (0x7f << 16)    /* Start Up time */
+#define          ATMEL_TSADCC_SHTIM    (0xf  << 24)    /* Sample & Hold time */
+#define          ATMEL_TSADCC_PENDBC   (0xf  << 28)    /* Pen Detect debouncing time */
+
+#define ATMEL_TSADCC_TRGR      0x08    /* Trigger register */
+#define          ATMEL_TSADCC_TRGMOD   (7      <<  0)  /* Trigger mode */
+#define            ATMEL_TSADCC_TRGMOD_NONE            (0 << 0)
+#define     ATMEL_TSADCC_TRGMOD_EXT_RISING     (1 << 0)
+#define     ATMEL_TSADCC_TRGMOD_EXT_FALLING    (2 << 0)
+#define     ATMEL_TSADCC_TRGMOD_EXT_ANY                (3 << 0)
+#define     ATMEL_TSADCC_TRGMOD_PENDET         (4 << 0)
+#define     ATMEL_TSADCC_TRGMOD_PERIOD         (5 << 0)
+#define     ATMEL_TSADCC_TRGMOD_CONTINUOUS     (6 << 0)
+#define   ATMEL_TSADCC_TRGPER  (0xffff << 16)  /* Trigger period */
+
+#define ATMEL_TSADCC_TSR       0x0C    /* Touch Screen register */
+#define          ATMEL_TSADCC_TSFREQ   (0xf <<  0)     /* TS Frequency in Interleaved mode */
+#define          ATMEL_TSADCC_TSSHTIM  (0xf << 24)     /* Sample & Hold time */
+
+#define ATMEL_TSADCC_CHER      0x10    /* Channel Enable register */
+#define ATMEL_TSADCC_CHDR      0x14    /* Channel Disable register */
+#define ATMEL_TSADCC_CHSR      0x18    /* Channel Status register */
+#define          ATMEL_TSADCC_CH(n)    (1 << (n))      /* Channel number */
+
+#define ATMEL_TSADCC_SR                0x1C    /* Status register */
+#define          ATMEL_TSADCC_EOC(n)   (1 << ((n)+0))  /* End of conversion for channel N */
+#define          ATMEL_TSADCC_OVRE(n)  (1 << ((n)+8))  /* Overrun error for channel N */
+#define          ATMEL_TSADCC_DRDY     (1 << 16)       /* Data Ready */
+#define          ATMEL_TSADCC_GOVRE    (1 << 17)       /* General Overrun Error */
+#define          ATMEL_TSADCC_ENDRX    (1 << 18)       /* End of RX Buffer */
+#define          ATMEL_TSADCC_RXBUFF   (1 << 19)       /* TX Buffer full */
+#define          ATMEL_TSADCC_PENCNT   (1 << 20)       /* Pen contact */
+#define          ATMEL_TSADCC_NOCNT    (1 << 21)       /* No contact */
+
+#define ATMEL_TSADCC_LCDR      0x20    /* Last Converted Data register */
+#define          ATMEL_TSADCC_DATA     (0x3ff << 0)    /* Channel data */
+
+#define ATMEL_TSADCC_IER       0x24    /* Interrupt Enable register */
+#define ATMEL_TSADCC_IDR       0x28    /* Interrupt Disable register */
+#define ATMEL_TSADCC_IMR       0x2C    /* Interrupt Mask register */
+#define ATMEL_TSADCC_CDR0      0x30    /* Channel Data 0 */
+#define ATMEL_TSADCC_CDR1      0x34    /* Channel Data 1 */
+#define ATMEL_TSADCC_CDR2      0x38    /* Channel Data 2 */
+#define ATMEL_TSADCC_CDR3      0x3C    /* Channel Data 3 */
+#define ATMEL_TSADCC_CDR4      0x40    /* Channel Data 4 */
+#define ATMEL_TSADCC_CDR5      0x44    /* Channel Data 5 */
+
+#define ADC_CLOCK      1000000
+
+struct atmel_tsadcc {
+       struct input_dev        *input;
+       char                    phys[32];
+       struct clk              *clk;
+       int                     irq;
+};
+
+static void __iomem            *tsc_base;
+
+#define atmel_tsadcc_read(reg)         __raw_readl(tsc_base + (reg))
+#define atmel_tsadcc_write(reg, val)   __raw_writel((val), tsc_base + (reg))
+
+static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
+{
+       struct input_dev *input_dev = ((struct atmel_tsadcc *)dev)->input;
+
+       unsigned int absx;
+       unsigned int absy;
+       unsigned int status;
+       unsigned int reg;
+
+       status = atmel_tsadcc_read(ATMEL_TSADCC_SR);
+       status &= atmel_tsadcc_read(ATMEL_TSADCC_IMR);
+
+       if (status & ATMEL_TSADCC_NOCNT) {
+               /* Contact lost */
+               reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC;
+
+               atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
+               atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
+               atmel_tsadcc_write(ATMEL_TSADCC_IDR,
+                                  ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
+               atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
+
+               input_report_key(input_dev, BTN_TOUCH, 0);
+               input_sync(input_dev);
+
+       } else if (status & ATMEL_TSADCC_PENCNT) {
+               /* Pen detected */
+               reg = atmel_tsadcc_read(ATMEL_TSADCC_MR);
+               reg &= ~ATMEL_TSADCC_PENDBC;
+
+               atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT);
+               atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
+               atmel_tsadcc_write(ATMEL_TSADCC_IER,
+                                  ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
+               atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
+                                  ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16));
+
+       } else if (status & ATMEL_TSADCC_EOC(3)) {
+               /* Conversion finished */
+
+               absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
+               absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
+
+               absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
+               absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
+
+               input_report_abs(input_dev, ABS_X, absx);
+               input_report_abs(input_dev, ABS_Y, absy);
+               input_report_key(input_dev, BTN_TOUCH, 1);
+               input_sync(input_dev);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
+{
+       struct atmel_tsadcc     *ts_dev;
+       struct input_dev        *input_dev;
+       struct resource         *res;
+       int             err = 0;
+       unsigned int    prsc;
+       unsigned int    reg;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "no mmio resource defined.\n");
+               return -ENXIO;
+       }
+
+       /* Allocate memory for device */
+       ts_dev = kzalloc(sizeof(struct atmel_tsadcc), GFP_KERNEL);
+       if (!ts_dev) {
+               dev_err(&pdev->dev, "failed to allocate memory.\n");
+               return -ENOMEM;
+       }
+       platform_set_drvdata(pdev, ts_dev);
+
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               dev_err(&pdev->dev, "failed to allocate input device.\n");
+               err = -EBUSY;
+               goto err_free_mem;
+       }
+
+       ts_dev->irq = platform_get_irq(pdev, 0);
+       if (ts_dev->irq < 0) {
+               dev_err(&pdev->dev, "no irq ID is designated.\n");
+               err = -ENODEV;
+               goto err_free_dev;
+       }
+
+       if (!request_mem_region(res->start, res->end - res->start + 1,
+                               "atmel tsadcc regs")) {
+               dev_err(&pdev->dev, "resources is unavailable.\n");
+               err = -EBUSY;
+               goto err_free_dev;
+       }
+
+       tsc_base = ioremap(res->start, res->end - res->start + 1);
+       if (!tsc_base) {
+               dev_err(&pdev->dev, "failed to map registers.\n");
+               err = -ENOMEM;
+               goto err_release_mem;
+       }
+
+       err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, IRQF_DISABLED,
+                       pdev->dev.driver->name, ts_dev);
+       if (err) {
+               dev_err(&pdev->dev, "failed to allocate irq.\n");
+               goto err_unmap_regs;
+       }
+
+       ts_dev->clk = clk_get(&pdev->dev, "tsc_clk");
+       if (IS_ERR(ts_dev->clk)) {
+               dev_err(&pdev->dev, "failed to get ts_clk\n");
+               err = PTR_ERR(ts_dev->clk);
+               goto err_free_irq;
+       }
+
+       ts_dev->input = input_dev;
+
+       snprintf(ts_dev->phys, sizeof(ts_dev->phys),
+                "%s/input0", pdev->dev.bus_id);
+
+       input_dev->name = "atmel touch screen controller";
+       input_dev->phys = ts_dev->phys;
+       input_dev->dev.parent = &pdev->dev;
+
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+       input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0);
+
+       /* clk_enable() always returns 0, no need to check it */
+       clk_enable(ts_dev->clk);
+
+       prsc = clk_get_rate(ts_dev->clk);
+       dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc);
+
+       prsc = prsc / ADC_CLOCK / 2 - 1;
+
+       reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE          |
+               ((0x00 << 5) & ATMEL_TSADCC_SLEEP)      |       /* Normal Mode */
+               ((0x01 << 6) & ATMEL_TSADCC_PENDET)     |       /* Enable Pen Detect */
+               ((prsc << 8) & ATMEL_TSADCC_PRESCAL)    |       /* PRESCAL */
+               ((0x13 << 16) & ATMEL_TSADCC_STARTUP)   |       /* STARTUP */
+               ((0x0F << 28) & ATMEL_TSADCC_PENDBC);           /* PENDBC */
+
+       atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST);
+       atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
+       atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
+       atmel_tsadcc_write(ATMEL_TSADCC_TSR, (0x3 << 24) & ATMEL_TSADCC_TSSHTIM);
+
+       atmel_tsadcc_read(ATMEL_TSADCC_SR);
+       atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
+
+       /* All went ok, so register to the input system */
+       err = input_register_device(input_dev);
+       if (err)
+               goto err_fail;
+
+       return 0;
+
+err_fail:
+       clk_disable(ts_dev->clk);
+       clk_put(ts_dev->clk);
+err_free_irq:
+       free_irq(ts_dev->irq, ts_dev);
+err_unmap_regs:
+       iounmap(tsc_base);
+err_release_mem:
+       release_mem_region(res->start, res->end - res->start + 1);
+err_free_dev:
+       input_free_device(ts_dev->input);
+err_free_mem:
+       kfree(ts_dev);
+       return err;
+}
+
+static int __devexit atmel_tsadcc_remove(struct platform_device *pdev)
+{
+       struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev);
+       struct resource *res;
+
+       free_irq(ts_dev->irq, ts_dev);
+
+       input_unregister_device(ts_dev->input);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       iounmap(tsc_base);
+       release_mem_region(res->start, res->end - res->start + 1);
+
+       clk_disable(ts_dev->clk);
+       clk_put(ts_dev->clk);
+
+       kfree(ts_dev);
+
+       return 0;
+}
+
+static struct platform_driver atmel_tsadcc_driver = {
+       .probe          = atmel_tsadcc_probe,
+       .remove         = __devexit_p(atmel_tsadcc_remove),
+       .driver         = {
+               .name   = "atmel_tsadcc",
+       },
+};
+
+static int __init atmel_tsadcc_init(void)
+{
+       return platform_driver_register(&atmel_tsadcc_driver);
+}
+
+static void __exit atmel_tsadcc_exit(void)
+{
+       platform_driver_unregister(&atmel_tsadcc_driver);
+}
+
+module_init(atmel_tsadcc_init);
+module_exit(atmel_tsadcc_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Atmel TouchScreen Driver");
+MODULE_AUTHOR("Dan Liang <dan.liang@atmel.com>");
+
index 4e9d8eece2e003f8674d90a8f6ac0caaa447934f..d0e13fc4a88c0391976859d7561a69f381c17eac 100644 (file)
@@ -195,7 +195,7 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer)
 {
        if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) {
                /* Disable Interrupt */
-               set_irq_type(corgi_ts->irq_gpio, IRQT_NOEDGE);
+               set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_NONE);
                if (read_xydata(corgi_ts)) {
                        corgi_ts->pendown = 1;
                        new_data(corgi_ts);
@@ -214,7 +214,7 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer)
                }
 
                /* Enable Falling Edge */
-               set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
+               set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING);
                corgi_ts->pendown = 0;
        }
 }
@@ -258,7 +258,7 @@ static int corgits_resume(struct platform_device *dev)
 
        corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
        /* Enable Falling Edge */
-       set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
+       set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING);
        corgi_ts->power_mode = PWR_MODE_ACTIVE;
 
        return 0;
@@ -333,7 +333,7 @@ static int __init corgits_probe(struct platform_device *pdev)
        corgi_ts->power_mode = PWR_MODE_ACTIVE;
 
        /* Enable Falling Edge */
-       set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
+       set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING);
 
        return 0;
 
index a79f029b91c04ff0b8e15f5da3fac88d9d8558af..590a1379aa321b3b0c59d80504818e897314f7fb 100644 (file)
@@ -198,7 +198,7 @@ static int wm97xx_acc_startup(struct wm97xx *wm)
                switch (wm->id) {
                case WM9705_ID2:
                        wm->pen_irq = IRQ_GPIO(4);
-                       set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE);
+                       set_irq_type(IRQ_GPIO(4), IRQ_TYPE_EDGE_BOTH);
                        break;
                case WM9712_ID2:
                case WM9713_ID2:
index 66f946aa30b3fb0830b8a858e0ef91d9a47cfd73..3d113c6e4a703242e32c0d9f57cc09be29516690 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 menuconfig ISDN
-       tristate "ISDN support"
+       bool "ISDN support"
        depends on NET
        depends on !S390
        ---help---
@@ -21,6 +21,8 @@ menuconfig ISDN
 
 if ISDN
 
+source "drivers/isdn/mISDN/Kconfig"
+
 menuconfig ISDN_I4L
        tristate "Old ISDN4Linux (deprecated)"
        ---help---
index 988142c30a6d374c4db55b0d041bc30932ed0db6..8380a4568d11dda17aa5c0b92839a8ab334e5dbf 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_ISDN_I4L)                 += i4l/
 obj-$(CONFIG_ISDN_CAPI)                        += capi/
+obj-$(CONFIG_MISDN)                    += mISDN/
 obj-$(CONFIG_ISDN_CAPI)                        += hardware/
 obj-$(CONFIG_ISDN_DIVERSION)           += divert/
 obj-$(CONFIG_ISDN_DRV_HISAX)           += hisax/
index 091deb9d1c47cfb85e5252effbf019d65aba67e3..c2bd97d29273ce584b5182578d05d41fd995c3da 100644 (file)
@@ -575,7 +575,8 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
        else
                skb = iraw_encode(skb, HW_HDR_LEN, 0);
        if (!skb) {
-               err("unable to allocate memory for encoding!\n");
+               dev_err(bcs->cs->dev,
+                       "unable to allocate memory for encoding!\n");
                return -ENOMEM;
        }
 
index 5255b5e20e132021c46259eb0f44de8c3af3fb10..3f11910c7ccdbf4c2edb31d360f3e40feba77d4b 100644 (file)
@@ -1050,10 +1050,9 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
                }
 
                /* retrieve block of data to send */
-               ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf,
-                                                      ifd->length);
-               if (ifd->offset < 0) {
-                       if (ifd->offset == -EBUSY) {
+               rc = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length);
+               if (rc < 0) {
+                       if (rc == -EBUSY) {
                                gig_dbg(DEBUG_ISO,
                                        "%s: buffer busy at frame %d",
                                        __func__, nframe);
@@ -1062,11 +1061,12 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
                        } else {
                                dev_err(ucx->bcs->cs->dev,
                                        "%s: buffer error %d at frame %d\n",
-                                       __func__, ifd->offset, nframe);
-                               return ifd->offset;
+                                       __func__, rc, nframe);
+                               return rc;
                        }
                        break;
                }
+               ifd->offset = rc;
                ucx->limit = ubc->isooutbuf->nextread;
                ifd->status = 0;
                ifd->actual_length = 0;
index 827c32c167951aa3235477992697909ccd770944..9d3ce7718e58faac892540caf6c2e61eadd2f051 100644 (file)
@@ -287,7 +287,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
        tail = cs->ev_tail;
        next = (tail + 1) % MAX_EVENTS;
        if (unlikely(next == cs->ev_head))
-               err("event queue full");
+               dev_err(cs->dev, "event queue full\n");
        else {
                event = cs->events + tail;
                event->type = type;
index f365993161fcc6a2a8432e4d890c9ddef45b628a..003752954993cffa46534a2a3a95383fcddd8645 100644 (file)
@@ -106,7 +106,6 @@ enum debuglevel {
 #undef err
 #undef info
 #undef warn
-#undef notice
 
 #define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
        format "\n" , ## arg)
@@ -114,8 +113,6 @@ enum debuglevel {
        format "\n" , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \
        format "\n" , ## arg)
-#define notice(format, arg...) printk(KERN_NOTICE KBUILD_MODNAME ": " \
-       format "\n" , ## arg)
 
 #ifdef CONFIG_GIGASET_DEBUG
 
index 9e089f06a942a0e6aad81695819831fb47f7b2ca..3c127a8cbaf2261f473e28a01b29c0e00c2f2c93 100644 (file)
@@ -46,7 +46,8 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
                return -ENODEV;
        }
        if (channel < 0 || channel >= cs->channels) {
-               err("%s: invalid channel ID (%d)", __func__, channel);
+               dev_err(cs->dev, "%s: invalid channel ID (%d)\n",
+                       __func__, channel);
                return -ENODEV;
        }
        bcs = &cs->bcs[channel];
@@ -58,11 +59,13 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
 
        if (!len) {
                if (ack)
-                       notice("%s: not ACKing empty packet", __func__);
+                       dev_notice(cs->dev, "%s: not ACKing empty packet\n",
+                                  __func__);
                return 0;
        }
        if (len > MAX_BUF_SIZE) {
-               err("%s: packet too large (%d bytes)", __func__, len);
+               dev_err(cs->dev, "%s: packet too large (%d bytes)\n",
+                       __func__, len);
                return -EINVAL;
        }
 
@@ -116,8 +119,7 @@ static int command_from_LL(isdn_ctrl *cntrl)
        gigaset_debugdrivers();
 
        if (!cs) {
-               warn("LL tried to access unknown device with nr. %d",
-                    cntrl->driver);
+               err("%s: invalid driver ID (%d)", __func__, cntrl->driver);
                return -ENODEV;
        }
 
@@ -126,7 +128,7 @@ static int command_from_LL(isdn_ctrl *cntrl)
                gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)",
                        cntrl->driver, cntrl->arg);
 
-               warn("ISDN_CMD_IOCTL is not supported.");
+               dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n");
                return -EINVAL;
 
        case ISDN_CMD_DIAL:
@@ -138,22 +140,23 @@ static int command_from_LL(isdn_ctrl *cntrl)
                        cntrl->parm.setup.si1, cntrl->parm.setup.si2);
 
                if (cntrl->arg >= cs->channels) {
-                       err("ISDN_CMD_DIAL: invalid channel (%d)",
-                           (int) cntrl->arg);
+                       dev_err(cs->dev,
+                               "ISDN_CMD_DIAL: invalid channel (%d)\n",
+                               (int) cntrl->arg);
                        return -EINVAL;
                }
 
                bcs = cs->bcs + cntrl->arg;
 
                if (!gigaset_get_channel(bcs)) {
-                       err("ISDN_CMD_DIAL: channel not free");
+                       dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
                        return -EBUSY;
                }
 
                sp = kmalloc(sizeof *sp, GFP_ATOMIC);
                if (!sp) {
                        gigaset_free_channel(bcs);
-                       err("ISDN_CMD_DIAL: out of memory");
+                       dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
                        return -ENOMEM;
                }
                *sp = cntrl->parm.setup;
@@ -173,8 +176,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
                gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
 
                if (cntrl->arg >= cs->channels) {
-                       err("ISDN_CMD_ACCEPTD: invalid channel (%d)",
-                           (int) cntrl->arg);
+                       dev_err(cs->dev,
+                               "ISDN_CMD_ACCEPTD: invalid channel (%d)\n",
+                               (int) cntrl->arg);
                        return -EINVAL;
                }
 
@@ -196,8 +200,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
                        (int) cntrl->arg);
 
                if (cntrl->arg >= cs->channels) {
-                       err("ISDN_CMD_HANGUP: invalid channel (%u)",
-                           (unsigned) cntrl->arg);
+                       dev_err(cs->dev,
+                               "ISDN_CMD_HANGUP: invalid channel (%d)\n",
+                               (int) cntrl->arg);
                        return -EINVAL;
                }
 
@@ -224,8 +229,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
                        cntrl->arg & 0xff, (cntrl->arg >> 8));
 
                if ((cntrl->arg & 0xff) >= cs->channels) {
-                       err("ISDN_CMD_SETL2: invalid channel (%u)",
-                           (unsigned) cntrl->arg & 0xff);
+                       dev_err(cs->dev,
+                               "ISDN_CMD_SETL2: invalid channel (%d)\n",
+                               (int) cntrl->arg & 0xff);
                        return -EINVAL;
                }
 
@@ -244,14 +250,16 @@ static int command_from_LL(isdn_ctrl *cntrl)
                        cntrl->arg & 0xff, (cntrl->arg >> 8));
 
                if ((cntrl->arg & 0xff) >= cs->channels) {
-                       err("ISDN_CMD_SETL3: invalid channel (%u)",
-                           (unsigned) cntrl->arg & 0xff);
+                       dev_err(cs->dev,
+                               "ISDN_CMD_SETL3: invalid channel (%d)\n",
+                               (int) cntrl->arg & 0xff);
                        return -EINVAL;
                }
 
                if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
-                       err("ISDN_CMD_SETL3: invalid protocol %lu",
-                           cntrl->arg >> 8);
+                       dev_err(cs->dev,
+                               "ISDN_CMD_SETL3: invalid protocol %lu\n",
+                               cntrl->arg >> 8);
                        return -EINVAL;
                }
 
@@ -262,8 +270,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
        case ISDN_CMD_ALERT:
                gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
                if (cntrl->arg >= cs->channels) {
-                       err("ISDN_CMD_ALERT: invalid channel (%d)",
-                           (int) cntrl->arg);
+                       dev_err(cs->dev,
+                               "ISDN_CMD_ALERT: invalid channel (%d)\n",
+                               (int) cntrl->arg);
                        return -EINVAL;
                }
                //bcs = cs->bcs + cntrl->arg;
@@ -295,7 +304,8 @@ static int command_from_LL(isdn_ctrl *cntrl)
                gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
                break;
        default:
-               err("unknown command %d from LL", cntrl->command);
+               dev_err(cs->dev, "unknown command %d from LL\n",
+                       cntrl->command);
                return -EINVAL;
        }
 
index af195b07c191b6b02b09c57548f6477334672a92..521951a898ece00218d3bd96645e94466c26a349 100644 (file)
@@ -197,7 +197,7 @@ static void if_close(struct tty_struct *tty, struct file *filp)
        mutex_lock(&cs->mutex);
 
        if (!cs->open_count)
-               warn("%s: device not opened", __func__);
+               dev_warn(cs->dev, "%s: device not opened\n", __func__);
        else {
                if (!--cs->open_count) {
                        spin_lock_irqsave(&cs->lock, flags);
@@ -232,7 +232,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file,
                return -ERESTARTSYS; // FIXME -EINTR?
 
        if (!cs->open_count)
-               warn("%s: device not opened", __func__);
+               dev_warn(cs->dev, "%s: device not opened\n", __func__);
        else {
                retval = 0;
                switch (cmd) {
@@ -364,9 +364,9 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
                return -ERESTARTSYS; // FIXME -EINTR?
 
        if (!cs->open_count)
-               warn("%s: device not opened", __func__);
+               dev_warn(cs->dev, "%s: device not opened\n", __func__);
        else if (cs->mstate != MS_LOCKED) {
-               warn("can't write to unlocked device");
+               dev_warn(cs->dev, "can't write to unlocked device\n");
                retval = -EBUSY;
        } else if (!cs->connected) {
                gig_dbg(DEBUG_ANY, "can't write to unplugged device");
@@ -398,9 +398,9 @@ static int if_write_room(struct tty_struct *tty)
                return -ERESTARTSYS; // FIXME -EINTR?
 
        if (!cs->open_count)
-               warn("%s: device not opened", __func__);
+               dev_warn(cs->dev, "%s: device not opened\n", __func__);
        else if (cs->mstate != MS_LOCKED) {
-               warn("can't write to unlocked device");
+               dev_warn(cs->dev, "can't write to unlocked device\n");
                retval = -EBUSY;
        } else if (!cs->connected) {
                gig_dbg(DEBUG_ANY, "can't write to unplugged device");
@@ -430,9 +430,9 @@ static int if_chars_in_buffer(struct tty_struct *tty)
                return -ERESTARTSYS; // FIXME -EINTR?
 
        if (!cs->open_count)
-               warn("%s: device not opened", __func__);
+               dev_warn(cs->dev, "%s: device not opened\n", __func__);
        else if (cs->mstate != MS_LOCKED) {
-               warn("can't write to unlocked device");
+               dev_warn(cs->dev, "can't write to unlocked device\n");
                retval = -EBUSY;
        } else if (!cs->connected) {
                gig_dbg(DEBUG_ANY, "can't write to unplugged device");
@@ -460,7 +460,7 @@ static void if_throttle(struct tty_struct *tty)
        mutex_lock(&cs->mutex);
 
        if (!cs->open_count)
-               warn("%s: device not opened", __func__);
+               dev_warn(cs->dev, "%s: device not opened\n", __func__);
        else {
                //FIXME
        }
@@ -483,7 +483,7 @@ static void if_unthrottle(struct tty_struct *tty)
        mutex_lock(&cs->mutex);
 
        if (!cs->open_count)
-               warn("%s: device not opened", __func__);
+               dev_warn(cs->dev, "%s: device not opened\n", __func__);
        else {
                //FIXME
        }
@@ -510,7 +510,7 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
        mutex_lock(&cs->mutex);
 
        if (!cs->open_count) {
-               warn("%s: device not opened", __func__);
+               dev_warn(cs->dev, "%s: device not opened\n", __func__);
                goto out;
        }
 
@@ -623,7 +623,8 @@ void gigaset_if_init(struct cardstate *cs)
        if (!IS_ERR(cs->tty_dev))
                dev_set_drvdata(cs->tty_dev, cs);
        else {
-               warn("could not register device to the tty subsystem");
+               dev_warn(cs->dev,
+                        "could not register device to the tty subsystem\n");
                cs->tty_dev = NULL;
        }
        mutex_unlock(&cs->mutex);
index 77d20ab0cd4d422b31226c9093a08eedb22ad937..4661830a49db9a471f349c4d30fbc323f363ccaa 100644 (file)
@@ -498,8 +498,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
 
                        if (status) {
                                ucs->busy = 0;
-                               err("could not submit urb (error %d)\n",
-                                   -status);
+                               dev_err(cs->dev,
+                                       "could not submit urb (error %d)\n",
+                                       -status);
                                cb->len = 0; /* skip urb => remove cb+wakeup
                                                in next loop cycle */
                        }
@@ -670,7 +671,7 @@ static int write_modem(struct cardstate *cs)
        spin_unlock_irqrestore(&cs->lock, flags);
 
        if (ret) {
-               err("could not submit urb (error %d)\n", -ret);
+               dev_err(cs->dev, "could not submit urb (error %d)\n", -ret);
                ucs->busy = 0;
        }
 
index 11c8a183948c60cddf556602b60c1c032bd2dc09..a5d8fce4c4c496acec316ddea08431a4ec274ebb 100644 (file)
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_CAPI_AVM)         += avm/
 obj-$(CONFIG_CAPI_EICON)       += eicon/
+obj-$(CONFIG_MISDN)            += mISDN/
diff --git a/drivers/isdn/hardware/mISDN/Kconfig b/drivers/isdn/hardware/mISDN/Kconfig
new file mode 100644 (file)
index 0000000..1479348
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# Hardware for mISDN
+#
+comment "mISDN hardware drivers"
+
+config MISDN_HFCPCI
+       tristate "Support for HFC PCI cards"
+       depends on MISDN
+       depends on PCI
+       help
+         Enable support for cards with Cologne Chip AG's
+          HFC PCI chip.
+
+config MISDN_HFCMULTI
+       tristate "Support for HFC multiport cards (HFC-4S/8S/E1)"
+       depends on PCI
+       depends on MISDN
+       help
+         Enable support for cards with Cologne Chip AG's HFC multiport
+         chip. There are three types of chips that are quite similar,
+         but the interface is different:
+          * HFC-4S (4 S/T interfaces on one chip)
+          * HFC-8S (8 S/T interfaces on one chip)
+          * HFC-E1 (E1 interface for 2Mbit ISDN)
+
diff --git a/drivers/isdn/hardware/mISDN/Makefile b/drivers/isdn/hardware/mISDN/Makefile
new file mode 100644 (file)
index 0000000..1e7ca53
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the modular ISDN hardware drivers
+#
+#
+
+obj-$(CONFIG_MISDN_HFCPCI) += hfcpci.o
+obj-$(CONFIG_MISDN_HFCMULTI) += hfcmulti.o
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
new file mode 100644 (file)
index 0000000..a33d87a
--- /dev/null
@@ -0,0 +1,1204 @@
+/*
+ * see notice in hfc_multi.c
+ */
+
+extern void ztdummy_extern_interrupt(void);
+extern void ztdummy_register_interrupt(void);
+extern int ztdummy_unregister_interrupt(void);
+
+#define DEBUG_HFCMULTI_FIFO    0x00010000
+#define        DEBUG_HFCMULTI_CRC      0x00020000
+#define        DEBUG_HFCMULTI_INIT     0x00040000
+#define        DEBUG_HFCMULTI_PLXSD    0x00080000
+#define        DEBUG_HFCMULTI_MODE     0x00100000
+#define        DEBUG_HFCMULTI_MSG      0x00200000
+#define        DEBUG_HFCMULTI_STATE    0x00400000
+#define        DEBUG_HFCMULTI_SYNC     0x01000000
+#define        DEBUG_HFCMULTI_DTMF     0x02000000
+#define        DEBUG_HFCMULTI_LOCK     0x80000000
+
+#define        PCI_ENA_REGIO   0x01
+#define        PCI_ENA_MEMIO   0x02
+
+/*
+ * NOTE: some registers are assigned multiple times due to different modes
+ *       also registers are assigned differen for HFC-4s/8s and HFC-E1
+ */
+
+/*
+#define MAX_FRAME_SIZE 2048
+*/
+
+struct hfc_chan {
+       struct dchannel *dch;   /* link if channel is a D-channel */
+       struct bchannel *bch;   /* link if channel is a B-channel */
+       int             port;   /* the interface port this */
+                               /* channel is associated with */
+       int             nt_timer; /* -1 if off, 0 if elapsed, >0 if running */
+       int             los, ais, slip_tx, slip_rx, rdi; /* current alarms */
+       int             jitter;
+       u_long          cfg;    /* port configuration */
+       int             sync;   /* sync state (used by E1) */
+       u_int           protocol; /* current protocol */
+       int             slot_tx; /* current pcm slot */
+       int             bank_tx; /* current pcm bank */
+       int             slot_rx;
+       int             bank_rx;
+       int             conf;   /* conference setting of TX slot */
+       int             txpending;      /* if there is currently data in */
+                                       /* the FIFO 0=no, 1=yes, 2=splloop */
+       int             rx_off; /* set to turn fifo receive off */
+       int             coeff_count; /* curren coeff block */
+       s32             *coeff; /* memory pointer to 8 coeff blocks */
+};
+
+
+struct hfcm_hw {
+       u_char  r_ctrl;
+       u_char  r_irq_ctrl;
+       u_char  r_cirm;
+       u_char  r_ram_sz;
+       u_char  r_pcm_md0;
+       u_char  r_irqmsk_misc;
+       u_char  r_dtmf;
+       u_char  r_st_sync;
+       u_char  r_sci_msk;
+       u_char  r_tx0, r_tx1;
+       u_char  a_st_ctrl0[8];
+       timer_t timer;
+};
+
+
+/* for each stack these flags are used (cfg) */
+#define        HFC_CFG_NONCAP_TX       1 /* S/T TX interface has less capacity */
+#define        HFC_CFG_DIS_ECHANNEL    2 /* disable E-channel processing */
+#define        HFC_CFG_REG_ECHANNEL    3 /* register E-channel */
+#define        HFC_CFG_OPTICAL         4 /* the E1 interface is optical */
+#define        HFC_CFG_REPORT_LOS      5 /* the card should report loss of signal */
+#define        HFC_CFG_REPORT_AIS      6 /* the card should report alarm ind. sign. */
+#define        HFC_CFG_REPORT_SLIP     7 /* the card should report bit slips */
+#define        HFC_CFG_REPORT_RDI      8 /* the card should report remote alarm */
+#define        HFC_CFG_DTMF            9 /* enable DTMF-detection */
+#define        HFC_CFG_CRC4            10 /* disable CRC-4 Multiframe mode, */
+                                       /* use double frame instead. */
+
+#define        HFC_CHIP_EXRAM_128      0 /* external ram 128k */
+#define        HFC_CHIP_EXRAM_512      1 /* external ram 256k */
+#define        HFC_CHIP_REVISION0      2 /* old fifo handling */
+#define        HFC_CHIP_PCM_SLAVE      3 /* PCM is slave */
+#define        HFC_CHIP_PCM_MASTER     4 /* PCM is master */
+#define        HFC_CHIP_RX_SYNC        5 /* disable pll sync for pcm */
+#define        HFC_CHIP_DTMF           6 /* DTMF decoding is enabled */
+#define        HFC_CHIP_ULAW           7 /* ULAW mode */
+#define        HFC_CHIP_CLOCK2         8 /* double clock mode */
+#define        HFC_CHIP_E1CLOCK_GET    9 /* always get clock from E1 interface */
+#define        HFC_CHIP_E1CLOCK_PUT    10 /* always put clock from E1 interface */
+#define        HFC_CHIP_WATCHDOG       11 /* whether we should send signals */
+                                       /* to the watchdog */
+#define        HFC_CHIP_B410P          12 /* whether we have a b410p with echocan in */
+                                       /* hw */
+#define        HFC_CHIP_PLXSD          13 /* whether we have a Speech-Design PLX */
+
+#define HFC_IO_MODE_PCIMEM     0x00 /* normal memory mapped IO */
+#define HFC_IO_MODE_REGIO      0x01 /* PCI io access */
+#define HFC_IO_MODE_PLXSD      0x02 /* access HFC via PLX9030 */
+
+/* table entry in the PCI devices list */
+struct hm_map {
+       char *vendor_name;
+       char *card_name;
+       int type;
+       int ports;
+       int clock2;
+       int leds;
+       int opticalsupport;
+       int dip_type;
+       int io_mode;
+};
+
+struct hfc_multi {
+       struct list_head        list;
+       struct hm_map   *mtyp;
+       int             id;
+       int             pcm;    /* id of pcm bus */
+       int             type;
+       int             ports;
+
+       u_int           irq;    /* irq used by card */
+       u_int           irqcnt;
+       struct pci_dev  *pci_dev;
+       int             io_mode; /* selects mode */
+#ifdef HFC_REGISTER_DEBUG
+       void            (*HFC_outb)(struct hfc_multi *hc, u_char reg,
+                               u_char val, const char *function, int line);
+       void            (*HFC_outb_nodebug)(struct hfc_multi *hc, u_char reg,
+                               u_char val, const char *function, int line);
+       u_char          (*HFC_inb)(struct hfc_multi *hc, u_char reg,
+                               const char *function, int line);
+       u_char          (*HFC_inb_nodebug)(struct hfc_multi *hc, u_char reg,
+                               const char *function, int line);
+       u_short         (*HFC_inw)(struct hfc_multi *hc, u_char reg,
+                               const char *function, int line);
+       u_short         (*HFC_inw_nodebug)(struct hfc_multi *hc, u_char reg,
+                               const char *function, int line);
+       void            (*HFC_wait)(struct hfc_multi *hc,
+                               const char *function, int line);
+       void            (*HFC_wait_nodebug)(struct hfc_multi *hc,
+                               const char *function, int line);
+#else
+       void            (*HFC_outb)(struct hfc_multi *hc, u_char reg,
+                               u_char val);
+       void            (*HFC_outb_nodebug)(struct hfc_multi *hc, u_char reg,
+                               u_char val);
+       u_char          (*HFC_inb)(struct hfc_multi *hc, u_char reg);
+       u_char          (*HFC_inb_nodebug)(struct hfc_multi *hc, u_char reg);
+       u_short         (*HFC_inw)(struct hfc_multi *hc, u_char reg);
+       u_short         (*HFC_inw_nodebug)(struct hfc_multi *hc, u_char reg);
+       void            (*HFC_wait)(struct hfc_multi *hc);
+       void            (*HFC_wait_nodebug)(struct hfc_multi *hc);
+#endif
+       void            (*read_fifo)(struct hfc_multi *hc, u_char *data,
+                               int len);
+       void            (*write_fifo)(struct hfc_multi *hc, u_char *data,
+                               int len);
+       u_long          pci_origmembase, plx_origmembase, dsp_origmembase;
+       u_char          *pci_membase; /* PCI memory (MUST BE BYTE POINTER) */
+       u_char          *plx_membase; /* PLX memory */
+       u_char          *dsp_membase; /* DSP on PLX */
+       u_long          pci_iobase; /* PCI IO */
+       struct hfcm_hw  hw;     /* remember data of write-only-registers */
+
+       u_long          chip;   /* chip configuration */
+       int             masterclk; /* port that provides master clock -1=off */
+       int             dtmf;   /* flag that dtmf is currently in process */
+       int             Flen;   /* F-buffer size */
+       int             Zlen;   /* Z-buffer size (must be int for calculation)*/
+       int             max_trans; /* maximum transparent fifo fill */
+       int             Zmin;   /* Z-buffer offset */
+       int             DTMFbase; /* base address of DTMF coefficients */
+
+       u_int           slots;  /* number of PCM slots */
+       u_int           leds;   /* type of leds */
+       u_int           ledcount; /* used to animate leds */
+       u_long          ledstate; /* save last state of leds */
+       int             opticalsupport; /* has the e1 board */
+                                       /* an optical Interface */
+       int             dslot;  /* channel # of d-channel (E1) default 16 */
+
+       u_long          wdcount;        /* every 500 ms we need to */
+                                       /* send the watchdog a signal */
+       u_char          wdbyte; /* watchdog toggle byte */
+       u_int           activity[8];    /* if there is any action on this */
+                                       /* port (will be cleared after */
+                                       /* showing led-states) */
+       int             e1_state; /* keep track of last state */
+       int             e1_getclock; /* if sync is retrieved from interface */
+       int             syncronized; /* keep track of existing sync interface */
+       int             e1_resync; /* resync jobs */
+
+       spinlock_t      lock;   /* the lock */
+
+       /*
+        * the channel index is counted from 0, regardless where the channel
+        * is located on the hfc-channel.
+        * the bch->channel is equvalent to the hfc-channel
+        */
+       struct hfc_chan chan[32];
+       u_char          created[8]; /* what port is created */
+       signed char     slot_owner[256]; /* owner channel of slot */
+};
+
+/* PLX GPIOs */
+#define        PLX_GPIO4_DIR_BIT       13
+#define        PLX_GPIO4_BIT           14
+#define        PLX_GPIO5_DIR_BIT       16
+#define        PLX_GPIO5_BIT           17
+#define        PLX_GPIO6_DIR_BIT       19
+#define        PLX_GPIO6_BIT           20
+#define        PLX_GPIO7_DIR_BIT       22
+#define        PLX_GPIO7_BIT           23
+#define PLX_GPIO8_DIR_BIT      25
+#define PLX_GPIO8_BIT          26
+
+#define        PLX_GPIO4               (1 << PLX_GPIO4_BIT)
+#define        PLX_GPIO5               (1 << PLX_GPIO5_BIT)
+#define        PLX_GPIO6               (1 << PLX_GPIO6_BIT)
+#define        PLX_GPIO7               (1 << PLX_GPIO7_BIT)
+#define PLX_GPIO8              (1 << PLX_GPIO8_BIT)
+
+#define        PLX_GPIO4_DIR           (1 << PLX_GPIO4_DIR_BIT)
+#define        PLX_GPIO5_DIR           (1 << PLX_GPIO5_DIR_BIT)
+#define        PLX_GPIO6_DIR           (1 << PLX_GPIO6_DIR_BIT)
+#define        PLX_GPIO7_DIR           (1 << PLX_GPIO7_DIR_BIT)
+#define PLX_GPIO8_DIR          (1 << PLX_GPIO8_DIR_BIT)
+
+#define        PLX_TERM_ON                     PLX_GPIO7
+#define        PLX_SLAVE_EN_N          PLX_GPIO5
+#define        PLX_MASTER_EN           PLX_GPIO6
+#define        PLX_SYNC_O_EN           PLX_GPIO4
+#define PLX_DSP_RES_N          PLX_GPIO8
+/* GPIO4..8 Enable & Set to OUT, SLAVE_EN_N = 1 */
+#define PLX_GPIOC_INIT         (PLX_GPIO4_DIR | PLX_GPIO5_DIR | PLX_GPIO6_DIR \
+                       | PLX_GPIO7_DIR | PLX_GPIO8_DIR | PLX_SLAVE_EN_N)
+
+/* PLX Interrupt Control/STATUS */
+#define PLX_INTCSR_LINTI1_ENABLE 0x01
+#define PLX_INTCSR_LINTI1_STATUS 0x04
+#define PLX_INTCSR_LINTI2_ENABLE 0x08
+#define PLX_INTCSR_LINTI2_STATUS 0x20
+#define PLX_INTCSR_PCIINT_ENABLE 0x40
+
+/* PLX Registers */
+#define PLX_INTCSR 0x4c
+#define PLX_CNTRL  0x50
+#define PLX_GPIOC  0x54
+
+
+/*
+ * REGISTER SETTING FOR HFC-4S/8S AND HFC-E1
+ */
+
+/* write only registers */
+#define R_CIRM                 0x00
+#define R_CTRL                 0x01
+#define R_BRG_PCM_CFG          0x02
+#define R_RAM_ADDR0            0x08
+#define R_RAM_ADDR1            0x09
+#define R_RAM_ADDR2            0x0A
+#define R_FIRST_FIFO           0x0B
+#define R_RAM_SZ               0x0C
+#define R_FIFO_MD              0x0D
+#define R_INC_RES_FIFO         0x0E
+#define R_FSM_IDX              0x0F
+#define R_FIFO                 0x0F
+#define R_SLOT                 0x10
+#define R_IRQMSK_MISC          0x11
+#define R_SCI_MSK              0x12
+#define R_IRQ_CTRL             0x13
+#define R_PCM_MD0              0x14
+#define R_PCM_MD1              0x15
+#define R_PCM_MD2              0x15
+#define R_SH0H                 0x15
+#define R_SH1H                 0x15
+#define R_SH0L                 0x15
+#define R_SH1L                 0x15
+#define R_SL_SEL0              0x15
+#define R_SL_SEL1              0x15
+#define R_SL_SEL2              0x15
+#define R_SL_SEL3              0x15
+#define R_SL_SEL4              0x15
+#define R_SL_SEL5              0x15
+#define R_SL_SEL6              0x15
+#define R_SL_SEL7              0x15
+#define R_ST_SEL               0x16
+#define R_ST_SYNC              0x17
+#define R_CONF_EN              0x18
+#define R_TI_WD                        0x1A
+#define R_BERT_WD_MD           0x1B
+#define R_DTMF                 0x1C
+#define R_DTMF_N               0x1D
+#define R_E1_WR_STA            0x20
+#define R_E1_RD_STA            0x20
+#define R_LOS0                 0x22
+#define R_LOS1                 0x23
+#define R_RX0                  0x24
+#define R_RX_FR0               0x25
+#define R_RX_FR1               0x26
+#define R_TX0                  0x28
+#define R_TX1                  0x29
+#define R_TX_FR0               0x2C
+
+#define R_TX_FR1               0x2D
+#define R_TX_FR2               0x2E
+#define R_JATT_ATT             0x2F /* undocumented */
+#define A_ST_RD_STATE          0x30
+#define A_ST_WR_STATE          0x30
+#define R_RX_OFF               0x30
+#define A_ST_CTRL0             0x31
+#define R_SYNC_OUT             0x31
+#define A_ST_CTRL1             0x32
+#define A_ST_CTRL2             0x33
+#define A_ST_SQ_WR             0x34
+#define R_TX_OFF               0x34
+#define R_SYNC_CTRL            0x35
+#define A_ST_CLK_DLY           0x37
+#define R_PWM0                 0x38
+#define R_PWM1                 0x39
+#define A_ST_B1_TX             0x3C
+#define A_ST_B2_TX             0x3D
+#define A_ST_D_TX              0x3E
+#define R_GPIO_OUT0            0x40
+#define R_GPIO_OUT1            0x41
+#define R_GPIO_EN0             0x42
+#define R_GPIO_EN1             0x43
+#define R_GPIO_SEL             0x44
+#define R_BRG_CTRL             0x45
+#define R_PWM_MD               0x46
+#define R_BRG_MD               0x47
+#define R_BRG_TIM0             0x48
+#define R_BRG_TIM1             0x49
+#define R_BRG_TIM2             0x4A
+#define R_BRG_TIM3             0x4B
+#define R_BRG_TIM_SEL01                0x4C
+#define R_BRG_TIM_SEL23                0x4D
+#define R_BRG_TIM_SEL45                0x4E
+#define R_BRG_TIM_SEL67                0x4F
+#define A_SL_CFG               0xD0
+#define A_CONF                 0xD1
+#define A_CH_MSK               0xF4
+#define A_CON_HDLC             0xFA
+#define A_SUBCH_CFG            0xFB
+#define A_CHANNEL              0xFC
+#define A_FIFO_SEQ             0xFD
+#define A_IRQ_MSK              0xFF
+
+/* read only registers */
+#define A_Z12                  0x04
+#define A_Z1L                  0x04
+#define A_Z1                   0x04
+#define A_Z1H                  0x05
+#define A_Z2L                  0x06
+#define A_Z2                   0x06
+#define A_Z2H                  0x07
+#define A_F1                   0x0C
+#define A_F12                  0x0C
+#define A_F2                   0x0D
+#define R_IRQ_OVIEW            0x10
+#define R_IRQ_MISC             0x11
+#define R_IRQ_STATECH          0x12
+#define R_CONF_OFLOW           0x14
+#define R_RAM_USE              0x15
+#define R_CHIP_ID              0x16
+#define R_BERT_STA             0x17
+#define R_F0_CNTL              0x18
+#define R_F0_CNTH              0x19
+#define R_BERT_EC              0x1A
+#define R_BERT_ECL             0x1A
+#define R_BERT_ECH             0x1B
+#define R_STATUS               0x1C
+#define R_CHIP_RV              0x1F
+#define R_STATE                        0x20
+#define R_SYNC_STA             0x24
+#define R_RX_SL0_0             0x25
+#define R_RX_SL0_1             0x26
+#define R_RX_SL0_2             0x27
+#define R_JATT_DIR             0x2b /* undocumented */
+#define R_SLIP                 0x2c
+#define A_ST_RD_STA            0x30
+#define R_FAS_EC               0x30
+#define R_FAS_ECL              0x30
+#define R_FAS_ECH              0x31
+#define R_VIO_EC               0x32
+#define R_VIO_ECL              0x32
+#define R_VIO_ECH              0x33
+#define A_ST_SQ_RD             0x34
+#define R_CRC_EC               0x34
+#define R_CRC_ECL              0x34
+#define R_CRC_ECH              0x35
+#define R_E_EC                 0x36
+#define R_E_ECL                        0x36
+#define R_E_ECH                        0x37
+#define R_SA6_SA13_EC          0x38
+#define R_SA6_SA13_ECL         0x38
+#define R_SA6_SA13_ECH         0x39
+#define R_SA6_SA23_EC          0x3A
+#define R_SA6_SA23_ECL         0x3A
+#define R_SA6_SA23_ECH         0x3B
+#define A_ST_B1_RX             0x3C
+#define A_ST_B2_RX             0x3D
+#define A_ST_D_RX              0x3E
+#define A_ST_E_RX              0x3F
+#define R_GPIO_IN0             0x40
+#define R_GPIO_IN1             0x41
+#define R_GPI_IN0              0x44
+#define R_GPI_IN1              0x45
+#define R_GPI_IN2              0x46
+#define R_GPI_IN3              0x47
+#define R_INT_DATA             0x88
+#define R_IRQ_FIFO_BL0         0xC8
+#define R_IRQ_FIFO_BL1         0xC9
+#define R_IRQ_FIFO_BL2         0xCA
+#define R_IRQ_FIFO_BL3         0xCB
+#define R_IRQ_FIFO_BL4         0xCC
+#define R_IRQ_FIFO_BL5         0xCD
+#define R_IRQ_FIFO_BL6         0xCE
+#define R_IRQ_FIFO_BL7         0xCF
+
+/* read and write registers */
+#define A_FIFO_DATA0           0x80
+#define A_FIFO_DATA1           0x80
+#define A_FIFO_DATA2           0x80
+#define A_FIFO_DATA0_NOINC     0x84
+#define A_FIFO_DATA1_NOINC     0x84
+#define A_FIFO_DATA2_NOINC     0x84
+#define R_RAM_DATA             0xC0
+
+
+/*
+ * BIT SETTING FOR HFC-4S/8S AND HFC-E1
+ */
+
+/* chapter 2: universal bus interface */
+/* R_CIRM */
+#define V_IRQ_SEL              0x01
+#define V_SRES                 0x08
+#define V_HFCRES               0x10
+#define V_PCMRES               0x20
+#define V_STRES                        0x40
+#define V_ETRES                        0x40
+#define V_RLD_EPR              0x80
+/* R_CTRL */
+#define V_FIFO_LPRIO           0x02
+#define V_SLOW_RD              0x04
+#define V_EXT_RAM              0x08
+#define V_CLK_OFF              0x20
+#define V_ST_CLK               0x40
+/* R_RAM_ADDR0 */
+#define V_RAM_ADDR2            0x01
+#define V_ADDR_RES             0x40
+#define V_ADDR_INC             0x80
+/* R_RAM_SZ */
+#define V_RAM_SZ               0x01
+#define V_PWM0_16KHZ           0x10
+#define V_PWM1_16KHZ           0x20
+#define V_FZ_MD                        0x80
+/* R_CHIP_ID */
+#define V_PNP_IRQ              0x01
+#define V_CHIP_ID              0x10
+
+/* chapter 3: data flow */
+/* R_FIRST_FIFO */
+#define V_FIRST_FIRO_DIR       0x01
+#define V_FIRST_FIFO_NUM       0x02
+/* R_FIFO_MD */
+#define V_FIFO_MD              0x01
+#define V_CSM_MD               0x04
+#define V_FSM_MD               0x08
+#define V_FIFO_SZ              0x10
+/* R_FIFO */
+#define V_FIFO_DIR             0x01
+#define V_FIFO_NUM             0x02
+#define V_REV                  0x80
+/* R_SLOT */
+#define V_SL_DIR               0x01
+#define V_SL_NUM               0x02
+/* A_SL_CFG */
+#define V_CH_DIR               0x01
+#define V_CH_SEL               0x02
+#define V_ROUTING              0x40
+/* A_CON_HDLC */
+#define V_IFF                  0x01
+#define V_HDLC_TRP             0x02
+#define V_TRP_IRQ              0x04
+#define V_DATA_FLOW            0x20
+/* A_SUBCH_CFG */
+#define V_BIT_CNT              0x01
+#define V_START_BIT            0x08
+#define V_LOOP_FIFO            0x40
+#define V_INV_DATA             0x80
+/* A_CHANNEL */
+#define V_CH_DIR0              0x01
+#define V_CH_NUM0              0x02
+/* A_FIFO_SEQ */
+#define V_NEXT_FIFO_DIR                0x01
+#define V_NEXT_FIFO_NUM                0x02
+#define V_SEQ_END              0x40
+
+/* chapter 4: FIFO handling and HDLC controller */
+/* R_INC_RES_FIFO */
+#define V_INC_F                        0x01
+#define V_RES_F                        0x02
+#define V_RES_LOST             0x04
+
+/* chapter 5: S/T interface */
+/* R_SCI_MSK */
+#define V_SCI_MSK_ST0          0x01
+#define V_SCI_MSK_ST1          0x02
+#define V_SCI_MSK_ST2          0x04
+#define V_SCI_MSK_ST3          0x08
+#define V_SCI_MSK_ST4          0x10
+#define V_SCI_MSK_ST5          0x20
+#define V_SCI_MSK_ST6          0x40
+#define V_SCI_MSK_ST7          0x80
+/* R_ST_SEL */
+#define V_ST_SEL               0x01
+#define V_MULT_ST              0x08
+/* R_ST_SYNC */
+#define V_SYNC_SEL             0x01
+#define V_AUTO_SYNC            0x08
+/* A_ST_WR_STA */
+#define V_ST_SET_STA           0x01
+#define V_ST_LD_STA            0x10
+#define V_ST_ACT               0x20
+#define V_SET_G2_G3            0x80
+/* A_ST_CTRL0 */
+#define V_B1_EN                        0x01
+#define V_B2_EN                        0x02
+#define V_ST_MD                        0x04
+#define V_D_PRIO               0x08
+#define V_SQ_EN                        0x10
+#define V_96KHZ                        0x20
+#define V_TX_LI                        0x40
+#define V_ST_STOP              0x80
+/* A_ST_CTRL1 */
+#define V_G2_G3_EN             0x01
+#define V_D_HI                 0x04
+#define V_E_IGNO               0x08
+#define V_E_LO                 0x10
+#define V_B12_SWAP             0x80
+/* A_ST_CTRL2 */
+#define V_B1_RX_EN             0x01
+#define V_B2_RX_EN             0x02
+#define V_ST_TRIS              0x40
+/* A_ST_CLK_DLY */
+#define V_ST_CK_DLY            0x01
+#define V_ST_SMPL              0x10
+/* A_ST_D_TX */
+#define V_ST_D_TX              0x40
+/* R_IRQ_STATECH */
+#define V_SCI_ST0              0x01
+#define V_SCI_ST1              0x02
+#define V_SCI_ST2              0x04
+#define V_SCI_ST3              0x08
+#define V_SCI_ST4              0x10
+#define V_SCI_ST5              0x20
+#define V_SCI_ST6              0x40
+#define V_SCI_ST7              0x80
+/* A_ST_RD_STA */
+#define V_ST_STA               0x01
+#define V_FR_SYNC_ST           0x10
+#define V_TI2_EXP              0x20
+#define V_INFO0                        0x40
+#define V_G2_G3                        0x80
+/* A_ST_SQ_RD */
+#define V_ST_SQ                        0x01
+#define V_MF_RX_RDY            0x10
+#define V_MF_TX_RDY            0x80
+/* A_ST_D_RX */
+#define V_ST_D_RX              0x40
+/* A_ST_E_RX */
+#define V_ST_E_RX              0x40
+
+/* chapter 5: E1 interface */
+/* R_E1_WR_STA */
+/* R_E1_RD_STA */
+#define V_E1_SET_STA           0x01
+#define V_E1_LD_STA            0x10
+/* R_RX0 */
+#define V_RX_CODE              0x01
+#define V_RX_FBAUD             0x04
+#define V_RX_CMI               0x08
+#define V_RX_INV_CMI           0x10
+#define V_RX_INV_CLK           0x20
+#define V_RX_INV_DATA          0x40
+#define V_AIS_ITU              0x80
+/* R_RX_FR0 */
+#define V_NO_INSYNC            0x01
+#define V_AUTO_RESYNC          0x02
+#define V_AUTO_RECO            0x04
+#define V_SWORD_COND           0x08
+#define V_SYNC_LOSS            0x10
+#define V_XCRC_SYNC            0x20
+#define V_MF_RESYNC            0x40
+#define V_RESYNC               0x80
+/* R_RX_FR1 */
+#define V_RX_MF                        0x01
+#define V_RX_MF_SYNC           0x02
+#define V_RX_SL0_RAM           0x04
+#define V_ERR_SIM              0x20
+#define V_RES_NMF              0x40
+/* R_TX0 */
+#define V_TX_CODE              0x01
+#define V_TX_FBAUD             0x04
+#define V_TX_CMI_CODE          0x08
+#define V_TX_INV_CMI_CODE      0x10
+#define V_TX_INV_CLK           0x20
+#define V_TX_INV_DATA          0x40
+#define V_OUT_EN               0x80
+/* R_TX1 */
+#define V_INV_CLK              0x01
+#define V_EXCHG_DATA_LI                0x02
+#define V_AIS_OUT              0x04
+#define V_ATX                  0x20
+#define V_NTRI                 0x40
+#define V_AUTO_ERR_RES         0x80
+/* R_TX_FR0 */
+#define V_TRP_FAS              0x01
+#define V_TRP_NFAS             0x02
+#define V_TRP_RAL              0x04
+#define V_TRP_SA               0x08
+/* R_TX_FR1 */
+#define V_TX_FAS               0x01
+#define V_TX_NFAS              0x02
+#define V_TX_RAL               0x04
+#define V_TX_SA                        0x08
+/* R_TX_FR2 */
+#define V_TX_MF                        0x01
+#define V_TRP_SL0              0x02
+#define V_TX_SL0_RAM           0x04
+#define V_TX_E                 0x10
+#define V_NEG_E                        0x20
+#define V_XS12_ON              0x40
+#define V_XS15_ON              0x80
+/* R_RX_OFF */
+#define V_RX_SZ                        0x01
+#define V_RX_INIT              0x04
+/* R_SYNC_OUT */
+#define V_SYNC_E1_RX           0x01
+#define V_IPATS0               0x20
+#define V_IPATS1               0x40
+#define V_IPATS2               0x80
+/* R_TX_OFF */
+#define V_TX_SZ                        0x01
+#define V_TX_INIT              0x04
+/* R_SYNC_CTRL */
+#define V_EXT_CLK_SYNC         0x01
+#define V_SYNC_OFFS            0x02
+#define V_PCM_SYNC             0x04
+#define V_NEG_CLK              0x08
+#define V_HCLK                 0x10
+/*
+#define V_JATT_AUTO_DEL                0x20
+#define V_JATT_AUTO            0x40
+*/
+#define V_JATT_OFF             0x80
+/* R_STATE */
+#define V_E1_STA               0x01
+#define V_ALT_FR_RX            0x40
+#define V_ALT_FR_TX            0x80
+/* R_SYNC_STA */
+#define V_RX_STA               0x01
+#define V_FR_SYNC_E1           0x04
+#define V_SIG_LOS              0x08
+#define V_MFA_STA              0x10
+#define V_AIS                  0x40
+#define V_NO_MF_SYNC           0x80
+/* R_RX_SL0_0 */
+#define V_SI_FAS               0x01
+#define V_SI_NFAS              0x02
+#define V_A                    0x04
+#define V_CRC_OK               0x08
+#define V_TX_E1                        0x10
+#define V_TX_E2                        0x20
+#define V_RX_E1                        0x40
+#define V_RX_E2                        0x80
+/* R_SLIP */
+#define V_SLIP_RX              0x01
+#define V_FOSLIP_RX            0x08
+#define V_SLIP_TX              0x10
+#define V_FOSLIP_TX            0x80
+
+/* chapter 6: PCM interface */
+/* R_PCM_MD0 */
+#define V_PCM_MD               0x01
+#define V_C4_POL               0x02
+#define V_F0_NEG               0x04
+#define V_F0_LEN               0x08
+#define V_PCM_ADDR             0x10
+/* R_SL_SEL0 */
+#define V_SL_SEL0              0x01
+#define V_SH_SEL0              0x80
+/* R_SL_SEL1 */
+#define V_SL_SEL1              0x01
+#define V_SH_SEL1              0x80
+/* R_SL_SEL2 */
+#define V_SL_SEL2              0x01
+#define V_SH_SEL2              0x80
+/* R_SL_SEL3 */
+#define V_SL_SEL3              0x01
+#define V_SH_SEL3              0x80
+/* R_SL_SEL4 */
+#define V_SL_SEL4              0x01
+#define V_SH_SEL4              0x80
+/* R_SL_SEL5 */
+#define V_SL_SEL5              0x01
+#define V_SH_SEL5              0x80
+/* R_SL_SEL6 */
+#define V_SL_SEL6              0x01
+#define V_SH_SEL6              0x80
+/* R_SL_SEL7 */
+#define V_SL_SEL7              0x01
+#define V_SH_SEL7              0x80
+/* R_PCM_MD1 */
+#define V_ODEC_CON             0x01
+#define V_PLL_ADJ              0x04
+#define V_PCM_DR               0x10
+#define V_PCM_LOOP             0x40
+/* R_PCM_MD2 */
+#define V_SYNC_PLL             0x02
+#define V_SYNC_SRC             0x04
+#define V_SYNC_OUT             0x08
+#define V_ICR_FR_TIME          0x40
+#define V_EN_PLL               0x80
+
+/* chapter 7: pulse width modulation */
+/* R_PWM_MD */
+#define V_EXT_IRQ_EN           0x08
+#define V_PWM0_MD              0x10
+#define V_PWM1_MD              0x40
+
+/* chapter 8: multiparty audio conferences */
+/* R_CONF_EN */
+#define V_CONF_EN              0x01
+#define V_ULAW                 0x80
+/* A_CONF */
+#define V_CONF_NUM             0x01
+#define V_NOISE_SUPPR          0x08
+#define V_ATT_LEV              0x20
+#define V_CONF_SL              0x80
+/* R_CONF_OFLOW */
+#define V_CONF_OFLOW0          0x01
+#define V_CONF_OFLOW1          0x02
+#define V_CONF_OFLOW2          0x04
+#define V_CONF_OFLOW3          0x08
+#define V_CONF_OFLOW4          0x10
+#define V_CONF_OFLOW5          0x20
+#define V_CONF_OFLOW6          0x40
+#define V_CONF_OFLOW7          0x80
+
+/* chapter 9: DTMF contoller */
+/* R_DTMF0 */
+#define V_DTMF_EN              0x01
+#define V_HARM_SEL             0x02
+#define V_DTMF_RX_CH           0x04
+#define V_DTMF_STOP            0x08
+#define V_CHBL_SEL             0x10
+#define V_RST_DTMF             0x40
+#define V_ULAW_SEL             0x80
+
+/* chapter 10: BERT */
+/* R_BERT_WD_MD */
+#define V_PAT_SEQ              0x01
+#define V_BERT_ERR             0x08
+#define V_AUTO_WD_RES          0x20
+#define V_WD_RES               0x80
+/* R_BERT_STA */
+#define V_BERT_SYNC_SRC                0x01
+#define V_BERT_SYNC            0x10
+#define V_BERT_INV_DATA                0x20
+
+/* chapter 11: auxiliary interface */
+/* R_BRG_PCM_CFG */
+#define V_BRG_EN               0x01
+#define V_BRG_MD               0x02
+#define V_PCM_CLK              0x20
+#define V_ADDR_WRDLY           0x40
+/* R_BRG_CTRL */
+#define V_BRG_CS               0x01
+#define V_BRG_ADDR             0x08
+#define V_BRG_CS_SRC           0x80
+/* R_BRG_MD */
+#define V_BRG_MD0              0x01
+#define V_BRG_MD1              0x02
+#define V_BRG_MD2              0x04
+#define V_BRG_MD3              0x08
+#define V_BRG_MD4              0x10
+#define V_BRG_MD5              0x20
+#define V_BRG_MD6              0x40
+#define V_BRG_MD7              0x80
+/* R_BRG_TIM0 */
+#define V_BRG_TIM0_IDLE                0x01
+#define V_BRG_TIM0_CLK         0x10
+/* R_BRG_TIM1 */
+#define V_BRG_TIM1_IDLE                0x01
+#define V_BRG_TIM1_CLK         0x10
+/* R_BRG_TIM2 */
+#define V_BRG_TIM2_IDLE                0x01
+#define V_BRG_TIM2_CLK         0x10
+/* R_BRG_TIM3 */
+#define V_BRG_TIM3_IDLE                0x01
+#define V_BRG_TIM3_CLK         0x10
+/* R_BRG_TIM_SEL01 */
+#define V_BRG_WR_SEL0          0x01
+#define V_BRG_RD_SEL0          0x04
+#define V_BRG_WR_SEL1          0x10
+#define V_BRG_RD_SEL1          0x40
+/* R_BRG_TIM_SEL23 */
+#define V_BRG_WR_SEL2          0x01
+#define V_BRG_RD_SEL2          0x04
+#define V_BRG_WR_SEL3          0x10
+#define V_BRG_RD_SEL3          0x40
+/* R_BRG_TIM_SEL45 */
+#define V_BRG_WR_SEL4          0x01
+#define V_BRG_RD_SEL4          0x04
+#define V_BRG_WR_SEL5          0x10
+#define V_BRG_RD_SEL5          0x40
+/* R_BRG_TIM_SEL67 */
+#define V_BRG_WR_SEL6          0x01
+#define V_BRG_RD_SEL6          0x04
+#define V_BRG_WR_SEL7          0x10
+#define V_BRG_RD_SEL7          0x40
+
+/* chapter 12: clock, reset, interrupt, timer and watchdog */
+/* R_IRQMSK_MISC */
+#define V_STA_IRQMSK           0x01
+#define V_TI_IRQMSK            0x02
+#define V_PROC_IRQMSK          0x04
+#define V_DTMF_IRQMSK          0x08
+#define V_IRQ1S_MSK            0x10
+#define V_SA6_IRQMSK           0x20
+#define V_RX_EOMF_MSK          0x40
+#define V_TX_EOMF_MSK          0x80
+/* R_IRQ_CTRL */
+#define V_FIFO_IRQ             0x01
+#define V_GLOB_IRQ_EN          0x08
+#define V_IRQ_POL              0x10
+/* R_TI_WD */
+#define V_EV_TS                        0x01
+#define V_WD_TS                        0x10
+/* A_IRQ_MSK */
+#define V_IRQ                  0x01
+#define V_BERT_EN              0x02
+#define V_MIX_IRQ              0x04
+/* R_IRQ_OVIEW */
+#define V_IRQ_FIFO_BL0         0x01
+#define V_IRQ_FIFO_BL1         0x02
+#define V_IRQ_FIFO_BL2         0x04
+#define V_IRQ_FIFO_BL3         0x08
+#define V_IRQ_FIFO_BL4         0x10
+#define V_IRQ_FIFO_BL5         0x20
+#define V_IRQ_FIFO_BL6         0x40
+#define V_IRQ_FIFO_BL7         0x80
+/* R_IRQ_MISC */
+#define V_STA_IRQ              0x01
+#define V_TI_IRQ               0x02
+#define V_IRQ_PROC             0x04
+#define V_DTMF_IRQ             0x08
+#define V_IRQ1S                        0x10
+#define V_SA6_IRQ              0x20
+#define V_RX_EOMF              0x40
+#define V_TX_EOMF              0x80
+/* R_STATUS */
+#define V_BUSY                 0x01
+#define V_PROC                 0x02
+#define V_DTMF_STA             0x04
+#define V_LOST_STA             0x08
+#define V_SYNC_IN              0x10
+#define V_EXT_IRQSTA           0x20
+#define V_MISC_IRQSTA          0x40
+#define V_FR_IRQSTA            0x80
+/* R_IRQ_FIFO_BL0 */
+#define V_IRQ_FIFO0_TX         0x01
+#define V_IRQ_FIFO0_RX         0x02
+#define V_IRQ_FIFO1_TX         0x04
+#define V_IRQ_FIFO1_RX         0x08
+#define V_IRQ_FIFO2_TX         0x10
+#define V_IRQ_FIFO2_RX         0x20
+#define V_IRQ_FIFO3_TX         0x40
+#define V_IRQ_FIFO3_RX         0x80
+/* R_IRQ_FIFO_BL1 */
+#define V_IRQ_FIFO4_TX         0x01
+#define V_IRQ_FIFO4_RX         0x02
+#define V_IRQ_FIFO5_TX         0x04
+#define V_IRQ_FIFO5_RX         0x08
+#define V_IRQ_FIFO6_TX         0x10
+#define V_IRQ_FIFO6_RX         0x20
+#define V_IRQ_FIFO7_TX         0x40
+#define V_IRQ_FIFO7_RX         0x80
+/* R_IRQ_FIFO_BL2 */
+#define V_IRQ_FIFO8_TX         0x01
+#define V_IRQ_FIFO8_RX         0x02
+#define V_IRQ_FIFO9_TX         0x04
+#define V_IRQ_FIFO9_RX         0x08
+#define V_IRQ_FIFO10_TX                0x10
+#define V_IRQ_FIFO10_RX                0x20
+#define V_IRQ_FIFO11_TX                0x40
+#define V_IRQ_FIFO11_RX                0x80
+/* R_IRQ_FIFO_BL3 */
+#define V_IRQ_FIFO12_TX                0x01
+#define V_IRQ_FIFO12_RX                0x02
+#define V_IRQ_FIFO13_TX                0x04
+#define V_IRQ_FIFO13_RX                0x08
+#define V_IRQ_FIFO14_TX                0x10
+#define V_IRQ_FIFO14_RX                0x20
+#define V_IRQ_FIFO15_TX                0x40
+#define V_IRQ_FIFO15_RX                0x80
+/* R_IRQ_FIFO_BL4 */
+#define V_IRQ_FIFO16_TX                0x01
+#define V_IRQ_FIFO16_RX                0x02
+#define V_IRQ_FIFO17_TX                0x04
+#define V_IRQ_FIFO17_RX                0x08
+#define V_IRQ_FIFO18_TX                0x10
+#define V_IRQ_FIFO18_RX                0x20
+#define V_IRQ_FIFO19_TX                0x40
+#define V_IRQ_FIFO19_RX                0x80
+/* R_IRQ_FIFO_BL5 */
+#define V_IRQ_FIFO20_TX                0x01
+#define V_IRQ_FIFO20_RX                0x02
+#define V_IRQ_FIFO21_TX                0x04
+#define V_IRQ_FIFO21_RX                0x08
+#define V_IRQ_FIFO22_TX                0x10
+#define V_IRQ_FIFO22_RX                0x20
+#define V_IRQ_FIFO23_TX                0x40
+#define V_IRQ_FIFO23_RX                0x80
+/* R_IRQ_FIFO_BL6 */
+#define V_IRQ_FIFO24_TX                0x01
+#define V_IRQ_FIFO24_RX                0x02
+#define V_IRQ_FIFO25_TX                0x04
+#define V_IRQ_FIFO25_RX                0x08
+#define V_IRQ_FIFO26_TX                0x10
+#define V_IRQ_FIFO26_RX                0x20
+#define V_IRQ_FIFO27_TX                0x40
+#define V_IRQ_FIFO27_RX                0x80
+/* R_IRQ_FIFO_BL7 */
+#define V_IRQ_FIFO28_TX                0x01
+#define V_IRQ_FIFO28_RX                0x02
+#define V_IRQ_FIFO29_TX                0x04
+#define V_IRQ_FIFO29_RX                0x08
+#define V_IRQ_FIFO30_TX                0x10
+#define V_IRQ_FIFO30_RX                0x20
+#define V_IRQ_FIFO31_TX                0x40
+#define V_IRQ_FIFO31_RX                0x80
+
+/* chapter 13: general purpose I/O pins (GPIO) and input pins (GPI) */
+/* R_GPIO_OUT0 */
+#define V_GPIO_OUT0            0x01
+#define V_GPIO_OUT1            0x02
+#define V_GPIO_OUT2            0x04
+#define V_GPIO_OUT3            0x08
+#define V_GPIO_OUT4            0x10
+#define V_GPIO_OUT5            0x20
+#define V_GPIO_OUT6            0x40
+#define V_GPIO_OUT7            0x80
+/* R_GPIO_OUT1 */
+#define V_GPIO_OUT8            0x01
+#define V_GPIO_OUT9            0x02
+#define V_GPIO_OUT10           0x04
+#define V_GPIO_OUT11           0x08
+#define V_GPIO_OUT12           0x10
+#define V_GPIO_OUT13           0x20
+#define V_GPIO_OUT14           0x40
+#define V_GPIO_OUT15           0x80
+/* R_GPIO_EN0 */
+#define V_GPIO_EN0             0x01
+#define V_GPIO_EN1             0x02
+#define V_GPIO_EN2             0x04
+#define V_GPIO_EN3             0x08
+#define V_GPIO_EN4             0x10
+#define V_GPIO_EN5             0x20
+#define V_GPIO_EN6             0x40
+#define V_GPIO_EN7             0x80
+/* R_GPIO_EN1 */
+#define V_GPIO_EN8             0x01
+#define V_GPIO_EN9             0x02
+#define V_GPIO_EN10            0x04
+#define V_GPIO_EN11            0x08
+#define V_GPIO_EN12            0x10
+#define V_GPIO_EN13            0x20
+#define V_GPIO_EN14            0x40
+#define V_GPIO_EN15            0x80
+/* R_GPIO_SEL */
+#define V_GPIO_SEL0            0x01
+#define V_GPIO_SEL1            0x02
+#define V_GPIO_SEL2            0x04
+#define V_GPIO_SEL3            0x08
+#define V_GPIO_SEL4            0x10
+#define V_GPIO_SEL5            0x20
+#define V_GPIO_SEL6            0x40
+#define V_GPIO_SEL7            0x80
+/* R_GPIO_IN0 */
+#define V_GPIO_IN0             0x01
+#define V_GPIO_IN1             0x02
+#define V_GPIO_IN2             0x04
+#define V_GPIO_IN3             0x08
+#define V_GPIO_IN4             0x10
+#define V_GPIO_IN5             0x20
+#define V_GPIO_IN6             0x40
+#define V_GPIO_IN7             0x80
+/* R_GPIO_IN1 */
+#define V_GPIO_IN8             0x01
+#define V_GPIO_IN9             0x02
+#define V_GPIO_IN10            0x04
+#define V_GPIO_IN11            0x08
+#define V_GPIO_IN12            0x10
+#define V_GPIO_IN13            0x20
+#define V_GPIO_IN14            0x40
+#define V_GPIO_IN15            0x80
+/* R_GPI_IN0 */
+#define V_GPI_IN0              0x01
+#define V_GPI_IN1              0x02
+#define V_GPI_IN2              0x04
+#define V_GPI_IN3              0x08
+#define V_GPI_IN4              0x10
+#define V_GPI_IN5              0x20
+#define V_GPI_IN6              0x40
+#define V_GPI_IN7              0x80
+/* R_GPI_IN1 */
+#define V_GPI_IN8              0x01
+#define V_GPI_IN9              0x02
+#define V_GPI_IN10             0x04
+#define V_GPI_IN11             0x08
+#define V_GPI_IN12             0x10
+#define V_GPI_IN13             0x20
+#define V_GPI_IN14             0x40
+#define V_GPI_IN15             0x80
+/* R_GPI_IN2 */
+#define V_GPI_IN16             0x01
+#define V_GPI_IN17             0x02
+#define V_GPI_IN18             0x04
+#define V_GPI_IN19             0x08
+#define V_GPI_IN20             0x10
+#define V_GPI_IN21             0x20
+#define V_GPI_IN22             0x40
+#define V_GPI_IN23             0x80
+/* R_GPI_IN3 */
+#define V_GPI_IN24             0x01
+#define V_GPI_IN25             0x02
+#define V_GPI_IN26             0x04
+#define V_GPI_IN27             0x08
+#define V_GPI_IN28             0x10
+#define V_GPI_IN29             0x20
+#define V_GPI_IN30             0x40
+#define V_GPI_IN31             0x80
+
+/* map of all registers, used for debugging */
+
+#ifdef HFC_REGISTER_DEBUG
+struct hfc_register_names {
+       char *name;
+       u_char reg;
+} hfc_register_names[] = {
+       /* write registers */
+       {"R_CIRM",              0x00},
+       {"R_CTRL",              0x01},
+       {"R_BRG_PCM_CFG ",      0x02},
+       {"R_RAM_ADDR0",         0x08},
+       {"R_RAM_ADDR1",         0x09},
+       {"R_RAM_ADDR2",         0x0A},
+       {"R_FIRST_FIFO",        0x0B},
+       {"R_RAM_SZ",            0x0C},
+       {"R_FIFO_MD",           0x0D},
+       {"R_INC_RES_FIFO",      0x0E},
+       {"R_FIFO / R_FSM_IDX",  0x0F},
+       {"R_SLOT",              0x10},
+       {"R_IRQMSK_MISC",       0x11},
+       {"R_SCI_MSK",           0x12},
+       {"R_IRQ_CTRL",          0x13},
+       {"R_PCM_MD0",           0x14},
+       {"R_0x15",              0x15},
+       {"R_ST_SEL",            0x16},
+       {"R_ST_SYNC",           0x17},
+       {"R_CONF_EN",           0x18},
+       {"R_TI_WD",             0x1A},
+       {"R_BERT_WD_MD",        0x1B},
+       {"R_DTMF",              0x1C},
+       {"R_DTMF_N",            0x1D},
+       {"R_E1_XX_STA",         0x20},
+       {"R_LOS0",              0x22},
+       {"R_LOS1",              0x23},
+       {"R_RX0",               0x24},
+       {"R_RX_FR0",            0x25},
+       {"R_RX_FR1",            0x26},
+       {"R_TX0",               0x28},
+       {"R_TX1",               0x29},
+       {"R_TX_FR0",            0x2C},
+       {"R_TX_FR1",            0x2D},
+       {"R_TX_FR2",            0x2E},
+       {"R_JATT_ATT",          0x2F},
+       {"A_ST_xx_STA/R_RX_OFF", 0x30},
+       {"A_ST_CTRL0/R_SYNC_OUT", 0x31},
+       {"A_ST_CTRL1",          0x32},
+       {"A_ST_CTRL2",          0x33},
+       {"A_ST_SQ_WR",          0x34},
+       {"R_TX_OFF",            0x34},
+       {"R_SYNC_CTRL",         0x35},
+       {"A_ST_CLK_DLY",        0x37},
+       {"R_PWM0",              0x38},
+       {"R_PWM1",              0x39},
+       {"A_ST_B1_TX",          0x3C},
+       {"A_ST_B2_TX",          0x3D},
+       {"A_ST_D_TX",           0x3E},
+       {"R_GPIO_OUT0",         0x40},
+       {"R_GPIO_OUT1",         0x41},
+       {"R_GPIO_EN0",          0x42},
+       {"R_GPIO_EN1",          0x43},
+       {"R_GPIO_SEL",          0x44},
+       {"R_BRG_CTRL",          0x45},
+       {"R_PWM_MD",            0x46},
+       {"R_BRG_MD",            0x47},
+       {"R_BRG_TIM0",          0x48},
+       {"R_BRG_TIM1",          0x49},
+       {"R_BRG_TIM2",          0x4A},
+       {"R_BRG_TIM3",          0x4B},
+       {"R_BRG_TIM_SEL01",     0x4C},
+       {"R_BRG_TIM_SEL23",     0x4D},
+       {"R_BRG_TIM_SEL45",     0x4E},
+       {"R_BRG_TIM_SEL67",     0x4F},
+       {"A_FIFO_DATA0-2",      0x80},
+       {"A_FIFO_DATA0-2_NOINC", 0x84},
+       {"R_RAM_DATA",          0xC0},
+       {"A_SL_CFG",            0xD0},
+       {"A_CONF",              0xD1},
+       {"A_CH_MSK",            0xF4},
+       {"A_CON_HDLC",          0xFA},
+       {"A_SUBCH_CFG",         0xFB},
+       {"A_CHANNEL",           0xFC},
+       {"A_FIFO_SEQ",          0xFD},
+       {"A_IRQ_MSK",           0xFF},
+       {NULL, 0},
+
+       /* read registers */
+       {"A_Z1",                0x04},
+       {"A_Z1H",               0x05},
+       {"A_Z2",                0x06},
+       {"A_Z2H",               0x07},
+       {"A_F1",                0x0C},
+       {"A_F2",                0x0D},
+       {"R_IRQ_OVIEW",         0x10},
+       {"R_IRQ_MISC",          0x11},
+       {"R_IRQ_STATECH",       0x12},
+       {"R_CONF_OFLOW",        0x14},
+       {"R_RAM_USE",           0x15},
+       {"R_CHIP_ID",           0x16},
+       {"R_BERT_STA",          0x17},
+       {"R_F0_CNTL",           0x18},
+       {"R_F0_CNTH",           0x19},
+       {"R_BERT_ECL",          0x1A},
+       {"R_BERT_ECH",          0x1B},
+       {"R_STATUS",            0x1C},
+       {"R_CHIP_RV",           0x1F},
+       {"R_STATE",             0x20},
+       {"R_SYNC_STA",          0x24},
+       {"R_RX_SL0_0",          0x25},
+       {"R_RX_SL0_1",          0x26},
+       {"R_RX_SL0_2",          0x27},
+       {"R_JATT_DIR",          0x2b},
+       {"R_SLIP",              0x2c},
+       {"A_ST_RD_STA",         0x30},
+       {"R_FAS_ECL",           0x30},
+       {"R_FAS_ECH",           0x31},
+       {"R_VIO_ECL",           0x32},
+       {"R_VIO_ECH",           0x33},
+       {"R_CRC_ECL / A_ST_SQ_RD", 0x34},
+       {"R_CRC_ECH",           0x35},
+       {"R_E_ECL",             0x36},
+       {"R_E_ECH",             0x37},
+       {"R_SA6_SA13_ECL",      0x38},
+       {"R_SA6_SA13_ECH",      0x39},
+       {"R_SA6_SA23_ECL",      0x3A},
+       {"R_SA6_SA23_ECH",      0x3B},
+       {"A_ST_B1_RX",          0x3C},
+       {"A_ST_B2_RX",          0x3D},
+       {"A_ST_D_RX",           0x3E},
+       {"A_ST_E_RX",           0x3F},
+       {"R_GPIO_IN0",          0x40},
+       {"R_GPIO_IN1",          0x41},
+       {"R_GPI_IN0",           0x44},
+       {"R_GPI_IN1",           0x45},
+       {"R_GPI_IN2",           0x46},
+       {"R_GPI_IN3",           0x47},
+       {"A_FIFO_DATA0-2",      0x80},
+       {"A_FIFO_DATA0-2_NOINC", 0x84},
+       {"R_INT_DATA",          0x88},
+       {"R_RAM_DATA",          0xC0},
+       {"R_IRQ_FIFO_BL0",      0xC8},
+       {"R_IRQ_FIFO_BL1",      0xC9},
+       {"R_IRQ_FIFO_BL2",      0xCA},
+       {"R_IRQ_FIFO_BL3",      0xCB},
+       {"R_IRQ_FIFO_BL4",      0xCC},
+       {"R_IRQ_FIFO_BL5",      0xCD},
+       {"R_IRQ_FIFO_BL6",      0xCE},
+       {"R_IRQ_FIFO_BL7",      0xCF},
+};
+#endif /* HFC_REGISTER_DEBUG */
+
diff --git a/drivers/isdn/hardware/mISDN/hfc_pci.h b/drivers/isdn/hardware/mISDN/hfc_pci.h
new file mode 100644 (file)
index 0000000..fd2c9be
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ *  specific defines for CCD's HFC 2BDS0 PCI chips
+ *
+ * Author     Werner Cornelius (werner@isdn4linux.de)
+ *
+ * Copyright 1999  by Werner Cornelius (werner@isdn4linux.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, 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.
+ *
+ */
+
+/*
+ * thresholds for transparent B-channel mode
+ * change mask and threshold simultaneously
+ */
+#define HFCPCI_BTRANS_THRESHOLD 128
+#define HFCPCI_BTRANS_MAX      256
+#define HFCPCI_BTRANS_THRESMASK 0x00
+
+/* defines for PCI config */
+#define PCI_ENA_MEMIO          0x02
+#define PCI_ENA_MASTER         0x04
+
+/* GCI/IOM bus monitor registers */
+#define HCFPCI_C_I             0x08
+#define HFCPCI_TRxR            0x0C
+#define HFCPCI_MON1_D          0x28
+#define HFCPCI_MON2_D          0x2C
+
+/* GCI/IOM bus timeslot registers */
+#define HFCPCI_B1_SSL          0x80
+#define HFCPCI_B2_SSL          0x84
+#define HFCPCI_AUX1_SSL                0x88
+#define HFCPCI_AUX2_SSL                0x8C
+#define HFCPCI_B1_RSL          0x90
+#define HFCPCI_B2_RSL          0x94
+#define HFCPCI_AUX1_RSL                0x98
+#define HFCPCI_AUX2_RSL                0x9C
+
+/* GCI/IOM bus data registers */
+#define HFCPCI_B1_D            0xA0
+#define HFCPCI_B2_D            0xA4
+#define HFCPCI_AUX1_D          0xA8
+#define HFCPCI_AUX2_D          0xAC
+
+/* GCI/IOM bus configuration registers */
+#define HFCPCI_MST_EMOD                0xB4
+#define HFCPCI_MST_MODE                0xB8
+#define HFCPCI_CONNECT                 0xBC
+
+
+/* Interrupt and status registers */
+#define HFCPCI_FIFO_EN         0x44
+#define HFCPCI_TRM             0x48
+#define HFCPCI_B_MODE          0x4C
+#define HFCPCI_CHIP_ID         0x58
+#define HFCPCI_CIRM            0x60
+#define HFCPCI_CTMT            0x64
+#define HFCPCI_INT_M1          0x68
+#define HFCPCI_INT_M2          0x6C
+#define HFCPCI_INT_S1          0x78
+#define HFCPCI_INT_S2          0x7C
+#define HFCPCI_STATUS          0x70
+
+/* S/T section registers */
+#define HFCPCI_STATES          0xC0
+#define HFCPCI_SCTRL           0xC4
+#define HFCPCI_SCTRL_E         0xC8
+#define HFCPCI_SCTRL_R         0xCC
+#define HFCPCI_SQ              0xD0
+#define HFCPCI_CLKDEL          0xDC
+#define HFCPCI_B1_REC          0xF0
+#define HFCPCI_B1_SEND         0xF0
+#define HFCPCI_B2_REC          0xF4
+#define HFCPCI_B2_SEND         0xF4
+#define HFCPCI_D_REC           0xF8
+#define HFCPCI_D_SEND          0xF8
+#define HFCPCI_E_REC           0xFC
+
+
+/* bits in status register (READ) */
+#define HFCPCI_PCI_PROC                0x02
+#define HFCPCI_NBUSY           0x04
+#define HFCPCI_TIMER_ELAP      0x10
+#define HFCPCI_STATINT         0x20
+#define HFCPCI_FRAMEINT                0x40
+#define HFCPCI_ANYINT          0x80
+
+/* bits in CTMT (Write) */
+#define HFCPCI_CLTIMER         0x80
+#define HFCPCI_TIM3_125                0x04
+#define HFCPCI_TIM25           0x10
+#define HFCPCI_TIM50           0x14
+#define HFCPCI_TIM400          0x18
+#define HFCPCI_TIM800          0x1C
+#define HFCPCI_AUTO_TIMER      0x20
+#define HFCPCI_TRANSB2         0x02
+#define HFCPCI_TRANSB1         0x01
+
+/* bits in CIRM (Write) */
+#define HFCPCI_AUX_MSK         0x07
+#define HFCPCI_RESET           0x08
+#define HFCPCI_B1_REV          0x40
+#define HFCPCI_B2_REV          0x80
+
+/* bits in INT_M1 and INT_S1 */
+#define HFCPCI_INTS_B1TRANS    0x01
+#define HFCPCI_INTS_B2TRANS    0x02
+#define HFCPCI_INTS_DTRANS     0x04
+#define HFCPCI_INTS_B1REC      0x08
+#define HFCPCI_INTS_B2REC      0x10
+#define HFCPCI_INTS_DREC       0x20
+#define HFCPCI_INTS_L1STATE    0x40
+#define HFCPCI_INTS_TIMER      0x80
+
+/* bits in INT_M2 */
+#define HFCPCI_PROC_TRANS      0x01
+#define HFCPCI_GCI_I_CHG       0x02
+#define HFCPCI_GCI_MON_REC     0x04
+#define HFCPCI_IRQ_ENABLE      0x08
+#define HFCPCI_PMESEL          0x80
+
+/* bits in STATES */
+#define HFCPCI_STATE_MSK       0x0F
+#define HFCPCI_LOAD_STATE      0x10
+#define HFCPCI_ACTIVATE                0x20
+#define HFCPCI_DO_ACTION       0x40
+#define HFCPCI_NT_G2_G3                0x80
+
+/* bits in HFCD_MST_MODE */
+#define HFCPCI_MASTER          0x01
+#define HFCPCI_SLAVE           0x00
+#define HFCPCI_F0IO_POSITIV    0x02
+#define HFCPCI_F0_NEGATIV      0x04
+#define HFCPCI_F0_2C4          0x08
+/* remaining bits are for codecs control */
+
+/* bits in HFCD_SCTRL */
+#define SCTRL_B1_ENA           0x01
+#define SCTRL_B2_ENA           0x02
+#define SCTRL_MODE_TE          0x00
+#define SCTRL_MODE_NT          0x04
+#define SCTRL_LOW_PRIO         0x08
+#define SCTRL_SQ_ENA           0x10
+#define SCTRL_TEST             0x20
+#define SCTRL_NONE_CAP         0x40
+#define SCTRL_PWR_DOWN         0x80
+
+/* bits in SCTRL_E  */
+#define HFCPCI_AUTO_AWAKE      0x01
+#define HFCPCI_DBIT_1          0x04
+#define HFCPCI_IGNORE_COL      0x08
+#define HFCPCI_CHG_B1_B2       0x80
+
+/* bits in FIFO_EN register */
+#define HFCPCI_FIFOEN_B1       0x03
+#define HFCPCI_FIFOEN_B2       0x0C
+#define HFCPCI_FIFOEN_DTX      0x10
+#define HFCPCI_FIFOEN_B1TX     0x01
+#define HFCPCI_FIFOEN_B1RX     0x02
+#define HFCPCI_FIFOEN_B2TX     0x04
+#define HFCPCI_FIFOEN_B2RX     0x08
+
+
+/* definitions of fifo memory area */
+#define MAX_D_FRAMES 15
+#define MAX_B_FRAMES 31
+#define B_SUB_VAL    0x200
+#define B_FIFO_SIZE  (0x2000 - B_SUB_VAL)
+#define D_FIFO_SIZE  512
+#define D_FREG_MASK  0xF
+
+struct zt {
+       unsigned short z1;  /* Z1 pointer 16 Bit */
+       unsigned short z2;  /* Z2 pointer 16 Bit */
+};
+
+struct dfifo {
+       u_char data[D_FIFO_SIZE]; /* FIFO data space */
+       u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */
+       u_char f1, f2; /* f pointers */
+       u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */
+       /* mask index with D_FREG_MASK for access */
+       struct zt za[MAX_D_FRAMES+1];
+       u_char fill3[0x4000-0x2100]; /* align 16K */
+};
+
+struct bzfifo {
+       struct zt       za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */
+       u_char          f1, f2; /* f pointers */
+       u_char          fill[0x2100-0x2082]; /* alignment */
+};
+
+
+union fifo_area {
+       struct {
+               struct dfifo d_tx; /* D-send channel */
+               struct dfifo d_rx; /* D-receive channel */
+       } d_chan;
+       struct {
+               u_char          fill1[0x200];
+               u_char          txdat_b1[B_FIFO_SIZE];
+               struct bzfifo   txbz_b1;
+               struct bzfifo   txbz_b2;
+               u_char          txdat_b2[B_FIFO_SIZE];
+               u_char          fill2[D_FIFO_SIZE];
+               u_char          rxdat_b1[B_FIFO_SIZE];
+               struct bzfifo   rxbz_b1;
+               struct bzfifo   rxbz_b2;
+               u_char rxdat_b2[B_FIFO_SIZE];
+       } b_chans;
+       u_char fill[32768];
+};
+
+#define Write_hfc(a, b, c) (writeb(c, (a->hw.pci_io)+b))
+#define Read_hfc(a, b) (readb((a->hw.pci_io)+b))
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
new file mode 100644 (file)
index 0000000..2649ea5
--- /dev/null
@@ -0,0 +1,5320 @@
+/*
+ * hfcmulti.c  low level driver for hfc-4s/hfc-8s/hfc-e1 based cards
+ *
+ * Author      Andreas Eversberg (jolly@eversberg.eu)
+ * ported to mqueue mechanism:
+ *             Peter Sprenger (sprengermoving-bytes.de)
+ *
+ * inspired by existing hfc-pci driver:
+ * Copyright 1999  by Werner Cornelius (werner@isdn-development.de)
+ * Copyright 2008  by Karsten Keil (kkeil@suse.de)
+ * Copyright 2008  by Andreas Eversberg (jolly@eversberg.eu)
+ *
+ * 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.
+ *
+ *
+ * Thanks to Cologne Chip AG for this great controller!
+ */
+
+/*
+ * module parameters:
+ * type:
+ *     By default (0), the card is automatically detected.
+ *     Or use the following combinations:
+ *     Bit 0-7   = 0x00001 = HFC-E1 (1 port)
+ * or  Bit 0-7   = 0x00004 = HFC-4S (4 ports)
+ * or  Bit 0-7   = 0x00008 = HFC-8S (8 ports)
+ *     Bit 8     = 0x00100 = uLaw (instead of aLaw)
+ *     Bit 9     = 0x00200 = Disable DTMF detect on all B-channels via hardware
+ *     Bit 10    = spare
+ *     Bit 11    = 0x00800 = Force PCM bus into slave mode. (otherwhise auto)
+ * or   Bit 12    = 0x01000 = Force PCM bus into master mode. (otherwhise auto)
+ *     Bit 13    = spare
+ *     Bit 14    = 0x04000 = Use external ram (128K)
+ *     Bit 15    = 0x08000 = Use external ram (512K)
+ *     Bit 16    = 0x10000 = Use 64 timeslots instead of 32
+ * or  Bit 17    = 0x20000 = Use 128 timeslots instead of anything else
+ *     Bit 18    = spare
+ *     Bit 19    = 0x80000 = Send the Watchdog a Signal (Dual E1 with Watchdog)
+ * (all other bits are reserved and shall be 0)
+ *     example: 0x20204 one HFC-4S with dtmf detection and 128 timeslots on PCM
+ *              bus (PCM master)
+ *
+ * port: (optional or required for all ports on all installed cards)
+ *     HFC-4S/HFC-8S only bits:
+ *     Bit 0     = 0x001 = Use master clock for this S/T interface
+ *                         (ony once per chip).
+ *     Bit 1     = 0x002 = transmitter line setup (non capacitive mode)
+ *                         Don't use this unless you know what you are doing!
+ *     Bit 2     = 0x004 = Disable E-channel. (No E-channel processing)
+ *     example: 0x0001,0x0000,0x0000,0x0000 one HFC-4S with master clock
+ *              received from port 1
+ *
+ *     HFC-E1 only bits:
+ *     Bit 0     = 0x0001 = interface: 0=copper, 1=optical
+ *     Bit 1     = 0x0002 = reserved (later for 32 B-channels transparent mode)
+ *     Bit 2     = 0x0004 = Report LOS
+ *     Bit 3     = 0x0008 = Report AIS
+ *     Bit 4     = 0x0010 = Report SLIP
+ *     Bit 5     = 0x0020 = Report RDI
+ *     Bit 8     = 0x0100 = Turn off CRC-4 Multiframe Mode, use double frame
+ *                          mode instead.
+ *     Bit 9     = 0x0200 = Force get clock from interface, even in NT mode.
+ * or  Bit 10    = 0x0400 = Force put clock to interface, even in TE mode.
+ *     Bit 11    = 0x0800 = Use direct RX clock for PCM sync rather than PLL.
+ *                          (E1 only)
+ *     Bit 12-13 = 0xX000 = elastic jitter buffer (1-3), Set both bits to 0
+ *                          for default.
+ * (all other bits are reserved and shall be 0)
+ *
+ * debug:
+ *     NOTE: only one debug value must be given for all cards
+ *     enable debugging (see hfc_multi.h for debug options)
+ *
+ * poll:
+ *     NOTE: only one poll value must be given for all cards
+ *     Give the number of samples for each fifo process.
+ *     By default 128 is used. Decrease to reduce delay, increase to
+ *     reduce cpu load. If unsure, don't mess with it!
+ *     Valid is 8, 16, 32, 64, 128, 256.
+ *
+ * pcm:
+ *     NOTE: only one pcm value must be given for every card.
+ *     The PCM bus id tells the mISDNdsp module about the connected PCM bus.
+ *     By default (0), the PCM bus id is 100 for the card that is PCM master.
+ *     If multiple cards are PCM master (because they are not interconnected),
+ *     each card with PCM master will have increasing PCM id.
+ *     All PCM busses with the same ID are expected to be connected and have
+ *     common time slots slots.
+ *     Only one chip of the PCM bus must be master, the others slave.
+ *     -1 means no support of PCM bus not even.
+ *     Omit this value, if all cards are interconnected or none is connected.
+ *     If unsure, don't give this parameter.
+ *
+ * dslot:
+ *     NOTE: only one poll value must be given for every card.
+ *     Also this value must be given for non-E1 cards. If omitted, the E1
+ *     card has D-channel on time slot 16, which is default.
+ *     If 1..15 or 17..31, an alternate time slot is used for D-channel.
+ *     In this case, the application must be able to handle this.
+ *     If -1 is given, the D-channel is disabled and all 31 slots can be used
+ *     for B-channel. (only for specific applications)
+ *     If you don't know how to use it, you don't need it!
+ *
+ * iomode:
+ *     NOTE: only one mode value must be given for every card.
+ *     -> See hfc_multi.h for HFC_IO_MODE_* values
+ *     By default, the IO mode is pci memory IO (MEMIO).
+ *     Some cards requre specific IO mode, so it cannot be changed.
+ *     It may be usefull to set IO mode to register io (REGIO) to solve
+ *     PCI bridge problems.
+ *     If unsure, don't give this parameter.
+ *
+ * clockdelay_nt:
+ *     NOTE: only one clockdelay_nt value must be given once for all cards.
+ *     Give the value of the clock control register (A_ST_CLK_DLY)
+ *     of the S/T interfaces in NT mode.
+ *     This register is needed for the TBR3 certification, so don't change it.
+ *
+ * clockdelay_te:
+ *     NOTE: only one clockdelay_te value must be given once
+ *     Give the value of the clock control register (A_ST_CLK_DLY)
+ *     of the S/T interfaces in TE mode.
+ *     This register is needed for the TBR3 certification, so don't change it.
+ */
+
+/*
+ * debug register access (never use this, it will flood your system log)
+ * #define HFC_REGISTER_DEBUG
+ */
+
+static const char *hfcmulti_revision = "2.00";
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mISDNhw.h>
+#include <linux/mISDNdsp.h>
+
+/*
+#define IRQCOUNT_DEBUG
+#define IRQ_DEBUG
+*/
+
+#include "hfc_multi.h"
+#ifdef ECHOPREP
+#include "gaintab.h"
+#endif
+
+#define        MAX_CARDS       8
+#define        MAX_PORTS       (8 * MAX_CARDS)
+
+static LIST_HEAD(HFClist);
+static spinlock_t HFClock; /* global hfc list lock */
+
+static void ph_state_change(struct dchannel *);
+static void (*hfc_interrupt)(void);
+static void (*register_interrupt)(void);
+static int (*unregister_interrupt)(void);
+static int interrupt_registered;
+
+static struct hfc_multi *syncmaster;
+int plxsd_master; /* if we have a master card (yet) */
+static spinlock_t plx_lock; /* may not acquire other lock inside */
+EXPORT_SYMBOL(plx_lock);
+
+#define        TYP_E1          1
+#define        TYP_4S          4
+#define TYP_8S         8
+
+static int poll_timer = 6;     /* default = 128 samples = 16ms */
+/* number of POLL_TIMER interrupts for G2 timeout (ca 1s) */
+static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30  };
+#define        CLKDEL_TE       0x0f    /* CLKDEL in TE mode */
+#define        CLKDEL_NT       0x6c    /* CLKDEL in NT mode
+                                  (0x60 MUST be included!) */
+static u_char silence =        0xff;   /* silence by LAW */
+
+#define        DIP_4S  0x1             /* DIP Switches for Beronet 1S/2S/4S cards */
+#define        DIP_8S  0x2             /* DIP Switches for Beronet 8S+ cards */
+#define        DIP_E1  0x3             /* DIP Switches for Beronet E1 cards */
+
+/*
+ * module stuff
+ */
+
+static uint    type[MAX_CARDS];
+static uint    pcm[MAX_CARDS];
+static uint    dslot[MAX_CARDS];
+static uint    iomode[MAX_CARDS];
+static uint    port[MAX_PORTS];
+static uint    debug;
+static uint    poll;
+static uint    timer;
+static uint    clockdelay_te = CLKDEL_TE;
+static uint    clockdelay_nt = CLKDEL_NT;
+
+static int     HFC_cnt, Port_cnt, PCM_cnt = 99;
+
+MODULE_AUTHOR("Andreas Eversberg");
+MODULE_LICENSE("GPL");
+module_param(debug, uint, S_IRUGO | S_IWUSR);
+module_param(poll, uint, S_IRUGO | S_IWUSR);
+module_param(timer, uint, S_IRUGO | S_IWUSR);
+module_param(clockdelay_te, uint, S_IRUGO | S_IWUSR);
+module_param(clockdelay_nt, uint, S_IRUGO | S_IWUSR);
+module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(pcm, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(dslot, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR);
+
+#ifdef HFC_REGISTER_DEBUG
+#define HFC_outb(hc, reg, val) \
+       (hc->HFC_outb(hc, reg, val, __func__, __LINE__))
+#define HFC_outb_nodebug(hc, reg, val) \
+       (hc->HFC_outb_nodebug(hc, reg, val, __func__, __LINE__))
+#define HFC_inb(hc, reg) \
+       (hc->HFC_inb(hc, reg, __func__, __LINE__))
+#define HFC_inb_nodebug(hc, reg) \
+       (hc->HFC_inb_nodebug(hc, reg, __func__, __LINE__))
+#define HFC_inw(hc, reg) \
+       (hc->HFC_inw(hc, reg, __func__, __LINE__))
+#define HFC_inw_nodebug(hc, reg) \
+       (hc->HFC_inw_nodebug(hc, reg, __func__, __LINE__))
+#define HFC_wait(hc) \
+       (hc->HFC_wait(hc, __func__, __LINE__))
+#define HFC_wait_nodebug(hc) \
+       (hc->HFC_wait_nodebug(hc, __func__, __LINE__))
+#else
+#define HFC_outb(hc, reg, val)         (hc->HFC_outb(hc, reg, val))
+#define HFC_outb_nodebug(hc, reg, val) (hc->HFC_outb_nodebug(hc, reg, val))
+#define HFC_inb(hc, reg)               (hc->HFC_inb(hc, reg))
+#define HFC_inb_nodebug(hc, reg)       (hc->HFC_inb_nodebug(hc, reg))
+#define HFC_inw(hc, reg)               (hc->HFC_inw(hc, reg))
+#define HFC_inw_nodebug(hc, reg)       (hc->HFC_inw_nodebug(hc, reg))
+#define HFC_wait(hc)                   (hc->HFC_wait(hc))
+#define HFC_wait_nodebug(hc)           (hc->HFC_wait_nodebug(hc))
+#endif
+
+/* HFC_IO_MODE_PCIMEM */
+static void
+#ifdef HFC_REGISTER_DEBUG
+HFC_outb_pcimem(struct hfc_multi *hc, u_char reg, u_char val,
+               const char *function, int line)
+#else
+HFC_outb_pcimem(struct hfc_multi *hc, u_char reg, u_char val)
+#endif
+{
+       writeb(val, (hc->pci_membase)+reg);
+}
+static u_char
+#ifdef HFC_REGISTER_DEBUG
+HFC_inb_pcimem(struct hfc_multi *hc, u_char reg, const char *function, int line)
+#else
+HFC_inb_pcimem(struct hfc_multi *hc, u_char reg)
+#endif
+{
+       return readb((hc->pci_membase)+reg);
+}
+static u_short
+#ifdef HFC_REGISTER_DEBUG
+HFC_inw_pcimem(struct hfc_multi *hc, u_char reg, const char *function, int line)
+#else
+HFC_inw_pcimem(struct hfc_multi *hc, u_char reg)
+#endif
+{
+       return readw((hc->pci_membase)+reg);
+}
+static void
+#ifdef HFC_REGISTER_DEBUG
+HFC_wait_pcimem(struct hfc_multi *hc, const char *function, int line)
+#else
+HFC_wait_pcimem(struct hfc_multi *hc)
+#endif
+{
+       while (readb((hc->pci_membase)+R_STATUS) & V_BUSY);
+}
+
+/* HFC_IO_MODE_REGIO */
+static void
+#ifdef HFC_REGISTER_DEBUG
+HFC_outb_regio(struct hfc_multi *hc, u_char reg, u_char val,
+       const char *function, int line)
+#else
+HFC_outb_regio(struct hfc_multi *hc, u_char reg, u_char val)
+#endif
+{
+       outb(reg, (hc->pci_iobase)+4);
+       outb(val, hc->pci_iobase);
+}
+static u_char
+#ifdef HFC_REGISTER_DEBUG
+HFC_inb_regio(struct hfc_multi *hc, u_char reg, const char *function, int line)
+#else
+HFC_inb_regio(struct hfc_multi *hc, u_char reg)
+#endif
+{
+       outb(reg, (hc->pci_iobase)+4);
+       return inb(hc->pci_iobase);
+}
+static u_short
+#ifdef HFC_REGISTER_DEBUG
+HFC_inw_regio(struct hfc_multi *hc, u_char reg, const char *function, int line)
+#else
+HFC_inw_regio(struct hfc_multi *hc, u_char reg)
+#endif
+{
+       outb(reg, (hc->pci_iobase)+4);
+       return inw(hc->pci_iobase);
+}
+static void
+#ifdef HFC_REGISTER_DEBUG
+HFC_wait_regio(struct hfc_multi *hc, const char *function, int line)
+#else
+HFC_wait_regio(struct hfc_multi *hc)
+#endif
+{
+       outb(R_STATUS, (hc->pci_iobase)+4);
+       while (inb(hc->pci_iobase) & V_BUSY);
+}
+
+#ifdef HFC_REGISTER_DEBUG
+static void
+HFC_outb_debug(struct hfc_multi *hc, u_char reg, u_char val,
+               const char *function, int line)
+{
+       char regname[256] = "", bits[9] = "xxxxxxxx";
+       int i;
+
+       i = -1;
+       while (hfc_register_names[++i].name) {
+               if (hfc_register_names[i].reg == reg)
+                       strcat(regname, hfc_register_names[i].name);
+       }
+       if (regname[0] == '\0')
+               strcpy(regname, "register");
+
+       bits[7] = '0'+(!!(val&1));
+       bits[6] = '0'+(!!(val&2));
+       bits[5] = '0'+(!!(val&4));
+       bits[4] = '0'+(!!(val&8));
+       bits[3] = '0'+(!!(val&16));
+       bits[2] = '0'+(!!(val&32));
+       bits[1] = '0'+(!!(val&64));
+       bits[0] = '0'+(!!(val&128));
+       printk(KERN_DEBUG
+           "HFC_outb(chip %d, %02x=%s, 0x%02x=%s); in %s() line %d\n",
+           hc->id, reg, regname, val, bits, function, line);
+       HFC_outb_nodebug(hc, reg, val);
+}
+static u_char
+HFC_inb_debug(struct hfc_multi *hc, u_char reg, const char *function, int line)
+{
+       char regname[256] = "", bits[9] = "xxxxxxxx";
+       u_char val = HFC_inb_nodebug(hc, reg);
+       int i;
+
+       i = 0;
+       while (hfc_register_names[i++].name)
+               ;
+       while (hfc_register_names[++i].name) {
+               if (hfc_register_names[i].reg == reg)
+                       strcat(regname, hfc_register_names[i].name);
+       }
+       if (regname[0] == '\0')
+               strcpy(regname, "register");
+
+       bits[7] = '0'+(!!(val&1));
+       bits[6] = '0'+(!!(val&2));
+       bits[5] = '0'+(!!(val&4));
+       bits[4] = '0'+(!!(val&8));
+       bits[3] = '0'+(!!(val&16));
+       bits[2] = '0'+(!!(val&32));
+       bits[1] = '0'+(!!(val&64));
+       bits[0] = '0'+(!!(val&128));
+       printk(KERN_DEBUG
+           "HFC_inb(chip %d, %02x=%s) = 0x%02x=%s; in %s() line %d\n",
+           hc->id, reg, regname, val, bits, function, line);
+       return val;
+}
+static u_short
+HFC_inw_debug(struct hfc_multi *hc, u_char reg, const char *function, int line)
+{
+       char regname[256] = "";
+       u_short val = HFC_inw_nodebug(hc, reg);
+       int i;
+
+       i = 0;
+       while (hfc_register_names[i++].name)
+               ;
+       while (hfc_register_names[++i].name) {
+               if (hfc_register_names[i].reg == reg)
+                       strcat(regname, hfc_register_names[i].name);
+       }
+       if (regname[0] == '\0')
+               strcpy(regname, "register");
+
+       printk(KERN_DEBUG
+           "HFC_inw(chip %d, %02x=%s) = 0x%04x; in %s() line %d\n",
+           hc->id, reg, regname, val, function, line);
+       return val;
+}
+static void
+HFC_wait_debug(struct hfc_multi *hc, const char *function, int line)
+{
+       printk(KERN_DEBUG "HFC_wait(chip %d); in %s() line %d\n",
+           hc->id, function, line);
+       HFC_wait_nodebug(hc);
+}
+#endif
+
+/* write fifo data (REGIO) */
+void
+write_fifo_regio(struct hfc_multi *hc, u_char *data, int len)
+{
+       outb(A_FIFO_DATA0, (hc->pci_iobase)+4);
+       while (len>>2) {
+               outl(*(u32 *)data, hc->pci_iobase);
+               data += 4;
+               len -= 4;
+       }
+       while (len>>1) {
+               outw(*(u16 *)data, hc->pci_iobase);
+               data += 2;
+               len -= 2;
+       }
+       while (len) {
+               outb(*data, hc->pci_iobase);
+               data++;
+               len--;
+       }
+}
+/* write fifo data (PCIMEM) */
+void
+write_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len)
+{
+       while (len>>2) {
+               writel(*(u32 *)data, (hc->pci_membase)+A_FIFO_DATA0);
+               data += 4;
+               len -= 4;
+       }
+       while (len>>1) {
+               writew(*(u16 *)data, (hc->pci_membase)+A_FIFO_DATA0);
+               data += 2;
+               len -= 2;
+       }
+       while (len) {
+               writeb(*data, (hc->pci_membase)+A_FIFO_DATA0);
+               data++;
+               len--;
+       }
+}
+/* read fifo data (REGIO) */
+void
+read_fifo_regio(struct hfc_multi *hc, u_char *data, int len)
+{
+       outb(A_FIFO_DATA0, (hc->pci_iobase)+4);
+       while (len>>2) {
+               *(u32 *)data = inl(hc->pci_iobase);
+               data += 4;
+               len -= 4;
+       }
+       while (len>>1) {
+               *(u16 *)data = inw(hc->pci_iobase);
+               data += 2;
+               len -= 2;
+       }
+       while (len) {
+               *data = inb(hc->pci_iobase);
+               data++;
+               len--;
+       }
+}
+
+/* read fifo data (PCIMEM) */
+void
+read_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len)
+{
+       while (len>>2) {
+               *(u32 *)data =
+                       readl((hc->pci_membase)+A_FIFO_DATA0);
+               data += 4;
+               len -= 4;
+       }
+       while (len>>1) {
+               *(u16 *)data =
+                       readw((hc->pci_membase)+A_FIFO_DATA0);
+               data += 2;
+               len -= 2;
+       }
+       while (len) {
+               *data = readb((hc->pci_membase)+A_FIFO_DATA0);
+               data++;
+               len--;
+       }
+}
+
+
+static void
+enable_hwirq(struct hfc_multi *hc)
+{
+       hc->hw.r_irq_ctrl |= V_GLOB_IRQ_EN;
+       HFC_outb(hc, R_IRQ_CTRL, hc->hw.r_irq_ctrl);
+}
+
+static void
+disable_hwirq(struct hfc_multi *hc)
+{
+       hc->hw.r_irq_ctrl &= ~((u_char)V_GLOB_IRQ_EN);
+       HFC_outb(hc, R_IRQ_CTRL, hc->hw.r_irq_ctrl);
+}
+
+#define        NUM_EC 2
+#define        MAX_TDM_CHAN 32
+
+
+inline void
+enablepcibridge(struct hfc_multi *c)
+{
+       HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x3); /* was _io before */
+}
+
+inline void
+disablepcibridge(struct hfc_multi *c)
+{
+       HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x2); /* was _io before */
+}
+
+inline unsigned char
+readpcibridge(struct hfc_multi *hc, unsigned char address)
+{
+       unsigned short cipv;
+       unsigned char data;
+
+       if (!hc->pci_iobase)
+               return 0;
+
+       /* slow down a PCI read access by 1 PCI clock cycle */
+       HFC_outb(hc, R_CTRL, 0x4); /*was _io before*/
+
+       if (address == 0)
+               cipv = 0x4000;
+       else
+               cipv = 0x5800;
+
+       /* select local bridge port address by writing to CIP port */
+       /* data = HFC_inb(c, cipv); * was _io before */
+       outw(cipv, hc->pci_iobase + 4);
+       data = inb(hc->pci_iobase);
+
+       /* restore R_CTRL for normal PCI read cycle speed */
+       HFC_outb(hc, R_CTRL, 0x0); /* was _io before */
+
+       return data;
+}
+
+inline void
+writepcibridge(struct hfc_multi *hc, unsigned char address, unsigned char data)
+{
+       unsigned short cipv;
+       unsigned int datav;
+
+       if (!hc->pci_iobase)
+               return;
+
+       if (address == 0)
+               cipv = 0x4000;
+       else
+               cipv = 0x5800;
+
+       /* select local bridge port address by writing to CIP port */
+       outw(cipv, hc->pci_iobase + 4);
+       /* define a 32 bit dword with 4 identical bytes for write sequence */
+       datav = data | ((__u32) data << 8) | ((__u32) data << 16) |
+           ((__u32) data << 24);
+
+       /*
+        * write this 32 bit dword to the bridge data port
+        * this will initiate a write sequence of up to 4 writes to the same
+        * address on the local bus interface the number of write accesses
+        * is undefined but >=1 and depends on the next PCI transaction
+        * during write sequence on the local bus
+        */
+       outl(datav, hc->pci_iobase);
+}
+
+inline void
+cpld_set_reg(struct hfc_multi *hc, unsigned char reg)
+{
+       /* Do data pin read low byte */
+       HFC_outb(hc, R_GPIO_OUT1, reg);
+}
+
+inline void
+cpld_write_reg(struct hfc_multi *hc, unsigned char reg, unsigned char val)
+{
+       cpld_set_reg(hc, reg);
+
+       enablepcibridge(hc);
+       writepcibridge(hc, 1, val);
+       disablepcibridge(hc);
+
+       return;
+}
+
+inline unsigned char
+cpld_read_reg(struct hfc_multi *hc, unsigned char reg)
+{
+       unsigned char bytein;
+
+       cpld_set_reg(hc, reg);
+
+       /* Do data pin read low byte */
+       HFC_outb(hc, R_GPIO_OUT1, reg);
+
+       enablepcibridge(hc);
+       bytein = readpcibridge(hc, 1);
+       disablepcibridge(hc);
+
+       return bytein;
+}
+
+inline void
+vpm_write_address(struct hfc_multi *hc, unsigned short addr)
+{
+       cpld_write_reg(hc, 0, 0xff & addr);
+       cpld_write_reg(hc, 1, 0x01 & (addr >> 8));
+}
+
+inline unsigned short
+vpm_read_address(struct hfc_multi *c)
+{
+       unsigned short addr;
+       unsigned short highbit;
+
+       addr = cpld_read_reg(c, 0);
+       highbit = cpld_read_reg(c, 1);
+
+       addr = addr | (highbit << 8);
+
+       return addr & 0x1ff;
+}
+
+inline unsigned char
+vpm_in(struct hfc_multi *c, int which, unsigned short addr)
+{
+       unsigned char res;
+
+       vpm_write_address(c, addr);
+
+       if (!which)
+               cpld_set_reg(c, 2);
+       else
+               cpld_set_reg(c, 3);
+
+       enablepcibridge(c);
+       res = readpcibridge(c, 1);
+       disablepcibridge(c);
+
+       cpld_set_reg(c, 0);
+
+       return res;
+}
+
+inline void
+vpm_out(struct hfc_multi *c, int which, unsigned short addr,
+    unsigned char data)
+{
+       vpm_write_address(c, addr);
+
+       enablepcibridge(c);
+
+       if (!which)
+               cpld_set_reg(c, 2);
+       else
+               cpld_set_reg(c, 3);
+
+       writepcibridge(c, 1, data);
+
+       cpld_set_reg(c, 0);
+
+       disablepcibridge(c);
+
+       {
+       unsigned char regin;
+       regin = vpm_in(c, which, addr);
+       if (regin != data)
+               printk(KERN_DEBUG "Wrote 0x%x to register 0x%x but got back "
+                       "0x%x\n", data, addr, regin);
+       }
+
+}
+
+
+void
+vpm_init(struct hfc_multi *wc)
+{
+       unsigned char reg;
+       unsigned int mask;
+       unsigned int i, x, y;
+       unsigned int ver;
+
+       for (x = 0; x < NUM_EC; x++) {
+               /* Setup GPIO's */
+               if (!x) {
+                       ver = vpm_in(wc, x, 0x1a0);
+                       printk(KERN_DEBUG "VPM: Chip %d: ver %02x\n", x, ver);
+               }
+
+               for (y = 0; y < 4; y++) {
+                       vpm_out(wc, x, 0x1a8 + y, 0x00); /* GPIO out */
+                       vpm_out(wc, x, 0x1ac + y, 0x00); /* GPIO dir */
+                       vpm_out(wc, x, 0x1b0 + y, 0x00); /* GPIO sel */
+               }
+
+               /* Setup TDM path - sets fsync and tdm_clk as inputs */
+               reg = vpm_in(wc, x, 0x1a3); /* misc_con */
+               vpm_out(wc, x, 0x1a3, reg & ~2);
+
+               /* Setup Echo length (256 taps) */
+               vpm_out(wc, x, 0x022, 1);
+               vpm_out(wc, x, 0x023, 0xff);
+
+               /* Setup timeslots */
+               vpm_out(wc, x, 0x02f, 0x00);
+               mask = 0x02020202 << (x * 4);
+
+               /* Setup the tdm channel masks for all chips */
+               for (i = 0; i < 4; i++)
+                       vpm_out(wc, x, 0x33 - i, (mask >> (i << 3)) & 0xff);
+
+               /* Setup convergence rate */
+               printk(KERN_DEBUG "VPM: A-law mode\n");
+               reg = 0x00 | 0x10 | 0x01;
+               vpm_out(wc, x, 0x20, reg);
+               printk(KERN_DEBUG "VPM reg 0x20 is %x\n", reg);
+               /*vpm_out(wc, x, 0x20, (0x00 | 0x08 | 0x20 | 0x10)); */
+
+               vpm_out(wc, x, 0x24, 0x02);
+               reg = vpm_in(wc, x, 0x24);
+               printk(KERN_DEBUG "NLP Thresh is set to %d (0x%x)\n", reg, reg);
+
+               /* Initialize echo cans */
+               for (i = 0; i < MAX_TDM_CHAN; i++) {
+                       if (mask & (0x00000001 << i))
+                               vpm_out(wc, x, i, 0x00);
+               }
+
+               /*
+                * ARM arch at least disallows a udelay of
+                * more than 2ms... it gives a fake "__bad_udelay"
+                * reference at link-time.
+                * long delays in kernel code are pretty sucky anyway
+                * for now work around it using 5 x 2ms instead of 1 x 10ms
+                */
+
+               udelay(2000);
+               udelay(2000);
+               udelay(2000);
+               udelay(2000);
+               udelay(2000);
+
+               /* Put in bypass mode */
+               for (i = 0; i < MAX_TDM_CHAN; i++) {
+                       if (mask & (0x00000001 << i))
+                               vpm_out(wc, x, i, 0x01);
+               }
+
+               /* Enable bypass */
+               for (i = 0; i < MAX_TDM_CHAN; i++) {
+                       if (mask & (0x00000001 << i))
+                               vpm_out(wc, x, 0x78 + i, 0x01);
+               }
+
+       }
+}
+
+void
+vpm_check(struct hfc_multi *hctmp)
+{
+       unsigned char gpi2;
+
+       gpi2 = HFC_inb(hctmp, R_GPI_IN2);
+
+       if ((gpi2 & 0x3) != 0x3)
+               printk(KERN_DEBUG "Got interrupt 0x%x from VPM!\n", gpi2);
+}
+
+
+/*
+ * Interface to enable/disable the HW Echocan
+ *
+ * these functions are called within a spin_lock_irqsave on
+ * the channel instance lock, so we are not disturbed by irqs
+ *
+ * we can later easily change the interface to make  other
+ * things configurable, for now we configure the taps
+ *
+ */
+
+void
+vpm_echocan_on(struct hfc_multi *hc, int ch, int taps)
+{
+       unsigned int timeslot;
+       unsigned int unit;
+       struct bchannel *bch = hc->chan[ch].bch;
+#ifdef TXADJ
+       int txadj = -4;
+       struct sk_buff *skb;
+#endif
+       if (hc->chan[ch].protocol != ISDN_P_B_RAW)
+               return;
+
+       if (!bch)
+               return;
+
+#ifdef TXADJ
+       skb = _alloc_mISDN_skb(PH_CONTROL_IND, HFC_VOL_CHANGE_TX,
+               sizeof(int), &txadj, GFP_ATOMIC);
+       if (skb)
+               recv_Bchannel_skb(bch, skb);
+#endif
+
+       timeslot = ((ch/4)*8) + ((ch%4)*4) + 1;
+       unit = ch % 4;
+
+       printk(KERN_NOTICE "vpm_echocan_on called taps [%d] on timeslot %d\n",
+           taps, timeslot);
+
+       vpm_out(hc, unit, timeslot, 0x7e);
+}
+
+void
+vpm_echocan_off(struct hfc_multi *hc, int ch)
+{
+       unsigned int timeslot;
+       unsigned int unit;
+       struct bchannel *bch = hc->chan[ch].bch;
+#ifdef TXADJ
+       int txadj = 0;
+       struct sk_buff *skb;
+#endif
+
+       if (hc->chan[ch].protocol != ISDN_P_B_RAW)
+               return;
+
+       if (!bch)
+               return;
+
+#ifdef TXADJ
+       skb = _alloc_mISDN_skb(PH_CONTROL_IND, HFC_VOL_CHANGE_TX,
+               sizeof(int), &txadj, GFP_ATOMIC);
+       if (skb)
+               recv_Bchannel_skb(bch, skb);
+#endif
+
+       timeslot = ((ch/4)*8) + ((ch%4)*4) + 1;
+       unit = ch % 4;
+
+       printk(KERN_NOTICE "vpm_echocan_off called on timeslot %d\n",
+           timeslot);
+       /* FILLME */
+       vpm_out(hc, unit, timeslot, 0x01);
+}
+
+
+/*
+ * Speech Design resync feature
+ * NOTE: This is called sometimes outside interrupt handler.
+ * We must lock irqsave, so no other interrupt (other card) will occurr!
+ * Also multiple interrupts may nest, so must lock each access (lists, card)!
+ */
+static inline void
+hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm)
+{
+       struct hfc_multi *hc, *next, *pcmmaster = 0;
+       u_int *plx_acc_32, pv;
+       u_long flags;
+
+       spin_lock_irqsave(&HFClock, flags);
+       spin_lock(&plx_lock); /* must be locked inside other locks */
+
+       if (debug & DEBUG_HFCMULTI_PLXSD)
+               printk(KERN_DEBUG "%s: RESYNC(syncmaster=0x%p)\n",
+                       __func__, syncmaster);
+
+       /* select new master */
+       if (newmaster) {
+               if (debug & DEBUG_HFCMULTI_PLXSD)
+                       printk(KERN_DEBUG "using provided controller\n");
+       } else {
+               list_for_each_entry_safe(hc, next, &HFClist, list) {
+                       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+                               if (hc->syncronized) {
+                                       newmaster = hc;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /* Disable sync of all cards */
+       list_for_each_entry_safe(hc, next, &HFClist, list) {
+               if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+                       plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC);
+                       pv = readl(plx_acc_32);
+                       pv &= ~PLX_SYNC_O_EN;
+                       writel(pv, plx_acc_32);
+                       if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)) {
+                               pcmmaster = hc;
+                               if (hc->type == 1) {
+                                       if (debug & DEBUG_HFCMULTI_PLXSD)
+                                               printk(KERN_DEBUG
+                                                       "Schedule SYNC_I\n");
+                                       hc->e1_resync |= 1; /* get SYNC_I */
+                               }
+                       }
+               }
+       }
+
+       if (newmaster) {
+               hc = newmaster;
+               if (debug & DEBUG_HFCMULTI_PLXSD)
+                       printk(KERN_DEBUG "id=%d (0x%p) = syncronized with "
+                               "interface.\n", hc->id, hc);
+               /* Enable new sync master */
+               plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC);
+               pv = readl(plx_acc_32);
+               pv |= PLX_SYNC_O_EN;
+               writel(pv, plx_acc_32);
+               /* switch to jatt PLL, if not disabled by RX_SYNC */
+               if (hc->type == 1 && !test_bit(HFC_CHIP_RX_SYNC, &hc->chip)) {
+                       if (debug & DEBUG_HFCMULTI_PLXSD)
+                               printk(KERN_DEBUG "Schedule jatt PLL\n");
+                       hc->e1_resync |= 2; /* switch to jatt */
+               }
+       } else {
+               if (pcmmaster) {
+                       hc = pcmmaster;
+                       if (debug & DEBUG_HFCMULTI_PLXSD)
+                               printk(KERN_DEBUG
+                                       "id=%d (0x%p) = PCM master syncronized "
+                                       "with QUARTZ\n", hc->id, hc);
+                       if (hc->type == 1) {
+                               /* Use the crystal clock for the PCM
+                                  master card */
+                               if (debug & DEBUG_HFCMULTI_PLXSD)
+                                       printk(KERN_DEBUG
+                                           "Schedule QUARTZ for HFC-E1\n");
+                               hc->e1_resync |= 4; /* switch quartz */
+                       } else {
+                               if (debug & DEBUG_HFCMULTI_PLXSD)
+                                       printk(KERN_DEBUG
+                                           "QUARTZ is automatically "
+                                           "enabled by HFC-%dS\n", hc->type);
+                       }
+                       plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC);
+                       pv = readl(plx_acc_32);
+                       pv |= PLX_SYNC_O_EN;
+                       writel(pv, plx_acc_32);
+               } else
+                       if (!rm)
+                               printk(KERN_ERR "%s no pcm master, this MUST "
+                                       "not happen!\n", __func__);
+       }
+       syncmaster = newmaster;
+
+       spin_unlock(&plx_lock);
+       spin_unlock_irqrestore(&HFClock, flags);
+}
+
+/* This must be called AND hc must be locked irqsave!!! */
+inline void
+plxsd_checksync(struct hfc_multi *hc, int rm)
+{
+       if (hc->syncronized) {
+               if (syncmaster == NULL) {
+                       if (debug & DEBUG_HFCMULTI_PLXSD)
+                               printk(KERN_WARNING "%s: GOT sync on card %d"
+                                       " (id=%d)\n", __func__, hc->id + 1,
+                                       hc->id);
+                       hfcmulti_resync(hc, hc, rm);
+               }
+       } else {
+               if (syncmaster == hc) {
+                       if (debug & DEBUG_HFCMULTI_PLXSD)
+                               printk(KERN_WARNING "%s: LOST sync on card %d"
+                                       " (id=%d)\n", __func__, hc->id + 1,
+                                       hc->id);
+                       hfcmulti_resync(hc, NULL, rm);
+               }
+       }
+}
+
+
+/*
+ * free hardware resources used by driver
+ */
+static void
+release_io_hfcmulti(struct hfc_multi *hc)
+{
+       u_int   *plx_acc_32, pv;
+       u_long  plx_flags;
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: entered\n", __func__);
+
+       /* soft reset also masks all interrupts */
+       hc->hw.r_cirm |= V_SRES;
+       HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
+       udelay(1000);
+       hc->hw.r_cirm &= ~V_SRES;
+       HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
+       udelay(1000); /* instead of 'wait' that may cause locking */
+
+       /* release Speech Design card, if PLX was initialized */
+       if (test_bit(HFC_CHIP_PLXSD, &hc->chip) && hc->plx_membase) {
+               if (debug & DEBUG_HFCMULTI_PLXSD)
+                       printk(KERN_DEBUG "%s: release PLXSD card %d\n",
+                           __func__, hc->id + 1);
+               spin_lock_irqsave(&plx_lock, plx_flags);
+               plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC);
+               writel(PLX_GPIOC_INIT, plx_acc_32);
+               pv = readl(plx_acc_32);
+               /* Termination off */
+               pv &= ~PLX_TERM_ON;
+               /* Disconnect the PCM */
+               pv |= PLX_SLAVE_EN_N;
+               pv &= ~PLX_MASTER_EN;
+               pv &= ~PLX_SYNC_O_EN;
+               /* Put the DSP in Reset */
+               pv &= ~PLX_DSP_RES_N;
+               writel(pv, plx_acc_32);
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_WARNING "%s: PCM off: PLX_GPIO=%x\n",
+                               __func__, pv);
+               spin_unlock_irqrestore(&plx_lock, plx_flags);
+       }
+
+       /* disable memory mapped ports / io ports */
+       test_and_clear_bit(HFC_CHIP_PLXSD, &hc->chip); /* prevent resync */
+       pci_write_config_word(hc->pci_dev, PCI_COMMAND, 0);
+       if (hc->pci_membase)
+               iounmap((void *)hc->pci_membase);
+       if (hc->plx_membase)
+               iounmap((void *)hc->plx_membase);
+       if (hc->pci_iobase)
+               release_region(hc->pci_iobase, 8);
+
+       if (hc->pci_dev) {
+               pci_disable_device(hc->pci_dev);
+               pci_set_drvdata(hc->pci_dev, NULL);
+       }
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: done\n", __func__);
+}
+
+/*
+ * function called to reset the HFC chip. A complete software reset of chip
+ * and fifos is done. All configuration of the chip is done.
+ */
+
+static int
+init_chip(struct hfc_multi *hc)
+{
+       u_long                  flags, val, val2 = 0, rev;
+       int                     i, err = 0;
+       u_char                  r_conf_en, rval;
+       u_int                   *plx_acc_32, pv;
+       u_long                  plx_flags, hfc_flags;
+       int                     plx_count;
+       struct hfc_multi        *pos, *next, *plx_last_hc;
+
+       spin_lock_irqsave(&hc->lock, flags);
+       /* reset all registers */
+       memset(&hc->hw, 0, sizeof(struct hfcm_hw));
+
+       /* revision check */
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: entered\n", __func__);
+       val = HFC_inb(hc, R_CHIP_ID)>>4;
+       if (val != 0x8 && val != 0xc && val != 0xe) {
+               printk(KERN_INFO "HFC_multi: unknown CHIP_ID:%x\n", (u_int)val);
+               err = -EIO;
+               goto out;
+       }
+       rev = HFC_inb(hc, R_CHIP_RV);
+       printk(KERN_INFO
+           "HFC_multi: detected HFC with chip ID=0x%lx revision=%ld%s\n",
+           val, rev, (rev == 0) ? " (old FIFO handling)" : "");
+       if (rev == 0) {
+               test_and_set_bit(HFC_CHIP_REVISION0, &hc->chip);
+               printk(KERN_WARNING
+                   "HFC_multi: NOTE: Your chip is revision 0, "
+                   "ask Cologne Chip for update. Newer chips "
+                   "have a better FIFO handling. Old chips "
+                   "still work but may have slightly lower "
+                   "HDLC transmit performance.\n");
+       }
+       if (rev > 1) {
+               printk(KERN_WARNING "HFC_multi: WARNING: This driver doesn't "
+                   "consider chip revision = %ld. The chip / "
+                   "bridge may not work.\n", rev);
+       }
+
+       /* set s-ram size */
+       hc->Flen = 0x10;
+       hc->Zmin = 0x80;
+       hc->Zlen = 384;
+       hc->DTMFbase = 0x1000;
+       if (test_bit(HFC_CHIP_EXRAM_128, &hc->chip)) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: changing to 128K extenal RAM\n",
+                           __func__);
+               hc->hw.r_ctrl |= V_EXT_RAM;
+               hc->hw.r_ram_sz = 1;
+               hc->Flen = 0x20;
+               hc->Zmin = 0xc0;
+               hc->Zlen = 1856;
+               hc->DTMFbase = 0x2000;
+       }
+       if (test_bit(HFC_CHIP_EXRAM_512, &hc->chip)) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: changing to 512K extenal RAM\n",
+                           __func__);
+               hc->hw.r_ctrl |= V_EXT_RAM;
+               hc->hw.r_ram_sz = 2;
+               hc->Flen = 0x20;
+               hc->Zmin = 0xc0;
+               hc->Zlen = 8000;
+               hc->DTMFbase = 0x2000;
+       }
+       hc->max_trans = poll << 1;
+       if (hc->max_trans > hc->Zlen)
+               hc->max_trans = hc->Zlen;
+
+       /* Speech Design PLX bridge */
+       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+               if (debug & DEBUG_HFCMULTI_PLXSD)
+                       printk(KERN_DEBUG "%s: initializing PLXSD card %d\n",
+                           __func__, hc->id + 1);
+               spin_lock_irqsave(&plx_lock, plx_flags);
+               plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC);
+               writel(PLX_GPIOC_INIT, plx_acc_32);
+               pv = readl(plx_acc_32);
+               /* The first and the last cards are terminating the PCM bus */
+               pv |= PLX_TERM_ON; /* hc is currently the last */
+               /* Disconnect the PCM */
+               pv |= PLX_SLAVE_EN_N;
+               pv &= ~PLX_MASTER_EN;
+               pv &= ~PLX_SYNC_O_EN;
+               /* Put the DSP in Reset */
+               pv &= ~PLX_DSP_RES_N;
+               writel(pv, plx_acc_32);
+               spin_unlock_irqrestore(&plx_lock, plx_flags);
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_WARNING "%s: slave/term: PLX_GPIO=%x\n",
+                               __func__, pv);
+               /*
+                * If we are the 3rd PLXSD card or higher, we must turn
+                * termination of last PLXSD card off.
+                */
+               spin_lock_irqsave(&HFClock, hfc_flags);
+               plx_count = 0;
+               plx_last_hc = NULL;
+               list_for_each_entry_safe(pos, next, &HFClist, list) {
+                       if (test_bit(HFC_CHIP_PLXSD, &pos->chip)) {
+                               plx_count++;
+                               if (pos != hc)
+                                       plx_last_hc = pos;
+                       }
+               }
+               if (plx_count >= 3) {
+                       if (debug & DEBUG_HFCMULTI_PLXSD)
+                               printk(KERN_DEBUG "%s: card %d is between, so "
+                                       "we disable termination\n",
+                                   __func__, plx_last_hc->id + 1);
+                       spin_lock_irqsave(&plx_lock, plx_flags);
+                       plx_acc_32 = (u_int *)(plx_last_hc->plx_membase
+                                       + PLX_GPIOC);
+                       pv = readl(plx_acc_32);
+                       pv &= ~PLX_TERM_ON;
+                       writel(pv, plx_acc_32);
+                       spin_unlock_irqrestore(&plx_lock, plx_flags);
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                           printk(KERN_WARNING "%s: term off: PLX_GPIO=%x\n",
+                                       __func__, pv);
+               }
+               spin_unlock_irqrestore(&HFClock, hfc_flags);
+               hc->hw.r_pcm_md0 = V_F0_LEN; /* shift clock for DSP */
+       }
+
+       /* we only want the real Z2 read-pointer for revision > 0 */
+       if (!test_bit(HFC_CHIP_REVISION0, &hc->chip))
+               hc->hw.r_ram_sz |= V_FZ_MD;
+
+       /* select pcm mode */
+       if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: setting PCM into slave mode\n",
+                           __func__);
+       } else
+       if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip) && !plxsd_master) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: setting PCM into master mode\n",
+                           __func__);
+               hc->hw.r_pcm_md0 |= V_PCM_MD;
+       } else {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: performing PCM auto detect\n",
+                           __func__);
+       }
+
+       /* soft reset */
+       HFC_outb(hc, R_CTRL, hc->hw.r_ctrl);
+       HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
+       HFC_outb(hc, R_FIFO_MD, 0);
+       hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES | V_RLD_EPR;
+       HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
+       udelay(100);
+       hc->hw.r_cirm = 0;
+       HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
+       udelay(100);
+       HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
+
+       /* Speech Design PLX bridge pcm and sync mode */
+       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+               spin_lock_irqsave(&plx_lock, plx_flags);
+               plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC);
+               pv = readl(plx_acc_32);
+               /* Connect PCM */
+               if (hc->hw.r_pcm_md0 & V_PCM_MD) {
+                       pv |= PLX_MASTER_EN | PLX_SLAVE_EN_N;
+                       pv |= PLX_SYNC_O_EN;
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_WARNING "%s: master: PLX_GPIO=%x\n",
+                                       __func__, pv);
+               } else {
+                       pv &= ~(PLX_MASTER_EN | PLX_SLAVE_EN_N);
+                       pv &= ~PLX_SYNC_O_EN;
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_WARNING "%s: slave: PLX_GPIO=%x\n",
+                                       __func__, pv);
+               }
+               writel(pv, plx_acc_32);
+               spin_unlock_irqrestore(&plx_lock, plx_flags);
+       }
+
+       /* PCM setup */
+       HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x90);
+       if (hc->slots == 32)
+               HFC_outb(hc, R_PCM_MD1, 0x00);
+       if (hc->slots == 64)
+               HFC_outb(hc, R_PCM_MD1, 0x10);
+       if (hc->slots == 128)
+               HFC_outb(hc, R_PCM_MD1, 0x20);
+       HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0xa0);
+       if (test_bit(HFC_CHIP_PLXSD, &hc->chip))
+               HFC_outb(hc, R_PCM_MD2, V_SYNC_SRC); /* sync via SYNC_I / O */
+       else
+               HFC_outb(hc, R_PCM_MD2, 0x00); /* sync from interface */
+       HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00);
+       for (i = 0; i < 256; i++) {
+               HFC_outb_nodebug(hc, R_SLOT, i);
+               HFC_outb_nodebug(hc, A_SL_CFG, 0);
+               HFC_outb_nodebug(hc, A_CONF, 0);
+               hc->slot_owner[i] = -1;
+       }
+
+       /* set clock speed */
+       if (test_bit(HFC_CHIP_CLOCK2, &hc->chip)) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG
+                           "%s: setting double clock\n", __func__);
+               HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK);
+       }
+
+       /* B410P GPIO */
+       if (test_bit(HFC_CHIP_B410P, &hc->chip)) {
+               printk(KERN_NOTICE "Setting GPIOs\n");
+               HFC_outb(hc, R_GPIO_SEL, 0x30);
+               HFC_outb(hc, R_GPIO_EN1, 0x3);
+               udelay(1000);
+               printk(KERN_NOTICE "calling vpm_init\n");
+               vpm_init(hc);
+       }
+
+       /* check if R_F0_CNT counts (8 kHz frame count) */
+       val = HFC_inb(hc, R_F0_CNTL);
+       val += HFC_inb(hc, R_F0_CNTH) << 8;
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG
+                   "HFC_multi F0_CNT %ld after reset\n", val);
+       spin_unlock_irqrestore(&hc->lock, flags);
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout((HZ/100)?:1); /* Timeout minimum 10ms */
+       spin_lock_irqsave(&hc->lock, flags);
+       val2 = HFC_inb(hc, R_F0_CNTL);
+       val2 += HFC_inb(hc, R_F0_CNTH) << 8;
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG
+                       "HFC_multi F0_CNT %ld after 10 ms (1st try)\n",
+                   val2);
+       if (val2 >= val+8) { /* 1 ms */
+               /* it counts, so we keep the pcm mode */
+               if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip))
+                       printk(KERN_INFO "controller is PCM bus MASTER\n");
+               else
+               if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip))
+                       printk(KERN_INFO "controller is PCM bus SLAVE\n");
+               else {
+                       test_and_set_bit(HFC_CHIP_PCM_SLAVE, &hc->chip);
+                       printk(KERN_INFO "controller is PCM bus SLAVE "
+                               "(auto detected)\n");
+               }
+       } else {
+               /* does not count */
+               if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)) {
+controller_fail:
+                       printk(KERN_ERR "HFC_multi ERROR, getting no 125us "
+                           "pulse. Seems that controller fails.\n");
+                       err = -EIO;
+                       goto out;
+               }
+               if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
+                       printk(KERN_INFO "controller is PCM bus SLAVE "
+                               "(ignoring missing PCM clock)\n");
+               } else {
+                       /* only one pcm master */
+                       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)
+                               && plxsd_master) {
+                               printk(KERN_ERR "HFC_multi ERROR, no clock "
+                                   "on another Speech Design card found. "
+                                   "Please be sure to connect PCM cable.\n");
+                               err = -EIO;
+                               goto out;
+                       }
+                       /* retry with master clock */
+                       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+                               spin_lock_irqsave(&plx_lock, plx_flags);
+                               plx_acc_32 = (u_int *)(hc->plx_membase +
+                                       PLX_GPIOC);
+                               pv = readl(plx_acc_32);
+                               pv |= PLX_MASTER_EN | PLX_SLAVE_EN_N;
+                               pv |= PLX_SYNC_O_EN;
+                               writel(pv, plx_acc_32);
+                               spin_unlock_irqrestore(&plx_lock, plx_flags);
+                               if (debug & DEBUG_HFCMULTI_INIT)
+                                   printk(KERN_WARNING "%s: master: PLX_GPIO"
+                                       "=%x\n", __func__, pv);
+                       }
+                       hc->hw.r_pcm_md0 |= V_PCM_MD;
+                       HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00);
+                       spin_unlock_irqrestore(&hc->lock, flags);
+                       set_current_state(TASK_UNINTERRUPTIBLE);
+                       schedule_timeout((HZ/100)?:1); /* Timeout min. 10ms */
+                       spin_lock_irqsave(&hc->lock, flags);
+                       val2 = HFC_inb(hc, R_F0_CNTL);
+                       val2 += HFC_inb(hc, R_F0_CNTH) << 8;
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_DEBUG "HFC_multi F0_CNT %ld after "
+                                       "10 ms (2nd try)\n", val2);
+                       if (val2 >= val+8) { /* 1 ms */
+                               test_and_set_bit(HFC_CHIP_PCM_MASTER,
+                                       &hc->chip);
+                               printk(KERN_INFO "controller is PCM bus MASTER "
+                                       "(auto detected)\n");
+                       } else
+                               goto controller_fail;
+               }
+       }
+
+       /* Release the DSP Reset */
+       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+               if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip))
+                       plxsd_master = 1;
+               spin_lock_irqsave(&plx_lock, plx_flags);
+               plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC);
+               pv = readl(plx_acc_32);
+               pv |=  PLX_DSP_RES_N;
+               writel(pv, plx_acc_32);
+               spin_unlock_irqrestore(&plx_lock, plx_flags);
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_WARNING "%s: reset off: PLX_GPIO=%x\n",
+                               __func__, pv);
+       }
+
+       /* pcm id */
+       if (hc->pcm)
+               printk(KERN_INFO "controller has given PCM BUS ID %d\n",
+                       hc->pcm);
+       else {
+               if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)
+                || test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+                       PCM_cnt++; /* SD has proprietary bridging */
+               }
+               hc->pcm = PCM_cnt;
+               printk(KERN_INFO "controller has PCM BUS ID %d "
+                       "(auto selected)\n", hc->pcm);
+       }
+
+       /* set up timer */
+       HFC_outb(hc, R_TI_WD, poll_timer);
+       hc->hw.r_irqmsk_misc |= V_TI_IRQMSK;
+
+       /*
+        * set up 125us interrupt, only if function pointer is available
+        * and module parameter timer is set
+        */
+       if (timer && hfc_interrupt && register_interrupt) {
+               /* only one chip should use this interrupt */
+               timer = 0;
+               interrupt_registered = 1;
+               hc->hw.r_irqmsk_misc |= V_PROC_IRQMSK;
+               /* deactivate other interrupts in ztdummy */
+               register_interrupt();
+       }
+
+       /* set E1 state machine IRQ */
+       if (hc->type == 1)
+               hc->hw.r_irqmsk_misc |= V_STA_IRQMSK;
+
+       /* set DTMF detection */
+       if (test_bit(HFC_CHIP_DTMF, &hc->chip)) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: enabling DTMF detection "
+                           "for all B-channel\n", __func__);
+               hc->hw.r_dtmf = V_DTMF_EN | V_DTMF_STOP;
+               if (test_bit(HFC_CHIP_ULAW, &hc->chip))
+                       hc->hw.r_dtmf |= V_ULAW_SEL;
+               HFC_outb(hc, R_DTMF_N, 102 - 1);
+               hc->hw.r_irqmsk_misc |= V_DTMF_IRQMSK;
+       }
+
+       /* conference engine */
+       if (test_bit(HFC_CHIP_ULAW, &hc->chip))
+               r_conf_en = V_CONF_EN | V_ULAW;
+       else
+               r_conf_en = V_CONF_EN;
+       HFC_outb(hc, R_CONF_EN, r_conf_en);
+
+       /* setting leds */
+       switch (hc->leds) {
+       case 1: /* HFC-E1 OEM */
+               if (test_bit(HFC_CHIP_WATCHDOG, &hc->chip))
+                       HFC_outb(hc, R_GPIO_SEL, 0x32);
+               else
+                       HFC_outb(hc, R_GPIO_SEL, 0x30);
+
+               HFC_outb(hc, R_GPIO_EN1, 0x0f);
+               HFC_outb(hc, R_GPIO_OUT1, 0x00);
+
+               HFC_outb(hc, R_GPIO_EN0, V_GPIO_EN2 | V_GPIO_EN3);
+               break;
+
+       case 2: /* HFC-4S OEM */
+       case 3:
+               HFC_outb(hc, R_GPIO_SEL, 0xf0);
+               HFC_outb(hc, R_GPIO_EN1, 0xff);
+               HFC_outb(hc, R_GPIO_OUT1, 0x00);
+               break;
+       }
+
+       /* set master clock */
+       if (hc->masterclk >= 0) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: setting ST master clock "
+                           "to port %d (0..%d)\n",
+                           __func__, hc->masterclk, hc->ports-1);
+               hc->hw.r_st_sync = hc->masterclk | V_AUTO_SYNC;
+               HFC_outb(hc, R_ST_SYNC, hc->hw.r_st_sync);
+       }
+
+       /* setting misc irq */
+       HFC_outb(hc, R_IRQMSK_MISC, hc->hw.r_irqmsk_misc);
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "r_irqmsk_misc.2: 0x%x\n",
+                   hc->hw.r_irqmsk_misc);
+
+       /* RAM access test */
+       HFC_outb(hc, R_RAM_ADDR0, 0);
+       HFC_outb(hc, R_RAM_ADDR1, 0);
+       HFC_outb(hc, R_RAM_ADDR2, 0);
+       for (i = 0; i < 256; i++) {
+               HFC_outb_nodebug(hc, R_RAM_ADDR0, i);
+               HFC_outb_nodebug(hc, R_RAM_DATA, ((i*3)&0xff));
+       }
+       for (i = 0; i < 256; i++) {
+               HFC_outb_nodebug(hc, R_RAM_ADDR0, i);
+               HFC_inb_nodebug(hc, R_RAM_DATA);
+               rval = HFC_inb_nodebug(hc, R_INT_DATA);
+               if (rval != ((i * 3) & 0xff)) {
+                       printk(KERN_DEBUG
+                           "addr:%x val:%x should:%x\n", i, rval,
+                           (i * 3) & 0xff);
+                       err++;
+               }
+       }
+       if (err) {
+               printk(KERN_DEBUG "aborting - %d RAM access errors\n", err);
+               err = -EIO;
+               goto out;
+       }
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: done\n", __func__);
+out:
+       spin_unlock_irqrestore(&hc->lock, flags);
+       return err;
+}
+
+
+/*
+ * control the watchdog
+ */
+static void
+hfcmulti_watchdog(struct hfc_multi *hc)
+{
+       hc->wdcount++;
+
+       if (hc->wdcount > 10) {
+               hc->wdcount = 0;
+               hc->wdbyte = hc->wdbyte == V_GPIO_OUT2 ?
+                   V_GPIO_OUT3 : V_GPIO_OUT2;
+
+       /* printk("Sending Watchdog Kill %x\n",hc->wdbyte); */
+               HFC_outb(hc, R_GPIO_EN0, V_GPIO_EN2 | V_GPIO_EN3);
+               HFC_outb(hc, R_GPIO_OUT0, hc->wdbyte);
+       }
+}
+
+
+
+/*
+ * output leds
+ */
+static void
+hfcmulti_leds(struct hfc_multi *hc)
+{
+       unsigned long lled;
+       unsigned long leddw;
+       int i, state, active, leds;
+       struct dchannel *dch;
+       int led[4];
+
+       hc->ledcount += poll;
+       if (hc->ledcount > 4096) {
+               hc->ledcount -= 4096;
+               hc->ledstate = 0xAFFEAFFE;
+       }
+
+       switch (hc->leds) {
+       case 1: /* HFC-E1 OEM */
+               /* 2 red blinking: NT mode deactivate
+                * 2 red steady:   TE mode deactivate
+                * left green:     L1 active
+                * left red:       frame sync, but no L1
+                * right green:    L2 active
+                */
+               if (hc->chan[hc->dslot].sync != 2) { /* no frame sync */
+                       if (hc->chan[hc->dslot].dch->dev.D.protocol
+                               != ISDN_P_NT_E1) {
+                               led[0] = 1;
+                               led[1] = 1;
+                       } else if (hc->ledcount>>11) {
+                               led[0] = 1;
+                               led[1] = 1;
+                       } else {
+                               led[0] = 0;
+                               led[1] = 0;
+                       }
+                       led[2] = 0;
+                       led[3] = 0;
+               } else { /* with frame sync */
+                       /* TODO make it work */
+                       led[0] = 0;
+                       led[1] = 0;
+                       led[2] = 0;
+                       led[3] = 1;
+               }
+               leds = (led[0] | (led[1]<<2) | (led[2]<<1) | (led[3]<<3))^0xF;
+                       /* leds are inverted */
+               if (leds != (int)hc->ledstate) {
+                       HFC_outb_nodebug(hc, R_GPIO_OUT1, leds);
+                       hc->ledstate = leds;
+               }
+               break;
+
+       case 2: /* HFC-4S OEM */
+               /* red blinking = PH_DEACTIVATE NT Mode
+                * red steady   = PH_DEACTIVATE TE Mode
+                * green steady = PH_ACTIVATE
+                */
+               for (i = 0; i < 4; i++) {
+                       state = 0;
+                       active = -1;
+                       dch = hc->chan[(i << 2) | 2].dch;
+                       if (dch) {
+                               state = dch->state;
+                               if (dch->dev.D.protocol == ISDN_P_NT_S0)
+                                       active = 3;
+                               else
+                                       active = 7;
+                       }
+                       if (state) {
+                               if (state == active) {
+                                       led[i] = 1; /* led green */
+                               } else
+                                       if (dch->dev.D.protocol == ISDN_P_TE_S0)
+                                               /* TE mode: led red */
+                                               led[i] = 2;
+                                       else
+                                               if (hc->ledcount>>11)
+                                                       /* led red */
+                                                       led[i] = 2;
+                                               else
+                                                       /* led off */
+                                                       led[i] = 0;
+                       } else
+                               led[i] = 0; /* led off */
+               }
+               if (test_bit(HFC_CHIP_B410P, &hc->chip)) {
+                       leds = 0;
+                       for (i = 0; i < 4; i++) {
+                               if (led[i] == 1) {
+                                       /*green*/
+                                       leds |= (0x2 << (i * 2));
+                               } else if (led[i] == 2) {
+                                       /*red*/
+                                       leds |= (0x1 << (i * 2));
+                               }
+                       }
+                       if (leds != (int)hc->ledstate) {
+                               vpm_out(hc, 0, 0x1a8 + 3, leds);
+                               hc->ledstate = leds;
+                       }
+               } else {
+                       leds = ((led[3] > 0) << 0) | ((led[1] > 0) << 1) |
+                           ((led[0] > 0) << 2) | ((led[2] > 0) << 3) |
+                           ((led[3] & 1) << 4) | ((led[1] & 1) << 5) |
+                           ((led[0] & 1) << 6) | ((led[2] & 1) << 7);
+                       if (leds != (int)hc->ledstate) {
+                               HFC_outb_nodebug(hc, R_GPIO_EN1, leds & 0x0F);
+                               HFC_outb_nodebug(hc, R_GPIO_OUT1, leds >> 4);
+                               hc->ledstate = leds;
+                       }
+               }
+               break;
+
+       case 3: /* HFC 1S/2S Beronet */
+               /* red blinking = PH_DEACTIVATE NT Mode
+                * red steady   = PH_DEACTIVATE TE Mode
+                * green steady = PH_ACTIVATE
+                */
+               for (i = 0; i < 2; i++) {
+                       state = 0;
+                       active = -1;
+                       dch = hc->chan[(i << 2) | 2].dch;
+                       if (dch) {
+                               state = dch->state;
+                               if (dch->dev.D.protocol == ISDN_P_NT_S0)
+                                       active = 3;
+                               else
+                                       active = 7;
+                       }
+                       if (state) {
+                               if (state == active) {
+                                       led[i] = 1; /* led green */
+                               } else
+                                       if (dch->dev.D.protocol == ISDN_P_TE_S0)
+                                               /* TE mode: led red */
+                                               led[i] = 2;
+                                       else
+                                               if (hc->ledcount >> 11)
+                                                       /* led red */
+                                                       led[i] = 2;
+                                               else
+                                                       /* led off */
+                                                       led[i] = 0;
+                       } else
+                               led[i] = 0; /* led off */
+               }
+
+
+               leds = (led[0] > 0) | ((led[1] > 0)<<1) | ((led[0]&1)<<2)
+                       | ((led[1]&1)<<3);
+               if (leds != (int)hc->ledstate) {
+                       HFC_outb_nodebug(hc, R_GPIO_EN1,
+                           ((led[0] > 0) << 2) | ((led[1] > 0) << 3));
+                       HFC_outb_nodebug(hc, R_GPIO_OUT1,
+                           ((led[0] & 1) << 2) | ((led[1] & 1) << 3));
+                       hc->ledstate = leds;
+               }
+               break;
+       case 8: /* HFC 8S+ Beronet */
+               lled = 0;
+
+               for (i = 0; i < 8; i++) {
+                       state = 0;
+                       active = -1;
+                       dch = hc->chan[(i << 2) | 2].dch;
+                       if (dch) {
+                               state = dch->state;
+                               if (dch->dev.D.protocol == ISDN_P_NT_S0)
+                                       active = 3;
+                               else
+                                       active = 7;
+                       }
+                       if (state) {
+                               if (state == active) {
+                                       lled |= 0 << i;
+                               } else
+                                       if (hc->ledcount >> 11)
+                                               lled |= 0 << i;
+                                       else
+                                               lled |= 1 << i;
+                       } else
+                               lled |= 1 << i;
+               }
+               leddw = lled << 24 | lled << 16 | lled << 8 | lled;
+               if (leddw != hc->ledstate) {
+                       /* HFC_outb(hc, R_BRG_PCM_CFG, 1);
+                       HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x3); */
+                       /* was _io before */
+                       HFC_outb_nodebug(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK);
+                       outw(0x4000, hc->pci_iobase + 4);
+                       outl(leddw, hc->pci_iobase);
+                       HFC_outb_nodebug(hc, R_BRG_PCM_CFG, V_PCM_CLK);
+                       hc->ledstate = leddw;
+               }
+               break;
+       }
+}
+/*
+ * read dtmf coefficients
+ */
+
+static void
+hfcmulti_dtmf(struct hfc_multi *hc)
+{
+       s32             *coeff;
+       u_int           mantissa;
+       int             co, ch;
+       struct bchannel *bch = NULL;
+       u8              exponent;
+       int             dtmf = 0;
+       int             addr;
+       u16             w_float;
+       struct sk_buff  *skb;
+       struct mISDNhead *hh;
+
+       if (debug & DEBUG_HFCMULTI_DTMF)
+               printk(KERN_DEBUG "%s: dtmf detection irq\n", __func__);
+       for (ch = 0; ch <= 31; ch++) {
+               /* only process enabled B-channels */
+               bch = hc->chan[ch].bch;
+               if (!bch)
+                       continue;
+               if (!hc->created[hc->chan[ch].port])
+                       continue;
+               if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
+                       continue;
+               if (debug & DEBUG_HFCMULTI_DTMF)
+                       printk(KERN_DEBUG "%s: dtmf channel %d:",
+                               __func__, ch);
+               coeff = &(hc->chan[ch].coeff[hc->chan[ch].coeff_count * 16]);
+               dtmf = 1;
+               for (co = 0; co < 8; co++) {
+                       /* read W(n-1) coefficient */
+                       addr = hc->DTMFbase + ((co<<7) | (ch<<2));
+                       HFC_outb_nodebug(hc, R_RAM_ADDR0, addr);
+                       HFC_outb_nodebug(hc, R_RAM_ADDR1, addr>>8);
+                       HFC_outb_nodebug(hc, R_RAM_ADDR2, (addr>>16)
+                               | V_ADDR_INC);
+                       w_float = HFC_inb_nodebug(hc, R_RAM_DATA);
+                       w_float |= (HFC_inb_nodebug(hc, R_RAM_DATA) << 8);
+                       if (debug & DEBUG_HFCMULTI_DTMF)
+                               printk(" %04x", w_float);
+
+                       /* decode float (see chip doc) */
+                       mantissa = w_float & 0x0fff;
+                       if (w_float & 0x8000)
+                               mantissa |= 0xfffff000;
+                       exponent = (w_float>>12) & 0x7;
+                       if (exponent) {
+                               mantissa ^= 0x1000;
+                               mantissa <<= (exponent-1);
+                       }
+
+                       /* store coefficient */
+                       coeff[co<<1] = mantissa;
+
+                       /* read W(n) coefficient */
+                       w_float = HFC_inb_nodebug(hc, R_RAM_DATA);
+                       w_float |= (HFC_inb_nodebug(hc, R_RAM_DATA) << 8);
+                       if (debug & DEBUG_HFCMULTI_DTMF)
+                               printk(" %04x", w_float);
+
+                       /* decode float (see chip doc) */
+                       mantissa = w_float & 0x0fff;
+                       if (w_float & 0x8000)
+                               mantissa |= 0xfffff000;
+                       exponent = (w_float>>12) & 0x7;
+                       if (exponent) {
+                               mantissa ^= 0x1000;
+                               mantissa <<= (exponent-1);
+                       }
+
+                       /* store coefficient */
+                       coeff[(co<<1)|1] = mantissa;
+               }
+               if (debug & DEBUG_HFCMULTI_DTMF)
+                       printk("%s: DTMF ready %08x %08x %08x %08x "
+                           "%08x %08x %08x %08x\n", __func__,
+                           coeff[0], coeff[1], coeff[2], coeff[3],
+                           coeff[4], coeff[5], coeff[6], coeff[7]);
+               hc->chan[ch].coeff_count++;
+               if (hc->chan[ch].coeff_count == 8) {
+                       hc->chan[ch].coeff_count = 0;
+                       skb = mI_alloc_skb(512, GFP_ATOMIC);
+                       if (!skb) {
+                               printk(KERN_WARNING "%s: No memory for skb\n",
+                                   __func__);
+                               continue;
+                       }
+                       hh = mISDN_HEAD_P(skb);
+                       hh->prim = PH_CONTROL_IND;
+                       hh->id = DTMF_HFC_COEF;
+                       memcpy(skb_put(skb, 512), hc->chan[ch].coeff, 512);
+                       recv_Bchannel_skb(bch, skb);
+               }
+       }
+
+       /* restart DTMF processing */
+       hc->dtmf = dtmf;
+       if (dtmf)
+               HFC_outb_nodebug(hc, R_DTMF, hc->hw.r_dtmf | V_RST_DTMF);
+}
+
+
+/*
+ * fill fifo as much as possible
+ */
+
+static void
+hfcmulti_tx(struct hfc_multi *hc, int ch)
+{
+       int i, ii, temp, len = 0;
+       int Zspace, z1, z2; /* must be int for calculation */
+       int Fspace, f1, f2;
+       u_char *d;
+       int *txpending, slot_tx;
+       struct  bchannel *bch;
+       struct  dchannel *dch;
+       struct  sk_buff **sp = NULL;
+       int *idxp;
+
+       bch = hc->chan[ch].bch;
+       dch = hc->chan[ch].dch;
+       if ((!dch) && (!bch))
+               return;
+
+       txpending = &hc->chan[ch].txpending;
+       slot_tx = hc->chan[ch].slot_tx;
+       if (dch) {
+               if (!test_bit(FLG_ACTIVE, &dch->Flags))
+                       return;
+               sp = &dch->tx_skb;
+               idxp = &dch->tx_idx;
+       } else {
+               if (!test_bit(FLG_ACTIVE, &bch->Flags))
+                       return;
+               sp = &bch->tx_skb;
+               idxp = &bch->tx_idx;
+       }
+       if (*sp)
+               len = (*sp)->len;
+
+       if ((!len) && *txpending != 1)
+               return; /* no data */
+
+       if (test_bit(HFC_CHIP_B410P, &hc->chip) &&
+           (hc->chan[ch].protocol == ISDN_P_B_RAW) &&
+           (hc->chan[ch].slot_rx < 0) &&
+           (hc->chan[ch].slot_tx < 0))
+               HFC_outb_nodebug(hc, R_FIFO, 0x20 | (ch << 1));
+       else
+               HFC_outb_nodebug(hc, R_FIFO, ch << 1);
+       HFC_wait_nodebug(hc);
+
+       if (*txpending == 2) {
+               /* reset fifo */
+               HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_RES_F);
+               HFC_wait_nodebug(hc);
+               HFC_outb(hc, A_SUBCH_CFG, 0);
+               *txpending = 1;
+       }
+next_frame:
+       if (dch || test_bit(FLG_HDLC, &bch->Flags)) {
+               f1 = HFC_inb_nodebug(hc, A_F1);
+               f2 = HFC_inb_nodebug(hc, A_F2);
+               while (f2 != (temp = HFC_inb_nodebug(hc, A_F2))) {
+                       if (debug & DEBUG_HFCMULTI_FIFO)
+                               printk(KERN_DEBUG
+                                   "%s(card %d): reread f2 because %d!=%d\n",
+                                   __func__, hc->id + 1, temp, f2);
+                       f2 = temp; /* repeat until F2 is equal */
+               }
+               Fspace = f2 - f1 - 1;
+               if (Fspace < 0)
+                       Fspace += hc->Flen;
+               /*
+                * Old FIFO handling doesn't give us the current Z2 read
+                * pointer, so we cannot send the next frame before the fifo
+                * is empty. It makes no difference except for a slightly
+                * lower performance.
+                */
+               if (test_bit(HFC_CHIP_REVISION0, &hc->chip)) {
+                       if (f1 != f2)
+                               Fspace = 0;
+                       else
+                               Fspace = 1;
+               }
+               /* one frame only for ST D-channels, to allow resending */
+               if (hc->type != 1 && dch) {
+                       if (f1 != f2)
+                               Fspace = 0;
+               }
+               /* F-counter full condition */
+               if (Fspace == 0)
+                       return;
+       }
+       z1 = HFC_inw_nodebug(hc, A_Z1) - hc->Zmin;
+       z2 = HFC_inw_nodebug(hc, A_Z2) - hc->Zmin;
+       while (z2 != (temp = (HFC_inw_nodebug(hc, A_Z2) - hc->Zmin))) {
+               if (debug & DEBUG_HFCMULTI_FIFO)
+                       printk(KERN_DEBUG "%s(card %d): reread z2 because "
+                               "%d!=%d\n", __func__, hc->id + 1, temp, z2);
+               z2 = temp; /* repeat unti Z2 is equal */
+       }
+       Zspace = z2 - z1;
+       if (Zspace <= 0)
+               Zspace += hc->Zlen;
+       Zspace -= 4; /* keep not too full, so pointers will not overrun */
+       /* fill transparent data only to maxinum transparent load (minus 4) */
+       if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
+               Zspace = Zspace - hc->Zlen + hc->max_trans;
+       if (Zspace <= 0) /* no space of 4 bytes */
+               return;
+
+       /* if no data */
+       if (!len) {
+               if (z1 == z2) { /* empty */
+                       /* if done with FIFO audio data during PCM connection */
+                       if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) &&
+                           *txpending && slot_tx >= 0) {
+                               if (debug & DEBUG_HFCMULTI_MODE)
+                                       printk(KERN_DEBUG
+                                           "%s: reconnecting PCM due to no "
+                                           "more FIFO data: channel %d "
+                                           "slot_tx %d\n",
+                                           __func__, ch, slot_tx);
+                               /* connect slot */
+                               HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 |
+                                   V_HDLC_TRP | V_IFF);
+                               HFC_outb_nodebug(hc, R_FIFO, ch<<1 | 1);
+                               HFC_wait_nodebug(hc);
+                               HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 |
+                                   V_HDLC_TRP | V_IFF);
+                               HFC_outb_nodebug(hc, R_FIFO, ch<<1);
+                               HFC_wait_nodebug(hc);
+                       }
+                       *txpending = 0;
+               }
+               return; /* no data */
+       }
+
+       /* if audio data and connected slot */
+       if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending)
+               && slot_tx >= 0) {
+               if (debug & DEBUG_HFCMULTI_MODE)
+                       printk(KERN_DEBUG "%s: disconnecting PCM due to "
+                           "FIFO data: channel %d slot_tx %d\n",
+                           __func__, ch, slot_tx);
+               /* disconnect slot */
+               HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
+               HFC_outb_nodebug(hc, R_FIFO, ch<<1 | 1);
+               HFC_wait_nodebug(hc);
+               HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
+               HFC_outb_nodebug(hc, R_FIFO, ch<<1);
+               HFC_wait_nodebug(hc);
+       }
+       *txpending = 1;
+
+       /* show activity */
+       hc->activity[hc->chan[ch].port] = 1;
+
+       /* fill fifo to what we have left */
+       ii = len;
+       if (dch || test_bit(FLG_HDLC, &bch->Flags))
+               temp = 1;
+       else
+               temp = 0;
+       i = *idxp;
+       d = (*sp)->data + i;
+       if (ii - i > Zspace)
+               ii = Zspace + i;
+       if (debug & DEBUG_HFCMULTI_FIFO)
+               printk(KERN_DEBUG "%s(card %d): fifo(%d) has %d bytes space "
+                   "left (z1=%04x, z2=%04x) sending %d of %d bytes %s\n",
+                       __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i,
+                       temp ? "HDLC":"TRANS");
+
+
+       /* Have to prep the audio data */
+       hc->write_fifo(hc, d, ii - i);
+       *idxp = ii;
+
+       /* if not all data has been written */
+       if (ii != len) {
+               /* NOTE: fifo is started by the calling function */
+               return;
+       }
+
+       /* if all data has been written, terminate frame */
+       if (dch || test_bit(FLG_HDLC, &bch->Flags)) {
+               /* increment f-counter */
+               HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_INC_F);
+               HFC_wait_nodebug(hc);
+       }
+
+       /* send confirm, since get_net_bframe will not do it with trans */
+       if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
+               confirm_Bsend(bch);
+
+       /* check for next frame */
+       dev_kfree_skb(*sp);
+       if (bch && get_next_bframe(bch)) { /* hdlc is confirmed here */
+               len = (*sp)->len;
+               goto next_frame;
+       }
+       if (dch && get_next_dframe(dch)) {
+               len = (*sp)->len;
+               goto next_frame;
+       }
+
+       /*
+        * now we have no more data, so in case of transparent,
+        * we set the last byte in fifo to 'silence' in case we will get
+        * no more data at all. this prevents sending an undefined value.
+        */
+       if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
+               HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence);
+}
+
+
+/* NOTE: only called if E1 card is in active state */
+static void
+hfcmulti_rx(struct hfc_multi *hc, int ch)
+{
+       int temp;
+       int Zsize, z1, z2 = 0; /* = 0, to make GCC happy */
+       int f1 = 0, f2 = 0; /* = 0, to make GCC happy */
+       int again = 0;
+       struct  bchannel *bch;
+       struct  dchannel *dch;
+       struct sk_buff  *skb, **sp = NULL;
+       int     maxlen;
+
+       bch = hc->chan[ch].bch;
+       dch = hc->chan[ch].dch;
+       if ((!dch) && (!bch))
+               return;
+       if (dch) {
+               if (!test_bit(FLG_ACTIVE, &dch->Flags))
+                       return;
+               sp = &dch->rx_skb;
+               maxlen = dch->maxlen;
+       } else {
+               if (!test_bit(FLG_ACTIVE, &bch->Flags))
+                       return;
+               sp = &bch->rx_skb;
+               maxlen = bch->maxlen;
+       }
+next_frame:
+       /* on first AND before getting next valid frame, R_FIFO must be written
+          to. */
+       if (test_bit(HFC_CHIP_B410P, &hc->chip) &&
+           (hc->chan[ch].protocol == ISDN_P_B_RAW) &&
+           (hc->chan[ch].slot_rx < 0) &&
+           (hc->chan[ch].slot_tx < 0))
+               HFC_outb_nodebug(hc, R_FIFO, 0x20 | (ch<<1) | 1);
+       else
+               HFC_outb_nodebug(hc, R_FIFO, (ch<<1)|1);
+       HFC_wait_nodebug(hc);
+
+       /* ignore if rx is off BUT change fifo (above) to start pending TX */
+       if (hc->chan[ch].rx_off)
+               return;
+
+       if (dch || test_bit(FLG_HDLC, &bch->Flags)) {
+               f1 = HFC_inb_nodebug(hc, A_F1);
+               while (f1 != (temp = HFC_inb_nodebug(hc, A_F1))) {
+                       if (debug & DEBUG_HFCMULTI_FIFO)
+                               printk(KERN_DEBUG
+                                   "%s(card %d): reread f1 because %d!=%d\n",
+                                   __func__, hc->id + 1, temp, f1);
+                       f1 = temp; /* repeat until F1 is equal */
+               }
+               f2 = HFC_inb_nodebug(hc, A_F2);
+       }
+       z1 = HFC_inw_nodebug(hc, A_Z1) - hc->Zmin;
+       while (z1 != (temp = (HFC_inw_nodebug(hc, A_Z1) - hc->Zmin))) {
+               if (debug & DEBUG_HFCMULTI_FIFO)
+                       printk(KERN_DEBUG "%s(card %d): reread z2 because "
+                               "%d!=%d\n", __func__, hc->id + 1, temp, z2);
+               z1 = temp; /* repeat until Z1 is equal */
+       }
+       z2 = HFC_inw_nodebug(hc, A_Z2) - hc->Zmin;
+       Zsize = z1 - z2;
+       if ((dch || test_bit(FLG_HDLC, &bch->Flags)) && f1 != f2)
+               /* complete hdlc frame */
+               Zsize++;
+       if (Zsize < 0)
+               Zsize += hc->Zlen;
+       /* if buffer is empty */
+       if (Zsize <= 0)
+               return;
+
+       if (*sp == NULL) {
+               *sp = mI_alloc_skb(maxlen + 3, GFP_ATOMIC);
+               if (*sp == NULL) {
+                       printk(KERN_DEBUG "%s: No mem for rx_skb\n",
+                           __func__);
+                       return;
+               }
+       }
+       /* show activity */
+       hc->activity[hc->chan[ch].port] = 1;
+
+       /* empty fifo with what we have */
+       if (dch || test_bit(FLG_HDLC, &bch->Flags)) {
+               if (debug & DEBUG_HFCMULTI_FIFO)
+                       printk(KERN_DEBUG "%s(card %d): fifo(%d) reading %d "
+                           "bytes (z1=%04x, z2=%04x) HDLC %s (f1=%d, f2=%d) "
+                           "got=%d (again %d)\n", __func__, hc->id + 1, ch,
+                           Zsize, z1, z2, (f1 == f2) ? "fragment" : "COMPLETE",
+                           f1, f2, Zsize + (*sp)->len, again);
+               /* HDLC */
+               if ((Zsize + (*sp)->len) > (maxlen + 3)) {
+                       if (debug & DEBUG_HFCMULTI_FIFO)
+                               printk(KERN_DEBUG
+                                   "%s(card %d): hdlc-frame too large.\n",
+                                   __func__, hc->id + 1);
+                       skb_trim(*sp, 0);
+                       HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_RES_F);
+                       HFC_wait_nodebug(hc);
+                       return;
+               }
+
+               hc->read_fifo(hc, skb_put(*sp, Zsize), Zsize);
+
+               if (f1 != f2) {
+                       /* increment Z2,F2-counter */
+                       HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_INC_F);
+                       HFC_wait_nodebug(hc);
+                       /* check size */
+                       if ((*sp)->len < 4) {
+                               if (debug & DEBUG_HFCMULTI_FIFO)
+                                       printk(KERN_DEBUG
+                                           "%s(card %d): Frame below minimum "
+                                           "size\n", __func__, hc->id + 1);
+                               skb_trim(*sp, 0);
+                               goto next_frame;
+                       }
+                       /* there is at least one complete frame, check crc */
+                       if ((*sp)->data[(*sp)->len - 1]) {
+                               if (debug & DEBUG_HFCMULTI_CRC)
+                                       printk(KERN_DEBUG
+                                           "%s: CRC-error\n", __func__);
+                               skb_trim(*sp, 0);
+                               goto next_frame;
+                       }
+                       skb_trim(*sp, (*sp)->len - 3);
+                       if ((*sp)->len < MISDN_COPY_SIZE) {
+                               skb = *sp;
+                               *sp = mI_alloc_skb(skb->len, GFP_ATOMIC);
+                               if (*sp) {
+                                       memcpy(skb_put(*sp, skb->len),
+                                           skb->data, skb->len);
+                                       skb_trim(skb, 0);
+                               } else {
+                                       printk(KERN_DEBUG "%s: No mem\n",
+                                           __func__);
+                                       *sp = skb;
+                                       skb = NULL;
+                               }
+                       } else {
+                               skb = NULL;
+                       }
+                       if (debug & DEBUG_HFCMULTI_FIFO) {
+                               printk(KERN_DEBUG "%s(card %d):",
+                                       __func__, hc->id + 1);
+                               temp = 0;
+                               while (temp < (*sp)->len)
+                                       printk(" %02x", (*sp)->data[temp++]);
+                               printk("\n");
+                       }
+                       if (dch)
+                               recv_Dchannel(dch);
+                       else
+                               recv_Bchannel(bch);
+                       *sp = skb;
+                       again++;
+                       goto next_frame;
+               }
+               /* there is an incomplete frame */
+       } else {
+               /* transparent */
+               if (Zsize > skb_tailroom(*sp))
+                       Zsize = skb_tailroom(*sp);
+               hc->read_fifo(hc, skb_put(*sp, Zsize), Zsize);
+               if (((*sp)->len) < MISDN_COPY_SIZE) {
+                       skb = *sp;
+                       *sp = mI_alloc_skb(skb->len, GFP_ATOMIC);
+                       if (*sp) {
+                               memcpy(skb_put(*sp, skb->len),
+                                   skb->data, skb->len);
+                               skb_trim(skb, 0);
+                       } else {
+                               printk(KERN_DEBUG "%s: No mem\n", __func__);
+                               *sp = skb;
+                               skb = NULL;
+                       }
+               } else {
+                       skb = NULL;
+               }
+               if (debug & DEBUG_HFCMULTI_FIFO)
+                       printk(KERN_DEBUG
+                           "%s(card %d): fifo(%d) reading %d bytes "
+                           "(z1=%04x, z2=%04x) TRANS\n",
+                               __func__, hc->id + 1, ch, Zsize, z1, z2);
+               /* only bch is transparent */
+               recv_Bchannel(bch);
+               *sp = skb;
+       }
+}
+
+
+/*
+ * Interrupt handler
+ */
+static void
+signal_state_up(struct dchannel *dch, int info, char *msg)
+{
+       struct sk_buff  *skb;
+       int             id, data = info;
+
+       if (debug & DEBUG_HFCMULTI_STATE)
+               printk(KERN_DEBUG "%s: %s\n", __func__, msg);
+
+       id = TEI_SAPI | (GROUP_TEI << 8); /* manager address */
+
+       skb = _alloc_mISDN_skb(MPH_INFORMATION_IND, id, sizeof(data), &data,
+               GFP_ATOMIC);
+       if (!skb)
+               return;
+       recv_Dchannel_skb(dch, skb);
+}
+
+static inline void
+handle_timer_irq(struct hfc_multi *hc)
+{
+       int             ch, temp;
+       struct dchannel *dch;
+       u_long          flags;
+
+       /* process queued resync jobs */
+       if (hc->e1_resync) {
+               /* lock, so e1_resync gets not changed */
+               spin_lock_irqsave(&HFClock, flags);
+               if (hc->e1_resync & 1) {
+                       if (debug & DEBUG_HFCMULTI_PLXSD)
+                               printk(KERN_DEBUG "Enable SYNC_I\n");
+                       HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC);
+                       /* disable JATT, if RX_SYNC is set */
+                       if (test_bit(HFC_CHIP_RX_SYNC, &hc->chip))
+                               HFC_outb(hc, R_SYNC_OUT, V_SYNC_E1_RX);
+               }
+               if (hc->e1_resync & 2) {
+                       if (debug & DEBUG_HFCMULTI_PLXSD)
+                               printk(KERN_DEBUG "Enable jatt PLL\n");
+                       HFC_outb(hc, R_SYNC_CTRL, V_SYNC_OFFS);
+               }
+               if (hc->e1_resync & 4) {
+                       if (debug & DEBUG_HFCMULTI_PLXSD)
+                               printk(KERN_DEBUG
+                                   "Enable QUARTZ for HFC-E1\n");
+                       /* set jatt to quartz */
+                       HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC
+                               | V_JATT_OFF);
+                       /* switch to JATT, in case it is not already */
+                       HFC_outb(hc, R_SYNC_OUT, 0);
+               }
+               hc->e1_resync = 0;
+               spin_unlock_irqrestore(&HFClock, flags);
+       }
+
+       if (hc->type != 1 || hc->e1_state == 1)
+               for (ch = 0; ch <= 31; ch++) {
+                       if (hc->created[hc->chan[ch].port]) {
+                               hfcmulti_tx(hc, ch);
+                               /* fifo is started when switching to rx-fifo */
+                               hfcmulti_rx(hc, ch);
+                               if (hc->chan[ch].dch &&
+                                   hc->chan[ch].nt_timer > -1) {
+                                       dch = hc->chan[ch].dch;
+                                       if (!(--hc->chan[ch].nt_timer)) {
+                                               schedule_event(dch,
+                                                   FLG_PHCHANGE);
+                                               if (debug &
+                                                   DEBUG_HFCMULTI_STATE)
+                                                       printk(KERN_DEBUG
+                                                           "%s: nt_timer at "
+                                                           "state %x\n",
+                                                           __func__,
+                                                           dch->state);
+                                       }
+                               }
+                       }
+               }
+       if (hc->type == 1 && hc->created[0]) {
+               dch = hc->chan[hc->dslot].dch;
+               if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) {
+                       /* LOS */
+                       temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_SIG_LOS;
+                       if (!temp && hc->chan[hc->dslot].los)
+                               signal_state_up(dch, L1_SIGNAL_LOS_ON,
+                                   "LOS detected");
+                       if (temp && !hc->chan[hc->dslot].los)
+                               signal_state_up(dch, L1_SIGNAL_LOS_OFF,
+                                   "LOS gone");
+                       hc->chan[hc->dslot].los = temp;
+               }
+               if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[hc->dslot].cfg)) {
+                       /* AIS */
+                       temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_AIS;
+                       if (!temp && hc->chan[hc->dslot].ais)
+                               signal_state_up(dch, L1_SIGNAL_AIS_ON,
+                                   "AIS detected");
+                       if (temp && !hc->chan[hc->dslot].ais)
+                               signal_state_up(dch, L1_SIGNAL_AIS_OFF,
+                                   "AIS gone");
+                       hc->chan[hc->dslot].ais = temp;
+               }
+               if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[hc->dslot].cfg)) {
+                       /* SLIP */
+                       temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_RX;
+                       if (!temp && hc->chan[hc->dslot].slip_rx)
+                               signal_state_up(dch, L1_SIGNAL_SLIP_RX,
+                                   " bit SLIP detected RX");
+                       hc->chan[hc->dslot].slip_rx = temp;
+                       temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_TX;
+                       if (!temp && hc->chan[hc->dslot].slip_tx)
+                               signal_state_up(dch, L1_SIGNAL_SLIP_TX,
+                                   " bit SLIP detected TX");
+                       hc->chan[hc->dslot].slip_tx = temp;
+               }
+               if (test_bit(HFC_CFG_REPORT_RDI, &hc->chan[hc->dslot].cfg)) {
+                       /* RDI */
+                       temp = HFC_inb_nodebug(hc, R_RX_SL0_0) & V_A;
+                       if (!temp && hc->chan[hc->dslot].rdi)
+                               signal_state_up(dch, L1_SIGNAL_RDI_ON,
+                                   "RDI detected");
+                       if (temp && !hc->chan[hc->dslot].rdi)
+                               signal_state_up(dch, L1_SIGNAL_RDI_OFF,
+                                   "RDI gone");
+                       hc->chan[hc->dslot].rdi = temp;
+               }
+               temp = HFC_inb_nodebug(hc, R_JATT_DIR);
+               switch (hc->chan[hc->dslot].sync) {
+               case 0:
+                       if ((temp & 0x60) == 0x60) {
+                               if (debug & DEBUG_HFCMULTI_SYNC)
+                                       printk(KERN_DEBUG
+                                           "%s: (id=%d) E1 now "
+                                           "in clock sync\n",
+                                           __func__, hc->id);
+                               HFC_outb(hc, R_RX_OFF,
+                                   hc->chan[hc->dslot].jitter | V_RX_INIT);
+                               HFC_outb(hc, R_TX_OFF,
+                                   hc->chan[hc->dslot].jitter | V_RX_INIT);
+                               hc->chan[hc->dslot].sync = 1;
+                               goto check_framesync;
+                       }
+                       break;
+               case 1:
+                       if ((temp & 0x60) != 0x60) {
+                               if (debug & DEBUG_HFCMULTI_SYNC)
+                                       printk(KERN_DEBUG
+                                           "%s: (id=%d) E1 "
+                                           "lost clock sync\n",
+                                           __func__, hc->id);
+                               hc->chan[hc->dslot].sync = 0;
+                               break;
+                       }
+check_framesync:
+                       temp = HFC_inb_nodebug(hc, R_SYNC_STA);
+                       if (temp == 0x27) {
+                               if (debug & DEBUG_HFCMULTI_SYNC)
+                                       printk(KERN_DEBUG
+                                           "%s: (id=%d) E1 "
+                                           "now in frame sync\n",
+                                           __func__, hc->id);
+                               hc->chan[hc->dslot].sync = 2;
+                       }
+                       break;
+               case 2:
+                       if ((temp & 0x60) != 0x60) {
+                               if (debug & DEBUG_HFCMULTI_SYNC)
+                                       printk(KERN_DEBUG
+                                           "%s: (id=%d) E1 lost "
+                                           "clock & frame sync\n",
+                                           __func__, hc->id);
+                               hc->chan[hc->dslot].sync = 0;
+                               break;
+                       }
+                       temp = HFC_inb_nodebug(hc, R_SYNC_STA);
+                       if (temp != 0x27) {
+                               if (debug & DEBUG_HFCMULTI_SYNC)
+                                       printk(KERN_DEBUG
+                                           "%s: (id=%d) E1 "
+                                           "lost frame sync\n",
+                                           __func__, hc->id);
+                               hc->chan[hc->dslot].sync = 1;
+                       }
+                       break;
+               }
+       }
+
+       if (test_bit(HFC_CHIP_WATCHDOG, &hc->chip))
+               hfcmulti_watchdog(hc);
+
+       if (hc->leds)
+               hfcmulti_leds(hc);
+}
+
+static void
+ph_state_irq(struct hfc_multi *hc, u_char r_irq_statech)
+{
+       struct dchannel *dch;
+       int             ch;
+       int             active;
+       u_char          st_status, temp;
+
+       /* state machine */
+       for (ch = 0; ch <= 31; ch++) {
+               if (hc->chan[ch].dch) {
+                       dch = hc->chan[ch].dch;
+                       if (r_irq_statech & 1) {
+                               HFC_outb_nodebug(hc, R_ST_SEL,
+                                       hc->chan[ch].port);
+                               /* undocumented: delay after R_ST_SEL */
+                               udelay(1);
+                               /* undocumented: status changes during read */
+                               st_status = HFC_inb_nodebug(hc, A_ST_RD_STATE);
+                               while (st_status != (temp =
+                                       HFC_inb_nodebug(hc, A_ST_RD_STATE))) {
+                                       if (debug & DEBUG_HFCMULTI_STATE)
+                                               printk(KERN_DEBUG "%s: reread "
+                                                   "STATE because %d!=%d\n",
+                                                   __func__, temp,
+                                                   st_status);
+                                       st_status = temp; /* repeat */
+                               }
+
+                               /* Speech Design TE-sync indication */
+                               if (test_bit(HFC_CHIP_PLXSD, &hc->chip) &&
+                                       dch->dev.D.protocol == ISDN_P_TE_S0) {
+                                       if (st_status & V_FR_SYNC_ST)
+                                               hc->syncronized |=
+                                                   (1 << hc->chan[ch].port);
+                                       else
+                                               hc->syncronized &=
+                                                  ~(1 << hc->chan[ch].port);
+                               }
+                               dch->state = st_status & 0x0f;
+                               if (dch->dev.D.protocol == ISDN_P_NT_S0)
+                                       active = 3;
+                               else
+                                       active = 7;
+                               if (dch->state == active) {
+                                       HFC_outb_nodebug(hc, R_FIFO,
+                                               (ch << 1) | 1);
+                                       HFC_wait_nodebug(hc);
+                                       HFC_outb_nodebug(hc,
+                                               R_INC_RES_FIFO, V_RES_F);
+                                       HFC_wait_nodebug(hc);
+                                       dch->tx_idx = 0;
+                               }
+                               schedule_event(dch, FLG_PHCHANGE);
+                               if (debug & DEBUG_HFCMULTI_STATE)
+                                       printk(KERN_DEBUG
+                                           "%s: S/T newstate %x port %d\n",
+                                           __func__, dch->state,
+                                           hc->chan[ch].port);
+                       }
+                       r_irq_statech >>= 1;
+               }
+       }
+       if (test_bit(HFC_CHIP_PLXSD, &hc->chip))
+               plxsd_checksync(hc, 0);
+}
+
+static void
+fifo_irq(struct hfc_multi *hc, int block)
+{
+       int     ch, j;
+       struct dchannel *dch;
+       struct bchannel *bch;
+       u_char r_irq_fifo_bl;
+
+       r_irq_fifo_bl = HFC_inb_nodebug(hc, R_IRQ_FIFO_BL0 + block);
+       j = 0;
+       while (j < 8) {
+               ch = (block << 2) + (j >> 1);
+               dch = hc->chan[ch].dch;
+               bch = hc->chan[ch].bch;
+               if (((!dch) && (!bch)) || (!hc->created[hc->chan[ch].port])) {
+                       j += 2;
+                       continue;
+               }
+               if (dch && (r_irq_fifo_bl & (1 << j)) &&
+                   test_bit(FLG_ACTIVE, &dch->Flags)) {
+                       hfcmulti_tx(hc, ch);
+                       /* start fifo */
+                       HFC_outb_nodebug(hc, R_FIFO, 0);
+                       HFC_wait_nodebug(hc);
+               }
+               if (bch && (r_irq_fifo_bl & (1 << j)) &&
+                   test_bit(FLG_ACTIVE, &bch->Flags)) {
+                       hfcmulti_tx(hc, ch);
+                       /* start fifo */
+                       HFC_outb_nodebug(hc, R_FIFO, 0);
+                       HFC_wait_nodebug(hc);
+               }
+               j++;
+               if (dch && (r_irq_fifo_bl & (1 << j)) &&
+                   test_bit(FLG_ACTIVE, &dch->Flags)) {
+                       hfcmulti_rx(hc, ch);
+               }
+               if (bch && (r_irq_fifo_bl & (1 << j)) &&
+                   test_bit(FLG_ACTIVE, &bch->Flags)) {
+                       hfcmulti_rx(hc, ch);
+               }
+               j++;
+       }
+}
+
+#ifdef IRQ_DEBUG
+int irqsem;
+#endif
+static irqreturn_t
+hfcmulti_interrupt(int intno, void *dev_id)
+{
+#ifdef IRQCOUNT_DEBUG
+       static int iq1 = 0, iq2 = 0, iq3 = 0, iq4 = 0,
+           iq5 = 0, iq6 = 0, iqcnt = 0;
+#endif
+       static int              count;
+       struct hfc_multi        *hc = dev_id;
+       struct dchannel         *dch;
+       u_char                  r_irq_statech, status, r_irq_misc, r_irq_oview;
+       int                     i;
+       u_short                 *plx_acc, wval;
+       u_char                  e1_syncsta, temp;
+       u_long                  flags;
+
+       if (!hc) {
+               printk(KERN_ERR "HFC-multi: Spurious interrupt!\n");
+               return IRQ_NONE;
+       }
+
+       spin_lock(&hc->lock);
+
+#ifdef IRQ_DEBUG
+       if (irqsem)
+               printk(KERN_ERR "irq for card %d during irq from "
+               "card %d, this is no bug.\n", hc->id + 1, irqsem);
+       irqsem = hc->id + 1;
+#endif
+
+       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+               spin_lock_irqsave(&plx_lock, flags);
+               plx_acc = (u_short *)(hc->plx_membase + PLX_INTCSR);
+               wval = readw(plx_acc);
+               spin_unlock_irqrestore(&plx_lock, flags);
+               if (!(wval & PLX_INTCSR_LINTI1_STATUS))
+                       goto irq_notforus;
+       }
+
+       status = HFC_inb_nodebug(hc, R_STATUS);
+       r_irq_statech = HFC_inb_nodebug(hc, R_IRQ_STATECH);
+#ifdef IRQCOUNT_DEBUG
+       if (r_irq_statech)
+               iq1++;
+       if (status & V_DTMF_STA)
+               iq2++;
+       if (status & V_LOST_STA)
+               iq3++;
+       if (status & V_EXT_IRQSTA)
+               iq4++;
+       if (status & V_MISC_IRQSTA)
+               iq5++;
+       if (status & V_FR_IRQSTA)
+               iq6++;
+       if (iqcnt++ > 5000) {
+               printk(KERN_ERR "iq1:%x iq2:%x iq3:%x iq4:%x iq5:%x iq6:%x\n",
+                   iq1, iq2, iq3, iq4, iq5, iq6);
+               iqcnt = 0;
+       }
+#endif
+       if (!r_irq_statech &&
+           !(status & (V_DTMF_STA | V_LOST_STA | V_EXT_IRQSTA |
+           V_MISC_IRQSTA | V_FR_IRQSTA))) {
+               /* irq is not for us */
+               goto irq_notforus;
+       }
+       hc->irqcnt++;
+       if (r_irq_statech) {
+               if (hc->type != 1)
+                       ph_state_irq(hc, r_irq_statech);
+       }
+       if (status & V_EXT_IRQSTA)
+               ; /* external IRQ */
+       if (status & V_LOST_STA) {
+               /* LOST IRQ */
+               HFC_outb(hc, R_INC_RES_FIFO, V_RES_LOST); /* clear irq! */
+       }
+       if (status & V_MISC_IRQSTA) {
+               /* misc IRQ */
+               r_irq_misc = HFC_inb_nodebug(hc, R_IRQ_MISC);
+               if (r_irq_misc & V_STA_IRQ) {
+                       if (hc->type == 1) {
+                               /* state machine */
+                               dch = hc->chan[hc->dslot].dch;
+                               e1_syncsta = HFC_inb_nodebug(hc, R_SYNC_STA);
+                               if (test_bit(HFC_CHIP_PLXSD, &hc->chip)
+                                && hc->e1_getclock) {
+                                       if (e1_syncsta & V_FR_SYNC_E1)
+                                               hc->syncronized = 1;
+                                       else
+                                               hc->syncronized = 0;
+                               }
+                               /* undocumented: status changes during read */
+                               dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA);
+                               while (dch->state != (temp =
+                                       HFC_inb_nodebug(hc, R_E1_RD_STA))) {
+                                       if (debug & DEBUG_HFCMULTI_STATE)
+                                               printk(KERN_DEBUG "%s: reread "
+                                                   "STATE because %d!=%d\n",
+                                                   __func__, temp,
+                                                   dch->state);
+                                       dch->state = temp; /* repeat */
+                               }
+                               dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA)
+                                       & 0x7;
+                               schedule_event(dch, FLG_PHCHANGE);
+                               if (debug & DEBUG_HFCMULTI_STATE)
+                                       printk(KERN_DEBUG
+                                           "%s: E1 (id=%d) newstate %x\n",
+                                           __func__, hc->id, dch->state);
+                               if (test_bit(HFC_CHIP_PLXSD, &hc->chip))
+                                       plxsd_checksync(hc, 0);
+                       }
+               }
+               if (r_irq_misc & V_TI_IRQ)
+                       handle_timer_irq(hc);
+
+               if (r_irq_misc & V_DTMF_IRQ) {
+                       /* -> DTMF IRQ */
+                       hfcmulti_dtmf(hc);
+               }
+               /* TODO: REPLACE !!!! 125 us Interrupts are not acceptable  */
+               if (r_irq_misc & V_IRQ_PROC) {
+                       /* IRQ every 125us */
+                       count++;
+                       /* generate 1kHz signal */
+                       if (count == 8) {
+                               if (hfc_interrupt)
+                                       hfc_interrupt();
+                               count = 0;
+                       }
+               }
+
+       }
+       if (status & V_FR_IRQSTA) {
+               /* FIFO IRQ */
+               r_irq_oview = HFC_inb_nodebug(hc, R_IRQ_OVIEW);
+               for (i = 0; i < 8; i++) {
+                       if (r_irq_oview & (1 << i))
+                               fifo_irq(hc, i);
+               }
+       }
+
+#ifdef IRQ_DEBUG
+       irqsem = 0;
+#endif
+       spin_unlock(&hc->lock);
+       return IRQ_HANDLED;
+
+irq_notforus:
+#ifdef IRQ_DEBUG
+       irqsem = 0;
+#endif
+       spin_unlock(&hc->lock);
+       return IRQ_NONE;
+}
+
+
+/*
+ * timer callback for D-chan busy resolution. Currently no function
+ */
+
+static void
+hfcmulti_dbusy_timer(struct hfc_multi *hc)
+{
+}
+
+
+/*
+ * activate/deactivate hardware for selected channels and mode
+ *
+ * configure B-channel with the given protocol
+ * ch eqals to the HFC-channel (0-31)
+ * ch is the number of channel (0-4,4-7,8-11,12-15,16-19,20-23,24-27,28-31
+ * for S/T, 1-31 for E1)
+ * the hdlc interrupts will be set/unset
+ */
+static int
+mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
+    int bank_tx, int slot_rx, int bank_rx)
+{
+       int flow_tx = 0, flow_rx = 0, routing = 0;
+       int oslot_tx, oslot_rx;
+       int conf;
+
+       if (ch < 0 || ch > 31)
+               return EINVAL;
+       oslot_tx = hc->chan[ch].slot_tx;
+       oslot_rx = hc->chan[ch].slot_rx;
+       conf = hc->chan[ch].conf;
+
+       if (debug & DEBUG_HFCMULTI_MODE)
+               printk(KERN_DEBUG
+                   "%s: card %d channel %d protocol %x slot old=%d new=%d "
+                   "bank new=%d (TX) slot old=%d new=%d bank new=%d (RX)\n",
+                   __func__, hc->id, ch, protocol, oslot_tx, slot_tx,
+                   bank_tx, oslot_rx, slot_rx, bank_rx);
+
+       if (oslot_tx >= 0 && slot_tx != oslot_tx) {
+               /* remove from slot */
+               if (debug & DEBUG_HFCMULTI_MODE)
+                       printk(KERN_DEBUG "%s: remove from slot %d (TX)\n",
+                           __func__, oslot_tx);
+               if (hc->slot_owner[oslot_tx<<1] == ch) {
+                       HFC_outb(hc, R_SLOT, oslot_tx << 1);
+                       HFC_outb(hc, A_SL_CFG, 0);
+                       HFC_outb(hc, A_CONF, 0);
+                       hc->slot_owner[oslot_tx<<1] = -1;
+               } else {
+                       if (debug & DEBUG_HFCMULTI_MODE)
+                               printk(KERN_DEBUG
+                                   "%s: we are not owner of this tx slot "
+                                   "anymore, channel %d is.\n",
+                                   __func__, hc->slot_owner[oslot_tx<<1]);
+               }
+       }
+
+       if (oslot_rx >= 0 && slot_rx != oslot_rx) {
+               /* remove from slot */
+               if (debug & DEBUG_HFCMULTI_MODE)
+                       printk(KERN_DEBUG
+                           "%s: remove from slot %d (RX)\n",
+                           __func__, oslot_rx);
+               if (hc->slot_owner[(oslot_rx << 1) | 1] == ch) {
+                       HFC_outb(hc, R_SLOT, (oslot_rx << 1) | V_SL_DIR);
+                       HFC_outb(hc, A_SL_CFG, 0);
+                       hc->slot_owner[(oslot_rx << 1) | 1] = -1;
+               } else {
+                       if (debug & DEBUG_HFCMULTI_MODE)
+                               printk(KERN_DEBUG
+                                   "%s: we are not owner of this rx slot "
+                                   "anymore, channel %d is.\n",
+                                   __func__,
+                                   hc->slot_owner[(oslot_rx << 1) | 1]);
+               }
+       }
+
+       if (slot_tx < 0) {
+               flow_tx = 0x80; /* FIFO->ST */
+               /* disable pcm slot */
+               hc->chan[ch].slot_tx = -1;
+               hc->chan[ch].bank_tx = 0;
+       } else {
+               /* set pcm slot */
+               if (hc->chan[ch].txpending)
+                       flow_tx = 0x80; /* FIFO->ST */
+               else
+                       flow_tx = 0xc0; /* PCM->ST */
+               /* put on slot */
+               routing = bank_tx ? 0xc0 : 0x80;
+               if (conf >= 0 || bank_tx > 1)
+                       routing = 0x40; /* loop */
+               if (debug & DEBUG_HFCMULTI_MODE)
+                       printk(KERN_DEBUG "%s: put channel %d to slot %d bank"
+                           " %d flow %02x routing %02x conf %d (TX)\n",
+                           __func__, ch, slot_tx, bank_tx,
+                           flow_tx, routing, conf);
+               HFC_outb(hc, R_SLOT, slot_tx << 1);
+               HFC_outb(hc, A_SL_CFG, (ch<<1) | routing);
+               HFC_outb(hc, A_CONF, (conf < 0) ? 0 : (conf | V_CONF_SL));
+               hc->slot_owner[slot_tx << 1] = ch;
+               hc->chan[ch].slot_tx = slot_tx;
+               hc->chan[ch].bank_tx = bank_tx;
+       }
+       if (slot_rx < 0) {
+               /* disable pcm slot */
+               flow_rx = 0x80; /* ST->FIFO */
+               hc->chan[ch].slot_rx = -1;
+               hc->chan[ch].bank_rx = 0;
+       } else {
+               /* set pcm slot */
+               if (hc->chan[ch].txpending)
+                       flow_rx = 0x80; /* ST->FIFO */
+               else
+                       flow_rx = 0xc0; /* ST->(FIFO,PCM) */
+               /* put on slot */
+               routing = bank_rx?0x80:0xc0; /* reversed */
+               if (conf >= 0 || bank_rx > 1)
+                       routing = 0x40; /* loop */
+               if (debug & DEBUG_HFCMULTI_MODE)
+                       printk(KERN_DEBUG "%s: put channel %d to slot %d bank"
+                           " %d flow %02x routing %02x conf %d (RX)\n",
+                           __func__, ch, slot_rx, bank_rx,
+                           flow_rx, routing, conf);
+               HFC_outb(hc, R_SLOT, (slot_rx<<1) | V_SL_DIR);
+               HFC_outb(hc, A_SL_CFG, (ch<<1) | V_CH_DIR | routing);
+               hc->slot_owner[(slot_rx<<1)|1] = ch;
+               hc->chan[ch].slot_rx = slot_rx;
+               hc->chan[ch].bank_rx = bank_rx;
+       }
+
+       switch (protocol) {
+       case (ISDN_P_NONE):
+               /* disable TX fifo */
+               HFC_outb(hc, R_FIFO, ch << 1);
+               HFC_wait(hc);
+               HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | V_IFF);
+               HFC_outb(hc, A_SUBCH_CFG, 0);
+               HFC_outb(hc, A_IRQ_MSK, 0);
+               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+               HFC_wait(hc);
+               /* disable RX fifo */
+               HFC_outb(hc, R_FIFO, (ch<<1)|1);
+               HFC_wait(hc);
+               HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00);
+               HFC_outb(hc, A_SUBCH_CFG, 0);
+               HFC_outb(hc, A_IRQ_MSK, 0);
+               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+               HFC_wait(hc);
+               if (hc->chan[ch].bch && hc->type != 1) {
+                       hc->hw.a_st_ctrl0[hc->chan[ch].port] &=
+                           ((ch & 0x3) == 0)? ~V_B1_EN: ~V_B2_EN;
+                       HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
+                       /* undocumented: delay after R_ST_SEL */
+                       udelay(1);
+                       HFC_outb(hc, A_ST_CTRL0,
+                           hc->hw.a_st_ctrl0[hc->chan[ch].port]);
+               }
+               if (hc->chan[ch].bch) {
+                       test_and_clear_bit(FLG_HDLC, &hc->chan[ch].bch->Flags);
+                       test_and_clear_bit(FLG_TRANSPARENT,
+                           &hc->chan[ch].bch->Flags);
+               }
+               break;
+       case (ISDN_P_B_RAW): /* B-channel */
+
+               if (test_bit(HFC_CHIP_B410P, &hc->chip) &&
+                   (hc->chan[ch].slot_rx < 0) &&
+                   (hc->chan[ch].slot_tx < 0)) {
+
+                       printk(KERN_DEBUG
+                           "Setting B-channel %d to echo cancelable "
+                           "state on PCM slot %d\n", ch,
+                           ((ch / 4) * 8) + ((ch % 4) * 4) + 1);
+                       printk(KERN_DEBUG
+                           "Enabling pass through for channel\n");
+                       vpm_out(hc, ch, ((ch / 4) * 8) +
+                           ((ch % 4) * 4) + 1, 0x01);
+                       /* rx path */
+                       /* S/T -> PCM */
+                       HFC_outb(hc, R_FIFO, (ch << 1));
+                       HFC_wait(hc);
+                       HFC_outb(hc, A_CON_HDLC, 0xc0 | V_HDLC_TRP | V_IFF);
+                       HFC_outb(hc, R_SLOT, (((ch / 4) * 8) +
+                           ((ch % 4) * 4) + 1) << 1);
+                       HFC_outb(hc, A_SL_CFG, 0x80 | (ch << 1));
+
+                       /* PCM -> FIFO */
+                       HFC_outb(hc, R_FIFO, 0x20 | (ch << 1) | 1);
+                       HFC_wait(hc);
+                       HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF);
+                       HFC_outb(hc, A_SUBCH_CFG, 0);
+                       HFC_outb(hc, A_IRQ_MSK, 0);
+                       HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+                       HFC_wait(hc);
+                       HFC_outb(hc, R_SLOT, ((((ch / 4) * 8) +
+                           ((ch % 4) * 4) + 1) << 1) | 1);
+                       HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1) | 1);
+
+                       /* tx path */
+                       /* PCM -> S/T */
+                       HFC_outb(hc, R_FIFO, (ch << 1) | 1);
+                       HFC_wait(hc);
+                       HFC_outb(hc, A_CON_HDLC, 0xc0 | V_HDLC_TRP | V_IFF);
+                       HFC_outb(hc, R_SLOT, ((((ch / 4) * 8) +
+                           ((ch % 4) * 4)) << 1) | 1);
+                       HFC_outb(hc, A_SL_CFG, 0x80 | 0x40 | (ch << 1) | 1);
+
+                       /* FIFO -> PCM */
+                       HFC_outb(hc, R_FIFO, 0x20 | (ch << 1));
+                       HFC_wait(hc);
+                       HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF);
+                       HFC_outb(hc, A_SUBCH_CFG, 0);
+                       HFC_outb(hc, A_IRQ_MSK, 0);
+                       HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+                       HFC_wait(hc);
+                       /* tx silence */
+                       HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence);
+                       HFC_outb(hc, R_SLOT, (((ch / 4) * 8) +
+                           ((ch % 4) * 4)) << 1);
+                       HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1));
+               } else {
+                       /* enable TX fifo */
+                       HFC_outb(hc, R_FIFO, ch << 1);
+                       HFC_wait(hc);
+                       HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 |
+                           V_HDLC_TRP | V_IFF);
+                       HFC_outb(hc, A_SUBCH_CFG, 0);
+                       HFC_outb(hc, A_IRQ_MSK, 0);
+                       HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+                       HFC_wait(hc);
+                       /* tx silence */
+                       HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence);
+                       /* enable RX fifo */
+                       HFC_outb(hc, R_FIFO, (ch<<1)|1);
+                       HFC_wait(hc);
+                       HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 | V_HDLC_TRP);
+                       HFC_outb(hc, A_SUBCH_CFG, 0);
+                       HFC_outb(hc, A_IRQ_MSK, 0);
+                       HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+                       HFC_wait(hc);
+               }
+               if (hc->type != 1) {
+                       hc->hw.a_st_ctrl0[hc->chan[ch].port] |=
+                           ((ch & 0x3) == 0) ? V_B1_EN : V_B2_EN;
+                       HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
+                       /* undocumented: delay after R_ST_SEL */
+                       udelay(1);
+                       HFC_outb(hc, A_ST_CTRL0,
+                           hc->hw.a_st_ctrl0[hc->chan[ch].port]);
+               }
+               if (hc->chan[ch].bch)
+                       test_and_set_bit(FLG_TRANSPARENT,
+                           &hc->chan[ch].bch->Flags);
+               break;
+       case (ISDN_P_B_HDLC): /* B-channel */
+       case (ISDN_P_TE_S0): /* D-channel */
+       case (ISDN_P_NT_S0):
+       case (ISDN_P_TE_E1):
+       case (ISDN_P_NT_E1):
+               /* enable TX fifo */
+               HFC_outb(hc, R_FIFO, ch<<1);
+               HFC_wait(hc);
+               if (hc->type == 1 || hc->chan[ch].bch) {
+                       /* E1 or B-channel */
+                       HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04);
+                       HFC_outb(hc, A_SUBCH_CFG, 0);
+               } else {
+                       /* D-Channel without HDLC fill flags */
+                       HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04 | V_IFF);
+                       HFC_outb(hc, A_SUBCH_CFG, 2);
+               }
+               HFC_outb(hc, A_IRQ_MSK, V_IRQ);
+               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+               HFC_wait(hc);
+               /* enable RX fifo */
+               HFC_outb(hc, R_FIFO, (ch<<1)|1);
+               HFC_wait(hc);
+               HFC_outb(hc, A_CON_HDLC, flow_rx | 0x04);
+               if (hc->type == 1 || hc->chan[ch].bch)
+                       HFC_outb(hc, A_SUBCH_CFG, 0); /* full 8 bits */
+               else
+                       HFC_outb(hc, A_SUBCH_CFG, 2); /* 2 bits dchannel */
+               HFC_outb(hc, A_IRQ_MSK, V_IRQ);
+               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+               HFC_wait(hc);
+               if (hc->chan[ch].bch) {
+                       test_and_set_bit(FLG_HDLC, &hc->chan[ch].bch->Flags);
+                       if (hc->type != 1) {
+                               hc->hw.a_st_ctrl0[hc->chan[ch].port] |=
+                                 ((ch&0x3) == 0) ? V_B1_EN : V_B2_EN;
+                               HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
+                               /* undocumented: delay after R_ST_SEL */
+                               udelay(1);
+                               HFC_outb(hc, A_ST_CTRL0,
+                                 hc->hw.a_st_ctrl0[hc->chan[ch].port]);
+                       }
+               }
+               break;
+       default:
+               printk(KERN_DEBUG "%s: protocol not known %x\n",
+                   __func__, protocol);
+               hc->chan[ch].protocol = ISDN_P_NONE;
+               return -ENOPROTOOPT;
+       }
+       hc->chan[ch].protocol = protocol;
+       return 0;
+}
+
+
+/*
+ * connect/disconnect PCM
+ */
+
+static void
+hfcmulti_pcm(struct hfc_multi *hc, int ch, int slot_tx, int bank_tx,
+    int slot_rx, int bank_rx)
+{
+       if (slot_rx < 0 || slot_rx < 0 || bank_tx < 0 || bank_rx < 0) {
+               /* disable PCM */
+               mode_hfcmulti(hc, ch, hc->chan[ch].protocol, -1, 0, -1, 0);
+               return;
+       }
+
+       /* enable pcm */
+       mode_hfcmulti(hc, ch, hc->chan[ch].protocol, slot_tx, bank_tx,
+               slot_rx, bank_rx);
+}
+
+/*
+ * set/disable conference
+ */
+
+static void
+hfcmulti_conf(struct hfc_multi *hc, int ch, int num)
+{
+       if (num >= 0 && num <= 7)
+               hc->chan[ch].conf = num;
+       else
+               hc->chan[ch].conf = -1;
+       mode_hfcmulti(hc, ch, hc->chan[ch].protocol, hc->chan[ch].slot_tx,
+           hc->chan[ch].bank_tx, hc->chan[ch].slot_rx,
+           hc->chan[ch].bank_rx);
+}
+
+
+/*
+ * set/disable sample loop
+ */
+
+/* NOTE: this function is experimental and therefore disabled */
+
+/*
+ * Layer 1 callback function
+ */
+static int
+hfcm_l1callback(struct dchannel *dch, u_int cmd)
+{
+       struct hfc_multi        *hc = dch->hw;
+       u_long  flags;
+
+       switch (cmd) {
+       case INFO3_P8:
+       case INFO3_P10:
+               break;
+       case HW_RESET_REQ:
+               /* start activation */
+               spin_lock_irqsave(&hc->lock, flags);
+               if (hc->type == 1) {
+                       if (debug & DEBUG_HFCMULTI_MSG)
+                               printk(KERN_DEBUG
+                                   "%s: HW_RESET_REQ no BRI\n",
+                                   __func__);
+               } else {
+                       HFC_outb(hc, R_ST_SEL, hc->chan[dch->slot].port);
+                       /* undocumented: delay after R_ST_SEL */
+                       udelay(1);
+                       HFC_outb(hc, A_ST_WR_STATE, V_ST_LD_STA | 3); /* F3 */
+                       udelay(6); /* wait at least 5,21us */
+                       HFC_outb(hc, A_ST_WR_STATE, 3);
+                       HFC_outb(hc, A_ST_WR_STATE, 3 | (V_ST_ACT*3));
+                               /* activate */
+               }
+               spin_unlock_irqrestore(&hc->lock, flags);
+               l1_event(dch->l1, HW_POWERUP_IND);
+               break;
+       case HW_DEACT_REQ:
+               /* start deactivation */
+               spin_lock_irqsave(&hc->lock, flags);
+               if (hc->type == 1) {
+                       if (debug & DEBUG_HFCMULTI_MSG)
+                               printk(KERN_DEBUG
+                                   "%s: HW_DEACT_REQ no BRI\n",
+                                   __func__);
+               } else {
+                       HFC_outb(hc, R_ST_SEL, hc->chan[dch->slot].port);
+                       /* undocumented: delay after R_ST_SEL */
+                       udelay(1);
+                       HFC_outb(hc, A_ST_WR_STATE, V_ST_ACT*2);
+                               /* deactivate */
+                       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+                               hc->syncronized &=
+                                  ~(1 << hc->chan[dch->slot].port);
+                               plxsd_checksync(hc, 0);
+                       }
+               }
+               skb_queue_purge(&dch->squeue);
+               if (dch->tx_skb) {
+                       dev_kfree_skb(dch->tx_skb);
+                       dch->tx_skb = NULL;
+               }
+               dch->tx_idx = 0;
+               if (dch->rx_skb) {
+                       dev_kfree_skb(dch->rx_skb);
+                       dch->rx_skb = NULL;
+               }
+               test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
+               if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
+                       del_timer(&dch->timer);
+               spin_unlock_irqrestore(&hc->lock, flags);
+               break;
+       case HW_POWERUP_REQ:
+               spin_lock_irqsave(&hc->lock, flags);
+               if (hc->type == 1) {
+                       if (debug & DEBUG_HFCMULTI_MSG)
+                               printk(KERN_DEBUG
+                                   "%s: HW_POWERUP_REQ no BRI\n",
+                                   __func__);
+               } else {
+                       HFC_outb(hc, R_ST_SEL, hc->chan[dch->slot].port);
+                       /* undocumented: delay after R_ST_SEL */
+                       udelay(1);
+                       HFC_outb(hc, A_ST_WR_STATE, 3 | 0x10); /* activate */
+                       udelay(6); /* wait at least 5,21us */
+                       HFC_outb(hc, A_ST_WR_STATE, 3); /* activate */
+               }
+               spin_unlock_irqrestore(&hc->lock, flags);
+               break;
+       case PH_ACTIVATE_IND:
+               test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+               _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+                       GFP_ATOMIC);
+               break;
+       case PH_DEACTIVATE_IND:
+               test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+               _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+                       GFP_ATOMIC);
+               break;
+       default:
+               if (dch->debug & DEBUG_HW)
+                       printk(KERN_DEBUG "%s: unknown command %x\n",
+                           __func__, cmd);
+               return -1;
+       }
+       return 0;
+}
+
+/*
+ * Layer2 -> Layer 1 Transfer
+ */
+
+static int
+handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct mISDNdevice      *dev = container_of(ch, struct mISDNdevice, D);
+       struct dchannel         *dch = container_of(dev, struct dchannel, dev);
+       struct hfc_multi        *hc = dch->hw;
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+       int                     ret = -EINVAL;
+       unsigned int            id;
+       u_long                  flags;
+
+       switch (hh->prim) {
+       case PH_DATA_REQ:
+               if (skb->len < 1)
+                       break;
+               spin_lock_irqsave(&hc->lock, flags);
+               ret = dchannel_senddata(dch, skb);
+               if (ret > 0) { /* direct TX */
+                       id = hh->id; /* skb can be freed */
+                       hfcmulti_tx(hc, dch->slot);
+                       ret = 0;
+                       /* start fifo */
+                       HFC_outb(hc, R_FIFO, 0);
+                       HFC_wait(hc);
+                       spin_unlock_irqrestore(&hc->lock, flags);
+                       queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+               } else
+                       spin_unlock_irqrestore(&hc->lock, flags);
+               return ret;
+       case PH_ACTIVATE_REQ:
+               if (dch->dev.D.protocol != ISDN_P_TE_S0) {
+                       spin_lock_irqsave(&hc->lock, flags);
+                       ret = 0;
+                       if (debug & DEBUG_HFCMULTI_MSG)
+                               printk(KERN_DEBUG
+                                   "%s: PH_ACTIVATE port %d (0..%d)\n",
+                                   __func__, hc->chan[dch->slot].port,
+                                   hc->ports-1);
+                       /* start activation */
+                       if (hc->type == 1) {
+                               ph_state_change(dch);
+                               if (debug & DEBUG_HFCMULTI_STATE)
+                                       printk(KERN_DEBUG
+                                           "%s: E1 report state %x \n",
+                                           __func__, dch->state);
+                       } else {
+                               HFC_outb(hc, R_ST_SEL,
+                                   hc->chan[dch->slot].port);
+                               /* undocumented: delay after R_ST_SEL */
+                               udelay(1);
+                               HFC_outb(hc, A_ST_WR_STATE, V_ST_LD_STA | 1);
+                                   /* G1 */
+                               udelay(6); /* wait at least 5,21us */
+                               HFC_outb(hc, A_ST_WR_STATE, 1);
+                               HFC_outb(hc, A_ST_WR_STATE, 1 |
+                                   (V_ST_ACT*3)); /* activate */
+                               dch->state = 1;
+                       }
+                       spin_unlock_irqrestore(&hc->lock, flags);
+               } else
+                       ret = l1_event(dch->l1, hh->prim);
+               break;
+       case PH_DEACTIVATE_REQ:
+               test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
+               if (dch->dev.D.protocol != ISDN_P_TE_S0) {
+                       spin_lock_irqsave(&hc->lock, flags);
+                       if (debug & DEBUG_HFCMULTI_MSG)
+                               printk(KERN_DEBUG
+                                   "%s: PH_DEACTIVATE port %d (0..%d)\n",
+                                   __func__, hc->chan[dch->slot].port,
+                                   hc->ports-1);
+                       /* start deactivation */
+                       if (hc->type == 1) {
+                               if (debug & DEBUG_HFCMULTI_MSG)
+                                       printk(KERN_DEBUG
+                                           "%s: PH_DEACTIVATE no BRI\n",
+                                           __func__);
+                       } else {
+                               HFC_outb(hc, R_ST_SEL,
+                                   hc->chan[dch->slot].port);
+                               /* undocumented: delay after R_ST_SEL */
+                               udelay(1);
+                               HFC_outb(hc, A_ST_WR_STATE, V_ST_ACT * 2);
+                                   /* deactivate */
+                               dch->state = 1;
+                       }
+                       skb_queue_purge(&dch->squeue);
+                       if (dch->tx_skb) {
+                               dev_kfree_skb(dch->tx_skb);
+                               dch->tx_skb = NULL;
+                       }
+                       dch->tx_idx = 0;
+                       if (dch->rx_skb) {
+                               dev_kfree_skb(dch->rx_skb);
+                               dch->rx_skb = NULL;
+                       }
+                       test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
+                       if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
+                               del_timer(&dch->timer);
+#ifdef FIXME
+                       if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags))
+                               dchannel_sched_event(&hc->dch, D_CLEARBUSY);
+#endif
+                       ret = 0;
+                       spin_unlock_irqrestore(&hc->lock, flags);
+               } else
+                       ret = l1_event(dch->l1, hh->prim);
+               break;
+       }
+       if (!ret)
+               dev_kfree_skb(skb);
+       return ret;
+}
+
+static void
+deactivate_bchannel(struct bchannel *bch)
+{
+       struct hfc_multi        *hc = bch->hw;
+       u_long                  flags;
+
+       spin_lock_irqsave(&hc->lock, flags);
+       if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
+               dev_kfree_skb(bch->next_skb);
+               bch->next_skb = NULL;
+       }
+       if (bch->tx_skb) {
+               dev_kfree_skb(bch->tx_skb);
+               bch->tx_skb = NULL;
+       }
+       bch->tx_idx = 0;
+       if (bch->rx_skb) {
+               dev_kfree_skb(bch->rx_skb);
+               bch->rx_skb = NULL;
+       }
+       hc->chan[bch->slot].coeff_count = 0;
+       test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
+       test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
+       hc->chan[bch->slot].rx_off = 0;
+       hc->chan[bch->slot].conf = -1;
+       mode_hfcmulti(hc, bch->slot, ISDN_P_NONE, -1, 0, -1, 0);
+       spin_unlock_irqrestore(&hc->lock, flags);
+}
+
+static int
+handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct bchannel         *bch = container_of(ch, struct bchannel, ch);
+       struct hfc_multi        *hc = bch->hw;
+       int                     ret = -EINVAL;
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+       unsigned int            id;
+       u_long                  flags;
+
+       switch (hh->prim) {
+       case PH_DATA_REQ:
+               if (!skb->len)
+                       break;
+               spin_lock_irqsave(&hc->lock, flags);
+               ret = bchannel_senddata(bch, skb);
+               if (ret > 0) { /* direct TX */
+                       id = hh->id; /* skb can be freed */
+                       hfcmulti_tx(hc, bch->slot);
+                       ret = 0;
+                       /* start fifo */
+                       HFC_outb_nodebug(hc, R_FIFO, 0);
+                       HFC_wait_nodebug(hc);
+                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) {
+                               spin_unlock_irqrestore(&hc->lock, flags);
+                               queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+                       } else
+                               spin_unlock_irqrestore(&hc->lock, flags);
+               } else
+                       spin_unlock_irqrestore(&hc->lock, flags);
+               return ret;
+       case PH_ACTIVATE_REQ:
+               if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG "%s: PH_ACTIVATE ch %d (0..32)\n",
+                               __func__, bch->slot);
+               spin_lock_irqsave(&hc->lock, flags);
+               /* activate B-channel if not already activated */
+               if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
+                       hc->chan[bch->slot].txpending = 0;
+                       ret = mode_hfcmulti(hc, bch->slot,
+                               ch->protocol,
+                               hc->chan[bch->slot].slot_tx,
+                               hc->chan[bch->slot].bank_tx,
+                               hc->chan[bch->slot].slot_rx,
+                               hc->chan[bch->slot].bank_rx);
+                       if (!ret) {
+                               if (ch->protocol == ISDN_P_B_RAW && !hc->dtmf
+                                       && test_bit(HFC_CHIP_DTMF, &hc->chip)) {
+                                       /* start decoder */
+                                       hc->dtmf = 1;
+                                       if (debug & DEBUG_HFCMULTI_DTMF)
+                                               printk(KERN_DEBUG
+                                                   "%s: start dtmf decoder\n",
+                                                       __func__);
+                                       HFC_outb(hc, R_DTMF, hc->hw.r_dtmf |
+                                           V_RST_DTMF);
+                               }
+                       }
+               } else
+                       ret = 0;
+               spin_unlock_irqrestore(&hc->lock, flags);
+               if (!ret)
+                       _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, NULL,
+                               GFP_KERNEL);
+               break;
+       case PH_CONTROL_REQ:
+               spin_lock_irqsave(&hc->lock, flags);
+               switch (hh->id) {
+               case HFC_SPL_LOOP_ON: /* set sample loop */
+                       if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG
+                           "%s: HFC_SPL_LOOP_ON (len = %d)\n",
+                           __func__, skb->len);
+                       ret = 0;
+                       break;
+               case HFC_SPL_LOOP_OFF: /* set silence */
+                       if (debug & DEBUG_HFCMULTI_MSG)
+                               printk(KERN_DEBUG "%s: HFC_SPL_LOOP_OFF\n",
+                                   __func__);
+                       ret = 0;
+                       break;
+               default:
+                       printk(KERN_ERR
+                            "%s: unknown PH_CONTROL_REQ info %x\n",
+                            __func__, hh->id);
+                       ret = -EINVAL;
+               }
+               spin_unlock_irqrestore(&hc->lock, flags);
+               break;
+       case PH_DEACTIVATE_REQ:
+               deactivate_bchannel(bch); /* locked there */
+               _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, NULL,
+                       GFP_KERNEL);
+               ret = 0;
+               break;
+       }
+       if (!ret)
+               dev_kfree_skb(skb);
+       return ret;
+}
+
+/*
+ * bchannel control function
+ */
+static int
+channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
+{
+       int                     ret = 0;
+       struct dsp_features     *features =
+               (struct dsp_features *)(*((u_long *)&cq->p1));
+       struct hfc_multi        *hc = bch->hw;
+       int                     slot_tx;
+       int                     bank_tx;
+       int                     slot_rx;
+       int                     bank_rx;
+       int                     num;
+
+       switch (cq->op) {
+       case MISDN_CTRL_GETOP:
+               cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP
+                       | MISDN_CTRL_RX_OFF;
+               break;
+       case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
+               hc->chan[bch->slot].rx_off = !!cq->p1;
+               if (!hc->chan[bch->slot].rx_off) {
+                       /* reset fifo on rx on */
+                       HFC_outb_nodebug(hc, R_FIFO, (bch->slot << 1) | 1);
+                       HFC_wait_nodebug(hc);
+                       HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_RES_F);
+                       HFC_wait_nodebug(hc);
+               }
+               if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n",
+                           __func__, bch->nr, hc->chan[bch->slot].rx_off);
+               break;
+       case MISDN_CTRL_HW_FEATURES: /* fill features structure */
+               if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG "%s: HW_FEATURE request\n",
+                           __func__);
+               /* create confirm */
+               features->hfc_id = hc->id;
+               if (test_bit(HFC_CHIP_DTMF, &hc->chip))
+                       features->hfc_dtmf = 1;
+               features->hfc_loops = 0;
+               if (test_bit(HFC_CHIP_B410P, &hc->chip)) {
+                       features->hfc_echocanhw = 1;
+               } else {
+                       features->pcm_id = hc->pcm;
+                       features->pcm_slots = hc->slots;
+                       features->pcm_banks = 2;
+               }
+               break;
+       case MISDN_CTRL_HFC_PCM_CONN: /* connect to pcm timeslot (0..N) */
+               slot_tx = cq->p1 & 0xff;
+               bank_tx = cq->p1 >> 8;
+               slot_rx = cq->p2 & 0xff;
+               bank_rx = cq->p2 >> 8;
+               if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG
+                           "%s: HFC_PCM_CONN slot %d bank %d (TX) "
+                           "slot %d bank %d (RX)\n",
+                           __func__, slot_tx, bank_tx,
+                           slot_rx, bank_rx);
+               if (slot_tx < hc->slots && bank_tx <= 2 &&
+                   slot_rx < hc->slots && bank_rx <= 2)
+                       hfcmulti_pcm(hc, bch->slot,
+                           slot_tx, bank_tx, slot_rx, bank_rx);
+               else {
+                       printk(KERN_WARNING
+                           "%s: HFC_PCM_CONN slot %d bank %d (TX) "
+                           "slot %d bank %d (RX) out of range\n",
+                           __func__, slot_tx, bank_tx,
+                           slot_rx, bank_rx);
+                       ret = -EINVAL;
+               }
+               break;
+       case MISDN_CTRL_HFC_PCM_DISC: /* release interface from pcm timeslot */
+               if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG "%s: HFC_PCM_DISC\n",
+                           __func__);
+               hfcmulti_pcm(hc, bch->slot, -1, 0, -1, 0);
+               break;
+       case MISDN_CTRL_HFC_CONF_JOIN: /* join conference (0..7) */
+               num = cq->p1 & 0xff;
+               if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG "%s: HFC_CONF_JOIN conf %d\n",
+                           __func__, num);
+               if (num <= 7)
+                       hfcmulti_conf(hc, bch->slot, num);
+               else {
+                       printk(KERN_WARNING
+                           "%s: HW_CONF_JOIN conf %d out of range\n",
+                           __func__, num);
+                       ret = -EINVAL;
+               }
+               break;
+       case MISDN_CTRL_HFC_CONF_SPLIT: /* split conference */
+               if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG "%s: HFC_CONF_SPLIT\n", __func__);
+               hfcmulti_conf(hc, bch->slot, -1);
+               break;
+       case MISDN_CTRL_HFC_ECHOCAN_ON:
+               if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG "%s: HFC_ECHOCAN_ON\n", __func__);
+               if (test_bit(HFC_CHIP_B410P, &hc->chip))
+                       vpm_echocan_on(hc, bch->slot, cq->p1);
+               else
+                       ret = -EINVAL;
+               break;
+
+       case MISDN_CTRL_HFC_ECHOCAN_OFF:
+               if (debug & DEBUG_HFCMULTI_MSG)
+                       printk(KERN_DEBUG "%s: HFC_ECHOCAN_OFF\n",
+                               __func__);
+               if (test_bit(HFC_CHIP_B410P, &hc->chip))
+                       vpm_echocan_off(hc, bch->slot);
+               else
+                       ret = -EINVAL;
+               break;
+       default:
+               printk(KERN_WARNING "%s: unknown Op %x\n",
+                   __func__, cq->op);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int
+hfcm_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct bchannel         *bch = container_of(ch, struct bchannel, ch);
+       struct hfc_multi        *hc = bch->hw;
+       int                     err = -EINVAL;
+       u_long  flags;
+
+       if (bch->debug & DEBUG_HW)
+               printk(KERN_DEBUG "%s: cmd:%x %p\n",
+                   __func__, cmd, arg);
+       switch (cmd) {
+       case CLOSE_CHANNEL:
+               test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               if (test_bit(FLG_ACTIVE, &bch->Flags))
+                       deactivate_bchannel(bch); /* locked there */
+               ch->protocol = ISDN_P_NONE;
+               ch->peer = NULL;
+               module_put(THIS_MODULE);
+               err = 0;
+               break;
+       case CONTROL_CHANNEL:
+               spin_lock_irqsave(&hc->lock, flags);
+               err = channel_bctrl(bch, arg);
+               spin_unlock_irqrestore(&hc->lock, flags);
+               break;
+       default:
+               printk(KERN_WARNING "%s: unknown prim(%x)\n",
+                       __func__, cmd);
+       }
+       return err;
+}
+
+/*
+ * handle D-channel events
+ *
+ * handle state change event
+ */
+static void
+ph_state_change(struct dchannel *dch)
+{
+       struct hfc_multi *hc = dch->hw;
+       int ch, i;
+
+       if (!dch) {
+               printk(KERN_WARNING "%s: ERROR given dch is NULL\n",
+                   __func__);
+               return;
+       }
+       ch = dch->slot;
+
+       if (hc->type == 1) {
+               if (dch->dev.D.protocol == ISDN_P_TE_E1) {
+                       if (debug & DEBUG_HFCMULTI_STATE)
+                               printk(KERN_DEBUG
+                                   "%s: E1 TE (id=%d) newstate %x\n",
+                                   __func__, hc->id, dch->state);
+               } else {
+                       if (debug & DEBUG_HFCMULTI_STATE)
+                               printk(KERN_DEBUG
+                                   "%s: E1 NT (id=%d) newstate %x\n",
+                                   __func__, hc->id, dch->state);
+               }
+               switch (dch->state) {
+               case (1):
+                       if (hc->e1_state != 1) {
+                           for (i = 1; i <= 31; i++) {
+                               /* reset fifos on e1 activation */
+                               HFC_outb_nodebug(hc, R_FIFO, (i << 1) | 1);
+                               HFC_wait_nodebug(hc);
+                               HFC_outb_nodebug(hc,
+                                       R_INC_RES_FIFO, V_RES_F);
+                               HFC_wait_nodebug(hc);
+                           }
+                       }
+                       test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+                       _queue_data(&dch->dev.D, PH_ACTIVATE_IND,
+                           MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+                       break;
+
+               default:
+                       if (hc->e1_state != 1)
+                               return;
+                       test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+                       _queue_data(&dch->dev.D, PH_DEACTIVATE_IND,
+                           MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+               }
+               hc->e1_state = dch->state;
+       } else {
+               if (dch->dev.D.protocol == ISDN_P_TE_S0) {
+                       if (debug & DEBUG_HFCMULTI_STATE)
+                               printk(KERN_DEBUG
+                                   "%s: S/T TE newstate %x\n",
+                                   __func__, dch->state);
+                       switch (dch->state) {
+                       case (0):
+                               l1_event(dch->l1, HW_RESET_IND);
+                               break;
+                       case (3):
+                               l1_event(dch->l1, HW_DEACT_IND);
+                               break;
+                       case (5):
+                       case (8):
+                               l1_event(dch->l1, ANYSIGNAL);
+                               break;
+                       case (6):
+                               l1_event(dch->l1, INFO2);
+                               break;
+                       case (7):
+                               l1_event(dch->l1, INFO4_P8);
+                               break;
+                       }
+               } else {
+                       if (debug & DEBUG_HFCMULTI_STATE)
+                               printk(KERN_DEBUG "%s: S/T NT newstate %x\n",
+                                   __func__, dch->state);
+                       switch (dch->state) {
+                       case (2):
+                               if (hc->chan[ch].nt_timer == 0) {
+                                       hc->chan[ch].nt_timer = -1;
+                                       HFC_outb(hc, R_ST_SEL,
+                                           hc->chan[ch].port);
+                                       /* undocumented: delay after R_ST_SEL */
+                                       udelay(1);
+                                       HFC_outb(hc, A_ST_WR_STATE, 4 |
+                                           V_ST_LD_STA); /* G4 */
+                                       udelay(6); /* wait at least 5,21us */
+                                       HFC_outb(hc, A_ST_WR_STATE, 4);
+                                       dch->state = 4;
+                               } else {
+                                       /* one extra count for the next event */
+                                       hc->chan[ch].nt_timer =
+                                           nt_t1_count[poll_timer] + 1;
+                                       HFC_outb(hc, R_ST_SEL,
+                                           hc->chan[ch].port);
+                                       /* undocumented: delay after R_ST_SEL */
+                                       udelay(1);
+                                       /* allow G2 -> G3 transition */
+                                       HFC_outb(hc, A_ST_WR_STATE, 2 |
+                                           V_SET_G2_G3);
+                               }
+                               break;
+                       case (1):
+                               hc->chan[ch].nt_timer = -1;
+                               test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+                               _queue_data(&dch->dev.D, PH_DEACTIVATE_IND,
+                                   MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+                               break;
+                       case (4):
+                               hc->chan[ch].nt_timer = -1;
+                               break;
+                       case (3):
+                               hc->chan[ch].nt_timer = -1;
+                               test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+                               _queue_data(&dch->dev.D, PH_ACTIVATE_IND,
+                                   MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+                               break;
+                       }
+               }
+       }
+}
+
+/*
+ * called for card mode init message
+ */
+
+static void
+hfcmulti_initmode(struct dchannel *dch)
+{
+       struct hfc_multi *hc = dch->hw;
+       u_char          a_st_wr_state, r_e1_wr_sta;
+       int             i, pt;
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: entered\n", __func__);
+
+       if (hc->type == 1) {
+               hc->chan[hc->dslot].slot_tx = -1;
+               hc->chan[hc->dslot].slot_rx = -1;
+               hc->chan[hc->dslot].conf = -1;
+               if (hc->dslot) {
+                       mode_hfcmulti(hc, hc->dslot, dch->dev.D.protocol,
+                               -1, 0, -1, 0);
+                       dch->timer.function = (void *) hfcmulti_dbusy_timer;
+                       dch->timer.data = (long) dch;
+                       init_timer(&dch->timer);
+               }
+               for (i = 1; i <= 31; i++) {
+                       if (i == hc->dslot)
+                               continue;
+                       hc->chan[i].slot_tx = -1;
+                       hc->chan[i].slot_rx = -1;
+                       hc->chan[i].conf = -1;
+                       mode_hfcmulti(hc, i, ISDN_P_NONE, -1, 0, -1, 0);
+               }
+               /* E1 */
+               if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) {
+                       HFC_outb(hc, R_LOS0, 255); /* 2 ms */
+                       HFC_outb(hc, R_LOS1, 255); /* 512 ms */
+               }
+               if (test_bit(HFC_CFG_OPTICAL, &hc->chan[hc->dslot].cfg)) {
+                       HFC_outb(hc, R_RX0, 0);
+                       hc->hw.r_tx0 = 0 | V_OUT_EN;
+               } else {
+                       HFC_outb(hc, R_RX0, 1);
+                       hc->hw.r_tx0 = 1 | V_OUT_EN;
+               }
+               hc->hw.r_tx1 = V_ATX | V_NTRI;
+               HFC_outb(hc, R_TX0, hc->hw.r_tx0);
+               HFC_outb(hc, R_TX1, hc->hw.r_tx1);
+               HFC_outb(hc, R_TX_FR0, 0x00);
+               HFC_outb(hc, R_TX_FR1, 0xf8);
+
+               if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg))
+                       HFC_outb(hc, R_TX_FR2, V_TX_MF | V_TX_E | V_NEG_E);
+
+               HFC_outb(hc, R_RX_FR0, V_AUTO_RESYNC | V_AUTO_RECO | 0);
+
+               if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg))
+                       HFC_outb(hc, R_RX_FR1, V_RX_MF | V_RX_MF_SYNC);
+
+               if (dch->dev.D.protocol == ISDN_P_NT_E1) {
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_DEBUG "%s: E1 port is NT-mode\n",
+                                   __func__);
+                       r_e1_wr_sta = 0; /* G0 */
+                       hc->e1_getclock = 0;
+               } else {
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_DEBUG "%s: E1 port is TE-mode\n",
+                                   __func__);
+                       r_e1_wr_sta = 0; /* F0 */
+                       hc->e1_getclock = 1;
+               }
+               if (test_bit(HFC_CHIP_RX_SYNC, &hc->chip))
+                       HFC_outb(hc, R_SYNC_OUT, V_SYNC_E1_RX);
+               else
+                       HFC_outb(hc, R_SYNC_OUT, 0);
+               if (test_bit(HFC_CHIP_E1CLOCK_GET, &hc->chip))
+                       hc->e1_getclock = 1;
+               if (test_bit(HFC_CHIP_E1CLOCK_PUT, &hc->chip))
+                       hc->e1_getclock = 0;
+               if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
+                       /* SLAVE (clock master) */
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_DEBUG
+                                   "%s: E1 port is clock master "
+                                   "(clock from PCM)\n", __func__);
+                       HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC | V_PCM_SYNC);
+               } else {
+                       if (hc->e1_getclock) {
+                               /* MASTER (clock slave) */
+                               if (debug & DEBUG_HFCMULTI_INIT)
+                                       printk(KERN_DEBUG
+                                           "%s: E1 port is clock slave "
+                                           "(clock to PCM)\n", __func__);
+                               HFC_outb(hc, R_SYNC_CTRL, V_SYNC_OFFS);
+                       } else {
+                               /* MASTER (clock master) */
+                               if (debug & DEBUG_HFCMULTI_INIT)
+                                       printk(KERN_DEBUG "%s: E1 port is "
+                                           "clock master "
+                                           "(clock from QUARTZ)\n",
+                                           __func__);
+                               HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC |
+                                   V_PCM_SYNC | V_JATT_OFF);
+                               HFC_outb(hc, R_SYNC_OUT, 0);
+                       }
+               }
+               HFC_outb(hc, R_JATT_ATT, 0x9c); /* undoc register */
+               HFC_outb(hc, R_PWM_MD, V_PWM0_MD);
+               HFC_outb(hc, R_PWM0, 0x50);
+               HFC_outb(hc, R_PWM1, 0xff);
+               /* state machine setup */
+               HFC_outb(hc, R_E1_WR_STA, r_e1_wr_sta | V_E1_LD_STA);
+               udelay(6); /* wait at least 5,21us */
+               HFC_outb(hc, R_E1_WR_STA, r_e1_wr_sta);
+               if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+                       hc->syncronized = 0;
+                       plxsd_checksync(hc, 0);
+               }
+       } else {
+               i = dch->slot;
+               hc->chan[i].slot_tx = -1;
+               hc->chan[i].slot_rx = -1;
+               hc->chan[i].conf = -1;
+               mode_hfcmulti(hc, i, dch->dev.D.protocol, -1, 0, -1, 0);
+               dch->timer.function = (void *)hfcmulti_dbusy_timer;
+               dch->timer.data = (long) dch;
+               init_timer(&dch->timer);
+               hc->chan[i - 2].slot_tx = -1;
+               hc->chan[i - 2].slot_rx = -1;
+               hc->chan[i - 2].conf = -1;
+               mode_hfcmulti(hc, i - 2, ISDN_P_NONE, -1, 0, -1, 0);
+               hc->chan[i - 1].slot_tx = -1;
+               hc->chan[i - 1].slot_rx = -1;
+               hc->chan[i - 1].conf = -1;
+               mode_hfcmulti(hc, i - 1, ISDN_P_NONE, -1, 0, -1, 0);
+               /* ST */
+               pt = hc->chan[i].port;
+               /* select interface */
+               HFC_outb(hc, R_ST_SEL, pt);
+               /* undocumented: delay after R_ST_SEL */
+               udelay(1);
+               if (dch->dev.D.protocol == ISDN_P_NT_S0) {
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_DEBUG
+                                   "%s: ST port %d is NT-mode\n",
+                                   __func__, pt);
+                       /* clock delay */
+                       HFC_outb(hc, A_ST_CLK_DLY, clockdelay_nt);
+                       a_st_wr_state = 1; /* G1 */
+                       hc->hw.a_st_ctrl0[pt] = V_ST_MD;
+               } else {
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_DEBUG
+                                   "%s: ST port %d is TE-mode\n",
+                                   __func__, pt);
+                       /* clock delay */
+                       HFC_outb(hc, A_ST_CLK_DLY, clockdelay_te);
+                       a_st_wr_state = 2; /* F2 */
+                       hc->hw.a_st_ctrl0[pt] = 0;
+               }
+               if (!test_bit(HFC_CFG_NONCAP_TX, &hc->chan[i].cfg))
+                       hc->hw.a_st_ctrl0[pt] |= V_TX_LI;
+               /* line setup */
+               HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[pt]);
+               /* disable E-channel */
+               if ((dch->dev.D.protocol == ISDN_P_NT_S0) ||
+                   test_bit(HFC_CFG_DIS_ECHANNEL, &hc->chan[i].cfg))
+                       HFC_outb(hc, A_ST_CTRL1, V_E_IGNO);
+               else
+                       HFC_outb(hc, A_ST_CTRL1, 0);
+               /* enable B-channel receive */
+               HFC_outb(hc, A_ST_CTRL2,  V_B1_RX_EN | V_B2_RX_EN);
+               /* state machine setup */
+               HFC_outb(hc, A_ST_WR_STATE, a_st_wr_state | V_ST_LD_STA);
+               udelay(6); /* wait at least 5,21us */
+               HFC_outb(hc, A_ST_WR_STATE, a_st_wr_state);
+               hc->hw.r_sci_msk |= 1 << pt;
+               /* state machine interrupts */
+               HFC_outb(hc, R_SCI_MSK, hc->hw.r_sci_msk);
+               /* unset sync on port */
+               if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+                       hc->syncronized &=
+                          ~(1 << hc->chan[dch->slot].port);
+                       plxsd_checksync(hc, 0);
+               }
+       }
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk("%s: done\n", __func__);
+}
+
+
+static int
+open_dchannel(struct hfc_multi *hc, struct dchannel *dch,
+    struct channel_req *rq)
+{
+       int     err = 0;
+       u_long  flags;
+
+       if (debug & DEBUG_HW_OPEN)
+               printk(KERN_DEBUG "%s: dev(%d) open from %p\n", __func__,
+                   dch->dev.id, __builtin_return_address(0));
+       if (rq->protocol == ISDN_P_NONE)
+               return -EINVAL;
+       if ((dch->dev.D.protocol != ISDN_P_NONE) &&
+           (dch->dev.D.protocol != rq->protocol)) {
+           if (debug & DEBUG_HFCMULTI_MODE)
+               printk(KERN_WARNING "%s: change protocol %x to %x\n",
+                   __func__, dch->dev.D.protocol, rq->protocol);
+       }
+       if ((dch->dev.D.protocol == ISDN_P_TE_S0)
+        && (rq->protocol != ISDN_P_TE_S0))
+               l1_event(dch->l1, CLOSE_CHANNEL);
+       if (dch->dev.D.protocol != rq->protocol) {
+               if (rq->protocol == ISDN_P_TE_S0) {
+                       err = create_l1(dch, hfcm_l1callback);
+                       if (err)
+                               return err;
+               }
+               dch->dev.D.protocol = rq->protocol;
+               spin_lock_irqsave(&hc->lock, flags);
+               hfcmulti_initmode(dch);
+               spin_unlock_irqrestore(&hc->lock, flags);
+       }
+
+       if (((rq->protocol == ISDN_P_NT_S0) && (dch->state == 3)) ||
+           ((rq->protocol == ISDN_P_TE_S0) && (dch->state == 7)) ||
+           ((rq->protocol == ISDN_P_NT_E1) && (dch->state == 1)) ||
+           ((rq->protocol == ISDN_P_TE_E1) && (dch->state == 1))) {
+               _queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY,
+                   0, NULL, GFP_KERNEL);
+       }
+       rq->ch = &dch->dev.D;
+       if (!try_module_get(THIS_MODULE))
+               printk(KERN_WARNING "%s:cannot get module\n", __func__);
+       return 0;
+}
+
+static int
+open_bchannel(struct hfc_multi *hc, struct dchannel *dch,
+    struct channel_req *rq)
+{
+       struct bchannel *bch;
+       int             ch;
+
+       if (!test_bit(rq->adr.channel, &dch->dev.channelmap[0]))
+               return -EINVAL;
+       if (rq->protocol == ISDN_P_NONE)
+               return -EINVAL;
+       if (hc->type == 1)
+               ch = rq->adr.channel;
+       else
+               ch = (rq->adr.channel - 1) + (dch->slot - 2);
+       bch = hc->chan[ch].bch;
+       if (!bch) {
+               printk(KERN_ERR "%s:internal error ch %d has no bch\n",
+                   __func__, ch);
+               return -EINVAL;
+       }
+       if (test_and_set_bit(FLG_OPEN, &bch->Flags))
+               return -EBUSY; /* b-channel can be only open once */
+       bch->ch.protocol = rq->protocol;
+       hc->chan[ch].rx_off = 0;
+       rq->ch = &bch->ch;
+       if (!try_module_get(THIS_MODULE))
+               printk(KERN_WARNING "%s:cannot get module\n", __func__);
+       return 0;
+}
+
+/*
+ * device control function
+ */
+static int
+channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
+{
+       int     ret = 0;
+
+       switch (cq->op) {
+       case MISDN_CTRL_GETOP:
+               cq->op = 0;
+               break;
+       default:
+               printk(KERN_WARNING "%s: unknown Op %x\n",
+                   __func__, cq->op);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int
+hfcm_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct mISDNdevice      *dev = container_of(ch, struct mISDNdevice, D);
+       struct dchannel         *dch = container_of(dev, struct dchannel, dev);
+       struct hfc_multi        *hc = dch->hw;
+       struct channel_req      *rq;
+       int                     err = 0;
+       u_long                  flags;
+
+       if (dch->debug & DEBUG_HW)
+               printk(KERN_DEBUG "%s: cmd:%x %p\n",
+                   __func__, cmd, arg);
+       switch (cmd) {
+       case OPEN_CHANNEL:
+               rq = arg;
+               switch (rq->protocol) {
+               case ISDN_P_TE_S0:
+               case ISDN_P_NT_S0:
+                       if (hc->type == 1) {
+                               err = -EINVAL;
+                               break;
+                       }
+                       err = open_dchannel(hc, dch, rq); /* locked there */
+                       break;
+               case ISDN_P_TE_E1:
+               case ISDN_P_NT_E1:
+                       if (hc->type != 1) {
+                               err = -EINVAL;
+                               break;
+                       }
+                       err = open_dchannel(hc, dch, rq); /* locked there */
+                       break;
+               default:
+                       spin_lock_irqsave(&hc->lock, flags);
+                       err = open_bchannel(hc, dch, rq);
+                       spin_unlock_irqrestore(&hc->lock, flags);
+               }
+               break;
+       case CLOSE_CHANNEL:
+               if (debug & DEBUG_HW_OPEN)
+                       printk(KERN_DEBUG "%s: dev(%d) close from %p\n",
+                           __func__, dch->dev.id,
+                           __builtin_return_address(0));
+               module_put(THIS_MODULE);
+               break;
+       case CONTROL_CHANNEL:
+               spin_lock_irqsave(&hc->lock, flags);
+               err = channel_dctrl(dch, arg);
+               spin_unlock_irqrestore(&hc->lock, flags);
+               break;
+       default:
+               if (dch->debug & DEBUG_HW)
+                       printk(KERN_DEBUG "%s: unknown command %x\n",
+                           __func__, cmd);
+               err = -EINVAL;
+       }
+       return err;
+}
+
+/*
+ * initialize the card
+ */
+
+/*
+ * start timer irq, wait some time and check if we have interrupts.
+ * if not, reset chip and try again.
+ */
+static int
+init_card(struct hfc_multi *hc)
+{
+       int     err = -EIO;
+       u_long  flags;
+       u_short *plx_acc;
+       u_long  plx_flags;
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: entered\n", __func__);
+
+       spin_lock_irqsave(&hc->lock, flags);
+       /* set interrupts but leave global interrupt disabled */
+       hc->hw.r_irq_ctrl = V_FIFO_IRQ;
+       disable_hwirq(hc);
+       spin_unlock_irqrestore(&hc->lock, flags);
+
+       if (request_irq(hc->pci_dev->irq, hfcmulti_interrupt, IRQF_SHARED,
+           "HFC-multi", hc)) {
+               printk(KERN_WARNING "mISDN: Could not get interrupt %d.\n",
+                   hc->pci_dev->irq);
+               return -EIO;
+       }
+       hc->irq = hc->pci_dev->irq;
+
+       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+               spin_lock_irqsave(&plx_lock, plx_flags);
+               plx_acc = (u_short *)(hc->plx_membase+PLX_INTCSR);
+               writew((PLX_INTCSR_PCIINT_ENABLE | PLX_INTCSR_LINTI1_ENABLE),
+                       plx_acc); /* enable PCI & LINT1 irq */
+               spin_unlock_irqrestore(&plx_lock, plx_flags);
+       }
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: IRQ %d count %d\n",
+                   __func__, hc->irq, hc->irqcnt);
+       err = init_chip(hc);
+       if (err)
+               goto error;
+       /*
+        * Finally enable IRQ output
+        * this is only allowed, if an IRQ routine is allready
+        * established for this HFC, so don't do that earlier
+        */
+       spin_lock_irqsave(&hc->lock, flags);
+       enable_hwirq(hc);
+       spin_unlock_irqrestore(&hc->lock, flags);
+       /* printk(KERN_DEBUG "no master irq set!!!\n"); */
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout((100*HZ)/1000); /* Timeout 100ms */
+       /* turn IRQ off until chip is completely initialized */
+       spin_lock_irqsave(&hc->lock, flags);
+       disable_hwirq(hc);
+       spin_unlock_irqrestore(&hc->lock, flags);
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: IRQ %d count %d\n",
+                   __func__, hc->irq, hc->irqcnt);
+       if (hc->irqcnt) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: done\n", __func__);
+
+               return 0;
+       }
+       if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
+               printk(KERN_INFO "ignoring missing interrupts\n");
+               return 0;
+       }
+
+       printk(KERN_ERR "HFC PCI: IRQ(%d) getting no interrupts during init.\n",
+               hc->irq);
+
+       err = -EIO;
+
+error:
+       if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+               spin_lock_irqsave(&plx_lock, plx_flags);
+               plx_acc = (u_short *)(hc->plx_membase+PLX_INTCSR);
+               writew(0x00, plx_acc); /*disable IRQs*/
+               spin_unlock_irqrestore(&plx_lock, plx_flags);
+       }
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_WARNING "%s: free irq %d\n", __func__, hc->irq);
+       if (hc->irq) {
+               free_irq(hc->irq, hc);
+               hc->irq = 0;
+       }
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: done (err=%d)\n", __func__, err);
+       return err;
+}
+
+/*
+ * find pci device and set it up
+ */
+
+static int
+setup_pci(struct hfc_multi *hc, struct pci_dev *pdev,
+               const struct pci_device_id *ent)
+{
+       struct hm_map   *m = (struct hm_map *)ent->driver_data;
+
+       printk(KERN_INFO
+           "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n",
+           m->vendor_name, m->card_name, m->clock2 ? "double" : "normal");
+
+       hc->pci_dev = pdev;
+       if (m->clock2)
+               test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip);
+
+       if (ent->device == 0xB410) {
+               test_and_set_bit(HFC_CHIP_B410P, &hc->chip);
+               test_and_set_bit(HFC_CHIP_PCM_MASTER, &hc->chip);
+               test_and_clear_bit(HFC_CHIP_PCM_SLAVE, &hc->chip);
+               hc->slots = 32;
+       }
+
+       if (hc->pci_dev->irq <= 0) {
+               printk(KERN_WARNING "HFC-multi: No IRQ for PCI card found.\n");
+               return -EIO;
+       }
+       if (pci_enable_device(hc->pci_dev)) {
+               printk(KERN_WARNING "HFC-multi: Error enabling PCI card.\n");
+               return -EIO;
+       }
+       hc->leds = m->leds;
+       hc->ledstate = 0xAFFEAFFE;
+       hc->opticalsupport = m->opticalsupport;
+
+       /* set memory access methods */
+       if (m->io_mode) /* use mode from card config */
+               hc->io_mode = m->io_mode;
+       switch (hc->io_mode) {
+       case HFC_IO_MODE_PLXSD:
+               test_and_set_bit(HFC_CHIP_PLXSD, &hc->chip);
+               hc->slots = 128; /* required */
+               /* fall through */
+       case HFC_IO_MODE_PCIMEM:
+               hc->HFC_outb = HFC_outb_pcimem;
+               hc->HFC_inb = HFC_inb_pcimem;
+               hc->HFC_inw = HFC_inw_pcimem;
+               hc->HFC_wait = HFC_wait_pcimem;
+               hc->read_fifo = read_fifo_pcimem;
+               hc->write_fifo = write_fifo_pcimem;
+               break;
+       case HFC_IO_MODE_REGIO:
+               hc->HFC_outb = HFC_outb_regio;
+               hc->HFC_inb = HFC_inb_regio;
+               hc->HFC_inw = HFC_inw_regio;
+               hc->HFC_wait = HFC_wait_regio;
+               hc->read_fifo = read_fifo_regio;
+               hc->write_fifo = write_fifo_regio;
+               break;
+       default:
+               printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n");
+               pci_disable_device(hc->pci_dev);
+               return -EIO;
+       }
+       hc->HFC_outb_nodebug = hc->HFC_outb;
+       hc->HFC_inb_nodebug = hc->HFC_inb;
+       hc->HFC_inw_nodebug = hc->HFC_inw;
+       hc->HFC_wait_nodebug = hc->HFC_wait;
+#ifdef HFC_REGISTER_DEBUG
+       hc->HFC_outb = HFC_outb_debug;
+       hc->HFC_inb = HFC_inb_debug;
+       hc->HFC_inw = HFC_inw_debug;
+       hc->HFC_wait = HFC_wait_debug;
+#endif
+       hc->pci_iobase = 0;
+       hc->pci_membase = NULL;
+       hc->plx_membase = NULL;
+
+       switch (hc->io_mode) {
+       case HFC_IO_MODE_PLXSD:
+               hc->plx_origmembase =  hc->pci_dev->resource[0].start;
+               /* MEMBASE 1 is PLX PCI Bridge */
+
+               if (!hc->plx_origmembase) {
+                       printk(KERN_WARNING
+                         "HFC-multi: No IO-Memory for PCI PLX bridge found\n");
+                       pci_disable_device(hc->pci_dev);
+                       return -EIO;
+               }
+
+               hc->plx_membase = ioremap(hc->plx_origmembase, 0x80);
+               if (!hc->plx_membase) {
+                       printk(KERN_WARNING
+                           "HFC-multi: failed to remap plx address space. "
+                           "(internal error)\n");
+                       pci_disable_device(hc->pci_dev);
+                       return -EIO;
+               }
+               printk(KERN_INFO
+                   "HFC-multi: plx_membase:%#lx plx_origmembase:%#lx\n",
+                   (u_long)hc->plx_membase, hc->plx_origmembase);
+
+               hc->pci_origmembase =  hc->pci_dev->resource[2].start;
+                   /* MEMBASE 1 is PLX PCI Bridge */
+               if (!hc->pci_origmembase) {
+                       printk(KERN_WARNING
+                           "HFC-multi: No IO-Memory for PCI card found\n");
+                       pci_disable_device(hc->pci_dev);
+                       return -EIO;
+               }
+
+               hc->pci_membase = ioremap(hc->pci_origmembase, 0x400);
+               if (!hc->pci_membase) {
+                       printk(KERN_WARNING "HFC-multi: failed to remap io "
+                           "address space. (internal error)\n");
+                       pci_disable_device(hc->pci_dev);
+                       return -EIO;
+               }
+
+               printk(KERN_INFO
+                   "card %d: defined at MEMBASE %#lx (%#lx) IRQ %d HZ %d "
+                   "leds-type %d\n",
+                   hc->id, (u_long)hc->pci_membase, hc->pci_origmembase,
+                   hc->pci_dev->irq, HZ, hc->leds);
+               pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO);
+               break;
+       case HFC_IO_MODE_PCIMEM:
+               hc->pci_origmembase = hc->pci_dev->resource[1].start;
+               if (!hc->pci_origmembase) {
+                       printk(KERN_WARNING
+                           "HFC-multi: No IO-Memory for PCI card found\n");
+                       pci_disable_device(hc->pci_dev);
+                       return -EIO;
+               }
+
+               hc->pci_membase = ioremap(hc->pci_origmembase, 256);
+               if (!hc->pci_membase) {
+                       printk(KERN_WARNING
+                           "HFC-multi: failed to remap io address space. "
+                           "(internal error)\n");
+                       pci_disable_device(hc->pci_dev);
+                       return -EIO;
+               }
+               printk(KERN_INFO "card %d: defined at MEMBASE %#lx (%#lx) IRQ %d "
+                   "HZ %d leds-type %d\n", hc->id, (u_long)hc->pci_membase,
+                   hc->pci_origmembase, hc->pci_dev->irq, HZ, hc->leds);
+               pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO);
+               break;
+       case HFC_IO_MODE_REGIO:
+               hc->pci_iobase = (u_int) hc->pci_dev->resource[0].start;
+               if (!hc->pci_iobase) {
+                       printk(KERN_WARNING
+                               "HFC-multi: No IO for PCI card found\n");
+                       pci_disable_device(hc->pci_dev);
+                       return -EIO;
+               }
+
+               if (!request_region(hc->pci_iobase, 8, "hfcmulti")) {
+                       printk(KERN_WARNING "HFC-multi: failed to request "
+                           "address space at 0x%08lx (internal error)\n",
+                           hc->pci_iobase);
+                       pci_disable_device(hc->pci_dev);
+                       return -EIO;
+               }
+
+               printk(KERN_INFO
+                   "%s %s: defined at IOBASE %#x IRQ %d HZ %d leds-type %d\n",
+                   m->vendor_name, m->card_name, (u_int) hc->pci_iobase,
+                   hc->pci_dev->irq, HZ, hc->leds);
+               pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_REGIO);
+               break;
+       default:
+               printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n");
+               pci_disable_device(hc->pci_dev);
+               return -EIO;
+       }
+
+       pci_set_drvdata(hc->pci_dev, hc);
+
+       /* At this point the needed PCI config is done */
+       /* fifos are still not enabled */
+       return 0;
+}
+
+
+/*
+ * remove port
+ */
+
+static void
+release_port(struct hfc_multi *hc, struct dchannel *dch)
+{
+       int     pt, ci, i = 0;
+       u_long  flags;
+       struct bchannel *pb;
+
+       ci = dch->slot;
+       pt = hc->chan[ci].port;
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: entered for port %d\n",
+                       __func__, pt + 1);
+
+       if (pt >= hc->ports) {
+               printk(KERN_WARNING "%s: ERROR port out of range (%d).\n",
+                    __func__, pt + 1);
+               return;
+       }
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: releasing port=%d\n",
+                   __func__, pt + 1);
+
+       if (dch->dev.D.protocol == ISDN_P_TE_S0)
+               l1_event(dch->l1, CLOSE_CHANNEL);
+
+       hc->chan[ci].dch = NULL;
+
+       if (hc->created[pt]) {
+               hc->created[pt] = 0;
+               mISDN_unregister_device(&dch->dev);
+       }
+
+       spin_lock_irqsave(&hc->lock, flags);
+
+       if (dch->timer.function) {
+               del_timer(&dch->timer);
+               dch->timer.function = NULL;
+       }
+
+       if (hc->type == 1) { /* E1 */
+               /* remove sync */
+               if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+                       hc->syncronized = 0;
+                       plxsd_checksync(hc, 1);
+               }
+               /* free channels */
+               for (i = 0; i <= 31; i++) {
+                       if (hc->chan[i].bch) {
+                               if (debug & DEBUG_HFCMULTI_INIT)
+                                       printk(KERN_DEBUG
+                                           "%s: free port %d channel %d\n",
+                                           __func__, hc->chan[i].port+1, i);
+                               pb = hc->chan[i].bch;
+                               hc->chan[i].bch = NULL;
+                               spin_unlock_irqrestore(&hc->lock, flags);
+                               mISDN_freebchannel(pb);
+                               kfree(pb);
+                               kfree(hc->chan[i].coeff);
+                               spin_lock_irqsave(&hc->lock, flags);
+                       }
+               }
+       } else {
+               /* remove sync */
+               if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+                       hc->syncronized &=
+                          ~(1 << hc->chan[ci].port);
+                       plxsd_checksync(hc, 1);
+               }
+               /* free channels */
+               if (hc->chan[ci - 2].bch) {
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_DEBUG
+                                   "%s: free port %d channel %d\n",
+                                   __func__, hc->chan[ci - 2].port+1,
+                                   ci - 2);
+                       pb = hc->chan[ci - 2].bch;
+                       hc->chan[ci - 2].bch = NULL;
+                       spin_unlock_irqrestore(&hc->lock, flags);
+                       mISDN_freebchannel(pb);
+                       kfree(pb);
+                       kfree(hc->chan[ci - 2].coeff);
+                       spin_lock_irqsave(&hc->lock, flags);
+               }
+               if (hc->chan[ci - 1].bch) {
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_DEBUG
+                                   "%s: free port %d channel %d\n",
+                                   __func__, hc->chan[ci - 1].port+1,
+                                   ci - 1);
+                       pb = hc->chan[ci - 1].bch;
+                       hc->chan[ci - 1].bch = NULL;
+                       spin_unlock_irqrestore(&hc->lock, flags);
+                       mISDN_freebchannel(pb);
+                       kfree(pb);
+                       kfree(hc->chan[ci - 1].coeff);
+                       spin_lock_irqsave(&hc->lock, flags);
+               }
+       }
+
+       spin_unlock_irqrestore(&hc->lock, flags);
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: free port %d channel D\n", __func__, pt);
+       mISDN_freedchannel(dch);
+       kfree(dch);
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: done!\n", __func__);
+}
+
+static void
+release_card(struct hfc_multi *hc)
+{
+       u_long  flags;
+       int     ch;
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_WARNING "%s: release card (%d) entered\n",
+                   __func__, hc->id);
+
+       spin_lock_irqsave(&hc->lock, flags);
+       disable_hwirq(hc);
+       spin_unlock_irqrestore(&hc->lock, flags);
+
+       udelay(1000);
+
+       /* dimm leds */
+       if (hc->leds)
+               hfcmulti_leds(hc);
+
+       /* disable D-channels & B-channels */
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: disable all channels (d and b)\n",
+                   __func__);
+       for (ch = 0; ch <= 31; ch++) {
+               if (hc->chan[ch].dch)
+                       release_port(hc, hc->chan[ch].dch);
+       }
+
+       /* release hardware & irq */
+       if (hc->irq) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_WARNING "%s: free irq %d\n",
+                           __func__, hc->irq);
+               free_irq(hc->irq, hc);
+               hc->irq = 0;
+
+       }
+       release_io_hfcmulti(hc);
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_WARNING "%s: remove instance from list\n",
+                    __func__);
+       list_del(&hc->list);
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_WARNING "%s: delete instance\n", __func__);
+       if (hc == syncmaster)
+               syncmaster = NULL;
+       kfree(hc);
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_WARNING "%s: card successfully removed\n",
+                   __func__);
+}
+
+static int
+init_e1_port(struct hfc_multi *hc, struct hm_map *m)
+{
+       struct dchannel *dch;
+       struct bchannel *bch;
+       int             ch, ret = 0;
+       char            name[MISDN_MAX_IDLEN];
+
+       dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL);
+       if (!dch)
+               return -ENOMEM;
+       dch->debug = debug;
+       mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change);
+       dch->hw = hc;
+       dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1);
+       dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+           (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+       dch->dev.D.send = handle_dmsg;
+       dch->dev.D.ctrl = hfcm_dctrl;
+       dch->dev.nrbchan = (hc->dslot)?30:31;
+       dch->slot = hc->dslot;
+       hc->chan[hc->dslot].dch = dch;
+       hc->chan[hc->dslot].port = 0;
+       hc->chan[hc->dslot].nt_timer = -1;
+       for (ch = 1; ch <= 31; ch++) {
+               if (ch == hc->dslot) /* skip dchannel */
+                       continue;
+               bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL);
+               if (!bch) {
+                       printk(KERN_ERR "%s: no memory for bchannel\n",
+                           __func__);
+                       ret = -ENOMEM;
+                       goto free_chan;
+               }
+               hc->chan[ch].coeff = kzalloc(512, GFP_KERNEL);
+               if (!hc->chan[ch].coeff) {
+                       printk(KERN_ERR "%s: no memory for coeffs\n",
+                           __func__);
+                       ret = -ENOMEM;
+                       goto free_chan;
+               }
+               bch->nr = ch;
+               bch->slot = ch;
+               bch->debug = debug;
+               mISDN_initbchannel(bch, MAX_DATA_MEM);
+               bch->hw = hc;
+               bch->ch.send = handle_bmsg;
+               bch->ch.ctrl = hfcm_bctrl;
+               bch->ch.nr = ch;
+               list_add(&bch->ch.list, &dch->dev.bchannels);
+               hc->chan[ch].bch = bch;
+               hc->chan[ch].port = 0;
+               test_and_set_bit(bch->nr, &dch->dev.channelmap[0]);
+       }
+       /* set optical line type */
+       if (port[Port_cnt] & 0x001) {
+               if (!m->opticalsupport)  {
+                       printk(KERN_INFO
+                           "This board has no optical "
+                           "support\n");
+               } else {
+                       if (debug & DEBUG_HFCMULTI_INIT)
+                               printk(KERN_DEBUG
+                                   "%s: PORT set optical "
+                                   "interfacs: card(%d) "
+                                   "port(%d)\n",
+                                   __func__,
+                                   HFC_cnt + 1, 1);
+                       test_and_set_bit(HFC_CFG_OPTICAL,
+                           &hc->chan[hc->dslot].cfg);
+               }
+       }
+       /* set LOS report */
+       if (port[Port_cnt] & 0x004) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: PORT set "
+                           "LOS report: card(%d) port(%d)\n",
+                           __func__, HFC_cnt + 1, 1);
+               test_and_set_bit(HFC_CFG_REPORT_LOS,
+                   &hc->chan[hc->dslot].cfg);
+       }
+       /* set AIS report */
+       if (port[Port_cnt] & 0x008) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: PORT set "
+                           "AIS report: card(%d) port(%d)\n",
+                           __func__, HFC_cnt + 1, 1);
+               test_and_set_bit(HFC_CFG_REPORT_AIS,
+                   &hc->chan[hc->dslot].cfg);
+       }
+       /* set SLIP report */
+       if (port[Port_cnt] & 0x010) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG
+                           "%s: PORT set SLIP report: "
+                           "card(%d) port(%d)\n",
+                           __func__, HFC_cnt + 1, 1);
+               test_and_set_bit(HFC_CFG_REPORT_SLIP,
+                   &hc->chan[hc->dslot].cfg);
+       }
+       /* set RDI report */
+       if (port[Port_cnt] & 0x020) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG
+                           "%s: PORT set RDI report: "
+                           "card(%d) port(%d)\n",
+                           __func__, HFC_cnt + 1, 1);
+               test_and_set_bit(HFC_CFG_REPORT_RDI,
+                   &hc->chan[hc->dslot].cfg);
+       }
+       /* set CRC-4 Mode */
+       if (!(port[Port_cnt] & 0x100)) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: PORT turn on CRC4 report:"
+                               " card(%d) port(%d)\n",
+                               __func__, HFC_cnt + 1, 1);
+               test_and_set_bit(HFC_CFG_CRC4,
+                   &hc->chan[hc->dslot].cfg);
+       } else {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: PORT turn off CRC4"
+                               " report: card(%d) port(%d)\n",
+                               __func__, HFC_cnt + 1, 1);
+       }
+       /* set forced clock */
+       if (port[Port_cnt] & 0x0200) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: PORT force getting clock from "
+                               "E1: card(%d) port(%d)\n",
+                               __func__, HFC_cnt + 1, 1);
+               test_and_set_bit(HFC_CHIP_E1CLOCK_GET, &hc->chip);
+       } else
+       if (port[Port_cnt] & 0x0400) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: PORT force putting clock to "
+                               "E1: card(%d) port(%d)\n",
+                               __func__, HFC_cnt + 1, 1);
+               test_and_set_bit(HFC_CHIP_E1CLOCK_PUT, &hc->chip);
+       }
+       /* set JATT PLL */
+       if (port[Port_cnt] & 0x0800) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG "%s: PORT disable JATT PLL on "
+                               "E1: card(%d) port(%d)\n",
+                               __func__, HFC_cnt + 1, 1);
+               test_and_set_bit(HFC_CHIP_RX_SYNC, &hc->chip);
+       }
+       /* set elastic jitter buffer */
+       if (port[Port_cnt] & 0x3000) {
+               hc->chan[hc->dslot].jitter = (port[Port_cnt]>>12) & 0x3;
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG
+                           "%s: PORT set elastic "
+                           "buffer to %d: card(%d) port(%d)\n",
+                           __func__, hc->chan[hc->dslot].jitter,
+                           HFC_cnt + 1, 1);
+       } else
+               hc->chan[hc->dslot].jitter = 2; /* default */
+       snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1);
+       ret = mISDN_register_device(&dch->dev, name);
+       if (ret)
+               goto free_chan;
+       hc->created[0] = 1;
+       return ret;
+free_chan:
+       release_port(hc, dch);
+       return ret;
+}
+
+static int
+init_multi_port(struct hfc_multi *hc, int pt)
+{
+       struct dchannel *dch;
+       struct bchannel *bch;
+       int             ch, i, ret = 0;
+       char            name[MISDN_MAX_IDLEN];
+
+       dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL);
+       if (!dch)
+               return -ENOMEM;
+       dch->debug = debug;
+       mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change);
+       dch->hw = hc;
+       dch->dev.Dprotocols = (1 << ISDN_P_TE_S0) | (1 << ISDN_P_NT_S0);
+       dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+           (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+       dch->dev.D.send = handle_dmsg;
+       dch->dev.D.ctrl = hfcm_dctrl;
+       dch->dev.nrbchan = 2;
+       i = pt << 2;
+       dch->slot = i + 2;
+       hc->chan[i + 2].dch = dch;
+       hc->chan[i + 2].port = pt;
+       hc->chan[i + 2].nt_timer = -1;
+       for (ch = 0; ch < dch->dev.nrbchan; ch++) {
+               bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL);
+               if (!bch) {
+                       printk(KERN_ERR "%s: no memory for bchannel\n",
+                           __func__);
+                       ret = -ENOMEM;
+                       goto free_chan;
+               }
+               hc->chan[i + ch].coeff = kzalloc(512, GFP_KERNEL);
+               if (!hc->chan[i + ch].coeff) {
+                       printk(KERN_ERR "%s: no memory for coeffs\n",
+                           __func__);
+                       ret = -ENOMEM;
+                       goto free_chan;
+               }
+               bch->nr = ch + 1;
+               bch->slot = i + ch;
+               bch->debug = debug;
+               mISDN_initbchannel(bch, MAX_DATA_MEM);
+               bch->hw = hc;
+               bch->ch.send = handle_bmsg;
+               bch->ch.ctrl = hfcm_bctrl;
+               bch->ch.nr = ch + 1;
+               list_add(&bch->ch.list, &dch->dev.bchannels);
+               hc->chan[i + ch].bch = bch;
+               hc->chan[i + ch].port = pt;
+               test_and_set_bit(bch->nr, &dch->dev.channelmap[0]);
+       }
+       /* set master clock */
+       if (port[Port_cnt] & 0x001) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG
+                           "%s: PROTOCOL set master clock: "
+                           "card(%d) port(%d)\n",
+                           __func__, HFC_cnt + 1, pt + 1);
+               if (dch->dev.D.protocol != ISDN_P_TE_S0) {
+                       printk(KERN_ERR "Error: Master clock "
+                           "for port(%d) of card(%d) is only"
+                           " possible with TE-mode\n",
+                           pt + 1, HFC_cnt + 1);
+                       ret = -EINVAL;
+                       goto free_chan;
+               }
+               if (hc->masterclk >= 0) {
+                       printk(KERN_ERR "Error: Master clock "
+                           "for port(%d) of card(%d) already "
+                           "defined for port(%d)\n",
+                           pt + 1, HFC_cnt + 1, hc->masterclk+1);
+                       ret = -EINVAL;
+                       goto free_chan;
+               }
+               hc->masterclk = pt;
+       }
+       /* set transmitter line to non capacitive */
+       if (port[Port_cnt] & 0x002) {
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG
+                           "%s: PROTOCOL set non capacitive "
+                           "transmitter: card(%d) port(%d)\n",
+                           __func__, HFC_cnt + 1, pt + 1);
+               test_and_set_bit(HFC_CFG_NONCAP_TX,
+                   &hc->chan[i + 2].cfg);
+       }
+       /* disable E-channel */
+       if (port[Port_cnt] & 0x004) {
+       if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG
+                           "%s: PROTOCOL disable E-channel: "
+                           "card(%d) port(%d)\n",
+                           __func__, HFC_cnt + 1, pt + 1);
+               test_and_set_bit(HFC_CFG_DIS_ECHANNEL,
+                   &hc->chan[i + 2].cfg);
+       }
+       snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d/%d",
+               hc->type, HFC_cnt + 1, pt + 1);
+       ret = mISDN_register_device(&dch->dev, name);
+       if (ret)
+               goto free_chan;
+       hc->created[pt] = 1;
+       return ret;
+free_chan:
+       release_port(hc, dch);
+       return ret;
+}
+
+static int
+hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       struct hm_map   *m = (struct hm_map *)ent->driver_data;
+       int             ret_err = 0;
+       int             pt;
+       struct hfc_multi        *hc;
+       u_long          flags;
+       u_char          dips = 0, pmj = 0; /* dip settings, port mode Jumpers */
+
+       if (HFC_cnt >= MAX_CARDS) {
+               printk(KERN_ERR "too many cards (max=%d).\n",
+                       MAX_CARDS);
+               return -EINVAL;
+       }
+       if ((type[HFC_cnt] & 0xff) && (type[HFC_cnt] & 0xff) != m->type) {
+               printk(KERN_WARNING "HFC-MULTI: Card '%s:%s' type %d found but "
+                   "type[%d] %d was supplied as module parameter\n",
+                   m->vendor_name, m->card_name, m->type, HFC_cnt,
+                   type[HFC_cnt] & 0xff);
+               printk(KERN_WARNING "HFC-MULTI: Load module without parameters "
+                       "first, to see cards and their types.");
+               return -EINVAL;
+       }
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: Registering %s:%s chip type %d (0x%x)\n",
+                   __func__, m->vendor_name, m->card_name, m->type,
+                   type[HFC_cnt]);
+
+       /* allocate card+fifo structure */
+       hc = kzalloc(sizeof(struct hfc_multi), GFP_KERNEL);
+       if (!hc) {
+               printk(KERN_ERR "No kmem for HFC-Multi card\n");
+               return -ENOMEM;
+       }
+       spin_lock_init(&hc->lock);
+       hc->mtyp = m;
+       hc->type =  m->type;
+       hc->ports = m->ports;
+       hc->id = HFC_cnt;
+       hc->pcm = pcm[HFC_cnt];
+       hc->io_mode = iomode[HFC_cnt];
+       if (dslot[HFC_cnt] < 0) {
+               hc->dslot = 0;
+               printk(KERN_INFO "HFC-E1 card has disabled D-channel, but "
+                       "31 B-channels\n");
+       } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32) {
+               hc->dslot = dslot[HFC_cnt];
+               printk(KERN_INFO "HFC-E1 card has alternating D-channel on "
+                       "time slot %d\n", dslot[HFC_cnt]);
+       } else
+               hc->dslot = 16;
+
+       /* set chip specific features */
+       hc->masterclk = -1;
+       if (type[HFC_cnt] & 0x100) {
+               test_and_set_bit(HFC_CHIP_ULAW, &hc->chip);
+               silence = 0xff; /* ulaw silence */
+       } else
+               silence = 0x2a; /* alaw silence */
+       if (!(type[HFC_cnt] & 0x200))
+               test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
+
+       if (type[HFC_cnt] & 0x800)
+               test_and_set_bit(HFC_CHIP_PCM_SLAVE, &hc->chip);
+       if (type[HFC_cnt] & 0x1000) {
+               test_and_set_bit(HFC_CHIP_PCM_MASTER, &hc->chip);
+               test_and_clear_bit(HFC_CHIP_PCM_SLAVE, &hc->chip);
+       }
+       if (type[HFC_cnt] & 0x4000)
+               test_and_set_bit(HFC_CHIP_EXRAM_128, &hc->chip);
+       if (type[HFC_cnt] & 0x8000)
+               test_and_set_bit(HFC_CHIP_EXRAM_512, &hc->chip);
+       hc->slots = 32;
+       if (type[HFC_cnt] & 0x10000)
+               hc->slots = 64;
+       if (type[HFC_cnt] & 0x20000)
+               hc->slots = 128;
+       if (type[HFC_cnt] & 0x80000) {
+               test_and_set_bit(HFC_CHIP_WATCHDOG, &hc->chip);
+               hc->wdcount = 0;
+               hc->wdbyte = V_GPIO_OUT2;
+               printk(KERN_NOTICE "Watchdog enabled\n");
+       }
+
+       /* setup pci, hc->slots may change due to PLXSD */
+       ret_err = setup_pci(hc, pdev, ent);
+       if (ret_err) {
+               if (hc == syncmaster)
+                       syncmaster = NULL;
+               kfree(hc);
+               return ret_err;
+       }
+
+       /* crate channels */
+       for (pt = 0; pt < hc->ports; pt++) {
+               if (Port_cnt >= MAX_PORTS) {
+                       printk(KERN_ERR "too many ports (max=%d).\n",
+                               MAX_PORTS);
+                       ret_err = -EINVAL;
+                       goto free_card;
+               }
+               if (hc->type == 1)
+                       ret_err = init_e1_port(hc, m);
+               else
+                       ret_err = init_multi_port(hc, pt);
+               if (debug & DEBUG_HFCMULTI_INIT)
+                       printk(KERN_DEBUG
+                           "%s: Registering D-channel, card(%d) port(%d)"
+                           "result %d\n",
+                           __func__, HFC_cnt + 1, pt, ret_err);
+
+               if (ret_err) {
+                       while (pt) { /* release already registered ports */
+                               pt--;
+                               release_port(hc, hc->chan[(pt << 2) + 2].dch);
+                       }
+                       goto free_card;
+               }
+               Port_cnt++;
+       }
+
+       /* disp switches */
+       switch (m->dip_type) {
+       case DIP_4S:
+               /*
+                * get DIP Setting for beroNet 1S/2S/4S cards
+                *  check if Port Jumper config matches
+                * module param 'protocol'
+                * DIP Setting: (collect GPIO 13/14/15 (R_GPIO_IN1) +
+                * GPI 19/23 (R_GPI_IN2))
+                */
+               dips = ((~HFC_inb(hc, R_GPIO_IN1) & 0xE0) >> 5) |
+                       ((~HFC_inb(hc, R_GPI_IN2) & 0x80) >> 3) |
+                       (~HFC_inb(hc, R_GPI_IN2) & 0x08);
+
+               /* Port mode (TE/NT) jumpers */
+               pmj = ((HFC_inb(hc, R_GPI_IN3) >> 4)  & 0xf);
+
+               if (test_bit(HFC_CHIP_B410P, &hc->chip))
+                       pmj = ~pmj & 0xf;
+
+               printk(KERN_INFO "%s: %s DIPs(0x%x) jumpers(0x%x)\n",
+                       m->vendor_name, m->card_name, dips, pmj);
+               break;
+       case DIP_8S:
+               /*
+                * get DIP Setting for beroNet 8S0+ cards
+                *
+                * enable PCI auxbridge function
+                */
+               HFC_outb(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK);
+               /* prepare access to auxport */
+               outw(0x4000, hc->pci_iobase + 4);
+               /*
+                * some dummy reads are required to
+                * read valid DIP switch data
+                */
+               dips = inb(hc->pci_iobase);
+               dips = inb(hc->pci_iobase);
+               dips = inb(hc->pci_iobase);
+               dips = ~inb(hc->pci_iobase) & 0x3F;
+               outw(0x0, hc->pci_iobase + 4);
+               /* disable PCI auxbridge function */
+               HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK);
+               printk(KERN_INFO "%s: %s DIPs(0x%x)\n",
+                   m->vendor_name, m->card_name, dips);
+               break;
+       case DIP_E1:
+               /*
+                * get DIP Setting for beroNet E1 cards
+                * DIP Setting: collect GPI 4/5/6/7 (R_GPI_IN0)
+                */
+               dips = (~HFC_inb(hc, R_GPI_IN0) & 0xF0)>>4;
+               printk(KERN_INFO "%s: %s DIPs(0x%x)\n",
+                   m->vendor_name, m->card_name, dips);
+               break;
+       }
+
+       /* add to list */
+       spin_lock_irqsave(&HFClock, flags);
+       list_add_tail(&hc->list, &HFClist);
+       spin_unlock_irqrestore(&HFClock, flags);
+
+       /* initialize hardware */
+       ret_err = init_card(hc);
+       if (ret_err) {
+               printk(KERN_ERR "init card returns %d\n", ret_err);
+               release_card(hc);
+               return ret_err;
+       }
+
+       /* start IRQ and return */
+       spin_lock_irqsave(&hc->lock, flags);
+       enable_hwirq(hc);
+       spin_unlock_irqrestore(&hc->lock, flags);
+       return 0;
+
+free_card:
+       release_io_hfcmulti(hc);
+       if (hc == syncmaster)
+               syncmaster = NULL;
+       kfree(hc);
+       return ret_err;
+}
+
+static void __devexit hfc_remove_pci(struct pci_dev *pdev)
+{
+       struct hfc_multi        *card = pci_get_drvdata(pdev);
+       u_long                  flags;
+
+       if (debug)
+               printk(KERN_INFO "removing hfc_multi card vendor:%x "
+                   "device:%x subvendor:%x subdevice:%x\n",
+                   pdev->vendor, pdev->device,
+                   pdev->subsystem_vendor, pdev->subsystem_device);
+
+       if (card) {
+               spin_lock_irqsave(&HFClock, flags);
+               release_card(card);
+               spin_unlock_irqrestore(&HFClock, flags);
+       }  else {
+               if (debug)
+                       printk(KERN_WARNING "%s: drvdata allready removed\n",
+                           __func__);
+       }
+}
+
+#define        VENDOR_CCD      "Cologne Chip AG"
+#define        VENDOR_BN       "beroNet GmbH"
+#define        VENDOR_DIG      "Digium Inc."
+#define VENDOR_JH      "Junghanns.NET GmbH"
+#define VENDOR_PRIM    "PrimuX"
+
+static const struct hm_map hfcm_map[] = {
+/*0*/  {VENDOR_BN, "HFC-1S Card (mini PCI)", 4, 1, 1, 3, 0, DIP_4S, 0},
+/*1*/  {VENDOR_BN, "HFC-2S Card", 4, 2, 1, 3, 0, DIP_4S},
+/*2*/  {VENDOR_BN, "HFC-2S Card (mini PCI)", 4, 2, 1, 3, 0, DIP_4S, 0},
+/*3*/  {VENDOR_BN, "HFC-4S Card", 4, 4, 1, 2, 0, DIP_4S, 0},
+/*4*/  {VENDOR_BN, "HFC-4S Card (mini PCI)", 4, 4, 1, 2, 0, 0, 0},
+/*5*/  {VENDOR_CCD, "HFC-4S Eval (old)", 4, 4, 0, 0, 0, 0, 0},
+/*6*/  {VENDOR_CCD, "HFC-4S IOB4ST", 4, 4, 1, 2, 0, 0, 0},
+/*7*/  {VENDOR_CCD, "HFC-4S", 4, 4, 1, 2, 0, 0, 0},
+/*8*/  {VENDOR_DIG, "HFC-4S Card", 4, 4, 0, 2, 0, 0, HFC_IO_MODE_REGIO},
+/*9*/  {VENDOR_CCD, "HFC-4S Swyx 4xS0 SX2 QuadBri", 4, 4, 1, 2, 0, 0, 0},
+/*10*/ {VENDOR_JH, "HFC-4S (junghanns 2.0)", 4, 4, 1, 2, 0, 0, 0},
+/*11*/ {VENDOR_PRIM, "HFC-2S Primux Card", 4, 2, 0, 0, 0, 0, 0},
+
+/*12*/ {VENDOR_BN, "HFC-8S Card", 8, 8, 1, 0, 0, 0, 0},
+/*13*/ {VENDOR_BN, "HFC-8S Card (+)", 8, 8, 1, 8, 0, DIP_8S,
+               HFC_IO_MODE_REGIO},
+/*14*/ {VENDOR_CCD, "HFC-8S Eval (old)", 8, 8, 0, 0, 0, 0, 0},
+/*15*/ {VENDOR_CCD, "HFC-8S IOB4ST Recording", 8, 8, 1, 0, 0, 0, 0},
+
+/*16*/ {VENDOR_CCD, "HFC-8S IOB8ST", 8, 8, 1, 0, 0, 0, 0},
+/*17*/ {VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0},
+/*18*/ {VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0},
+
+/*19*/ {VENDOR_BN, "HFC-E1 Card", 1, 1, 0, 1, 0, DIP_E1, 0},
+/*20*/ {VENDOR_BN, "HFC-E1 Card (mini PCI)", 1, 1, 0, 1, 0, 0, 0},
+/*21*/ {VENDOR_BN, "HFC-E1+ Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0},
+/*22*/ {VENDOR_BN, "HFC-E1 Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0},
+
+/*23*/ {VENDOR_CCD, "HFC-E1 Eval (old)", 1, 1, 0, 0, 0, 0, 0},
+/*24*/ {VENDOR_CCD, "HFC-E1 IOB1E1", 1, 1, 0, 1, 0, 0, 0},
+/*25*/ {VENDOR_CCD, "HFC-E1", 1, 1, 0, 1, 0, 0, 0},
+
+/*26*/ {VENDOR_CCD, "HFC-4S Speech Design", 4, 4, 0, 0, 0, 0,
+               HFC_IO_MODE_PLXSD},
+/*27*/ {VENDOR_CCD, "HFC-E1 Speech Design", 1, 1, 0, 0, 0, 0,
+               HFC_IO_MODE_PLXSD},
+/*28*/ {VENDOR_CCD, "HFC-4S OpenVox", 4, 4, 1, 0, 0, 0, 0},
+/*29*/ {VENDOR_CCD, "HFC-2S OpenVox", 4, 2, 1, 0, 0, 0, 0},
+/*30*/ {VENDOR_CCD, "HFC-8S OpenVox", 8, 8, 1, 0, 0, 0, 0},
+};
+
+#undef H
+#define H(x)   ((unsigned long)&hfcm_map[x])
+static struct pci_device_id hfmultipci_ids[] __devinitdata = {
+
+       /* Cards with HFC-4S Chip */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_BN1SM, 0, 0, H(0)}, /* BN1S mini PCI */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_BN2S, 0, 0, H(1)}, /* BN2S */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_BN2SM, 0, 0, H(2)}, /* BN2S mini PCI */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_BN4S, 0, 0, H(3)}, /* BN4S */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_BN4SM, 0, 0, H(4)}, /* BN4S mini PCI */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_DEVICE_ID_CCD_HFC4S, 0, 0, H(5)}, /* Old Eval */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_IOB4ST, 0, 0, H(6)}, /* IOB4ST */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_HFC4S, 0, 0, H(7)}, /* 4S */
+       { PCI_VENDOR_ID_DIGIUM, PCI_DEVICE_ID_DIGIUM_HFC4S,
+               PCI_VENDOR_ID_DIGIUM, PCI_DEVICE_ID_DIGIUM_HFC4S, 0, 0, H(8)},
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_SWYX4S, 0, 0, H(9)}, /* 4S Swyx */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_JH4S20, 0, 0, H(10)},
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_PMX2S, 0, 0, H(11)}, /* Primux */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_OV4S, 0, 0, H(28)}, /* OpenVox 4 */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_OV2S, 0, 0, H(29)}, /* OpenVox 2 */
+
+       /* Cards with HFC-8S Chip */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
+       PCI_SUBDEVICE_ID_CCD_BN8S, 0, 0, H(12)}, /* BN8S */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
+       PCI_SUBDEVICE_ID_CCD_BN8SP, 0, 0, H(13)}, /* BN8S+ */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
+       PCI_DEVICE_ID_CCD_HFC8S, 0, 0, H(14)}, /* old Eval */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
+       PCI_SUBDEVICE_ID_CCD_IOB8STR, 0, 0, H(15)},
+           /* IOB8ST Recording */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_IOB8ST, 0, 0, H(16)}, /* IOB8ST  */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_IOB8ST_1, 0, 0, H(17)}, /* IOB8ST  */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_HFC8S, 0, 0, H(18)}, /* 8S */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_OV8S, 0, 0, H(30)}, /* OpenVox 8 */
+
+
+       /* Cards with HFC-E1 Chip */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_BNE1, 0, 0, H(19)}, /* BNE1 */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_BNE1M, 0, 0, H(20)}, /* BNE1 mini PCI */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_BNE1DP, 0, 0, H(21)}, /* BNE1 + (Dual) */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_BNE1D, 0, 0, H(22)}, /* BNE1 (Dual) */
+
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD,
+               PCI_DEVICE_ID_CCD_HFCE1, 0, 0, H(23)}, /* Old Eval */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_IOB1E1, 0, 0, H(24)}, /* IOB1E1 */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_HFCE1, 0, 0, H(25)}, /* E1 */
+
+       { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_SPD4S, 0, 0, H(26)}, /* PLX PCI Bridge */
+       { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_CCD,
+               PCI_SUBDEVICE_ID_CCD_SPDE1, 0, 0, H(27)}, /* PLX PCI Bridge */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, 0},
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, 0},
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, 0},
+       {0, }
+};
+#undef H
+
+MODULE_DEVICE_TABLE(pci, hfmultipci_ids);
+
+static int
+hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       struct hm_map   *m = (struct hm_map *)ent->driver_data;
+       int             ret;
+
+       if (m == NULL) {
+               if (ent->vendor == PCI_VENDOR_ID_CCD)
+                       if (ent->device == PCI_DEVICE_ID_CCD_HFC4S ||
+                           ent->device == PCI_DEVICE_ID_CCD_HFC8S ||
+                           ent->device == PCI_DEVICE_ID_CCD_HFCE1)
+                               printk(KERN_ERR
+                                   "unknown HFC multiport controller "
+                                   "(vendor:%x device:%x subvendor:%x "
+                                   "subdevice:%x) Please contact the "
+                                   "driver maintainer for support.\n",
+                                   ent->vendor, ent->device,
+                                   ent->subvendor, ent->subdevice);
+               return -ENODEV;
+       }
+       ret = hfcmulti_init(pdev, ent);
+       if (ret)
+               return ret;
+       HFC_cnt++;
+       printk(KERN_INFO "%d devices registered\n", HFC_cnt);
+       return 0;
+}
+
+static struct pci_driver hfcmultipci_driver = {
+       .name           = "hfc_multi",
+       .probe          = hfcmulti_probe,
+       .remove         = __devexit_p(hfc_remove_pci),
+       .id_table       = hfmultipci_ids,
+};
+
+static void __exit
+HFCmulti_cleanup(void)
+{
+       struct hfc_multi *card, *next;
+
+       /* unload interrupt function symbol */
+       if (hfc_interrupt)
+               symbol_put(ztdummy_extern_interrupt);
+       if (register_interrupt)
+               symbol_put(ztdummy_register_interrupt);
+       if (unregister_interrupt) {
+               if (interrupt_registered) {
+                       interrupt_registered = 0;
+                       unregister_interrupt();
+               }
+               symbol_put(ztdummy_unregister_interrupt);
+       }
+
+       list_for_each_entry_safe(card, next, &HFClist, list)
+               release_card(card);
+       /* get rid of all devices of this driver */
+       pci_unregister_driver(&hfcmultipci_driver);
+}
+
+static int __init
+HFCmulti_init(void)
+{
+       int err;
+
+#ifdef IRQ_DEBUG
+       printk(KERN_ERR "%s: IRQ_DEBUG IS ENABLED!\n", __func__);
+#endif
+
+       spin_lock_init(&HFClock);
+       spin_lock_init(&plx_lock);
+
+       if (debug & DEBUG_HFCMULTI_INIT)
+               printk(KERN_DEBUG "%s: init entered\n", __func__);
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+       hfc_interrupt = symbol_get(ztdummy_extern_interrupt);
+       register_interrupt = symbol_get(ztdummy_register_interrupt);
+       unregister_interrupt = symbol_get(ztdummy_unregister_interrupt);
+       printk(KERN_INFO "mISDN: HFC-multi driver %s\n",
+           hfcmulti_revision);
+
+       switch (poll) {
+       case 0:
+               poll_timer = 6;
+               poll = 128;
+               break;
+               /*
+                * wenn dieses break nochmal verschwindet,
+                * gibt es heisse ohren :-)
+                * "without the break you will get hot ears ???"
+                */
+       case 8:
+               poll_timer = 2;
+               break;
+       case 16:
+               poll_timer = 3;
+               break;
+       case 32:
+               poll_timer = 4;
+               break;
+       case 64:
+               poll_timer = 5;
+               break;
+       case 128:
+               poll_timer = 6;
+               break;
+       case 256:
+               poll_timer = 7;
+               break;
+       default:
+               printk(KERN_ERR
+                   "%s: Wrong poll value (%d).\n", __func__, poll);
+               err = -EINVAL;
+               return err;
+
+       }
+
+       err = pci_register_driver(&hfcmultipci_driver);
+       if (err < 0) {
+               printk(KERN_ERR "error registering pci driver: %x\n", err);
+               if (hfc_interrupt)
+                       symbol_put(ztdummy_extern_interrupt);
+               if (register_interrupt)
+                       symbol_put(ztdummy_register_interrupt);
+               if (unregister_interrupt) {
+                       if (interrupt_registered) {
+                               interrupt_registered = 0;
+                               unregister_interrupt();
+                       }
+                       symbol_put(ztdummy_unregister_interrupt);
+               }
+               return err;
+       }
+       return 0;
+}
+
+
+module_init(HFCmulti_init);
+module_exit(HFCmulti_cleanup);
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
new file mode 100644 (file)
index 0000000..3231814
--- /dev/null
@@ -0,0 +1,2255 @@
+/*
+ *
+ * hfcpci.c     low level driver for CCD's hfc-pci based cards
+ *
+ * Author     Werner Cornelius (werner@isdn4linux.de)
+ *            based on existing driver for CCD hfc ISA cards
+ *            type approval valid for HFC-S PCI A based card
+ *
+ * Copyright 1999  by Werner Cornelius (werner@isdn-development.de)
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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/pci.h>
+#include <linux/delay.h>
+#include <linux/mISDNhw.h>
+
+#include "hfc_pci.h"
+
+static const char *hfcpci_revision = "2.0";
+
+#define MAX_CARDS      8
+static int HFC_cnt;
+static uint debug;
+
+MODULE_AUTHOR("Karsten Keil");
+MODULE_LICENSE("GPL");
+module_param(debug, uint, 0);
+
+static LIST_HEAD(HFClist);
+DEFINE_RWLOCK(HFClock);
+
+enum {
+       HFC_CCD_2BD0,
+       HFC_CCD_B000,
+       HFC_CCD_B006,
+       HFC_CCD_B007,
+       HFC_CCD_B008,
+       HFC_CCD_B009,
+       HFC_CCD_B00A,
+       HFC_CCD_B00B,
+       HFC_CCD_B00C,
+       HFC_CCD_B100,
+       HFC_CCD_B700,
+       HFC_CCD_B701,
+       HFC_ASUS_0675,
+       HFC_BERKOM_A1T,
+       HFC_BERKOM_TCONCEPT,
+       HFC_ANIGMA_MC145575,
+       HFC_ZOLTRIX_2BD0,
+       HFC_DIGI_DF_M_IOM2_E,
+       HFC_DIGI_DF_M_E,
+       HFC_DIGI_DF_M_IOM2_A,
+       HFC_DIGI_DF_M_A,
+       HFC_ABOCOM_2BD1,
+       HFC_SITECOM_DC105V2,
+};
+
+struct hfcPCI_hw {
+       unsigned char           cirm;
+       unsigned char           ctmt;
+       unsigned char           clkdel;
+       unsigned char           states;
+       unsigned char           conn;
+       unsigned char           mst_m;
+       unsigned char           int_m1;
+       unsigned char           int_m2;
+       unsigned char           sctrl;
+       unsigned char           sctrl_r;
+       unsigned char           sctrl_e;
+       unsigned char           trm;
+       unsigned char           fifo_en;
+       unsigned char           bswapped;
+       unsigned char           protocol;
+       int                     nt_timer;
+       unsigned char           *pci_io; /* start of PCI IO memory */
+       dma_addr_t              dmahandle;
+       void                    *fifos; /* FIFO memory */
+       int                     last_bfifo_cnt[2];
+           /* marker saving last b-fifo frame count */
+       struct timer_list       timer;
+};
+
+#define        HFC_CFG_MASTER          1
+#define HFC_CFG_SLAVE          2
+#define        HFC_CFG_PCM             3
+#define HFC_CFG_2HFC           4
+#define HFC_CFG_SLAVEHFC       5
+#define HFC_CFG_NEG_F0         6
+#define HFC_CFG_SW_DD_DU       7
+
+#define FLG_HFC_TIMER_T1       16
+#define FLG_HFC_TIMER_T3       17
+
+#define NT_T1_COUNT    1120    /* number of 3.125ms interrupts (3.5s) */
+#define NT_T3_COUNT    31      /* number of 3.125ms interrupts (97 ms) */
+#define CLKDEL_TE      0x0e    /* CLKDEL in TE mode */
+#define CLKDEL_NT      0x6c    /* CLKDEL in NT mode */
+
+
+struct hfc_pci {
+       struct list_head        list;
+       u_char                  subtype;
+       u_char                  chanlimit;
+       u_char                  initdone;
+       u_long                  cfg;
+       u_int                   irq;
+       u_int                   irqcnt;
+       struct pci_dev          *pdev;
+       struct hfcPCI_hw        hw;
+       spinlock_t              lock;   /* card lock */
+       struct dchannel         dch;
+       struct bchannel         bch[2];
+};
+
+/* Interface functions */
+static void
+enable_hwirq(struct hfc_pci *hc)
+{
+       hc->hw.int_m2 |= HFCPCI_IRQ_ENABLE;
+       Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
+}
+
+static void
+disable_hwirq(struct hfc_pci *hc)
+{
+       hc->hw.int_m2 &= ~((u_char)HFCPCI_IRQ_ENABLE);
+       Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
+}
+
+/*
+ * free hardware resources used by driver
+ */
+static void
+release_io_hfcpci(struct hfc_pci *hc)
+{
+       /* disable memory mapped ports + busmaster */
+       pci_write_config_word(hc->pdev, PCI_COMMAND, 0);
+       del_timer(&hc->hw.timer);
+       pci_free_consistent(hc->pdev, 0x8000, hc->hw.fifos, hc->hw.dmahandle);
+       iounmap((void *)hc->hw.pci_io);
+}
+
+/*
+ * set mode (NT or TE)
+ */
+static void
+hfcpci_setmode(struct hfc_pci *hc)
+{
+       if (hc->hw.protocol == ISDN_P_NT_S0) {
+               hc->hw.clkdel = CLKDEL_NT;      /* ST-Bit delay for NT-Mode */
+               hc->hw.sctrl |= SCTRL_MODE_NT;  /* NT-MODE */
+               hc->hw.states = 1;              /* G1 */
+       } else {
+               hc->hw.clkdel = CLKDEL_TE;      /* ST-Bit delay for TE-Mode */
+               hc->hw.sctrl &= ~SCTRL_MODE_NT; /* TE-MODE */
+               hc->hw.states = 2;              /* F2 */
+       }
+       Write_hfc(hc, HFCPCI_CLKDEL, hc->hw.clkdel);
+       Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | hc->hw.states);
+       udelay(10);
+       Write_hfc(hc, HFCPCI_STATES, hc->hw.states | 0x40); /* Deactivate */
+       Write_hfc(hc, HFCPCI_SCTRL, hc->hw.sctrl);
+}
+
+/*
+ * function called to reset the HFC PCI chip. A complete software reset of chip
+ * and fifos is done.
+ */
+static void
+reset_hfcpci(struct hfc_pci *hc)
+{
+       u_char  val;
+       int     cnt = 0;
+
+       printk(KERN_DEBUG "reset_hfcpci: entered\n");
+       val = Read_hfc(hc, HFCPCI_CHIP_ID);
+       printk(KERN_INFO "HFC_PCI: resetting HFC ChipId(%x)\n", val);
+       /* enable memory mapped ports, disable busmaster */
+       pci_write_config_word(hc->pdev, PCI_COMMAND, PCI_ENA_MEMIO);
+       disable_hwirq(hc);
+       /* enable memory ports + busmaster */
+       pci_write_config_word(hc->pdev, PCI_COMMAND,
+           PCI_ENA_MEMIO + PCI_ENA_MASTER);
+       val = Read_hfc(hc, HFCPCI_STATUS);
+       printk(KERN_DEBUG "HFC-PCI status(%x) before reset\n", val);
+       hc->hw.cirm = HFCPCI_RESET;     /* Reset On */
+       Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       mdelay(10);                     /* Timeout 10ms */
+       hc->hw.cirm = 0;                /* Reset Off */
+       Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
+       val = Read_hfc(hc, HFCPCI_STATUS);
+       printk(KERN_DEBUG "HFC-PCI status(%x) after reset\n", val);
+       while (cnt < 50000) { /* max 50000 us */
+               udelay(5);
+               cnt += 5;
+               val = Read_hfc(hc, HFCPCI_STATUS);
+               if (!(val & 2))
+                       break;
+       }
+       printk(KERN_DEBUG "HFC-PCI status(%x) after %dus\n", val, cnt);
+
+       hc->hw.fifo_en = 0x30;  /* only D fifos enabled */
+
+       hc->hw.bswapped = 0;    /* no exchange */
+       hc->hw.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER;
+       hc->hw.trm = HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */
+       hc->hw.sctrl = 0x40;    /* set tx_lo mode, error in datasheet ! */
+       hc->hw.sctrl_r = 0;
+       hc->hw.sctrl_e = HFCPCI_AUTO_AWAKE;     /* S/T Auto awake */
+       hc->hw.mst_m = 0;
+       if (test_bit(HFC_CFG_MASTER, &hc->cfg))
+               hc->hw.mst_m |= HFCPCI_MASTER;  /* HFC Master Mode */
+       if (test_bit(HFC_CFG_NEG_F0, &hc->cfg))
+               hc->hw.mst_m |= HFCPCI_F0_NEGATIV;
+       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
+       Write_hfc(hc, HFCPCI_TRM, hc->hw.trm);
+       Write_hfc(hc, HFCPCI_SCTRL_E, hc->hw.sctrl_e);
+       Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt);
+
+       hc->hw.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC |
+           HFCPCI_INTS_L1STATE | HFCPCI_INTS_TIMER;
+       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+
+       /* Clear already pending ints */
+       if (Read_hfc(hc, HFCPCI_INT_S1));
+
+       /* set NT/TE mode */
+       hfcpci_setmode(hc);
+
+       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
+       Write_hfc(hc, HFCPCI_SCTRL_R, hc->hw.sctrl_r);
+
+       /*
+        * Init GCI/IOM2 in master mode
+        * Slots 0 and 1 are set for B-chan 1 and 2
+        * D- and monitor/CI channel are not enabled
+        * STIO1 is used as output for data, B1+B2 from ST->IOM+HFC
+        * STIO2 is used as data input, B1+B2 from IOM->ST
+        * ST B-channel send disabled -> continous 1s
+        * The IOM slots are always enabled
+        */
+       if (test_bit(HFC_CFG_PCM, &hc->cfg)) {
+               /* set data flow directions: connect B1,B2: HFC to/from PCM */
+               hc->hw.conn = 0x09;
+       } else {
+               hc->hw.conn = 0x36;     /* set data flow directions */
+               if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg)) {
+                       Write_hfc(hc, HFCPCI_B1_SSL, 0xC0);
+                       Write_hfc(hc, HFCPCI_B2_SSL, 0xC1);
+                       Write_hfc(hc, HFCPCI_B1_RSL, 0xC0);
+                       Write_hfc(hc, HFCPCI_B2_RSL, 0xC1);
+               } else {
+                       Write_hfc(hc, HFCPCI_B1_SSL, 0x80);
+                       Write_hfc(hc, HFCPCI_B2_SSL, 0x81);
+                       Write_hfc(hc, HFCPCI_B1_RSL, 0x80);
+                       Write_hfc(hc, HFCPCI_B2_RSL, 0x81);
+               }
+       }
+       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
+       val = Read_hfc(hc, HFCPCI_INT_S2);
+}
+
+/*
+ * Timer function called when kernel timer expires
+ */
+static void
+hfcpci_Timer(struct hfc_pci *hc)
+{
+       hc->hw.timer.expires = jiffies + 75;
+       /* WD RESET */
+/*
+ *     WriteReg(hc, HFCD_DATA, HFCD_CTMT, hc->hw.ctmt | 0x80);
+ *     add_timer(&hc->hw.timer);
+ */
+}
+
+
+/*
+ * select a b-channel entry matching and active
+ */
+static struct bchannel *
+Sel_BCS(struct hfc_pci *hc, int channel)
+{
+       if (test_bit(FLG_ACTIVE, &hc->bch[0].Flags) &&
+               (hc->bch[0].nr & channel))
+               return &hc->bch[0];
+       else if (test_bit(FLG_ACTIVE, &hc->bch[1].Flags) &&
+               (hc->bch[1].nr & channel))
+               return &hc->bch[1];
+       else
+               return NULL;
+}
+
+/*
+ * clear the desired B-channel rx fifo
+ */
+static void
+hfcpci_clear_fifo_rx(struct hfc_pci *hc, int fifo)
+{
+       u_char          fifo_state;
+       struct bzfifo   *bzr;
+
+       if (fifo) {
+               bzr = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2;
+               fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B2RX;
+       } else {
+               bzr = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1;
+               fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B1RX;
+       }
+       if (fifo_state)
+               hc->hw.fifo_en ^= fifo_state;
+       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
+       hc->hw.last_bfifo_cnt[fifo] = 0;
+       bzr->f1 = MAX_B_FRAMES;
+       bzr->f2 = bzr->f1;      /* init F pointers to remain constant */
+       bzr->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1);
+       bzr->za[MAX_B_FRAMES].z2 = cpu_to_le16(
+           le16_to_cpu(bzr->za[MAX_B_FRAMES].z1));
+       if (fifo_state)
+               hc->hw.fifo_en |= fifo_state;
+       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
+}
+
+/*
+ * clear the desired B-channel tx fifo
+ */
+static void hfcpci_clear_fifo_tx(struct hfc_pci *hc, int fifo)
+{
+       u_char          fifo_state;
+       struct bzfifo   *bzt;
+
+       if (fifo) {
+               bzt = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2;
+               fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B2TX;
+       } else {
+               bzt = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b1;
+               fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B1TX;
+       }
+       if (fifo_state)
+               hc->hw.fifo_en ^= fifo_state;
+       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
+       if (hc->bch[fifo].debug & DEBUG_HW_BCHANNEL)
+               printk(KERN_DEBUG "hfcpci_clear_fifo_tx%d f1(%x) f2(%x) "
+                   "z1(%x) z2(%x) state(%x)\n",
+                   fifo, bzt->f1, bzt->f2,
+                   le16_to_cpu(bzt->za[MAX_B_FRAMES].z1),
+                   le16_to_cpu(bzt->za[MAX_B_FRAMES].z2),
+                   fifo_state);
+       bzt->f2 = MAX_B_FRAMES;
+       bzt->f1 = bzt->f2;      /* init F pointers to remain constant */
+       bzt->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1);
+       bzt->za[MAX_B_FRAMES].z2 = cpu_to_le16(
+           le16_to_cpu(bzt->za[MAX_B_FRAMES].z1 - 1));
+       if (fifo_state)
+               hc->hw.fifo_en |= fifo_state;
+       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
+       if (hc->bch[fifo].debug & DEBUG_HW_BCHANNEL)
+               printk(KERN_DEBUG
+                   "hfcpci_clear_fifo_tx%d f1(%x) f2(%x) z1(%x) z2(%x)\n",
+                   fifo, bzt->f1, bzt->f2,
+                   le16_to_cpu(bzt->za[MAX_B_FRAMES].z1),
+                   le16_to_cpu(bzt->za[MAX_B_FRAMES].z2));
+}
+
+/*
+ * read a complete B-frame out of the buffer
+ */
+static void
+hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
+    u_char *bdata, int count)
+{
+       u_char          *ptr, *ptr1, new_f2;
+       int             total, maxlen, new_z2;
+       struct zt       *zp;
+
+       if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO))
+               printk(KERN_DEBUG "hfcpci_empty_fifo\n");
+       zp = &bz->za[bz->f2];   /* point to Z-Regs */
+       new_z2 = le16_to_cpu(zp->z2) + count;   /* new position in fifo */
+       if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
+               new_z2 -= B_FIFO_SIZE;  /* buffer wrap */
+       new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
+       if ((count > MAX_DATA_SIZE + 3) || (count < 4) ||
+           (*(bdata + (le16_to_cpu(zp->z1) - B_SUB_VAL)))) {
+               if (bch->debug & DEBUG_HW)
+                       printk(KERN_DEBUG "hfcpci_empty_fifo: incoming packet "
+                           "invalid length %d or crc\n", count);
+#ifdef ERROR_STATISTIC
+               bch->err_inv++;
+#endif
+               bz->za[new_f2].z2 = cpu_to_le16(new_z2);
+               bz->f2 = new_f2;        /* next buffer */
+       } else {
+               bch->rx_skb = mI_alloc_skb(count - 3, GFP_ATOMIC);
+               if (!bch->rx_skb) {
+                       printk(KERN_WARNING "HFCPCI: receive out of memory\n");
+                       return;
+               }
+               total = count;
+               count -= 3;
+               ptr = skb_put(bch->rx_skb, count);
+
+               if (le16_to_cpu(zp->z2) + count <= B_FIFO_SIZE + B_SUB_VAL)
+                       maxlen = count;         /* complete transfer */
+               else
+                       maxlen = B_FIFO_SIZE + B_SUB_VAL -
+                           le16_to_cpu(zp->z2);        /* maximum */
+
+               ptr1 = bdata + (le16_to_cpu(zp->z2) - B_SUB_VAL);
+                   /* start of data */
+               memcpy(ptr, ptr1, maxlen);      /* copy data */
+               count -= maxlen;
+
+               if (count) {    /* rest remaining */
+                       ptr += maxlen;
+                       ptr1 = bdata;   /* start of buffer */
+                       memcpy(ptr, ptr1, count);       /* rest */
+               }
+               bz->za[new_f2].z2 = cpu_to_le16(new_z2);
+               bz->f2 = new_f2;        /* next buffer */
+               recv_Bchannel(bch);
+       }
+}
+
+/*
+ * D-channel receive procedure
+ */
+static int
+receive_dmsg(struct hfc_pci *hc)
+{
+       struct dchannel *dch = &hc->dch;
+       int             maxlen;
+       int             rcnt, total;
+       int             count = 5;
+       u_char          *ptr, *ptr1;
+       struct dfifo    *df;
+       struct zt       *zp;
+
+       df = &((union fifo_area *)(hc->hw.fifos))->d_chan.d_rx;
+       while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) {
+               zp = &df->za[df->f2 & D_FREG_MASK];
+               rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
+               if (rcnt < 0)
+                       rcnt += D_FIFO_SIZE;
+               rcnt++;
+               if (dch->debug & DEBUG_HW_DCHANNEL)
+                       printk(KERN_DEBUG
+                           "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)\n",
+                               df->f1, df->f2,
+                               le16_to_cpu(zp->z1),
+                               le16_to_cpu(zp->z2),
+                               rcnt);
+
+               if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
+                   (df->data[le16_to_cpu(zp->z1)])) {
+                       if (dch->debug & DEBUG_HW)
+                               printk(KERN_DEBUG
+                                   "empty_fifo hfcpci paket inv. len "
+                                   "%d or crc %d\n",
+                                   rcnt,
+                                   df->data[le16_to_cpu(zp->z1)]);
+#ifdef ERROR_STATISTIC
+                       cs->err_rx++;
+#endif
+                       df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) |
+                           (MAX_D_FRAMES + 1); /* next buffer */
+                       df->za[df->f2 & D_FREG_MASK].z2 =
+                           cpu_to_le16((zp->z2 + rcnt) & (D_FIFO_SIZE - 1));
+               } else {
+                       dch->rx_skb = mI_alloc_skb(rcnt - 3, GFP_ATOMIC);
+                       if (!dch->rx_skb) {
+                               printk(KERN_WARNING
+                                   "HFC-PCI: D receive out of memory\n");
+                               break;
+                       }
+                       total = rcnt;
+                       rcnt -= 3;
+                       ptr = skb_put(dch->rx_skb, rcnt);
+
+                       if (le16_to_cpu(zp->z2) + rcnt <= D_FIFO_SIZE)
+                               maxlen = rcnt;  /* complete transfer */
+                       else
+                               maxlen = D_FIFO_SIZE - le16_to_cpu(zp->z2);
+                                   /* maximum */
+
+                       ptr1 = df->data + le16_to_cpu(zp->z2);
+                           /* start of data */
+                       memcpy(ptr, ptr1, maxlen);      /* copy data */
+                       rcnt -= maxlen;
+
+                       if (rcnt) {     /* rest remaining */
+                               ptr += maxlen;
+                               ptr1 = df->data;        /* start of buffer */
+                               memcpy(ptr, ptr1, rcnt);        /* rest */
+                       }
+                       df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) |
+                           (MAX_D_FRAMES + 1); /* next buffer */
+                       df->za[df->f2 & D_FREG_MASK].z2 = cpu_to_le16((
+                           le16_to_cpu(zp->z2) + total) & (D_FIFO_SIZE - 1));
+                       recv_Dchannel(dch);
+               }
+       }
+       return 1;
+}
+
+/*
+ * check for transparent receive data and read max one threshold size if avail
+ */
+int
+hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
+{
+       unsigned short  *z1r, *z2r;
+       int             new_z2, fcnt, maxlen;
+       u_char          *ptr, *ptr1;
+
+       z1r = &bz->za[MAX_B_FRAMES].z1;         /* pointer to z reg */
+       z2r = z1r + 1;
+
+       fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r);
+       if (!fcnt)
+               return 0;       /* no data avail */
+
+       if (fcnt <= 0)
+               fcnt += B_FIFO_SIZE;    /* bytes actually buffered */
+       if (fcnt > HFCPCI_BTRANS_THRESHOLD)
+               fcnt = HFCPCI_BTRANS_THRESHOLD;         /* limit size */
+
+       new_z2 = le16_to_cpu(*z2r) + fcnt;      /* new position in fifo */
+       if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
+               new_z2 -= B_FIFO_SIZE;  /* buffer wrap */
+
+       bch->rx_skb = mI_alloc_skb(fcnt, GFP_ATOMIC);
+       if (bch->rx_skb) {
+               ptr = skb_put(bch->rx_skb, fcnt);
+               if (le16_to_cpu(*z2r) + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
+                       maxlen = fcnt;  /* complete transfer */
+               else
+                       maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r);
+                           /* maximum */
+
+               ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL);
+                   /* start of data */
+               memcpy(ptr, ptr1, maxlen);      /* copy data */
+               fcnt -= maxlen;
+
+               if (fcnt) {     /* rest remaining */
+                       ptr += maxlen;
+                       ptr1 = bdata;   /* start of buffer */
+                       memcpy(ptr, ptr1, fcnt);        /* rest */
+               }
+               recv_Bchannel(bch);
+       } else
+               printk(KERN_WARNING "HFCPCI: receive out of memory\n");
+
+       *z2r = cpu_to_le16(new_z2);             /* new position */
+       return 1;
+}
+
+/*
+ * B-channel main receive routine
+ */
+void
+main_rec_hfcpci(struct bchannel *bch)
+{
+       struct hfc_pci  *hc = bch->hw;
+       int             rcnt, real_fifo;
+       int             receive, count = 5;
+       struct bzfifo   *bz;
+       u_char          *bdata;
+       struct zt       *zp;
+
+
+       if ((bch->nr & 2) && (!hc->hw.bswapped)) {
+               bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2;
+               bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b2;
+               real_fifo = 1;
+       } else {
+               bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1;
+               bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b1;
+               real_fifo = 0;
+       }
+Begin:
+       count--;
+       if (bz->f1 != bz->f2) {
+               if (bch->debug & DEBUG_HW_BCHANNEL)
+                       printk(KERN_DEBUG "hfcpci rec ch(%x) f1(%d) f2(%d)\n",
+                           bch->nr, bz->f1, bz->f2);
+               zp = &bz->za[bz->f2];
+
+               rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
+               if (rcnt < 0)
+                       rcnt += B_FIFO_SIZE;
+               rcnt++;
+               if (bch->debug & DEBUG_HW_BCHANNEL)
+                       printk(KERN_DEBUG
+                           "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)\n",
+                           bch->nr, le16_to_cpu(zp->z1),
+                           le16_to_cpu(zp->z2), rcnt);
+               hfcpci_empty_bfifo(bch, bz, bdata, rcnt);
+               rcnt = bz->f1 - bz->f2;
+               if (rcnt < 0)
+                       rcnt += MAX_B_FRAMES + 1;
+               if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) {
+                       rcnt = 0;
+                       hfcpci_clear_fifo_rx(hc, real_fifo);
+               }
+               hc->hw.last_bfifo_cnt[real_fifo] = rcnt;
+               if (rcnt > 1)
+                       receive = 1;
+               else
+                       receive = 0;
+       } else if (test_bit(FLG_TRANSPARENT, &bch->Flags))
+               receive = hfcpci_empty_fifo_trans(bch, bz, bdata);
+       else
+               receive = 0;
+       if (count && receive)
+               goto Begin;
+
+}
+
+/*
+ * D-channel send routine
+ */
+static void
+hfcpci_fill_dfifo(struct hfc_pci *hc)
+{
+       struct dchannel *dch = &hc->dch;
+       int             fcnt;
+       int             count, new_z1, maxlen;
+       struct dfifo    *df;
+       u_char          *src, *dst, new_f1;
+
+       if ((dch->debug & DEBUG_HW_DCHANNEL) && !(dch->debug & DEBUG_HW_DFIFO))
+               printk(KERN_DEBUG "%s\n", __func__);
+
+       if (!dch->tx_skb)
+               return;
+       count = dch->tx_skb->len - dch->tx_idx;
+       if (count <= 0)
+               return;
+       df = &((union fifo_area *) (hc->hw.fifos))->d_chan.d_tx;
+
+       if (dch->debug & DEBUG_HW_DFIFO)
+               printk(KERN_DEBUG "%s:f1(%d) f2(%d) z1(f1)(%x)\n", __func__,
+                   df->f1, df->f2,
+                   le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1));
+       fcnt = df->f1 - df->f2; /* frame count actually buffered */
+       if (fcnt < 0)
+               fcnt += (MAX_D_FRAMES + 1);     /* if wrap around */
+       if (fcnt > (MAX_D_FRAMES - 1)) {
+               if (dch->debug & DEBUG_HW_DCHANNEL)
+                       printk(KERN_DEBUG
+                           "hfcpci_fill_Dfifo more as 14 frames\n");
+#ifdef ERROR_STATISTIC
+               cs->err_tx++;
+#endif
+               return;
+       }
+       /* now determine free bytes in FIFO buffer */
+       maxlen = le16_to_cpu(df->za[df->f2 & D_FREG_MASK].z2) -
+           le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1) - 1;
+       if (maxlen <= 0)
+               maxlen += D_FIFO_SIZE;  /* count now contains available bytes */
+
+       if (dch->debug & DEBUG_HW_DCHANNEL)
+               printk(KERN_DEBUG "hfcpci_fill_Dfifo count(%d/%d)\n",
+                       count, maxlen);
+       if (count > maxlen) {
+               if (dch->debug & DEBUG_HW_DCHANNEL)
+                       printk(KERN_DEBUG "hfcpci_fill_Dfifo no fifo mem\n");
+               return;
+       }
+       new_z1 = (le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1) + count) &
+           (D_FIFO_SIZE - 1);
+       new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1);
+       src = dch->tx_skb->data + dch->tx_idx;  /* source pointer */
+       dst = df->data + le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1);
+       maxlen = D_FIFO_SIZE - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1);
+           /* end fifo */
+       if (maxlen > count)
+               maxlen = count; /* limit size */
+       memcpy(dst, src, maxlen);       /* first copy */
+
+       count -= maxlen;        /* remaining bytes */
+       if (count) {
+               dst = df->data; /* start of buffer */
+               src += maxlen;  /* new position */
+               memcpy(dst, src, count);
+       }
+       df->za[new_f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1);
+           /* for next buffer */
+       df->za[df->f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1);
+           /* new pos actual buffer */
+       df->f1 = new_f1;        /* next frame */
+       dch->tx_idx = dch->tx_skb->len;
+}
+
+/*
+ * B-channel send routine
+ */
+static void
+hfcpci_fill_fifo(struct bchannel *bch)
+{
+       struct hfc_pci  *hc = bch->hw;
+       int             maxlen, fcnt;
+       int             count, new_z1;
+       struct bzfifo   *bz;
+       u_char          *bdata;
+       u_char          new_f1, *src, *dst;
+       unsigned short  *z1t, *z2t;
+
+       if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO))
+               printk(KERN_DEBUG "%s\n", __func__);
+       if ((!bch->tx_skb) || bch->tx_skb->len <= 0)
+               return;
+       count = bch->tx_skb->len - bch->tx_idx;
+       if ((bch->nr & 2) && (!hc->hw.bswapped)) {
+               bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2;
+               bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.txdat_b2;
+       } else {
+               bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b1;
+               bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.txdat_b1;
+       }
+
+       if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
+               z1t = &bz->za[MAX_B_FRAMES].z1;
+               z2t = z1t + 1;
+               if (bch->debug & DEBUG_HW_BCHANNEL)
+                       printk(KERN_DEBUG "hfcpci_fill_fifo_trans ch(%x) "
+                           "cnt(%d) z1(%x) z2(%x)\n", bch->nr, count,
+                           le16_to_cpu(*z1t), le16_to_cpu(*z2t));
+               fcnt = le16_to_cpu(*z2t) - le16_to_cpu(*z1t);
+               if (fcnt <= 0)
+                       fcnt += B_FIFO_SIZE;
+                           /* fcnt contains available bytes in fifo */
+               fcnt = B_FIFO_SIZE - fcnt;
+                   /* remaining bytes to send (bytes in fifo) */
+next_t_frame:
+               count = bch->tx_skb->len - bch->tx_idx;
+               /* maximum fill shall be HFCPCI_BTRANS_MAX */
+               if (count > HFCPCI_BTRANS_MAX - fcnt)
+                       count = HFCPCI_BTRANS_MAX - fcnt;
+               if (count <= 0)
+                       return;
+               /* data is suitable for fifo */
+               new_z1 = le16_to_cpu(*z1t) + count;
+                   /* new buffer Position */
+               if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
+                       new_z1 -= B_FIFO_SIZE;  /* buffer wrap */
+               src = bch->tx_skb->data + bch->tx_idx;
+                   /* source pointer */
+               dst = bdata + (le16_to_cpu(*z1t) - B_SUB_VAL);
+               maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(*z1t);
+                   /* end of fifo */
+               if (bch->debug & DEBUG_HW_BFIFO)
+                       printk(KERN_DEBUG "hfcpci_FFt fcnt(%d) "
+                           "maxl(%d) nz1(%x) dst(%p)\n",
+                           fcnt, maxlen, new_z1, dst);
+               fcnt += count;
+               bch->tx_idx += count;
+               if (maxlen > count)
+                       maxlen = count;         /* limit size */
+               memcpy(dst, src, maxlen);       /* first copy */
+               count -= maxlen;        /* remaining bytes */
+               if (count) {
+                       dst = bdata;    /* start of buffer */
+                       src += maxlen;  /* new position */
+                       memcpy(dst, src, count);
+               }
+               *z1t = cpu_to_le16(new_z1);     /* now send data */
+               if (bch->tx_idx < bch->tx_skb->len)
+                       return;
+               /* send confirm, on trans, free on hdlc. */
+               if (test_bit(FLG_TRANSPARENT, &bch->Flags))
+                       confirm_Bsend(bch);
+               dev_kfree_skb(bch->tx_skb);
+               if (get_next_bframe(bch))
+                       goto next_t_frame;
+               return;
+       }
+       if (bch->debug & DEBUG_HW_BCHANNEL)
+               printk(KERN_DEBUG
+                   "%s: ch(%x) f1(%d) f2(%d) z1(f1)(%x)\n",
+                   __func__, bch->nr, bz->f1, bz->f2,
+                   bz->za[bz->f1].z1);
+       fcnt = bz->f1 - bz->f2; /* frame count actually buffered */
+       if (fcnt < 0)
+               fcnt += (MAX_B_FRAMES + 1);     /* if wrap around */
+       if (fcnt > (MAX_B_FRAMES - 1)) {
+               if (bch->debug & DEBUG_HW_BCHANNEL)
+                       printk(KERN_DEBUG
+                           "hfcpci_fill_Bfifo more as 14 frames\n");
+               return;
+       }
+       /* now determine free bytes in FIFO buffer */
+       maxlen = le16_to_cpu(bz->za[bz->f2].z2) -
+           le16_to_cpu(bz->za[bz->f1].z1) - 1;
+       if (maxlen <= 0)
+               maxlen += B_FIFO_SIZE;  /* count now contains available bytes */
+
+       if (bch->debug & DEBUG_HW_BCHANNEL)
+               printk(KERN_DEBUG "hfcpci_fill_fifo ch(%x) count(%d/%d)\n",
+                       bch->nr, count, maxlen);
+
+       if (maxlen < count) {
+               if (bch->debug & DEBUG_HW_BCHANNEL)
+                       printk(KERN_DEBUG "hfcpci_fill_fifo no fifo mem\n");
+               return;
+       }
+       new_z1 = le16_to_cpu(bz->za[bz->f1].z1) + count;
+           /* new buffer Position */
+       if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
+               new_z1 -= B_FIFO_SIZE;  /* buffer wrap */
+
+       new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES);
+       src = bch->tx_skb->data + bch->tx_idx;  /* source pointer */
+       dst = bdata + (le16_to_cpu(bz->za[bz->f1].z1) - B_SUB_VAL);
+       maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(bz->za[bz->f1].z1);
+           /* end fifo */
+       if (maxlen > count)
+               maxlen = count; /* limit size */
+       memcpy(dst, src, maxlen);       /* first copy */
+
+       count -= maxlen;        /* remaining bytes */
+       if (count) {
+               dst = bdata;    /* start of buffer */
+               src += maxlen;  /* new position */
+               memcpy(dst, src, count);
+       }
+       bz->za[new_f1].z1 = cpu_to_le16(new_z1);        /* for next buffer */
+       bz->f1 = new_f1;        /* next frame */
+       dev_kfree_skb(bch->tx_skb);
+       get_next_bframe(bch);
+}
+
+
+
+/*
+ * handle L1 state changes TE
+ */
+
+static void
+ph_state_te(struct dchannel *dch)
+{
+       if (dch->debug)
+               printk(KERN_DEBUG "%s: TE newstate %x\n",
+                       __func__, dch->state);
+       switch (dch->state) {
+       case 0:
+               l1_event(dch->l1, HW_RESET_IND);
+               break;
+       case 3:
+               l1_event(dch->l1, HW_DEACT_IND);
+               break;
+       case 5:
+       case 8:
+               l1_event(dch->l1, ANYSIGNAL);
+               break;
+       case 6:
+               l1_event(dch->l1, INFO2);
+               break;
+       case 7:
+               l1_event(dch->l1, INFO4_P8);
+               break;
+       }
+}
+
+/*
+ * handle L1 state changes NT
+ */
+
+static void
+handle_nt_timer3(struct dchannel *dch) {
+       struct hfc_pci  *hc = dch->hw;
+
+       test_and_clear_bit(FLG_HFC_TIMER_T3, &dch->Flags);
+       hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
+       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+       hc->hw.nt_timer = 0;
+       test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+       if (test_bit(HFC_CFG_MASTER, &hc->cfg))
+               hc->hw.mst_m |= HFCPCI_MASTER;
+       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
+       _queue_data(&dch->dev.D, PH_ACTIVATE_IND,
+           MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+}
+
+static void
+ph_state_nt(struct dchannel *dch)
+{
+       struct hfc_pci  *hc = dch->hw;
+
+       if (dch->debug)
+               printk(KERN_DEBUG "%s: NT newstate %x\n",
+                       __func__, dch->state);
+       switch (dch->state) {
+       case 2:
+               if (hc->hw.nt_timer < 0) {
+                       hc->hw.nt_timer = 0;
+                       test_and_clear_bit(FLG_HFC_TIMER_T3, &dch->Flags);
+                       test_and_clear_bit(FLG_HFC_TIMER_T1, &dch->Flags);
+                       hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
+                       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+                       /* Clear already pending ints */
+                       if (Read_hfc(hc, HFCPCI_INT_S1));
+                       Write_hfc(hc, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
+                       udelay(10);
+                       Write_hfc(hc, HFCPCI_STATES, 4);
+                       dch->state = 4;
+               } else if (hc->hw.nt_timer == 0) {
+                       hc->hw.int_m1 |= HFCPCI_INTS_TIMER;
+                       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+                       hc->hw.nt_timer = NT_T1_COUNT;
+                       hc->hw.ctmt &= ~HFCPCI_AUTO_TIMER;
+                       hc->hw.ctmt |= HFCPCI_TIM3_125;
+                       Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt |
+                               HFCPCI_CLTIMER);
+                       test_and_clear_bit(FLG_HFC_TIMER_T3, &dch->Flags);
+                       test_and_set_bit(FLG_HFC_TIMER_T1, &dch->Flags);
+                       /* allow G2 -> G3 transition */
+                       Write_hfc(hc, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3);
+               } else {
+                       Write_hfc(hc, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3);
+               }
+               break;
+       case 1:
+               hc->hw.nt_timer = 0;
+               test_and_clear_bit(FLG_HFC_TIMER_T3, &dch->Flags);
+               test_and_clear_bit(FLG_HFC_TIMER_T1, &dch->Flags);
+               hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
+               Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+               test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+               hc->hw.mst_m &= ~HFCPCI_MASTER;
+               Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
+               test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
+               _queue_data(&dch->dev.D, PH_DEACTIVATE_IND,
+                   MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+               break;
+       case 4:
+               hc->hw.nt_timer = 0;
+               test_and_clear_bit(FLG_HFC_TIMER_T3, &dch->Flags);
+               test_and_clear_bit(FLG_HFC_TIMER_T1, &dch->Flags);
+               hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
+               Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+               break;
+       case 3:
+               if (!test_and_set_bit(FLG_HFC_TIMER_T3, &dch->Flags)) {
+                       if (!test_and_clear_bit(FLG_L2_ACTIVATED,
+                           &dch->Flags)) {
+                               handle_nt_timer3(dch);
+                               break;
+                       }
+                       test_and_clear_bit(FLG_HFC_TIMER_T1, &dch->Flags);
+                       hc->hw.int_m1 |= HFCPCI_INTS_TIMER;
+                       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+                       hc->hw.nt_timer = NT_T3_COUNT;
+                       hc->hw.ctmt &= ~HFCPCI_AUTO_TIMER;
+                       hc->hw.ctmt |= HFCPCI_TIM3_125;
+                       Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt |
+                               HFCPCI_CLTIMER);
+               }
+               break;
+       }
+}
+
+static void
+ph_state(struct dchannel *dch)
+{
+       struct hfc_pci  *hc = dch->hw;
+
+       if (hc->hw.protocol == ISDN_P_NT_S0) {
+               if (test_bit(FLG_HFC_TIMER_T3, &dch->Flags) &&
+                   hc->hw.nt_timer < 0)
+                       handle_nt_timer3(dch);
+               else
+                       ph_state_nt(dch);
+       } else
+               ph_state_te(dch);
+}
+
+/*
+ * Layer 1 callback function
+ */
+static int
+hfc_l1callback(struct dchannel *dch, u_int cmd)
+{
+       struct hfc_pci          *hc = dch->hw;
+
+       switch (cmd) {
+       case INFO3_P8:
+       case INFO3_P10:
+               if (test_bit(HFC_CFG_MASTER, &hc->cfg))
+                       hc->hw.mst_m |= HFCPCI_MASTER;
+               Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
+               break;
+       case HW_RESET_REQ:
+               Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3);
+               /* HFC ST 3 */
+               udelay(6);
+               Write_hfc(hc, HFCPCI_STATES, 3);        /* HFC ST 2 */
+               if (test_bit(HFC_CFG_MASTER, &hc->cfg))
+                       hc->hw.mst_m |= HFCPCI_MASTER;
+               Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
+               Write_hfc(hc, HFCPCI_STATES, HFCPCI_ACTIVATE |
+                  HFCPCI_DO_ACTION);
+               l1_event(dch->l1, HW_POWERUP_IND);
+               break;
+       case HW_DEACT_REQ:
+               hc->hw.mst_m &= ~HFCPCI_MASTER;
+               Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
+               skb_queue_purge(&dch->squeue);
+               if (dch->tx_skb) {
+                       dev_kfree_skb(dch->tx_skb);
+                       dch->tx_skb = NULL;
+               }
+               dch->tx_idx = 0;
+               if (dch->rx_skb) {
+                       dev_kfree_skb(dch->rx_skb);
+                       dch->rx_skb = NULL;
+               }
+               test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
+               if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
+                       del_timer(&dch->timer);
+               break;
+       case HW_POWERUP_REQ:
+               Write_hfc(hc, HFCPCI_STATES, HFCPCI_DO_ACTION);
+               break;
+       case PH_ACTIVATE_IND:
+               test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+               _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+                       GFP_ATOMIC);
+               break;
+       case PH_DEACTIVATE_IND:
+               test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+               _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+                       GFP_ATOMIC);
+               break;
+       default:
+               if (dch->debug & DEBUG_HW)
+                       printk(KERN_DEBUG "%s: unknown command %x\n",
+                           __func__, cmd);
+               return -1;
+       }
+       return 0;
+}
+
+/*
+ * Interrupt handler
+ */
+static inline void
+tx_birq(struct bchannel *bch)
+{
+       if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
+               hfcpci_fill_fifo(bch);
+       else {
+               if (bch->tx_skb)
+                       dev_kfree_skb(bch->tx_skb);
+               if (get_next_bframe(bch))
+                       hfcpci_fill_fifo(bch);
+       }
+}
+
+static inline void
+tx_dirq(struct dchannel *dch)
+{
+       if (dch->tx_skb && dch->tx_idx < dch->tx_skb->len)
+               hfcpci_fill_dfifo(dch->hw);
+       else {
+               if (dch->tx_skb)
+                       dev_kfree_skb(dch->tx_skb);
+               if (get_next_dframe(dch))
+                       hfcpci_fill_dfifo(dch->hw);
+       }
+}
+
+static irqreturn_t
+hfcpci_int(int intno, void *dev_id)
+{
+       struct hfc_pci  *hc = dev_id;
+       u_char          exval;
+       struct bchannel *bch;
+       u_char          val, stat;
+
+       spin_lock(&hc->lock);
+       if (!(hc->hw.int_m2 & 0x08)) {
+               spin_unlock(&hc->lock);
+               return IRQ_NONE; /* not initialised */
+       }
+       stat = Read_hfc(hc, HFCPCI_STATUS);
+       if (HFCPCI_ANYINT & stat) {
+               val = Read_hfc(hc, HFCPCI_INT_S1);
+               if (hc->dch.debug & DEBUG_HW_DCHANNEL)
+                       printk(KERN_DEBUG
+                           "HFC-PCI: stat(%02x) s1(%02x)\n", stat, val);
+       } else {
+               /* shared */
+               spin_unlock(&hc->lock);
+               return IRQ_NONE;
+       }
+       hc->irqcnt++;
+
+       if (hc->dch.debug & DEBUG_HW_DCHANNEL)
+               printk(KERN_DEBUG "HFC-PCI irq %x\n", val);
+       val &= hc->hw.int_m1;
+       if (val & 0x40) {       /* state machine irq */
+               exval = Read_hfc(hc, HFCPCI_STATES) & 0xf;
+               if (hc->dch.debug & DEBUG_HW_DCHANNEL)
+                       printk(KERN_DEBUG "ph_state chg %d->%d\n",
+                               hc->dch.state, exval);
+               hc->dch.state = exval;
+               schedule_event(&hc->dch, FLG_PHCHANGE);
+               val &= ~0x40;
+       }
+       if (val & 0x80) {       /* timer irq */
+               if (hc->hw.protocol == ISDN_P_NT_S0) {
+                       if ((--hc->hw.nt_timer) < 0)
+                               schedule_event(&hc->dch, FLG_PHCHANGE);
+               }
+               val &= ~0x80;
+               Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
+       }
+       if (val & 0x08) {
+               bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
+               if (bch)
+                       main_rec_hfcpci(bch);
+               else if (hc->dch.debug)
+                       printk(KERN_DEBUG "hfcpci spurious 0x08 IRQ\n");
+       }
+       if (val & 0x10) {
+               bch = Sel_BCS(hc, 2);
+               if (bch)
+                       main_rec_hfcpci(bch);
+               else if (hc->dch.debug)
+                       printk(KERN_DEBUG "hfcpci spurious 0x10 IRQ\n");
+       }
+       if (val & 0x01) {
+               bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
+               if (bch)
+                       tx_birq(bch);
+               else if (hc->dch.debug)
+                       printk(KERN_DEBUG "hfcpci spurious 0x01 IRQ\n");
+       }
+       if (val & 0x02) {
+               bch = Sel_BCS(hc, 2);
+               if (bch)
+                       tx_birq(bch);
+               else if (hc->dch.debug)
+                       printk(KERN_DEBUG "hfcpci spurious 0x02 IRQ\n");
+       }
+       if (val & 0x20)
+               receive_dmsg(hc);
+       if (val & 0x04) {       /* dframe transmitted */
+               if (test_and_clear_bit(FLG_BUSY_TIMER, &hc->dch.Flags))
+                       del_timer(&hc->dch.timer);
+               tx_dirq(&hc->dch);
+       }
+       spin_unlock(&hc->lock);
+       return IRQ_HANDLED;
+}
+
+/*
+ * timer callback for D-chan busy resolution. Currently no function
+ */
+static void
+hfcpci_dbusy_timer(struct hfc_pci *hc)
+{
+}
+
+/*
+ * activate/deactivate hardware for selected channels and mode
+ */
+static int
+mode_hfcpci(struct bchannel *bch, int bc, int protocol)
+{
+       struct hfc_pci  *hc = bch->hw;
+       int             fifo2;
+       u_char          rx_slot = 0, tx_slot = 0, pcm_mode;
+
+       if (bch->debug & DEBUG_HW_BCHANNEL)
+               printk(KERN_DEBUG
+                   "HFCPCI bchannel protocol %x-->%x ch %x-->%x\n",
+                   bch->state, protocol, bch->nr, bc);
+
+       fifo2 = bc;
+       pcm_mode = (bc>>24) & 0xff;
+       if (pcm_mode) { /* PCM SLOT USE */
+               if (!test_bit(HFC_CFG_PCM, &hc->cfg))
+                       printk(KERN_WARNING
+                           "%s: pcm channel id without HFC_CFG_PCM\n",
+                           __func__);
+               rx_slot = (bc>>8) & 0xff;
+               tx_slot = (bc>>16) & 0xff;
+               bc = bc & 0xff;
+       } else if (test_bit(HFC_CFG_PCM, &hc->cfg) &&
+           (protocol > ISDN_P_NONE))
+               printk(KERN_WARNING "%s: no pcm channel id but HFC_CFG_PCM\n",
+                   __func__);
+       if (hc->chanlimit > 1) {
+               hc->hw.bswapped = 0;    /* B1 and B2 normal mode */
+               hc->hw.sctrl_e &= ~0x80;
+       } else {
+               if (bc & 2) {
+                       if (protocol != ISDN_P_NONE) {
+                               hc->hw.bswapped = 1; /* B1 and B2 exchanged */
+                               hc->hw.sctrl_e |= 0x80;
+                       } else {
+                               hc->hw.bswapped = 0; /* B1 and B2 normal mode */
+                               hc->hw.sctrl_e &= ~0x80;
+                       }
+                       fifo2 = 1;
+               } else {
+                       hc->hw.bswapped = 0;    /* B1 and B2 normal mode */
+                       hc->hw.sctrl_e &= ~0x80;
+               }
+       }
+       switch (protocol) {
+       case (-1): /* used for init */
+               bch->state = -1;
+               bch->nr = bc;
+       case (ISDN_P_NONE):
+               if (bch->state == ISDN_P_NONE)
+                       return 0;
+               if (bc & 2) {
+                       hc->hw.sctrl &= ~SCTRL_B2_ENA;
+                       hc->hw.sctrl_r &= ~SCTRL_B2_ENA;
+               } else {
+                       hc->hw.sctrl &= ~SCTRL_B1_ENA;
+                       hc->hw.sctrl_r &= ~SCTRL_B1_ENA;
+               }
+               if (fifo2 & 2) {
+                       hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B2;
+                       hc->hw.int_m1 &= ~(HFCPCI_INTS_B2TRANS +
+                               HFCPCI_INTS_B2REC);
+               } else {
+                       hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B1;
+                       hc->hw.int_m1 &= ~(HFCPCI_INTS_B1TRANS +
+                               HFCPCI_INTS_B1REC);
+               }
+#ifdef REVERSE_BITORDER
+               if (bch->nr & 2)
+                       hc->hw.cirm &= 0x7f;
+               else
+                       hc->hw.cirm &= 0xbf;
+#endif
+               bch->state = ISDN_P_NONE;
+               bch->nr = bc;
+               test_and_clear_bit(FLG_HDLC, &bch->Flags);
+               test_and_clear_bit(FLG_TRANSPARENT, &bch->Flags);
+               break;
+       case (ISDN_P_B_RAW):
+               bch->state = protocol;
+               bch->nr = bc;
+               hfcpci_clear_fifo_rx(hc, (fifo2 & 2)?1:0);
+               hfcpci_clear_fifo_tx(hc, (fifo2 & 2)?1:0);
+               if (bc & 2) {
+                       hc->hw.sctrl |= SCTRL_B2_ENA;
+                       hc->hw.sctrl_r |= SCTRL_B2_ENA;
+#ifdef REVERSE_BITORDER
+                       hc->hw.cirm |= 0x80;
+#endif
+               } else {
+                       hc->hw.sctrl |= SCTRL_B1_ENA;
+                       hc->hw.sctrl_r |= SCTRL_B1_ENA;
+#ifdef REVERSE_BITORDER
+                       hc->hw.cirm |= 0x40;
+#endif
+               }
+               if (fifo2 & 2) {
+                       hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
+                       hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS +
+                           HFCPCI_INTS_B2REC);
+                       hc->hw.ctmt |= 2;
+                       hc->hw.conn &= ~0x18;
+               } else {
+                       hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
+                       hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS +
+                           HFCPCI_INTS_B1REC);
+                       hc->hw.ctmt |= 1;
+                       hc->hw.conn &= ~0x03;
+               }
+               test_and_set_bit(FLG_TRANSPARENT, &bch->Flags);
+               break;
+       case (ISDN_P_B_HDLC):
+               bch->state = protocol;
+               bch->nr = bc;
+               hfcpci_clear_fifo_rx(hc, (fifo2 & 2)?1:0);
+               hfcpci_clear_fifo_tx(hc, (fifo2 & 2)?1:0);
+               if (bc & 2) {
+                       hc->hw.sctrl |= SCTRL_B2_ENA;
+                       hc->hw.sctrl_r |= SCTRL_B2_ENA;
+               } else {
+                       hc->hw.sctrl |= SCTRL_B1_ENA;
+                       hc->hw.sctrl_r |= SCTRL_B1_ENA;
+               }
+               if (fifo2 & 2) {
+                       hc->hw.last_bfifo_cnt[1] = 0;
+                       hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
+                       hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS +
+                           HFCPCI_INTS_B2REC);
+                       hc->hw.ctmt &= ~2;
+                       hc->hw.conn &= ~0x18;
+               } else {
+                       hc->hw.last_bfifo_cnt[0] = 0;
+                       hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
+                       hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS +
+                           HFCPCI_INTS_B1REC);
+                       hc->hw.ctmt &= ~1;
+                       hc->hw.conn &= ~0x03;
+               }
+               test_and_set_bit(FLG_HDLC, &bch->Flags);
+               break;
+       default:
+               printk(KERN_DEBUG "prot not known %x\n", protocol);
+               return -ENOPROTOOPT;
+       }
+       if (test_bit(HFC_CFG_PCM, &hc->cfg)) {
+               if ((protocol == ISDN_P_NONE) ||
+                       (protocol == -1)) {     /* init case */
+                       rx_slot = 0;
+                       tx_slot = 0;
+               } else {
+                       if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg)) {
+                               rx_slot |= 0xC0;
+                               tx_slot |= 0xC0;
+                       } else {
+                               rx_slot |= 0x80;
+                               tx_slot |= 0x80;
+                       }
+               }
+               if (bc & 2) {
+                       hc->hw.conn &= 0xc7;
+                       hc->hw.conn |= 0x08;
+                       printk(KERN_DEBUG "%s: Write_hfc: B2_SSL 0x%x\n",
+                               __func__, tx_slot);
+                       printk(KERN_DEBUG "%s: Write_hfc: B2_RSL 0x%x\n",
+                               __func__, rx_slot);
+                       Write_hfc(hc, HFCPCI_B2_SSL, tx_slot);
+                       Write_hfc(hc, HFCPCI_B2_RSL, rx_slot);
+               } else {
+                       hc->hw.conn &= 0xf8;
+                       hc->hw.conn |= 0x01;
+                       printk(KERN_DEBUG "%s: Write_hfc: B1_SSL 0x%x\n",
+                               __func__, tx_slot);
+                       printk(KERN_DEBUG "%s: Write_hfc: B1_RSL 0x%x\n",
+                               __func__, rx_slot);
+                       Write_hfc(hc, HFCPCI_B1_SSL, tx_slot);
+                       Write_hfc(hc, HFCPCI_B1_RSL, rx_slot);
+               }
+       }
+       Write_hfc(hc, HFCPCI_SCTRL_E, hc->hw.sctrl_e);
+       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
+       Write_hfc(hc, HFCPCI_SCTRL, hc->hw.sctrl);
+       Write_hfc(hc, HFCPCI_SCTRL_R, hc->hw.sctrl_r);
+       Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt);
+       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
+#ifdef REVERSE_BITORDER
+       Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
+#endif
+       return 0;
+}
+
+static int
+set_hfcpci_rxtest(struct bchannel *bch, int protocol, int chan)
+{
+       struct hfc_pci  *hc = bch->hw;
+
+       if (bch->debug & DEBUG_HW_BCHANNEL)
+               printk(KERN_DEBUG
+                   "HFCPCI bchannel test rx protocol %x-->%x ch %x-->%x\n",
+                   bch->state, protocol, bch->nr, chan);
+       if (bch->nr != chan) {
+               printk(KERN_DEBUG
+                   "HFCPCI rxtest wrong channel parameter %x/%x\n",
+                   bch->nr, chan);
+               return -EINVAL;
+       }
+       switch (protocol) {
+       case (ISDN_P_B_RAW):
+               bch->state = protocol;
+               hfcpci_clear_fifo_rx(hc, (chan & 2)?1:0);
+               if (chan & 2) {
+                       hc->hw.sctrl_r |= SCTRL_B2_ENA;
+                       hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX;
+                       hc->hw.int_m1 |= HFCPCI_INTS_B2REC;
+                       hc->hw.ctmt |= 2;
+                       hc->hw.conn &= ~0x18;
+#ifdef REVERSE_BITORDER
+                       hc->hw.cirm |= 0x80;
+#endif
+               } else {
+                       hc->hw.sctrl_r |= SCTRL_B1_ENA;
+                       hc->hw.fifo_en |= HFCPCI_FIFOEN_B1RX;
+                       hc->hw.int_m1 |= HFCPCI_INTS_B1REC;
+                       hc->hw.ctmt |= 1;
+                       hc->hw.conn &= ~0x03;
+#ifdef REVERSE_BITORDER
+                       hc->hw.cirm |= 0x40;
+#endif
+               }
+               break;
+       case (ISDN_P_B_HDLC):
+               bch->state = protocol;
+               hfcpci_clear_fifo_rx(hc, (chan & 2)?1:0);
+               if (chan & 2) {
+                       hc->hw.sctrl_r |= SCTRL_B2_ENA;
+                       hc->hw.last_bfifo_cnt[1] = 0;
+                       hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX;
+                       hc->hw.int_m1 |= HFCPCI_INTS_B2REC;
+                       hc->hw.ctmt &= ~2;
+                       hc->hw.conn &= ~0x18;
+               } else {
+                       hc->hw.sctrl_r |= SCTRL_B1_ENA;
+                       hc->hw.last_bfifo_cnt[0] = 0;
+                       hc->hw.fifo_en |= HFCPCI_FIFOEN_B1RX;
+                       hc->hw.int_m1 |= HFCPCI_INTS_B1REC;
+                       hc->hw.ctmt &= ~1;
+                       hc->hw.conn &= ~0x03;
+               }
+               break;
+       default:
+               printk(KERN_DEBUG "prot not known %x\n", protocol);
+               return -ENOPROTOOPT;
+       }
+       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
+       Write_hfc(hc, HFCPCI_SCTRL_R, hc->hw.sctrl_r);
+       Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt);
+       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
+#ifdef REVERSE_BITORDER
+       Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
+#endif
+       return 0;
+}
+
+static void
+deactivate_bchannel(struct bchannel *bch)
+{
+       struct hfc_pci  *hc = bch->hw;
+       u_long          flags;
+
+       spin_lock_irqsave(&hc->lock, flags);
+       if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
+               dev_kfree_skb(bch->next_skb);
+               bch->next_skb = NULL;
+       }
+       if (bch->tx_skb) {
+               dev_kfree_skb(bch->tx_skb);
+               bch->tx_skb = NULL;
+       }
+       bch->tx_idx = 0;
+       if (bch->rx_skb) {
+               dev_kfree_skb(bch->rx_skb);
+               bch->rx_skb = NULL;
+       }
+       mode_hfcpci(bch, bch->nr, ISDN_P_NONE);
+       test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
+       test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
+       spin_unlock_irqrestore(&hc->lock, flags);
+}
+
+/*
+ * Layer 1 B-channel hardware access
+ */
+static int
+channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
+{
+       int                     ret = 0;
+
+       switch (cq->op) {
+       case MISDN_CTRL_GETOP:
+               cq->op = 0;
+               break;
+       default:
+               printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+static int
+hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct bchannel *bch = container_of(ch, struct bchannel, ch);
+       struct hfc_pci  *hc = bch->hw;
+       int             ret = -EINVAL;
+       u_long          flags;
+
+       if (bch->debug & DEBUG_HW)
+               printk(KERN_DEBUG "%s: cmd:%x %p\n", __func__, cmd, arg);
+       switch (cmd) {
+       case HW_TESTRX_RAW:
+               spin_lock_irqsave(&hc->lock, flags);
+               ret = set_hfcpci_rxtest(bch, ISDN_P_B_RAW, (int)(long)arg);
+               spin_unlock_irqrestore(&hc->lock, flags);
+               break;
+       case HW_TESTRX_HDLC:
+               spin_lock_irqsave(&hc->lock, flags);
+               ret = set_hfcpci_rxtest(bch, ISDN_P_B_HDLC, (int)(long)arg);
+               spin_unlock_irqrestore(&hc->lock, flags);
+               break;
+       case HW_TESTRX_OFF:
+               spin_lock_irqsave(&hc->lock, flags);
+               mode_hfcpci(bch, bch->nr, ISDN_P_NONE);
+               spin_unlock_irqrestore(&hc->lock, flags);
+               ret = 0;
+               break;
+       case CLOSE_CHANNEL:
+               test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               if (test_bit(FLG_ACTIVE, &bch->Flags))
+                       deactivate_bchannel(bch);
+               ch->protocol = ISDN_P_NONE;
+               ch->peer = NULL;
+               module_put(THIS_MODULE);
+               ret = 0;
+               break;
+       case CONTROL_CHANNEL:
+               ret = channel_bctrl(bch, arg);
+               break;
+       default:
+               printk(KERN_WARNING "%s: unknown prim(%x)\n",
+                       __func__, cmd);
+       }
+       return ret;
+}
+
+/*
+ * Layer2 -> Layer 1 Dchannel data
+ */
+static int
+hfcpci_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct mISDNdevice      *dev = container_of(ch, struct mISDNdevice, D);
+       struct dchannel         *dch = container_of(dev, struct dchannel, dev);
+       struct hfc_pci          *hc = dch->hw;
+       int                     ret = -EINVAL;
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+       unsigned int            id;
+       u_long                  flags;
+
+       switch (hh->prim) {
+       case PH_DATA_REQ:
+               spin_lock_irqsave(&hc->lock, flags);
+               ret = dchannel_senddata(dch, skb);
+               if (ret > 0) { /* direct TX */
+                       id = hh->id; /* skb can be freed */
+                       hfcpci_fill_dfifo(dch->hw);
+                       ret = 0;
+                       spin_unlock_irqrestore(&hc->lock, flags);
+                       queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+               } else
+                       spin_unlock_irqrestore(&hc->lock, flags);
+               return ret;
+       case PH_ACTIVATE_REQ:
+               spin_lock_irqsave(&hc->lock, flags);
+               if (hc->hw.protocol == ISDN_P_NT_S0) {
+                       ret = 0;
+                       if (test_bit(HFC_CFG_MASTER, &hc->cfg))
+                               hc->hw.mst_m |= HFCPCI_MASTER;
+                       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
+                       if (test_bit(FLG_ACTIVE, &dch->Flags)) {
+                               spin_unlock_irqrestore(&hc->lock, flags);
+                               _queue_data(&dch->dev.D, PH_ACTIVATE_IND,
+                                   MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+                               break;
+                       }
+                       test_and_set_bit(FLG_L2_ACTIVATED, &dch->Flags);
+                       Write_hfc(hc, HFCPCI_STATES, HFCPCI_ACTIVATE |
+                           HFCPCI_DO_ACTION | 1);
+               } else
+                       ret = l1_event(dch->l1, hh->prim);
+               spin_unlock_irqrestore(&hc->lock, flags);
+               break;
+       case PH_DEACTIVATE_REQ:
+               test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
+               spin_lock_irqsave(&hc->lock, flags);
+               if (hc->hw.protocol == ISDN_P_NT_S0) {
+                       /* prepare deactivation */
+                       Write_hfc(hc, HFCPCI_STATES, 0x40);
+                       skb_queue_purge(&dch->squeue);
+                       if (dch->tx_skb) {
+                               dev_kfree_skb(dch->tx_skb);
+                               dch->tx_skb = NULL;
+                       }
+                       dch->tx_idx = 0;
+                       if (dch->rx_skb) {
+                               dev_kfree_skb(dch->rx_skb);
+                               dch->rx_skb = NULL;
+                       }
+                       test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
+                       if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
+                               del_timer(&dch->timer);
+#ifdef FIXME
+                       if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags))
+                               dchannel_sched_event(&hc->dch, D_CLEARBUSY);
+#endif
+                       hc->hw.mst_m &= ~HFCPCI_MASTER;
+                       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
+                       ret = 0;
+               } else {
+                       ret = l1_event(dch->l1, hh->prim);
+               }
+               spin_unlock_irqrestore(&hc->lock, flags);
+               break;
+       }
+       if (!ret)
+               dev_kfree_skb(skb);
+       return ret;
+}
+
+/*
+ * Layer2 -> Layer 1 Bchannel data
+ */
+static int
+hfcpci_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct bchannel         *bch = container_of(ch, struct bchannel, ch);
+       struct hfc_pci          *hc = bch->hw;
+       int                     ret = -EINVAL;
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+       unsigned int            id;
+       u_long                  flags;
+
+       switch (hh->prim) {
+       case PH_DATA_REQ:
+               spin_lock_irqsave(&hc->lock, flags);
+               ret = bchannel_senddata(bch, skb);
+               if (ret > 0) { /* direct TX */
+                       id = hh->id; /* skb can be freed */
+                       hfcpci_fill_fifo(bch);
+                       ret = 0;
+                       spin_unlock_irqrestore(&hc->lock, flags);
+                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
+                               queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+               } else
+                       spin_unlock_irqrestore(&hc->lock, flags);
+               return ret;
+       case PH_ACTIVATE_REQ:
+               spin_lock_irqsave(&hc->lock, flags);
+               if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
+                       ret = mode_hfcpci(bch, bch->nr, ch->protocol);
+               else
+                       ret = 0;
+               spin_unlock_irqrestore(&hc->lock, flags);
+               if (!ret)
+                       _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
+                               NULL, GFP_KERNEL);
+               break;
+       case PH_DEACTIVATE_REQ:
+               deactivate_bchannel(bch);
+               _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
+                       NULL, GFP_KERNEL);
+               ret = 0;
+               break;
+       }
+       if (!ret)
+               dev_kfree_skb(skb);
+       return ret;
+}
+
+/*
+ * called for card init message
+ */
+
+void
+inithfcpci(struct hfc_pci *hc)
+{
+       printk(KERN_DEBUG "inithfcpci: entered\n");
+       hc->dch.timer.function = (void *) hfcpci_dbusy_timer;
+       hc->dch.timer.data = (long) &hc->dch;
+       init_timer(&hc->dch.timer);
+       hc->chanlimit = 2;
+       mode_hfcpci(&hc->bch[0], 1, -1);
+       mode_hfcpci(&hc->bch[1], 2, -1);
+}
+
+
+static int
+init_card(struct hfc_pci *hc)
+{
+       int     cnt = 3;
+       u_long  flags;
+
+       printk(KERN_DEBUG "init_card: entered\n");
+
+
+       spin_lock_irqsave(&hc->lock, flags);
+       disable_hwirq(hc);
+       spin_unlock_irqrestore(&hc->lock, flags);
+       if (request_irq(hc->irq, hfcpci_int, IRQF_SHARED, "HFC PCI", hc)) {
+               printk(KERN_WARNING
+                   "mISDN: couldn't get interrupt %d\n", hc->irq);
+               return -EIO;
+       }
+       spin_lock_irqsave(&hc->lock, flags);
+       reset_hfcpci(hc);
+       while (cnt) {
+               inithfcpci(hc);
+               /*
+                * Finally enable IRQ output
+                * this is only allowed, if an IRQ routine is allready
+                * established for this HFC, so don't do that earlier
+                */
+               enable_hwirq(hc);
+               spin_unlock_irqrestore(&hc->lock, flags);
+               /* Timeout 80ms */
+               current->state = TASK_UNINTERRUPTIBLE;
+               schedule_timeout((80*HZ)/1000);
+               printk(KERN_INFO "HFC PCI: IRQ %d count %d\n",
+                       hc->irq, hc->irqcnt);
+               /* now switch timer interrupt off */
+               spin_lock_irqsave(&hc->lock, flags);
+               hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
+               Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+               /* reinit mode reg */
+               Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
+               if (!hc->irqcnt) {
+                       printk(KERN_WARNING
+                           "HFC PCI: IRQ(%d) getting no interrupts "
+                           "during init %d\n", hc->irq, 4 - cnt);
+                       if (cnt == 1) {
+                               spin_unlock_irqrestore(&hc->lock, flags);
+                               return -EIO;
+                       } else {
+                               reset_hfcpci(hc);
+                               cnt--;
+                       }
+               } else {
+                       spin_unlock_irqrestore(&hc->lock, flags);
+                       hc->initdone = 1;
+                       return 0;
+               }
+       }
+       disable_hwirq(hc);
+       spin_unlock_irqrestore(&hc->lock, flags);
+       free_irq(hc->irq, hc);
+       return -EIO;
+}
+
+static int
+channel_ctrl(struct hfc_pci *hc, struct mISDN_ctrl_req *cq)
+{
+       int     ret = 0;
+       u_char  slot;
+
+       switch (cq->op) {
+       case MISDN_CTRL_GETOP:
+               cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_CONNECT |
+                   MISDN_CTRL_DISCONNECT;
+               break;
+       case MISDN_CTRL_LOOP:
+               /* channel 0 disabled loop */
+               if (cq->channel < 0 || cq->channel > 2) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (cq->channel & 1) {
+                       if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg))
+                               slot = 0xC0;
+                       else
+                               slot = 0x80;
+                       printk(KERN_DEBUG "%s: Write_hfc: B1_SSL/RSL 0x%x\n",
+                           __func__, slot);
+                       Write_hfc(hc, HFCPCI_B1_SSL, slot);
+                       Write_hfc(hc, HFCPCI_B1_RSL, slot);
+                       hc->hw.conn = (hc->hw.conn & ~7) | 6;
+                       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
+               }
+               if (cq->channel & 2) {
+                       if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg))
+                               slot = 0xC1;
+                       else
+                               slot = 0x81;
+                       printk(KERN_DEBUG "%s: Write_hfc: B2_SSL/RSL 0x%x\n",
+                           __func__, slot);
+                       Write_hfc(hc, HFCPCI_B2_SSL, slot);
+                       Write_hfc(hc, HFCPCI_B2_RSL, slot);
+                       hc->hw.conn = (hc->hw.conn & ~0x38) | 0x30;
+                       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
+               }
+               if (cq->channel & 3)
+                       hc->hw.trm |= 0x80;     /* enable IOM-loop */
+               else {
+                       hc->hw.conn = (hc->hw.conn & ~0x3f) | 0x09;
+                       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
+                       hc->hw.trm &= 0x7f;     /* disable IOM-loop */
+               }
+               Write_hfc(hc, HFCPCI_TRM, hc->hw.trm);
+               break;
+       case MISDN_CTRL_CONNECT:
+               if (cq->channel == cq->p1) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (cq->channel < 1 || cq->channel > 2 ||
+                   cq->p1 < 1 || cq->p1 > 2) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg))
+                       slot = 0xC0;
+               else
+                       slot = 0x80;
+               printk(KERN_DEBUG "%s: Write_hfc: B1_SSL/RSL 0x%x\n",
+                   __func__, slot);
+               Write_hfc(hc, HFCPCI_B1_SSL, slot);
+               Write_hfc(hc, HFCPCI_B2_RSL, slot);
+               if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg))
+                       slot = 0xC1;
+               else
+                       slot = 0x81;
+               printk(KERN_DEBUG "%s: Write_hfc: B2_SSL/RSL 0x%x\n",
+                   __func__, slot);
+               Write_hfc(hc, HFCPCI_B2_SSL, slot);
+               Write_hfc(hc, HFCPCI_B1_RSL, slot);
+               hc->hw.conn = (hc->hw.conn & ~0x3f) | 0x36;
+               Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
+               hc->hw.trm |= 0x80;
+               Write_hfc(hc, HFCPCI_TRM, hc->hw.trm);
+               break;
+       case MISDN_CTRL_DISCONNECT:
+               hc->hw.conn = (hc->hw.conn & ~0x3f) | 0x09;
+               Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
+               hc->hw.trm &= 0x7f;     /* disable IOM-loop */
+               break;
+       default:
+               printk(KERN_WARNING "%s: unknown Op %x\n",
+                   __func__, cq->op);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int
+open_dchannel(struct hfc_pci *hc, struct mISDNchannel *ch,
+    struct channel_req *rq)
+{
+       int err = 0;
+
+       if (debug & DEBUG_HW_OPEN)
+               printk(KERN_DEBUG "%s: dev(%d) open from %p\n", __func__,
+                   hc->dch.dev.id, __builtin_return_address(0));
+       if (rq->protocol == ISDN_P_NONE)
+               return -EINVAL;
+       if (!hc->initdone) {
+               if (rq->protocol == ISDN_P_TE_S0) {
+                       err = create_l1(&hc->dch, hfc_l1callback);
+                       if (err)
+                               return err;
+               }
+               hc->hw.protocol = rq->protocol;
+               ch->protocol = rq->protocol;
+               err = init_card(hc);
+               if (err)
+                       return err;
+       } else {
+               if (rq->protocol != ch->protocol) {
+                       if (hc->hw.protocol == ISDN_P_TE_S0)
+                               l1_event(hc->dch.l1, CLOSE_CHANNEL);
+                       hc->hw.protocol = rq->protocol;
+                       ch->protocol = rq->protocol;
+                       hfcpci_setmode(hc);
+               }
+       }
+
+       if (((ch->protocol == ISDN_P_NT_S0) && (hc->dch.state == 3)) ||
+           ((ch->protocol == ISDN_P_TE_S0) && (hc->dch.state == 7))) {
+               _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
+                   0, NULL, GFP_KERNEL);
+       }
+       rq->ch = ch;
+       if (!try_module_get(THIS_MODULE))
+               printk(KERN_WARNING "%s:cannot get module\n", __func__);
+       return 0;
+}
+
+static int
+open_bchannel(struct hfc_pci *hc, struct channel_req *rq)
+{
+       struct bchannel         *bch;
+
+       if (rq->adr.channel > 2)
+               return -EINVAL;
+       if (rq->protocol == ISDN_P_NONE)
+               return -EINVAL;
+       bch = &hc->bch[rq->adr.channel - 1];
+       if (test_and_set_bit(FLG_OPEN, &bch->Flags))
+               return -EBUSY; /* b-channel can be only open once */
+       bch->ch.protocol = rq->protocol;
+       rq->ch = &bch->ch; /* TODO: E-channel */
+       if (!try_module_get(THIS_MODULE))
+               printk(KERN_WARNING "%s:cannot get module\n", __func__);
+       return 0;
+}
+
+/*
+ * device control function
+ */
+static int
+hfc_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct mISDNdevice      *dev = container_of(ch, struct mISDNdevice, D);
+       struct dchannel         *dch = container_of(dev, struct dchannel, dev);
+       struct hfc_pci          *hc = dch->hw;
+       struct channel_req      *rq;
+       int                     err = 0;
+
+       if (dch->debug & DEBUG_HW)
+               printk(KERN_DEBUG "%s: cmd:%x %p\n",
+                   __func__, cmd, arg);
+       switch (cmd) {
+       case OPEN_CHANNEL:
+               rq = arg;
+               if (rq->adr.channel == 0)
+                       err = open_dchannel(hc, ch, rq);
+               else
+                       err = open_bchannel(hc, rq);
+               break;
+       case CLOSE_CHANNEL:
+               if (debug & DEBUG_HW_OPEN)
+                       printk(KERN_DEBUG "%s: dev(%d) close from %p\n",
+                           __func__, hc->dch.dev.id,
+                           __builtin_return_address(0));
+               module_put(THIS_MODULE);
+               break;
+       case CONTROL_CHANNEL:
+               err = channel_ctrl(hc, arg);
+               break;
+       default:
+               if (dch->debug & DEBUG_HW)
+                       printk(KERN_DEBUG "%s: unknown command %x\n",
+                           __func__, cmd);
+               return -EINVAL;
+       }
+       return err;
+}
+
+static int
+setup_hw(struct hfc_pci *hc)
+{
+       void    *buffer;
+
+       printk(KERN_INFO "mISDN: HFC-PCI driver %s\n", hfcpci_revision);
+       hc->hw.cirm = 0;
+       hc->dch.state = 0;
+       pci_set_master(hc->pdev);
+       if (!hc->irq) {
+               printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
+               return 1;
+       }
+       hc->hw.pci_io = (char *)(ulong)hc->pdev->resource[1].start;
+
+       if (!hc->hw.pci_io) {
+               printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
+               return 1;
+       }
+       /* Allocate memory for FIFOS */
+       /* the memory needs to be on a 32k boundary within the first 4G */
+       pci_set_dma_mask(hc->pdev, 0xFFFF8000);
+       buffer = pci_alloc_consistent(hc->pdev, 0x8000, &hc->hw.dmahandle);
+       /* We silently assume the address is okay if nonzero */
+       if (!buffer) {
+               printk(KERN_WARNING
+                   "HFC-PCI: Error allocating memory for FIFO!\n");
+               return 1;
+       }
+       hc->hw.fifos = buffer;
+       pci_write_config_dword(hc->pdev, 0x80, hc->hw.dmahandle);
+       hc->hw.pci_io = ioremap((ulong) hc->hw.pci_io, 256);
+       printk(KERN_INFO
+               "HFC-PCI: defined at mem %#lx fifo %#lx(%#lx) IRQ %d HZ %d\n",
+               (u_long) hc->hw.pci_io, (u_long) hc->hw.fifos,
+               (u_long) hc->hw.dmahandle, hc->irq, HZ);
+       /* enable memory mapped ports, disable busmaster */
+       pci_write_config_word(hc->pdev, PCI_COMMAND, PCI_ENA_MEMIO);
+       hc->hw.int_m2 = 0;
+       disable_hwirq(hc);
+       hc->hw.int_m1 = 0;
+       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
+       /* At this point the needed PCI config is done */
+       /* fifos are still not enabled */
+       hc->hw.timer.function = (void *) hfcpci_Timer;
+       hc->hw.timer.data = (long) hc;
+       init_timer(&hc->hw.timer);
+       /* default PCM master */
+       test_and_set_bit(HFC_CFG_MASTER, &hc->cfg);
+       return 0;
+}
+
+static void
+release_card(struct hfc_pci *hc) {
+       u_long  flags;
+
+       spin_lock_irqsave(&hc->lock, flags);
+       hc->hw.int_m2 = 0; /* interrupt output off ! */
+       disable_hwirq(hc);
+       mode_hfcpci(&hc->bch[0], 1, ISDN_P_NONE);
+       mode_hfcpci(&hc->bch[1], 2, ISDN_P_NONE);
+       if (hc->dch.timer.function != NULL) {
+               del_timer(&hc->dch.timer);
+               hc->dch.timer.function = NULL;
+       }
+       spin_unlock_irqrestore(&hc->lock, flags);
+       if (hc->hw.protocol == ISDN_P_TE_S0)
+               l1_event(hc->dch.l1, CLOSE_CHANNEL);
+       if (hc->initdone)
+               free_irq(hc->irq, hc);
+       release_io_hfcpci(hc); /* must release after free_irq! */
+       mISDN_unregister_device(&hc->dch.dev);
+       mISDN_freebchannel(&hc->bch[1]);
+       mISDN_freebchannel(&hc->bch[0]);
+       mISDN_freedchannel(&hc->dch);
+       list_del(&hc->list);
+       pci_set_drvdata(hc->pdev, NULL);
+       kfree(hc);
+}
+
+static int
+setup_card(struct hfc_pci *card)
+{
+       int             err = -EINVAL;
+       u_int           i;
+       u_long          flags;
+       char            name[MISDN_MAX_IDLEN];
+
+       if (HFC_cnt >= MAX_CARDS)
+               return -EINVAL; /* maybe better value */
+
+       card->dch.debug = debug;
+       spin_lock_init(&card->lock);
+       mISDN_initdchannel(&card->dch, MAX_DFRAME_LEN_L1, ph_state);
+       card->dch.hw = card;
+       card->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0) | (1 << ISDN_P_NT_S0);
+       card->dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+           (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+       card->dch.dev.D.send = hfcpci_l2l1D;
+       card->dch.dev.D.ctrl = hfc_dctrl;
+       card->dch.dev.nrbchan = 2;
+       for (i = 0; i < 2; i++) {
+               card->bch[i].nr = i + 1;
+               test_and_set_bit(i + 1, &card->dch.dev.channelmap[0]);
+               card->bch[i].debug = debug;
+               mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM);
+               card->bch[i].hw = card;
+               card->bch[i].ch.send = hfcpci_l2l1B;
+               card->bch[i].ch.ctrl = hfc_bctrl;
+               card->bch[i].ch.nr = i + 1;
+               list_add(&card->bch[i].ch.list, &card->dch.dev.bchannels);
+       }
+       err = setup_hw(card);
+       if (err)
+               goto error;
+       snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-pci.%d", HFC_cnt + 1);
+       err = mISDN_register_device(&card->dch.dev, name);
+       if (err)
+               goto error;
+       HFC_cnt++;
+       write_lock_irqsave(&HFClock, flags);
+       list_add_tail(&card->list, &HFClist);
+       write_unlock_irqrestore(&HFClock, flags);
+       printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt);
+       return 0;
+error:
+       mISDN_freebchannel(&card->bch[1]);
+       mISDN_freebchannel(&card->bch[0]);
+       mISDN_freedchannel(&card->dch);
+       kfree(card);
+       return err;
+}
+
+/* private data in the PCI devices list */
+struct _hfc_map {
+       u_int   subtype;
+       u_int   flag;
+       char    *name;
+};
+
+static const struct _hfc_map hfc_map[] =
+{
+       {HFC_CCD_2BD0, 0, "CCD/Billion/Asuscom 2BD0"},
+       {HFC_CCD_B000, 0, "Billion B000"},
+       {HFC_CCD_B006, 0, "Billion B006"},
+       {HFC_CCD_B007, 0, "Billion B007"},
+       {HFC_CCD_B008, 0, "Billion B008"},
+       {HFC_CCD_B009, 0, "Billion B009"},
+       {HFC_CCD_B00A, 0, "Billion B00A"},
+       {HFC_CCD_B00B, 0, "Billion B00B"},
+       {HFC_CCD_B00C, 0, "Billion B00C"},
+       {HFC_CCD_B100, 0, "Seyeon B100"},
+       {HFC_CCD_B700, 0, "Primux II S0 B700"},
+       {HFC_CCD_B701, 0, "Primux II S0 NT B701"},
+       {HFC_ABOCOM_2BD1, 0, "Abocom/Magitek 2BD1"},
+       {HFC_ASUS_0675, 0, "Asuscom/Askey 675"},
+       {HFC_BERKOM_TCONCEPT, 0, "German telekom T-Concept"},
+       {HFC_BERKOM_A1T, 0, "German telekom A1T"},
+       {HFC_ANIGMA_MC145575, 0, "Motorola MC145575"},
+       {HFC_ZOLTRIX_2BD0, 0, "Zoltrix 2BD0"},
+       {HFC_DIGI_DF_M_IOM2_E, 0,
+           "Digi International DataFire Micro V IOM2 (Europe)"},
+       {HFC_DIGI_DF_M_E, 0,
+           "Digi International DataFire Micro V (Europe)"},
+       {HFC_DIGI_DF_M_IOM2_A, 0,
+           "Digi International DataFire Micro V IOM2 (North America)"},
+       {HFC_DIGI_DF_M_A, 0,
+           "Digi International DataFire Micro V (North America)"},
+       {HFC_SITECOM_DC105V2, 0, "Sitecom Connectivity DC-105 ISDN TA"},
+       {},
+};
+
+static struct pci_device_id hfc_ids[] =
+{
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[0]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[1]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[2]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[3]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[4]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[5]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[6]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[7]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[8]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[9]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B700,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[10]},
+       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B701,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[11]},
+       {PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[12]},
+       {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[13]},
+       {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[14]},
+       {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[15]},
+       {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[16]},
+       {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[17]},
+       {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[18]},
+       {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[19]},
+       {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[20]},
+       {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[21]},
+       {PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &hfc_map[22]},
+       {},
+};
+
+static int __devinit
+hfc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       int             err = -ENOMEM;
+       struct hfc_pci  *card;
+       struct _hfc_map *m = (struct _hfc_map *)ent->driver_data;
+
+       card = kzalloc(sizeof(struct hfc_pci), GFP_ATOMIC);
+       if (!card) {
+               printk(KERN_ERR "No kmem for HFC card\n");
+               return err;
+       }
+       card->pdev = pdev;
+       card->subtype = m->subtype;
+       err = pci_enable_device(pdev);
+       if (err) {
+               kfree(card);
+               return err;
+       }
+
+       printk(KERN_INFO "mISDN_hfcpci: found adapter %s at %s\n",
+              m->name, pci_name(pdev));
+
+       card->irq = pdev->irq;
+       pci_set_drvdata(pdev, card);
+       err = setup_card(card);
+       if (err)
+               pci_set_drvdata(pdev, NULL);
+       return err;
+}
+
+static void __devexit
+hfc_remove_pci(struct pci_dev *pdev)
+{
+       struct hfc_pci  *card = pci_get_drvdata(pdev);
+       u_long          flags;
+
+       if (card) {
+               write_lock_irqsave(&HFClock, flags);
+               release_card(card);
+               write_unlock_irqrestore(&HFClock, flags);
+       } else
+               if (debug)
+                       printk(KERN_WARNING "%s: drvdata allready removed\n",
+                           __func__);
+}
+
+
+static struct pci_driver hfc_driver = {
+       .name = "hfcpci",
+       .probe = hfc_probe,
+       .remove = __devexit_p(hfc_remove_pci),
+       .id_table = hfc_ids,
+};
+
+static int __init
+HFC_init(void)
+{
+       int             err;
+
+       err = pci_register_driver(&hfc_driver);
+       return err;
+}
+
+static void __exit
+HFC_cleanup(void)
+{
+       struct hfc_pci  *card, *next;
+
+       list_for_each_entry_safe(card, next, &HFClist, list) {
+               release_card(card);
+       }
+       pci_unregister_driver(&hfc_driver);
+}
+
+module_init(HFC_init);
+module_exit(HFC_cleanup);
index c0b4db2f8364cf186f25f2861bf41af59d411e49..1925118122f877bdb2313d64f7fc8478e678e141 100644 (file)
@@ -974,8 +974,6 @@ static struct pnp_driver fcpnp_driver = {
        .remove         = __devexit_p(fcpnp_remove),
        .id_table       = fcpnp_ids,
 };
-#else
-static struct pnp_driver fcpnp_driver;
 #endif
 
 static void __devexit fcpci_remove(struct pci_dev *pdev)
index 2044e7173ab46a9d81f5f1b646c361383c8245a1..cff7a6354334234ca9f2030229bf5e49b08de432 100644 (file)
@@ -220,7 +220,7 @@ enum {
 #define ERR(format, arg...) \
 printk(KERN_ERR "%s:%s: " format "\n" , __FILE__,  __func__ , ## arg)
 
-#define WARN(format, arg...) \
+#define WARNING(format, arg...) \
 printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__,  __func__ , ## arg)
 
 #define INFO(format, arg...) \
@@ -412,7 +412,7 @@ struct st5481_adapter {
 ({ \
        int status; \
        if ((status = usb_submit_urb(urb, mem_flags)) < 0) { \
-               WARN("usb_submit_urb failed,status=%d", status); \
+               WARNING("usb_submit_urb failed,status=%d", status); \
        } \
         status; \
 })
index fa64115cd7c7570267a2adec29c19392d9dcf448..0074b600a0efa2d98b86c8ef16f97b0ebfdd4404 100644 (file)
@@ -180,7 +180,7 @@ static void usb_b_out_complete(struct urb *urb)
                                DBG(4,"urb killed status %d", urb->status);
                                return; // Give up
                        default: 
-                               WARN("urb status %d",urb->status);
+                               WARNING("urb status %d",urb->status);
                                if (b_out->busy == 0) {
                                        st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
                                }
@@ -372,6 +372,6 @@ void st5481_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
                B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
                break;
        default:
-               WARN("pr %#x\n", pr);
+               WARNING("pr %#x\n", pr);
        }
 }
index b8c4855cc8894c700169184e3b04ae5500dcf86c..077991c1cd050d9f93c0228155877d8377b95b88 100644 (file)
@@ -389,7 +389,7 @@ static void usb_d_out_complete(struct urb *urb)
                                DBG(1,"urb killed status %d", urb->status);
                                break;
                        default: 
-                               WARN("urb status %d",urb->status);
+                               WARNING("urb status %d",urb->status);
                                if (d_out->busy == 0) {
                                        st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
                                }
@@ -420,7 +420,7 @@ static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg)
        isdnhdlc_out_init(&d_out->hdlc_state, 1, 0);
 
        if (test_and_set_bit(buf_nr, &d_out->busy)) {
-               WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
+               WARNING("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
                return;
        }
        urb = d_out->urb[buf_nr];
@@ -601,7 +601,7 @@ void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
                FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL);
                break;
        default:
-               WARN("pr %#x\n", pr);
+               WARNING("pr %#x\n", pr);
                break;
        }
 }
index 427a8b0520f5aee14684503f208e5faa6f841d1b..ec3c0e507669804236ce5952fb91a19d9e721947 100644 (file)
@@ -66,7 +66,7 @@ static void usb_ctrl_msg(struct st5481_adapter *adapter,
        struct ctrl_msg *ctrl_msg;
        
        if ((w_index = fifo_add(&ctrl->msg_fifo.f)) < 0) {
-               WARN("control msg FIFO full");
+               WARNING("control msg FIFO full");
                return;
        }
        ctrl_msg = &ctrl->msg_fifo.data[w_index]; 
@@ -139,7 +139,7 @@ static void usb_ctrl_complete(struct urb *urb)
                                DBG(1,"urb killed status %d", urb->status);
                                return; // Give up
                        default: 
-                               WARN("urb status %d",urb->status);
+                               WARNING("urb status %d",urb->status);
                                break;
                }
        }
@@ -198,7 +198,7 @@ static void usb_int_complete(struct urb *urb)
                        DBG(2, "urb shutting down with status: %d", urb->status);
                        return;
                default:
-                       WARN("nonzero urb status received: %d", urb->status);
+                       WARNING("nonzero urb status received: %d", urb->status);
                        goto exit;
        }
 
@@ -235,7 +235,7 @@ static void usb_int_complete(struct urb *urb)
 exit:
        status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status)
-               WARN("usb_submit_urb failed with result %d", status);
+               WARNING("usb_submit_urb failed with result %d", status);
 }
 
 /* ======================================================================
@@ -257,7 +257,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
        DBG(2,"");
        
        if ((status = usb_reset_configuration (dev)) < 0) {
-               WARN("reset_configuration failed,status=%d",status);
+               WARNING("reset_configuration failed,status=%d",status);
                return status;
        }
 
@@ -269,7 +269,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
 
        // Check if the config is sane
        if ( altsetting->desc.bNumEndpoints != 7 ) {
-               WARN("expecting 7 got %d endpoints!", altsetting->desc.bNumEndpoints);
+               WARNING("expecting 7 got %d endpoints!", altsetting->desc.bNumEndpoints);
                return -EINVAL;
        }
 
@@ -279,7 +279,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
 
        // Use alternative setting 3 on interface 0 to have 2B+D
        if ((status = usb_set_interface (dev, 0, 3)) < 0) {
-               WARN("usb_set_interface failed,status=%d",status);
+               WARNING("usb_set_interface failed,status=%d",status);
                return status;
        }
 
@@ -497,7 +497,7 @@ static void usb_in_complete(struct urb *urb)
                                DBG(1,"urb killed status %d", urb->status);
                                return; // Give up
                        default: 
-                               WARN("urb status %d",urb->status);
+                               WARNING("urb status %d",urb->status);
                                break;
                }
        }
@@ -523,7 +523,7 @@ static void usb_in_complete(struct urb *urb)
                        DBG(4,"count=%d",status);
                        DBG_PACKET(0x400, in->rcvbuf, status);
                        if (!(skb = dev_alloc_skb(status))) {
-                               WARN("receive out of memory\n");
+                               WARNING("receive out of memory\n");
                                break;
                        }
                        memcpy(skb_put(skb, status), in->rcvbuf, status);
diff --git a/drivers/isdn/mISDN/Kconfig b/drivers/isdn/mISDN/Kconfig
new file mode 100644 (file)
index 0000000..4938355
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# modularer ISDN driver
+#
+
+menuconfig MISDN
+       tristate "Modular ISDN driver"
+       help
+         Enable support for the modular ISDN driver.
+
+if MISDN != n
+
+config MISDN_DSP
+       tristate "Digital Audio Processing of transparent data"
+       depends on MISDN
+       help
+         Enable support for digital audio processing capability.
+         This module may be used for special applications that require
+         cross connecting of bchannels, conferencing, dtmf decoding
+         echo cancelation, tone generation, and Blowfish encryption and
+         decryption.
+         It may use hardware features if available.
+         E.g. it is required for PBX4Linux. Go to http://isdn.eversberg.eu
+         and get more informations about this module and it's usage.
+         If unsure, say 'N'.
+
+config MISDN_L1OIP
+       tristate "ISDN over IP tunnel"
+       depends on MISDN
+       help
+         Enable support for ISDN over IP tunnel.
+
+         It features:
+           - dynamic IP exchange, if one or both peers have dynamic IPs
+           - BRI (S0) and PRI (S2M) interface
+           - layer 1 control via network keepalive frames
+           - direct tunneling of physical interface via IP
+
+         NOTE: This protocol is called 'Layer 1 over IP' and is not
+         compatible with ISDNoIP (Agfeo) or TDMoIP. Protocol description is
+         provided in the source code.
+
+source "drivers/isdn/hardware/mISDN/Kconfig"
+
+endif #MISDN
diff --git a/drivers/isdn/mISDN/Makefile b/drivers/isdn/mISDN/Makefile
new file mode 100644 (file)
index 0000000..1cb5e63
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for the modular ISDN driver
+#
+
+obj-$(CONFIG_MISDN) += mISDN_core.o
+obj-$(CONFIG_MISDN_DSP) += mISDN_dsp.o
+obj-$(CONFIG_MISDN_L1OIP) += l1oip.o
+
+# multi objects
+
+mISDN_core-objs := core.o fsm.o socket.o hwchannel.o stack.o layer1.o layer2.o tei.o timerdev.o
+mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_pipeline.o dsp_hwec.o
+l1oip-objs := l1oip_core.o l1oip_codec.o
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
new file mode 100644 (file)
index 0000000..3306817
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/mISDNif.h>
+#include "core.h"
+
+static u_int debug;
+
+MODULE_AUTHOR("Karsten Keil");
+MODULE_LICENSE("GPL");
+module_param(debug, uint, S_IRUGO | S_IWUSR);
+
+static LIST_HEAD(devices);
+DEFINE_RWLOCK(device_lock);
+static u64             device_ids;
+#define MAX_DEVICE_ID  63
+
+static LIST_HEAD(Bprotocols);
+DEFINE_RWLOCK(bp_lock);
+
+struct mISDNdevice
+*get_mdevice(u_int id)
+{
+       struct mISDNdevice      *dev;
+
+       read_lock(&device_lock);
+       list_for_each_entry(dev, &devices, D.list)
+               if (dev->id == id) {
+                       read_unlock(&device_lock);
+                       return dev;
+               }
+       read_unlock(&device_lock);
+       return NULL;
+}
+
+int
+get_mdevice_count(void)
+{
+       struct mISDNdevice      *dev;
+       int                     cnt = 0;
+
+       read_lock(&device_lock);
+       list_for_each_entry(dev, &devices, D.list)
+               cnt++;
+       read_unlock(&device_lock);
+       return cnt;
+}
+
+static int
+get_free_devid(void)
+{
+       u_int   i;
+
+       for (i = 0; i <= MAX_DEVICE_ID; i++)
+               if (!test_and_set_bit(i, (u_long *)&device_ids))
+                       return i;
+       return -1;
+}
+
+int
+mISDN_register_device(struct mISDNdevice *dev, char *name)
+{
+       u_long  flags;
+       int     err;
+
+       dev->id = get_free_devid();
+       if (dev->id < 0)
+               return -EBUSY;
+       if (name && name[0])
+               strcpy(dev->name, name);
+       else
+               sprintf(dev->name, "mISDN%d", dev->id);
+       if (debug & DEBUG_CORE)
+               printk(KERN_DEBUG "mISDN_register %s %d\n",
+                       dev->name, dev->id);
+       err = create_stack(dev);
+       if (err)
+               return err;
+       write_lock_irqsave(&device_lock, flags);
+       list_add_tail(&dev->D.list, &devices);
+       write_unlock_irqrestore(&device_lock, flags);
+       return 0;
+}
+EXPORT_SYMBOL(mISDN_register_device);
+
+void
+mISDN_unregister_device(struct mISDNdevice *dev) {
+       u_long  flags;
+
+       if (debug & DEBUG_CORE)
+               printk(KERN_DEBUG "mISDN_unregister %s %d\n",
+                       dev->name, dev->id);
+       write_lock_irqsave(&device_lock, flags);
+       list_del(&dev->D.list);
+       write_unlock_irqrestore(&device_lock, flags);
+       test_and_clear_bit(dev->id, (u_long *)&device_ids);
+       delete_stack(dev);
+}
+EXPORT_SYMBOL(mISDN_unregister_device);
+
+u_int
+get_all_Bprotocols(void)
+{
+       struct Bprotocol        *bp;
+       u_int   m = 0;
+
+       read_lock(&bp_lock);
+       list_for_each_entry(bp, &Bprotocols, list)
+               m |= bp->Bprotocols;
+       read_unlock(&bp_lock);
+       return m;
+}
+
+struct Bprotocol *
+get_Bprotocol4mask(u_int m)
+{
+       struct Bprotocol        *bp;
+
+       read_lock(&bp_lock);
+       list_for_each_entry(bp, &Bprotocols, list)
+               if (bp->Bprotocols & m) {
+                       read_unlock(&bp_lock);
+                       return bp;
+               }
+       read_unlock(&bp_lock);
+       return NULL;
+}
+
+struct Bprotocol *
+get_Bprotocol4id(u_int id)
+{
+       u_int   m;
+
+       if (id < ISDN_P_B_START || id > 63) {
+               printk(KERN_WARNING "%s id not in range  %d\n",
+                   __func__, id);
+               return NULL;
+       }
+       m = 1 << (id & ISDN_P_B_MASK);
+       return get_Bprotocol4mask(m);
+}
+
+int
+mISDN_register_Bprotocol(struct Bprotocol *bp)
+{
+       u_long                  flags;
+       struct Bprotocol        *old;
+
+       if (debug & DEBUG_CORE)
+               printk(KERN_DEBUG "%s: %s/%x\n", __func__,
+                   bp->name, bp->Bprotocols);
+       old = get_Bprotocol4mask(bp->Bprotocols);
+       if (old) {
+               printk(KERN_WARNING
+                   "register duplicate protocol old %s/%x new %s/%x\n",
+                   old->name, old->Bprotocols, bp->name, bp->Bprotocols);
+               return -EBUSY;
+       }
+       write_lock_irqsave(&bp_lock, flags);
+       list_add_tail(&bp->list, &Bprotocols);
+       write_unlock_irqrestore(&bp_lock, flags);
+       return 0;
+}
+EXPORT_SYMBOL(mISDN_register_Bprotocol);
+
+void
+mISDN_unregister_Bprotocol(struct Bprotocol *bp)
+{
+       u_long  flags;
+
+       if (debug & DEBUG_CORE)
+               printk(KERN_DEBUG "%s: %s/%x\n", __func__, bp->name,
+                       bp->Bprotocols);
+       write_lock_irqsave(&bp_lock, flags);
+       list_del(&bp->list);
+       write_unlock_irqrestore(&bp_lock, flags);
+}
+EXPORT_SYMBOL(mISDN_unregister_Bprotocol);
+
+int
+mISDNInit(void)
+{
+       int     err;
+
+       printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n",
+               MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE);
+       mISDN_initstack(&debug);
+       err = mISDN_inittimer(&debug);
+       if (err)
+               goto error;
+       err = l1_init(&debug);
+       if (err) {
+               mISDN_timer_cleanup();
+               goto error;
+       }
+       err = Isdnl2_Init(&debug);
+       if (err) {
+               mISDN_timer_cleanup();
+               l1_cleanup();
+               goto error;
+       }
+       err = misdn_sock_init(&debug);
+       if (err) {
+               mISDN_timer_cleanup();
+               l1_cleanup();
+               Isdnl2_cleanup();
+       }
+error:
+       return err;
+}
+
+void mISDN_cleanup(void)
+{
+       misdn_sock_cleanup();
+       mISDN_timer_cleanup();
+       l1_cleanup();
+       Isdnl2_cleanup();
+
+       if (!list_empty(&devices))
+               printk(KERN_ERR "%s devices still registered\n", __func__);
+
+       if (!list_empty(&Bprotocols))
+               printk(KERN_ERR "%s Bprotocols still registered\n", __func__);
+       printk(KERN_DEBUG "mISDNcore unloaded\n");
+}
+
+module_init(mISDNInit);
+module_exit(mISDN_cleanup);
+
diff --git a/drivers/isdn/mISDN/core.h b/drivers/isdn/mISDN/core.h
new file mode 100644 (file)
index 0000000..7da7233
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef mISDN_CORE_H
+#define mISDN_CORE_H
+
+extern struct mISDNdevice      *get_mdevice(u_int);
+extern int                     get_mdevice_count(void);
+
+/* stack status flag */
+#define mISDN_STACK_ACTION_MASK                0x0000ffff
+#define mISDN_STACK_COMMAND_MASK       0x000f0000
+#define mISDN_STACK_STATUS_MASK                0xfff00000
+/* action bits 0-15 */
+#define mISDN_STACK_WORK       0
+#define mISDN_STACK_SETUP      1
+#define mISDN_STACK_CLEARING   2
+#define mISDN_STACK_RESTART    3
+#define mISDN_STACK_WAKEUP     4
+#define mISDN_STACK_ABORT      15
+/* command bits 16-19 */
+#define mISDN_STACK_STOPPED    16
+#define mISDN_STACK_INIT       17
+#define mISDN_STACK_THREADSTART        18
+/* status bits 20-31 */
+#define mISDN_STACK_BCHANNEL   20
+#define mISDN_STACK_ACTIVE      29
+#define mISDN_STACK_RUNNING     30
+#define mISDN_STACK_KILLED      31
+
+
+/* manager options */
+#define MGR_OPT_USER           24
+#define MGR_OPT_NETWORK                25
+
+extern int     connect_Bstack(struct mISDNdevice *, struct mISDNchannel *,
+                       u_int, struct sockaddr_mISDN *);
+extern int     connect_layer1(struct mISDNdevice *, struct mISDNchannel *,
+                       u_int, struct sockaddr_mISDN *);
+extern int     create_l2entity(struct mISDNdevice *, struct mISDNchannel *,
+                       u_int, struct sockaddr_mISDN *);
+
+extern int     create_stack(struct mISDNdevice *);
+extern int     create_teimanager(struct mISDNdevice *);
+extern void    delete_teimanager(struct mISDNchannel *);
+extern void    delete_channel(struct mISDNchannel *);
+extern void    delete_stack(struct mISDNdevice *);
+extern void    mISDN_initstack(u_int *);
+extern int      misdn_sock_init(u_int *);
+extern void     misdn_sock_cleanup(void);
+extern void    add_layer2(struct mISDNchannel *, struct mISDNstack *);
+extern void    __add_layer2(struct mISDNchannel *, struct mISDNstack *);
+
+extern u_int           get_all_Bprotocols(void);
+struct Bprotocol       *get_Bprotocol4mask(u_int);
+struct Bprotocol       *get_Bprotocol4id(u_int);
+
+extern int     mISDN_inittimer(u_int *);
+extern void    mISDN_timer_cleanup(void);
+
+extern int     l1_init(u_int *);
+extern void    l1_cleanup(void);
+extern int     Isdnl2_Init(u_int *);
+extern void    Isdnl2_cleanup(void);
+
+#endif
diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h
new file mode 100644 (file)
index 0000000..6c3fed6
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Audio support data for ISDN4Linux.
+ *
+ * Copyright 2002/2003 by Andreas Eversberg (jolly@eversberg.eu)
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ */
+
+#define DEBUG_DSP_CTRL         0x0001
+#define DEBUG_DSP_CORE         0x0002
+#define DEBUG_DSP_DTMF         0x0004
+#define DEBUG_DSP_CMX          0x0010
+#define DEBUG_DSP_TONE         0x0020
+#define DEBUG_DSP_BLOWFISH     0x0040
+#define DEBUG_DSP_DELAY                0x0100
+#define DEBUG_DSP_DTMFCOEFF    0x8000 /* heavy output */
+
+/* options may be:
+ *
+ * bit 0 = use ulaw instead of alaw
+ * bit 1 = enable hfc hardware accelleration for all channels
+ *
+ */
+#define DSP_OPT_ULAW           (1<<0)
+#define DSP_OPT_NOHARDWARE     (1<<1)
+
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+
+#include "dsp_ecdis.h"
+
+extern int dsp_options;
+extern int dsp_debug;
+extern int dsp_poll;
+extern int dsp_tics;
+extern spinlock_t dsp_lock;
+extern struct work_struct dsp_workq;
+extern u32 dsp_poll_diff; /* calculated fix-comma corrected poll value */
+
+/***************
+ * audio stuff *
+ ***************/
+
+extern s32 dsp_audio_alaw_to_s32[256];
+extern s32 dsp_audio_ulaw_to_s32[256];
+extern s32 *dsp_audio_law_to_s32;
+extern u8 dsp_audio_s16_to_law[65536];
+extern u8 dsp_audio_alaw_to_ulaw[256];
+extern u8 dsp_audio_mix_law[65536];
+extern u8 dsp_audio_seven2law[128];
+extern u8 dsp_audio_law2seven[256];
+extern void dsp_audio_generate_law_tables(void);
+extern void dsp_audio_generate_s2law_table(void);
+extern void dsp_audio_generate_seven(void);
+extern void dsp_audio_generate_mix_table(void);
+extern void dsp_audio_generate_ulaw_samples(void);
+extern void dsp_audio_generate_volume_changes(void);
+extern u8 dsp_silence;
+
+
+/*************
+ * cmx stuff *
+ *************/
+
+#define MAX_POLL       256     /* maximum number of send-chunks */
+
+#define CMX_BUFF_SIZE  0x8000  /* must be 2**n (0x1000 about 1/2 second) */
+#define CMX_BUFF_HALF  0x4000  /* CMX_BUFF_SIZE / 2 */
+#define CMX_BUFF_MASK  0x7fff  /* CMX_BUFF_SIZE - 1 */
+
+/* how many seconds will we check the lowest delay until the jitter buffer
+   is reduced by that delay */
+#define MAX_SECONDS_JITTER_CHECK 5
+
+extern struct timer_list dsp_spl_tl;
+extern u32 dsp_spl_jiffies;
+
+/* the structure of conferences:
+ *
+ * each conference has a unique number, given by user space.
+ * the conferences are linked in a chain.
+ * each conference has members linked in a chain.
+ * each dsplayer points to a member, each member points to a dsplayer.
+ */
+
+/* all members within a conference (this is linked 1:1 with the dsp) */
+struct dsp;
+struct dsp_conf_member {
+       struct list_head        list;
+       struct dsp              *dsp;
+};
+
+/* the list of all conferences */
+struct dsp_conf {
+       struct list_head        list;
+       u32                     id;
+                               /* all cmx stacks with the same ID are
+                                connected */
+       struct list_head        mlist;
+       int                     software; /* conf is processed by software */
+       int                     hardware; /* conf is processed by hardware */
+                               /* note: if both unset, has only one member */
+};
+
+
+/**************
+ * DTMF stuff *
+ **************/
+
+#define DSP_DTMF_NPOINTS 102
+
+#define ECHOCAN_BUFLEN (4*128)
+
+struct dsp_dtmf {
+       int             treshold; /* above this is dtmf (square of) */
+       int             software; /* dtmf uses software decoding */
+       int             hardware; /* dtmf uses hardware decoding */
+       int             size; /* number of bytes in buffer */
+       signed short    buffer[DSP_DTMF_NPOINTS];
+               /* buffers one full dtmf frame */
+       u8              lastwhat, lastdigit;
+       int             count;
+       u8              digits[16]; /* just the dtmf result */
+};
+
+
+/******************
+ * pipeline stuff *
+ ******************/
+struct dsp_pipeline {
+       rwlock_t  lock;
+       struct list_head list;
+       int inuse;
+};
+
+/***************
+ * tones stuff *
+ ***************/
+
+struct dsp_tone {
+       int             software; /* tones are generated by software */
+       int             hardware; /* tones are generated by hardware */
+       int             tone;
+       void            *pattern;
+       int             count;
+       int             index;
+       struct timer_list tl;
+};
+
+/*****************
+ * general stuff *
+ *****************/
+
+struct dsp {
+       struct list_head list;
+       struct mISDNchannel     ch;
+       struct mISDNchannel     *up;
+       unsigned char   name[64];
+       int             b_active;
+       int             echo; /* echo is enabled */
+       int             rx_disabled; /* what the user wants */
+       int             rx_is_off; /* what the card is */
+       int             tx_mix;
+       struct dsp_tone tone;
+       struct dsp_dtmf dtmf;
+       int             tx_volume, rx_volume;
+
+       /* queue for sending frames */
+       struct work_struct      workq;
+       struct sk_buff_head     sendq;
+       int             hdlc;   /* if mode is hdlc */
+       int             data_pending;   /* currently an unconfirmed frame */
+
+       /* conference stuff */
+       u32             conf_id;
+       struct dsp_conf *conf;
+       struct dsp_conf_member
+                       *member;
+
+       /* buffer stuff */
+       int             rx_W; /* current write pos for data without timestamp */
+       int             rx_R; /* current read pos for transmit clock */
+       int             rx_init; /* if set, pointers will be adjusted first */
+       int             tx_W; /* current write pos for transmit data */
+       int             tx_R; /* current read pos for transmit clock */
+       int             rx_delay[MAX_SECONDS_JITTER_CHECK];
+       int             tx_delay[MAX_SECONDS_JITTER_CHECK];
+       u8              tx_buff[CMX_BUFF_SIZE];
+       u8              rx_buff[CMX_BUFF_SIZE];
+       int             last_tx; /* if set, we transmitted last poll interval */
+       int             cmx_delay; /* initial delay of buffers,
+                               or 0 for dynamic jitter buffer */
+       int             tx_dejitter; /* if set, dejitter tx buffer */
+       int             tx_data; /* enables tx-data of CMX to upper layer */
+
+       /* hardware stuff */
+       struct dsp_features features;
+       int             features_rx_off; /* set if rx_off is featured */
+       int             pcm_slot_rx; /* current PCM slot (or -1) */
+       int             pcm_bank_rx;
+       int             pcm_slot_tx;
+       int             pcm_bank_tx;
+       int             hfc_conf; /* unique id of current conference (or -1) */
+
+       /* encryption stuff */
+       int             bf_enable;
+       u32             bf_p[18];
+       u32             bf_s[1024];
+       int             bf_crypt_pos;
+       u8              bf_data_in[9];
+       u8              bf_crypt_out[9];
+       int             bf_decrypt_in_pos;
+       int             bf_decrypt_out_pos;
+       u8              bf_crypt_inring[16];
+       u8              bf_data_out[9];
+       int             bf_sync;
+
+       struct dsp_pipeline
+                       pipeline;
+};
+
+/* functions */
+
+extern void dsp_change_volume(struct sk_buff *skb, int volume);
+
+extern struct list_head dsp_ilist;
+extern struct list_head conf_ilist;
+extern void dsp_cmx_debug(struct dsp *dsp);
+extern void dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp);
+extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id);
+extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb);
+extern void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb);
+extern void dsp_cmx_send(void *arg);
+extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb);
+extern int dsp_cmx_del_conf_member(struct dsp *dsp);
+extern int dsp_cmx_del_conf(struct dsp_conf *conf);
+
+extern void dsp_dtmf_goertzel_init(struct dsp *dsp);
+extern void dsp_dtmf_hardware(struct dsp *dsp);
+extern u8 *dsp_dtmf_goertzel_decode(struct dsp *dsp, u8 *data, int len,
+               int fmt);
+
+extern int dsp_tone(struct dsp *dsp, int tone);
+extern void dsp_tone_copy(struct dsp *dsp, u8 *data, int len);
+extern void dsp_tone_timeout(void *arg);
+
+extern void dsp_bf_encrypt(struct dsp *dsp, u8 *data, int len);
+extern void dsp_bf_decrypt(struct dsp *dsp, u8 *data, int len);
+extern int dsp_bf_init(struct dsp *dsp, const u8 *key, unsigned int keylen);
+extern void dsp_bf_cleanup(struct dsp *dsp);
+
+extern int  dsp_pipeline_module_init(void);
+extern void dsp_pipeline_module_exit(void);
+extern int  dsp_pipeline_init(struct dsp_pipeline *pipeline);
+extern void dsp_pipeline_destroy(struct dsp_pipeline *pipeline);
+extern int  dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg);
+extern void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data,
+               int len);
+extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data,
+               int len);
+
diff --git a/drivers/isdn/mISDN/dsp_audio.c b/drivers/isdn/mISDN/dsp_audio.c
new file mode 100644 (file)
index 0000000..1c2dd56
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * Audio support data for mISDN_dsp.
+ *
+ * Copyright 2002/2003 by Andreas Eversberg (jolly@eversberg.eu)
+ * Rewritten by Peter
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/mISDNif.h>
+#include <linux/mISDNdsp.h>
+#include "core.h"
+#include "dsp.h"
+
+/* ulaw[unsigned char] -> signed 16-bit */
+s32 dsp_audio_ulaw_to_s32[256];
+/* alaw[unsigned char] -> signed 16-bit */
+s32 dsp_audio_alaw_to_s32[256];
+
+s32 *dsp_audio_law_to_s32;
+EXPORT_SYMBOL(dsp_audio_law_to_s32);
+
+/* signed 16-bit -> law */
+u8 dsp_audio_s16_to_law[65536];
+EXPORT_SYMBOL(dsp_audio_s16_to_law);
+
+/* alaw -> ulaw */
+u8 dsp_audio_alaw_to_ulaw[256];
+/* ulaw -> alaw */
+u8 dsp_audio_ulaw_to_alaw[256];
+u8 dsp_silence;
+
+
+/*****************************************************
+ * generate table for conversion of s16 to alaw/ulaw *
+ *****************************************************/
+
+#define AMI_MASK 0x55
+
+static inline unsigned char linear2alaw(short int linear)
+{
+       int mask;
+       int seg;
+       int pcm_val;
+       static int seg_end[8] = {
+               0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
+       };
+
+       pcm_val = linear;
+       if (pcm_val >= 0) {
+               /* Sign (7th) bit = 1 */
+               mask = AMI_MASK | 0x80;
+       } else {
+               /* Sign bit = 0 */
+               mask = AMI_MASK;
+               pcm_val = -pcm_val;
+       }
+
+       /* Convert the scaled magnitude to segment number. */
+       for (seg = 0;  seg < 8;  seg++) {
+               if (pcm_val <= seg_end[seg])
+                       break;
+       }
+       /* Combine the sign, segment, and quantization bits. */
+       return  ((seg << 4) |
+                ((pcm_val >> ((seg)  ?  (seg + 3)  :  4)) & 0x0F)) ^ mask;
+}
+
+
+static inline short int alaw2linear(unsigned char alaw)
+{
+       int i;
+       int seg;
+
+       alaw ^= AMI_MASK;
+       i = ((alaw & 0x0F) << 4) + 8 /* rounding error */;
+       seg = (((int) alaw & 0x70) >> 4);
+       if (seg)
+               i = (i + 0x100) << (seg - 1);
+       return (short int) ((alaw & 0x80)  ?  i  :  -i);
+}
+
+static inline short int ulaw2linear(unsigned char ulaw)
+{
+       short mu, e, f, y;
+       static short etab[] = {0, 132, 396, 924, 1980, 4092, 8316, 16764};
+
+       mu = 255 - ulaw;
+       e = (mu & 0x70) / 16;
+       f = mu & 0x0f;
+       y = f * (1 << (e + 3));
+       y += etab[e];
+       if (mu & 0x80)
+               y = -y;
+       return y;
+}
+
+#define BIAS 0x84   /*!< define the add-in bias for 16 bit samples */
+
+static unsigned char linear2ulaw(short sample)
+{
+       static int exp_lut[256] = {
+               0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+               4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+               5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+               5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
+       int sign, exponent, mantissa;
+       unsigned char ulawbyte;
+
+       /* Get the sample into sign-magnitude. */
+       sign = (sample >> 8) & 0x80;      /* set aside the sign */
+       if (sign != 0)
+               sample = -sample;             /* get magnitude */
+
+       /* Convert from 16 bit linear to ulaw. */
+       sample = sample + BIAS;
+       exponent = exp_lut[(sample >> 7) & 0xFF];
+       mantissa = (sample >> (exponent + 3)) & 0x0F;
+       ulawbyte = ~(sign | (exponent << 4) | mantissa);
+
+       return ulawbyte;
+}
+
+static int reverse_bits(int i)
+{
+       int z, j;
+       z = 0;
+
+       for (j = 0; j < 8; j++) {
+               if ((i & (1 << j)) != 0)
+                       z |= 1 << (7 - j);
+       }
+       return z;
+}
+
+
+void dsp_audio_generate_law_tables(void)
+{
+       int i;
+       for (i = 0; i < 256; i++)
+               dsp_audio_alaw_to_s32[i] = alaw2linear(reverse_bits(i));
+
+       for (i = 0; i < 256; i++)
+               dsp_audio_ulaw_to_s32[i] = ulaw2linear(reverse_bits(i));
+
+       for (i = 0; i < 256; i++) {
+               dsp_audio_alaw_to_ulaw[i] =
+                       linear2ulaw(dsp_audio_alaw_to_s32[i]);
+               dsp_audio_ulaw_to_alaw[i] =
+                       linear2alaw(dsp_audio_ulaw_to_s32[i]);
+       }
+}
+
+void
+dsp_audio_generate_s2law_table(void)
+{
+       int i;
+
+       if (dsp_options & DSP_OPT_ULAW) {
+               /* generating ulaw-table */
+               for (i = -32768; i < 32768; i++) {
+                       dsp_audio_s16_to_law[i & 0xffff] =
+                               reverse_bits(linear2ulaw(i));
+               }
+       } else {
+               /* generating alaw-table */
+               for (i = -32768; i < 32768; i++) {
+                       dsp_audio_s16_to_law[i & 0xffff] =
+                               reverse_bits(linear2alaw(i));
+               }
+       }
+}
+
+
+/*
+ * the seven bit sample is the number of every second alaw-sample ordered by
+ * aplitude. 0x00 is negative, 0x7f is positive amplitude.
+ */
+u8 dsp_audio_seven2law[128];
+u8 dsp_audio_law2seven[256];
+
+/********************************************************************
+ * generate table for conversion law from/to 7-bit alaw-like sample *
+ ********************************************************************/
+
+void
+dsp_audio_generate_seven(void)
+{
+       int i, j, k;
+       u8 spl;
+       u8 sorted_alaw[256];
+
+       /* generate alaw table, sorted by the linear value */
+       for (i = 0; i < 256; i++) {
+               j = 0;
+               for (k = 0; k < 256; k++) {
+                       if (dsp_audio_alaw_to_s32[k]
+                               < dsp_audio_alaw_to_s32[i]) {
+                       j++;
+                       }
+               }
+               sorted_alaw[j] = i;
+       }
+
+       /* generate tabels */
+       for (i = 0; i < 256; i++) {
+               /* spl is the source: the law-sample (converted to alaw) */
+               spl = i;
+               if (dsp_options & DSP_OPT_ULAW)
+                       spl = dsp_audio_ulaw_to_alaw[i];
+               /* find the 7-bit-sample */
+               for (j = 0; j < 256; j++) {
+                       if (sorted_alaw[j] == spl)
+                               break;
+               }
+               /* write 7-bit audio value */
+               dsp_audio_law2seven[i] = j >> 1;
+       }
+       for (i = 0; i < 128; i++) {
+               spl = sorted_alaw[i << 1];
+               if (dsp_options & DSP_OPT_ULAW)
+                       spl = dsp_audio_alaw_to_ulaw[spl];
+               dsp_audio_seven2law[i] = spl;
+       }
+}
+
+
+/* mix 2*law -> law */
+u8 dsp_audio_mix_law[65536];
+
+/******************************************************
+ * generate mix table to mix two law samples into one *
+ ******************************************************/
+
+void
+dsp_audio_generate_mix_table(void)
+{
+       int i, j;
+       s32 sample;
+
+       i = 0;
+       while (i < 256) {
+               j = 0;
+               while (j < 256) {
+                       sample = dsp_audio_law_to_s32[i];
+                       sample += dsp_audio_law_to_s32[j];
+                       if (sample > 32767)
+                               sample = 32767;
+                       if (sample < -32768)
+                               sample = -32768;
+                       dsp_audio_mix_law[(i<<8)|j] =
+                               dsp_audio_s16_to_law[sample & 0xffff];
+                       j++;
+               }
+               i++;
+       }
+}
+
+
+/*************************************
+ * generate different volume changes *
+ *************************************/
+
+static u8 dsp_audio_reduce8[256];
+static u8 dsp_audio_reduce7[256];
+static u8 dsp_audio_reduce6[256];
+static u8 dsp_audio_reduce5[256];
+static u8 dsp_audio_reduce4[256];
+static u8 dsp_audio_reduce3[256];
+static u8 dsp_audio_reduce2[256];
+static u8 dsp_audio_reduce1[256];
+static u8 dsp_audio_increase1[256];
+static u8 dsp_audio_increase2[256];
+static u8 dsp_audio_increase3[256];
+static u8 dsp_audio_increase4[256];
+static u8 dsp_audio_increase5[256];
+static u8 dsp_audio_increase6[256];
+static u8 dsp_audio_increase7[256];
+static u8 dsp_audio_increase8[256];
+
+static u8 *dsp_audio_volume_change[16] = {
+       dsp_audio_reduce8,
+       dsp_audio_reduce7,
+       dsp_audio_reduce6,
+       dsp_audio_reduce5,
+       dsp_audio_reduce4,
+       dsp_audio_reduce3,
+       dsp_audio_reduce2,
+       dsp_audio_reduce1,
+       dsp_audio_increase1,
+       dsp_audio_increase2,
+       dsp_audio_increase3,
+       dsp_audio_increase4,
+       dsp_audio_increase5,
+       dsp_audio_increase6,
+       dsp_audio_increase7,
+       dsp_audio_increase8,
+};
+
+void
+dsp_audio_generate_volume_changes(void)
+{
+       register s32 sample;
+       int i;
+       int num[]   = { 110, 125, 150, 175, 200, 300, 400, 500 };
+       int denum[] = { 100, 100, 100, 100, 100, 100, 100, 100 };
+
+       i = 0;
+       while (i < 256) {
+               dsp_audio_reduce8[i] = dsp_audio_s16_to_law[
+                       (dsp_audio_law_to_s32[i] * denum[7] / num[7]) & 0xffff];
+               dsp_audio_reduce7[i] = dsp_audio_s16_to_law[
+                       (dsp_audio_law_to_s32[i] * denum[6] / num[6]) & 0xffff];
+               dsp_audio_reduce6[i] = dsp_audio_s16_to_law[
+                       (dsp_audio_law_to_s32[i] * denum[5] / num[5]) & 0xffff];
+               dsp_audio_reduce5[i] = dsp_audio_s16_to_law[
+                       (dsp_audio_law_to_s32[i] * denum[4] / num[4]) & 0xffff];
+               dsp_audio_reduce4[i] = dsp_audio_s16_to_law[
+                       (dsp_audio_law_to_s32[i] * denum[3] / num[3]) & 0xffff];
+               dsp_audio_reduce3[i] = dsp_audio_s16_to_law[
+                       (dsp_audio_law_to_s32[i] * denum[2] / num[2]) & 0xffff];
+               dsp_audio_reduce2[i] = dsp_audio_s16_to_law[
+                       (dsp_audio_law_to_s32[i] * denum[1] / num[1]) & 0xffff];
+               dsp_audio_reduce1[i] = dsp_audio_s16_to_law[
+                       (dsp_audio_law_to_s32[i] * denum[0] / num[0]) & 0xffff];
+               sample = dsp_audio_law_to_s32[i] * num[0] / denum[0];
+               if (sample < -32768)
+                       sample = -32768;
+               else if (sample > 32767)
+                       sample = 32767;
+               dsp_audio_increase1[i] = dsp_audio_s16_to_law[sample & 0xffff];
+               sample = dsp_audio_law_to_s32[i] * num[1] / denum[1];
+               if (sample < -32768)
+                       sample = -32768;
+               else if (sample > 32767)
+                       sample = 32767;
+               dsp_audio_increase2[i] = dsp_audio_s16_to_law[sample & 0xffff];
+               sample = dsp_audio_law_to_s32[i] * num[2] / denum[2];
+               if (sample < -32768)
+                       sample = -32768;
+               else if (sample > 32767)
+                       sample = 32767;
+               dsp_audio_increase3[i] = dsp_audio_s16_to_law[sample & 0xffff];
+               sample = dsp_audio_law_to_s32[i] * num[3] / denum[3];
+               if (sample < -32768)
+                       sample = -32768;
+               else if (sample > 32767)
+                       sample = 32767;
+               dsp_audio_increase4[i] = dsp_audio_s16_to_law[sample & 0xffff];
+               sample = dsp_audio_law_to_s32[i] * num[4] / denum[4];
+               if (sample < -32768)
+                       sample = -32768;
+               else if (sample > 32767)
+                       sample = 32767;
+               dsp_audio_increase5[i] = dsp_audio_s16_to_law[sample & 0xffff];
+               sample = dsp_audio_law_to_s32[i] * num[5] / denum[5];
+               if (sample < -32768)
+                       sample = -32768;
+               else if (sample > 32767)
+                       sample = 32767;
+               dsp_audio_increase6[i] = dsp_audio_s16_to_law[sample & 0xffff];
+               sample = dsp_audio_law_to_s32[i] * num[6] / denum[6];
+               if (sample < -32768)
+                       sample = -32768;
+               else if (sample > 32767)
+                       sample = 32767;
+               dsp_audio_increase7[i] = dsp_audio_s16_to_law[sample & 0xffff];
+               sample = dsp_audio_law_to_s32[i] * num[7] / denum[7];
+               if (sample < -32768)
+                       sample = -32768;
+               else if (sample > 32767)
+                       sample = 32767;
+               dsp_audio_increase8[i] = dsp_audio_s16_to_law[sample & 0xffff];
+
+               i++;
+       }
+}
+
+
+/**************************************
+ * change the volume of the given skb *
+ **************************************/
+
+/* this is a helper function for changing volume of skb. the range may be
+ * -8 to 8, which is a shift to the power of 2. 0 == no volume, 3 == volume*8
+ */
+void
+dsp_change_volume(struct sk_buff *skb, int volume)
+{
+       u8 *volume_change;
+       int i, ii;
+       u8 *p;
+       int shift;
+
+       if (volume == 0)
+               return;
+
+       /* get correct conversion table */
+       if (volume < 0) {
+               shift = volume + 8;
+               if (shift < 0)
+                       shift = 0;
+       } else {
+               shift = volume + 7;
+               if (shift > 15)
+                       shift = 15;
+       }
+       volume_change = dsp_audio_volume_change[shift];
+       i = 0;
+       ii = skb->len;
+       p = skb->data;
+       /* change volume */
+       while (i < ii) {
+               *p = volume_change[*p];
+               p++;
+               i++;
+       }
+}
+
diff --git a/drivers/isdn/mISDN/dsp_biquad.h b/drivers/isdn/mISDN/dsp_biquad.h
new file mode 100644 (file)
index 0000000..038191b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * biquad.h - General telephony bi-quad section routines (currently this just
+ *            handles canonic/type 2 form)
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2001 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+struct biquad2_state {
+       int32_t gain;
+       int32_t a1;
+       int32_t a2;
+       int32_t b1;
+       int32_t b2;
+
+       int32_t z1;
+       int32_t z2;
+};
+
+static inline void biquad2_init(struct biquad2_state *bq,
+    int32_t gain, int32_t a1, int32_t a2, int32_t b1, int32_t b2)
+{
+       bq->gain = gain;
+       bq->a1 = a1;
+       bq->a2 = a2;
+       bq->b1 = b1;
+       bq->b2 = b2;
+
+       bq->z1 = 0;
+       bq->z2 = 0;
+}
+
+static inline int16_t biquad2(struct biquad2_state *bq, int16_t sample)
+{
+       int32_t y;
+       int32_t z0;
+
+       z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2;
+       y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2;
+
+       bq->z2 = bq->z1;
+       bq->z1 = z0 >> 15;
+       y >>= 15;
+       return  y;
+}
diff --git a/drivers/isdn/mISDN/dsp_blowfish.c b/drivers/isdn/mISDN/dsp_blowfish.c
new file mode 100644 (file)
index 0000000..18e411e
--- /dev/null
@@ -0,0 +1,672 @@
+/*
+ * Blowfish encryption/decryption for mISDN_dsp.
+ *
+ * Copyright Andreas Eversberg (jolly@eversberg.eu)
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ */
+
+#include <linux/mISDNif.h>
+#include <linux/mISDNdsp.h>
+#include "core.h"
+#include "dsp.h"
+
+/*
+ * how to encode a sample stream to 64-bit blocks that will be encryped
+ *
+ * first of all, data is collected until a block of 9 samples are received.
+ * of course, a packet may have much more than 9 sample, but is may have
+ * not excacly the multiple of 9 samples. if there is a rest, the next
+ * received data will complete the block.
+ *
+ * the block is then converted to 9 uLAW samples without the least sigificant
+ * bit. the result is a 7-bit encoded sample.
+ *
+ * the samples will be reoganised to form 8 bytes of data:
+ * (5(6) means: encoded sample no. 5, bit 6)
+ *
+ * 0(6) 0(5) 0(4) 0(3) 0(2) 0(1) 0(0) 1(6)
+ * 1(5) 1(4) 1(3) 1(2) 1(1) 1(0) 2(6) 2(5)
+ * 2(4) 2(3) 2(2) 2(1) 2(0) 3(6) 3(5) 3(4)
+ * 3(3) 3(2) 3(1) 3(0) 4(6) 4(5) 4(4) 4(3)
+ * 4(2) 4(1) 4(0) 5(6) 5(5) 5(4) 5(3) 5(2)
+ * 5(1) 5(0) 6(6) 6(5) 6(4) 6(3) 6(2) 6(1)
+ * 6(0) 7(6) 7(5) 7(4) 7(3) 7(2) 7(1) 7(0)
+ * 8(6) 8(5) 8(4) 8(3) 8(2) 8(1) 8(0)
+ *
+ * the missing bit 0 of the last byte is filled with some
+ * random noise, to fill all 8 bytes.
+ *
+ * the 8 bytes will be encrypted using blowfish.
+ *
+ * the result will be converted into 9 bytes. the bit 7 is used for
+ * checksumme (CS) for sync (0, 1) and for the last bit:
+ * (5(6) means: crypted byte 5, bit 6)
+ *
+ * 1    0(7) 0(6) 0(5) 0(4) 0(3) 0(2) 0(1)
+ * 0    0(0) 1(7) 1(6) 1(5) 1(4) 1(3) 1(2)
+ * 0    1(1) 1(0) 2(7) 2(6) 2(5) 2(4) 2(3)
+ * 0    2(2) 2(1) 2(0) 3(7) 3(6) 3(5) 3(4)
+ * 0    3(3) 3(2) 3(1) 3(0) 4(7) 4(6) 4(5)
+ * CS   4(4) 4(3) 4(2) 4(1) 4(0) 5(7) 5(6)
+ * CS   5(5) 5(4) 5(3) 5(2) 5(1) 5(0) 6(7)
+ * CS   6(6) 6(5) 6(4) 6(3) 6(2) 6(1) 6(0)
+ * 7(0) 7(6) 7(5) 7(4) 7(3) 7(2) 7(1) 7(0)
+ *
+ * the checksum is used to detect transmission errors and frame drops.
+ *
+ * synchronisation of received block is done by shifting the upper bit of each
+ * byte (bit 7) to a shift register. if the rigister has the first five bits
+ * (10000), this is used to find the sync. only if sync has been found, the
+ * current block of 9 received bytes are decrypted. before that the check
+ * sum is calculated. if it is incorrect the block is dropped.
+ * this will avoid loud noise due to corrupt encrypted data.
+ *
+ * if the last block is corrupt, the current decoded block is repeated
+ * until a valid block has been received.
+ */
+
+/*
+ *  some blowfish parts are taken from the
+ * crypto-api for faster implementation
+ */
+
+struct bf_ctx {
+       u32 p[18];
+       u32 s[1024];
+};
+
+static const u32 bf_pbox[16 + 2] = {
+       0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+       0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+       0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+       0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+       0x9216d5d9, 0x8979fb1b,
+};
+
+static const u32 bf_sbox[256 * 4] = {
+       0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+       0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+       0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+       0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+       0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+       0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+       0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+       0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+       0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+       0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+       0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+       0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+       0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+       0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+       0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+       0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+       0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+       0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+       0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+       0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+       0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+       0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+       0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+       0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+       0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+       0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+       0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+       0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+       0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+       0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+       0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+       0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+       0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+       0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+       0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+       0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+       0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+       0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+       0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+       0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+       0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+       0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+       0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+       0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+       0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+       0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+       0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+       0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+       0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+       0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+       0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+       0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+       0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+       0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+       0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+       0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+       0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+       0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+       0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+       0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+       0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+       0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+       0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+       0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+       0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+       0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+       0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+       0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+       0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+       0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+       0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+       0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+       0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+       0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+       0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+       0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+       0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+       0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+       0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+       0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+       0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+       0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+       0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+       0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+       0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+       0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+       0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+       0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+       0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+       0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+       0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+       0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+       0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+       0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+       0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+       0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+       0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+       0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+       0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+       0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+       0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+       0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+       0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+       0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+       0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+       0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+       0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+       0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+       0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+       0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+       0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+       0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+       0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+       0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+       0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+       0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+       0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+       0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+       0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+       0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+       0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+       0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+       0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+       0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+       0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+       0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+       0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+       0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+       0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+       0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+       0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+       0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+       0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+       0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+       0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+       0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+       0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+       0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+       0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+       0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+       0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+       0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+       0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+       0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+       0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+       0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+       0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+       0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+       0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+       0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+       0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+       0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+       0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+       0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+       0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+       0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+       0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+       0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+       0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+       0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+       0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+       0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+       0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+       0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+       0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+       0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+       0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+       0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+       0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+       0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+       0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+       0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+       0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+       0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+       0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+       0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+       0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+       0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+       0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+       0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+       0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+       0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+       0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+       0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+       0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+       0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+       0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+       0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+       0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+       0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+       0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+       0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+       0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+       0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+       0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+       0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+       0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+       0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+       0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+       0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+       0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+       0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+       0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+       0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+       0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+       0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+       0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+       0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+       0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+       0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+       0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+       0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+       0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+       0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+       0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+       0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+       0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+       0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+       0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+       0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+       0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+       0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+       0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+       0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+       0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+       0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+       0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+       0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+       0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+       0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+       0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+       0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+       0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+       0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+       0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+       0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+       0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+       0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+       0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+       0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+       0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+       0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+       0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+       0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+       0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+       0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+       0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+       0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+       0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+       0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+       0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+       0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+       0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+       0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+       0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+       0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
+};
+
+/*
+ * Round loop unrolling macros, S is a pointer to a S-Box array
+ * organized in 4 unsigned longs at a row.
+ */
+#define GET32_3(x) (((x) & 0xff))
+#define GET32_2(x) (((x) >> (8)) & (0xff))
+#define GET32_1(x) (((x) >> (16)) & (0xff))
+#define GET32_0(x) (((x) >> (24)) & (0xff))
+
+#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
+    S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
+
+#define EROUND(a, b, n)  do { b ^= P[n]; a ^= bf_F(b); } while (0)
+#define DROUND(a, b, n)  do { a ^= bf_F(b); b ^= P[n]; } while (0)
+
+
+/*
+ * encrypt isdn data frame
+ * every block with 9 samples is encrypted
+ */
+void
+dsp_bf_encrypt(struct dsp *dsp, u8 *data, int len)
+{
+       int i = 0, j = dsp->bf_crypt_pos;
+       u8 *bf_data_in = dsp->bf_data_in;
+       u8 *bf_crypt_out = dsp->bf_crypt_out;
+       u32 *P = dsp->bf_p;
+       u32 *S = dsp->bf_s;
+       u32 yl, yr;
+       u32 cs;
+       u8 nibble;
+
+       while (i < len) {
+               /* collect a block of 9 samples */
+               if (j < 9) {
+                       bf_data_in[j] = *data;
+                       *data++ = bf_crypt_out[j++];
+                       i++;
+                       continue;
+               }
+               j = 0;
+               /* transcode 9 samples xlaw to 8 bytes */
+               yl = dsp_audio_law2seven[bf_data_in[0]];
+               yl = (yl<<7) | dsp_audio_law2seven[bf_data_in[1]];
+               yl = (yl<<7) | dsp_audio_law2seven[bf_data_in[2]];
+               yl = (yl<<7) | dsp_audio_law2seven[bf_data_in[3]];
+               nibble = dsp_audio_law2seven[bf_data_in[4]];
+               yr = nibble;
+               yl = (yl<<4) | (nibble>>3);
+               yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[5]];
+               yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[6]];
+               yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[7]];
+               yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[8]];
+               yr = (yr<<1) | (bf_data_in[0] & 1);
+
+               /* fill unused bit with random noise of audio input */
+               /* encrypt */
+
+               EROUND(yr, yl, 0);
+               EROUND(yl, yr, 1);
+               EROUND(yr, yl, 2);
+               EROUND(yl, yr, 3);
+               EROUND(yr, yl, 4);
+               EROUND(yl, yr, 5);
+               EROUND(yr, yl, 6);
+               EROUND(yl, yr, 7);
+               EROUND(yr, yl, 8);
+               EROUND(yl, yr, 9);
+               EROUND(yr, yl, 10);
+               EROUND(yl, yr, 11);
+               EROUND(yr, yl, 12);
+               EROUND(yl, yr, 13);
+               EROUND(yr, yl, 14);
+               EROUND(yl, yr, 15);
+               yl ^= P[16];
+               yr ^= P[17];
+
+               /* calculate 3-bit checksumme */
+               cs = yl ^ (yl>>3) ^ (yl>>6) ^ (yl>>9) ^ (yl>>12) ^ (yl>>15)
+                       ^ (yl>>18) ^ (yl>>21) ^ (yl>>24) ^ (yl>>27) ^ (yl>>30)
+                       ^ (yr<<2) ^ (yr>>1) ^ (yr>>4) ^ (yr>>7) ^ (yr>>10)
+                       ^ (yr>>13) ^ (yr>>16) ^ (yr>>19) ^ (yr>>22) ^ (yr>>25)
+                       ^ (yr>>28) ^ (yr>>31);
+
+               /*
+                * transcode 8 crypted bytes to 9 data bytes with sync
+                * and checksum information
+                */
+               bf_crypt_out[0] = (yl>>25) | 0x80;
+               bf_crypt_out[1] = (yl>>18) & 0x7f;
+               bf_crypt_out[2] = (yl>>11) & 0x7f;
+               bf_crypt_out[3] = (yl>>4) & 0x7f;
+               bf_crypt_out[4] = ((yl<<3) & 0x78) | ((yr>>29) & 0x07);
+               bf_crypt_out[5] = ((yr>>22) & 0x7f) | ((cs<<5) & 0x80);
+               bf_crypt_out[6] = ((yr>>15) & 0x7f) | ((cs<<6) & 0x80);
+               bf_crypt_out[7] = ((yr>>8) & 0x7f) | (cs<<7);
+               bf_crypt_out[8] = yr;
+       }
+
+       /* write current count */
+       dsp->bf_crypt_pos = j;
+
+}
+
+
+/*
+ * decrypt isdn data frame
+ * every block with 9 bytes is decrypted
+ */
+void
+dsp_bf_decrypt(struct dsp *dsp, u8 *data, int len)
+{
+       int i = 0;
+       u8 j = dsp->bf_decrypt_in_pos;
+       u8 k = dsp->bf_decrypt_out_pos;
+       u8 *bf_crypt_inring = dsp->bf_crypt_inring;
+       u8 *bf_data_out = dsp->bf_data_out;
+       u16 sync = dsp->bf_sync;
+       u32 *P = dsp->bf_p;
+       u32 *S = dsp->bf_s;
+       u32 yl, yr;
+       u8 nibble;
+       u8 cs, cs0, cs1, cs2;
+
+       while (i < len) {
+               /*
+                * shift upper bit and rotate data to buffer ring
+                * send current decrypted data
+                */
+               sync = (sync<<1) | ((*data)>>7);
+               bf_crypt_inring[j++ & 15] = *data;
+               *data++ = bf_data_out[k++];
+               i++;
+               if (k == 9)
+                       k = 0; /* repeat if no sync has been found */
+               /* check if not in sync */
+               if ((sync&0x1f0) != 0x100)
+                       continue;
+               j -= 9;
+               /* transcode receive data to 64 bit block of encrypted data */
+               yl = bf_crypt_inring[j++ & 15];
+               yl = (yl<<7) | bf_crypt_inring[j++ & 15]; /* bit7 = 0 */
+               yl = (yl<<7) | bf_crypt_inring[j++ & 15]; /* bit7 = 0 */
+               yl = (yl<<7) | bf_crypt_inring[j++ & 15]; /* bit7 = 0 */
+               nibble = bf_crypt_inring[j++ & 15]; /* bit7 = 0 */
+               yr = nibble;
+               yl = (yl<<4) | (nibble>>3);
+               cs2 = bf_crypt_inring[j++ & 15];
+               yr = (yr<<7) | (cs2 & 0x7f);
+               cs1 = bf_crypt_inring[j++ & 15];
+               yr = (yr<<7) | (cs1 & 0x7f);
+               cs0 = bf_crypt_inring[j++ & 15];
+               yr = (yr<<7) | (cs0 & 0x7f);
+               yr = (yr<<8) | bf_crypt_inring[j++ & 15];
+
+               /* calculate 3-bit checksumme */
+               cs = yl ^ (yl>>3) ^ (yl>>6) ^ (yl>>9) ^ (yl>>12) ^ (yl>>15)
+                       ^ (yl>>18) ^ (yl>>21) ^ (yl>>24) ^ (yl>>27) ^ (yl>>30)
+                       ^ (yr<<2) ^ (yr>>1) ^ (yr>>4) ^ (yr>>7) ^ (yr>>10)
+                       ^ (yr>>13) ^ (yr>>16) ^ (yr>>19) ^ (yr>>22) ^ (yr>>25)
+                       ^ (yr>>28) ^ (yr>>31);
+
+               /* check if frame is valid */
+               if ((cs&0x7) != (((cs2>>5)&4) | ((cs1>>6)&2) | (cs0 >> 7))) {
+                       if (dsp_debug & DEBUG_DSP_BLOWFISH)
+                               printk(KERN_DEBUG
+                                   "DSP BLOWFISH: received corrupt frame, "
+                                   "checksumme is not correct\n");
+                       continue;
+               }
+
+               /* decrypt */
+               yr ^= P[17];
+               yl ^= P[16];
+               DROUND(yl, yr, 15);
+               DROUND(yr, yl, 14);
+               DROUND(yl, yr, 13);
+               DROUND(yr, yl, 12);
+               DROUND(yl, yr, 11);
+               DROUND(yr, yl, 10);
+               DROUND(yl, yr, 9);
+               DROUND(yr, yl, 8);
+               DROUND(yl, yr, 7);
+               DROUND(yr, yl, 6);
+               DROUND(yl, yr, 5);
+               DROUND(yr, yl, 4);
+               DROUND(yl, yr, 3);
+               DROUND(yr, yl, 2);
+               DROUND(yl, yr, 1);
+               DROUND(yr, yl, 0);
+
+               /* transcode 8 crypted bytes to 9 sample bytes */
+               bf_data_out[0] = dsp_audio_seven2law[(yl>>25) & 0x7f];
+               bf_data_out[1] = dsp_audio_seven2law[(yl>>18) & 0x7f];
+               bf_data_out[2] = dsp_audio_seven2law[(yl>>11) & 0x7f];
+               bf_data_out[3] = dsp_audio_seven2law[(yl>>4) & 0x7f];
+               bf_data_out[4] = dsp_audio_seven2law[((yl<<3) & 0x78) |
+                   ((yr>>29) & 0x07)];
+
+               bf_data_out[5] = dsp_audio_seven2law[(yr>>22) & 0x7f];
+               bf_data_out[6] = dsp_audio_seven2law[(yr>>15) & 0x7f];
+               bf_data_out[7] = dsp_audio_seven2law[(yr>>8) & 0x7f];
+               bf_data_out[8] = dsp_audio_seven2law[(yr>>1) & 0x7f];
+               k = 0; /* start with new decoded frame */
+       }
+
+       /* write current count and sync */
+       dsp->bf_decrypt_in_pos = j;
+       dsp->bf_decrypt_out_pos = k;
+       dsp->bf_sync = sync;
+}
+
+
+/* used to encrypt S and P boxes */
+static inline void
+encrypt_block(const u32 *P, const u32 *S, u32 *dst, u32 *src)
+{
+       u32 yl = src[0];
+       u32 yr = src[1];
+
+       EROUND(yr, yl, 0);
+       EROUND(yl, yr, 1);
+       EROUND(yr, yl, 2);
+       EROUND(yl, yr, 3);
+       EROUND(yr, yl, 4);
+       EROUND(yl, yr, 5);
+       EROUND(yr, yl, 6);
+       EROUND(yl, yr, 7);
+       EROUND(yr, yl, 8);
+       EROUND(yl, yr, 9);
+       EROUND(yr, yl, 10);
+       EROUND(yl, yr, 11);
+       EROUND(yr, yl, 12);
+       EROUND(yl, yr, 13);
+       EROUND(yr, yl, 14);
+       EROUND(yl, yr, 15);
+
+       yl ^= P[16];
+       yr ^= P[17];
+
+       dst[0] = yr;
+       dst[1] = yl;
+}
+
+/*
+ * initialize the dsp for encryption and decryption using the same key
+ * Calculates the blowfish S and P boxes for encryption and decryption.
+ * The margin of keylen must be 4-56 bytes.
+ * returns 0 if ok.
+ */
+int
+dsp_bf_init(struct dsp *dsp, const u8 *key, uint keylen)
+{
+       short i, j, count;
+       u32 data[2], temp;
+       u32 *P = (u32 *)dsp->bf_p;
+       u32 *S = (u32 *)dsp->bf_s;
+
+       if (keylen < 4 || keylen > 56)
+               return 1;
+
+       /* Set dsp states */
+       i = 0;
+       while (i < 9) {
+               dsp->bf_crypt_out[i] = 0xff;
+               dsp->bf_data_out[i] = dsp_silence;
+               i++;
+       }
+       dsp->bf_crypt_pos = 0;
+       dsp->bf_decrypt_in_pos = 0;
+       dsp->bf_decrypt_out_pos = 0;
+       dsp->bf_sync = 0x1ff;
+       dsp->bf_enable = 1;
+
+       /* Copy the initialization s-boxes */
+       for (i = 0, count = 0; i < 256; i++)
+               for (j = 0; j < 4; j++, count++)
+                       S[count] = bf_sbox[count];
+
+       /* Set the p-boxes */
+       for (i = 0; i < 16 + 2; i++)
+               P[i] = bf_pbox[i];
+
+       /* Actual subkey generation */
+       for (j = 0, i = 0; i < 16 + 2; i++) {
+               temp = (((u32)key[j] << 24) |
+                   ((u32)key[(j + 1) % keylen] << 16) |
+                   ((u32)key[(j + 2) % keylen] << 8) |
+                   ((u32)key[(j + 3) % keylen]));
+
+               P[i] = P[i] ^ temp;
+               j = (j + 4) % keylen;
+       }
+
+       data[0] = 0x00000000;
+       data[1] = 0x00000000;
+
+       for (i = 0; i < 16 + 2; i += 2) {
+               encrypt_block(P, S, data, data);
+
+               P[i] = data[0];
+               P[i + 1] = data[1];
+       }
+
+       for (i = 0; i < 4; i++) {
+               for (j = 0, count = i * 256; j < 256; j += 2, count += 2) {
+                       encrypt_block(P, S, data, data);
+
+                       S[count] = data[0];
+                       S[count + 1] = data[1];
+               }
+       }
+
+       return 0;
+}
+
+
+/*
+ * turn encryption off
+ */
+void
+dsp_bf_cleanup(struct dsp *dsp)
+{
+       dsp->bf_enable = 0;
+}
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
new file mode 100644 (file)
index 0000000..e92b1ba
--- /dev/null
@@ -0,0 +1,1886 @@
+/*
+ * Audio crossconnecting/conferrencing (hardware level).
+ *
+ * Copyright 2002 by Andreas Eversberg (jolly@eversberg.eu)
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ */
+
+/*
+ * The process of adding and removing parties to/from a conference:
+ *
+ * There is a chain of struct dsp_conf which has one or more members in a chain
+ * of struct dsp_conf_member.
+ *
+ * After a party is added, the conference is checked for hardware capability.
+ * Also if a party is removed, the conference is checked again.
+ *
+ * There are 3 different solutions: -1 = software, 0 = hardware-crossconnect
+ * 1-n = hardware-conference. The n will give the conference number.
+ *
+ * Depending on the change after removal or insertion of a party, hardware
+ * commands are given.
+ *
+ * The current solution is stored within the struct dsp_conf entry.
+ */
+
+/*
+ * HOW THE CMX WORKS:
+ *
+ * There are 3 types of interaction: One member is alone, in this case only
+ * data flow from upper to lower layer is done.
+ * Two members will also exchange their data so they are crossconnected.
+ * Three or more members will be added in a conference and will hear each
+ * other but will not receive their own speech (echo) if not enabled.
+ *
+ * Features of CMX are:
+ *  - Crossconnecting or even conference, if more than two members are together.
+ *  - Force mixing of transmit data with other crossconnect/conference members.
+ *  - Echo generation to benchmark the delay of audio processing.
+ *  - Use hardware to minimize cpu load, disable FIFO load and minimize delay.
+ *  - Dejittering and clock generation.
+ *
+ * There are 2 buffers:
+ *
+ *
+ * RX-Buffer
+ *                 R             W
+ *                 |             |
+ * ----------------+-------------+-------------------
+ *
+ * The rx-buffer is a ring buffer used to store the received data for each
+ * individual member. This is only the case if data needs to be dejittered
+ * or in case of a conference where different clocks require reclocking.
+ * The transmit-clock (R) will read the buffer.
+ * If the clock overruns the write-pointer, we will have a buffer underrun.
+ * If the write pointer always has a certain distance from the transmit-
+ * clock, we will have a delay. The delay will dynamically be increased and
+ * reduced.
+ *
+ *
+ * TX-Buffer
+ *                  R        W
+ *                  |        |
+ * -----------------+--------+-----------------------
+ *
+ * The tx-buffer is a ring buffer to queue the transmit data from user space
+ * until it will be mixed or sent. There are two pointers, R and W. If the write
+ * pointer W would reach or overrun R, the buffer would overrun. In this case
+ * (some) data is dropped so that it will not overrun.
+ * Additionally a dynamic dejittering can be enabled. this allows data from
+ * user space that have jitter and different clock source.
+ *
+ *
+ * Clock:
+ *
+ * A Clock is not required, if the data source has exactly one clock. In this
+ * case the data source is forwarded to the destination.
+ *
+ * A Clock is required, because the data source
+ *  - has multiple clocks.
+ *  - has no usable clock due to jitter or packet loss (VoIP).
+ * In this case the system's clock is used. The clock resolution depends on
+ * the jiffie resolution.
+ *
+ * If a member joins a conference:
+ *
+ * - If a member joins, its rx_buff is set to silence and change read pointer
+ *   to transmit clock.
+ *
+ * The procedure of received data from card is explained in cmx_receive.
+ * The procedure of received data from user space is explained in cmx_transmit.
+ * The procedure of transmit data to card is cmx_send.
+ *
+ *
+ * Interaction with other features:
+ *
+ * DTMF:
+ * DTMF decoding is done before the data is crossconnected.
+ *
+ * Volume change:
+ * Changing rx-volume is done before the data is crossconnected. The tx-volume
+ * must be changed whenever data is transmitted to the card by the cmx.
+ *
+ * Tones:
+ * If a tone is enabled, it will be processed whenever data is transmitted to
+ * the card. It will replace the tx-data from the user space.
+ * If tones are generated by hardware, this conference member is removed for
+ * this time.
+ *
+ * Disable rx-data:
+ * If cmx is realized in hardware, rx data will be disabled if requested by
+ * the upper layer. If dtmf decoding is done by software and enabled, rx data
+ * will not be diabled but blocked to the upper layer.
+ *
+ * HFC conference engine:
+ * If it is possible to realize all features using hardware, hardware will be
+ * used if not forbidden by control command. Disabling rx-data provides
+ * absolutely traffic free audio processing. (except for the quick 1-frame
+ * upload of a tone loop, only once for a new tone)
+ *
+ */
+
+/* delay.h is required for hw_lock.h */
+
+#include <linux/delay.h>
+#include <linux/mISDNif.h>
+#include <linux/mISDNdsp.h>
+#include "core.h"
+#include "dsp.h"
+/*
+ * debugging of multi party conference,
+ * by using conference even with two members
+ */
+
+/* #define CMX_CONF_DEBUG */
+
+/*#define CMX_DEBUG * massive read/write pointer output */
+/*#define CMX_TX_DEBUG * massive read/write on tx-buffer with content */
+
+static inline int
+count_list_member(struct list_head *head)
+{
+       int                     cnt = 0;
+       struct list_head        *m;
+
+       list_for_each(m, head)
+               cnt++;
+       return cnt;
+}
+
+/*
+ * debug cmx memory structure
+ */
+void
+dsp_cmx_debug(struct dsp *dsp)
+{
+       struct dsp_conf *conf;
+       struct dsp_conf_member  *member;
+       struct dsp              *odsp;
+
+       printk(KERN_DEBUG "-----Current DSP\n");
+       list_for_each_entry(odsp, &dsp_ilist, list) {
+               printk(KERN_DEBUG "* %s echo=%d txmix=%d",
+                   odsp->name, odsp->echo, odsp->tx_mix);
+               if (odsp->conf)
+                       printk(" (Conf %d)", odsp->conf->id);
+               if (dsp == odsp)
+                       printk(" *this*");
+               printk("\n");
+       }
+       printk(KERN_DEBUG "-----Current Conf:\n");
+       list_for_each_entry(conf, &conf_ilist, list) {
+               printk(KERN_DEBUG "* Conf %d (%p)\n", conf->id, conf);
+               list_for_each_entry(member, &conf->mlist, list) {
+                       printk(KERN_DEBUG
+                           "  - member = %s (slot_tx %d, bank_tx %d, "
+                           "slot_rx %d, bank_rx %d hfc_conf %d)%s\n",
+                           member->dsp->name, member->dsp->pcm_slot_tx,
+                           member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx,
+                           member->dsp->pcm_bank_rx, member->dsp->hfc_conf,
+                           (member->dsp == dsp) ? " *this*" : "");
+               }
+       }
+       printk(KERN_DEBUG "-----end\n");
+}
+
+/*
+ * search conference
+ */
+static struct dsp_conf *
+dsp_cmx_search_conf(u32 id)
+{
+       struct dsp_conf *conf;
+
+       if (!id) {
+               printk(KERN_WARNING "%s: conference ID is 0.\n", __func__);
+               return NULL;
+       }
+
+       /* search conference */
+       list_for_each_entry(conf, &conf_ilist, list)
+               if (conf->id == id)
+                       return conf;
+
+       return NULL;
+}
+
+
+/*
+ * add member to conference
+ */
+static int
+dsp_cmx_add_conf_member(struct dsp *dsp, struct dsp_conf *conf)
+{
+       struct dsp_conf_member *member;
+
+       if (!conf || !dsp) {
+               printk(KERN_WARNING "%s: conf or dsp is 0.\n", __func__);
+               return -EINVAL;
+       }
+       if (dsp->member) {
+               printk(KERN_WARNING "%s: dsp is already member in a conf.\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (dsp->conf) {
+               printk(KERN_WARNING "%s: dsp is already in a conf.\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       member = kzalloc(sizeof(struct dsp_conf_member), GFP_ATOMIC);
+       if (!member) {
+               printk(KERN_ERR "kmalloc struct dsp_conf_member failed\n");
+               return -ENOMEM;
+       }
+       member->dsp = dsp;
+       /* clear rx buffer */
+       memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
+       dsp->rx_init = 1; /* rx_W and rx_R will be adjusted on first frame */
+       dsp->rx_W = 0;
+       dsp->rx_R = 0;
+
+       list_add_tail(&member->list, &conf->mlist);
+
+       dsp->conf = conf;
+       dsp->member = member;
+
+       return 0;
+}
+
+
+/*
+ * del member from conference
+ */
+int
+dsp_cmx_del_conf_member(struct dsp *dsp)
+{
+       struct dsp_conf_member *member;
+
+       if (!dsp) {
+               printk(KERN_WARNING "%s: dsp is 0.\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (!dsp->conf) {
+               printk(KERN_WARNING "%s: dsp is not in a conf.\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (list_empty(&dsp->conf->mlist)) {
+               printk(KERN_WARNING "%s: dsp has linked an empty conf.\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       /* find us in conf */
+       list_for_each_entry(member, &dsp->conf->mlist, list) {
+               if (member->dsp == dsp) {
+                       list_del(&member->list);
+                       dsp->conf = NULL;
+                       dsp->member = NULL;
+                       kfree(member);
+                       return 0;
+               }
+       }
+       printk(KERN_WARNING
+           "%s: dsp is not present in its own conf_meber list.\n",
+           __func__);
+
+       return -EINVAL;
+}
+
+
+/*
+ * new conference
+ */
+static struct dsp_conf
+*dsp_cmx_new_conf(u32 id)
+{
+       struct dsp_conf *conf;
+
+       if (!id) {
+               printk(KERN_WARNING "%s: id is 0.\n",
+                   __func__);
+               return NULL;
+       }
+
+       conf = kzalloc(sizeof(struct dsp_conf), GFP_ATOMIC);
+       if (!conf) {
+               printk(KERN_ERR "kmalloc struct dsp_conf failed\n");
+               return NULL;
+       }
+       INIT_LIST_HEAD(&conf->mlist);
+       conf->id = id;
+
+       list_add_tail(&conf->list, &conf_ilist);
+
+       return conf;
+}
+
+
+/*
+ * del conference
+ */
+int
+dsp_cmx_del_conf(struct dsp_conf *conf)
+{
+       if (!conf) {
+               printk(KERN_WARNING "%s: conf is null.\n",
+                   __func__);
+               return -EINVAL;
+       }
+
+       if (!list_empty(&conf->mlist)) {
+               printk(KERN_WARNING "%s: conf not empty.\n",
+                   __func__);
+               return -EINVAL;
+       }
+       list_del(&conf->list);
+       kfree(conf);
+
+       return 0;
+}
+
+
+/*
+ * send HW message to hfc card
+ */
+static void
+dsp_cmx_hw_message(struct dsp *dsp, u32 message, u32 param1, u32 param2,
+    u32 param3, u32 param4)
+{
+       struct mISDN_ctrl_req cq;
+
+       memset(&cq, 0, sizeof(cq));
+       cq.op = message;
+       cq.p1 = param1 | (param2 << 8);
+       cq.p2 = param3 | (param4 << 8);
+       if (dsp->ch.peer)
+               dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq);
+}
+
+
+/*
+ * do hardware update and set the software/hardware flag
+ *
+ * either a conference or a dsp instance can be given
+ * if only dsp instance is given, the instance is not associated with a conf
+ * and therefore removed. if a conference is given, the dsp is expected to
+ * be member of that conference.
+ */
+void
+dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
+{
+       struct dsp_conf_member  *member, *nextm;
+       struct dsp              *finddsp;
+       int             memb = 0, i, ii, i1, i2;
+       int             freeunits[8];
+       u_char          freeslots[256];
+       int             same_hfc = -1, same_pcm = -1, current_conf = -1,
+           all_conf = 1;
+
+       /* dsp gets updated (no conf) */
+       if (!conf) {
+               if (!dsp)
+                       return;
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       printk(KERN_DEBUG "%s checking dsp %s\n",
+                           __func__, dsp->name);
+one_member:
+               /* remove HFC conference if enabled */
+               if (dsp->hfc_conf >= 0) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s removing %s from HFC conf %d "
+                                   "because dsp is split\n", __func__,
+                                   dsp->name, dsp->hfc_conf);
+                       dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_CONF_SPLIT,
+                           0, 0, 0, 0);
+                       dsp->hfc_conf = -1;
+               }
+               /* process hw echo */
+               if (dsp->features.pcm_banks < 1)
+                       return;
+               if (!dsp->echo) {
+                       /* NO ECHO: remove PCM slot if assigned */
+                       if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) {
+                               if (dsp_debug & DEBUG_DSP_CMX)
+                                       printk(KERN_DEBUG "%s removing %s from"
+                                           " PCM slot %d (TX) %d (RX) because"
+                                           " dsp is split (no echo)\n",
+                                           __func__, dsp->name,
+                                           dsp->pcm_slot_tx, dsp->pcm_slot_rx);
+                               dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_DISC,
+                                   0, 0, 0, 0);
+                               dsp->pcm_slot_tx = -1;
+                               dsp->pcm_bank_tx = -1;
+                               dsp->pcm_slot_rx = -1;
+                               dsp->pcm_bank_rx = -1;
+                       }
+                       return;
+               }
+               /* ECHO: already echo */
+               if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 &&
+                   dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2)
+                       return;
+               /* ECHO: if slot already assigned */
+               if (dsp->pcm_slot_tx >= 0) {
+                       dsp->pcm_slot_rx = dsp->pcm_slot_tx;
+                       dsp->pcm_bank_tx = 2; /* 2 means loop */
+                       dsp->pcm_bank_rx = 2;
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s refresh %s for echo using slot %d\n",
+                                   __func__, dsp->name,
+                                   dsp->pcm_slot_tx);
+                       dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
+                           dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
+                       return;
+               }
+               /* ECHO: find slot */
+               dsp->pcm_slot_tx = -1;
+               dsp->pcm_slot_rx = -1;
+               memset(freeslots, 1, sizeof(freeslots));
+               list_for_each_entry(finddsp, &dsp_ilist, list) {
+                       if (finddsp->features.pcm_id == dsp->features.pcm_id) {
+                               if (finddsp->pcm_slot_rx >= 0 &&
+                                   finddsp->pcm_slot_rx < sizeof(freeslots))
+                                       freeslots[finddsp->pcm_slot_tx] = 0;
+                               if (finddsp->pcm_slot_tx >= 0 &&
+                                   finddsp->pcm_slot_tx < sizeof(freeslots))
+                                       freeslots[finddsp->pcm_slot_rx] = 0;
+                       }
+               }
+               i = 0;
+               ii = dsp->features.pcm_slots;
+               while (i < ii) {
+                       if (freeslots[i])
+                               break;
+                       i++;
+               }
+               if (i == ii) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s no slot available for echo\n",
+                                   __func__);
+                       /* no more slots available */
+                       return;
+               }
+               /* assign free slot */
+               dsp->pcm_slot_tx = i;
+               dsp->pcm_slot_rx = i;
+               dsp->pcm_bank_tx = 2; /* loop */
+               dsp->pcm_bank_rx = 2;
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       printk(KERN_DEBUG
+                           "%s assign echo for %s using slot %d\n",
+                           __func__, dsp->name, dsp->pcm_slot_tx);
+               dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
+                   dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
+               return;
+       }
+
+       /* conf gets updated (all members) */
+       if (dsp_debug & DEBUG_DSP_CMX)
+               printk(KERN_DEBUG "%s checking conference %d\n",
+                   __func__, conf->id);
+
+       if (list_empty(&conf->mlist)) {
+               printk(KERN_ERR "%s: conference whithout members\n",
+                   __func__);
+               return;
+       }
+       member = list_entry(conf->mlist.next, struct dsp_conf_member, list);
+       same_hfc = member->dsp->features.hfc_id;
+       same_pcm = member->dsp->features.pcm_id;
+       /* check all members in our conference */
+       list_for_each_entry(member, &conf->mlist, list) {
+               /* check if member uses mixing */
+               if (member->dsp->tx_mix) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s dsp %s cannot form a conf, because "
+                                   "tx_mix is turned on\n", __func__,
+                                   member->dsp->name);
+conf_software:
+                       list_for_each_entry(member, &conf->mlist, list) {
+                               dsp = member->dsp;
+                               /* remove HFC conference if enabled */
+                               if (dsp->hfc_conf >= 0) {
+                                       if (dsp_debug & DEBUG_DSP_CMX)
+                                               printk(KERN_DEBUG
+                                                   "%s removing %s from HFC "
+                                                   "conf %d because not "
+                                                   "possible with hardware\n",
+                                                   __func__,
+                                                   dsp->name,
+                                                   dsp->hfc_conf);
+                                       dsp_cmx_hw_message(dsp,
+                                           MISDN_CTRL_HFC_CONF_SPLIT,
+                                           0, 0, 0, 0);
+                                       dsp->hfc_conf = -1;
+                               }
+                               /* remove PCM slot if assigned */
+                               if (dsp->pcm_slot_tx >= 0 ||
+                                   dsp->pcm_slot_rx >= 0) {
+                                       if (dsp_debug & DEBUG_DSP_CMX)
+                                               printk(KERN_DEBUG "%s removing "
+                                                   "%s from PCM slot %d (TX)"
+                                                   " slot %d (RX) because not"
+                                                   " possible with hardware\n",
+                                                   __func__,
+                                                   dsp->name,
+                                                   dsp->pcm_slot_tx,
+                                                   dsp->pcm_slot_rx);
+                                       dsp_cmx_hw_message(dsp,
+                                           MISDN_CTRL_HFC_PCM_DISC,
+                                           0, 0, 0, 0);
+                                       dsp->pcm_slot_tx = -1;
+                                       dsp->pcm_bank_tx = -1;
+                                       dsp->pcm_slot_rx = -1;
+                                       dsp->pcm_bank_rx = -1;
+                               }
+                       }
+                       conf->hardware = 0;
+                       conf->software = 1;
+                       return;
+               }
+               /* check if member has echo turned on */
+               if (member->dsp->echo) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s dsp %s cannot form a conf, because "
+                                   "echo is turned on\n", __func__,
+                                   member->dsp->name);
+                       goto conf_software;
+               }
+               /* check if member has tx_mix turned on */
+               if (member->dsp->tx_mix) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s dsp %s cannot form a conf, because "
+                                   "tx_mix is turned on\n",
+                                   __func__, member->dsp->name);
+                       goto conf_software;
+               }
+               /* check if member changes volume at an not suppoted level */
+               if (member->dsp->tx_volume) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s dsp %s cannot form a conf, because "
+                                   "tx_volume is changed\n",
+                                   __func__, member->dsp->name);
+                       goto conf_software;
+               }
+               if (member->dsp->rx_volume) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s dsp %s cannot form a conf, because "
+                                   "rx_volume is changed\n",
+                                   __func__, member->dsp->name);
+                       goto conf_software;
+               }
+               /* check if tx-data turned on */
+               if (member->dsp->tx_data) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s dsp %s cannot form a conf, because "
+                                   "tx_data is turned on\n",
+                                   __func__, member->dsp->name);
+                       goto conf_software;
+               }
+               /* check if pipeline exists */
+               if (member->dsp->pipeline.inuse) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s dsp %s cannot form a conf, because "
+                                   "pipeline exists\n", __func__,
+                                   member->dsp->name);
+                       goto conf_software;
+               }
+               /* check if encryption is enabled */
+               if (member->dsp->bf_enable) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG "%s dsp %s cannot form a "
+                                   "conf, because encryption is enabled\n",
+                                   __func__, member->dsp->name);
+                       goto conf_software;
+               }
+               /* check if member is on a card with PCM support */
+               if (member->dsp->features.pcm_id < 0) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s dsp %s cannot form a conf, because "
+                                   "dsp has no PCM bus\n",
+                                   __func__, member->dsp->name);
+                       goto conf_software;
+               }
+               /* check if relations are on the same PCM bus */
+               if (member->dsp->features.pcm_id != same_pcm) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s dsp %s cannot form a conf, because "
+                                   "dsp is on a different PCM bus than the "
+                                   "first dsp\n",
+                                   __func__, member->dsp->name);
+                       goto conf_software;
+               }
+               /* determine if members are on the same hfc chip */
+               if (same_hfc != member->dsp->features.hfc_id)
+                       same_hfc = -1;
+               /* if there are members already in a conference */
+               if (current_conf < 0 && member->dsp->hfc_conf >= 0)
+                       current_conf = member->dsp->hfc_conf;
+               /* if any member is not in a conference */
+               if (member->dsp->hfc_conf < 0)
+                       all_conf = 0;
+
+               memb++;
+       }
+
+       /* if no member, this is an error */
+       if (memb < 1)
+               return;
+
+       /* one member */
+       if (memb == 1) {
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       printk(KERN_DEBUG
+                           "%s conf %d cannot form a HW conference, "
+                           "because dsp is alone\n", __func__, conf->id);
+               conf->hardware = 0;
+               conf->software = 0;
+               member = list_entry(conf->mlist.next, struct dsp_conf_member,
+                       list);
+               dsp = member->dsp;
+               goto one_member;
+       }
+
+       /*
+        * ok, now we are sure that all members are on the same pcm.
+        * now we will see if we have only two members, so we can do
+        * crossconnections, which don't have any limitations.
+        */
+
+       /* if we have only two members */
+       if (memb == 2) {
+               member = list_entry(conf->mlist.next, struct dsp_conf_member,
+                       list);
+               nextm = list_entry(member->list.next, struct dsp_conf_member,
+                       list);
+               /* remove HFC conference if enabled */
+               if (member->dsp->hfc_conf >= 0) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s removing %s from HFC conf %d because "
+                                   "two parties require only a PCM slot\n",
+                                   __func__, member->dsp->name,
+                                   member->dsp->hfc_conf);
+                       dsp_cmx_hw_message(member->dsp,
+                           MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
+                       member->dsp->hfc_conf = -1;
+               }
+               if (nextm->dsp->hfc_conf >= 0) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s removing %s from HFC conf %d because "
+                                   "two parties require only a PCM slot\n",
+                                   __func__, nextm->dsp->name,
+                                   nextm->dsp->hfc_conf);
+                       dsp_cmx_hw_message(nextm->dsp,
+                           MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
+                       nextm->dsp->hfc_conf = -1;
+               }
+               /* if members have two banks (and not on the same chip) */
+               if (member->dsp->features.pcm_banks > 1 &&
+                   nextm->dsp->features.pcm_banks > 1 &&
+                   member->dsp->features.hfc_id !=
+                   nextm->dsp->features.hfc_id) {
+                       /* if both members have same slots with crossed banks */
+                       if (member->dsp->pcm_slot_tx >= 0 &&
+                           member->dsp->pcm_slot_rx >= 0 &&
+                           nextm->dsp->pcm_slot_tx >= 0 &&
+                           nextm->dsp->pcm_slot_rx >= 0 &&
+                           nextm->dsp->pcm_slot_tx ==
+                           member->dsp->pcm_slot_rx &&
+                           nextm->dsp->pcm_slot_rx ==
+                           member->dsp->pcm_slot_tx &&
+                           nextm->dsp->pcm_slot_tx ==
+                           member->dsp->pcm_slot_tx &&
+                           member->dsp->pcm_bank_tx !=
+                           member->dsp->pcm_bank_rx &&
+                           nextm->dsp->pcm_bank_tx !=
+                           nextm->dsp->pcm_bank_rx) {
+                               /* all members have same slot */
+                               if (dsp_debug & DEBUG_DSP_CMX)
+                                       printk(KERN_DEBUG
+                                           "%s dsp %s & %s stay joined on "
+                                           "PCM slot %d bank %d (TX) bank %d "
+                                           "(RX) (on different chips)\n",
+                                           __func__,
+                                           member->dsp->name,
+                                           nextm->dsp->name,
+                                           member->dsp->pcm_slot_tx,
+                                           member->dsp->pcm_bank_tx,
+                                           member->dsp->pcm_bank_rx);
+                               conf->hardware = 0;
+                               conf->software = 1;
+                               return;
+                       }
+                       /* find a new slot */
+                       memset(freeslots, 1, sizeof(freeslots));
+                       list_for_each_entry(dsp, &dsp_ilist, list) {
+                               if (dsp != member->dsp &&
+                                   dsp != nextm->dsp &&
+                                   member->dsp->features.pcm_id ==
+                                   dsp->features.pcm_id) {
+                                       if (dsp->pcm_slot_rx >= 0 &&
+                                           dsp->pcm_slot_rx <
+                                           sizeof(freeslots))
+                                               freeslots[dsp->pcm_slot_tx] = 0;
+                                       if (dsp->pcm_slot_tx >= 0 &&
+                                           dsp->pcm_slot_tx <
+                                           sizeof(freeslots))
+                                               freeslots[dsp->pcm_slot_rx] = 0;
+                               }
+                       }
+                       i = 0;
+                       ii = member->dsp->features.pcm_slots;
+                       while (i < ii) {
+                               if (freeslots[i])
+                                       break;
+                               i++;
+                       }
+                       if (i == ii) {
+                               if (dsp_debug & DEBUG_DSP_CMX)
+                                       printk(KERN_DEBUG
+                                           "%s no slot available for "
+                                           "%s & %s\n", __func__,
+                                           member->dsp->name,
+                                           nextm->dsp->name);
+                               /* no more slots available */
+                               goto conf_software;
+                       }
+                       /* assign free slot */
+                       member->dsp->pcm_slot_tx = i;
+                       member->dsp->pcm_slot_rx = i;
+                       nextm->dsp->pcm_slot_tx = i;
+                       nextm->dsp->pcm_slot_rx = i;
+                       member->dsp->pcm_bank_rx = 0;
+                       member->dsp->pcm_bank_tx = 1;
+                       nextm->dsp->pcm_bank_rx = 1;
+                       nextm->dsp->pcm_bank_tx = 0;
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s adding %s & %s to new PCM slot %d "
+                                   "(TX and RX on different chips) because "
+                                   "both members have not same slots\n",
+                                   __func__,
+                                   member->dsp->name,
+                                   nextm->dsp->name,
+                                   member->dsp->pcm_slot_tx);
+                       dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
+                           member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
+                           member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
+                       dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
+                           nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
+                           nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
+                       conf->hardware = 1;
+                       conf->software = 0;
+                       return;
+               /* if members have one bank (or on the same chip) */
+               } else {
+                       /* if both members have different crossed slots */
+                       if (member->dsp->pcm_slot_tx >= 0 &&
+                           member->dsp->pcm_slot_rx >= 0 &&
+                           nextm->dsp->pcm_slot_tx >= 0 &&
+                           nextm->dsp->pcm_slot_rx >= 0 &&
+                           nextm->dsp->pcm_slot_tx ==
+                           member->dsp->pcm_slot_rx &&
+                           nextm->dsp->pcm_slot_rx ==
+                           member->dsp->pcm_slot_tx &&
+                           member->dsp->pcm_slot_tx !=
+                           member->dsp->pcm_slot_rx &&
+                           member->dsp->pcm_bank_tx == 0 &&
+                           member->dsp->pcm_bank_rx == 0 &&
+                           nextm->dsp->pcm_bank_tx == 0 &&
+                           nextm->dsp->pcm_bank_rx == 0) {
+                               /* all members have same slot */
+                               if (dsp_debug & DEBUG_DSP_CMX)
+                                       printk(KERN_DEBUG
+                                           "%s dsp %s & %s stay joined on PCM "
+                                           "slot %d (TX) %d (RX) on same chip "
+                                           "or one bank PCM)\n", __func__,
+                                           member->dsp->name,
+                                           nextm->dsp->name,
+                                           member->dsp->pcm_slot_tx,
+                                           member->dsp->pcm_slot_rx);
+                               conf->hardware = 0;
+                               conf->software = 1;
+                               return;
+                       }
+                       /* find two new slot */
+                       memset(freeslots, 1, sizeof(freeslots));
+                       list_for_each_entry(dsp, &dsp_ilist, list) {
+                               if (dsp != member->dsp &&
+                                   dsp != nextm->dsp &&
+                                   member->dsp->features.pcm_id ==
+                                   dsp->features.pcm_id) {
+                                       if (dsp->pcm_slot_rx >= 0 &&
+                                           dsp->pcm_slot_rx <
+                                           sizeof(freeslots))
+                                               freeslots[dsp->pcm_slot_tx] = 0;
+                                       if (dsp->pcm_slot_tx >= 0 &&
+                                           dsp->pcm_slot_tx <
+                                           sizeof(freeslots))
+                                               freeslots[dsp->pcm_slot_rx] = 0;
+                               }
+                       }
+                       i1 = 0;
+                       ii = member->dsp->features.pcm_slots;
+                       while (i1 < ii) {
+                               if (freeslots[i1])
+                                       break;
+                               i1++;
+                       }
+                       if (i1 == ii) {
+                               if (dsp_debug & DEBUG_DSP_CMX)
+                                       printk(KERN_DEBUG
+                                           "%s no slot available "
+                                           "for %s & %s\n", __func__,
+                                           member->dsp->name,
+                                           nextm->dsp->name);
+                               /* no more slots available */
+                               goto conf_software;
+                       }
+                       i2 = i1+1;
+                       while (i2 < ii) {
+                               if (freeslots[i2])
+                                       break;
+                               i2++;
+                       }
+                       if (i2 == ii) {
+                               if (dsp_debug & DEBUG_DSP_CMX)
+                                       printk(KERN_DEBUG
+                                           "%s no slot available "
+                                           "for %s & %s\n",
+                                           __func__,
+                                           member->dsp->name,
+                                           nextm->dsp->name);
+                               /* no more slots available */
+                               goto conf_software;
+                       }
+                       /* assign free slots */
+                       member->dsp->pcm_slot_tx = i1;
+                       member->dsp->pcm_slot_rx = i2;
+                       nextm->dsp->pcm_slot_tx = i2;
+                       nextm->dsp->pcm_slot_rx = i1;
+                       member->dsp->pcm_bank_rx = 0;
+                       member->dsp->pcm_bank_tx = 0;
+                       nextm->dsp->pcm_bank_rx = 0;
+                       nextm->dsp->pcm_bank_tx = 0;
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s adding %s & %s to new PCM slot %d "
+                                   "(TX) %d (RX) on same chip or one bank "
+                                   "PCM, because both members have not "
+                                   "crossed slots\n", __func__,
+                                   member->dsp->name,
+                                   nextm->dsp->name,
+                                   member->dsp->pcm_slot_tx,
+                                   member->dsp->pcm_slot_rx);
+                       dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
+                           member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
+                           member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
+                       dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
+                           nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
+                           nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
+                       conf->hardware = 1;
+                       conf->software = 0;
+                       return;
+               }
+       }
+
+       /*
+        * if we have more than two, we may check if we have a conference
+        * unit available on the chip. also all members must be on the same
+        */
+
+       /* if not the same HFC chip */
+       if (same_hfc < 0) {
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       printk(KERN_DEBUG
+                           "%s conference %d cannot be formed, because "
+                           "members are on different chips or not "
+                           "on HFC chip\n",
+                           __func__, conf->id);
+               goto conf_software;
+       }
+
+       /* for more than two members.. */
+
+       /* in case of hdlc, we change to software */
+       if (dsp->hdlc)
+               goto conf_software;
+
+       /* if all members already have the same conference */
+       if (all_conf)
+               return;
+
+       /*
+        * if there is an existing conference, but not all members have joined
+        */
+       if (current_conf >= 0) {
+join_members:
+               list_for_each_entry(member, &conf->mlist, list) {
+                       /* join to current conference */
+                       if (member->dsp->hfc_conf == current_conf)
+                               continue;
+                       /* get a free timeslot first */
+                       memset(freeslots, 1, sizeof(freeslots));
+                       list_for_each_entry(dsp, &dsp_ilist, list) {
+                               /*
+                                * not checking current member, because
+                                * slot will be overwritten.
+                                */
+                               if (
+                                   dsp != member->dsp &&
+                               /* dsp must be on the same PCM */
+                                   member->dsp->features.pcm_id ==
+                                   dsp->features.pcm_id) {
+                                       /* dsp must be on a slot */
+                                       if (dsp->pcm_slot_tx >= 0 &&
+                                           dsp->pcm_slot_tx <
+                                           sizeof(freeslots))
+                                               freeslots[dsp->pcm_slot_tx] = 0;
+                                       if (dsp->pcm_slot_rx >= 0 &&
+                                           dsp->pcm_slot_rx <
+                                           sizeof(freeslots))
+                                               freeslots[dsp->pcm_slot_rx] = 0;
+                               }
+                       }
+                       i = 0;
+                       ii = member->dsp->features.pcm_slots;
+                       while (i < ii) {
+                               if (freeslots[i])
+                                       break;
+                               i++;
+                       }
+                       if (i == ii) {
+                               /* no more slots available */
+                               if (dsp_debug & DEBUG_DSP_CMX)
+                                       printk(KERN_DEBUG
+                                           "%s conference %d cannot be formed,"
+                                           " because no slot free\n",
+                                           __func__, conf->id);
+                               goto conf_software;
+                       }
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "%s changing dsp %s to HW conference "
+                                   "%d slot %d\n", __func__,
+                                   member->dsp->name, current_conf, i);
+                       /* assign free slot & set PCM & join conf */
+                       member->dsp->pcm_slot_tx = i;
+                       member->dsp->pcm_slot_rx = i;
+                       member->dsp->pcm_bank_tx = 2; /* loop */
+                       member->dsp->pcm_bank_rx = 2;
+                       member->dsp->hfc_conf = current_conf;
+                       dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
+                           i, 2, i, 2);
+                       dsp_cmx_hw_message(member->dsp,
+                           MISDN_CTRL_HFC_CONF_JOIN, current_conf, 0, 0, 0);
+               }
+               return;
+       }
+
+       /*
+        * no member is in a conference yet, so we find a free one
+        */
+       memset(freeunits, 1, sizeof(freeunits));
+       list_for_each_entry(dsp, &dsp_ilist, list) {
+               /* dsp must be on the same chip */
+               if (dsp->features.hfc_id == same_hfc &&
+                   /* dsp must have joined a HW conference */
+                   dsp->hfc_conf >= 0 &&
+                   /* slot must be within range */
+                   dsp->hfc_conf < 8)
+                       freeunits[dsp->hfc_conf] = 0;
+       }
+       i = 0;
+       ii = 8;
+       while (i < ii) {
+               if (freeunits[i])
+                       break;
+               i++;
+       }
+       if (i == ii) {
+               /* no more conferences available */
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       printk(KERN_DEBUG
+                           "%s conference %d cannot be formed, because "
+                           "no conference number free\n",
+                           __func__, conf->id);
+               goto conf_software;
+       }
+       /* join all members */
+       current_conf = i;
+       goto join_members;
+}
+
+
+/*
+ * conf_id != 0: join or change conference
+ * conf_id == 0: split from conference if not already
+ */
+int
+dsp_cmx_conf(struct dsp *dsp, u32 conf_id)
+{
+       int err;
+       struct dsp_conf *conf;
+       struct dsp_conf_member  *member;
+
+       /* if conference doesn't change */
+       if (dsp->conf_id == conf_id)
+               return 0;
+
+       /* first remove us from current conf */
+       if (dsp->conf_id) {
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       printk(KERN_DEBUG "removing us from conference %d\n",
+                               dsp->conf->id);
+               /* remove us from conf */
+               conf = dsp->conf;
+               err = dsp_cmx_del_conf_member(dsp);
+               if (err)
+                       return err;
+               dsp->conf_id = 0;
+
+               /* update hardware */
+               dsp_cmx_hardware(NULL, dsp);
+
+               /* conf now empty? */
+               if (list_empty(&conf->mlist)) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "conference is empty, so we remove it.\n");
+                       err = dsp_cmx_del_conf(conf);
+                       if (err)
+                               return err;
+               } else {
+                       /* update members left on conf */
+                       dsp_cmx_hardware(conf, NULL);
+               }
+       }
+
+       /* if split */
+       if (!conf_id)
+               return 0;
+
+       /* now add us to conf */
+       if (dsp_debug & DEBUG_DSP_CMX)
+               printk(KERN_DEBUG "searching conference %d\n",
+                       conf_id);
+       conf = dsp_cmx_search_conf(conf_id);
+       if (!conf) {
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       printk(KERN_DEBUG
+                           "conference doesn't exist yet, creating.\n");
+               /* the conference doesn't exist, so we create */
+               conf = dsp_cmx_new_conf(conf_id);
+               if (!conf)
+                       return -EINVAL;
+       } else if (!list_empty(&conf->mlist)) {
+               member = list_entry(conf->mlist.next, struct dsp_conf_member,
+                       list);
+               if (dsp->hdlc && !member->dsp->hdlc) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "cannot join transparent conference.\n");
+                       return -EINVAL;
+               }
+               if (!dsp->hdlc && member->dsp->hdlc) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "cannot join hdlc conference.\n");
+                       return -EINVAL;
+               }
+       }
+       /* add conference member */
+       err = dsp_cmx_add_conf_member(dsp, conf);
+       if (err)
+               return err;
+       dsp->conf_id = conf_id;
+
+       /* if we are alone, we do nothing! */
+       if (list_empty(&conf->mlist)) {
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       printk(KERN_DEBUG
+                           "we are alone in this conference, so exit.\n");
+               /* update hardware */
+               dsp_cmx_hardware(NULL, dsp);
+               return 0;
+       }
+
+       /* update members on conf */
+       dsp_cmx_hardware(conf, NULL);
+
+       return 0;
+}
+
+
+/*
+ * audio data is received from card
+ */
+void
+dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
+{
+       u8 *d, *p;
+       int len = skb->len;
+       struct mISDNhead *hh = mISDN_HEAD_P(skb);
+       int w, i, ii;
+
+       /* check if we have sompen */
+       if (len < 1)
+               return;
+
+       /* half of the buffer should be larger than maximum packet size */
+       if (len >= CMX_BUFF_HALF) {
+               printk(KERN_ERR
+                   "%s line %d: packet from card is too large (%d bytes). "
+                   "please make card send smaller packets OR increase "
+                   "CMX_BUFF_SIZE\n", __FILE__, __LINE__, len);
+               return;
+       }
+
+       /*
+        * initialize pointers if not already -
+        * also add delay if requested by PH_SIGNAL
+        */
+       if (dsp->rx_init) {
+               dsp->rx_init = 0;
+               if (dsp->features.unordered) {
+                       dsp->rx_R = (hh->id & CMX_BUFF_MASK);
+                       dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
+                               & CMX_BUFF_MASK;
+               } else {
+                       dsp->rx_R = 0;
+                       dsp->rx_W = dsp->cmx_delay;
+               }
+       }
+       /* if frame contains time code, write directly */
+       if (dsp->features.unordered) {
+               dsp->rx_W = (hh->id & CMX_BUFF_MASK);
+               /* printk(KERN_DEBUG "%s %08x\n", dsp->name, hh->id); */
+       }
+       /*
+        * if we underrun (or maybe overrun),
+        * we set our new read pointer, and write silence to buffer
+        */
+       if (((dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK) >= CMX_BUFF_HALF) {
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       printk(KERN_DEBUG
+                           "cmx_receive(dsp=%lx): UNDERRUN (or overrun the "
+                           "maximum delay), adjusting read pointer! "
+                           "(inst %s)\n", (u_long)dsp, dsp->name);
+               /* flush buffer */
+               if (dsp->features.unordered) {
+                       dsp->rx_R = (hh->id & CMX_BUFF_MASK);
+                       dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
+                               & CMX_BUFF_MASK;
+               } else {
+                       dsp->rx_R = 0;
+                       dsp->rx_W = dsp->cmx_delay;
+               }
+               memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
+       }
+       /* if we have reached double delay, jump back to middle */
+       if (dsp->cmx_delay)
+               if (((dsp->rx_W - dsp->rx_R) & CMX_BUFF_MASK) >=
+                   (dsp->cmx_delay << 1)) {
+                       if (dsp_debug & DEBUG_DSP_CMX)
+                               printk(KERN_DEBUG
+                                   "cmx_receive(dsp=%lx): OVERRUN (because "
+                                   "twice the delay is reached), adjusting "
+                                   "read pointer! (inst %s)\n",
+                                   (u_long)dsp, dsp->name);
+               /* flush buffer */
+               if (dsp->features.unordered) {
+                       dsp->rx_R = (hh->id & CMX_BUFF_MASK);
+                       dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
+                               & CMX_BUFF_MASK;
+               } else {
+                       dsp->rx_R = 0;
+                       dsp->rx_W = dsp->cmx_delay;
+               }
+               memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
+       }
+
+       /* show where to write */
+#ifdef CMX_DEBUG
+       printk(KERN_DEBUG
+           "cmx_receive(dsp=%lx): rx_R(dsp)=%05x rx_W(dsp)=%05x len=%d %s\n",
+           (u_long)dsp, dsp->rx_R, dsp->rx_W, len, dsp->name);
+#endif
+
+       /* write data into rx_buffer */
+       p = skb->data;
+       d = dsp->rx_buff;
+       w = dsp->rx_W;
+       i = 0;
+       ii = len;
+       while (i < ii) {
+               d[w++ & CMX_BUFF_MASK] = *p++;
+               i++;
+       }
+
+       /* increase write-pointer */
+       dsp->rx_W = ((dsp->rx_W+len) & CMX_BUFF_MASK);
+}
+
+
+/*
+ * send (mixed) audio data to card and control jitter
+ */
+static void
+dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
+{
+       struct dsp_conf *conf = dsp->conf;
+       struct dsp *member, *other;
+       register s32 sample;
+       u8 *d, *p, *q, *o_q;
+       struct sk_buff *nskb, *txskb;
+       int r, rr, t, tt, o_r, o_rr;
+       int preload = 0;
+       struct mISDNhead *hh, *thh;
+
+       /* don't process if: */
+       if (!dsp->b_active) { /* if not active */
+               dsp->last_tx = 0;
+               return;
+       }
+       if (dsp->pcm_slot_tx >= 0 && /* connected to pcm slot */
+           dsp->tx_R == dsp->tx_W && /* AND no tx-data */
+           !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */
+               dsp->last_tx = 0;
+               return;
+       }
+
+#ifdef CMX_DEBUG
+       printk(KERN_DEBUG
+           "SEND members=%d dsp=%s, conf=%p, rx_R=%05x rx_W=%05x\n",
+           members, dsp->name, conf, dsp->rx_R, dsp->rx_W);
+#endif
+
+       /* preload if we have delay set */
+       if (dsp->cmx_delay && !dsp->last_tx) {
+               preload = len;
+               if (preload < 128)
+                       preload = 128;
+       }
+
+       /* PREPARE RESULT */
+       nskb = mI_alloc_skb(len + preload, GFP_ATOMIC);
+       if (!nskb) {
+               printk(KERN_ERR
+                   "FATAL ERROR in mISDN_dsp.o: cannot alloc %d bytes\n",
+                   len + preload);
+               return;
+       }
+       hh = mISDN_HEAD_P(nskb);
+       hh->prim = PH_DATA_REQ;
+       hh->id = 0;
+       dsp->last_tx = 1;
+
+       /* set pointers, indexes and stuff */
+       member = dsp;
+       p = dsp->tx_buff; /* transmit data */
+       q = dsp->rx_buff; /* received data */
+       d = skb_put(nskb, preload + len); /* result */
+       t = dsp->tx_R; /* tx-pointers */
+       tt = dsp->tx_W;
+       r = dsp->rx_R; /* rx-pointers */
+       rr = (r + len) & CMX_BUFF_MASK;
+
+       /* preload with silence, if required */
+       if (preload) {
+               memset(d, dsp_silence, preload);
+               d += preload;
+       }
+
+       /* PROCESS TONES/TX-DATA ONLY */
+       if (dsp->tone.tone && dsp->tone.software) {
+               /* -> copy tone */
+               dsp_tone_copy(dsp, d, len);
+               dsp->tx_R = 0; /* clear tx buffer */
+               dsp->tx_W = 0;
+               goto send_packet;
+       }
+       /* if we have tx-data but do not use mixing */
+       if (!dsp->tx_mix && t != tt) {
+               /* -> send tx-data and continue when not enough */
+#ifdef CMX_TX_DEBUG
+       sprintf(debugbuf, "TX sending (%04x-%04x)%p: ", t, tt, p);
+#endif
+               while (r != rr && t != tt) {
+#ifdef CMX_TX_DEBUG
+                       if (strlen(debugbuf) < 48)
+                           sprintf(debugbuf+strlen(debugbuf), " %02x", p[t]);
+#endif
+                       *d++ = p[t]; /* write tx_buff */
+                       t = (t+1) & CMX_BUFF_MASK;
+                       r = (r+1) & CMX_BUFF_MASK;
+               }
+               if (r == rr) {
+                       dsp->tx_R = t;
+#ifdef CMX_TX_DEBUG
+       printk(KERN_DEBUG "%s\n", debugbuf);
+#endif
+                       goto send_packet;
+               }
+       }
+#ifdef CMX_TX_DEBUG
+       printk(KERN_DEBUG "%s\n", debugbuf);
+#endif
+
+       /* PROCESS DATA (one member / no conf) */
+       if (!conf || members <= 1) {
+               /* -> if echo is NOT enabled */
+               if (!dsp->echo) {
+                       /* -> send tx-data if available or use 0-volume */
+                       while (r != rr && t != tt) {
+                               *d++ = p[t]; /* write tx_buff */
+                               t = (t+1) & CMX_BUFF_MASK;
+                               r = (r+1) & CMX_BUFF_MASK;
+                       }
+                       if (r != rr)
+                               memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK);
+               /* -> if echo is enabled */
+               } else {
+                       /*
+                        * -> mix tx-data with echo if available,
+                        * or use echo only
+                        */
+                       while (r != rr && t != tt) {
+                               *d++ = dsp_audio_mix_law[(p[t]<<8)|q[r]];
+                               t = (t+1) & CMX_BUFF_MASK;
+                               r = (r+1) & CMX_BUFF_MASK;
+                       }
+                       while (r != rr) {
+                               *d++ = q[r]; /* echo */
+                               r = (r+1) & CMX_BUFF_MASK;
+                       }
+               }
+               dsp->tx_R = t;
+               goto send_packet;
+       }
+       /* PROCESS DATA (two members) */
+#ifdef CMX_CONF_DEBUG
+       if (0) {
+#else
+       if (members == 2) {
+#endif
+               /* "other" becomes other party */
+               other = (list_entry(conf->mlist.next,
+                   struct dsp_conf_member, list))->dsp;
+               if (other == member)
+                       other = (list_entry(conf->mlist.prev,
+                           struct dsp_conf_member, list))->dsp;
+               o_q = other->rx_buff; /* received data */
+               o_rr = (other->rx_R + len) & CMX_BUFF_MASK;
+                       /* end of rx-pointer */
+               o_r = (o_rr - rr + r) & CMX_BUFF_MASK;
+                       /* start rx-pointer at current read position*/
+               /* -> if echo is NOT enabled */
+               if (!dsp->echo) {
+                       /*
+                        * -> copy other member's rx-data,
+                        * if tx-data is available, mix
+                        */
+                       while (o_r != o_rr && t != tt) {
+                               *d++ = dsp_audio_mix_law[(p[t]<<8)|o_q[o_r]];
+                               t = (t+1) & CMX_BUFF_MASK;
+                               o_r = (o_r+1) & CMX_BUFF_MASK;
+                       }
+                       while (o_r != o_rr) {
+                               *d++ = o_q[o_r];
+                               o_r = (o_r+1) & CMX_BUFF_MASK;
+                       }
+               /* -> if echo is enabled */
+               } else {
+                       /*
+                        * -> mix other member's rx-data with echo,
+                        * if tx-data is available, mix
+                        */
+                       while (r != rr && t != tt) {
+                               sample = dsp_audio_law_to_s32[p[t]] +
+                                   dsp_audio_law_to_s32[q[r]] +
+                                   dsp_audio_law_to_s32[o_q[o_r]];
+                               if (sample < -32768)
+                                       sample = -32768;
+                               else if (sample > 32767)
+                                       sample = 32767;
+                               *d++ = dsp_audio_s16_to_law[sample & 0xffff];
+                                   /* tx-data + rx_data + echo */
+                               t = (t+1) & CMX_BUFF_MASK;
+                               r = (r+1) & CMX_BUFF_MASK;
+                               o_r = (o_r+1) & CMX_BUFF_MASK;
+                       }
+                       while (r != rr) {
+                               *d++ = dsp_audio_mix_law[(q[r]<<8)|o_q[o_r]];
+                               r = (r+1) & CMX_BUFF_MASK;
+                               o_r = (o_r+1) & CMX_BUFF_MASK;
+                       }
+               }
+               dsp->tx_R = t;
+               goto send_packet;
+       }
+#ifdef DSP_NEVER_DEFINED
+       }
+#endif
+       /* PROCESS DATA (three or more members) */
+       /* -> if echo is NOT enabled */
+       if (!dsp->echo) {
+               /*
+                * -> substract rx-data from conf-data,
+                * if tx-data is available, mix
+                */
+               while (r != rr && t != tt) {
+                       sample = dsp_audio_law_to_s32[p[t]] + *c++ -
+                           dsp_audio_law_to_s32[q[r]];
+                       if (sample < -32768)
+                               sample = -32768;
+                       else if (sample > 32767)
+                               sample = 32767;
+                       *d++ = dsp_audio_s16_to_law[sample & 0xffff];
+                           /* conf-rx+tx */
+                       r = (r+1) & CMX_BUFF_MASK;
+                       t = (t+1) & CMX_BUFF_MASK;
+               }
+               while (r != rr) {
+                       sample = *c++ - dsp_audio_law_to_s32[q[r]];
+                       if (sample < -32768)
+                               sample = -32768;
+                       else if (sample > 32767)
+                               sample = 32767;
+                       *d++ = dsp_audio_s16_to_law[sample & 0xffff];
+                           /* conf-rx */
+                       r = (r+1) & CMX_BUFF_MASK;
+               }
+       /* -> if echo is enabled */
+       } else {
+               /*
+                * -> encode conf-data, if tx-data
+                * is available, mix
+                */
+               while (r != rr && t != tt) {
+                       sample = dsp_audio_law_to_s32[p[t]] + *c++;
+                       if (sample < -32768)
+                               sample = -32768;
+                       else if (sample > 32767)
+                               sample = 32767;
+                       *d++ = dsp_audio_s16_to_law[sample & 0xffff];
+                           /* conf(echo)+tx */
+                       t = (t+1) & CMX_BUFF_MASK;
+                       r = (r+1) & CMX_BUFF_MASK;
+               }
+               while (r != rr) {
+                       sample = *c++;
+                       if (sample < -32768)
+                               sample = -32768;
+                       else if (sample > 32767)
+                               sample = 32767;
+                       *d++ = dsp_audio_s16_to_law[sample & 0xffff];
+                           /* conf(echo) */
+                       r = (r+1) & CMX_BUFF_MASK;
+               }
+       }
+       dsp->tx_R = t;
+       goto send_packet;
+
+send_packet:
+       /*
+        * send tx-data if enabled - don't filter,
+        * becuase we want what we send, not what we filtered
+        */
+       if (dsp->tx_data) {
+               /* PREPARE RESULT */
+               txskb = mI_alloc_skb(len, GFP_ATOMIC);
+               if (!txskb) {
+                       printk(KERN_ERR
+                           "FATAL ERROR in mISDN_dsp.o: "
+                           "cannot alloc %d bytes\n", len);
+               } else {
+                       thh = mISDN_HEAD_P(txskb);
+                       thh->prim = DL_DATA_REQ;
+                       thh->id = 0;
+                       memcpy(skb_put(txskb, len), nskb->data+preload, len);
+                       /* queue (trigger later) */
+                       skb_queue_tail(&dsp->sendq, txskb);
+               }
+       }
+       /* adjust volume */
+       if (dsp->tx_volume)
+               dsp_change_volume(nskb, dsp->tx_volume);
+       /* pipeline */
+       if (dsp->pipeline.inuse)
+               dsp_pipeline_process_tx(&dsp->pipeline, nskb->data, nskb->len);
+       /* crypt */
+       if (dsp->bf_enable)
+               dsp_bf_encrypt(dsp, nskb->data, nskb->len);
+       /* queue and trigger */
+       skb_queue_tail(&dsp->sendq, nskb);
+       schedule_work(&dsp->workq);
+}
+
+u32    samplecount;
+struct timer_list dsp_spl_tl;
+u32    dsp_spl_jiffies; /* calculate the next time to fire */
+u32    dsp_start_jiffies; /* jiffies at the time, the calculation begins */
+struct timeval dsp_start_tv; /* time at start of calculation */
+
+void
+dsp_cmx_send(void *arg)
+{
+       struct dsp_conf *conf;
+       struct dsp_conf_member *member;
+       struct dsp *dsp;
+       int mustmix, members;
+       s32 mixbuffer[MAX_POLL+100], *c;
+       u8 *p, *q;
+       int r, rr;
+       int jittercheck = 0, delay, i;
+       u_long flags;
+       struct timeval tv;
+       u32 elapsed;
+       s16 length;
+
+       /* lock */
+       spin_lock_irqsave(&dsp_lock, flags);
+
+       if (!dsp_start_tv.tv_sec) {
+               do_gettimeofday(&dsp_start_tv);
+               length = dsp_poll;
+       } else {
+               do_gettimeofday(&tv);
+               elapsed = ((tv.tv_sec - dsp_start_tv.tv_sec) * 8000)
+                   + ((s32)(tv.tv_usec / 125) - (dsp_start_tv.tv_usec / 125));
+               dsp_start_tv.tv_sec = tv.tv_sec;
+               dsp_start_tv.tv_usec = tv.tv_usec;
+               length = elapsed;
+       }
+       if (length > MAX_POLL + 100)
+               length = MAX_POLL + 100;
+/* printk(KERN_DEBUG "len=%d dsp_count=0x%x.%04x dsp_poll_diff=0x%x.%04x\n",
+ length, dsp_count >> 16, dsp_count & 0xffff, dsp_poll_diff >> 16,
+ dsp_poll_diff & 0xffff);
+ */
+
+       /*
+        * check if jitter needs to be checked
+        * (this is about every second = 8192 samples)
+        */
+       samplecount += length;
+       if ((samplecount & 8191) < length)
+               jittercheck = 1;
+
+       /* loop all members that do not require conference mixing */
+       list_for_each_entry(dsp, &dsp_ilist, list) {
+               if (dsp->hdlc)
+                       continue;
+               conf = dsp->conf;
+               mustmix = 0;
+               members = 0;
+               if (conf) {
+                       members = count_list_member(&conf->mlist);
+#ifdef CMX_CONF_DEBUG
+                       if (conf->software && members > 1)
+#else
+                       if (conf->software && members > 2)
+#endif
+                               mustmix = 1;
+               }
+
+               /* transmission required */
+               if (!mustmix) {
+                       dsp_cmx_send_member(dsp, length, mixbuffer, members);
+
+                       /*
+                        * unused mixbuffer is given to prevent a
+                        * potential null-pointer-bug
+                        */
+               }
+       }
+
+       /* loop all members that require conference mixing */
+       list_for_each_entry(conf, &conf_ilist, list) {
+               /* count members and check hardware */
+               members = count_list_member(&conf->mlist);
+#ifdef CMX_CONF_DEBUG
+               if (conf->software && members > 1) {
+#else
+               if (conf->software && members > 2) {
+#endif
+                       /* check for hdlc conf */
+                       member = list_entry(conf->mlist.next,
+                               struct dsp_conf_member, list);
+                       if (member->dsp->hdlc)
+                               continue;
+                       /* mix all data */
+                       memset(mixbuffer, 0, length*sizeof(s32));
+                       list_for_each_entry(member, &conf->mlist, list) {
+                               dsp = member->dsp;
+                               /* get range of data to mix */
+                               c = mixbuffer;
+                               q = dsp->rx_buff;
+                               r = dsp->rx_R;
+                               rr = (r + length) & CMX_BUFF_MASK;
+                               /* add member's data */
+                               while (r != rr) {
+                                       *c++ += dsp_audio_law_to_s32[q[r]];
+                                       r = (r+1) & CMX_BUFF_MASK;
+                               }
+                       }
+
+                       /* process each member */
+                       list_for_each_entry(member, &conf->mlist, list) {
+                               /* transmission */
+                               dsp_cmx_send_member(member->dsp, length,
+                                   mixbuffer, members);
+                       }
+               }
+       }
+
+       /* delete rx-data, increment buffers, change pointers */
+       list_for_each_entry(dsp, &dsp_ilist, list) {
+               if (dsp->hdlc)
+                       continue;
+               p = dsp->rx_buff;
+               q = dsp->tx_buff;
+               r = dsp->rx_R;
+               /* move receive pointer when receiving */
+               if (!dsp->rx_is_off) {
+                       rr = (r + length) & CMX_BUFF_MASK;
+                       /* delete rx-data */
+                       while (r != rr) {
+                               p[r] = dsp_silence;
+                               r = (r+1) & CMX_BUFF_MASK;
+                       }
+                       /* increment rx-buffer pointer */
+                       dsp->rx_R = r; /* write incremented read pointer */
+               }
+
+               /* check current rx_delay */
+               delay = (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK;
+               if (delay >= CMX_BUFF_HALF)
+                       delay = 0; /* will be the delay before next write */
+               /* check for lower delay */
+               if (delay < dsp->rx_delay[0])
+                       dsp->rx_delay[0] = delay;
+               /* check current tx_delay */
+               delay = (dsp->tx_W-dsp->tx_R) & CMX_BUFF_MASK;
+               if (delay >= CMX_BUFF_HALF)
+                       delay = 0; /* will be the delay before next write */
+               /* check for lower delay */
+               if (delay < dsp->tx_delay[0])
+                       dsp->tx_delay[0] = delay;
+               if (jittercheck) {
+                       /* find the lowest of all rx_delays */
+                       delay = dsp->rx_delay[0];
+                       i = 1;
+                       while (i < MAX_SECONDS_JITTER_CHECK) {
+                               if (delay > dsp->rx_delay[i])
+                                       delay = dsp->rx_delay[i];
+                               i++;
+                       }
+                       /*
+                        * remove rx_delay only if we have delay AND we
+                        * have not preset cmx_delay
+                        */
+                       if (delay && !dsp->cmx_delay) {
+                               if (dsp_debug & DEBUG_DSP_CMX)
+                                       printk(KERN_DEBUG
+                                           "%s lowest rx_delay of %d bytes for"
+                                           " dsp %s are now removed.\n",
+                                           __func__, delay,
+                                           dsp->name);
+                               r = dsp->rx_R;
+                               rr = (r + delay) & CMX_BUFF_MASK;
+                               /* delete rx-data */
+                               while (r != rr) {
+                                       p[r] = dsp_silence;
+                                       r = (r+1) & CMX_BUFF_MASK;
+                               }
+                               /* increment rx-buffer pointer */
+                               dsp->rx_R = r;
+                                   /* write incremented read pointer */
+                       }
+                       /* find the lowest of all tx_delays */
+                       delay = dsp->tx_delay[0];
+                       i = 1;
+                       while (i < MAX_SECONDS_JITTER_CHECK) {
+                               if (delay > dsp->tx_delay[i])
+                                       delay = dsp->tx_delay[i];
+                               i++;
+                       }
+                       /*
+                        * remove delay only if we have delay AND we
+                        * have enabled tx_dejitter
+                        */
+                       if (delay && dsp->tx_dejitter) {
+                               if (dsp_debug & DEBUG_DSP_CMX)
+                                       printk(KERN_DEBUG
+                                           "%s lowest tx_delay of %d bytes for"
+                                           " dsp %s are now removed.\n",
+                                           __func__, delay,
+                                           dsp->name);
+                               r = dsp->tx_R;
+                               rr = (r + delay) & CMX_BUFF_MASK;
+                               /* delete tx-data */
+                               while (r != rr) {
+                                       q[r] = dsp_silence;
+                                       r = (r+1) & CMX_BUFF_MASK;
+                               }
+                               /* increment rx-buffer pointer */
+                               dsp->tx_R = r;
+                                   /* write incremented read pointer */
+                       }
+                       /* scroll up delays */
+                       i = MAX_SECONDS_JITTER_CHECK - 1;
+                       while (i) {
+                               dsp->rx_delay[i] = dsp->rx_delay[i-1];
+                               dsp->tx_delay[i] = dsp->tx_delay[i-1];
+                               i--;
+                       }
+                       dsp->tx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
+                       dsp->rx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
+               }
+       }
+
+       /* if next event would be in the past ... */
+       if ((s32)(dsp_spl_jiffies+dsp_tics-jiffies) <= 0)
+               dsp_spl_jiffies = jiffies + 1;
+       else
+               dsp_spl_jiffies += dsp_tics;
+
+       dsp_spl_tl.expires = dsp_spl_jiffies;
+       add_timer(&dsp_spl_tl);
+
+       /* unlock */
+       spin_unlock_irqrestore(&dsp_lock, flags);
+}
+
+/*
+ * audio data is transmitted from upper layer to the dsp
+ */
+void
+dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb)
+{
+       u_int w, ww;
+       u8 *d, *p;
+       int space; /* todo: , l = skb->len; */
+#ifdef CMX_TX_DEBUG
+       char debugbuf[256] = "";
+#endif
+
+       /* check if there is enough space, and then copy */
+       w = dsp->tx_W;
+       ww = dsp->tx_R;
+       p = dsp->tx_buff;
+       d = skb->data;
+       space = ww-w;
+       if (space <= 0)
+               space += CMX_BUFF_SIZE;
+       /* write-pointer should not overrun nor reach read pointer */
+       if (space-1 < skb->len)
+               /* write to the space we have left */
+               ww = (ww - 1) & CMX_BUFF_MASK;
+       else
+               /* write until all byte are copied */
+               ww = (w + skb->len) & CMX_BUFF_MASK;
+       dsp->tx_W = ww;
+
+       /* show current buffer */
+#ifdef CMX_DEBUG
+       printk(KERN_DEBUG
+           "cmx_transmit(dsp=%lx) %d bytes to 0x%x-0x%x. %s\n",
+           (u_long)dsp, (ww-w)&CMX_BUFF_MASK, w, ww, dsp->name);
+#endif
+
+       /* copy transmit data to tx-buffer */
+#ifdef CMX_TX_DEBUG
+       sprintf(debugbuf, "TX getting (%04x-%04x)%p: ", w, ww, p);
+#endif
+       while (w != ww) {
+#ifdef CMX_TX_DEBUG
+               if (strlen(debugbuf) < 48)
+                       sprintf(debugbuf+strlen(debugbuf), " %02x", *d);
+#endif
+               p[w] = *d++;
+               w = (w+1) & CMX_BUFF_MASK;
+       }
+#ifdef CMX_TX_DEBUG
+       printk(KERN_DEBUG "%s\n", debugbuf);
+#endif
+
+}
+
+/*
+ * hdlc data is received from card and sent to all members.
+ */
+void
+dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
+{
+       struct sk_buff *nskb = NULL;
+       struct dsp_conf_member *member;
+       struct mISDNhead *hh;
+
+       /* not if not active */
+       if (!dsp->b_active)
+               return;
+
+       /* check if we have sompen */
+       if (skb->len < 1)
+               return;
+
+       /* no conf */
+       if (!dsp->conf) {
+               /* in case of hardware (echo) */
+               if (dsp->pcm_slot_tx >= 0)
+                       return;
+               if (dsp->echo)
+                       nskb = skb_clone(skb, GFP_ATOMIC);
+                       if (nskb) {
+                               hh = mISDN_HEAD_P(nskb);
+                               hh->prim = PH_DATA_REQ;
+                               hh->id = 0;
+                               skb_queue_tail(&dsp->sendq, nskb);
+                               schedule_work(&dsp->workq);
+                       }
+               return;
+       }
+       /* in case of hardware conference */
+       if (dsp->conf->hardware)
+               return;
+       list_for_each_entry(member, &dsp->conf->mlist, list) {
+               if (dsp->echo || member->dsp != dsp) {
+                       nskb = skb_clone(skb, GFP_ATOMIC);
+                       if (nskb) {
+                               hh = mISDN_HEAD_P(nskb);
+                               hh->prim = PH_DATA_REQ;
+                               hh->id = 0;
+                               skb_queue_tail(&member->dsp->sendq, nskb);
+                               schedule_work(&member->dsp->workq);
+                       }
+               }
+       }
+}
+
+
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
new file mode 100644 (file)
index 0000000..2f10ed8
--- /dev/null
@@ -0,0 +1,1191 @@
+/*
+ * Author       Andreas Eversberg (jolly@eversberg.eu)
+ * Based on source code structure by
+ *             Karsten Keil (keil@isdn4linux.de)
+ *
+ *             This file is (c) under GNU PUBLIC LICENSE
+ *             For changes and modifications please read
+ *             ../../../Documentation/isdn/mISDN.cert
+ *
+ * Thanks to    Karsten Keil (great drivers)
+ *              Cologne Chip (great chips)
+ *
+ * This module does:
+ *             Real-time tone generation
+ *             DTMF detection
+ *             Real-time cross-connection and conferrence
+ *             Compensate jitter due to system load and hardware fault.
+ *             All features are done in kernel space and will be realized
+ *             using hardware, if available and supported by chip set.
+ *             Blowfish encryption/decryption
+ */
+
+/* STRUCTURE:
+ *
+ * The dsp module provides layer 2 for b-channels (64kbit). It provides
+ * transparent audio forwarding with special digital signal processing:
+ *
+ * - (1) generation of tones
+ * - (2) detection of dtmf tones
+ * - (3) crossconnecting and conferences (clocking)
+ * - (4) echo generation for delay test
+ * - (5) volume control
+ * - (6) disable receive data
+ * - (7) pipeline
+ * - (8) encryption/decryption
+ *
+ * Look:
+ *             TX            RX
+ *         ------upper layer------
+ *             |             ^
+ *             |             |(6)
+ *             v             |
+ *       +-----+-------------+-----+
+ *       |(3)(4)                   |
+ *       |           CMX           |
+ *       |                         |
+ *       |           +-------------+
+ *       |           |       ^
+ *       |           |       |
+ *       |+---------+|  +----+----+
+ *       ||(1)      ||  |(2)      |
+ *       ||         ||  |         |
+ *       ||  Tones  ||  |  DTMF   |
+ *       ||         ||  |         |
+ *       ||         ||  |         |
+ *       |+----+----+|  +----+----+
+ *       +-----+-----+       ^
+ *             |             |
+ *             v             |
+ *        +----+----+   +----+----+
+ *        |(5)      |   |(5)      |
+ *        |         |   |         |
+ *        |TX Volume|   |RX Volume|
+ *        |         |   |         |
+ *        |         |   |         |
+ *        +----+----+   +----+----+
+ *             |             ^
+ *             |             |
+ *             v             |
+ *        +----+-------------+----+
+ *        |(7)                    |
+ *        |                       |
+ *        |  Pipeline Processing  |
+ *        |                       |
+ *        |                       |
+ *        +----+-------------+----+
+ *             |             ^
+ *             |             |
+ *             v             |
+ *        +----+----+   +----+----+
+ *        |(8)      |   |(8)      |
+ *        |         |   |         |
+ *        | Encrypt |   | Decrypt |
+ *        |         |   |         |
+ *        |         |   |         |
+ *        +----+----+   +----+----+
+ *             |             ^
+ *             |             |
+ *             v             |
+ *         ------card  layer------
+ *             TX            RX
+ *
+ * Above you can see the logical data flow. If software is used to do the
+ * process, it is actually the real data flow. If hardware is used, data
+ * may not flow, but hardware commands to the card, to provide the data flow
+ * as shown.
+ *
+ * NOTE: The channel must be activated in order to make dsp work, even if
+ * no data flow to the upper layer is intended. Activation can be done
+ * after and before controlling the setting using PH_CONTROL requests.
+ *
+ * DTMF: Will be detected by hardware if possible. It is done before CMX
+ * processing.
+ *
+ * Tones: Will be generated via software if endless looped audio fifos are
+ * not supported by hardware. Tones will override all data from CMX.
+ * It is not required to join a conference to use tones at any time.
+ *
+ * CMX: Is transparent when not used. When it is used, it will do
+ * crossconnections and conferences via software if not possible through
+ * hardware. If hardware capability is available, hardware is used.
+ *
+ * Echo: Is generated by CMX and is used to check performane of hard and
+ * software CMX.
+ *
+ * The CMX has special functions for conferences with one, two and more
+ * members. It will allow different types of data flow. Receive and transmit
+ * data to/form upper layer may be swithed on/off individually without loosing
+ * features of CMX, Tones and DTMF.
+ *
+ * Echo Cancellation: Sometimes we like to cancel echo from the interface.
+ * Note that a VoIP call may not have echo caused by the IP phone. The echo
+ * is generated by the telephone line connected to it. Because the delay
+ * is high, it becomes an echo. RESULT: Echo Cachelation is required if
+ * both echo AND delay is applied to an interface.
+ * Remember that software CMX always generates a more or less delay.
+ *
+ * If all used features can be realized in hardware, and if transmit and/or
+ * receive data ist disabled, the card may not send/receive any data at all.
+ * Not receiving is usefull if only announcements are played. Not sending is
+ * usefull if an answering machine records audio. Not sending and receiving is
+ * usefull during most states of the call. If supported by hardware, tones
+ * will be played without cpu load. Small PBXs and NT-Mode applications will
+ * not need expensive hardware when processing calls.
+ *
+ *
+ * LOCKING:
+ *
+ * When data is received from upper or lower layer (card), the complete dsp
+ * module is locked by a global lock.  This lock MUST lock irq, because it
+ * must lock timer events by DSP poll timer.
+ * When data is ready to be transmitted down, the data is queued and sent
+ * outside lock and timer event.
+ * PH_CONTROL must not change any settings, join or split conference members
+ * during process of data.
+ *
+ * HDLC:
+ *
+ * It works quite the same as transparent, except that HDLC data is forwarded
+ * to all other conference members if no hardware bridging is possible.
+ * Send data will be writte to sendq. Sendq will be sent if confirm is received.
+ * Conference cannot join, if one member is not hdlc.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/mISDNif.h>
+#include <linux/mISDNdsp.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include "core.h"
+#include "dsp.h"
+
+const char *mISDN_dsp_revision = "2.0";
+
+static int debug;
+static int options;
+static int poll;
+static int dtmfthreshold = 100;
+
+MODULE_AUTHOR("Andreas Eversberg");
+module_param(debug, uint, S_IRUGO | S_IWUSR);
+module_param(options, uint, S_IRUGO | S_IWUSR);
+module_param(poll, uint, S_IRUGO | S_IWUSR);
+module_param(dtmfthreshold, uint, S_IRUGO | S_IWUSR);
+MODULE_LICENSE("GPL");
+
+/*int spinnest = 0;*/
+
+spinlock_t dsp_lock; /* global dsp lock */
+struct list_head dsp_ilist;
+struct list_head conf_ilist;
+int dsp_debug;
+int dsp_options;
+int dsp_poll, dsp_tics;
+
+/* check if rx may be turned off or must be turned on */
+static void
+dsp_rx_off_member(struct dsp *dsp)
+{
+       struct mISDN_ctrl_req   cq;
+       int rx_off = 1;
+
+       if (!dsp->features_rx_off)
+               return;
+
+       /* not disabled */
+       if (!dsp->rx_disabled)
+               rx_off = 0;
+       /* software dtmf */
+       else if (dsp->dtmf.software)
+               rx_off = 0;
+       /* echo in software */
+       else if (dsp->echo && dsp->pcm_slot_tx < 0)
+               rx_off = 0;
+       /* bridge in software */
+       else if (dsp->conf) {
+               if (dsp->conf->software)
+                       rx_off = 0;
+       }
+
+       if (rx_off == dsp->rx_is_off)
+               return;
+
+       if (!dsp->ch.peer) {
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: no peer, no rx_off\n",
+                               __func__);
+               return;
+       }
+       cq.op = MISDN_CTRL_RX_OFF;
+       cq.p1 = rx_off;
+       if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) {
+               printk(KERN_DEBUG "%s: 2nd CONTROL_CHANNEL failed\n",
+                       __func__);
+               return;
+       }
+       dsp->rx_is_off = rx_off;
+       if (dsp_debug & DEBUG_DSP_CORE)
+               printk(KERN_DEBUG "%s: %s set rx_off = %d\n",
+                       __func__, dsp->name, rx_off);
+}
+static void
+dsp_rx_off(struct dsp *dsp)
+{
+       struct dsp_conf_member  *member;
+
+       if (dsp_options & DSP_OPT_NOHARDWARE)
+               return;
+
+       /* no conf */
+       if (!dsp->conf) {
+               dsp_rx_off_member(dsp);
+               return;
+       }
+       /* check all members in conf */
+       list_for_each_entry(member, &dsp->conf->mlist, list) {
+               dsp_rx_off_member(member->dsp);
+       }
+}
+
+static int
+dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
+{
+       struct          sk_buff *nskb;
+       int ret = 0;
+       int cont;
+       u8 *data;
+       int len;
+
+       if (skb->len < sizeof(int))
+               printk(KERN_ERR "%s: PH_CONTROL message too short\n", __func__);
+       cont = *((int *)skb->data);
+       len = skb->len - sizeof(int);
+       data = skb->data + sizeof(int);
+
+       switch (cont) {
+       case DTMF_TONE_START: /* turn on DTMF */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: start dtmf\n", __func__);
+               if (len == sizeof(int)) {
+                       printk(KERN_NOTICE "changing DTMF Threshold "
+                               "to %d\n", *((int *)data));
+                       dsp->dtmf.treshold = (*(int *)data) * 10000;
+               }
+               /* init goertzel */
+               dsp_dtmf_goertzel_init(dsp);
+
+               /* check dtmf hardware */
+               dsp_dtmf_hardware(dsp);
+               break;
+       case DTMF_TONE_STOP: /* turn off DTMF */
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: stop dtmf\n", __func__);
+               dsp->dtmf.hardware = 0;
+               dsp->dtmf.software = 0;
+               break;
+       case DSP_CONF_JOIN: /* join / update conference */
+               if (len < sizeof(int)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (*((u32 *)data) == 0)
+                       goto conf_split;
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: join conference %d\n",
+                               __func__, *((u32 *)data));
+               ret = dsp_cmx_conf(dsp, *((u32 *)data));
+                       /* dsp_cmx_hardware will also be called here */
+               dsp_rx_off(dsp);
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       dsp_cmx_debug(dsp);
+               break;
+       case DSP_CONF_SPLIT: /* remove from conference */
+conf_split:
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: release conference\n", __func__);
+               ret = dsp_cmx_conf(dsp, 0);
+                       /* dsp_cmx_hardware will also be called here */
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       dsp_cmx_debug(dsp);
+               dsp_rx_off(dsp);
+               break;
+       case DSP_TONE_PATT_ON: /* play tone */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (len < sizeof(int)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: turn tone 0x%x on\n",
+                               __func__, *((int *)skb->data));
+               ret = dsp_tone(dsp, *((int *)data));
+               if (!ret) {
+                       dsp_cmx_hardware(dsp->conf, dsp);
+                       dsp_rx_off(dsp);
+               }
+               if (!dsp->tone.tone)
+                       goto tone_off;
+               break;
+       case DSP_TONE_PATT_OFF: /* stop tone */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: turn tone off\n", __func__);
+               dsp_tone(dsp, 0);
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_rx_off(dsp);
+               /* reset tx buffers (user space data) */
+tone_off:
+               dsp->rx_W = 0;
+               dsp->rx_R = 0;
+               break;
+       case DSP_VOL_CHANGE_TX: /* change volume */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (len < sizeof(int)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               dsp->tx_volume = *((int *)data);
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: change tx vol to %d\n",
+                               __func__, dsp->tx_volume);
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_dtmf_hardware(dsp);
+               dsp_rx_off(dsp);
+               break;
+       case DSP_VOL_CHANGE_RX: /* change volume */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (len < sizeof(int)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               dsp->rx_volume = *((int *)data);
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: change rx vol to %d\n",
+                               __func__, dsp->tx_volume);
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_dtmf_hardware(dsp);
+               dsp_rx_off(dsp);
+               break;
+       case DSP_ECHO_ON: /* enable echo */
+               dsp->echo = 1; /* soft echo */
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: enable cmx-echo\n", __func__);
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_rx_off(dsp);
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       dsp_cmx_debug(dsp);
+               break;
+       case DSP_ECHO_OFF: /* disable echo */
+               dsp->echo = 0;
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: disable cmx-echo\n", __func__);
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_rx_off(dsp);
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       dsp_cmx_debug(dsp);
+               break;
+       case DSP_RECEIVE_ON: /* enable receive to user space */
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: enable receive to user "
+                               "space\n", __func__);
+               dsp->rx_disabled = 0;
+               dsp_rx_off(dsp);
+               break;
+       case DSP_RECEIVE_OFF: /* disable receive to user space */
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: disable receive to "
+                               "user space\n", __func__);
+               dsp->rx_disabled = 1;
+               dsp_rx_off(dsp);
+               break;
+       case DSP_MIX_ON: /* enable mixing of tx data */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: enable mixing of "
+                               "tx-data with conf mebers\n", __func__);
+               dsp->tx_mix = 1;
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_rx_off(dsp);
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       dsp_cmx_debug(dsp);
+               break;
+       case DSP_MIX_OFF: /* disable mixing of tx data */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: disable mixing of "
+                               "tx-data with conf mebers\n", __func__);
+               dsp->tx_mix = 0;
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_rx_off(dsp);
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       dsp_cmx_debug(dsp);
+               break;
+       case DSP_TXDATA_ON: /* enable txdata */
+               dsp->tx_data = 1;
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: enable tx-data\n", __func__);
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_rx_off(dsp);
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       dsp_cmx_debug(dsp);
+               break;
+       case DSP_TXDATA_OFF: /* disable txdata */
+               dsp->tx_data = 0;
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: disable tx-data\n", __func__);
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_rx_off(dsp);
+               if (dsp_debug & DEBUG_DSP_CMX)
+                       dsp_cmx_debug(dsp);
+               break;
+       case DSP_DELAY: /* use delay algorithm instead of dynamic
+                          jitter algorithm */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (len < sizeof(int)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               dsp->cmx_delay = (*((int *)data)) << 3;
+                       /* miliseconds to samples */
+               if (dsp->cmx_delay >= (CMX_BUFF_HALF>>1))
+                       /* clip to half of maximum usable buffer
+                       (half of half buffer) */
+                       dsp->cmx_delay = (CMX_BUFF_HALF>>1) - 1;
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: use delay algorithm to "
+                               "compensate jitter (%d samples)\n",
+                               __func__, dsp->cmx_delay);
+               break;
+       case DSP_JITTER: /* use dynamic jitter algorithm instead of
+                   delay algorithm */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               dsp->cmx_delay = 0;
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: use jitter algorithm to "
+                               "compensate jitter\n", __func__);
+               break;
+       case DSP_TX_DEJITTER: /* use dynamic jitter algorithm for tx-buffer */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               dsp->tx_dejitter = 1;
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: use dejitter on TX "
+                               "buffer\n", __func__);
+               break;
+       case DSP_TX_DEJ_OFF: /* use tx-buffer without dejittering*/
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               dsp->tx_dejitter = 0;
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: use TX buffer without "
+                               "dejittering\n", __func__);
+               break;
+       case DSP_PIPELINE_CFG:
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (len > 0 && ((char *)data)[len - 1]) {
+                       printk(KERN_DEBUG "%s: pipeline config string "
+                               "is not NULL terminated!\n", __func__);
+                       ret = -EINVAL;
+               } else {
+                       dsp->pipeline.inuse = 1;
+                       dsp_cmx_hardware(dsp->conf, dsp);
+                       ret = dsp_pipeline_build(&dsp->pipeline,
+                               len > 0 ? (char *)data : NULL);
+                       dsp_cmx_hardware(dsp->conf, dsp);
+                       dsp_rx_off(dsp);
+               }
+               break;
+       case DSP_BF_ENABLE_KEY: /* turn blowfish on */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (len < 4 || len > 56) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: turn blowfish on (key "
+                               "not shown)\n", __func__);
+               ret = dsp_bf_init(dsp, (u8 *)data, len);
+               /* set new cont */
+               if (!ret)
+                       cont = DSP_BF_ACCEPT;
+               else
+                       cont = DSP_BF_REJECT;
+               /* send indication if it worked to set it */
+               nskb = _alloc_mISDN_skb(PH_CONTROL_IND, MISDN_ID_ANY,
+                       sizeof(int), &cont, GFP_ATOMIC);
+               if (nskb) {
+                       if (dsp->up) {
+                               if (dsp->up->send(dsp->up, nskb))
+                                       dev_kfree_skb(nskb);
+                       } else
+                               dev_kfree_skb(nskb);
+               }
+               if (!ret) {
+                       dsp_cmx_hardware(dsp->conf, dsp);
+                       dsp_dtmf_hardware(dsp);
+                       dsp_rx_off(dsp);
+               }
+               break;
+       case DSP_BF_DISABLE: /* turn blowfish off */
+               if (dsp->hdlc) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: turn blowfish off\n", __func__);
+               dsp_bf_cleanup(dsp);
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_dtmf_hardware(dsp);
+               dsp_rx_off(dsp);
+               break;
+       default:
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: ctrl req %x unhandled\n",
+                               __func__, cont);
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static void
+get_features(struct mISDNchannel *ch)
+{
+       struct dsp              *dsp = container_of(ch, struct dsp, ch);
+       struct mISDN_ctrl_req   cq;
+
+       if (dsp_options & DSP_OPT_NOHARDWARE)
+               return;
+       if (!ch->peer) {
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: no peer, no features\n",
+                               __func__);
+               return;
+       }
+       memset(&cq, 0, sizeof(cq));
+       cq.op = MISDN_CTRL_GETOP;
+       if (ch->peer->ctrl(ch->peer, CONTROL_CHANNEL, &cq) < 0) {
+               printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
+                       __func__);
+               return;
+       }
+       if (cq.op & MISDN_CTRL_RX_OFF)
+               dsp->features_rx_off = 1;
+       if ((cq.op & MISDN_CTRL_HW_FEATURES_OP)) {
+               cq.op = MISDN_CTRL_HW_FEATURES;
+               *((u_long *)&cq.p1) = (u_long)&dsp->features;
+               if (ch->peer->ctrl(ch->peer, CONTROL_CHANNEL, &cq)) {
+                       printk(KERN_DEBUG "%s: 2nd CONTROL_CHANNEL failed\n",
+                               __func__);
+               }
+       } else
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: features not supported for %s\n",
+                               __func__, dsp->name);
+}
+
+static int
+dsp_function(struct mISDNchannel *ch,  struct sk_buff *skb)
+{
+       struct dsp                      *dsp = container_of(ch, struct dsp, ch);
+       struct mISDNhead        *hh;
+       int                     ret = 0;
+       u8                      *digits;
+       int                     cont;
+       struct                  sk_buff *nskb;
+       u_long                  flags;
+
+       hh = mISDN_HEAD_P(skb);
+       switch (hh->prim) {
+       /* FROM DOWN */
+       case (PH_DATA_CNF):
+               dsp->data_pending = 0;
+               /* trigger next hdlc frame, if any */
+               if (dsp->hdlc) {
+                       spin_lock_irqsave(&dsp_lock, flags);
+                       if (dsp->b_active)
+                               schedule_work(&dsp->workq);
+                       spin_unlock_irqrestore(&dsp_lock, flags);
+               }
+               break;
+       case (PH_DATA_IND):
+       case (DL_DATA_IND):
+               if (skb->len < 1) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (dsp->rx_is_off) {
+                       if (dsp_debug & DEBUG_DSP_CORE)
+                               printk(KERN_DEBUG "%s: rx-data during rx_off"
+                                       " for %s\n",
+                               __func__, dsp->name);
+               }
+               if (dsp->hdlc) {
+                       /* hdlc */
+                       spin_lock_irqsave(&dsp_lock, flags);
+                       dsp_cmx_hdlc(dsp, skb);
+                       spin_unlock_irqrestore(&dsp_lock, flags);
+                       if (dsp->rx_disabled) {
+                               /* if receive is not allowed */
+                               break;
+                       }
+                       hh->prim = DL_DATA_IND;
+                       if (dsp->up)
+                               return dsp->up->send(dsp->up, skb);
+                       break;
+               }
+
+               /* decrypt if enabled */
+               if (dsp->bf_enable)
+                       dsp_bf_decrypt(dsp, skb->data, skb->len);
+               /* pipeline */
+               if (dsp->pipeline.inuse)
+                       dsp_pipeline_process_rx(&dsp->pipeline, skb->data,
+                               skb->len);
+               /* change volume if requested */
+               if (dsp->rx_volume)
+                       dsp_change_volume(skb, dsp->rx_volume);
+
+               /* check if dtmf soft decoding is turned on */
+               if (dsp->dtmf.software) {
+                       digits = dsp_dtmf_goertzel_decode(dsp, skb->data,
+                               skb->len, (dsp_options&DSP_OPT_ULAW)?1:0);
+                       while (*digits) {
+                               if (dsp_debug & DEBUG_DSP_DTMF)
+                                       printk(KERN_DEBUG "%s: digit"
+                                           "(%c) to layer %s\n",
+                                           __func__, *digits, dsp->name);
+                               cont = DTMF_TONE_VAL | *digits;
+                               nskb = _alloc_mISDN_skb(PH_CONTROL_IND,
+                                   MISDN_ID_ANY, sizeof(int), &cont,
+                                   GFP_ATOMIC);
+                               if (nskb) {
+                                       if (dsp->up) {
+                                               if (dsp->up->send(
+                                                   dsp->up, nskb))
+                                               dev_kfree_skb(nskb);
+                                       } else
+                                               dev_kfree_skb(nskb);
+                               }
+                               digits++;
+                       }
+               }
+               /* we need to process receive data if software */
+               spin_lock_irqsave(&dsp_lock, flags);
+               if (dsp->pcm_slot_tx < 0 && dsp->pcm_slot_rx < 0) {
+                       /* process data from card at cmx */
+                       dsp_cmx_receive(dsp, skb);
+               }
+               spin_unlock_irqrestore(&dsp_lock, flags);
+
+               if (dsp->rx_disabled) {
+                       /* if receive is not allowed */
+                       break;
+               }
+               hh->prim = DL_DATA_IND;
+               if (dsp->up)
+                       return dsp->up->send(dsp->up, skb);
+               break;
+       case (PH_CONTROL_IND):
+               if (dsp_debug & DEBUG_DSP_DTMFCOEFF)
+                       printk(KERN_DEBUG "%s: PH_CONTROL INDICATION "
+                               "received: %x (len %d) %s\n", __func__,
+                               hh->id, skb->len, dsp->name);
+               switch (hh->id) {
+               case (DTMF_HFC_COEF): /* getting coefficients */
+                       if (!dsp->dtmf.hardware) {
+                               if (dsp_debug & DEBUG_DSP_DTMFCOEFF)
+                                       printk(KERN_DEBUG "%s: ignoring DTMF "
+                                               "coefficients from HFC\n",
+                                               __func__);
+                               break;
+                       }
+                       digits = dsp_dtmf_goertzel_decode(dsp, skb->data,
+                               skb->len, 2);
+                       while (*digits) {
+                               int k;
+                               struct sk_buff *nskb;
+                               if (dsp_debug & DEBUG_DSP_DTMF)
+                                       printk(KERN_DEBUG "%s: digit"
+                                           "(%c) to layer %s\n",
+                                           __func__, *digits, dsp->name);
+                               k = *digits | DTMF_TONE_VAL;
+                               nskb = _alloc_mISDN_skb(PH_CONTROL_IND,
+                                       MISDN_ID_ANY, sizeof(int), &k,
+                                       GFP_ATOMIC);
+                               if (nskb) {
+                                       if (dsp->up) {
+                                               if (dsp->up->send(
+                                                   dsp->up, nskb))
+                                               dev_kfree_skb(nskb);
+                                       } else
+                                               dev_kfree_skb(nskb);
+                               }
+                               digits++;
+                       }
+                       break;
+               case (HFC_VOL_CHANGE_TX): /* change volume */
+                       if (skb->len != sizeof(int)) {
+                               ret = -EINVAL;
+                               break;
+                       }
+                       spin_lock_irqsave(&dsp_lock, flags);
+                       dsp->tx_volume = *((int *)skb->data);
+                       if (dsp_debug & DEBUG_DSP_CORE)
+                               printk(KERN_DEBUG "%s: change tx volume to "
+                                       "%d\n", __func__, dsp->tx_volume);
+                       dsp_cmx_hardware(dsp->conf, dsp);
+                       dsp_dtmf_hardware(dsp);
+                       dsp_rx_off(dsp);
+                       spin_unlock_irqrestore(&dsp_lock, flags);
+                       break;
+               default:
+                       if (dsp_debug & DEBUG_DSP_CORE)
+                               printk(KERN_DEBUG "%s: ctrl ind %x unhandled "
+                                       "%s\n", __func__, hh->id, dsp->name);
+                       ret = -EINVAL;
+               }
+               break;
+       case (PH_ACTIVATE_IND):
+       case (PH_ACTIVATE_CNF):
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: b_channel is now active %s\n",
+                               __func__, dsp->name);
+               /* bchannel now active */
+               spin_lock_irqsave(&dsp_lock, flags);
+               dsp->b_active = 1;
+               dsp->data_pending = 0;
+               dsp->rx_init = 1;
+                       /* rx_W and rx_R will be adjusted on first frame */
+               dsp->rx_W = 0;
+               dsp->rx_R = 0;
+               memset(dsp->rx_buff, 0, sizeof(dsp->rx_buff));
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_dtmf_hardware(dsp);
+               dsp_rx_off(dsp);
+               spin_unlock_irqrestore(&dsp_lock, flags);
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: done with activation, sending "
+                               "confirm to user space. %s\n", __func__,
+                               dsp->name);
+               /* send activation to upper layer */
+               hh->prim = DL_ESTABLISH_CNF;
+               if (dsp->up)
+                       return dsp->up->send(dsp->up, skb);
+               break;
+       case (PH_DEACTIVATE_IND):
+       case (PH_DEACTIVATE_CNF):
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: b_channel is now inactive %s\n",
+                               __func__, dsp->name);
+               /* bchannel now inactive */
+               spin_lock_irqsave(&dsp_lock, flags);
+               dsp->b_active = 0;
+               dsp->data_pending = 0;
+               dsp_cmx_hardware(dsp->conf, dsp);
+               dsp_rx_off(dsp);
+               spin_unlock_irqrestore(&dsp_lock, flags);
+               hh->prim = DL_RELEASE_CNF;
+               if (dsp->up)
+                       return dsp->up->send(dsp->up, skb);
+               break;
+       /* FROM UP */
+       case (DL_DATA_REQ):
+       case (PH_DATA_REQ):
+               if (skb->len < 1) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (dsp->hdlc) {
+                       /* hdlc */
+                       spin_lock_irqsave(&dsp_lock, flags);
+                       if (dsp->b_active) {
+                               skb_queue_tail(&dsp->sendq, skb);
+                               schedule_work(&dsp->workq);
+                       }
+                       spin_unlock_irqrestore(&dsp_lock, flags);
+                       return 0;
+               }
+               /* send data to tx-buffer (if no tone is played) */
+               if (!dsp->tone.tone) {
+                       spin_lock_irqsave(&dsp_lock, flags);
+                       dsp_cmx_transmit(dsp, skb);
+                       spin_unlock_irqrestore(&dsp_lock, flags);
+               }
+               break;
+       case (PH_CONTROL_REQ):
+               spin_lock_irqsave(&dsp_lock, flags);
+               ret = dsp_control_req(dsp, hh, skb);
+               spin_unlock_irqrestore(&dsp_lock, flags);
+               break;
+       case (DL_ESTABLISH_REQ):
+       case (PH_ACTIVATE_REQ):
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: activating b_channel %s\n",
+                               __func__, dsp->name);
+               if (dsp->dtmf.hardware || dsp->dtmf.software)
+                       dsp_dtmf_goertzel_init(dsp);
+               get_features(ch);
+               /* send ph_activate */
+               hh->prim = PH_ACTIVATE_REQ;
+               if (ch->peer)
+                       return ch->recv(ch->peer, skb);
+               break;
+       case (DL_RELEASE_REQ):
+       case (PH_DEACTIVATE_REQ):
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: releasing b_channel %s\n",
+                               __func__, dsp->name);
+               spin_lock_irqsave(&dsp_lock, flags);
+               dsp->tone.tone = 0;
+               dsp->tone.hardware = 0;
+               dsp->tone.software = 0;
+               if (timer_pending(&dsp->tone.tl))
+                       del_timer(&dsp->tone.tl);
+               if (dsp->conf)
+                       dsp_cmx_conf(dsp, 0); /* dsp_cmx_hardware will also be
+                                                called here */
+               skb_queue_purge(&dsp->sendq);
+               spin_unlock_irqrestore(&dsp_lock, flags);
+               hh->prim = PH_DEACTIVATE_REQ;
+               if (ch->peer)
+                       return ch->recv(ch->peer, skb);
+               break;
+       default:
+               if (dsp_debug & DEBUG_DSP_CORE)
+                       printk(KERN_DEBUG "%s: msg %x unhandled %s\n",
+                               __func__, hh->prim, dsp->name);
+               ret = -EINVAL;
+       }
+       if (!ret)
+               dev_kfree_skb(skb);
+       return ret;
+}
+
+static int
+dsp_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct dsp              *dsp = container_of(ch, struct dsp, ch);
+       u_long          flags;
+       int             err = 0;
+
+       if (debug & DEBUG_DSP_CTRL)
+       printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd);
+
+       switch (cmd) {
+       case OPEN_CHANNEL:
+               break;
+       case CLOSE_CHANNEL:
+               if (dsp->ch.peer)
+                       dsp->ch.peer->ctrl(dsp->ch.peer, CLOSE_CHANNEL, NULL);
+
+               /* wait until workqueue has finished,
+                * must lock here, or we may hit send-process currently
+                * queueing. */
+               spin_lock_irqsave(&dsp_lock, flags);
+               dsp->b_active = 0;
+               spin_unlock_irqrestore(&dsp_lock, flags);
+               /* MUST not be locked, because it waits until queue is done. */
+               cancel_work_sync(&dsp->workq);
+               spin_lock_irqsave(&dsp_lock, flags);
+               if (timer_pending(&dsp->tone.tl))
+                       del_timer(&dsp->tone.tl);
+               skb_queue_purge(&dsp->sendq);
+               if (dsp_debug & DEBUG_DSP_CTRL)
+                       printk(KERN_DEBUG "%s: releasing member %s\n",
+                               __func__, dsp->name);
+               dsp->b_active = 0;
+               dsp_cmx_conf(dsp, 0); /* dsp_cmx_hardware will also be called
+                                        here */
+               dsp_pipeline_destroy(&dsp->pipeline);
+
+               if (dsp_debug & DEBUG_DSP_CTRL)
+                       printk(KERN_DEBUG "%s: remove & destroy object %s\n",
+                               __func__, dsp->name);
+               list_del(&dsp->list);
+               spin_unlock_irqrestore(&dsp_lock, flags);
+
+               if (dsp_debug & DEBUG_DSP_CTRL)
+                       printk(KERN_DEBUG "%s: dsp instance released\n",
+                               __func__);
+               vfree(dsp);
+               module_put(THIS_MODULE);
+               break;
+       }
+       return err;
+}
+
+static void
+dsp_send_bh(struct work_struct *work)
+{
+       struct dsp *dsp = container_of(work, struct dsp, workq);
+       struct sk_buff *skb;
+       struct mISDNhead        *hh;
+
+       if (dsp->hdlc && dsp->data_pending)
+               return; /* wait until data has been acknowledged */
+
+       /* send queued data */
+       while ((skb = skb_dequeue(&dsp->sendq))) {
+               /* in locked date, we must have still data in queue */
+               if (dsp->data_pending) {
+                       if (dsp_debug & DEBUG_DSP_CORE)
+                               printk(KERN_DEBUG "%s: fifo full %s, this is "
+                                       "no bug!\n", __func__, dsp->name);
+                       /* flush transparent data, if not acked */
+                       dev_kfree_skb(skb);
+                       continue;
+               }
+               hh = mISDN_HEAD_P(skb);
+               if (hh->prim == DL_DATA_REQ) {
+                       /* send packet up */
+                       if (dsp->up) {
+                               if (dsp->up->send(dsp->up, skb))
+                                       dev_kfree_skb(skb);
+                       } else
+                               dev_kfree_skb(skb);
+               } else {
+                       /* send packet down */
+                       if (dsp->ch.peer) {
+                               dsp->data_pending = 1;
+                               if (dsp->ch.recv(dsp->ch.peer, skb)) {
+                                       dev_kfree_skb(skb);
+                                       dsp->data_pending = 0;
+                               }
+                       } else
+                               dev_kfree_skb(skb);
+               }
+       }
+}
+
+static int
+dspcreate(struct channel_req *crq)
+{
+       struct dsp              *ndsp;
+       u_long          flags;
+
+       if (crq->protocol != ISDN_P_B_L2DSP
+        && crq->protocol != ISDN_P_B_L2DSPHDLC)
+               return -EPROTONOSUPPORT;
+       ndsp = vmalloc(sizeof(struct dsp));
+       if (!ndsp) {
+               printk(KERN_ERR "%s: vmalloc struct dsp failed\n", __func__);
+               return -ENOMEM;
+       }
+       memset(ndsp, 0, sizeof(struct dsp));
+       if (dsp_debug & DEBUG_DSP_CTRL)
+               printk(KERN_DEBUG "%s: creating new dsp instance\n", __func__);
+
+       /* default enabled */
+       INIT_WORK(&ndsp->workq, (void *)dsp_send_bh);
+       skb_queue_head_init(&ndsp->sendq);
+       ndsp->ch.send = dsp_function;
+       ndsp->ch.ctrl = dsp_ctrl;
+       ndsp->up = crq->ch;
+       crq->ch = &ndsp->ch;
+       if (crq->protocol == ISDN_P_B_L2DSP) {
+               crq->protocol = ISDN_P_B_RAW;
+               ndsp->hdlc = 0;
+       } else {
+               crq->protocol = ISDN_P_B_HDLC;
+               ndsp->hdlc = 1;
+       }
+       if (!try_module_get(THIS_MODULE))
+               printk(KERN_WARNING "%s:cannot get module\n",
+                       __func__);
+
+       sprintf(ndsp->name, "DSP_C%x(0x%p)",
+               ndsp->up->st->dev->id + 1, ndsp);
+       /* set frame size to start */
+       ndsp->features.hfc_id = -1; /* current PCM id */
+       ndsp->features.pcm_id = -1; /* current PCM id */
+       ndsp->pcm_slot_rx = -1; /* current CPM slot */
+       ndsp->pcm_slot_tx = -1;
+       ndsp->pcm_bank_rx = -1;
+       ndsp->pcm_bank_tx = -1;
+       ndsp->hfc_conf = -1; /* current conference number */
+       /* set tone timer */
+       ndsp->tone.tl.function = (void *)dsp_tone_timeout;
+       ndsp->tone.tl.data = (long) ndsp;
+       init_timer(&ndsp->tone.tl);
+
+       if (dtmfthreshold < 20 || dtmfthreshold > 500)
+               dtmfthreshold = 200;
+       ndsp->dtmf.treshold = dtmfthreshold*10000;
+
+       /* init pipeline append to list */
+       spin_lock_irqsave(&dsp_lock, flags);
+       dsp_pipeline_init(&ndsp->pipeline);
+       list_add_tail(&ndsp->list, &dsp_ilist);
+       spin_unlock_irqrestore(&dsp_lock, flags);
+
+       return 0;
+}
+
+
+static struct Bprotocol DSP = {
+       .Bprotocols = (1 << (ISDN_P_B_L2DSP & ISDN_P_B_MASK))
+               | (1 << (ISDN_P_B_L2DSPHDLC & ISDN_P_B_MASK)),
+       .name = "dsp",
+       .create = dspcreate
+};
+
+static int dsp_init(void)
+{
+       int err;
+       int tics;
+
+       printk(KERN_INFO "DSP modul %s\n", mISDN_dsp_revision);
+
+       dsp_options = options;
+       dsp_debug = debug;
+
+       /* set packet size */
+       dsp_poll = poll;
+       if (dsp_poll) {
+               if (dsp_poll > MAX_POLL) {
+                       printk(KERN_ERR "%s: Wrong poll value (%d), use %d "
+                               "maximum.\n", __func__, poll, MAX_POLL);
+                       err = -EINVAL;
+                       return err;
+               }
+               if (dsp_poll < 8) {
+                       printk(KERN_ERR "%s: Wrong poll value (%d), use 8 "
+                               "minimum.\n", __func__, dsp_poll);
+                       err = -EINVAL;
+                       return err;
+               }
+               dsp_tics = poll * HZ / 8000;
+               if (dsp_tics * 8000 != poll * HZ) {
+                       printk(KERN_INFO "mISDN_dsp: Cannot clock every %d "
+                               "samples (0,125 ms). It is not a multiple of "
+                               "%d HZ.\n", poll, HZ);
+                       err = -EINVAL;
+                       return err;
+               }
+       } else {
+               poll = 8;
+               while (poll <= MAX_POLL) {
+                       tics = poll * HZ / 8000;
+                       if (tics * 8000 == poll * HZ) {
+                               dsp_tics = tics;
+                               dsp_poll = poll;
+                               if (poll >= 64)
+                                       break;
+                       }
+                       poll++;
+               }
+       }
+       if (dsp_poll == 0) {
+               printk(KERN_INFO "mISDN_dsp: There is no multiple of kernel "
+                       "clock that equals exactly the duration of 8-256 "
+                       "samples. (Choose kernel clock speed like 100, 250, "
+                       "300, 1000)\n");
+               err = -EINVAL;
+               return err;
+       }
+       printk(KERN_INFO "mISDN_dsp: DSP clocks every %d samples. This equals "
+               "%d jiffies.\n", dsp_poll, dsp_tics);
+
+       spin_lock_init(&dsp_lock);
+       INIT_LIST_HEAD(&dsp_ilist);
+       INIT_LIST_HEAD(&conf_ilist);
+
+       /* init conversion tables */
+       dsp_audio_generate_law_tables();
+       dsp_silence = (dsp_options&DSP_OPT_ULAW)?0xff:0x2a;
+       dsp_audio_law_to_s32 = (dsp_options&DSP_OPT_ULAW)?dsp_audio_ulaw_to_s32:
+               dsp_audio_alaw_to_s32;
+       dsp_audio_generate_s2law_table();
+       dsp_audio_generate_seven();
+       dsp_audio_generate_mix_table();
+       if (dsp_options & DSP_OPT_ULAW)
+               dsp_audio_generate_ulaw_samples();
+       dsp_audio_generate_volume_changes();
+
+       err = dsp_pipeline_module_init();
+       if (err) {
+               printk(KERN_ERR "mISDN_dsp: Can't initialize pipeline, "
+                       "error(%d)\n", err);
+               return err;
+       }
+
+       err = mISDN_register_Bprotocol(&DSP);
+       if (err) {
+               printk(KERN_ERR "Can't register %s error(%d)\n", DSP.name, err);
+               return err;
+       }
+
+       /* set sample timer */
+       dsp_spl_tl.function = (void *)dsp_cmx_send;
+       dsp_spl_tl.data = 0;
+       init_timer(&dsp_spl_tl);
+       dsp_spl_tl.expires = jiffies + dsp_tics;
+       dsp_spl_jiffies = dsp_spl_tl.expires;
+       add_timer(&dsp_spl_tl);
+
+       return 0;
+}
+
+
+static void dsp_cleanup(void)
+{
+       mISDN_unregister_Bprotocol(&DSP);
+
+       if (timer_pending(&dsp_spl_tl))
+               del_timer(&dsp_spl_tl);
+
+       if (!list_empty(&dsp_ilist)) {
+               printk(KERN_ERR "mISDN_dsp: Audio DSP object inst list not "
+                       "empty.\n");
+       }
+       if (!list_empty(&conf_ilist)) {
+               printk(KERN_ERR "mISDN_dsp: Conference list not empty. Not "
+                       "all memory freed.\n");
+       }
+
+       dsp_pipeline_module_exit();
+}
+
+module_init(dsp_init);
+module_exit(dsp_cleanup);
+
diff --git a/drivers/isdn/mISDN/dsp_dtmf.c b/drivers/isdn/mISDN/dsp_dtmf.c
new file mode 100644 (file)
index 0000000..efc371c
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * DTMF decoder.
+ *
+ * Copyright            by Andreas Eversberg (jolly@eversberg.eu)
+ *                     based on different decoders such as ISDN4Linux
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ */
+
+#include <linux/mISDNif.h>
+#include <linux/mISDNdsp.h>
+#include "core.h"
+#include "dsp.h"
+
+#define NCOEFF            8     /* number of frequencies to be analyzed */
+
+/* For DTMF recognition:
+ * 2 * cos(2 * PI * k / N) precalculated for all k
+ */
+static u64 cos2pik[NCOEFF] =
+{
+       /* k << 15 (source: hfc-4s/8s documentation (www.colognechip.de)) */
+       55960, 53912, 51402, 48438, 38146, 32650, 26170, 18630
+};
+
+/* digit matrix */
+static char dtmf_matrix[4][4] =
+{
+       {'1', '2', '3', 'A'},
+       {'4', '5', '6', 'B'},
+       {'7', '8', '9', 'C'},
+       {'*', '0', '#', 'D'}
+};
+
+/* dtmf detection using goertzel algorithm
+ * init function
+ */
+void dsp_dtmf_goertzel_init(struct dsp *dsp)
+{
+       dsp->dtmf.size = 0;
+       dsp->dtmf.lastwhat = '\0';
+       dsp->dtmf.lastdigit = '\0';
+       dsp->dtmf.count = 0;
+}
+
+/* check for hardware or software features
+ */
+void dsp_dtmf_hardware(struct dsp *dsp)
+{
+       int hardware = 1;
+
+       if (!dsp->features.hfc_dtmf)
+               hardware = 0;
+
+       /* check for volume change */
+       if (dsp->tx_volume) {
+               if (dsp_debug & DEBUG_DSP_DTMF)
+                       printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, "
+                               "because tx_volume is changed\n",
+                               __func__, dsp->name);
+               hardware = 0;
+       }
+       if (dsp->rx_volume) {
+               if (dsp_debug & DEBUG_DSP_DTMF)
+                       printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, "
+                               "because rx_volume is changed\n",
+                               __func__, dsp->name);
+               hardware = 0;
+       }
+       /* check if encryption is enabled */
+       if (dsp->bf_enable) {
+               if (dsp_debug & DEBUG_DSP_DTMF)
+                       printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, "
+                               "because encryption is enabled\n",
+                               __func__, dsp->name);
+               hardware = 0;
+       }
+       /* check if pipeline exists */
+       if (dsp->pipeline.inuse) {
+               if (dsp_debug & DEBUG_DSP_DTMF)
+                       printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, "
+                               "because pipeline exists.\n",
+                               __func__, dsp->name);
+               hardware = 0;
+       }
+
+       dsp->dtmf.hardware = hardware;
+       dsp->dtmf.software = !hardware;
+}
+
+
+/*************************************************************
+ * calculate the coefficients of the given sample and decode *
+ *************************************************************/
+
+/* the given sample is decoded. if the sample is not long enough for a
+ * complete frame, the decoding is finished and continued with the next
+ * call of this function.
+ *
+ * the algorithm is very good for detection with a minimum of errors. i
+ * tested it allot. it even works with very short tones (40ms). the only
+ * disadvantage is, that it doesn't work good with different volumes of both
+ * tones. this will happen, if accoustically coupled dialers are used.
+ * it sometimes detects tones during speach, which is normal for decoders.
+ * use sequences to given commands during calls.
+ *
+ * dtmf - points to a structure of the current dtmf state
+ * spl and len - the sample
+ * fmt - 0 = alaw, 1 = ulaw, 2 = coefficients from HFC DTMF hw-decoder
+ */
+
+u8
+*dsp_dtmf_goertzel_decode(struct dsp *dsp, u8 *data, int len, int fmt)
+{
+       u8 what;
+       int size;
+       signed short *buf;
+       s32 sk, sk1, sk2;
+       int k, n, i;
+       s32 *hfccoeff;
+       s32 result[NCOEFF], tresh, treshl;
+       int lowgroup, highgroup;
+       s64 cos2pik_;
+
+       dsp->dtmf.digits[0] = '\0';
+
+       /* Note: The function will loop until the buffer has not enough samples
+        * left to decode a full frame.
+        */
+again:
+       /* convert samples */
+       size = dsp->dtmf.size;
+       buf = dsp->dtmf.buffer;
+       switch (fmt) {
+       case 0: /* alaw */
+       case 1: /* ulaw */
+               while (size < DSP_DTMF_NPOINTS && len) {
+                       buf[size++] = dsp_audio_law_to_s32[*data++];
+                       len--;
+               }
+               break;
+
+       case 2: /* HFC coefficients */
+       default:
+               if (len < 64) {
+                       if (len > 0)
+                               printk(KERN_ERR "%s: coefficients have invalid "
+                                       "size. (is=%d < must=%d)\n",
+                                       __func__, len, 64);
+                       return dsp->dtmf.digits;
+               }
+               hfccoeff = (s32 *)data;
+               for (k = 0; k < NCOEFF; k++) {
+                       sk2 = (*hfccoeff++)>>4;
+                       sk = (*hfccoeff++)>>4;
+                       if (sk > 32767 || sk < -32767 || sk2 > 32767
+                           || sk2 < -32767)
+                               printk(KERN_WARNING
+                                       "DTMF-Detection overflow\n");
+                       /* compute |X(k)|**2 */
+                       result[k] =
+                                (sk * sk) -
+                                (((cos2pik[k] * sk) >> 15) * sk2) +
+                                (sk2 * sk2);
+               }
+               data += 64;
+               len -= 64;
+               goto coefficients;
+               break;
+       }
+       dsp->dtmf.size = size;
+
+       if (size < DSP_DTMF_NPOINTS)
+               return dsp->dtmf.digits;
+
+       dsp->dtmf.size = 0;
+
+       /* now we have a full buffer of signed long samples - we do goertzel */
+       for (k = 0; k < NCOEFF; k++) {
+               sk = 0;
+               sk1 = 0;
+               sk2 = 0;
+               buf = dsp->dtmf.buffer;
+               cos2pik_ = cos2pik[k];
+               for (n = 0; n < DSP_DTMF_NPOINTS; n++) {
+                       sk = ((cos2pik_*sk1)>>15) - sk2 + (*buf++);
+                       sk2 = sk1;
+                       sk1 = sk;
+               }
+               sk >>= 8;
+               sk2 >>= 8;
+               if (sk > 32767 || sk < -32767 || sk2 > 32767 || sk2 < -32767)
+                       printk(KERN_WARNING "DTMF-Detection overflow\n");
+               /* compute |X(k)|**2 */
+               result[k] =
+                       (sk * sk) -
+                       (((cos2pik[k] * sk) >> 15) * sk2) +
+                       (sk2 * sk2);
+       }
+
+       /* our (squared) coefficients have been calculated, we need to process
+        * them.
+        */
+coefficients:
+       tresh = 0;
+       for (i = 0; i < NCOEFF; i++) {
+               if (result[i] < 0)
+                       result[i] = 0;
+               if (result[i] > dsp->dtmf.treshold) {
+                       if (result[i] > tresh)
+                               tresh = result[i];
+               }
+       }
+
+       if (tresh == 0) {
+               what = 0;
+               goto storedigit;
+       }
+
+       if (dsp_debug & DEBUG_DSP_DTMFCOEFF)
+               printk(KERN_DEBUG "a %3d %3d %3d %3d %3d %3d %3d %3d"
+                       " tr:%3d r %3d %3d %3d %3d %3d %3d %3d %3d\n",
+                       result[0]/10000, result[1]/10000, result[2]/10000,
+                       result[3]/10000, result[4]/10000, result[5]/10000,
+                       result[6]/10000, result[7]/10000, tresh/10000,
+                       result[0]/(tresh/100), result[1]/(tresh/100),
+                       result[2]/(tresh/100), result[3]/(tresh/100),
+                       result[4]/(tresh/100), result[5]/(tresh/100),
+                       result[6]/(tresh/100), result[7]/(tresh/100));
+
+       /* calc digit (lowgroup/highgroup) */
+       lowgroup = -1;
+       highgroup = -1;
+       treshl = tresh >> 3;  /* tones which are not on, must be below 9 dB */
+       tresh = tresh >> 2;  /* touchtones must match within 6 dB */
+       for (i = 0; i < NCOEFF; i++) {
+               if (result[i] < treshl)
+                       continue;  /* ignore */
+               if (result[i] < tresh) {
+                       lowgroup = -1;
+                       highgroup = -1;
+                       break;  /* noise inbetween */
+               }
+               /* good level found. This is allowed only one time per group */
+               if (i < NCOEFF/2) {
+                       /* lowgroup */
+                       if (lowgroup >= 0) {
+                               /* Bad. Another tone found. */
+                               lowgroup = -1;
+                               break;
+                       } else
+                               lowgroup = i;
+               } else {
+                       /* higroup */
+                       if (highgroup >= 0) {
+                               /* Bad. Another tone found. */
+                               highgroup = -1;
+                               break;
+                       } else
+                               highgroup = i-(NCOEFF/2);
+               }
+       }
+
+       /* get digit or null */
+       what = 0;
+       if (lowgroup >= 0 && highgroup >= 0)
+               what = dtmf_matrix[lowgroup][highgroup];
+
+storedigit:
+       if (what && (dsp_debug & DEBUG_DSP_DTMF))
+               printk(KERN_DEBUG "DTMF what: %c\n", what);
+
+       if (dsp->dtmf.lastwhat != what)
+               dsp->dtmf.count = 0;
+
+       /* the tone (or no tone) must remain 3 times without change */
+       if (dsp->dtmf.count == 2) {
+               if (dsp->dtmf.lastdigit != what) {
+                       dsp->dtmf.lastdigit = what;
+                       if (what) {
+                               if (dsp_debug & DEBUG_DSP_DTMF)
+                                       printk(KERN_DEBUG "DTMF digit: %c\n",
+                                               what);
+                               if ((strlen(dsp->dtmf.digits)+1)
+                                       < sizeof(dsp->dtmf.digits)) {
+                                       dsp->dtmf.digits[strlen(
+                                               dsp->dtmf.digits)+1] = '\0';
+                                       dsp->dtmf.digits[strlen(
+                                               dsp->dtmf.digits)] = what;
+                               }
+                       }
+               }
+       } else
+               dsp->dtmf.count++;
+
+       dsp->dtmf.lastwhat = what;
+
+       goto again;
+}
+
+
diff --git a/drivers/isdn/mISDN/dsp_ecdis.h b/drivers/isdn/mISDN/dsp_ecdis.h
new file mode 100644 (file)
index 0000000..8a20af4
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * ec_disable_detector.h - A detector which should eventually meet the
+ *                         G.164/G.165 requirements for detecting the
+ *                         2100Hz echo cancellor disable tone.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2001 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "dsp_biquad.h"
+
+struct ec_disable_detector_state {
+       struct biquad2_state notch;
+       int notch_level;
+       int channel_level;
+       int tone_present;
+       int tone_cycle_duration;
+       int good_cycles;
+       int hit;
+};
+
+
+#define FALSE 0
+#define TRUE (!FALSE)
+
+static inline void
+echo_can_disable_detector_init(struct ec_disable_detector_state *det)
+{
+    /* Elliptic notch */
+    /* This is actually centred at 2095Hz, but gets the balance we want, due
+       to the asymmetric walls of the notch */
+       biquad2_init(&det->notch,
+               (int32_t) (-0.7600000*32768.0),
+               (int32_t) (-0.1183852*32768.0),
+               (int32_t) (-0.5104039*32768.0),
+               (int32_t) (0.1567596*32768.0),
+               (int32_t) (1.0000000*32768.0));
+
+       det->channel_level = 0;
+       det->notch_level = 0;
+       det->tone_present = FALSE;
+       det->tone_cycle_duration = 0;
+       det->good_cycles = 0;
+       det->hit = 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static inline int
+echo_can_disable_detector_update(struct ec_disable_detector_state *det,
+int16_t amp)
+{
+       int16_t notched;
+
+       notched = biquad2(&det->notch, amp);
+       /* Estimate the overall energy in the channel, and the energy in
+          the notch (i.e. overall channel energy - tone energy => noise).
+          Use abs instead of multiply for speed (is it really faster?).
+          Damp the overall energy a little more for a stable result.
+          Damp the notch energy a little less, so we don't damp out the
+          blip every time the phase reverses */
+       det->channel_level += ((abs(amp) - det->channel_level) >> 5);
+       det->notch_level += ((abs(notched) - det->notch_level) >> 4);
+       if (det->channel_level > 280) {
+               /* There is adequate energy in the channel.
+                Is it mostly at 2100Hz? */
+               if (det->notch_level*6 < det->channel_level) {
+                       /* The notch says yes, so we have the tone. */
+                       if (!det->tone_present) {
+                               /* Do we get a kick every 450+-25ms? */
+                               if (det->tone_cycle_duration >= 425*8
+                                       && det->tone_cycle_duration <= 475*8) {
+                                       det->good_cycles++;
+                                       if (det->good_cycles > 2)
+                                       det->hit = TRUE;
+                               }
+                               det->tone_cycle_duration = 0;
+                       }
+                       det->tone_present = TRUE;
+               } else
+                       det->tone_present = FALSE;
+               det->tone_cycle_duration++;
+       } else {
+               det->tone_present = FALSE;
+               det->tone_cycle_duration = 0;
+               det->good_cycles = 0;
+       }
+       return det->hit;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
diff --git a/drivers/isdn/mISDN/dsp_hwec.c b/drivers/isdn/mISDN/dsp_hwec.c
new file mode 100644 (file)
index 0000000..eb892d9
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * dsp_hwec.c:
+ * builtin mISDN dsp pipeline element for enabling the hw echocanceller
+ *
+ * Copyright (C) 2007, Nadi Sarrar
+ *
+ * Nadi Sarrar <nadi@beronet.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.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mISDNdsp.h>
+#include <linux/mISDNif.h>
+#include "core.h"
+#include "dsp.h"
+#include "dsp_hwec.h"
+
+static struct mISDN_dsp_element_arg args[] = {
+       { "deftaps", "128", "Set the number of taps of cancellation." },
+};
+
+static struct mISDN_dsp_element dsp_hwec_p = {
+       .name = "hwec",
+       .new = NULL,
+       .free = NULL,
+       .process_tx = NULL,
+       .process_rx = NULL,
+       .num_args = sizeof(args) / sizeof(struct mISDN_dsp_element_arg),
+       .args = args,
+};
+struct mISDN_dsp_element *dsp_hwec = &dsp_hwec_p;
+
+void dsp_hwec_enable(struct dsp *dsp, const char *arg)
+{
+       int deftaps = 128,
+               len;
+       struct mISDN_ctrl_req   cq;
+
+       if (!dsp) {
+               printk(KERN_ERR "%s: failed to enable hwec: dsp is NULL\n",
+                       __func__);
+               return;
+       }
+
+       if (!arg)
+               goto _do;
+
+       len = strlen(arg);
+       if (!len)
+               goto _do;
+
+       {
+               char _dup[len + 1];
+               char *dup, *tok, *name, *val;
+               int tmp;
+
+               strcpy(_dup, arg);
+               dup = _dup;
+
+               while ((tok = strsep(&dup, ","))) {
+                       if (!strlen(tok))
+                               continue;
+                       name = strsep(&tok, "=");
+                       val = tok;
+
+                       if (!val)
+                               continue;
+
+                       if (!strcmp(name, "deftaps")) {
+                               if (sscanf(val, "%d", &tmp) == 1)
+                                       deftaps = tmp;
+                       }
+               }
+       }
+
+_do:
+       printk(KERN_DEBUG "%s: enabling hwec with deftaps=%d\n",
+               __func__, deftaps);
+       memset(&cq, 0, sizeof(cq));
+       cq.op = MISDN_CTRL_HFC_ECHOCAN_ON;
+       cq.p1 = deftaps;
+       if (!dsp->ch.peer->ctrl(&dsp->ch, CONTROL_CHANNEL, &cq)) {
+               printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
+                       __func__);
+               return;
+       }
+}
+
+void dsp_hwec_disable(struct dsp *dsp)
+{
+       struct mISDN_ctrl_req   cq;
+
+       if (!dsp) {
+               printk(KERN_ERR "%s: failed to disable hwec: dsp is NULL\n",
+                       __func__);
+               return;
+       }
+
+       printk(KERN_DEBUG "%s: disabling hwec\n", __func__);
+       memset(&cq, 0, sizeof(cq));
+       cq.op = MISDN_CTRL_HFC_ECHOCAN_OFF;
+       if (!dsp->ch.peer->ctrl(&dsp->ch, CONTROL_CHANNEL, &cq)) {
+               printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
+                       __func__);
+               return;
+       }
+}
+
+int dsp_hwec_init(void)
+{
+       mISDN_dsp_element_register(dsp_hwec);
+
+       return 0;
+}
+
+void dsp_hwec_exit(void)
+{
+       mISDN_dsp_element_unregister(dsp_hwec);
+}
+
diff --git a/drivers/isdn/mISDN/dsp_hwec.h b/drivers/isdn/mISDN/dsp_hwec.h
new file mode 100644 (file)
index 0000000..eebe80c
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * dsp_hwec.h
+ */
+
+extern struct mISDN_dsp_element *dsp_hwec;
+extern void dsp_hwec_enable(struct dsp *dsp, const char *arg);
+extern void dsp_hwec_disable(struct dsp *dsp);
+extern int  dsp_hwec_init(void);
+extern void dsp_hwec_exit(void);
+
diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c
new file mode 100644 (file)
index 0000000..850260a
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * dsp_pipeline.c: pipelined audio processing
+ *
+ * Copyright (C) 2007, Nadi Sarrar
+ *
+ * Nadi Sarrar <nadi@beronet.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.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/mISDNif.h>
+#include <linux/mISDNdsp.h>
+#include "dsp.h"
+#include "dsp_hwec.h"
+
+/* uncomment for debugging */
+/*#define PIPELINE_DEBUG*/
+
+struct dsp_pipeline_entry {
+       struct mISDN_dsp_element *elem;
+       void                *p;
+       struct list_head     list;
+};
+struct dsp_element_entry {
+       struct mISDN_dsp_element *elem;
+       struct device        dev;
+       struct list_head     list;
+};
+
+static LIST_HEAD(dsp_elements);
+
+/* sysfs */
+static struct class *elements_class;
+
+static ssize_t
+attr_show_args(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct mISDN_dsp_element *elem = dev_get_drvdata(dev);
+       ssize_t len = 0;
+       int i = 0;
+
+       *buf = 0;
+       for (; i < elem->num_args; ++i)
+               len = sprintf(buf, "%sName:        %s\n%s%s%sDescription: %s\n"
+                       "\n", buf,
+                         elem->args[i].name,
+                         elem->args[i].def ? "Default:     " : "",
+                         elem->args[i].def ? elem->args[i].def : "",
+                         elem->args[i].def ? "\n" : "",
+                         elem->args[i].desc);
+
+       return len;
+}
+
+static struct device_attribute element_attributes[] = {
+       __ATTR(args, 0444, attr_show_args, NULL),
+};
+
+int mISDN_dsp_element_register(struct mISDN_dsp_element *elem)
+{
+       struct dsp_element_entry *entry;
+       int ret, i;
+
+       if (!elem)
+               return -EINVAL;
+
+       entry = kzalloc(sizeof(struct dsp_element_entry), GFP_KERNEL);
+       if (!entry)
+               return -ENOMEM;
+
+       entry->elem = elem;
+
+       entry->dev.class = elements_class;
+       dev_set_drvdata(&entry->dev, elem);
+       snprintf(entry->dev.bus_id, BUS_ID_SIZE, elem->name);
+       ret = device_register(&entry->dev);
+       if (ret) {
+               printk(KERN_ERR "%s: failed to register %s\n",
+                       __func__, elem->name);
+               goto err1;
+       }
+
+       for (i = 0; i < (sizeof(element_attributes)
+               / sizeof(struct device_attribute)); ++i)
+               ret = device_create_file(&entry->dev,
+                               &element_attributes[i]);
+               if (ret) {
+                       printk(KERN_ERR "%s: failed to create device file\n",
+                               __func__);
+                       goto err2;
+               }
+
+       list_add_tail(&entry->list, &dsp_elements);
+
+       printk(KERN_DEBUG "%s: %s registered\n", __func__, elem->name);
+
+       return 0;
+
+err2:
+       device_unregister(&entry->dev);
+err1:
+       kfree(entry);
+       return ret;
+}
+EXPORT_SYMBOL(mISDN_dsp_element_register);
+
+void mISDN_dsp_element_unregister(struct mISDN_dsp_element *elem)
+{
+       struct dsp_element_entry *entry, *n;
+
+       if (!elem)
+               return;
+
+       list_for_each_entry_safe(entry, n, &dsp_elements, list)
+               if (entry->elem == elem) {
+                       list_del(&entry->list);
+                       device_unregister(&entry->dev);
+                       kfree(entry);
+                       printk(KERN_DEBUG "%s: %s unregistered\n",
+                               __func__, elem->name);
+                       return;
+               }
+       printk(KERN_ERR "%s: element %s not in list.\n", __func__, elem->name);
+}
+EXPORT_SYMBOL(mISDN_dsp_element_unregister);
+
+int dsp_pipeline_module_init(void)
+{
+       elements_class = class_create(THIS_MODULE, "dsp_pipeline");
+       if (IS_ERR(elements_class))
+               return PTR_ERR(elements_class);
+
+#ifdef PIPELINE_DEBUG
+       printk(KERN_DEBUG "%s: dsp pipeline module initialized\n", __func__);
+#endif
+
+       dsp_hwec_init();
+
+       return 0;
+}
+
+void dsp_pipeline_module_exit(void)
+{
+       struct dsp_element_entry *entry, *n;
+
+       dsp_hwec_exit();
+
+       class_destroy(elements_class);
+
+       list_for_each_entry_safe(entry, n, &dsp_elements, list) {
+               list_del(&entry->list);
+               printk(KERN_WARNING "%s: element was still registered: %s\n",
+                       __func__, entry->elem->name);
+               kfree(entry);
+       }
+
+       printk(KERN_DEBUG "%s: dsp pipeline module exited\n", __func__);
+}
+
+int dsp_pipeline_init(struct dsp_pipeline *pipeline)
+{
+       if (!pipeline)
+               return -EINVAL;
+
+       INIT_LIST_HEAD(&pipeline->list);
+
+#ifdef PIPELINE_DEBUG
+       printk(KERN_DEBUG "%s: dsp pipeline ready\n", __func__);
+#endif
+
+       return 0;
+}
+
+static inline void _dsp_pipeline_destroy(struct dsp_pipeline *pipeline)
+{
+       struct dsp_pipeline_entry *entry, *n;
+
+       list_for_each_entry_safe(entry, n, &pipeline->list, list) {
+               list_del(&entry->list);
+               if (entry->elem == dsp_hwec)
+                       dsp_hwec_disable(container_of(pipeline, struct dsp,
+                               pipeline));
+               else
+                       entry->elem->free(entry->p);
+               kfree(entry);
+       }
+}
+
+void dsp_pipeline_destroy(struct dsp_pipeline *pipeline)
+{
+
+       if (!pipeline)
+               return;
+
+       _dsp_pipeline_destroy(pipeline);
+
+#ifdef PIPELINE_DEBUG
+       printk(KERN_DEBUG "%s: dsp pipeline destroyed\n", __func__);
+#endif
+}
+
+int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
+{
+       int len, incomplete = 0, found = 0;
+       char *dup, *tok, *name, *args;
+       struct dsp_element_entry *entry, *n;
+       struct dsp_pipeline_entry *pipeline_entry;
+       struct mISDN_dsp_element *elem;
+
+       if (!pipeline)
+               return -EINVAL;
+
+       if (!list_empty(&pipeline->list))
+               _dsp_pipeline_destroy(pipeline);
+
+       if (!cfg)
+               return 0;
+
+       len = strlen(cfg);
+       if (!len)
+               return 0;
+
+       dup = kmalloc(len + 1, GFP_KERNEL);
+       if (!dup)
+               return 0;
+       strcpy(dup, cfg);
+       while ((tok = strsep(&dup, "|"))) {
+               if (!strlen(tok))
+                       continue;
+               name = strsep(&tok, "(");
+               args = strsep(&tok, ")");
+               if (args && !*args)
+                       args = 0;
+
+               list_for_each_entry_safe(entry, n, &dsp_elements, list)
+                       if (!strcmp(entry->elem->name, name)) {
+                               elem = entry->elem;
+
+                               pipeline_entry = kmalloc(sizeof(struct
+                                       dsp_pipeline_entry), GFP_KERNEL);
+                               if (!pipeline_entry) {
+                                       printk(KERN_DEBUG "%s: failed to add "
+                                           "entry to pipeline: %s (out of "
+                                           "memory)\n", __func__, elem->name);
+                                       incomplete = 1;
+                                       goto _out;
+                               }
+                               pipeline_entry->elem = elem;
+
+                               if (elem == dsp_hwec) {
+                                       /* This is a hack to make the hwec
+                                          available as a pipeline module */
+                                       dsp_hwec_enable(container_of(pipeline,
+                                               struct dsp, pipeline), args);
+                                       list_add_tail(&pipeline_entry->list,
+                                               &pipeline->list);
+                               } else {
+                                       pipeline_entry->p = elem->new(args);
+                                       if (pipeline_entry->p) {
+                                               list_add_tail(&pipeline_entry->
+                                                       list, &pipeline->list);
+#ifdef PIPELINE_DEBUG
+                                               printk(KERN_DEBUG "%s: created "
+                                                   "instance of %s%s%s\n",
+                                                   __func__, name, args ?
+                                                   " with args " : "", args ?
+                                                   args : "");
+#endif
+                                       } else {
+                                               printk(KERN_DEBUG "%s: failed "
+                                                 "to add entry to pipeline: "
+                                                 "%s (new() returned NULL)\n",
+                                                 __func__, elem->name);
+                                               kfree(pipeline_entry);
+                                               incomplete = 1;
+                                       }
+                               }
+                               found = 1;
+                               break;
+                       }
+
+               if (found)
+                       found = 0;
+               else {
+                       printk(KERN_DEBUG "%s: element not found, skipping: "
+                               "%s\n", __func__, name);
+                       incomplete = 1;
+               }
+       }
+
+_out:
+       if (!list_empty(&pipeline->list))
+               pipeline->inuse = 1;
+       else
+               pipeline->inuse = 0;
+
+#ifdef PIPELINE_DEBUG
+       printk(KERN_DEBUG "%s: dsp pipeline built%s: %s\n",
+               __func__, incomplete ? " incomplete" : "", cfg);
+#endif
+       kfree(dup);
+       return 0;
+}
+
+void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, int len)
+{
+       struct dsp_pipeline_entry *entry;
+
+       if (!pipeline)
+               return;
+
+       list_for_each_entry(entry, &pipeline->list, list)
+               if (entry->elem->process_tx)
+                       entry->elem->process_tx(entry->p, data, len);
+}
+
+void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len)
+{
+       struct dsp_pipeline_entry *entry;
+
+       if (!pipeline)
+               return;
+
+       list_for_each_entry_reverse(entry, &pipeline->list, list)
+               if (entry->elem->process_rx)
+                       entry->elem->process_rx(entry->p, data, len);
+}
+
+
diff --git a/drivers/isdn/mISDN/dsp_tones.c b/drivers/isdn/mISDN/dsp_tones.c
new file mode 100644 (file)
index 0000000..23dd0dd
--- /dev/null
@@ -0,0 +1,551 @@
+/*
+ * Audio support data for ISDN4Linux.
+ *
+ * Copyright Andreas Eversberg (jolly@eversberg.eu)
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ */
+
+#include <linux/mISDNif.h>
+#include <linux/mISDNdsp.h>
+#include "core.h"
+#include "dsp.h"
+
+
+#define DATA_S sample_silence
+#define SIZE_S (&sizeof_silence)
+#define DATA_GA sample_german_all
+#define SIZE_GA (&sizeof_german_all)
+#define DATA_GO sample_german_old
+#define SIZE_GO (&sizeof_german_old)
+#define DATA_DT sample_american_dialtone
+#define SIZE_DT (&sizeof_american_dialtone)
+#define DATA_RI sample_american_ringing
+#define SIZE_RI (&sizeof_american_ringing)
+#define DATA_BU sample_american_busy
+#define SIZE_BU (&sizeof_american_busy)
+#define DATA_S1 sample_special1
+#define SIZE_S1 (&sizeof_special1)
+#define DATA_S2 sample_special2
+#define SIZE_S2 (&sizeof_special2)
+#define DATA_S3 sample_special3
+#define SIZE_S3 (&sizeof_special3)
+
+/***************/
+/* tones loops */
+/***************/
+
+/* all tones are alaw encoded */
+/* the last sample+1 is in phase with the first sample. the error is low */
+
+static u8 sample_german_all[] = {
+       0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
+       0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
+       0xdc, 0xfc, 0x6c,
+       0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
+       0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
+       0xdc, 0xfc, 0x6c,
+       0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
+       0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
+       0xdc, 0xfc, 0x6c,
+       0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
+       0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
+       0xdc, 0xfc, 0x6c,
+};
+static u32 sizeof_german_all = sizeof(sample_german_all);
+
+static u8 sample_german_old[] = {
+       0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
+       0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
+       0x8c,
+       0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
+       0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
+       0x8c,
+       0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
+       0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
+       0x8c,
+       0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
+       0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
+       0x8c,
+};
+static u32 sizeof_german_old = sizeof(sample_german_old);
+
+static u8 sample_american_dialtone[] = {
+       0x2a, 0x18, 0x90, 0x6c, 0x4c, 0xbc, 0x4c, 0x6c,
+       0x10, 0x58, 0x32, 0xb9, 0x31, 0x2d, 0x8d, 0x0d,
+       0x8d, 0x2d, 0x31, 0x99, 0x0f, 0x28, 0x60, 0xf0,
+       0xd0, 0x50, 0xd0, 0x30, 0x60, 0x08, 0x8e, 0x67,
+       0x09, 0x19, 0x21, 0xe1, 0xd9, 0xb9, 0x29, 0x67,
+       0x83, 0x02, 0xce, 0xbe, 0xee, 0x1a, 0x1b, 0xef,
+       0xbf, 0xcf, 0x03, 0x82, 0x66, 0x28, 0xb8, 0xd8,
+       0xe0, 0x20, 0x18, 0x08, 0x66, 0x8f, 0x09, 0x61,
+       0x31, 0xd1, 0x51, 0xd1, 0xf1, 0x61, 0x29, 0x0e,
+       0x98, 0x30, 0x2c, 0x8c, 0x0c, 0x8c, 0x2c, 0x30,
+       0xb8, 0x33, 0x59, 0x11, 0x6d, 0x4d, 0xbd, 0x4d,
+       0x6d, 0x91, 0x19,
+};
+static u32 sizeof_american_dialtone = sizeof(sample_american_dialtone);
+
+static u8 sample_american_ringing[] = {
+       0x2a, 0xe0, 0xac, 0x0c, 0xbc, 0x4c, 0x8c, 0x90,
+       0x48, 0xc7, 0xc1, 0xed, 0xcd, 0x4d, 0xcd, 0xed,
+       0xc1, 0xb7, 0x08, 0x30, 0xec, 0xcc, 0xcc, 0x8c,
+       0x10, 0x58, 0x1a, 0x99, 0x71, 0xed, 0x8d, 0x8d,
+       0x2d, 0x41, 0x89, 0x9e, 0x20, 0x70, 0x2c, 0xec,
+       0x2c, 0x70, 0x20, 0x86, 0x77, 0xe1, 0x31, 0x11,
+       0xd1, 0xf1, 0x81, 0x09, 0xa3, 0x56, 0x58, 0x00,
+       0x40, 0xc0, 0x60, 0x38, 0x46, 0x43, 0x57, 0x39,
+       0xd9, 0x59, 0x99, 0xc9, 0x77, 0x2f, 0x2e, 0xc6,
+       0xd6, 0x28, 0xd6, 0x36, 0x26, 0x2e, 0x8a, 0xa3,
+       0x43, 0x63, 0x4b, 0x4a, 0x62, 0x42, 0xa2, 0x8b,
+       0x2f, 0x27, 0x37, 0xd7, 0x29, 0xd7, 0xc7, 0x2f,
+       0x2e, 0x76, 0xc8, 0x98, 0x58, 0xd8, 0x38, 0x56,
+       0x42, 0x47, 0x39, 0x61, 0xc1, 0x41, 0x01, 0x59,
+       0x57, 0xa2, 0x08, 0x80, 0xf0, 0xd0, 0x10, 0x30,
+       0xe0, 0x76, 0x87, 0x21, 0x71, 0x2d, 0xed, 0x2d,
+       0x71, 0x21, 0x9f, 0x88, 0x40, 0x2c, 0x8c, 0x8c,
+       0xec, 0x70, 0x98, 0x1b, 0x59, 0x11, 0x8d, 0xcd,
+       0xcd, 0xed, 0x31, 0x09, 0xb6, 0xc0, 0xec, 0xcc,
+       0x4c, 0xcc, 0xec, 0xc0, 0xc6, 0x49, 0x91, 0x8d,
+       0x4d, 0xbd, 0x0d, 0xad, 0xe1,
+};
+static u32 sizeof_american_ringing = sizeof(sample_american_ringing);
+
+static u8 sample_american_busy[] = {
+       0x2a, 0x00, 0x6c, 0x4c, 0x4c, 0x6c, 0xb0, 0x66,
+       0x99, 0x11, 0x6d, 0x8d, 0x2d, 0x41, 0xd7, 0x96,
+       0x60, 0xf0, 0x70, 0x40, 0x58, 0xf6, 0x53, 0x57,
+       0x09, 0x89, 0xd7, 0x5f, 0xe3, 0x2a, 0xe3, 0x5f,
+       0xd7, 0x89, 0x09, 0x57, 0x53, 0xf6, 0x58, 0x40,
+       0x70, 0xf0, 0x60, 0x96, 0xd7, 0x41, 0x2d, 0x8d,
+       0x6d, 0x11, 0x99, 0x66, 0xb0, 0x6c, 0x4c, 0x4c,
+       0x6c, 0x00, 0x2a, 0x01, 0x6d, 0x4d, 0x4d, 0x6d,
+       0xb1, 0x67, 0x98, 0x10, 0x6c, 0x8c, 0x2c, 0x40,
+       0xd6, 0x97, 0x61, 0xf1, 0x71, 0x41, 0x59, 0xf7,
+       0x52, 0x56, 0x08, 0x88, 0xd6, 0x5e, 0xe2, 0x2a,
+       0xe2, 0x5e, 0xd6, 0x88, 0x08, 0x56, 0x52, 0xf7,
+       0x59, 0x41, 0x71, 0xf1, 0x61, 0x97, 0xd6, 0x40,
+       0x2c, 0x8c, 0x6c, 0x10, 0x98, 0x67, 0xb1, 0x6d,
+       0x4d, 0x4d, 0x6d, 0x01,
+};
+static u32 sizeof_american_busy = sizeof(sample_american_busy);
+
+static u8 sample_special1[] = {
+       0x2a, 0x2c, 0xbc, 0x6c, 0xd6, 0x71, 0xbd, 0x0d,
+       0xd9, 0x80, 0xcc, 0x4c, 0x40, 0x39, 0x0d, 0xbd,
+       0x11, 0x86, 0xec, 0xbc, 0xec, 0x0e, 0x51, 0xbd,
+       0x8d, 0x89, 0x30, 0x4c, 0xcc, 0xe0, 0xe1, 0xcd,
+       0x4d, 0x31, 0x88, 0x8c, 0xbc, 0x50, 0x0f, 0xed,
+       0xbd, 0xed, 0x87, 0x10, 0xbc, 0x0c, 0x38, 0x41,
+       0x4d, 0xcd, 0x81, 0xd8, 0x0c, 0xbc, 0x70, 0xd7,
+       0x6d, 0xbd, 0x2d,
+};
+static u32 sizeof_special1 = sizeof(sample_special1);
+
+static u8 sample_special2[] = {
+       0x2a, 0xcc, 0x8c, 0xd7, 0x4d, 0x2d, 0x18, 0xbc,
+       0x10, 0xc1, 0xbd, 0xc1, 0x10, 0xbc, 0x18, 0x2d,
+       0x4d, 0xd7, 0x8c, 0xcc, 0x2a, 0xcd, 0x8d, 0xd6,
+       0x4c, 0x2c, 0x19, 0xbd, 0x11, 0xc0, 0xbc, 0xc0,
+       0x11, 0xbd, 0x19, 0x2c, 0x4c, 0xd6, 0x8d, 0xcd,
+       0x2a, 0xcc, 0x8c, 0xd7, 0x4d, 0x2d, 0x18, 0xbc,
+       0x10, 0xc1, 0xbd, 0xc1, 0x10, 0xbc, 0x18, 0x2d,
+       0x4d, 0xd7, 0x8c, 0xcc, 0x2a, 0xcd, 0x8d, 0xd6,
+       0x4c, 0x2c, 0x19, 0xbd, 0x11, 0xc0, 0xbc, 0xc0,
+       0x11, 0xbd, 0x19, 0x2c, 0x4c, 0xd6, 0x8d, 0xcd,
+};
+static u32 sizeof_special2 = sizeof(sample_special2);
+
+static u8 sample_special3[] = {
+       0x2a, 0xbc, 0x18, 0xcd, 0x11, 0x2c, 0x8c, 0xc1,
+       0x4d, 0xd6, 0xbc, 0xd6, 0x4d, 0xc1, 0x8c, 0x2c,
+       0x11, 0xcd, 0x18, 0xbc, 0x2a, 0xbd, 0x19, 0xcc,
+       0x10, 0x2d, 0x8d, 0xc0, 0x4c, 0xd7, 0xbd, 0xd7,
+       0x4c, 0xc0, 0x8d, 0x2d, 0x10, 0xcc, 0x19, 0xbd,
+       0x2a, 0xbc, 0x18, 0xcd, 0x11, 0x2c, 0x8c, 0xc1,
+       0x4d, 0xd6, 0xbc, 0xd6, 0x4d, 0xc1, 0x8c, 0x2c,
+       0x11, 0xcd, 0x18, 0xbc, 0x2a, 0xbd, 0x19, 0xcc,
+       0x10, 0x2d, 0x8d, 0xc0, 0x4c, 0xd7, 0xbd, 0xd7,
+       0x4c, 0xc0, 0x8d, 0x2d, 0x10, 0xcc, 0x19, 0xbd,
+};
+static u32 sizeof_special3 = sizeof(sample_special3);
+
+static u8 sample_silence[] = {
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+       0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
+};
+static u32 sizeof_silence = sizeof(sample_silence);
+
+struct tones_samples {
+       u32 *len;
+       u8 *data;
+};
+static struct
+tones_samples samples[] = {
+       {&sizeof_german_all, sample_german_all},
+       {&sizeof_german_old, sample_german_old},
+       {&sizeof_american_dialtone, sample_american_dialtone},
+       {&sizeof_american_ringing, sample_american_ringing},
+       {&sizeof_american_busy, sample_american_busy},
+       {&sizeof_special1, sample_special1},
+       {&sizeof_special2, sample_special2},
+       {&sizeof_special3, sample_special3},
+       {NULL, NULL},
+};
+
+/***********************************
+ * generate ulaw from alaw samples *
+ ***********************************/
+
+void
+dsp_audio_generate_ulaw_samples(void)
+{
+       int i, j;
+
+       i = 0;
+       while (samples[i].len) {
+               j = 0;
+               while (j < (*samples[i].len)) {
+                       samples[i].data[j] =
+                               dsp_audio_alaw_to_ulaw[samples[i].data[j]];
+                       j++;
+               }
+               i++;
+       }
+}
+
+
+/****************************
+ * tone sequence definition *
+ ****************************/
+
+struct pattern {
+       int tone;
+       u8 *data[10];
+       u32 *siz[10];
+       u32 seq[10];
+} pattern[] = {
+       {TONE_GERMAN_DIALTONE,
+       {DATA_GA, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_GA, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {1900, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_OLDDIALTONE,
+       {DATA_GO, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_GO, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {1998, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_AMERICAN_DIALTONE,
+       {DATA_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_DIALPBX,
+       {DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, 0, 0, 0, 0},
+       {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, 0, 0, 0, 0},
+       {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_OLDDIALPBX,
+       {DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, 0, 0, 0, 0},
+       {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0},
+       {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
+
+       {TONE_AMERICAN_DIALPBX,
+       {DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, 0, 0, 0, 0},
+       {SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, 0, 0, 0, 0},
+       {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_RINGING,
+       {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_OLDRINGING,
+       {DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {8000, 40000, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_AMERICAN_RINGING,
+       {DATA_RI, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_RI, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_RINGPBX,
+       {DATA_GA, DATA_S, DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0},
+       {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0},
+       {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_OLDRINGPBX,
+       {DATA_GO, DATA_S, DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0},
+       {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0},
+       {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_AMERICAN_RINGPBX,
+       {DATA_RI, DATA_S, DATA_RI, DATA_S, 0, 0, 0, 0, 0, 0},
+       {SIZE_RI, SIZE_S, SIZE_RI, SIZE_S, 0, 0, 0, 0, 0, 0},
+       {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_BUSY,
+       {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_OLDBUSY,
+       {DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_AMERICAN_BUSY,
+       {DATA_BU, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_BU, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_HANGUP,
+       {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_OLDHANGUP,
+       {DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_AMERICAN_HANGUP,
+       {DATA_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_SPECIAL_INFO,
+       {DATA_S1, DATA_S2, DATA_S3, DATA_S, 0, 0, 0, 0, 0, 0},
+       {SIZE_S1, SIZE_S2, SIZE_S3, SIZE_S, 0, 0, 0, 0, 0, 0},
+       {2666, 2666, 2666, 8002, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_GASSENBESETZT,
+       {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
+       {2000, 2000, 0, 0, 0, 0, 0, 0, 0, 0} },
+
+       {TONE_GERMAN_AUFSCHALTTON,
+       {DATA_GO, DATA_S, DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0},
+       {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0},
+       {1000, 5000, 1000, 17000, 0, 0, 0, 0, 0, 0} },
+
+       {0,
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+/******************
+ * copy tone data *
+ ******************/
+
+/* an sk_buff is generated from the number of samples needed.
+ * the count will be changed and may begin from 0 each pattern period.
+ * the clue is to precalculate the pointers and legths to use only one
+ * memcpy per function call, or two memcpy if the tone sequence changes.
+ *
+ * pattern - the type of the pattern
+ * count - the sample from the beginning of the pattern (phase)
+ * len - the number of bytes
+ *
+ * return - the sk_buff with the sample
+ *
+ * if tones has finished (e.g. knocking tone), dsp->tones is turned off
+ */
+void dsp_tone_copy(struct dsp *dsp, u8 *data, int len)
+{
+       int index, count, start, num;
+       struct pattern *pat;
+       struct dsp_tone *tone = &dsp->tone;
+
+       /* if we have no tone, we copy silence */
+       if (!tone->tone) {
+               memset(data, dsp_silence, len);
+               return;
+       }
+
+       /* process pattern */
+       pat = (struct pattern *)tone->pattern;
+               /* points to the current pattern */
+       index = tone->index; /* gives current sequence index */
+       count = tone->count; /* gives current sample */
+
+       /* copy sample */
+       while (len) {
+               /* find sample to start with */
+               while (42) {
+                       /* warp arround */
+                       if (!pat->seq[index]) {
+                               count = 0;
+                               index = 0;
+                       }
+                       /* check if we are currently playing this tone */
+                       if (count < pat->seq[index])
+                               break;
+                       if (dsp_debug & DEBUG_DSP_TONE)
+                               printk(KERN_DEBUG "%s: reaching next sequence "
+                                       "(index=%d)\n", __func__, index);
+                       count -= pat->seq[index];
+                       index++;
+               }
+               /* calculate start and number of samples */
+               start = count % (*(pat->siz[index]));
+               num = len;
+               if (num+count > pat->seq[index])
+                       num = pat->seq[index] - count;
+               if (num+start > (*(pat->siz[index])))
+                       num = (*(pat->siz[index])) - start;
+               /* copy memory */
+               memcpy(data, pat->data[index]+start, num);
+               /* reduce length */
+               data += num;
+               count += num;
+               len -= num;
+       }
+       tone->index = index;
+       tone->count = count;
+
+       /* return sk_buff */
+       return;
+}
+
+
+/*******************************
+ * send HW message to hfc card *
+ *******************************/
+
+static void
+dsp_tone_hw_message(struct dsp *dsp, u8 *sample, int len)
+{
+       struct sk_buff *nskb;
+
+       /* unlocking is not required, because we don't expect a response */
+       nskb = _alloc_mISDN_skb(PH_CONTROL_REQ,
+               (len)?HFC_SPL_LOOP_ON:HFC_SPL_LOOP_OFF, len, sample,
+               GFP_ATOMIC);
+       if (nskb) {
+               if (dsp->ch.peer) {
+                       if (dsp->ch.recv(dsp->ch.peer, nskb))
+                               dev_kfree_skb(nskb);
+               } else
+                       dev_kfree_skb(nskb);
+       }
+}
+
+
+/*****************
+ * timer expires *
+ *****************/
+void
+dsp_tone_timeout(void *arg)
+{
+       struct dsp *dsp = arg;
+       struct dsp_tone *tone = &dsp->tone;
+       struct pattern *pat = (struct pattern *)tone->pattern;
+       int index = tone->index;
+
+       if (!tone->tone)
+               return;
+
+       index++;
+       if (!pat->seq[index])
+               index = 0;
+       tone->index = index;
+
+       /* set next tone */
+       if (pat->data[index] == DATA_S)
+               dsp_tone_hw_message(dsp, 0, 0);
+       else
+               dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index]));
+       /* set timer */
+       init_timer(&tone->tl);
+       tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000;
+       add_timer(&tone->tl);
+}
+
+
+/********************
+ * set/release tone *
+ ********************/
+
+/*
+ * tones are relaized by streaming or by special loop commands if supported
+ * by hardware. when hardware is used, the patterns will be controlled by
+ * timers.
+ */
+int
+dsp_tone(struct dsp *dsp, int tone)
+{
+       struct pattern *pat;
+       int i;
+       struct dsp_tone *tonet = &dsp->tone;
+
+       tonet->software = 0;
+       tonet->hardware = 0;
+
+       /* we turn off the tone */
+       if (!tone) {
+               if (dsp->features.hfc_loops)
+               if (timer_pending(&tonet->tl))
+                       del_timer(&tonet->tl);
+               if (dsp->features.hfc_loops)
+                       dsp_tone_hw_message(dsp, NULL, 0);
+               tonet->tone = 0;
+               return 0;
+       }
+
+       pat = NULL;
+       i = 0;
+       while (pattern[i].tone) {
+               if (pattern[i].tone == tone) {
+                       pat = &pattern[i];
+                       break;
+               }
+               i++;
+       }
+       if (!pat) {
+               printk(KERN_WARNING "dsp: given tone 0x%x is invalid\n", tone);
+               return -EINVAL;
+       }
+       if (dsp_debug & DEBUG_DSP_TONE)
+               printk(KERN_DEBUG "%s: now starting tone %d (index=%d)\n",
+                       __func__, tone, 0);
+       tonet->tone = tone;
+       tonet->pattern = pat;
+       tonet->index = 0;
+       tonet->count = 0;
+
+       if (dsp->features.hfc_loops) {
+               tonet->hardware = 1;
+               /* set first tone */
+               dsp_tone_hw_message(dsp, pat->data[0], *(pat->siz[0]));
+               /* set timer */
+               if (timer_pending(&tonet->tl))
+                       del_timer(&tonet->tl);
+               init_timer(&tonet->tl);
+               tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000;
+               add_timer(&tonet->tl);
+       } else {
+               tonet->software = 1;
+       }
+
+       return 0;
+}
+
+
+
+
+
diff --git a/drivers/isdn/mISDN/fsm.c b/drivers/isdn/mISDN/fsm.c
new file mode 100644 (file)
index 0000000..b5d6553
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * finite state machine implementation
+ *
+ * Author       Karsten Keil <kkeil@novell.com>
+ *
+ * Thanks to    Jan den Ouden
+ *              Fritz Elfert
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include "fsm.h"
+
+#define FSM_TIMER_DEBUG 0
+
+void
+mISDN_FsmNew(struct Fsm *fsm,
+       struct FsmNode *fnlist, int fncount)
+{
+       int i;
+
+       fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count *
+               fsm->event_count, GFP_KERNEL);
+
+       for (i = 0; i < fncount; i++)
+               if ((fnlist[i].state >= fsm->state_count) ||
+                   (fnlist[i].event >= fsm->event_count)) {
+                       printk(KERN_ERR
+                           "mISDN_FsmNew Error: %d st(%ld/%ld) ev(%ld/%ld)\n",
+                           i, (long)fnlist[i].state, (long)fsm->state_count,
+                           (long)fnlist[i].event, (long)fsm->event_count);
+               } else
+                       fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
+                           fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
+}
+EXPORT_SYMBOL(mISDN_FsmNew);
+
+void
+mISDN_FsmFree(struct Fsm *fsm)
+{
+       kfree((void *) fsm->jumpmatrix);
+}
+EXPORT_SYMBOL(mISDN_FsmFree);
+
+int
+mISDN_FsmEvent(struct FsmInst *fi, int event, void *arg)
+{
+       FSMFNPTR r;
+
+       if ((fi->state >= fi->fsm->state_count) ||
+           (event >= fi->fsm->event_count)) {
+               printk(KERN_ERR
+                   "mISDN_FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
+                   (long)fi->state, (long)fi->fsm->state_count, event,
+                   (long)fi->fsm->event_count);
+               return 1;
+       }
+       r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
+       if (r) {
+               if (fi->debug)
+                       fi->printdebug(fi, "State %s Event %s",
+                               fi->fsm->strState[fi->state],
+                               fi->fsm->strEvent[event]);
+               r(fi, event, arg);
+               return 0;
+       } else {
+               if (fi->debug)
+                       fi->printdebug(fi, "State %s Event %s no action",
+                               fi->fsm->strState[fi->state],
+                               fi->fsm->strEvent[event]);
+               return 1;
+       }
+}
+EXPORT_SYMBOL(mISDN_FsmEvent);
+
+void
+mISDN_FsmChangeState(struct FsmInst *fi, int newstate)
+{
+       fi->state = newstate;
+       if (fi->debug)
+               fi->printdebug(fi, "ChangeState %s",
+                       fi->fsm->strState[newstate]);
+}
+EXPORT_SYMBOL(mISDN_FsmChangeState);
+
+static void
+FsmExpireTimer(struct FsmTimer *ft)
+{
+#if FSM_TIMER_DEBUG
+       if (ft->fi->debug)
+               ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
+#endif
+       mISDN_FsmEvent(ft->fi, ft->event, ft->arg);
+}
+
+void
+mISDN_FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
+{
+       ft->fi = fi;
+       ft->tl.function = (void *) FsmExpireTimer;
+       ft->tl.data = (long) ft;
+#if FSM_TIMER_DEBUG
+       if (ft->fi->debug)
+               ft->fi->printdebug(ft->fi, "mISDN_FsmInitTimer %lx", (long) ft);
+#endif
+       init_timer(&ft->tl);
+}
+EXPORT_SYMBOL(mISDN_FsmInitTimer);
+
+void
+mISDN_FsmDelTimer(struct FsmTimer *ft, int where)
+{
+#if FSM_TIMER_DEBUG
+       if (ft->fi->debug)
+               ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d",
+                       (long) ft, where);
+#endif
+       del_timer(&ft->tl);
+}
+EXPORT_SYMBOL(mISDN_FsmDelTimer);
+
+int
+mISDN_FsmAddTimer(struct FsmTimer *ft,
+           int millisec, int event, void *arg, int where)
+{
+
+#if FSM_TIMER_DEBUG
+       if (ft->fi->debug)
+               ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer %lx %d %d",
+                       (long) ft, millisec, where);
+#endif
+
+       if (timer_pending(&ft->tl)) {
+               if (ft->fi->debug) {
+                       printk(KERN_WARNING
+                               "mISDN_FsmAddTimer: timer already active!\n");
+                       ft->fi->printdebug(ft->fi,
+                               "mISDN_FsmAddTimer already active!");
+               }
+               return -1;
+       }
+       init_timer(&ft->tl);
+       ft->event = event;
+       ft->arg = arg;
+       ft->tl.expires = jiffies + (millisec * HZ) / 1000;
+       add_timer(&ft->tl);
+       return 0;
+}
+EXPORT_SYMBOL(mISDN_FsmAddTimer);
+
+void
+mISDN_FsmRestartTimer(struct FsmTimer *ft,
+           int millisec, int event, void *arg, int where)
+{
+
+#if FSM_TIMER_DEBUG
+       if (ft->fi->debug)
+               ft->fi->printdebug(ft->fi, "mISDN_FsmRestartTimer %lx %d %d",
+                       (long) ft, millisec, where);
+#endif
+
+       if (timer_pending(&ft->tl))
+               del_timer(&ft->tl);
+       init_timer(&ft->tl);
+       ft->event = event;
+       ft->arg = arg;
+       ft->tl.expires = jiffies + (millisec * HZ) / 1000;
+       add_timer(&ft->tl);
+}
+EXPORT_SYMBOL(mISDN_FsmRestartTimer);
diff --git a/drivers/isdn/mISDN/fsm.h b/drivers/isdn/mISDN/fsm.h
new file mode 100644 (file)
index 0000000..928f5be
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *
+ * Author       Karsten Keil <kkeil@novell.com>
+ *
+ * Thanks to    Jan den Ouden
+ *              Fritz Elfert
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MISDN_FSM_H
+#define _MISDN_FSM_H
+
+#include <linux/timer.h>
+
+/* Statemachine */
+
+struct FsmInst;
+
+typedef void (*FSMFNPTR)(struct FsmInst *, int, void *);
+
+struct Fsm {
+       FSMFNPTR *jumpmatrix;
+       int state_count, event_count;
+       char **strEvent, **strState;
+};
+
+struct FsmInst {
+       struct Fsm *fsm;
+       int state;
+       int debug;
+       void *userdata;
+       int userint;
+       void (*printdebug) (struct FsmInst *, char *, ...);
+};
+
+struct FsmNode {
+       int state, event;
+       void (*routine) (struct FsmInst *, int, void *);
+};
+
+struct FsmTimer {
+       struct FsmInst *fi;
+       struct timer_list tl;
+       int event;
+       void *arg;
+};
+
+extern void mISDN_FsmNew(struct Fsm *, struct FsmNode *, int);
+extern void mISDN_FsmFree(struct Fsm *);
+extern int mISDN_FsmEvent(struct FsmInst *, int , void *);
+extern void mISDN_FsmChangeState(struct FsmInst *, int);
+extern void mISDN_FsmInitTimer(struct FsmInst *, struct FsmTimer *);
+extern int mISDN_FsmAddTimer(struct FsmTimer *, int, int, void *, int);
+extern void mISDN_FsmRestartTimer(struct FsmTimer *, int, int, void *, int);
+extern void mISDN_FsmDelTimer(struct FsmTimer *, int);
+
+#endif
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
new file mode 100644 (file)
index 0000000..2596fba
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ *
+ * Author      Karsten Keil <kkeil@novell.com>
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/mISDNhw.h>
+
+static void
+dchannel_bh(struct work_struct *ws)
+{
+       struct dchannel *dch  = container_of(ws, struct dchannel, workq);
+       struct sk_buff  *skb;
+       int             err;
+
+       if (test_and_clear_bit(FLG_RECVQUEUE, &dch->Flags)) {
+               while ((skb = skb_dequeue(&dch->rqueue))) {
+                       if (likely(dch->dev.D.peer)) {
+                               err = dch->dev.D.recv(dch->dev.D.peer, skb);
+                               if (err)
+                                       dev_kfree_skb(skb);
+                       } else
+                               dev_kfree_skb(skb);
+               }
+       }
+       if (test_and_clear_bit(FLG_PHCHANGE, &dch->Flags)) {
+               if (dch->phfunc)
+                       dch->phfunc(dch);
+       }
+}
+
+static void
+bchannel_bh(struct work_struct *ws)
+{
+       struct bchannel *bch  = container_of(ws, struct bchannel, workq);
+       struct sk_buff  *skb;
+       int             err;
+
+       if (test_and_clear_bit(FLG_RECVQUEUE, &bch->Flags)) {
+               while ((skb = skb_dequeue(&bch->rqueue))) {
+                       if (bch->rcount >= 64)
+                               printk(KERN_WARNING "B-channel %p receive "
+                                       "queue if full, but empties...\n", bch);
+                       bch->rcount--;
+                       if (likely(bch->ch.peer)) {
+                               err = bch->ch.recv(bch->ch.peer, skb);
+                               if (err)
+                                       dev_kfree_skb(skb);
+                       } else
+                               dev_kfree_skb(skb);
+               }
+       }
+}
+
+int
+mISDN_initdchannel(struct dchannel *ch, int maxlen, void *phf)
+{
+       test_and_set_bit(FLG_HDLC, &ch->Flags);
+       ch->maxlen = maxlen;
+       ch->hw = NULL;
+       ch->rx_skb = NULL;
+       ch->tx_skb = NULL;
+       ch->tx_idx = 0;
+       ch->phfunc = phf;
+       skb_queue_head_init(&ch->squeue);
+       skb_queue_head_init(&ch->rqueue);
+       INIT_LIST_HEAD(&ch->dev.bchannels);
+       INIT_WORK(&ch->workq, dchannel_bh);
+       return 0;
+}
+EXPORT_SYMBOL(mISDN_initdchannel);
+
+int
+mISDN_initbchannel(struct bchannel *ch, int maxlen)
+{
+       ch->Flags = 0;
+       ch->maxlen = maxlen;
+       ch->hw = NULL;
+       ch->rx_skb = NULL;
+       ch->tx_skb = NULL;
+       ch->tx_idx = 0;
+       skb_queue_head_init(&ch->rqueue);
+       ch->rcount = 0;
+       ch->next_skb = NULL;
+       INIT_WORK(&ch->workq, bchannel_bh);
+       return 0;
+}
+EXPORT_SYMBOL(mISDN_initbchannel);
+
+int
+mISDN_freedchannel(struct dchannel *ch)
+{
+       if (ch->tx_skb) {
+               dev_kfree_skb(ch->tx_skb);
+               ch->tx_skb = NULL;
+       }
+       if (ch->rx_skb) {
+               dev_kfree_skb(ch->rx_skb);
+               ch->rx_skb = NULL;
+       }
+       skb_queue_purge(&ch->squeue);
+       skb_queue_purge(&ch->rqueue);
+       flush_scheduled_work();
+       return 0;
+}
+EXPORT_SYMBOL(mISDN_freedchannel);
+
+int
+mISDN_freebchannel(struct bchannel *ch)
+{
+       if (ch->tx_skb) {
+               dev_kfree_skb(ch->tx_skb);
+               ch->tx_skb = NULL;
+       }
+       if (ch->rx_skb) {
+               dev_kfree_skb(ch->rx_skb);
+               ch->rx_skb = NULL;
+       }
+       if (ch->next_skb) {
+               dev_kfree_skb(ch->next_skb);
+               ch->next_skb = NULL;
+       }
+       skb_queue_purge(&ch->rqueue);
+       ch->rcount = 0;
+       flush_scheduled_work();
+       return 0;
+}
+EXPORT_SYMBOL(mISDN_freebchannel);
+
+static inline u_int
+get_sapi_tei(u_char *p)
+{
+       u_int   sapi, tei;
+
+       sapi = *p >> 2;
+       tei = p[1] >> 1;
+       return sapi | (tei << 8);
+}
+
+void
+recv_Dchannel(struct dchannel *dch)
+{
+       struct mISDNhead *hh;
+
+       if (dch->rx_skb->len < 2) { /* at least 2 for sapi / tei */
+               dev_kfree_skb(dch->rx_skb);
+               dch->rx_skb = NULL;
+               return;
+       }
+       hh = mISDN_HEAD_P(dch->rx_skb);
+       hh->prim = PH_DATA_IND;
+       hh->id = get_sapi_tei(dch->rx_skb->data);
+       skb_queue_tail(&dch->rqueue, dch->rx_skb);
+       dch->rx_skb = NULL;
+       schedule_event(dch, FLG_RECVQUEUE);
+}
+EXPORT_SYMBOL(recv_Dchannel);
+
+void
+recv_Bchannel(struct bchannel *bch)
+{
+       struct mISDNhead *hh;
+
+       hh = mISDN_HEAD_P(bch->rx_skb);
+       hh->prim = PH_DATA_IND;
+       hh->id = MISDN_ID_ANY;
+       if (bch->rcount >= 64) {
+               dev_kfree_skb(bch->rx_skb);
+               bch->rx_skb = NULL;
+               return;
+       }
+       bch->rcount++;
+       skb_queue_tail(&bch->rqueue, bch->rx_skb);
+       bch->rx_skb = NULL;
+       schedule_event(bch, FLG_RECVQUEUE);
+}
+EXPORT_SYMBOL(recv_Bchannel);
+
+void
+recv_Dchannel_skb(struct dchannel *dch, struct sk_buff *skb)
+{
+       skb_queue_tail(&dch->rqueue, skb);
+       schedule_event(dch, FLG_RECVQUEUE);
+}
+EXPORT_SYMBOL(recv_Dchannel_skb);
+
+void
+recv_Bchannel_skb(struct bchannel *bch, struct sk_buff *skb)
+{
+       if (bch->rcount >= 64) {
+               dev_kfree_skb(skb);
+               return;
+       }
+       bch->rcount++;
+       skb_queue_tail(&bch->rqueue, skb);
+       schedule_event(bch, FLG_RECVQUEUE);
+}
+EXPORT_SYMBOL(recv_Bchannel_skb);
+
+static void
+confirm_Dsend(struct dchannel *dch)
+{
+       struct sk_buff  *skb;
+
+       skb = _alloc_mISDN_skb(PH_DATA_CNF, mISDN_HEAD_ID(dch->tx_skb),
+           0, NULL, GFP_ATOMIC);
+       if (!skb) {
+               printk(KERN_ERR "%s: no skb id %x\n", __func__,
+                   mISDN_HEAD_ID(dch->tx_skb));
+               return;
+       }
+       skb_queue_tail(&dch->rqueue, skb);
+       schedule_event(dch, FLG_RECVQUEUE);
+}
+
+int
+get_next_dframe(struct dchannel *dch)
+{
+       dch->tx_idx = 0;
+       dch->tx_skb = skb_dequeue(&dch->squeue);
+       if (dch->tx_skb) {
+               confirm_Dsend(dch);
+               return 1;
+       }
+       dch->tx_skb = NULL;
+       test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
+       return 0;
+}
+EXPORT_SYMBOL(get_next_dframe);
+
+void
+confirm_Bsend(struct bchannel *bch)
+{
+       struct sk_buff  *skb;
+
+       if (bch->rcount >= 64)
+               return;
+       skb = _alloc_mISDN_skb(PH_DATA_CNF, mISDN_HEAD_ID(bch->tx_skb),
+           0, NULL, GFP_ATOMIC);
+       if (!skb) {
+               printk(KERN_ERR "%s: no skb id %x\n", __func__,
+                   mISDN_HEAD_ID(bch->tx_skb));
+               return;
+       }
+       bch->rcount++;
+       skb_queue_tail(&bch->rqueue, skb);
+       schedule_event(bch, FLG_RECVQUEUE);
+}
+EXPORT_SYMBOL(confirm_Bsend);
+
+int
+get_next_bframe(struct bchannel *bch)
+{
+       bch->tx_idx = 0;
+       if (test_bit(FLG_TX_NEXT, &bch->Flags)) {
+               bch->tx_skb = bch->next_skb;
+               if (bch->tx_skb) {
+                       bch->next_skb = NULL;
+                       test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
+                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
+                               confirm_Bsend(bch); /* not for transparent */
+                       return 1;
+               } else {
+                       test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
+                       printk(KERN_WARNING "B TX_NEXT without skb\n");
+               }
+       }
+       bch->tx_skb = NULL;
+       test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
+       return 0;
+}
+EXPORT_SYMBOL(get_next_bframe);
+
+void
+queue_ch_frame(struct mISDNchannel *ch, u_int pr, int id, struct sk_buff *skb)
+{
+       struct mISDNhead *hh;
+
+       if (!skb) {
+               _queue_data(ch, pr, id, 0, NULL, GFP_ATOMIC);
+       } else {
+               if (ch->peer) {
+                       hh = mISDN_HEAD_P(skb);
+                       hh->prim = pr;
+                       hh->id = id;
+                       if (!ch->recv(ch->peer, skb))
+                               return;
+               }
+               dev_kfree_skb(skb);
+       }
+}
+EXPORT_SYMBOL(queue_ch_frame);
+
+int
+dchannel_senddata(struct dchannel *ch, struct sk_buff *skb)
+{
+       /* check oversize */
+       if (skb->len <= 0) {
+               printk(KERN_WARNING "%s: skb too small\n", __func__);
+               return -EINVAL;
+       }
+       if (skb->len > ch->maxlen) {
+               printk(KERN_WARNING "%s: skb too large(%d/%d)\n",
+                       __func__, skb->len, ch->maxlen);
+               return -EINVAL;
+       }
+       /* HW lock must be obtained */
+       if (test_and_set_bit(FLG_TX_BUSY, &ch->Flags)) {
+               skb_queue_tail(&ch->squeue, skb);
+               return 0;
+       } else {
+               /* write to fifo */
+               ch->tx_skb = skb;
+               ch->tx_idx = 0;
+               return 1;
+       }
+}
+EXPORT_SYMBOL(dchannel_senddata);
+
+int
+bchannel_senddata(struct bchannel *ch, struct sk_buff *skb)
+{
+
+       /* check oversize */
+       if (skb->len <= 0) {
+               printk(KERN_WARNING "%s: skb too small\n", __func__);
+               return -EINVAL;
+       }
+       if (skb->len > ch->maxlen) {
+               printk(KERN_WARNING "%s: skb too large(%d/%d)\n",
+                       __func__, skb->len, ch->maxlen);
+               return -EINVAL;
+       }
+       /* HW lock must be obtained */
+       /* check for pending next_skb */
+       if (ch->next_skb) {
+               printk(KERN_WARNING
+                   "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n",
+                   __func__, skb->len, ch->next_skb->len);
+               return -EBUSY;
+       }
+       if (test_and_set_bit(FLG_TX_BUSY, &ch->Flags)) {
+               test_and_set_bit(FLG_TX_NEXT, &ch->Flags);
+               ch->next_skb = skb;
+               return 0;
+       } else {
+               /* write to fifo */
+               ch->tx_skb = skb;
+               ch->tx_idx = 0;
+               return 1;
+       }
+}
+EXPORT_SYMBOL(bchannel_senddata);
diff --git a/drivers/isdn/mISDN/l1oip.h b/drivers/isdn/mISDN/l1oip.h
new file mode 100644 (file)
index 0000000..a23d575
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * see notice in l1oip.c
+ */
+
+/* debugging */
+#define DEBUG_L1OIP_INIT       0x00010000
+#define DEBUG_L1OIP_SOCKET     0x00020000
+#define DEBUG_L1OIP_MGR                0x00040000
+#define DEBUG_L1OIP_MSG                0x00080000
+
+/* enable to disorder received bchannels by sequence 2143658798... */
+/*
+#define REORDER_DEBUG
+*/
+
+/* frames */
+#define L1OIP_MAX_LEN          2048            /* max packet size form l2 */
+#define L1OIP_MAX_PERFRAME     1400            /* max data size in one frame */
+
+
+/* timers */
+#define L1OIP_KEEPALIVE                15
+#define L1OIP_TIMEOUT          65
+
+
+/* socket */
+#define L1OIP_DEFAULTPORT      931
+
+
+/* channel structure */
+struct l1oip_chan {
+       struct dchannel         *dch;
+       struct bchannel         *bch;
+       u32                     tx_counter;     /* counts xmit bytes/packets */
+       u32                     rx_counter;     /* counts recv bytes/packets */
+       u32                     codecstate;     /* used by codec to save data */
+#ifdef REORDER_DEBUG
+       int                     disorder_flag;
+       struct sk_buff          *disorder_skb;
+       u32                     disorder_cnt;
+#endif
+};
+
+
+/* card structure */
+struct l1oip {
+       struct list_head        list;
+
+       /* card */
+       int                     registered;     /* if registered with mISDN */
+       char                    name[MISDN_MAX_IDLEN];
+       int                     idx;            /* card index */
+       int                     pri;            /* 1=pri, 0=bri */
+       int                     d_idx;          /* current dchannel number */
+       int                     b_num;          /* number of bchannels */
+       u32                     id;             /* id of connection */
+       int                     ondemand;       /* if transmis. is on demand */
+       int                     bundle;         /* bundle channels in one frm */
+       int                     codec;          /* codec to use for transmis. */
+       int                     limit;          /* limit number of bchannels */
+
+       /* timer */
+       struct timer_list       keep_tl;
+       struct timer_list       timeout_tl;
+       int                     timeout_on;
+       struct work_struct      workq;
+
+       /* socket */
+       struct socket           *socket;        /* if set, socket is created */
+       struct completion       socket_complete;/* completion of sock thread */
+       struct task_struct      *socket_thread;
+       spinlock_t              socket_lock;    /* access sock outside thread */
+       u32                     remoteip;       /* if all set, ip is assigned */
+       u16                     localport;      /* must always be set */
+       u16                     remoteport;     /* must always be set */
+       struct sockaddr_in      sin_local;      /* local socket name */
+       struct sockaddr_in      sin_remote;     /* remote socket name */
+       struct msghdr           sendmsg;        /* ip message to send */
+       struct iovec            sendiov;        /* iov for message */
+
+       /* frame */
+       struct l1oip_chan       chan[128];      /* channel instances */
+};
+
+extern int l1oip_law_to_4bit(u8 *data, int len, u8 *result, u32 *state);
+extern int l1oip_4bit_to_law(u8 *data, int len, u8 *result);
+extern int l1oip_alaw_to_ulaw(u8 *data, int len, u8 *result);
+extern int l1oip_ulaw_to_alaw(u8 *data, int len, u8 *result);
+extern void l1oip_4bit_free(void);
+extern int l1oip_4bit_alloc(int ulaw);
+
diff --git a/drivers/isdn/mISDN/l1oip_codec.c b/drivers/isdn/mISDN/l1oip_codec.c
new file mode 100644 (file)
index 0000000..a2dc457
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+
+ * l1oip_codec.c  generic codec using lookup table
+ *  -> conversion from a-Law to u-Law
+ *  -> conversion from u-Law to a-Law
+ *  -> compression by reducing the number of sample resolution to 4
+ *
+ * NOTE: It is not compatible with any standard codec like ADPCM.
+ *
+ * Author      Andreas Eversberg (jolly@eversberg.eu)
+ *
+ * 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.
+
+ */
+
+/*
+
+How the codec works:
+--------------------
+
+The volume is increased to increase the dynamic range of the audio signal.
+Each sample is converted to a-LAW with only 16 steps of level resolution.
+A pair of two samples are stored in one byte.
+
+The first byte is stored in the upper bits, the second byte is stored in the
+lower bits.
+
+To speed up compression and decompression, two lookup tables are formed:
+
+- 16 bits index for two samples (law encoded) with 8 bit compressed result.
+- 8 bits index for one compressed data with 16 bits decompressed result.
+
+NOTE: The bytes are handled as they are law-encoded.
+
+*/
+
+#include <linux/vmalloc.h>
+#include <linux/mISDNif.h>
+#include "core.h"
+
+/* definitions of codec. don't use calculations, code may run slower. */
+
+static u8 *table_com;
+static u16 *table_dec;
+
+
+/* alaw -> ulaw */
+static u8 alaw_to_ulaw[256] =
+{
+       0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
+       0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
+       0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
+       0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
+       0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
+       0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
+       0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
+       0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
+       0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
+       0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
+       0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
+       0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
+       0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
+       0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
+       0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
+       0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
+       0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
+       0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
+       0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
+       0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
+       0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
+       0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
+       0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
+       0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
+       0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
+       0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
+       0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
+       0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
+       0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
+       0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
+       0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
+       0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
+};
+
+/* ulaw -> alaw */
+static u8 ulaw_to_alaw[256] =
+{
+       0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
+       0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
+       0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
+       0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
+       0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
+       0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
+       0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
+       0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
+       0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
+       0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
+       0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
+       0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
+       0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
+       0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
+       0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
+       0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
+       0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
+       0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
+       0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
+       0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
+       0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
+       0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
+       0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
+       0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
+       0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
+       0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
+       0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
+       0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
+       0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
+       0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
+       0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
+       0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
+};
+
+/* alaw -> 4bit compression */
+static u8 alaw_to_4bit[256] = {
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0d, 0x02,
+       0x0e, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
+       0x0d, 0x02, 0x08, 0x07, 0x0f, 0x01, 0x0a, 0x05,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x09, 0x07, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
+       0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
+       0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
+};
+
+/* 4bit -> alaw decompression */
+static u8 _4bit_to_alaw[16] = {
+       0x5d, 0x51, 0xd9, 0xd7, 0x5f, 0x53, 0xa3, 0x4b,
+       0x2a, 0x3a, 0x22, 0x2e, 0x26, 0x56, 0x20, 0x2c,
+};
+
+/* ulaw -> 4bit compression */
+static u8 ulaw_to_4bit[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+       0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+       0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+       0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04,
+       0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+       0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
+       0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+       0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+       0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+       0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08,
+       0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+       0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+       0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+       0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+       0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+       0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+       0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
+       0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
+       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b,
+       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+       0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a,
+       0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+       0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+       0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+};
+
+/* 4bit -> ulaw decompression */
+static u8 _4bit_to_ulaw[16] = {
+       0x11, 0x21, 0x31, 0x40, 0x4e, 0x5c, 0x68, 0x71,
+       0xfe, 0xef, 0xe7, 0xdb, 0xcd, 0xbf, 0xaf, 0x9f,
+};
+
+
+/*
+ * Compresses data to the result buffer
+ * The result size must be at least half of the input buffer.
+ * The number of samples also must be even!
+ */
+int
+l1oip_law_to_4bit(u8 *data, int len, u8 *result, u32 *state)
+{
+       int ii, i = 0, o = 0;
+
+       if (!len)
+               return 0;
+
+       /* send saved byte and first input byte */
+       if (*state) {
+               *result++ = table_com[(((*state)<<8)&0xff00) | (*data++)];
+               len--;
+               o++;
+       }
+
+       ii = len >> 1;
+
+       while (i < ii) {
+               *result++ = table_com[(data[0]<<8) | (data[1])];
+               data += 2;
+               i++;
+               o++;
+       }
+
+       /* if len has an odd number, we save byte for next call */
+       if (len & 1)
+               *state = 0x100 + *data;
+       else
+               *state = 0;
+
+       return o;
+}
+
+/* Decompress data to the result buffer
+ * The result size must be the number of sample in packet. (2 * input data)
+ * The number of samples in the result are even!
+ */
+int
+l1oip_4bit_to_law(u8 *data, int len, u8 *result)
+{
+       int i = 0;
+       u16 r;
+
+       while (i < len) {
+               r = table_dec[*data++];
+               *result++ = r>>8;
+               *result++ = r;
+               i++;
+       }
+
+       return len << 1;
+}
+
+
+/*
+ * law conversion
+ */
+int
+l1oip_alaw_to_ulaw(u8 *data, int len, u8 *result)
+{
+       int i = 0;
+
+       while (i < len) {
+               *result++ = alaw_to_ulaw[*data++];
+               i++;
+       }
+
+       return len;
+}
+
+int
+l1oip_ulaw_to_alaw(u8 *data, int len, u8 *result)
+{
+       int i = 0;
+
+       while (i < len) {
+               *result++ = ulaw_to_alaw[*data++];
+               i++;
+       }
+
+       return len;
+}
+
+
+/*
+ * generate/free compression and decompression table
+ */
+void
+l1oip_4bit_free(void)
+{
+       if (table_dec)
+               vfree(table_dec);
+       if (table_com)
+               vfree(table_com);
+       table_com = NULL;
+       table_dec = NULL;
+}
+
+int
+l1oip_4bit_alloc(int ulaw)
+{
+       int i1, i2, c, sample;
+
+       /* in case, it is called again */
+       if (table_dec)
+               return 0;
+
+       /* alloc conversion tables */
+       table_com = vmalloc(65536);
+       table_dec = vmalloc(512);
+       if (!table_com | !table_dec) {
+               l1oip_4bit_free();
+               return -ENOMEM;
+       }
+       memset(table_com, 0, 65536);
+       memset(table_dec, 0, 512);
+       /* generate compression table */
+       i1 = 0;
+       while (i1 < 256) {
+               if (ulaw)
+                       c = ulaw_to_4bit[i1];
+               else
+                       c = alaw_to_4bit[i1];
+               i2 = 0;
+               while (i2 < 256) {
+                       table_com[(i1<<8) | i2] |= (c<<4);
+                       table_com[(i2<<8) | i1] |= c;
+                       i2++;
+               }
+               i1++;
+       }
+
+       /* generate decompression table */
+       i1 = 0;
+       while (i1 < 16) {
+               if (ulaw)
+                       sample = _4bit_to_ulaw[i1];
+               else
+                       sample = _4bit_to_alaw[i1];
+               i2 = 0;
+               while (i2 < 16) {
+                       table_dec[(i1<<4) | i2] |= (sample<<8);
+                       table_dec[(i2<<4) | i1] |= sample;
+                       i2++;
+               }
+               i1++;
+       }
+
+       return 0;
+}
+
+
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
new file mode 100644 (file)
index 0000000..155b997
--- /dev/null
@@ -0,0 +1,1518 @@
+/*
+
+ * l1oip.c  low level driver for tunneling layer 1 over IP
+ *
+ * NOTE: It is not compatible with TDMoIP nor "ISDN over IP".
+ *
+ * Author      Andreas Eversberg (jolly@eversberg.eu)
+ *
+ * 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.
+ *
+ */
+
+/* module parameters:
+ * type:
+       Value 1 = BRI
+       Value 2 = PRI
+       Value 3 = BRI (multi channel frame, not supported yet)
+       Value 4 = PRI (multi channel frame, not supported yet)
+       A multi channel frame reduces overhead to a single frame for all
+       b-channels, but increases delay.
+       (NOTE: Multi channel frames are not implemented yet.)
+
+ * codec:
+       Value 0 = transparent (default)
+       Value 1 = transfer ALAW
+       Value 2 = transfer ULAW
+       Value 3 = transfer generic 4 bit compression.
+
+ * ulaw:
+       0 = we use a-Law (default)
+       1 = we use u-Law
+
+ * limit:
+       limitation of B-channels to control bandwidth (1...126)
+       BRI: 1 or 2
+       PRI: 1-30, 31-126 (126, because dchannel ist not counted here)
+       Also limited ressources are used for stack, resulting in less channels.
+       It is possible to have more channels than 30 in PRI mode, this must
+       be supported by the application.
+
+ * ip:
+       byte representation of remote ip address (127.0.0.1 -> 127,0,0,1)
+       If not given or four 0, no remote address is set.
+       For multiple interfaces, concat ip addresses. (127,0,0,1,127,0,0,1)
+
+ * port:
+       port number (local interface)
+       If not given or 0, port 931 is used for fist instance, 932 for next...
+       For multiple interfaces, different ports must be given.
+
+ * remoteport:
+       port number (remote interface)
+       If not given or 0, remote port equals local port
+       For multiple interfaces on equal sites, different ports must be given.
+
+ * ondemand:
+       0 = fixed (always transmit packets, even when remote side timed out)
+       1 = on demand (only transmit packets, when remote side is detected)
+       the default is 0
+       NOTE: ID must also be set for on demand.
+
+ * id:
+       optional value to identify frames. This value must be equal on both
+       peers and should be random. If omitted or 0, no ID is transmitted.
+
+ * debug:
+       NOTE: only one debug value must be given for all cards
+       enable debugging (see l1oip.h for debug options)
+
+
+Special mISDN controls:
+
+ op = MISDN_CTRL_SETPEER*
+ p1 = bytes 0-3 : remote IP address in network order (left element first)
+ p2 = bytes 1-2 : remote port in network order (high byte first)
+ optional:
+ p2 = bytes 3-4 : local port in network order (high byte first)
+
+ op = MISDN_CTRL_UNSETPEER*
+
+ * Use l1oipctrl for comfortable setting or removing ip address.
+   (Layer 1 Over IP CTRL)
+
+
+L1oIP-Protocol
+--------------
+
+Frame Header:
+
+ 7 6 5 4 3 2 1 0
++---------------+
+|Ver|T|I|Coding |
++---------------+
+|  ID byte 3 *  |
++---------------+
+|  ID byte 2 *  |
++---------------+
+|  ID byte 1 *  |
++---------------+
+|  ID byte 0 *  |
++---------------+
+|M|   Channel   |
++---------------+
+|    Length *   |
++---------------+
+| Time Base MSB |
++---------------+
+| Time Base LSB |
++---------------+
+| Data....     |
+
+...
+
+|               |
++---------------+
+|M|   Channel   |
++---------------+
+|    Length *   |
++---------------+
+| Time Base MSB |
++---------------+
+| Time Base LSB |
++---------------+
+| Data....     |
+
+...
+
+
+* Only included in some cases.
+
+- Ver = Version
+If version is missmatch, the frame must be ignored.
+
+- T = Type of interface
+Must be 0 for S0 or 1 for E1.
+
+- I = Id present
+If bit is set, four ID bytes are included in frame.
+
+- ID = Connection ID
+Additional ID to prevent Denial of Service attacs. Also it prevents hijacking
+connections with dynamic IP. The ID should be random and must not be 0.
+
+- Coding = Type of codec
+Must be 0 for no transcoding. Also for D-channel and other HDLC frames.
+ 1 and 2 are reserved for explicitly use of a-LAW or u-LAW codec.
+ 3 is used for generic table compressor.
+
+- M = More channels to come. If this flag is 1, the following byte contains
+the length of the channel data. After the data block, the next channel will
+be defined. The flag for the last channel block (or if only one channel is
+transmitted), must be 0 and no length is given.
+
+- Channel = Channel number
+0 reserved
+1-3 channel data for S0 (3 is D-channel)
+1-31 channel data for E1 (16 is D-channel)
+32-127 channel data for extended E1 (16 is D-channel)
+
+- The length is used if the M-flag is 1. It is used to find the next channel
+inside frame.
+NOTE: A value of 0 equals 256 bytes of data.
+ -> For larger data blocks, a single frame must be used.
+ -> For larger streams, a single frame or multiple blocks with same channel ID
+   must be used.
+
+- Time Base = Timestamp of first sample in frame
+The "Time Base" is used to rearange packets and to detect packet loss.
+The 16 bits are sent in network order (MSB first) and count 1/8000 th of a
+second. This causes a wrap arround each 8,192 seconds. There is no requirement
+for the initial "Time Base", but 0 should be used for the first packet.
+In case of HDLC data, this timestamp counts the packet or byte number.
+
+
+Two Timers:
+
+After initialisation, a timer of 15 seconds is started. Whenever a packet is
+transmitted, the timer is reset to 15 seconds again. If the timer expires, an
+empty packet is transmitted. This keep the connection alive.
+
+When a valid packet is received, a timer 65 seconds is started. The interface
+become ACTIVE. If the timer expires, the interface becomes INACTIVE.
+
+
+Dynamic IP handling:
+
+To allow dynamic IP, the ID must be non 0. In this case, any packet with the
+correct port number and ID will be accepted. If the remote side changes its IP
+the new IP is used for all transmitted packets until it changes again.
+
+
+On Demand:
+
+If the ondemand parameter is given, the remote IP is set to 0 on timeout.
+This will stop keepalive traffic to remote. If the remote is online again,
+traffic will continue to the remote address. This is usefull for road warriors.
+This feature only works with ID set, otherwhise it is highly unsecure.
+
+
+Socket and Thread
+-----------------
+
+The complete socket opening and closing is done by a thread.
+When the thread opened a socket, the hc->socket descriptor is set. Whenever a
+packet shall be sent to the socket, the hc->socket must be checked wheter not
+NULL. To prevent change in socket descriptor, the hc->socket_lock must be used.
+To change the socket, a recall of l1oip_socket_open() will safely kill the
+socket process and create a new one.
+
+*/
+
+#define L1OIP_VERSION  0       /* 0...3 */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mISDNif.h>
+#include <linux/mISDNhw.h>
+#include <linux/mISDNdsp.h>
+#include <linux/init.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+#include <net/sock.h>
+#include "core.h"
+#include "l1oip.h"
+
+static const char *l1oip_revision = "2.00";
+
+static int l1oip_cnt;
+static spinlock_t l1oip_lock;
+static struct list_head l1oip_ilist;
+
+#define MAX_CARDS      16
+static u_int type[MAX_CARDS];
+static u_int codec[MAX_CARDS];
+static u_int ip[MAX_CARDS*4];
+static u_int port[MAX_CARDS];
+static u_int remoteport[MAX_CARDS];
+static u_int ondemand[MAX_CARDS];
+static u_int limit[MAX_CARDS];
+static u_int id[MAX_CARDS];
+static int debug;
+static int ulaw;
+
+MODULE_AUTHOR("Andreas Eversberg");
+MODULE_LICENSE("GPL");
+module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(codec, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(ip, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(remoteport, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(ondemand, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(limit, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(id, uint, NULL, S_IRUGO | S_IWUSR);
+module_param(ulaw, uint, S_IRUGO | S_IWUSR);
+module_param(debug, uint, S_IRUGO | S_IWUSR);
+
+/*
+ * send a frame via socket, if open and restart timer
+ */
+static int
+l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask,
+       u16 timebase, u8 *buf, int len)
+{
+       u8 *p;
+       int multi = 0;
+       u8 frame[len+32];
+       struct socket *socket = NULL;
+       mm_segment_t oldfs;
+
+       if (debug & DEBUG_L1OIP_MSG)
+               printk(KERN_DEBUG "%s: sending data to socket (len = %d)\n",
+                       __func__, len);
+
+       p = frame;
+
+       /* restart timer */
+       if ((int)(hc->keep_tl.expires-jiffies) < 5*HZ) {
+               del_timer(&hc->keep_tl);
+               hc->keep_tl.expires = jiffies + L1OIP_KEEPALIVE*HZ;
+               add_timer(&hc->keep_tl);
+       } else
+               hc->keep_tl.expires = jiffies + L1OIP_KEEPALIVE*HZ;
+
+       if (debug & DEBUG_L1OIP_MSG)
+               printk(KERN_DEBUG "%s: resetting timer\n", __func__);
+
+       /* drop if we have no remote ip or port */
+       if (!hc->sin_remote.sin_addr.s_addr || !hc->sin_remote.sin_port) {
+               if (debug & DEBUG_L1OIP_MSG)
+                       printk(KERN_DEBUG "%s: dropping frame, because remote "
+                               "IP is not set.\n", __func__);
+               return len;
+       }
+
+       /* assemble frame */
+       *p++ = (L1OIP_VERSION<<6) /* version and coding */
+            | (hc->pri?0x20:0x00) /* type */
+            | (hc->id?0x10:0x00) /* id */
+            | localcodec;
+       if (hc->id) {
+               *p++ = hc->id>>24; /* id */
+               *p++ = hc->id>>16;
+               *p++ = hc->id>>8;
+               *p++ = hc->id;
+       }
+       *p++ = (multi == 1)?0x80:0x00 + channel; /* m-flag, channel */
+       if (multi == 1)
+               *p++ = len; /* length */
+       *p++ = timebase>>8; /* time base */
+       *p++ = timebase;
+
+       if (buf && len) { /* add data to frame */
+               if (localcodec == 1 && ulaw)
+                       l1oip_ulaw_to_alaw(buf, len, p);
+               else if (localcodec == 2 && !ulaw)
+                       l1oip_alaw_to_ulaw(buf, len, p);
+               else if (localcodec == 3)
+                       len = l1oip_law_to_4bit(buf, len, p,
+                               &hc->chan[channel].codecstate);
+               else
+                       memcpy(p, buf, len);
+       }
+       len += p - frame;
+
+       /* check for socket in safe condition */
+       spin_lock(&hc->socket_lock);
+       if (!hc->socket) {
+               spin_unlock(&hc->socket_lock);
+               return 0;
+       }
+       /* seize socket */
+       socket = hc->socket;
+       hc->socket = NULL;
+       spin_unlock(&hc->socket_lock);
+       /* send packet */
+       if (debug & DEBUG_L1OIP_MSG)
+               printk(KERN_DEBUG "%s: sending packet to socket (len "
+                       "= %d)\n", __func__, len);
+       hc->sendiov.iov_base = frame;
+       hc->sendiov.iov_len  = len;
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       len = sock_sendmsg(socket, &hc->sendmsg, len);
+       set_fs(oldfs);
+       /* give socket back */
+       hc->socket = socket; /* no locking required */
+
+       return len;
+}
+
+
+/*
+ * receive channel data from socket
+ */
+static void
+l1oip_socket_recv(struct l1oip *hc, u8 remotecodec, u8 channel, u16 timebase,
+       u8 *buf, int len)
+{
+       struct sk_buff *nskb;
+       struct bchannel *bch;
+       struct dchannel *dch;
+       u8 *p;
+       u32 rx_counter;
+
+       if (len == 0) {
+               if (debug & DEBUG_L1OIP_MSG)
+                       printk(KERN_DEBUG "%s: received empty keepalive data, "
+                               "ignoring\n", __func__);
+               return;
+       }
+
+       if (debug & DEBUG_L1OIP_MSG)
+               printk(KERN_DEBUG "%s: received data, sending to mISDN (%d)\n",
+                       __func__, len);
+
+       if (channel < 1 || channel > 127) {
+               printk(KERN_WARNING "%s: packet error - channel %d out of "
+                       "range\n", __func__, channel);
+               return;
+       }
+       dch = hc->chan[channel].dch;
+       bch = hc->chan[channel].bch;
+       if (!dch && !bch) {
+               printk(KERN_WARNING "%s: packet error - channel %d not in "
+                       "stack\n", __func__, channel);
+               return;
+       }
+
+       /* prepare message */
+       nskb = mI_alloc_skb((remotecodec == 3)?(len<<1):len, GFP_ATOMIC);
+       if (!nskb) {
+               printk(KERN_ERR "%s: No mem for skb.\n", __func__);
+               return;
+       }
+       p = skb_put(nskb, (remotecodec == 3)?(len<<1):len);
+
+       if (remotecodec == 1 && ulaw)
+               l1oip_alaw_to_ulaw(buf, len, p);
+       else if (remotecodec == 2 && !ulaw)
+               l1oip_ulaw_to_alaw(buf, len, p);
+       else if (remotecodec == 3)
+               len = l1oip_4bit_to_law(buf, len, p);
+       else
+               memcpy(p, buf, len);
+
+       /* send message up */
+       if (dch && len >= 2) {
+               dch->rx_skb = nskb;
+               recv_Dchannel(dch);
+       }
+       if (bch) {
+               /* expand 16 bit sequence number to 32 bit sequence number */
+               rx_counter = hc->chan[channel].rx_counter;
+               if (((s16)(timebase - rx_counter)) >= 0) {
+                       /* time has changed forward */
+                       if (timebase >= (rx_counter & 0xffff))
+                               rx_counter =
+                                       (rx_counter & 0xffff0000) | timebase;
+                       else
+                               rx_counter = ((rx_counter & 0xffff0000)+0x10000)
+                                       | timebase;
+               } else {
+                       /* time has changed backwards */
+                       if (timebase < (rx_counter & 0xffff))
+                               rx_counter =
+                                       (rx_counter & 0xffff0000) | timebase;
+                       else
+                               rx_counter = ((rx_counter & 0xffff0000)-0x10000)
+                                       | timebase;
+               }
+               hc->chan[channel].rx_counter = rx_counter;
+
+#ifdef REORDER_DEBUG
+               if (hc->chan[channel].disorder_flag) {
+                       struct sk_buff *skb;
+                       int cnt;
+                       skb = hc->chan[channel].disorder_skb;
+                       hc->chan[channel].disorder_skb = nskb;
+                       nskb = skb;
+                       cnt = hc->chan[channel].disorder_cnt;
+                       hc->chan[channel].disorder_cnt = rx_counter;
+                       rx_counter = cnt;
+               }
+               hc->chan[channel].disorder_flag ^= 1;
+               if (nskb)
+#endif
+               queue_ch_frame(&bch->ch, PH_DATA_IND, rx_counter, nskb);
+       }
+}
+
+
+/*
+ * parse frame and extract channel data
+ */
+static void
+l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len)
+{
+       u32                     id;
+       u8                      channel;
+       u8                      remotecodec;
+       u16                     timebase;
+       int                     m, mlen;
+       int                     len_start = len; /* initial frame length */
+       struct dchannel         *dch = hc->chan[hc->d_idx].dch;
+
+       if (debug & DEBUG_L1OIP_MSG)
+               printk(KERN_DEBUG "%s: received frame, parsing... (%d)\n",
+                       __func__, len);
+
+       /* check lenght */
+       if (len < 1+1+2) {
+               printk(KERN_WARNING "%s: packet error - length %d below "
+                       "4 bytes\n", __func__, len);
+               return;
+       }
+
+       /* check version */
+       if (((*buf)>>6) != L1OIP_VERSION) {
+               printk(KERN_WARNING "%s: packet error - unknown version %d\n",
+                       __func__, buf[0]>>6);
+               return;
+       }
+
+       /* check type */
+       if (((*buf)&0x20) && !hc->pri) {
+               printk(KERN_WARNING "%s: packet error - received E1 packet "
+                       "on S0 interface\n", __func__);
+               return;
+       }
+       if (!((*buf)&0x20) && hc->pri) {
+               printk(KERN_WARNING "%s: packet error - received S0 packet "
+                       "on E1 interface\n", __func__);
+               return;
+       }
+
+       /* get id flag */
+       id = (*buf>>4)&1;
+
+       /* check coding */
+       remotecodec = (*buf) & 0x0f;
+       if (remotecodec > 3) {
+               printk(KERN_WARNING "%s: packet error - remotecodec %d "
+                       "unsupported\n", __func__, remotecodec);
+               return;
+       }
+       buf++;
+       len--;
+
+       /* check id */
+       if (id) {
+               if (!hc->id) {
+                       printk(KERN_WARNING "%s: packet error - packet has id "
+                               "0x%x, but we have not\n", __func__, id);
+                       return;
+               }
+               if (len < 4) {
+                       printk(KERN_WARNING "%s: packet error - packet too "
+                               "short for ID value\n", __func__);
+                       return;
+               }
+               id = (*buf++) << 24;
+               id += (*buf++) << 16;
+               id += (*buf++) << 8;
+               id += (*buf++);
+               len -= 4;
+
+               if (id != hc->id) {
+                       printk(KERN_WARNING "%s: packet error - ID mismatch, "
+                               "got 0x%x, we 0x%x\n",
+                               __func__, id, hc->id);
+                       return;
+               }
+       } else {
+               if (hc->id) {
+                       printk(KERN_WARNING "%s: packet error - packet has no "
+                               "ID, but we have\n", __func__);
+                       return;
+               }
+       }
+
+multiframe:
+       if (len < 1) {
+               printk(KERN_WARNING "%s: packet error - packet too short, "
+                       "channel expected at position %d.\n",
+                       __func__, len-len_start+1);
+               return;
+       }
+
+       /* get channel and multiframe flag */
+       channel = *buf&0x7f;
+       m = *buf >> 7;
+       buf++;
+       len--;
+
+       /* check length on multiframe */
+       if (m) {
+               if (len < 1) {
+                       printk(KERN_WARNING "%s: packet error - packet too "
+                               "short, length expected at position %d.\n",
+                               __func__, len_start-len-1);
+                       return;
+               }
+
+               mlen = *buf++;
+               len--;
+               if (mlen == 0)
+                       mlen = 256;
+               if (len < mlen+3) {
+                       printk(KERN_WARNING "%s: packet error - length %d at "
+                               "position %d exceeds total length %d.\n",
+                               __func__, mlen, len_start-len-1, len_start);
+                       return;
+               }
+               if (len == mlen+3) {
+                       printk(KERN_WARNING "%s: packet error - length %d at "
+                               "position %d will not allow additional "
+                               "packet.\n",
+                               __func__, mlen, len_start-len+1);
+                       return;
+               }
+       } else
+               mlen = len-2; /* single frame, substract timebase */
+
+       if (len < 2) {
+               printk(KERN_WARNING "%s: packet error - packet too short, time "
+                       "base expected at position %d.\n",
+                       __func__, len-len_start+1);
+               return;
+       }
+
+       /* get time base */
+       timebase = (*buf++) << 8;
+       timebase |= (*buf++);
+       len -= 2;
+
+       /* if inactive, we send up a PH_ACTIVATE and activate */
+       if (!test_bit(FLG_ACTIVE, &dch->Flags)) {
+               if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET))
+                       printk(KERN_DEBUG "%s: interface become active due to "
+                               "received packet\n", __func__);
+               test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+               _queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
+                       NULL, GFP_ATOMIC);
+       }
+
+       /* distribute packet */
+       l1oip_socket_recv(hc, remotecodec, channel, timebase, buf, mlen);
+       buf += mlen;
+       len -= mlen;
+
+       /* multiframe */
+       if (m)
+               goto multiframe;
+
+       /* restart timer */
+       if ((int)(hc->timeout_tl.expires-jiffies) < 5*HZ || !hc->timeout_on) {
+               hc->timeout_on = 1;
+               del_timer(&hc->timeout_tl);
+               hc->timeout_tl.expires = jiffies + L1OIP_TIMEOUT*HZ;
+               add_timer(&hc->timeout_tl);
+       } else /* only adjust timer */
+               hc->timeout_tl.expires = jiffies + L1OIP_TIMEOUT*HZ;
+
+       /* if ip or source port changes */
+       if ((hc->sin_remote.sin_addr.s_addr != sin->sin_addr.s_addr)
+        || (hc->sin_remote.sin_port != sin->sin_port)) {
+               if (debug & DEBUG_L1OIP_SOCKET)
+                       printk(KERN_DEBUG "%s: remote address changes from "
+                               "0x%08x to 0x%08x (port %d to %d)\n", __func__,
+                               ntohl(hc->sin_remote.sin_addr.s_addr),
+                               ntohl(sin->sin_addr.s_addr),
+                               ntohs(hc->sin_remote.sin_port),
+                               ntohs(sin->sin_port));
+               hc->sin_remote.sin_addr.s_addr = sin->sin_addr.s_addr;
+               hc->sin_remote.sin_port = sin->sin_port;
+       }
+}
+
+
+/*
+ * socket stuff
+ */
+static int
+l1oip_socket_thread(void *data)
+{
+       struct l1oip *hc = (struct l1oip *)data;
+       int ret = 0;
+       struct msghdr msg;
+       struct iovec iov;
+       mm_segment_t oldfs;
+       struct sockaddr_in sin_rx;
+       unsigned char recvbuf[1500];
+       int recvlen;
+       struct socket *socket = NULL;
+       DECLARE_COMPLETION(wait);
+
+       /* make daemon */
+       allow_signal(SIGTERM);
+
+       /* create socket */
+       if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &socket)) {
+               printk(KERN_ERR "%s: Failed to create socket.\n", __func__);
+               return -EIO;
+       }
+
+       /* set incoming address */
+       hc->sin_local.sin_family = AF_INET;
+       hc->sin_local.sin_addr.s_addr = INADDR_ANY;
+       hc->sin_local.sin_port = htons((unsigned short)hc->localport);
+
+       /* set outgoing address */
+       hc->sin_remote.sin_family = AF_INET;
+       hc->sin_remote.sin_addr.s_addr = htonl(hc->remoteip);
+       hc->sin_remote.sin_port = htons((unsigned short)hc->remoteport);
+
+       /* bind to incomming port */
+       if (socket->ops->bind(socket, (struct sockaddr *)&hc->sin_local,
+           sizeof(hc->sin_local))) {
+               printk(KERN_ERR "%s: Failed to bind socket to port %d.\n",
+                       __func__, hc->localport);
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       /* check sk */
+       if (socket->sk == NULL) {
+               printk(KERN_ERR "%s: socket->sk == NULL\n", __func__);
+               ret = -EIO;
+               goto fail;
+       }
+
+       /* build receive message */
+       msg.msg_name = &sin_rx;
+       msg.msg_namelen = sizeof(sin_rx);
+       msg.msg_control = NULL;
+       msg.msg_controllen = 0;
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+
+       /* build send message */
+       hc->sendmsg.msg_name = &hc->sin_remote;
+       hc->sendmsg.msg_namelen = sizeof(hc->sin_remote);
+       hc->sendmsg.msg_control = NULL;
+       hc->sendmsg.msg_controllen = 0;
+       hc->sendmsg.msg_iov    = &hc->sendiov;
+       hc->sendmsg.msg_iovlen = 1;
+
+       /* give away socket */
+       spin_lock(&hc->socket_lock);
+       hc->socket = socket;
+       spin_unlock(&hc->socket_lock);
+
+       /* read loop */
+       if (debug & DEBUG_L1OIP_SOCKET)
+               printk(KERN_DEBUG "%s: socket created and open\n",
+                       __func__);
+       while (!signal_pending(current)) {
+               iov.iov_base = recvbuf;
+               iov.iov_len = sizeof(recvbuf);
+               oldfs = get_fs();
+               set_fs(KERNEL_DS);
+               recvlen = sock_recvmsg(socket, &msg, sizeof(recvbuf), 0);
+               set_fs(oldfs);
+               if (recvlen > 0) {
+                       l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen);
+               } else {
+                       if (debug & DEBUG_L1OIP_SOCKET)
+                           printk(KERN_WARNING "%s: broken pipe on socket\n",
+                               __func__);
+               }
+       }
+
+       /* get socket back, check first if in use, maybe by send function */
+       spin_lock(&hc->socket_lock);
+       /* if hc->socket is NULL, it is in use until it is given back */
+       while (!hc->socket) {
+               spin_unlock(&hc->socket_lock);
+               schedule_timeout(HZ/10);
+               spin_lock(&hc->socket_lock);
+       }
+       hc->socket = NULL;
+       spin_unlock(&hc->socket_lock);
+
+       if (debug & DEBUG_L1OIP_SOCKET)
+               printk(KERN_DEBUG "%s: socket thread terminating\n",
+                       __func__);
+
+fail:
+       /* close socket */
+       if (socket)
+               sock_release(socket);
+
+       /* if we got killed, signal completion */
+       complete(&hc->socket_complete);
+       hc->socket_thread = NULL; /* show termination of thread */
+
+       if (debug & DEBUG_L1OIP_SOCKET)
+               printk(KERN_DEBUG "%s: socket thread terminated\n",
+                       __func__);
+       return ret;
+}
+
+static void
+l1oip_socket_close(struct l1oip *hc)
+{
+       /* kill thread */
+       if (hc->socket_thread) {
+               if (debug & DEBUG_L1OIP_SOCKET)
+                       printk(KERN_DEBUG "%s: socket thread exists, "
+                               "killing...\n", __func__);
+               send_sig(SIGTERM, hc->socket_thread, 0);
+               wait_for_completion(&hc->socket_complete);
+       }
+}
+
+static int
+l1oip_socket_open(struct l1oip *hc)
+{
+       /* in case of reopen, we need to close first */
+       l1oip_socket_close(hc);
+
+       init_completion(&hc->socket_complete);
+
+       /* create receive process */
+       hc->socket_thread = kthread_run(l1oip_socket_thread, hc, "l1oip_%s",
+               hc->name);
+       if (IS_ERR(hc->socket_thread)) {
+               int err = PTR_ERR(hc->socket_thread);
+               printk(KERN_ERR "%s: Failed (%d) to create socket process.\n",
+                       __func__, err);
+               hc->socket_thread = NULL;
+               sock_release(hc->socket);
+               return err;
+       }
+       if (debug & DEBUG_L1OIP_SOCKET)
+               printk(KERN_DEBUG "%s: socket thread created\n", __func__);
+
+       return 0;
+}
+
+
+static void
+l1oip_send_bh(struct work_struct *work)
+{
+       struct l1oip *hc = container_of(work, struct l1oip, workq);
+
+       if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET))
+               printk(KERN_DEBUG "%s: keepalive timer expired, sending empty "
+                       "frame on dchannel\n", __func__);
+
+       /* send an empty l1oip frame at D-channel */
+       l1oip_socket_send(hc, 0, hc->d_idx, 0, 0, NULL, 0);
+}
+
+
+/*
+ * timer stuff
+ */
+static void
+l1oip_keepalive(void *data)
+{
+       struct l1oip *hc = (struct l1oip *)data;
+
+       schedule_work(&hc->workq);
+}
+
+static void
+l1oip_timeout(void *data)
+{
+       struct l1oip                    *hc = (struct l1oip *)data;
+       struct dchannel         *dch = hc->chan[hc->d_idx].dch;
+
+       if (debug & DEBUG_L1OIP_MSG)
+               printk(KERN_DEBUG "%s: timeout timer expired, turn layer one "
+                       "down.\n", __func__);
+
+       hc->timeout_on = 0; /* state that timer must be initialized next time */
+
+       /* if timeout, we send up a PH_DEACTIVATE and deactivate */
+       if (test_bit(FLG_ACTIVE, &dch->Flags)) {
+               if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET))
+                       printk(KERN_DEBUG "%s: interface become deactivated "
+                               "due to timeout\n", __func__);
+               test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+               _queue_data(&dch->dev.D, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
+                       NULL, GFP_ATOMIC);
+       }
+
+       /* if we have ondemand set, we remove ip address */
+       if (hc->ondemand) {
+               if (debug & DEBUG_L1OIP_MSG)
+                       printk(KERN_DEBUG "%s: on demand causes ip address to "
+                               "be removed\n", __func__);
+               hc->sin_remote.sin_addr.s_addr = 0;
+       }
+}
+
+
+/*
+ * message handling
+ */
+static int
+handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct mISDNdevice      *dev = container_of(ch, struct mISDNdevice, D);
+       struct dchannel         *dch = container_of(dev, struct dchannel, dev);
+       struct l1oip                    *hc = dch->hw;
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+       int                     ret = -EINVAL;
+       int                     l, ll;
+       unsigned char           *p;
+
+       switch (hh->prim) {
+       case PH_DATA_REQ:
+               if (skb->len < 1) {
+                       printk(KERN_WARNING "%s: skb too small\n",
+                               __func__);
+                       break;
+               }
+               if (skb->len > MAX_DFRAME_LEN_L1 || skb->len > L1OIP_MAX_LEN) {
+                       printk(KERN_WARNING "%s: skb too large\n",
+                               __func__);
+                       break;
+               }
+               /* send frame */
+               p = skb->data;
+               l = skb->len;
+               while (l) {
+                       ll = (l < L1OIP_MAX_PERFRAME)?l:L1OIP_MAX_PERFRAME;
+                       l1oip_socket_send(hc, 0, dch->slot, 0,
+                               hc->chan[dch->slot].tx_counter++, p, ll);
+                       p += ll;
+                       l -= ll;
+               }
+               skb_trim(skb, 0);
+               queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb);
+               return 0;
+       case PH_ACTIVATE_REQ:
+               if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET))
+                       printk(KERN_DEBUG "%s: PH_ACTIVATE channel %d (1..%d)\n"
+                               , __func__, dch->slot, hc->b_num+1);
+               skb_trim(skb, 0);
+               if (test_bit(FLG_ACTIVE, &dch->Flags))
+                       queue_ch_frame(ch, PH_ACTIVATE_IND, hh->id, skb);
+               else
+                       queue_ch_frame(ch, PH_DEACTIVATE_IND, hh->id, skb);
+               return 0;
+       case PH_DEACTIVATE_REQ:
+               if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET))
+                       printk(KERN_DEBUG "%s: PH_DEACTIVATE channel %d "
+                               "(1..%d)\n", __func__, dch->slot,
+                               hc->b_num+1);
+               skb_trim(skb, 0);
+               if (test_bit(FLG_ACTIVE, &dch->Flags))
+                       queue_ch_frame(ch, PH_ACTIVATE_IND, hh->id, skb);
+               else
+                       queue_ch_frame(ch, PH_DEACTIVATE_IND, hh->id, skb);
+               return 0;
+       }
+       if (!ret)
+               dev_kfree_skb(skb);
+       return ret;
+}
+
+static int
+channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
+{
+       int     ret = 0;
+       struct l1oip    *hc = dch->hw;
+
+       switch (cq->op) {
+       case MISDN_CTRL_GETOP:
+               cq->op = MISDN_CTRL_SETPEER | MISDN_CTRL_UNSETPEER;
+               break;
+       case MISDN_CTRL_SETPEER:
+               hc->remoteip = (u32)cq->p1;
+               hc->remoteport = cq->p2 & 0xffff;
+               hc->localport = cq->p2 >> 16;
+               if (!hc->remoteport)
+                       hc->remoteport = hc->localport;
+               if (debug & DEBUG_L1OIP_SOCKET)
+                       printk(KERN_DEBUG "%s: got new ip address from user "
+                               "space.\n", __func__);
+                       l1oip_socket_open(hc);
+               break;
+       case MISDN_CTRL_UNSETPEER:
+               if (debug & DEBUG_L1OIP_SOCKET)
+                       printk(KERN_DEBUG "%s: removing ip address.\n",
+                               __func__);
+               hc->remoteip = 0;
+               l1oip_socket_open(hc);
+               break;
+       default:
+               printk(KERN_WARNING "%s: unknown Op %x\n",
+                   __func__, cq->op);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int
+open_dchannel(struct l1oip *hc, struct dchannel *dch, struct channel_req *rq)
+{
+       if (debug & DEBUG_HW_OPEN)
+               printk(KERN_DEBUG "%s: dev(%d) open from %p\n", __func__,
+                   dch->dev.id, __builtin_return_address(0));
+       if (rq->protocol == ISDN_P_NONE)
+               return -EINVAL;
+       if ((dch->dev.D.protocol != ISDN_P_NONE) &&
+           (dch->dev.D.protocol != rq->protocol)) {
+               if (debug & DEBUG_HW_OPEN)
+                       printk(KERN_WARNING "%s: change protocol %x to %x\n",
+                       __func__, dch->dev.D.protocol, rq->protocol);
+       }
+       if (dch->dev.D.protocol != rq->protocol)
+               dch->dev.D.protocol = rq->protocol;
+
+       if (test_bit(FLG_ACTIVE, &dch->Flags)) {
+               _queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY,
+                   0, NULL, GFP_KERNEL);
+       }
+       rq->ch = &dch->dev.D;
+       if (!try_module_get(THIS_MODULE))
+               printk(KERN_WARNING "%s:cannot get module\n", __func__);
+       return 0;
+}
+
+static int
+open_bchannel(struct l1oip *hc, struct dchannel *dch, struct channel_req *rq)
+{
+       struct bchannel *bch;
+       int             ch;
+
+       if (!test_bit(rq->adr.channel & 0x1f,
+               &dch->dev.channelmap[rq->adr.channel >> 5]))
+               return -EINVAL;
+       if (rq->protocol == ISDN_P_NONE)
+               return -EINVAL;
+       ch = rq->adr.channel; /* BRI: 1=B1 2=B2  PRI: 1..15,17.. */
+       bch = hc->chan[ch].bch;
+       if (!bch) {
+               printk(KERN_ERR "%s:internal error ch %d has no bch\n",
+                   __func__, ch);
+               return -EINVAL;
+       }
+       if (test_and_set_bit(FLG_OPEN, &bch->Flags))
+               return -EBUSY; /* b-channel can be only open once */
+       bch->ch.protocol = rq->protocol;
+       rq->ch = &bch->ch;
+       if (!try_module_get(THIS_MODULE))
+               printk(KERN_WARNING "%s:cannot get module\n", __func__);
+       return 0;
+}
+
+static int
+l1oip_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct mISDNdevice      *dev = container_of(ch, struct mISDNdevice, D);
+       struct dchannel         *dch = container_of(dev, struct dchannel, dev);
+       struct l1oip                    *hc = dch->hw;
+       struct channel_req      *rq;
+       int                     err = 0;
+
+       if (dch->debug & DEBUG_HW)
+               printk(KERN_DEBUG "%s: cmd:%x %p\n",
+                   __func__, cmd, arg);
+       switch (cmd) {
+       case OPEN_CHANNEL:
+               rq = arg;
+               switch (rq->protocol) {
+               case ISDN_P_TE_S0:
+               case ISDN_P_NT_S0:
+                       if (hc->pri) {
+                               err = -EINVAL;
+                               break;
+                       }
+                       err = open_dchannel(hc, dch, rq);
+                       break;
+               case ISDN_P_TE_E1:
+               case ISDN_P_NT_E1:
+                       if (!hc->pri) {
+                               err = -EINVAL;
+                               break;
+                       }
+                       err = open_dchannel(hc, dch, rq);
+                       break;
+               default:
+                       err = open_bchannel(hc, dch, rq);
+               }
+               break;
+       case CLOSE_CHANNEL:
+               if (debug & DEBUG_HW_OPEN)
+                       printk(KERN_DEBUG "%s: dev(%d) close from %p\n",
+                           __func__, dch->dev.id,
+                           __builtin_return_address(0));
+               module_put(THIS_MODULE);
+               break;
+       case CONTROL_CHANNEL:
+               err = channel_dctrl(dch, arg);
+               break;
+       default:
+               if (dch->debug & DEBUG_HW)
+                       printk(KERN_DEBUG "%s: unknown command %x\n",
+                           __func__, cmd);
+               err = -EINVAL;
+       }
+       return err;
+}
+
+static int
+handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct bchannel         *bch = container_of(ch, struct bchannel, ch);
+       struct l1oip                    *hc = bch->hw;
+       int                     ret = -EINVAL;
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+       int                     l, ll, i;
+       unsigned char           *p;
+
+       switch (hh->prim) {
+       case PH_DATA_REQ:
+               if (skb->len <= 0) {
+                       printk(KERN_WARNING "%s: skb too small\n",
+                               __func__);
+                       break;
+               }
+               if (skb->len > MAX_DFRAME_LEN_L1 || skb->len > L1OIP_MAX_LEN) {
+                       printk(KERN_WARNING "%s: skb too large\n",
+                               __func__);
+                       break;
+               }
+               /* check for AIS / ulaw-silence */
+               p = skb->data;
+               l = skb->len;
+               for (i = 0; i < l; i++) {
+                       if (*p++ != 0xff)
+                               break;
+               }
+               if (i == l) {
+                       if (debug & DEBUG_L1OIP_MSG)
+                               printk(KERN_DEBUG "%s: got AIS, not sending, "
+                                       "but counting\n", __func__);
+                       hc->chan[bch->slot].tx_counter += l;
+                       skb_trim(skb, 0);
+                       queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb);
+                       return 0;
+               }
+               /* check for silence */
+               p = skb->data;
+               l = skb->len;
+               for (i = 0; i < l; i++) {
+                       if (*p++ != 0x2a)
+                               break;
+               }
+               if (i == l) {
+                       if (debug & DEBUG_L1OIP_MSG)
+                               printk(KERN_DEBUG "%s: got silence, not sending"
+                                       ", but counting\n", __func__);
+                       hc->chan[bch->slot].tx_counter += l;
+                       skb_trim(skb, 0);
+                       queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb);
+                       return 0;
+               }
+
+               /* send frame */
+               p = skb->data;
+               l = skb->len;
+               while (l) {
+                       ll = (l < L1OIP_MAX_PERFRAME)?l:L1OIP_MAX_PERFRAME;
+                       l1oip_socket_send(hc, hc->codec, bch->slot, 0,
+                               hc->chan[bch->slot].tx_counter, p, ll);
+                       hc->chan[bch->slot].tx_counter += ll;
+                       p += ll;
+                       l -= ll;
+               }
+               skb_trim(skb, 0);
+               queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb);
+               return 0;
+       case PH_ACTIVATE_REQ:
+               if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET))
+                       printk(KERN_DEBUG "%s: PH_ACTIVATE channel %d (1..%d)\n"
+                               , __func__, bch->slot, hc->b_num+1);
+               hc->chan[bch->slot].codecstate = 0;
+               test_and_set_bit(FLG_ACTIVE, &bch->Flags);
+               skb_trim(skb, 0);
+               queue_ch_frame(ch, PH_ACTIVATE_IND, hh->id, skb);
+               return 0;
+       case PH_DEACTIVATE_REQ:
+               if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET))
+                       printk(KERN_DEBUG "%s: PH_DEACTIVATE channel %d "
+                               "(1..%d)\n", __func__, bch->slot,
+                               hc->b_num+1);
+               test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
+               skb_trim(skb, 0);
+               queue_ch_frame(ch, PH_DEACTIVATE_IND, hh->id, skb);
+               return 0;
+       }
+       if (!ret)
+               dev_kfree_skb(skb);
+       return ret;
+}
+
+static int
+channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
+{
+       int                     ret = 0;
+       struct dsp_features     *features =
+               (struct dsp_features *)(*((u_long *)&cq->p1));
+
+       switch (cq->op) {
+       case MISDN_CTRL_GETOP:
+               cq->op = MISDN_CTRL_HW_FEATURES_OP;
+               break;
+       case MISDN_CTRL_HW_FEATURES: /* fill features structure */
+               if (debug & DEBUG_L1OIP_MSG)
+                       printk(KERN_DEBUG "%s: HW_FEATURE request\n",
+                           __func__);
+               /* create confirm */
+               features->unclocked = 1;
+               features->unordered = 1;
+               break;
+       default:
+               printk(KERN_WARNING "%s: unknown Op %x\n",
+                   __func__, cq->op);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int
+l1oip_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct bchannel *bch = container_of(ch, struct bchannel, ch);
+       int             err = -EINVAL;
+
+       if (bch->debug & DEBUG_HW)
+               printk(KERN_DEBUG "%s: cmd:%x %p\n",
+                   __func__, cmd, arg);
+       switch (cmd) {
+       case CLOSE_CHANNEL:
+               test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
+               ch->protocol = ISDN_P_NONE;
+               ch->peer = NULL;
+               module_put(THIS_MODULE);
+               err = 0;
+               break;
+       case CONTROL_CHANNEL:
+               err = channel_bctrl(bch, arg);
+               break;
+       default:
+               printk(KERN_WARNING "%s: unknown prim(%x)\n",
+                       __func__, cmd);
+       }
+       return err;
+}
+
+
+/*
+ * cleanup module and stack
+ */
+static void
+release_card(struct l1oip *hc)
+{
+       int     ch;
+
+       if (timer_pending(&hc->keep_tl))
+               del_timer(&hc->keep_tl);
+
+       if (timer_pending(&hc->timeout_tl))
+               del_timer(&hc->timeout_tl);
+
+       if (hc->socket_thread)
+               l1oip_socket_close(hc);
+
+       if (hc->registered && hc->chan[hc->d_idx].dch)
+               mISDN_unregister_device(&hc->chan[hc->d_idx].dch->dev);
+       for (ch = 0; ch < 128; ch++) {
+               if (hc->chan[ch].dch) {
+                       mISDN_freedchannel(hc->chan[ch].dch);
+                       kfree(hc->chan[ch].dch);
+               }
+               if (hc->chan[ch].bch) {
+                       mISDN_freebchannel(hc->chan[ch].bch);
+                       kfree(hc->chan[ch].bch);
+#ifdef REORDER_DEBUG
+                       if (hc->chan[ch].disorder_skb)
+                               dev_kfree_skb(hc->chan[ch].disorder_skb);
+#endif
+               }
+       }
+
+       spin_lock(&l1oip_lock);
+       list_del(&hc->list);
+       spin_unlock(&l1oip_lock);
+
+       kfree(hc);
+}
+
+static void
+l1oip_cleanup(void)
+{
+       struct l1oip *hc, *next;
+
+       list_for_each_entry_safe(hc, next, &l1oip_ilist, list)
+               release_card(hc);
+
+       l1oip_4bit_free();
+}
+
+
+/*
+ * module and stack init
+ */
+static int
+init_card(struct l1oip *hc, int pri, int bundle)
+{
+       struct dchannel *dch;
+       struct bchannel *bch;
+       int             ret;
+       int             i, ch;
+
+       spin_lock_init(&hc->socket_lock);
+       hc->idx = l1oip_cnt;
+       hc->pri = pri;
+       hc->d_idx = pri?16:3;
+       hc->b_num = pri?30:2;
+       hc->bundle = bundle;
+       if (hc->pri)
+               sprintf(hc->name, "l1oip-e1.%d", l1oip_cnt + 1);
+       else
+               sprintf(hc->name, "l1oip-s0.%d", l1oip_cnt + 1);
+
+       switch (codec[l1oip_cnt]) {
+       case 0: /* as is */
+       case 1: /* alaw */
+       case 2: /* ulaw */
+       case 3: /* 4bit */
+               break;
+       default:
+               printk(KERN_ERR "Codec(%d) not supported.\n",
+                       codec[l1oip_cnt]);
+               return -EINVAL;
+       }
+       hc->codec = codec[l1oip_cnt];
+       if (debug & DEBUG_L1OIP_INIT)
+               printk(KERN_DEBUG "%s: using codec %d\n",
+                       __func__, hc->codec);
+
+       if (id[l1oip_cnt] == 0) {
+               printk(KERN_WARNING "Warning: No 'id' value given or "
+                       "0, this is highly unsecure. Please use 32 "
+                       "bit randmom number 0x...\n");
+       }
+       hc->id = id[l1oip_cnt];
+       if (debug & DEBUG_L1OIP_INIT)
+               printk(KERN_DEBUG "%s: using id 0x%x\n", __func__, hc->id);
+
+       hc->ondemand = ondemand[l1oip_cnt];
+       if (hc->ondemand && !hc->id) {
+               printk(KERN_ERR "%s: ondemand option only allowed in "
+                       "conjunction with non 0 ID\n", __func__);
+               return -EINVAL;
+       }
+
+       if (limit[l1oip_cnt])
+               hc->b_num = limit[l1oip_cnt];
+       if (!pri && hc->b_num > 2) {
+               printk(KERN_ERR "Maximum limit for BRI interface is 2 "
+                       "channels.\n");
+               return -EINVAL;
+       }
+       if (pri && hc->b_num > 126) {
+               printk(KERN_ERR "Maximum limit for PRI interface is 126 "
+                       "channels.\n");
+               return -EINVAL;
+       }
+       if (pri && hc->b_num > 30) {
+               printk(KERN_WARNING "Maximum limit for BRI interface is 30 "
+                       "channels.\n");
+               printk(KERN_WARNING "Your selection of %d channels must be "
+                       "supported by application.\n", hc->limit);
+       }
+
+       hc->remoteip = ip[l1oip_cnt<<2] << 24
+                    | ip[(l1oip_cnt<<2)+1] << 16
+                    | ip[(l1oip_cnt<<2)+2] << 8
+                    | ip[(l1oip_cnt<<2)+3];
+       hc->localport = port[l1oip_cnt]?:(L1OIP_DEFAULTPORT+l1oip_cnt);
+       if (remoteport[l1oip_cnt])
+               hc->remoteport = remoteport[l1oip_cnt];
+       else
+               hc->remoteport = hc->localport;
+       if (debug & DEBUG_L1OIP_INIT)
+               printk(KERN_DEBUG "%s: using local port %d remote ip "
+                       "%d.%d.%d.%d port %d ondemand %d\n", __func__,
+                       hc->localport, hc->remoteip >> 24,
+                       (hc->remoteip >> 16) & 0xff,
+                       (hc->remoteip >> 8) & 0xff, hc->remoteip & 0xff,
+                       hc->remoteport, hc->ondemand);
+
+       dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL);
+       if (!dch)
+               return -ENOMEM;
+       dch->debug = debug;
+       mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, NULL);
+       dch->hw = hc;
+       if (pri)
+               dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1);
+       else
+               dch->dev.Dprotocols = (1 << ISDN_P_TE_S0) | (1 << ISDN_P_NT_S0);
+       dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+           (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+       dch->dev.D.send = handle_dmsg;
+       dch->dev.D.ctrl = l1oip_dctrl;
+       dch->dev.nrbchan = hc->b_num;
+       dch->slot = hc->d_idx;
+       hc->chan[hc->d_idx].dch = dch;
+       i = 1;
+       for (ch = 0; ch < dch->dev.nrbchan; ch++) {
+               if (ch == 15)
+                       i++;
+               bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL);
+               if (!bch) {
+                       printk(KERN_ERR "%s: no memory for bchannel\n",
+                           __func__);
+                       return -ENOMEM;
+               }
+               bch->nr = i + ch;
+               bch->slot = i + ch;
+               bch->debug = debug;
+               mISDN_initbchannel(bch, MAX_DATA_MEM);
+               bch->hw = hc;
+               bch->ch.send = handle_bmsg;
+               bch->ch.ctrl = l1oip_bctrl;
+               bch->ch.nr = i + ch;
+               list_add(&bch->ch.list, &dch->dev.bchannels);
+               hc->chan[i + ch].bch = bch;
+               test_and_set_bit(bch->nr & 0x1f,
+                       &dch->dev.channelmap[bch->nr >> 5]);
+       }
+       ret = mISDN_register_device(&dch->dev, hc->name);
+       if (ret)
+               return ret;
+       hc->registered = 1;
+
+       if (debug & DEBUG_L1OIP_INIT)
+               printk(KERN_DEBUG "%s: Setting up network card(%d)\n",
+                       __func__, l1oip_cnt + 1);
+       ret = l1oip_socket_open(hc);
+       if (ret)
+               return ret;
+
+       hc->keep_tl.function = (void *)l1oip_keepalive;
+       hc->keep_tl.data = (ulong)hc;
+       init_timer(&hc->keep_tl);
+       hc->keep_tl.expires = jiffies + 2*HZ; /* two seconds first time */
+       add_timer(&hc->keep_tl);
+
+       hc->timeout_tl.function = (void *)l1oip_timeout;
+       hc->timeout_tl.data = (ulong)hc;
+       init_timer(&hc->timeout_tl);
+       hc->timeout_on = 0; /* state that we have timer off */
+
+       return 0;
+}
+
+static int __init
+l1oip_init(void)
+{
+       int             pri, bundle;
+       struct l1oip            *hc;
+       int             ret;
+
+       printk(KERN_INFO "mISDN: Layer-1-over-IP driver Rev. %s\n",
+               l1oip_revision);
+
+       INIT_LIST_HEAD(&l1oip_ilist);
+       spin_lock_init(&l1oip_lock);
+
+       if (l1oip_4bit_alloc(ulaw))
+               return -ENOMEM;
+
+       l1oip_cnt = 0;
+       while (type[l1oip_cnt] && l1oip_cnt < MAX_CARDS) {
+               switch (type[l1oip_cnt] & 0xff) {
+               case 1:
+                       pri = 0;
+                       bundle = 0;
+                       break;
+               case 2:
+                       pri = 1;
+                       bundle = 0;
+                       break;
+               case 3:
+                       pri = 0;
+                       bundle = 1;
+                       break;
+               case 4:
+                       pri = 1;
+                       bundle = 1;
+                       break;
+               default:
+                       printk(KERN_ERR "Card type(%d) not supported.\n",
+                               type[l1oip_cnt] & 0xff);
+                       l1oip_cleanup();
+                       return -EINVAL;
+               }
+
+               if (debug & DEBUG_L1OIP_INIT)
+                       printk(KERN_DEBUG "%s: interface %d is %s with %s.\n",
+                               __func__, l1oip_cnt, pri?"PRI":"BRI",
+                               bundle?"bundled IP packet for all B-channels"
+                                :"seperate IP packets for every B-channel");
+
+               hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC);
+               if (!hc) {
+                       printk(KERN_ERR "No kmem for L1-over-IP driver.\n");
+                       l1oip_cleanup();
+                       return -ENOMEM;
+               }
+               INIT_WORK(&hc->workq, (void *)l1oip_send_bh);
+
+               spin_lock(&l1oip_lock);
+               list_add_tail(&hc->list, &l1oip_ilist);
+               spin_unlock(&l1oip_lock);
+
+               ret = init_card(hc, pri, bundle);
+               if (ret) {
+                       l1oip_cleanup();
+                       return ret;
+               }
+
+               l1oip_cnt++;
+       }
+       printk(KERN_INFO "%d virtual devices registered\n", l1oip_cnt);
+       return 0;
+}
+
+module_init(l1oip_init);
+module_exit(l1oip_cleanup);
+
diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c
new file mode 100644 (file)
index 0000000..fced1a2
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ *
+ * Author      Karsten Keil <kkeil@novell.com>
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/mISDNhw.h>
+#include "layer1.h"
+#include "fsm.h"
+
+static int *debug;
+
+struct layer1 {
+       u_long                  Flags;
+       struct FsmInst          l1m;
+       struct FsmTimer         timer;
+       int                     delay;
+       struct dchannel         *dch;
+       dchannel_l1callback     *dcb;
+};
+
+#define TIMER3_VALUE 7000
+
+static
+struct Fsm l1fsm_s = {NULL, 0, 0, NULL, NULL};
+
+enum {
+       ST_L1_F2,
+       ST_L1_F3,
+       ST_L1_F4,
+       ST_L1_F5,
+       ST_L1_F6,
+       ST_L1_F7,
+       ST_L1_F8,
+};
+
+#define L1S_STATE_COUNT (ST_L1_F8+1)
+
+static char *strL1SState[] =
+{
+       "ST_L1_F2",
+       "ST_L1_F3",
+       "ST_L1_F4",
+       "ST_L1_F5",
+       "ST_L1_F6",
+       "ST_L1_F7",
+       "ST_L1_F8",
+};
+
+enum {
+       EV_PH_ACTIVATE,
+       EV_PH_DEACTIVATE,
+       EV_RESET_IND,
+       EV_DEACT_CNF,
+       EV_DEACT_IND,
+       EV_POWER_UP,
+       EV_ANYSIG_IND,
+       EV_INFO2_IND,
+       EV_INFO4_IND,
+       EV_TIMER_DEACT,
+       EV_TIMER_ACT,
+       EV_TIMER3,
+};
+
+#define L1_EVENT_COUNT (EV_TIMER3 + 1)
+
+static char *strL1Event[] =
+{
+       "EV_PH_ACTIVATE",
+       "EV_PH_DEACTIVATE",
+       "EV_RESET_IND",
+       "EV_DEACT_CNF",
+       "EV_DEACT_IND",
+       "EV_POWER_UP",
+       "EV_ANYSIG_IND",
+       "EV_INFO2_IND",
+       "EV_INFO4_IND",
+       "EV_TIMER_DEACT",
+       "EV_TIMER_ACT",
+       "EV_TIMER3",
+};
+
+static void
+l1m_debug(struct FsmInst *fi, char *fmt, ...)
+{
+       struct layer1 *l1 = fi->userdata;
+       va_list va;
+
+       va_start(va, fmt);
+       printk(KERN_DEBUG "%s: ", l1->dch->dev.name);
+       vprintk(fmt, va);
+       printk("\n");
+       va_end(va);
+}
+
+static void
+l1_reset(struct FsmInst *fi, int event, void *arg)
+{
+       mISDN_FsmChangeState(fi, ST_L1_F3);
+}
+
+static void
+l1_deact_cnf(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       mISDN_FsmChangeState(fi, ST_L1_F3);
+       if (test_bit(FLG_L1_ACTIVATING, &l1->Flags))
+               l1->dcb(l1->dch, HW_POWERUP_REQ);
+}
+
+static void
+l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       mISDN_FsmChangeState(fi, ST_L1_F3);
+       mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
+       test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
+}
+
+static void
+l1_power_up_s(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       if (test_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
+               mISDN_FsmChangeState(fi, ST_L1_F4);
+               l1->dcb(l1->dch, INFO3_P8);
+       } else
+               mISDN_FsmChangeState(fi, ST_L1_F3);
+}
+
+static void
+l1_go_F5(struct FsmInst *fi, int event, void *arg)
+{
+       mISDN_FsmChangeState(fi, ST_L1_F5);
+}
+
+static void
+l1_go_F8(struct FsmInst *fi, int event, void *arg)
+{
+       mISDN_FsmChangeState(fi, ST_L1_F8);
+}
+
+static void
+l1_info2_ind(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       mISDN_FsmChangeState(fi, ST_L1_F6);
+       l1->dcb(l1->dch, INFO3_P8);
+}
+
+static void
+l1_info4_ind(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       mISDN_FsmChangeState(fi, ST_L1_F7);
+       l1->dcb(l1->dch, INFO3_P8);
+       if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))
+               mISDN_FsmDelTimer(&l1->timer, 4);
+       if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {
+               if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))
+                       mISDN_FsmDelTimer(&l1->timer, 3);
+               mISDN_FsmRestartTimer(&l1->timer, 110, EV_TIMER_ACT, NULL, 2);
+               test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);
+       }
+}
+
+static void
+l1_timer3(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags);
+       if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
+               if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
+                       l1->dcb(l1->dch, HW_D_NOBLOCKED);
+               l1->dcb(l1->dch, PH_DEACTIVATE_IND);
+       }
+       if (l1->l1m.state != ST_L1_F6) {
+               mISDN_FsmChangeState(fi, ST_L1_F3);
+               l1->dcb(l1->dch, HW_POWERUP_REQ);
+       }
+}
+
+static void
+l1_timer_act(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       test_and_clear_bit(FLG_L1_ACTTIMER, &l1->Flags);
+       test_and_set_bit(FLG_L1_ACTIVATED, &l1->Flags);
+       l1->dcb(l1->dch, PH_ACTIVATE_IND);
+}
+
+static void
+l1_timer_deact(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags);
+       test_and_clear_bit(FLG_L1_ACTIVATED, &l1->Flags);
+       if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
+               l1->dcb(l1->dch, HW_D_NOBLOCKED);
+       l1->dcb(l1->dch, PH_DEACTIVATE_IND);
+       l1->dcb(l1->dch, HW_DEACT_REQ);
+}
+
+static void
+l1_activate_s(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
+       test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
+       l1->dcb(l1->dch, HW_RESET_REQ);
+}
+
+static void
+l1_activate_no(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer1 *l1 = fi->userdata;
+
+       if ((!test_bit(FLG_L1_DEACTTIMER, &l1->Flags)) &&
+           (!test_bit(FLG_L1_T3RUN, &l1->Flags))) {
+               test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags);
+               if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
+                       l1->dcb(l1->dch, HW_D_NOBLOCKED);
+               l1->dcb(l1->dch, PH_DEACTIVATE_IND);
+       }
+}
+
+static struct FsmNode L1SFnList[] =
+{
+       {ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s},
+       {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
+       {ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},
+       {ST_L1_F3, EV_RESET_IND, l1_reset},
+       {ST_L1_F4, EV_RESET_IND, l1_reset},
+       {ST_L1_F5, EV_RESET_IND, l1_reset},
+       {ST_L1_F6, EV_RESET_IND, l1_reset},
+       {ST_L1_F7, EV_RESET_IND, l1_reset},
+       {ST_L1_F8, EV_RESET_IND, l1_reset},
+       {ST_L1_F3, EV_DEACT_CNF, l1_deact_cnf},
+       {ST_L1_F4, EV_DEACT_CNF, l1_deact_cnf},
+       {ST_L1_F5, EV_DEACT_CNF, l1_deact_cnf},
+       {ST_L1_F6, EV_DEACT_CNF, l1_deact_cnf},
+       {ST_L1_F7, EV_DEACT_CNF, l1_deact_cnf},
+       {ST_L1_F8, EV_DEACT_CNF, l1_deact_cnf},
+       {ST_L1_F6, EV_DEACT_IND, l1_deact_req_s},
+       {ST_L1_F7, EV_DEACT_IND, l1_deact_req_s},
+       {ST_L1_F8, EV_DEACT_IND, l1_deact_req_s},
+       {ST_L1_F3, EV_POWER_UP,  l1_power_up_s},
+       {ST_L1_F4, EV_ANYSIG_IND, l1_go_F5},
+       {ST_L1_F6, EV_ANYSIG_IND, l1_go_F8},
+       {ST_L1_F7, EV_ANYSIG_IND, l1_go_F8},
+       {ST_L1_F3, EV_INFO2_IND, l1_info2_ind},
+       {ST_L1_F4, EV_INFO2_IND, l1_info2_ind},
+       {ST_L1_F5, EV_INFO2_IND, l1_info2_ind},
+       {ST_L1_F7, EV_INFO2_IND, l1_info2_ind},
+       {ST_L1_F8, EV_INFO2_IND, l1_info2_ind},
+       {ST_L1_F3, EV_INFO4_IND, l1_info4_ind},
+       {ST_L1_F4, EV_INFO4_IND, l1_info4_ind},
+       {ST_L1_F5, EV_INFO4_IND, l1_info4_ind},
+       {ST_L1_F6, EV_INFO4_IND, l1_info4_ind},
+       {ST_L1_F8, EV_INFO4_IND, l1_info4_ind},
+       {ST_L1_F3, EV_TIMER3, l1_timer3},
+       {ST_L1_F4, EV_TIMER3, l1_timer3},
+       {ST_L1_F5, EV_TIMER3, l1_timer3},
+       {ST_L1_F6, EV_TIMER3, l1_timer3},
+       {ST_L1_F8, EV_TIMER3, l1_timer3},
+       {ST_L1_F7, EV_TIMER_ACT, l1_timer_act},
+       {ST_L1_F3, EV_TIMER_DEACT, l1_timer_deact},
+       {ST_L1_F4, EV_TIMER_DEACT, l1_timer_deact},
+       {ST_L1_F5, EV_TIMER_DEACT, l1_timer_deact},
+       {ST_L1_F6, EV_TIMER_DEACT, l1_timer_deact},
+       {ST_L1_F7, EV_TIMER_DEACT, l1_timer_deact},
+       {ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
+};
+
+static void
+release_l1(struct layer1 *l1) {
+       mISDN_FsmDelTimer(&l1->timer, 0);
+       if (l1->dch)
+               l1->dch->l1 = NULL;
+       module_put(THIS_MODULE);
+       kfree(l1);
+}
+
+int
+l1_event(struct layer1 *l1, u_int event)
+{
+       int             err = 0;
+
+       if (!l1)
+               return -EINVAL;
+       switch (event) {
+       case HW_RESET_IND:
+               mISDN_FsmEvent(&l1->l1m, EV_RESET_IND, NULL);
+               break;
+       case HW_DEACT_IND:
+               mISDN_FsmEvent(&l1->l1m, EV_DEACT_IND, NULL);
+               break;
+       case HW_POWERUP_IND:
+               mISDN_FsmEvent(&l1->l1m, EV_POWER_UP, NULL);
+               break;
+       case HW_DEACT_CNF:
+               mISDN_FsmEvent(&l1->l1m, EV_DEACT_CNF, NULL);
+               break;
+       case ANYSIGNAL:
+               mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
+               break;
+       case LOSTFRAMING:
+               mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
+               break;
+       case INFO2:
+               mISDN_FsmEvent(&l1->l1m, EV_INFO2_IND, NULL);
+               break;
+       case INFO4_P8:
+               mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
+               break;
+       case INFO4_P10:
+               mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
+               break;
+       case PH_ACTIVATE_REQ:
+               if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))
+                       l1->dcb(l1->dch, PH_ACTIVATE_IND);
+               else {
+                       test_and_set_bit(FLG_L1_ACTIVATING, &l1->Flags);
+                       mISDN_FsmEvent(&l1->l1m, EV_PH_ACTIVATE, NULL);
+               }
+               break;
+       case CLOSE_CHANNEL:
+               release_l1(l1);
+               break;
+       default:
+               if (*debug & DEBUG_L1)
+                       printk(KERN_DEBUG "%s %x unhandled\n",
+                           __func__, event);
+               err = -EINVAL;
+       }
+       return err;
+}
+EXPORT_SYMBOL(l1_event);
+
+int
+create_l1(struct dchannel *dch, dchannel_l1callback *dcb) {
+       struct layer1   *nl1;
+
+       nl1 = kzalloc(sizeof(struct layer1), GFP_ATOMIC);
+       if (!nl1) {
+               printk(KERN_ERR "kmalloc struct layer1 failed\n");
+               return -ENOMEM;
+       }
+       nl1->l1m.fsm = &l1fsm_s;
+       nl1->l1m.state = ST_L1_F3;
+       nl1->Flags = 0;
+       nl1->l1m.debug = *debug & DEBUG_L1_FSM;
+       nl1->l1m.userdata = nl1;
+       nl1->l1m.userint = 0;
+       nl1->l1m.printdebug = l1m_debug;
+       nl1->dch = dch;
+       nl1->dcb = dcb;
+       mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer);
+       __module_get(THIS_MODULE);
+       dch->l1 = nl1;
+       return 0;
+}
+EXPORT_SYMBOL(create_l1);
+
+int
+l1_init(u_int *deb)
+{
+       debug = deb;
+       l1fsm_s.state_count = L1S_STATE_COUNT;
+       l1fsm_s.event_count = L1_EVENT_COUNT;
+       l1fsm_s.strEvent = strL1Event;
+       l1fsm_s.strState = strL1SState;
+       mISDN_FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));
+       return 0;
+}
+
+void
+l1_cleanup(void)
+{
+       mISDN_FsmFree(&l1fsm_s);
+}
diff --git a/drivers/isdn/mISDN/layer1.h b/drivers/isdn/mISDN/layer1.h
new file mode 100644 (file)
index 0000000..9c8125f
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *
+ * Layer 1 defines
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define FLG_L1_ACTIVATING      1
+#define FLG_L1_ACTIVATED       2
+#define FLG_L1_DEACTTIMER      3
+#define FLG_L1_ACTTIMER                4
+#define FLG_L1_T3RUN           5
+#define FLG_L1_PULL_REQ                6
+#define FLG_L1_UINT            7
+#define FLG_L1_DBLOCKED                8
+
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
new file mode 100644 (file)
index 0000000..a7915a1
--- /dev/null
@@ -0,0 +1,2216 @@
+/*
+ *
+ * Author      Karsten Keil <kkeil@novell.com>
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "fsm.h"
+#include "layer2.h"
+
+static int *debug;
+
+static
+struct Fsm l2fsm = {NULL, 0, 0, NULL, NULL};
+
+static char *strL2State[] =
+{
+       "ST_L2_1",
+       "ST_L2_2",
+       "ST_L2_3",
+       "ST_L2_4",
+       "ST_L2_5",
+       "ST_L2_6",
+       "ST_L2_7",
+       "ST_L2_8",
+};
+
+enum {
+       EV_L2_UI,
+       EV_L2_SABME,
+       EV_L2_DISC,
+       EV_L2_DM,
+       EV_L2_UA,
+       EV_L2_FRMR,
+       EV_L2_SUPER,
+       EV_L2_I,
+       EV_L2_DL_DATA,
+       EV_L2_ACK_PULL,
+       EV_L2_DL_UNITDATA,
+       EV_L2_DL_ESTABLISH_REQ,
+       EV_L2_DL_RELEASE_REQ,
+       EV_L2_MDL_ASSIGN,
+       EV_L2_MDL_REMOVE,
+       EV_L2_MDL_ERROR,
+       EV_L1_DEACTIVATE,
+       EV_L2_T200,
+       EV_L2_T203,
+       EV_L2_SET_OWN_BUSY,
+       EV_L2_CLEAR_OWN_BUSY,
+       EV_L2_FRAME_ERROR,
+};
+
+#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR+1)
+
+static char *strL2Event[] =
+{
+       "EV_L2_UI",
+       "EV_L2_SABME",
+       "EV_L2_DISC",
+       "EV_L2_DM",
+       "EV_L2_UA",
+       "EV_L2_FRMR",
+       "EV_L2_SUPER",
+       "EV_L2_I",
+       "EV_L2_DL_DATA",
+       "EV_L2_ACK_PULL",
+       "EV_L2_DL_UNITDATA",
+       "EV_L2_DL_ESTABLISH_REQ",
+       "EV_L2_DL_RELEASE_REQ",
+       "EV_L2_MDL_ASSIGN",
+       "EV_L2_MDL_REMOVE",
+       "EV_L2_MDL_ERROR",
+       "EV_L1_DEACTIVATE",
+       "EV_L2_T200",
+       "EV_L2_T203",
+       "EV_L2_SET_OWN_BUSY",
+       "EV_L2_CLEAR_OWN_BUSY",
+       "EV_L2_FRAME_ERROR",
+};
+
+static void
+l2m_debug(struct FsmInst *fi, char *fmt, ...)
+{
+       struct layer2 *l2 = fi->userdata;
+       va_list va;
+
+       if (!(*debug & DEBUG_L2_FSM))
+               return;
+       va_start(va, fmt);
+       printk(KERN_DEBUG "l2 (tei %d): ", l2->tei);
+       vprintk(fmt, va);
+       printk("\n");
+       va_end(va);
+}
+
+inline u_int
+l2headersize(struct layer2 *l2, int ui)
+{
+       return ((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) +
+               (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);
+}
+
+inline u_int
+l2addrsize(struct layer2 *l2)
+{
+       return test_bit(FLG_LAPD, &l2->flag) ? 2 : 1;
+}
+
+static u_int
+l2_newid(struct layer2 *l2)
+{
+       u_int   id;
+
+       id = l2->next_id++;
+       if (id == 0x7fff)
+               l2->next_id = 1;
+       id <<= 16;
+       id |= l2->tei << 8;
+       id |= l2->sapi;
+       return id;
+}
+
+static void
+l2up(struct layer2 *l2, u_int prim, struct sk_buff *skb)
+{
+       int     err;
+
+       if (!l2->up)
+               return;
+       mISDN_HEAD_PRIM(skb) = prim;
+       mISDN_HEAD_ID(skb) = (l2->ch.nr << 16) | l2->ch.addr;
+       err = l2->up->send(l2->up, skb);
+       if (err) {
+               printk(KERN_WARNING "%s: err=%d\n", __func__, err);
+               dev_kfree_skb(skb);
+       }
+}
+
+static void
+l2up_create(struct layer2 *l2, u_int prim, int len, void *arg)
+{
+       struct sk_buff  *skb;
+       struct mISDNhead *hh;
+       int             err;
+
+       if (!l2->up)
+               return;
+       skb = mI_alloc_skb(len, GFP_ATOMIC);
+       if (!skb)
+               return;
+       hh = mISDN_HEAD_P(skb);
+       hh->prim = prim;
+       hh->id = (l2->ch.nr << 16) | l2->ch.addr;
+       if (len)
+               memcpy(skb_put(skb, len), arg, len);
+       err = l2->up->send(l2->up, skb);
+       if (err) {
+               printk(KERN_WARNING "%s: err=%d\n", __func__, err);
+               dev_kfree_skb(skb);
+       }
+}
+
+static int
+l2down_skb(struct layer2 *l2, struct sk_buff *skb) {
+       int ret;
+
+       ret = l2->ch.recv(l2->ch.peer, skb);
+       if (ret && (*debug & DEBUG_L2_RECV))
+               printk(KERN_DEBUG "l2down_skb: ret(%d)\n", ret);
+       return ret;
+}
+
+static int
+l2down_raw(struct layer2 *l2, struct sk_buff *skb)
+{
+       struct mISDNhead *hh = mISDN_HEAD_P(skb);
+
+       if (hh->prim == PH_DATA_REQ) {
+               if (test_and_set_bit(FLG_L1_NOTREADY, &l2->flag)) {
+                       skb_queue_tail(&l2->down_queue, skb);
+                       return 0;
+               }
+               l2->down_id = mISDN_HEAD_ID(skb);
+       }
+       return l2down_skb(l2, skb);
+}
+
+static int
+l2down(struct layer2 *l2, u_int prim, u_int id, struct sk_buff *skb)
+{
+       struct mISDNhead *hh = mISDN_HEAD_P(skb);
+
+       hh->prim = prim;
+       hh->id = id;
+       return l2down_raw(l2, skb);
+}
+
+static int
+l2down_create(struct layer2 *l2, u_int prim, u_int id, int len, void *arg)
+{
+       struct sk_buff  *skb;
+       int             err;
+       struct mISDNhead *hh;
+
+       skb = mI_alloc_skb(len, GFP_ATOMIC);
+       if (!skb)
+               return -ENOMEM;
+       hh = mISDN_HEAD_P(skb);
+       hh->prim = prim;
+       hh->id = id;
+       if (len)
+               memcpy(skb_put(skb, len), arg, len);
+       err = l2down_raw(l2, skb);
+       if (err)
+               dev_kfree_skb(skb);
+       return err;
+}
+
+static int
+ph_data_confirm(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) {
+       struct sk_buff *nskb = skb;
+       int ret = -EAGAIN;
+
+       if (test_bit(FLG_L1_NOTREADY, &l2->flag)) {
+               if (hh->id == l2->down_id) {
+                       nskb = skb_dequeue(&l2->down_queue);
+                       if (nskb) {
+                               l2->down_id = mISDN_HEAD_ID(nskb);
+                               if (l2down_skb(l2, nskb)) {
+                                       dev_kfree_skb(nskb);
+                                       l2->down_id = MISDN_ID_NONE;
+                               }
+                       } else
+                               l2->down_id = MISDN_ID_NONE;
+                       if (ret) {
+                               dev_kfree_skb(skb);
+                               ret = 0;
+                       }
+                       if (l2->down_id == MISDN_ID_NONE) {
+                               test_and_clear_bit(FLG_L1_NOTREADY, &l2->flag);
+                               mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL);
+                       }
+               }
+       }
+       if (!test_and_set_bit(FLG_L1_NOTREADY, &l2->flag)) {
+               nskb = skb_dequeue(&l2->down_queue);
+               if (nskb) {
+                       l2->down_id = mISDN_HEAD_ID(nskb);
+                       if (l2down_skb(l2, nskb)) {
+                               dev_kfree_skb(nskb);
+                               l2->down_id = MISDN_ID_NONE;
+                               test_and_clear_bit(FLG_L1_NOTREADY, &l2->flag);
+                       }
+               } else
+                       test_and_clear_bit(FLG_L1_NOTREADY, &l2->flag);
+       }
+       return ret;
+}
+
+static int
+l2mgr(struct layer2 *l2, u_int prim, void *arg) {
+       long c = (long)arg;
+
+       printk(KERN_WARNING
+           "l2mgr: addr:%x prim %x %c\n", l2->id, prim, (char)c);
+       if (test_bit(FLG_LAPD, &l2->flag) &&
+               !test_bit(FLG_FIXED_TEI, &l2->flag)) {
+               switch (c) {
+               case 'C':
+               case 'D':
+               case 'G':
+               case 'H':
+                       l2_tei(l2, prim, (u_long)arg);
+                       break;
+               }
+       }
+       return 0;
+}
+
+static void
+set_peer_busy(struct layer2 *l2) {
+       test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
+       if (skb_queue_len(&l2->i_queue) || skb_queue_len(&l2->ui_queue))
+               test_and_set_bit(FLG_L2BLOCK, &l2->flag);
+}
+
+static void
+clear_peer_busy(struct layer2 *l2) {
+       if (test_and_clear_bit(FLG_PEER_BUSY, &l2->flag))
+               test_and_clear_bit(FLG_L2BLOCK, &l2->flag);
+}
+
+static void
+InitWin(struct layer2 *l2)
+{
+       int i;
+
+       for (i = 0; i < MAX_WINDOW; i++)
+               l2->windowar[i] = NULL;
+}
+
+static int
+freewin(struct layer2 *l2)
+{
+       int i, cnt = 0;
+
+       for (i = 0; i < MAX_WINDOW; i++) {
+               if (l2->windowar[i]) {
+                       cnt++;
+                       dev_kfree_skb(l2->windowar[i]);
+                       l2->windowar[i] = NULL;
+               }
+       }
+       return cnt;
+}
+
+static void
+ReleaseWin(struct layer2 *l2)
+{
+       int cnt = freewin(l2);
+
+       if (cnt)
+               printk(KERN_WARNING
+                   "isdnl2 freed %d skbuffs in release\n", cnt);
+}
+
+inline unsigned int
+cansend(struct layer2 *l2)
+{
+       unsigned int p1;
+
+       if (test_bit(FLG_MOD128, &l2->flag))
+               p1 = (l2->vs - l2->va) % 128;
+       else
+               p1 = (l2->vs - l2->va) % 8;
+       return (p1 < l2->window) && !test_bit(FLG_PEER_BUSY, &l2->flag);
+}
+
+inline void
+clear_exception(struct layer2 *l2)
+{
+       test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
+       test_and_clear_bit(FLG_REJEXC, &l2->flag);
+       test_and_clear_bit(FLG_OWN_BUSY, &l2->flag);
+       clear_peer_busy(l2);
+}
+
+static int
+sethdraddr(struct layer2 *l2, u_char *header, int rsp)
+{
+       u_char *ptr = header;
+       int crbit = rsp;
+
+       if (test_bit(FLG_LAPD, &l2->flag)) {
+               if (test_bit(FLG_LAPD_NET, &l2->flag))
+                       crbit = !crbit;
+               *ptr++ = (l2->sapi << 2) | (crbit ? 2 : 0);
+               *ptr++ = (l2->tei << 1) | 1;
+               return 2;
+       } else {
+               if (test_bit(FLG_ORIG, &l2->flag))
+                       crbit = !crbit;
+               if (crbit)
+                       *ptr++ = l2->addr.B;
+               else
+                       *ptr++ = l2->addr.A;
+               return 1;
+       }
+}
+
+static inline void
+enqueue_super(struct layer2 *l2, struct sk_buff *skb)
+{
+       if (l2down(l2, PH_DATA_REQ, l2_newid(l2), skb))
+               dev_kfree_skb(skb);
+}
+
+static inline void
+enqueue_ui(struct layer2 *l2, struct sk_buff *skb)
+{
+       if (l2->tm)
+               l2_tei(l2, MDL_STATUS_UI_IND, 0);
+       if (l2down(l2, PH_DATA_REQ, l2_newid(l2), skb))
+               dev_kfree_skb(skb);
+}
+
+inline int
+IsUI(u_char *data)
+{
+       return (data[0] & 0xef) == UI;
+}
+
+inline int
+IsUA(u_char *data)
+{
+       return (data[0] & 0xef) == UA;
+}
+
+inline int
+IsDM(u_char *data)
+{
+       return (data[0] & 0xef) == DM;
+}
+
+inline int
+IsDISC(u_char *data)
+{
+       return (data[0] & 0xef) == DISC;
+}
+
+inline int
+IsRR(u_char *data, struct layer2 *l2)
+{
+       if (test_bit(FLG_MOD128, &l2->flag))
+               return data[0] == RR;
+       else
+               return (data[0] & 0xf) == 1;
+}
+
+inline int
+IsSFrame(u_char *data, struct layer2 *l2)
+{
+       register u_char d = *data;
+
+       if (!test_bit(FLG_MOD128, &l2->flag))
+               d &= 0xf;
+       return ((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c);
+}
+
+inline int
+IsSABME(u_char *data, struct layer2 *l2)
+{
+       u_char d = data[0] & ~0x10;
+
+       return test_bit(FLG_MOD128, &l2->flag) ? d == SABME : d == SABM;
+}
+
+inline int
+IsREJ(u_char *data, struct layer2 *l2)
+{
+       return test_bit(FLG_MOD128, &l2->flag) ?
+               data[0] == REJ : (data[0] & 0xf) == REJ;
+}
+
+inline int
+IsFRMR(u_char *data)
+{
+       return (data[0] & 0xef) == FRMR;
+}
+
+inline int
+IsRNR(u_char *data, struct layer2 *l2)
+{
+       return test_bit(FLG_MOD128, &l2->flag) ?
+           data[0] == RNR : (data[0] & 0xf) == RNR;
+}
+
+int
+iframe_error(struct layer2 *l2, struct sk_buff *skb)
+{
+       u_int   i;
+       int     rsp = *skb->data & 0x2;
+
+       i = l2addrsize(l2) + (test_bit(FLG_MOD128, &l2->flag) ? 2 : 1);
+       if (test_bit(FLG_ORIG, &l2->flag))
+               rsp = !rsp;
+       if (rsp)
+               return 'L';
+       if (skb->len < i)
+               return 'N';
+       if ((skb->len - i) > l2->maxlen)
+               return 'O';
+       return 0;
+}
+
+int
+super_error(struct layer2 *l2, struct sk_buff *skb)
+{
+       if (skb->len != l2addrsize(l2) +
+           (test_bit(FLG_MOD128, &l2->flag) ? 2 : 1))
+               return 'N';
+       return 0;
+}
+
+int
+unnum_error(struct layer2 *l2, struct sk_buff *skb, int wantrsp)
+{
+       int rsp = (*skb->data & 0x2) >> 1;
+       if (test_bit(FLG_ORIG, &l2->flag))
+               rsp = !rsp;
+       if (rsp != wantrsp)
+               return 'L';
+       if (skb->len != l2addrsize(l2) + 1)
+               return 'N';
+       return 0;
+}
+
+int
+UI_error(struct layer2 *l2, struct sk_buff *skb)
+{
+       int rsp = *skb->data & 0x2;
+       if (test_bit(FLG_ORIG, &l2->flag))
+               rsp = !rsp;
+       if (rsp)
+               return 'L';
+       if (skb->len > l2->maxlen + l2addrsize(l2) + 1)
+               return 'O';
+       return 0;
+}
+
+int
+FRMR_error(struct layer2 *l2, struct sk_buff *skb)
+{
+       u_int   headers = l2addrsize(l2) + 1;
+       u_char  *datap = skb->data + headers;
+       int     rsp = *skb->data & 0x2;
+
+       if (test_bit(FLG_ORIG, &l2->flag))
+               rsp = !rsp;
+       if (!rsp)
+               return 'L';
+       if (test_bit(FLG_MOD128, &l2->flag)) {
+               if (skb->len < headers + 5)
+                       return 'N';
+               else if (*debug & DEBUG_L2)
+                       l2m_debug(&l2->l2m,
+                           "FRMR information %2x %2x %2x %2x %2x",
+                           datap[0], datap[1], datap[2], datap[3], datap[4]);
+       } else {
+               if (skb->len < headers + 3)
+                       return 'N';
+               else if (*debug & DEBUG_L2)
+                       l2m_debug(&l2->l2m,
+                           "FRMR information %2x %2x %2x",
+                           datap[0], datap[1], datap[2]);
+       }
+       return 0;
+}
+
+static unsigned int
+legalnr(struct layer2 *l2, unsigned int nr)
+{
+       if (test_bit(FLG_MOD128, &l2->flag))
+               return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128);
+       else
+               return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8);
+}
+
+static void
+setva(struct layer2 *l2, unsigned int nr)
+{
+       struct sk_buff  *skb;
+
+       while (l2->va != nr) {
+               l2->va++;
+               if (test_bit(FLG_MOD128, &l2->flag))
+                       l2->va %= 128;
+               else
+                       l2->va %= 8;
+               if (l2->windowar[l2->sow]) {
+                       skb_trim(l2->windowar[l2->sow], 0);
+                       skb_queue_tail(&l2->tmp_queue, l2->windowar[l2->sow]);
+                       l2->windowar[l2->sow] = NULL;
+               }
+               l2->sow = (l2->sow + 1) % l2->window;
+       }
+       skb = skb_dequeue(&l2->tmp_queue);
+       while (skb) {
+               dev_kfree_skb(skb);
+               skb = skb_dequeue(&l2->tmp_queue);
+       }
+}
+
+static void
+send_uframe(struct layer2 *l2, struct sk_buff *skb, u_char cmd, u_char cr)
+{
+       u_char tmp[MAX_L2HEADER_LEN];
+       int i;
+
+       i = sethdraddr(l2, tmp, cr);
+       tmp[i++] = cmd;
+       if (skb)
+               skb_trim(skb, 0);
+       else {
+               skb = mI_alloc_skb(i, GFP_ATOMIC);
+               if (!skb) {
+                       printk(KERN_WARNING "%s: can't alloc skbuff\n",
+                               __func__);
+                       return;
+               }
+       }
+       memcpy(skb_put(skb, i), tmp, i);
+       enqueue_super(l2, skb);
+}
+
+
+inline u_char
+get_PollFlag(struct layer2 *l2, struct sk_buff *skb)
+{
+       return skb->data[l2addrsize(l2)] & 0x10;
+}
+
+inline u_char
+get_PollFlagFree(struct layer2 *l2, struct sk_buff *skb)
+{
+       u_char PF;
+
+       PF = get_PollFlag(l2, skb);
+       dev_kfree_skb(skb);
+       return PF;
+}
+
+inline void
+start_t200(struct layer2 *l2, int i)
+{
+       mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, i);
+       test_and_set_bit(FLG_T200_RUN, &l2->flag);
+}
+
+inline void
+restart_t200(struct layer2 *l2, int i)
+{
+       mISDN_FsmRestartTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, i);
+       test_and_set_bit(FLG_T200_RUN, &l2->flag);
+}
+
+inline void
+stop_t200(struct layer2 *l2, int i)
+{
+       if (test_and_clear_bit(FLG_T200_RUN, &l2->flag))
+               mISDN_FsmDelTimer(&l2->t200, i);
+}
+
+inline void
+st5_dl_release_l2l3(struct layer2 *l2)
+{
+       int pr;
+
+       if (test_and_clear_bit(FLG_PEND_REL, &l2->flag))
+               pr = DL_RELEASE_CNF;
+       else
+               pr = DL_RELEASE_IND;
+       l2up_create(l2, pr, 0, NULL);
+}
+
+inline void
+lapb_dl_release_l2l3(struct layer2 *l2, int f)
+{
+       if (test_bit(FLG_LAPB, &l2->flag))
+               l2down_create(l2, PH_DEACTIVATE_REQ, l2_newid(l2), 0, NULL);
+       l2up_create(l2, f, 0, NULL);
+}
+
+static void
+establishlink(struct FsmInst *fi)
+{
+       struct layer2 *l2 = fi->userdata;
+       u_char cmd;
+
+       clear_exception(l2);
+       l2->rc = 0;
+       cmd = (test_bit(FLG_MOD128, &l2->flag) ? SABME : SABM) | 0x10;
+       send_uframe(l2, NULL, cmd, CMD);
+       mISDN_FsmDelTimer(&l2->t203, 1);
+       restart_t200(l2, 1);
+       test_and_clear_bit(FLG_PEND_REL, &l2->flag);
+       freewin(l2);
+       mISDN_FsmChangeState(fi, ST_L2_5);
+}
+
+static void
+l2_mdl_error_ua(struct FsmInst *fi, int event, void *arg)
+{
+       struct sk_buff *skb = arg;
+       struct layer2 *l2 = fi->userdata;
+
+       if (get_PollFlagFree(l2, skb))
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'C');
+       else
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'D');
+
+}
+
+static void
+l2_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
+{
+       struct sk_buff *skb = arg;
+       struct layer2 *l2 = fi->userdata;
+
+       if (get_PollFlagFree(l2, skb))
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'B');
+       else {
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'E');
+               establishlink(fi);
+               test_and_clear_bit(FLG_L3_INIT, &l2->flag);
+       }
+}
+
+static void
+l2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
+{
+       struct sk_buff *skb = arg;
+       struct layer2 *l2 = fi->userdata;
+
+       if (get_PollFlagFree(l2, skb))
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'B');
+       else
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'E');
+       establishlink(fi);
+       test_and_clear_bit(FLG_L3_INIT, &l2->flag);
+}
+
+static void
+l2_go_st3(struct FsmInst *fi, int event, void *arg)
+{
+       dev_kfree_skb((struct sk_buff *)arg);
+       mISDN_FsmChangeState(fi, ST_L2_3);
+}
+
+static void
+l2_mdl_assign(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2   *l2 = fi->userdata;
+
+       mISDN_FsmChangeState(fi, ST_L2_3);
+       dev_kfree_skb((struct sk_buff *)arg);
+       l2_tei(l2, MDL_ASSIGN_IND, 0);
+}
+
+static void
+l2_queue_ui_assign(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_tail(&l2->ui_queue, skb);
+       mISDN_FsmChangeState(fi, ST_L2_2);
+       l2_tei(l2, MDL_ASSIGN_IND, 0);
+}
+
+static void
+l2_queue_ui(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_tail(&l2->ui_queue, skb);
+}
+
+static void
+tx_ui(struct layer2 *l2)
+{
+       struct sk_buff *skb;
+       u_char header[MAX_L2HEADER_LEN];
+       int i;
+
+       i = sethdraddr(l2, header, CMD);
+       if (test_bit(FLG_LAPD_NET, &l2->flag))
+               header[1] = 0xff; /* tei 127 */
+       header[i++] = UI;
+       while ((skb = skb_dequeue(&l2->ui_queue))) {
+               memcpy(skb_push(skb, i), header, i);
+               enqueue_ui(l2, skb);
+       }
+}
+
+static void
+l2_send_ui(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_tail(&l2->ui_queue, skb);
+       tx_ui(l2);
+}
+
+static void
+l2_got_ui(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_pull(skb, l2headersize(l2, 1));
+/*
+ *             in states 1-3 for broadcast
+ */
+
+       if (l2->tm)
+               l2_tei(l2, MDL_STATUS_UI_IND, 0);
+       l2up(l2, DL_UNITDATA_IND, skb);
+}
+
+static void
+l2_establish(struct FsmInst *fi, int event, void *arg)
+{
+       struct sk_buff *skb = arg;
+       struct layer2 *l2 = fi->userdata;
+
+       establishlink(fi);
+       test_and_set_bit(FLG_L3_INIT, &l2->flag);
+       dev_kfree_skb(skb);
+}
+
+static void
+l2_discard_i_setl3(struct FsmInst *fi, int event, void *arg)
+{
+       struct sk_buff *skb = arg;
+       struct layer2 *l2 = fi->userdata;
+
+       skb_queue_purge(&l2->i_queue);
+       test_and_set_bit(FLG_L3_INIT, &l2->flag);
+       test_and_clear_bit(FLG_PEND_REL, &l2->flag);
+       dev_kfree_skb(skb);
+}
+
+static void
+l2_l3_reestablish(struct FsmInst *fi, int event, void *arg)
+{
+       struct sk_buff *skb = arg;
+       struct layer2 *l2 = fi->userdata;
+
+       skb_queue_purge(&l2->i_queue);
+       establishlink(fi);
+       test_and_set_bit(FLG_L3_INIT, &l2->flag);
+       dev_kfree_skb(skb);
+}
+
+static void
+l2_release(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_trim(skb, 0);
+       l2up(l2, DL_RELEASE_CNF, skb);
+}
+
+static void
+l2_pend_rel(struct FsmInst *fi, int event, void *arg)
+{
+       struct sk_buff *skb = arg;
+       struct layer2 *l2 = fi->userdata;
+
+       test_and_set_bit(FLG_PEND_REL, &l2->flag);
+       dev_kfree_skb(skb);
+}
+
+static void
+l2_disconnect(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_purge(&l2->i_queue);
+       freewin(l2);
+       mISDN_FsmChangeState(fi, ST_L2_6);
+       l2->rc = 0;
+       send_uframe(l2, NULL, DISC | 0x10, CMD);
+       mISDN_FsmDelTimer(&l2->t203, 1);
+       restart_t200(l2, 2);
+       if (skb)
+               dev_kfree_skb(skb);
+}
+
+static void
+l2_start_multi(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2   *l2 = fi->userdata;
+       struct sk_buff  *skb = arg;
+
+       l2->vs = 0;
+       l2->va = 0;
+       l2->vr = 0;
+       l2->sow = 0;
+       clear_exception(l2);
+       send_uframe(l2, NULL, UA | get_PollFlag(l2, skb), RSP);
+       mISDN_FsmChangeState(fi, ST_L2_7);
+       mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3);
+       skb_trim(skb, 0);
+       l2up(l2, DL_ESTABLISH_IND, skb);
+       if (l2->tm)
+               l2_tei(l2, MDL_STATUS_UP_IND, 0);
+}
+
+static void
+l2_send_UA(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP);
+}
+
+static void
+l2_send_DM(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       send_uframe(l2, skb, DM | get_PollFlag(l2, skb), RSP);
+}
+
+static void
+l2_restart_multi(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2   *l2 = fi->userdata;
+       struct sk_buff  *skb = arg;
+       int             est = 0;
+
+       send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP);
+
+       l2mgr(l2, MDL_ERROR_IND, (void *) 'F');
+
+       if (l2->vs != l2->va) {
+               skb_queue_purge(&l2->i_queue);
+               est = 1;
+       }
+
+       clear_exception(l2);
+       l2->vs = 0;
+       l2->va = 0;
+       l2->vr = 0;
+       l2->sow = 0;
+       mISDN_FsmChangeState(fi, ST_L2_7);
+       stop_t200(l2, 3);
+       mISDN_FsmRestartTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3);
+
+       if (est)
+               l2up_create(l2, DL_ESTABLISH_IND, 0, NULL);
+/*             mISDN_queue_data(&l2->inst, l2->inst.id | MSG_BROADCAST,
+ *                 MGR_SHORTSTATUS | INDICATION, SSTATUS_L2_ESTABLISHED,
+ *                 0, NULL, 0);
+ */
+       if (skb_queue_len(&l2->i_queue) && cansend(l2))
+               mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
+}
+
+static void
+l2_stop_multi(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2   *l2 = fi->userdata;
+       struct sk_buff  *skb = arg;
+
+       mISDN_FsmChangeState(fi, ST_L2_4);
+       mISDN_FsmDelTimer(&l2->t203, 3);
+       stop_t200(l2, 4);
+
+       send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP);
+       skb_queue_purge(&l2->i_queue);
+       freewin(l2);
+       lapb_dl_release_l2l3(l2, DL_RELEASE_IND);
+       if (l2->tm)
+               l2_tei(l2, MDL_STATUS_DOWN_IND, 0);
+}
+
+static void
+l2_connected(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2   *l2 = fi->userdata;
+       struct sk_buff  *skb = arg;
+       int pr = -1;
+
+       if (!get_PollFlag(l2, skb)) {
+               l2_mdl_error_ua(fi, event, arg);
+               return;
+       }
+       dev_kfree_skb(skb);
+       if (test_and_clear_bit(FLG_PEND_REL, &l2->flag))
+               l2_disconnect(fi, event, NULL);
+       if (test_and_clear_bit(FLG_L3_INIT, &l2->flag)) {
+               pr = DL_ESTABLISH_CNF;
+       } else if (l2->vs != l2->va) {
+               skb_queue_purge(&l2->i_queue);
+               pr = DL_ESTABLISH_IND;
+       }
+       stop_t200(l2, 5);
+       l2->vr = 0;
+       l2->vs = 0;
+       l2->va = 0;
+       l2->sow = 0;
+       mISDN_FsmChangeState(fi, ST_L2_7);
+       mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 4);
+       if (pr != -1)
+               l2up_create(l2, pr, 0, NULL);
+
+       if (skb_queue_len(&l2->i_queue) && cansend(l2))
+               mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
+
+       if (l2->tm)
+               l2_tei(l2, MDL_STATUS_UP_IND, 0);
+}
+
+static void
+l2_released(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       if (!get_PollFlag(l2, skb)) {
+               l2_mdl_error_ua(fi, event, arg);
+               return;
+       }
+       dev_kfree_skb(skb);
+       stop_t200(l2, 6);
+       lapb_dl_release_l2l3(l2, DL_RELEASE_CNF);
+       mISDN_FsmChangeState(fi, ST_L2_4);
+       if (l2->tm)
+               l2_tei(l2, MDL_STATUS_DOWN_IND, 0);
+}
+
+static void
+l2_reestablish(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       if (!get_PollFlagFree(l2, skb)) {
+               establishlink(fi);
+               test_and_set_bit(FLG_L3_INIT, &l2->flag);
+       }
+}
+
+static void
+l2_st5_dm_release(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       if (get_PollFlagFree(l2, skb)) {
+               stop_t200(l2, 7);
+               if (!test_bit(FLG_L3_INIT, &l2->flag))
+                       skb_queue_purge(&l2->i_queue);
+               if (test_bit(FLG_LAPB, &l2->flag))
+                       l2down_create(l2, PH_DEACTIVATE_REQ,
+                               l2_newid(l2), 0, NULL);
+               st5_dl_release_l2l3(l2);
+               mISDN_FsmChangeState(fi, ST_L2_4);
+               if (l2->tm)
+                       l2_tei(l2, MDL_STATUS_DOWN_IND, 0);
+       }
+}
+
+static void
+l2_st6_dm_release(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       if (get_PollFlagFree(l2, skb)) {
+               stop_t200(l2, 8);
+               lapb_dl_release_l2l3(l2, DL_RELEASE_CNF);
+               mISDN_FsmChangeState(fi, ST_L2_4);
+               if (l2->tm)
+                       l2_tei(l2, MDL_STATUS_DOWN_IND, 0);
+       }
+}
+
+void
+enquiry_cr(struct layer2 *l2, u_char typ, u_char cr, u_char pf)
+{
+       struct sk_buff *skb;
+       u_char tmp[MAX_L2HEADER_LEN];
+       int i;
+
+       i = sethdraddr(l2, tmp, cr);
+       if (test_bit(FLG_MOD128, &l2->flag)) {
+               tmp[i++] = typ;
+               tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0);
+       } else
+               tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
+       skb = mI_alloc_skb(i, GFP_ATOMIC);
+       if (!skb) {
+               printk(KERN_WARNING
+                   "isdnl2 can't alloc sbbuff for enquiry_cr\n");
+               return;
+       }
+       memcpy(skb_put(skb, i), tmp, i);
+       enqueue_super(l2, skb);
+}
+
+inline void
+enquiry_response(struct layer2 *l2)
+{
+       if (test_bit(FLG_OWN_BUSY, &l2->flag))
+               enquiry_cr(l2, RNR, RSP, 1);
+       else
+               enquiry_cr(l2, RR, RSP, 1);
+       test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
+}
+
+inline void
+transmit_enquiry(struct layer2 *l2)
+{
+       if (test_bit(FLG_OWN_BUSY, &l2->flag))
+               enquiry_cr(l2, RNR, CMD, 1);
+       else
+               enquiry_cr(l2, RR, CMD, 1);
+       test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
+       start_t200(l2, 9);
+}
+
+
+static void
+nrerrorrecovery(struct FsmInst *fi)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       l2mgr(l2, MDL_ERROR_IND, (void *) 'J');
+       establishlink(fi);
+       test_and_clear_bit(FLG_L3_INIT, &l2->flag);
+}
+
+static void
+invoke_retransmission(struct layer2 *l2, unsigned int nr)
+{
+       u_int   p1;
+
+       if (l2->vs != nr) {
+               while (l2->vs != nr) {
+                       (l2->vs)--;
+                       if (test_bit(FLG_MOD128, &l2->flag)) {
+                               l2->vs %= 128;
+                               p1 = (l2->vs - l2->va) % 128;
+                       } else {
+                               l2->vs %= 8;
+                               p1 = (l2->vs - l2->va) % 8;
+                       }
+                       p1 = (p1 + l2->sow) % l2->window;
+                       if (l2->windowar[p1])
+                               skb_queue_head(&l2->i_queue, l2->windowar[p1]);
+                       else
+                               printk(KERN_WARNING
+                                   "%s: windowar[%d] is NULL\n",
+                                   __func__, p1);
+                       l2->windowar[p1] = NULL;
+               }
+               mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL);
+       }
+}
+
+static void
+l2_st7_got_super(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+       int PollFlag, rsp, typ = RR;
+       unsigned int nr;
+
+       rsp = *skb->data & 0x2;
+       if (test_bit(FLG_ORIG, &l2->flag))
+               rsp = !rsp;
+
+       skb_pull(skb, l2addrsize(l2));
+       if (IsRNR(skb->data, l2)) {
+               set_peer_busy(l2);
+               typ = RNR;
+       } else
+               clear_peer_busy(l2);
+       if (IsREJ(skb->data, l2))
+               typ = REJ;
+
+       if (test_bit(FLG_MOD128, &l2->flag)) {
+               PollFlag = (skb->data[1] & 0x1) == 0x1;
+               nr = skb->data[1] >> 1;
+       } else {
+               PollFlag = (skb->data[0] & 0x10);
+               nr = (skb->data[0] >> 5) & 0x7;
+       }
+       dev_kfree_skb(skb);
+
+       if (PollFlag) {
+               if (rsp)
+                       l2mgr(l2, MDL_ERROR_IND, (void *) 'A');
+               else
+                       enquiry_response(l2);
+       }
+       if (legalnr(l2, nr)) {
+               if (typ == REJ) {
+                       setva(l2, nr);
+                       invoke_retransmission(l2, nr);
+                       stop_t200(l2, 10);
+                       if (mISDN_FsmAddTimer(&l2->t203, l2->T203,
+                                       EV_L2_T203, NULL, 6))
+                               l2m_debug(&l2->l2m, "Restart T203 ST7 REJ");
+               } else if ((nr == l2->vs) && (typ == RR)) {
+                       setva(l2, nr);
+                       stop_t200(l2, 11);
+                       mISDN_FsmRestartTimer(&l2->t203, l2->T203,
+                                       EV_L2_T203, NULL, 7);
+               } else if ((l2->va != nr) || (typ == RNR)) {
+                       setva(l2, nr);
+                       if (typ != RR)
+                               mISDN_FsmDelTimer(&l2->t203, 9);
+                       restart_t200(l2, 12);
+               }
+               if (skb_queue_len(&l2->i_queue) && (typ == RR))
+                       mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
+       } else
+               nrerrorrecovery(fi);
+}
+
+static void
+l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       if (!test_bit(FLG_L3_INIT, &l2->flag))
+               skb_queue_tail(&l2->i_queue, skb);
+       else
+               dev_kfree_skb(skb);
+}
+
+static void
+l2_feed_i_pull(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_tail(&l2->i_queue, skb);
+       mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
+}
+
+static void
+l2_feed_iqueue(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_tail(&l2->i_queue, skb);
+}
+
+static void
+l2_got_iframe(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2   *l2 = fi->userdata;
+       struct sk_buff  *skb = arg;
+       int             PollFlag, i;
+       u_int           ns, nr;
+
+       i = l2addrsize(l2);
+       if (test_bit(FLG_MOD128, &l2->flag)) {
+               PollFlag = ((skb->data[i + 1] & 0x1) == 0x1);
+               ns = skb->data[i] >> 1;
+               nr = (skb->data[i + 1] >> 1) & 0x7f;
+       } else {
+               PollFlag = (skb->data[i] & 0x10);
+               ns = (skb->data[i] >> 1) & 0x7;
+               nr = (skb->data[i] >> 5) & 0x7;
+       }
+       if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
+               dev_kfree_skb(skb);
+               if (PollFlag)
+                       enquiry_response(l2);
+       } else {
+               if (l2->vr == ns) {
+                       l2->vr++;
+                       if (test_bit(FLG_MOD128, &l2->flag))
+                               l2->vr %= 128;
+                       else
+                               l2->vr %= 8;
+                       test_and_clear_bit(FLG_REJEXC, &l2->flag);
+                       if (PollFlag)
+                               enquiry_response(l2);
+                       else
+                               test_and_set_bit(FLG_ACK_PEND, &l2->flag);
+                       skb_pull(skb, l2headersize(l2, 0));
+                       l2up(l2, DL_DATA_IND, skb);
+               } else {
+                       /* n(s)!=v(r) */
+                       dev_kfree_skb(skb);
+                       if (test_and_set_bit(FLG_REJEXC, &l2->flag)) {
+                               if (PollFlag)
+                                       enquiry_response(l2);
+                       } else {
+                               enquiry_cr(l2, REJ, RSP, PollFlag);
+                               test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
+                       }
+               }
+       }
+       if (legalnr(l2, nr)) {
+               if (!test_bit(FLG_PEER_BUSY, &l2->flag) &&
+                   (fi->state == ST_L2_7)) {
+                       if (nr == l2->vs) {
+                               stop_t200(l2, 13);
+                               mISDN_FsmRestartTimer(&l2->t203, l2->T203,
+                                               EV_L2_T203, NULL, 7);
+                       } else if (nr != l2->va)
+                               restart_t200(l2, 14);
+               }
+               setva(l2, nr);
+       } else {
+               nrerrorrecovery(fi);
+               return;
+       }
+       if (skb_queue_len(&l2->i_queue) && (fi->state == ST_L2_7))
+               mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
+       if (test_and_clear_bit(FLG_ACK_PEND, &l2->flag))
+               enquiry_cr(l2, RR, RSP, 0);
+}
+
+static void
+l2_got_tei(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2   *l2 = fi->userdata;
+       u_int           info;
+
+       l2->tei = (signed char)(long)arg;
+       set_channel_address(&l2->ch, l2->sapi, l2->tei);
+       info = DL_INFO_L2_CONNECT;
+       l2up_create(l2, DL_INFORMATION_IND, sizeof(info), &info);
+       if (fi->state == ST_L2_3) {
+               establishlink(fi);
+               test_and_set_bit(FLG_L3_INIT, &l2->flag);
+       } else
+               mISDN_FsmChangeState(fi, ST_L2_4);
+       if (skb_queue_len(&l2->ui_queue))
+               tx_ui(l2);
+}
+
+static void
+l2_st5_tout_200(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       if (test_bit(FLG_LAPD, &l2->flag) &&
+               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
+               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
+       } else if (l2->rc == l2->N200) {
+               mISDN_FsmChangeState(fi, ST_L2_4);
+               test_and_clear_bit(FLG_T200_RUN, &l2->flag);
+               skb_queue_purge(&l2->i_queue);
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'G');
+               if (test_bit(FLG_LAPB, &l2->flag))
+                       l2down_create(l2, PH_DEACTIVATE_REQ,
+                               l2_newid(l2), 0, NULL);
+               st5_dl_release_l2l3(l2);
+               if (l2->tm)
+                       l2_tei(l2, MDL_STATUS_DOWN_IND, 0);
+       } else {
+               l2->rc++;
+               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
+               send_uframe(l2, NULL, (test_bit(FLG_MOD128, &l2->flag) ?
+                       SABME : SABM) | 0x10, CMD);
+       }
+}
+
+static void
+l2_st6_tout_200(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       if (test_bit(FLG_LAPD, &l2->flag) &&
+               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
+               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
+       } else if (l2->rc == l2->N200) {
+               mISDN_FsmChangeState(fi, ST_L2_4);
+               test_and_clear_bit(FLG_T200_RUN, &l2->flag);
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'H');
+               lapb_dl_release_l2l3(l2, DL_RELEASE_CNF);
+               if (l2->tm)
+                       l2_tei(l2, MDL_STATUS_DOWN_IND, 0);
+       } else {
+               l2->rc++;
+               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200,
+                           NULL, 9);
+               send_uframe(l2, NULL, DISC | 0x10, CMD);
+       }
+}
+
+static void
+l2_st7_tout_200(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       if (test_bit(FLG_LAPD, &l2->flag) &&
+               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
+               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
+               return;
+       }
+       test_and_clear_bit(FLG_T200_RUN, &l2->flag);
+       l2->rc = 0;
+       mISDN_FsmChangeState(fi, ST_L2_8);
+       transmit_enquiry(l2);
+       l2->rc++;
+}
+
+static void
+l2_st8_tout_200(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       if (test_bit(FLG_LAPD, &l2->flag) &&
+               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
+               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
+               return;
+       }
+       test_and_clear_bit(FLG_T200_RUN, &l2->flag);
+       if (l2->rc == l2->N200) {
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'I');
+               establishlink(fi);
+               test_and_clear_bit(FLG_L3_INIT, &l2->flag);
+       } else {
+               transmit_enquiry(l2);
+               l2->rc++;
+       }
+}
+
+static void
+l2_st7_tout_203(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       if (test_bit(FLG_LAPD, &l2->flag) &&
+               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
+               mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 9);
+               return;
+       }
+       mISDN_FsmChangeState(fi, ST_L2_8);
+       transmit_enquiry(l2);
+       l2->rc = 0;
+}
+
+static void
+l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2   *l2 = fi->userdata;
+       struct sk_buff  *skb, *nskb, *oskb;
+       u_char          header[MAX_L2HEADER_LEN];
+       u_int           i, p1;
+
+       if (!cansend(l2))
+               return;
+
+       skb = skb_dequeue(&l2->i_queue);
+       if (!skb)
+               return;
+
+       if (test_bit(FLG_MOD128, &l2->flag))
+               p1 = (l2->vs - l2->va) % 128;
+       else
+               p1 = (l2->vs - l2->va) % 8;
+       p1 = (p1 + l2->sow) % l2->window;
+       if (l2->windowar[p1]) {
+               printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
+                   p1);
+               dev_kfree_skb(l2->windowar[p1]);
+       }
+       l2->windowar[p1] = skb;
+       i = sethdraddr(l2, header, CMD);
+       if (test_bit(FLG_MOD128, &l2->flag)) {
+               header[i++] = l2->vs << 1;
+               header[i++] = l2->vr << 1;
+               l2->vs = (l2->vs + 1) % 128;
+       } else {
+               header[i++] = (l2->vr << 5) | (l2->vs << 1);
+               l2->vs = (l2->vs + 1) % 8;
+       }
+
+       nskb = skb_clone(skb, GFP_ATOMIC);
+       p1 = skb_headroom(nskb);
+       if (p1 >= i)
+               memcpy(skb_push(nskb, i), header, i);
+       else {
+               printk(KERN_WARNING
+                   "isdnl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
+               oskb = nskb;
+               nskb = mI_alloc_skb(oskb->len + i, GFP_ATOMIC);
+               if (!nskb) {
+                       dev_kfree_skb(oskb);
+                       printk(KERN_WARNING "%s: no skb mem\n", __func__);
+                       return;
+               }
+               memcpy(skb_put(nskb, i), header, i);
+               memcpy(skb_put(nskb, oskb->len), oskb->data, oskb->len);
+               dev_kfree_skb(oskb);
+       }
+       l2down(l2, PH_DATA_REQ, l2_newid(l2), nskb);
+       test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
+       if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) {
+               mISDN_FsmDelTimer(&l2->t203, 13);
+               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 11);
+       }
+}
+
+static void
+l2_st8_got_super(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+       int PollFlag, rsp, rnr = 0;
+       unsigned int nr;
+
+       rsp = *skb->data & 0x2;
+       if (test_bit(FLG_ORIG, &l2->flag))
+               rsp = !rsp;
+
+       skb_pull(skb, l2addrsize(l2));
+
+       if (IsRNR(skb->data, l2)) {
+               set_peer_busy(l2);
+               rnr = 1;
+       } else
+               clear_peer_busy(l2);
+
+       if (test_bit(FLG_MOD128, &l2->flag)) {
+               PollFlag = (skb->data[1] & 0x1) == 0x1;
+               nr = skb->data[1] >> 1;
+       } else {
+               PollFlag = (skb->data[0] & 0x10);
+               nr = (skb->data[0] >> 5) & 0x7;
+       }
+       dev_kfree_skb(skb);
+       if (rsp && PollFlag) {
+               if (legalnr(l2, nr)) {
+                       if (rnr) {
+                               restart_t200(l2, 15);
+                       } else {
+                               stop_t200(l2, 16);
+                               mISDN_FsmAddTimer(&l2->t203, l2->T203,
+                                           EV_L2_T203, NULL, 5);
+                               setva(l2, nr);
+                       }
+                       invoke_retransmission(l2, nr);
+                       mISDN_FsmChangeState(fi, ST_L2_7);
+                       if (skb_queue_len(&l2->i_queue) && cansend(l2))
+                               mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
+               } else
+                       nrerrorrecovery(fi);
+       } else {
+               if (!rsp && PollFlag)
+                       enquiry_response(l2);
+               if (legalnr(l2, nr))
+                       setva(l2, nr);
+               else
+                       nrerrorrecovery(fi);
+       }
+}
+
+static void
+l2_got_FRMR(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_pull(skb, l2addrsize(l2) + 1);
+
+       if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) || /* I or S */
+           (IsUA(skb->data) && (fi->state == ST_L2_7))) {
+               l2mgr(l2, MDL_ERROR_IND, (void *) 'K');
+               establishlink(fi);
+               test_and_clear_bit(FLG_L3_INIT, &l2->flag);
+       }
+       dev_kfree_skb(skb);
+}
+
+static void
+l2_st24_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       skb_queue_purge(&l2->ui_queue);
+       l2->tei = GROUP_TEI;
+       mISDN_FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st3_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       skb_queue_purge(&l2->ui_queue);
+       l2->tei = GROUP_TEI;
+       l2up_create(l2, DL_RELEASE_IND, 0, NULL);
+       mISDN_FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st5_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       skb_queue_purge(&l2->i_queue);
+       skb_queue_purge(&l2->ui_queue);
+       freewin(l2);
+       l2->tei = GROUP_TEI;
+       stop_t200(l2, 17);
+       st5_dl_release_l2l3(l2);
+       mISDN_FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st6_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       skb_queue_purge(&l2->ui_queue);
+       l2->tei = GROUP_TEI;
+       stop_t200(l2, 18);
+       l2up_create(l2, DL_RELEASE_IND, 0, NULL);
+       mISDN_FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       skb_queue_purge(&l2->i_queue);
+       skb_queue_purge(&l2->ui_queue);
+       freewin(l2);
+       l2->tei = GROUP_TEI;
+       stop_t200(l2, 17);
+       mISDN_FsmDelTimer(&l2->t203, 19);
+       l2up_create(l2, DL_RELEASE_IND, 0, NULL);
+/*     mISDN_queue_data(&l2->inst, l2->inst.id | MSG_BROADCAST,
+ *             MGR_SHORTSTATUS_IND, SSTATUS_L2_RELEASED,
+ *             0, NULL, 0);
+ */
+       mISDN_FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_purge(&l2->i_queue);
+       skb_queue_purge(&l2->ui_queue);
+       if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag))
+               l2up(l2, DL_RELEASE_IND, skb);
+       else
+               dev_kfree_skb(skb);
+}
+
+static void
+l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_purge(&l2->i_queue);
+       skb_queue_purge(&l2->ui_queue);
+       freewin(l2);
+       stop_t200(l2, 19);
+       st5_dl_release_l2l3(l2);
+       mISDN_FsmChangeState(fi, ST_L2_4);
+       if (l2->tm)
+               l2_tei(l2, MDL_STATUS_DOWN_IND, 0);
+       dev_kfree_skb(skb);
+}
+
+static void
+l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_purge(&l2->ui_queue);
+       stop_t200(l2, 20);
+       l2up(l2, DL_RELEASE_CNF, skb);
+       mISDN_FsmChangeState(fi, ST_L2_4);
+       if (l2->tm)
+               l2_tei(l2, MDL_STATUS_DOWN_IND, 0);
+}
+
+static void
+l2_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       skb_queue_purge(&l2->i_queue);
+       skb_queue_purge(&l2->ui_queue);
+       freewin(l2);
+       stop_t200(l2, 19);
+       mISDN_FsmDelTimer(&l2->t203, 19);
+       l2up(l2, DL_RELEASE_IND, skb);
+       mISDN_FsmChangeState(fi, ST_L2_4);
+       if (l2->tm)
+               l2_tei(l2, MDL_STATUS_DOWN_IND, 0);
+}
+
+static void
+l2_set_own_busy(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       if (!test_and_set_bit(FLG_OWN_BUSY, &l2->flag)) {
+               enquiry_cr(l2, RNR, RSP, 0);
+               test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+}
+
+static void
+l2_clear_own_busy(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+       struct sk_buff *skb = arg;
+
+       if (!test_and_clear_bit(FLG_OWN_BUSY, &l2->flag)) {
+               enquiry_cr(l2, RR, RSP, 0);
+               test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+}
+
+static void
+l2_frame_error(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       l2mgr(l2, MDL_ERROR_IND, arg);
+}
+
+static void
+l2_frame_error_reest(struct FsmInst *fi, int event, void *arg)
+{
+       struct layer2 *l2 = fi->userdata;
+
+       l2mgr(l2, MDL_ERROR_IND, arg);
+       establishlink(fi);
+       test_and_clear_bit(FLG_L3_INIT, &l2->flag);
+}
+
+static struct FsmNode L2FnList[] =
+{
+       {ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign},
+       {ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3},
+       {ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish},
+       {ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3},
+       {ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
+       {ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
+       {ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release},
+       {ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel},
+       {ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect},
+       {ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect},
+       {ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest},
+       {ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull},
+       {ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue},
+       {ST_L2_1, EV_L2_DL_UNITDATA, l2_queue_ui_assign},
+       {ST_L2_2, EV_L2_DL_UNITDATA, l2_queue_ui},
+       {ST_L2_3, EV_L2_DL_UNITDATA, l2_queue_ui},
+       {ST_L2_4, EV_L2_DL_UNITDATA, l2_send_ui},
+       {ST_L2_5, EV_L2_DL_UNITDATA, l2_send_ui},
+       {ST_L2_6, EV_L2_DL_UNITDATA, l2_send_ui},
+       {ST_L2_7, EV_L2_DL_UNITDATA, l2_send_ui},
+       {ST_L2_8, EV_L2_DL_UNITDATA, l2_send_ui},
+       {ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei},
+       {ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei},
+       {ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei},
+       {ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove},
+       {ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove},
+       {ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove},
+       {ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove},
+       {ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove},
+       {ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove},
+       {ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove},
+       {ST_L2_4, EV_L2_SABME, l2_start_multi},
+       {ST_L2_5, EV_L2_SABME, l2_send_UA},
+       {ST_L2_6, EV_L2_SABME, l2_send_DM},
+       {ST_L2_7, EV_L2_SABME, l2_restart_multi},
+       {ST_L2_8, EV_L2_SABME, l2_restart_multi},
+       {ST_L2_4, EV_L2_DISC, l2_send_DM},
+       {ST_L2_5, EV_L2_DISC, l2_send_DM},
+       {ST_L2_6, EV_L2_DISC, l2_send_UA},
+       {ST_L2_7, EV_L2_DISC, l2_stop_multi},
+       {ST_L2_8, EV_L2_DISC, l2_stop_multi},
+       {ST_L2_4, EV_L2_UA, l2_mdl_error_ua},
+       {ST_L2_5, EV_L2_UA, l2_connected},
+       {ST_L2_6, EV_L2_UA, l2_released},
+       {ST_L2_7, EV_L2_UA, l2_mdl_error_ua},
+       {ST_L2_8, EV_L2_UA, l2_mdl_error_ua},
+       {ST_L2_4, EV_L2_DM, l2_reestablish},
+       {ST_L2_5, EV_L2_DM, l2_st5_dm_release},
+       {ST_L2_6, EV_L2_DM, l2_st6_dm_release},
+       {ST_L2_7, EV_L2_DM, l2_mdl_error_dm},
+       {ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm},
+       {ST_L2_1, EV_L2_UI, l2_got_ui},
+       {ST_L2_2, EV_L2_UI, l2_got_ui},
+       {ST_L2_3, EV_L2_UI, l2_got_ui},
+       {ST_L2_4, EV_L2_UI, l2_got_ui},
+       {ST_L2_5, EV_L2_UI, l2_got_ui},
+       {ST_L2_6, EV_L2_UI, l2_got_ui},
+       {ST_L2_7, EV_L2_UI, l2_got_ui},
+       {ST_L2_8, EV_L2_UI, l2_got_ui},
+       {ST_L2_7, EV_L2_FRMR, l2_got_FRMR},
+       {ST_L2_8, EV_L2_FRMR, l2_got_FRMR},
+       {ST_L2_7, EV_L2_SUPER, l2_st7_got_super},
+       {ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
+       {ST_L2_7, EV_L2_I, l2_got_iframe},
+       {ST_L2_8, EV_L2_I, l2_got_iframe},
+       {ST_L2_5, EV_L2_T200, l2_st5_tout_200},
+       {ST_L2_6, EV_L2_T200, l2_st6_tout_200},
+       {ST_L2_7, EV_L2_T200, l2_st7_tout_200},
+       {ST_L2_8, EV_L2_T200, l2_st8_tout_200},
+       {ST_L2_7, EV_L2_T203, l2_st7_tout_203},
+       {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
+       {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
+       {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
+       {ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
+       {ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
+       {ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error},
+       {ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error},
+       {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
+       {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
+       {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
+       {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da},
+       {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
+       {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
+       {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da},
+       {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da},
+       {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da},
+       {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da},
+       {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
+};
+
+#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
+
+static int
+ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
+{
+       u_char  *datap = skb->data;
+       int     ret = -EINVAL;
+       int     psapi, ptei;
+       u_int   l;
+       int     c = 0;
+
+       l = l2addrsize(l2);
+       if (skb->len <= l) {
+               mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *) 'N');
+               return ret;
+       }
+       if (test_bit(FLG_LAPD, &l2->flag)) { /* Maybe not needed */
+               psapi = *datap++;
+               ptei = *datap++;
+               if ((psapi & 1) || !(ptei & 1)) {
+                       printk(KERN_WARNING
+                           "l2 D-channel frame wrong EA0/EA1\n");
+                       return ret;
+               }
+               psapi >>= 2;
+               ptei >>= 1;
+               if (psapi != l2->sapi) {
+                       /* not our bussiness
+                        * printk(KERN_DEBUG "%s: sapi %d/%d sapi mismatch\n",
+                        *  __func__,
+                        *      psapi, l2->sapi);
+                        */
+                       dev_kfree_skb(skb);
+                       return 0;
+               }
+               if ((ptei != l2->tei) && (ptei != GROUP_TEI)) {
+                       /* not our bussiness
+                        * printk(KERN_DEBUG "%s: tei %d/%d sapi %d mismatch\n",
+                        *  __func__,
+                        *      ptei, l2->tei, psapi);
+                        */
+                       dev_kfree_skb(skb);
+                       return 0;
+               }
+       } else
+               datap += l;
+       if (!(*datap & 1)) {    /* I-Frame */
+               c = iframe_error(l2, skb);
+               if (!c)
+                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_I, skb);
+       } else if (IsSFrame(datap, l2)) {       /* S-Frame */
+               c = super_error(l2, skb);
+               if (!c)
+                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_SUPER, skb);
+       } else if (IsUI(datap)) {
+               c = UI_error(l2, skb);
+               if (!c)
+                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_UI, skb);
+       } else if (IsSABME(datap, l2)) {
+               c = unnum_error(l2, skb, CMD);
+               if (!c)
+                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_SABME, skb);
+       } else if (IsUA(datap)) {
+               c = unnum_error(l2, skb, RSP);
+               if (!c)
+                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_UA, skb);
+       } else if (IsDISC(datap)) {
+               c = unnum_error(l2, skb, CMD);
+               if (!c)
+                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DISC, skb);
+       } else if (IsDM(datap)) {
+               c = unnum_error(l2, skb, RSP);
+               if (!c)
+                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DM, skb);
+       } else if (IsFRMR(datap)) {
+               c = FRMR_error(l2, skb);
+               if (!c)
+                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_FRMR, skb);
+       } else
+               c = 'L';
+       if (c) {
+               printk(KERN_WARNING "l2 D-channel frame error %c\n", c);
+               mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
+       }
+       return ret;
+}
+
+static int
+l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct layer2           *l2 = container_of(ch, struct layer2, ch);
+       struct mISDNhead        *hh =  mISDN_HEAD_P(skb);
+       int                     ret = -EINVAL;
+
+       if (*debug & DEBUG_L2_RECV)
+               printk(KERN_DEBUG "%s: prim(%x) id(%x) tei(%d)\n",
+                   __func__, hh->prim, hh->id, l2->tei);
+       switch (hh->prim) {
+       case PH_DATA_IND:
+               ret = ph_data_indication(l2, hh, skb);
+               break;
+       case PH_DATA_CNF:
+               ret = ph_data_confirm(l2, hh, skb);
+               break;
+       case PH_ACTIVATE_IND:
+               test_and_set_bit(FLG_L1_ACTIV, &l2->flag);
+               l2up_create(l2, MPH_ACTIVATE_IND, 0, NULL);
+               if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag))
+                       ret = mISDN_FsmEvent(&l2->l2m,
+                               EV_L2_DL_ESTABLISH_REQ, skb);
+               break;
+       case PH_DEACTIVATE_IND:
+               test_and_clear_bit(FLG_L1_ACTIV, &l2->flag);
+               l2up_create(l2, MPH_DEACTIVATE_IND, 0, NULL);
+               ret = mISDN_FsmEvent(&l2->l2m, EV_L1_DEACTIVATE, skb);
+               break;
+       case MPH_INFORMATION_IND:
+               if (!l2->up)
+                       break;
+               ret = l2->up->send(l2->up, skb);
+               break;
+       case DL_DATA_REQ:
+               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_DATA, skb);
+               break;
+       case DL_UNITDATA_REQ:
+               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_UNITDATA, skb);
+               break;
+       case DL_ESTABLISH_REQ:
+               if (test_bit(FLG_LAPB, &l2->flag))
+                       test_and_set_bit(FLG_ORIG, &l2->flag);
+               if (test_bit(FLG_L1_ACTIV, &l2->flag)) {
+                       if (test_bit(FLG_LAPD, &l2->flag) ||
+                               test_bit(FLG_ORIG, &l2->flag))
+                               ret = mISDN_FsmEvent(&l2->l2m,
+                                       EV_L2_DL_ESTABLISH_REQ, skb);
+               } else {
+                       if (test_bit(FLG_LAPD, &l2->flag) ||
+                               test_bit(FLG_ORIG, &l2->flag)) {
+                               test_and_set_bit(FLG_ESTAB_PEND,
+                                       &l2->flag);
+                       }
+                       ret = l2down(l2, PH_ACTIVATE_REQ, l2_newid(l2),
+                           skb);
+               }
+               break;
+       case DL_RELEASE_REQ:
+               if (test_bit(FLG_LAPB, &l2->flag))
+                       l2down_create(l2, PH_DEACTIVATE_REQ,
+                               l2_newid(l2), 0, NULL);
+               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ,
+                   skb);
+               break;
+       default:
+               if (*debug & DEBUG_L2)
+                       l2m_debug(&l2->l2m, "l2 unknown pr %04x",
+                           hh->prim);
+       }
+       if (ret) {
+               dev_kfree_skb(skb);
+               ret = 0;
+       }
+       return ret;
+}
+
+int
+tei_l2(struct layer2 *l2, u_int cmd, u_long arg)
+{
+       int             ret = -EINVAL;
+
+       if (*debug & DEBUG_L2_TEI)
+               printk(KERN_DEBUG "%s: cmd(%x)\n", __func__, cmd);
+       switch (cmd) {
+       case (MDL_ASSIGN_REQ):
+               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ASSIGN, (void *)arg);
+               break;
+       case (MDL_REMOVE_REQ):
+               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_REMOVE, NULL);
+               break;
+       case (MDL_ERROR_IND):
+               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, NULL);
+               break;
+       case (MDL_ERROR_RSP):
+               /* ETS 300-125 5.3.2.1 Test: TC13010 */
+               printk(KERN_NOTICE "MDL_ERROR|REQ (tei_l2)\n");
+               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, NULL);
+               break;
+       }
+       return ret;
+}
+
+static void
+release_l2(struct layer2 *l2)
+{
+       mISDN_FsmDelTimer(&l2->t200, 21);
+       mISDN_FsmDelTimer(&l2->t203, 16);
+       skb_queue_purge(&l2->i_queue);
+       skb_queue_purge(&l2->ui_queue);
+       skb_queue_purge(&l2->down_queue);
+       ReleaseWin(l2);
+       if (test_bit(FLG_LAPD, &l2->flag)) {
+               TEIrelease(l2);
+               if (l2->ch.st)
+                       l2->ch.st->dev->D.ctrl(&l2->ch.st->dev->D,
+                           CLOSE_CHANNEL, NULL);
+       }
+       kfree(l2);
+}
+
+static int
+l2_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct layer2           *l2 = container_of(ch, struct layer2, ch);
+       u_int                   info;
+
+       if (*debug & DEBUG_L2_CTRL)
+               printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd);
+
+       switch (cmd) {
+       case OPEN_CHANNEL:
+               if (test_bit(FLG_LAPD, &l2->flag)) {
+                       set_channel_address(&l2->ch, l2->sapi, l2->tei);
+                       info = DL_INFO_L2_CONNECT;
+                       l2up_create(l2, DL_INFORMATION_IND,
+                           sizeof(info), &info);
+               }
+               break;
+       case CLOSE_CHANNEL:
+               if (l2->ch.peer)
+                       l2->ch.peer->ctrl(l2->ch.peer, CLOSE_CHANNEL, NULL);
+               release_l2(l2);
+               break;
+       }
+       return 0;
+}
+
+struct layer2 *
+create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
+{
+       struct layer2           *l2;
+       struct channel_req      rq;
+
+       l2 = kzalloc(sizeof(struct layer2), GFP_KERNEL);
+       if (!l2) {
+               printk(KERN_ERR "kzalloc layer2 failed\n");
+               return NULL;
+       }
+       l2->next_id = 1;
+       l2->down_id = MISDN_ID_NONE;
+       l2->up = ch;
+       l2->ch.st = ch->st;
+       l2->ch.send = l2_send;
+       l2->ch.ctrl = l2_ctrl;
+       switch (protocol) {
+       case ISDN_P_LAPD_NT:
+               test_and_set_bit(FLG_LAPD, &l2->flag);
+               test_and_set_bit(FLG_LAPD_NET, &l2->flag);
+               test_and_set_bit(FLG_MOD128, &l2->flag);
+               l2->sapi = 0;
+               l2->maxlen = MAX_DFRAME_LEN;
+               if (test_bit(OPTION_L2_PMX, &options))
+                       l2->window = 7;
+               else
+                       l2->window = 1;
+               if (test_bit(OPTION_L2_PTP, &options))
+                       test_and_set_bit(FLG_PTP, &l2->flag);
+               if (test_bit(OPTION_L2_FIXEDTEI, &options))
+                       test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
+               l2->tei = (u_int)arg;
+               l2->T200 = 1000;
+               l2->N200 = 3;
+               l2->T203 = 10000;
+               if (test_bit(OPTION_L2_PMX, &options))
+                       rq.protocol = ISDN_P_NT_E1;
+               else
+                       rq.protocol = ISDN_P_NT_S0;
+               rq.adr.channel = 0;
+               l2->ch.st->dev->D.ctrl(&l2->ch.st->dev->D, OPEN_CHANNEL, &rq);
+               break;
+       case ISDN_P_LAPD_TE:
+               test_and_set_bit(FLG_LAPD, &l2->flag);
+               test_and_set_bit(FLG_MOD128, &l2->flag);
+               test_and_set_bit(FLG_ORIG, &l2->flag);
+               l2->sapi = 0;
+               l2->maxlen = MAX_DFRAME_LEN;
+               if (test_bit(OPTION_L2_PMX, &options))
+                       l2->window = 7;
+               else
+                       l2->window = 1;
+               if (test_bit(OPTION_L2_PTP, &options))
+                       test_and_set_bit(FLG_PTP, &l2->flag);
+               if (test_bit(OPTION_L2_FIXEDTEI, &options))
+                       test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
+               l2->tei = (u_int)arg;
+               l2->T200 = 1000;
+               l2->N200 = 3;
+               l2->T203 = 10000;
+               if (test_bit(OPTION_L2_PMX, &options))
+                       rq.protocol = ISDN_P_TE_E1;
+               else
+                       rq.protocol = ISDN_P_TE_S0;
+               rq.adr.channel = 0;
+               l2->ch.st->dev->D.ctrl(&l2->ch.st->dev->D, OPEN_CHANNEL, &rq);
+               break;
+       case ISDN_P_B_X75SLP:
+               test_and_set_bit(FLG_LAPB, &l2->flag);
+               l2->window = 7;
+               l2->maxlen = MAX_DATA_SIZE;
+               l2->T200 = 1000;
+               l2->N200 = 4;
+               l2->T203 = 5000;
+               l2->addr.A = 3;
+               l2->addr.B = 1;
+               break;
+       default:
+               printk(KERN_ERR "layer2 create failed prt %x\n",
+                       protocol);
+               kfree(l2);
+               return NULL;
+       }
+       skb_queue_head_init(&l2->i_queue);
+       skb_queue_head_init(&l2->ui_queue);
+       skb_queue_head_init(&l2->down_queue);
+       skb_queue_head_init(&l2->tmp_queue);
+       InitWin(l2);
+       l2->l2m.fsm = &l2fsm;
+       if (test_bit(FLG_LAPB, &l2->flag) ||
+               test_bit(FLG_PTP, &l2->flag) ||
+               test_bit(FLG_LAPD_NET, &l2->flag))
+               l2->l2m.state = ST_L2_4;
+       else
+               l2->l2m.state = ST_L2_1;
+       l2->l2m.debug = *debug;
+       l2->l2m.userdata = l2;
+       l2->l2m.userint = 0;
+       l2->l2m.printdebug = l2m_debug;
+
+       mISDN_FsmInitTimer(&l2->l2m, &l2->t200);
+       mISDN_FsmInitTimer(&l2->l2m, &l2->t203);
+       return l2;
+}
+
+static int
+x75create(struct channel_req *crq)
+{
+       struct layer2   *l2;
+
+       if (crq->protocol != ISDN_P_B_X75SLP)
+               return -EPROTONOSUPPORT;
+       l2 = create_l2(crq->ch, crq->protocol, 0, 0);
+       if (!l2)
+               return -ENOMEM;
+       crq->ch = &l2->ch;
+       crq->protocol = ISDN_P_B_HDLC;
+       return 0;
+}
+
+static struct Bprotocol X75SLP = {
+       .Bprotocols = (1 << (ISDN_P_B_X75SLP & ISDN_P_B_MASK)),
+       .name = "X75SLP",
+       .create = x75create
+};
+
+int
+Isdnl2_Init(u_int *deb)
+{
+       debug = deb;
+       mISDN_register_Bprotocol(&X75SLP);
+       l2fsm.state_count = L2_STATE_COUNT;
+       l2fsm.event_count = L2_EVENT_COUNT;
+       l2fsm.strEvent = strL2Event;
+       l2fsm.strState = strL2State;
+       mISDN_FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList));
+       TEIInit(deb);
+       return 0;
+}
+
+void
+Isdnl2_cleanup(void)
+{
+       mISDN_unregister_Bprotocol(&X75SLP);
+       TEIFree();
+       mISDN_FsmFree(&l2fsm);
+}
+
diff --git a/drivers/isdn/mISDN/layer2.h b/drivers/isdn/mISDN/layer2.h
new file mode 100644 (file)
index 0000000..6293f80
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Layer 2 defines
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/mISDNif.h>
+#include <linux/skbuff.h>
+#include "fsm.h"
+
+#define MAX_WINDOW     8
+
+struct manager {
+       struct mISDNchannel     ch;
+       struct mISDNchannel     bcast;
+       u_long                  options;
+       struct list_head        layer2;
+       rwlock_t                lock;
+       struct FsmInst          deact;
+       struct FsmTimer         datimer;
+       struct sk_buff_head     sendq;
+       struct mISDNchannel     *up;
+       u_int                   nextid;
+       u_int                   lastid;
+};
+
+struct teimgr {
+       int                     ri;
+       int                     rcnt;
+       struct FsmInst          tei_m;
+       struct FsmTimer         timer;
+       int                     tval, nval;
+       struct layer2           *l2;
+       struct manager          *mgr;
+};
+
+struct laddr {
+       u_char  A;
+       u_char  B;
+};
+
+struct layer2 {
+       struct list_head        list;
+       struct mISDNchannel     ch;
+       u_long                  flag;
+       int                     id;
+       struct mISDNchannel     *up;
+       signed char             sapi;
+       signed char             tei;
+       struct laddr            addr;
+       u_int                   maxlen;
+       struct teimgr           *tm;
+       u_int                   vs, va, vr;
+       int                     rc;
+       u_int                   window;
+       u_int                   sow;
+       struct FsmInst          l2m;
+       struct FsmTimer         t200, t203;
+       int                     T200, N200, T203;
+       u_int                   next_id;
+       u_int                   down_id;
+       struct sk_buff          *windowar[MAX_WINDOW];
+       struct sk_buff_head     i_queue;
+       struct sk_buff_head     ui_queue;
+       struct sk_buff_head     down_queue;
+       struct sk_buff_head     tmp_queue;
+};
+
+enum {
+       ST_L2_1,
+       ST_L2_2,
+       ST_L2_3,
+       ST_L2_4,
+       ST_L2_5,
+       ST_L2_6,
+       ST_L2_7,
+       ST_L2_8,
+};
+
+#define L2_STATE_COUNT (ST_L2_8+1)
+
+extern struct layer2   *create_l2(struct mISDNchannel *, u_int,
+                               u_long, u_long);
+extern int             tei_l2(struct layer2 *, u_int, u_long arg);
+
+
+/* from tei.c */
+extern int             l2_tei(struct layer2 *, u_int, u_long arg);
+extern void            TEIrelease(struct layer2 *);
+extern int             TEIInit(u_int *);
+extern void            TEIFree(void);
+
+#define MAX_L2HEADER_LEN 4
+
+#define RR     0x01
+#define RNR    0x05
+#define REJ    0x09
+#define SABME  0x6f
+#define SABM   0x2f
+#define DM     0x0f
+#define UI     0x03
+#define DISC   0x43
+#define UA     0x63
+#define FRMR   0x87
+#define XID    0xaf
+
+#define CMD    0
+#define RSP    1
+
+#define LC_FLUSH_WAIT 1
+
+#define FLG_LAPB       0
+#define FLG_LAPD       1
+#define FLG_ORIG       2
+#define FLG_MOD128     3
+#define FLG_PEND_REL   4
+#define FLG_L3_INIT    5
+#define FLG_T200_RUN   6
+#define FLG_ACK_PEND   7
+#define FLG_REJEXC     8
+#define FLG_OWN_BUSY   9
+#define FLG_PEER_BUSY  10
+#define FLG_DCHAN_BUSY 11
+#define FLG_L1_ACTIV   12
+#define FLG_ESTAB_PEND 13
+#define FLG_PTP                14
+#define FLG_FIXED_TEI  15
+#define FLG_L2BLOCK    16
+#define FLG_L1_NOTREADY        17
+#define FLG_LAPD_NET   18
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
new file mode 100644 (file)
index 0000000..4ba4cc3
--- /dev/null
@@ -0,0 +1,781 @@
+/*
+ *
+ * Author      Karsten Keil <kkeil@novell.com>
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/mISDNif.h>
+#include "core.h"
+
+static int     *debug;
+
+static struct proto mISDN_proto = {
+       .name           = "misdn",
+       .owner          = THIS_MODULE,
+       .obj_size       = sizeof(struct mISDN_sock)
+};
+
+#define _pms(sk)       ((struct mISDN_sock *)sk)
+
+static struct mISDN_sock_list  data_sockets = {
+       .lock = __RW_LOCK_UNLOCKED(data_sockets.lock)
+};
+
+static struct mISDN_sock_list  base_sockets = {
+       .lock = __RW_LOCK_UNLOCKED(base_sockets.lock)
+};
+
+#define L2_HEADER_LEN  4
+
+static inline struct sk_buff *
+_l2_alloc_skb(unsigned int len, gfp_t gfp_mask)
+{
+       struct sk_buff  *skb;
+
+       skb = alloc_skb(len + L2_HEADER_LEN, gfp_mask);
+       if (likely(skb))
+               skb_reserve(skb, L2_HEADER_LEN);
+       return skb;
+}
+
+static void
+mISDN_sock_link(struct mISDN_sock_list *l, struct sock *sk)
+{
+       write_lock_bh(&l->lock);
+       sk_add_node(sk, &l->head);
+       write_unlock_bh(&l->lock);
+}
+
+static void mISDN_sock_unlink(struct mISDN_sock_list *l, struct sock *sk)
+{
+       write_lock_bh(&l->lock);
+       sk_del_node_init(sk);
+       write_unlock_bh(&l->lock);
+}
+
+static int
+mISDN_send(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct mISDN_sock *msk;
+       int     err;
+
+       msk = container_of(ch, struct mISDN_sock, ch);
+       if (*debug & DEBUG_SOCKET)
+               printk(KERN_DEBUG "%s len %d %p\n", __func__, skb->len, skb);
+       if (msk->sk.sk_state == MISDN_CLOSED)
+               return -EUNATCH;
+       __net_timestamp(skb);
+       err = sock_queue_rcv_skb(&msk->sk, skb);
+       if (err)
+               printk(KERN_WARNING "%s: error %d\n", __func__, err);
+       return err;
+}
+
+static int
+mISDN_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct mISDN_sock *msk;
+
+       msk = container_of(ch, struct mISDN_sock, ch);
+       if (*debug & DEBUG_SOCKET)
+               printk(KERN_DEBUG "%s(%p, %x, %p)\n", __func__, ch, cmd, arg);
+       switch (cmd) {
+       case CLOSE_CHANNEL:
+               msk->sk.sk_state = MISDN_CLOSED;
+               break;
+       }
+       return 0;
+}
+
+static inline void
+mISDN_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
+{
+       struct timeval  tv;
+
+       if (_pms(sk)->cmask & MISDN_TIME_STAMP) {
+               skb_get_timestamp(skb, &tv);
+               put_cmsg(msg, SOL_MISDN, MISDN_TIME_STAMP, sizeof(tv), &tv);
+       }
+}
+
+static int
+mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+    struct msghdr *msg, size_t len, int flags)
+{
+       struct sk_buff          *skb;
+       struct sock             *sk = sock->sk;
+       struct sockaddr_mISDN   *maddr;
+
+       int             copied, err;
+
+       if (*debug & DEBUG_SOCKET)
+               printk(KERN_DEBUG "%s: len %d, flags %x ch.nr %d, proto %x\n",
+                       __func__, (int)len, flags, _pms(sk)->ch.nr,
+                       sk->sk_protocol);
+       if (flags & (MSG_OOB))
+               return -EOPNOTSUPP;
+
+       if (sk->sk_state == MISDN_CLOSED)
+               return 0;
+
+       skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
+       if (!skb)
+               return err;
+
+       if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) {
+               msg->msg_namelen = sizeof(struct sockaddr_mISDN);
+               maddr = (struct sockaddr_mISDN *)msg->msg_name;
+               maddr->family = AF_ISDN;
+               maddr->dev = _pms(sk)->dev->id;
+               if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
+                   (sk->sk_protocol == ISDN_P_LAPD_NT)) {
+                       maddr->channel = (mISDN_HEAD_ID(skb) >> 16) & 0xff;
+                       maddr->tei =  (mISDN_HEAD_ID(skb) >> 8) & 0xff;
+                       maddr->sapi = mISDN_HEAD_ID(skb) & 0xff;
+               } else {
+                       maddr->channel = _pms(sk)->ch.nr;
+                       maddr->sapi = _pms(sk)->ch.addr & 0xFF;
+                       maddr->tei =  (_pms(sk)->ch.addr >> 8) & 0xFF;
+               }
+       } else {
+               if (msg->msg_namelen)
+                       printk(KERN_WARNING "%s: too small namelen %d\n",
+                           __func__, msg->msg_namelen);
+               msg->msg_namelen = 0;
+       }
+
+       copied = skb->len + MISDN_HEADER_LEN;
+       if (len < copied) {
+               if (flags & MSG_PEEK)
+                       atomic_dec(&skb->users);
+               else
+                       skb_queue_head(&sk->sk_receive_queue, skb);
+               return -ENOSPC;
+       }
+       memcpy(skb_push(skb, MISDN_HEADER_LEN), mISDN_HEAD_P(skb),
+           MISDN_HEADER_LEN);
+
+       err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+
+       mISDN_sock_cmsg(sk, msg, skb);
+
+       skb_free_datagram(sk, skb);
+
+       return err ? : copied;
+}
+
+static int
+mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
+    struct msghdr *msg, size_t len)
+{
+       struct sock             *sk = sock->sk;
+       struct sk_buff          *skb;
+       int                     err = -ENOMEM;
+       struct sockaddr_mISDN   *maddr;
+
+       if (*debug & DEBUG_SOCKET)
+               printk(KERN_DEBUG "%s: len %d flags %x ch %d proto %x\n",
+                    __func__, (int)len, msg->msg_flags, _pms(sk)->ch.nr,
+                    sk->sk_protocol);
+
+       if (msg->msg_flags & MSG_OOB)
+               return -EOPNOTSUPP;
+
+       if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
+               return -EINVAL;
+
+       if (len < MISDN_HEADER_LEN)
+               return -EINVAL;
+
+       if (sk->sk_state != MISDN_BOUND)
+               return -EBADFD;
+
+       lock_sock(sk);
+
+       skb = _l2_alloc_skb(len, GFP_KERNEL);
+       if (!skb)
+               goto done;
+
+       if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
+               err = -EFAULT;
+               goto drop;
+       }
+
+       memcpy(mISDN_HEAD_P(skb), skb->data, MISDN_HEADER_LEN);
+       skb_pull(skb, MISDN_HEADER_LEN);
+
+       if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) {
+               /* if we have a address, we use it */
+               maddr = (struct sockaddr_mISDN *)msg->msg_name;
+               mISDN_HEAD_ID(skb) = maddr->channel;
+       } else { /* use default for L2 messages */
+               if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
+                   (sk->sk_protocol == ISDN_P_LAPD_NT))
+                   mISDN_HEAD_ID(skb) = _pms(sk)->ch.nr;
+       }
+
+       if (*debug & DEBUG_SOCKET)
+               printk(KERN_DEBUG "%s: ID:%x\n",
+                    __func__, mISDN_HEAD_ID(skb));
+
+       err = -ENODEV;
+       if (!_pms(sk)->ch.peer ||
+           (err = _pms(sk)->ch.recv(_pms(sk)->ch.peer, skb)))
+               goto drop;
+
+       err = len;
+
+done:
+       release_sock(sk);
+       return err;
+
+drop:
+       kfree_skb(skb);
+       goto done;
+}
+
+static int
+data_sock_release(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+
+       if (*debug & DEBUG_SOCKET)
+               printk(KERN_DEBUG "%s(%p) sk=%p\n", __func__, sock, sk);
+       if (!sk)
+               return 0;
+       switch (sk->sk_protocol) {
+       case ISDN_P_TE_S0:
+       case ISDN_P_NT_S0:
+       case ISDN_P_TE_E1:
+       case ISDN_P_NT_E1:
+               if (sk->sk_state == MISDN_BOUND)
+                       delete_channel(&_pms(sk)->ch);
+               else
+                       mISDN_sock_unlink(&data_sockets, sk);
+               break;
+       case ISDN_P_LAPD_TE:
+       case ISDN_P_LAPD_NT:
+       case ISDN_P_B_RAW:
+       case ISDN_P_B_HDLC:
+       case ISDN_P_B_X75SLP:
+       case ISDN_P_B_L2DTMF:
+       case ISDN_P_B_L2DSP:
+       case ISDN_P_B_L2DSPHDLC:
+               delete_channel(&_pms(sk)->ch);
+               mISDN_sock_unlink(&data_sockets, sk);
+               break;
+       }
+
+       lock_sock(sk);
+
+       sock_orphan(sk);
+       skb_queue_purge(&sk->sk_receive_queue);
+
+       release_sock(sk);
+       sock_put(sk);
+
+       return 0;
+}
+
+static int
+data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p)
+{
+       struct mISDN_ctrl_req   cq;
+       int                     err = -EINVAL, val;
+       struct mISDNchannel     *bchan, *next;
+
+       lock_sock(sk);
+       if (!_pms(sk)->dev) {
+               err = -ENODEV;
+               goto done;
+       }
+       switch (cmd) {
+       case IMCTRLREQ:
+               if (copy_from_user(&cq, p, sizeof(cq))) {
+                       err = -EFAULT;
+                       break;
+               }
+               if ((sk->sk_protocol & ~ISDN_P_B_MASK) == ISDN_P_B_START) {
+                       list_for_each_entry_safe(bchan, next,
+                               &_pms(sk)->dev->bchannels, list) {
+                               if (bchan->nr == cq.channel) {
+                                       err = bchan->ctrl(bchan,
+                                               CONTROL_CHANNEL, &cq);
+                                       break;
+                               }
+                       }
+               } else
+                       err = _pms(sk)->dev->D.ctrl(&_pms(sk)->dev->D,
+                               CONTROL_CHANNEL, &cq);
+               if (err)
+                       break;
+               if (copy_to_user(p, &cq, sizeof(cq)))
+                       err = -EFAULT;
+               break;
+       case IMCLEAR_L2:
+               if (sk->sk_protocol != ISDN_P_LAPD_NT) {
+                       err = -EINVAL;
+                       break;
+               }
+               if (get_user(val, (int __user *)p)) {
+                       err = -EFAULT;
+                       break;
+               }
+               err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr,
+                   CONTROL_CHANNEL, &val);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+done:
+       release_sock(sk);
+       return err;
+}
+
+static int
+data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       int                     err = 0, id;
+       struct sock             *sk = sock->sk;
+       struct mISDNdevice      *dev;
+       struct mISDNversion     ver;
+
+       switch (cmd) {
+       case IMGETVERSION:
+               ver.major = MISDN_MAJOR_VERSION;
+               ver.minor = MISDN_MINOR_VERSION;
+               ver.release = MISDN_RELEASE;
+               if (copy_to_user((void __user *)arg, &ver, sizeof(ver)))
+                       err = -EFAULT;
+               break;
+       case IMGETCOUNT:
+               id = get_mdevice_count();
+               if (put_user(id, (int __user *)arg))
+                       err = -EFAULT;
+               break;
+       case IMGETDEVINFO:
+               if (get_user(id, (int __user *)arg)) {
+                       err = -EFAULT;
+                       break;
+               }
+               dev = get_mdevice(id);
+               if (dev) {
+                       struct mISDN_devinfo di;
+
+                       di.id = dev->id;
+                       di.Dprotocols = dev->Dprotocols;
+                       di.Bprotocols = dev->Bprotocols | get_all_Bprotocols();
+                       di.protocol = dev->D.protocol;
+                       memcpy(di.channelmap, dev->channelmap,
+                               MISDN_CHMAP_SIZE * 4);
+                       di.nrbchan = dev->nrbchan;
+                       strcpy(di.name, dev->name);
+                       if (copy_to_user((void __user *)arg, &di, sizeof(di)))
+                               err = -EFAULT;
+               } else
+                       err = -ENODEV;
+               break;
+       default:
+               if (sk->sk_state == MISDN_BOUND)
+                       err = data_sock_ioctl_bound(sk, cmd,
+                               (void __user *)arg);
+               else
+                       err = -ENOTCONN;
+       }
+       return err;
+}
+
+static int data_sock_setsockopt(struct socket *sock, int level, int optname,
+       char __user *optval, int len)
+{
+       struct sock *sk = sock->sk;
+       int err = 0, opt = 0;
+
+       if (*debug & DEBUG_SOCKET)
+               printk(KERN_DEBUG "%s(%p, %d, %x, %p, %d)\n", __func__, sock,
+                   level, optname, optval, len);
+
+       lock_sock(sk);
+
+       switch (optname) {
+       case MISDN_TIME_STAMP:
+               if (get_user(opt, (int __user *)optval)) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               if (opt)
+                       _pms(sk)->cmask |= MISDN_TIME_STAMP;
+               else
+                       _pms(sk)->cmask &= ~MISDN_TIME_STAMP;
+               break;
+       default:
+               err = -ENOPROTOOPT;
+               break;
+       }
+       release_sock(sk);
+       return err;
+}
+
+static int data_sock_getsockopt(struct socket *sock, int level, int optname,
+       char __user *optval, int __user *optlen)
+{
+       struct sock *sk = sock->sk;
+       int len, opt;
+
+       if (get_user(len, optlen))
+               return -EFAULT;
+
+       switch (optname) {
+       case MISDN_TIME_STAMP:
+               if (_pms(sk)->cmask & MISDN_TIME_STAMP)
+                       opt = 1;
+               else
+                       opt = 0;
+
+               if (put_user(opt, optval))
+                       return -EFAULT;
+               break;
+       default:
+               return -ENOPROTOOPT;
+       }
+
+       return 0;
+}
+
+static int
+data_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
+{
+       struct sockaddr_mISDN *maddr = (struct sockaddr_mISDN *) addr;
+       struct sock *sk = sock->sk;
+       int err = 0;
+
+       if (*debug & DEBUG_SOCKET)
+               printk(KERN_DEBUG "%s(%p) sk=%p\n", __func__, sock, sk);
+       if (addr_len != sizeof(struct sockaddr_mISDN))
+               return -EINVAL;
+       if (!maddr || maddr->family != AF_ISDN)
+               return -EINVAL;
+
+       lock_sock(sk);
+
+       if (_pms(sk)->dev) {
+               err = -EALREADY;
+               goto done;
+       }
+       _pms(sk)->dev = get_mdevice(maddr->dev);
+       if (!_pms(sk)->dev) {
+               err = -ENODEV;
+               goto done;
+       }
+       _pms(sk)->ch.send = mISDN_send;
+       _pms(sk)->ch.ctrl = mISDN_ctrl;
+
+       switch (sk->sk_protocol) {
+       case ISDN_P_TE_S0:
+       case ISDN_P_NT_S0:
+       case ISDN_P_TE_E1:
+       case ISDN_P_NT_E1:
+               mISDN_sock_unlink(&data_sockets, sk);
+               err = connect_layer1(_pms(sk)->dev, &_pms(sk)->ch,
+                   sk->sk_protocol, maddr);
+               if (err)
+                       mISDN_sock_link(&data_sockets, sk);
+               break;
+       case ISDN_P_LAPD_TE:
+       case ISDN_P_LAPD_NT:
+               err = create_l2entity(_pms(sk)->dev, &_pms(sk)->ch,
+                   sk->sk_protocol, maddr);
+               break;
+       case ISDN_P_B_RAW:
+       case ISDN_P_B_HDLC:
+       case ISDN_P_B_X75SLP:
+       case ISDN_P_B_L2DTMF:
+       case ISDN_P_B_L2DSP:
+       case ISDN_P_B_L2DSPHDLC:
+               err = connect_Bstack(_pms(sk)->dev, &_pms(sk)->ch,
+                   sk->sk_protocol, maddr);
+               break;
+       default:
+               err = -EPROTONOSUPPORT;
+       }
+       if (err)
+               goto done;
+       sk->sk_state = MISDN_BOUND;
+       _pms(sk)->ch.protocol = sk->sk_protocol;
+
+done:
+       release_sock(sk);
+       return err;
+}
+
+static int
+data_sock_getname(struct socket *sock, struct sockaddr *addr,
+    int *addr_len, int peer)
+{
+       struct sockaddr_mISDN   *maddr = (struct sockaddr_mISDN *) addr;
+       struct sock             *sk = sock->sk;
+
+       if (!_pms(sk)->dev)
+               return -EBADFD;
+
+       lock_sock(sk);
+
+       *addr_len = sizeof(*maddr);
+       maddr->dev = _pms(sk)->dev->id;
+       maddr->channel = _pms(sk)->ch.nr;
+       maddr->sapi = _pms(sk)->ch.addr & 0xff;
+       maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xff;
+       release_sock(sk);
+       return 0;
+}
+
+static const struct proto_ops data_sock_ops = {
+       .family         = PF_ISDN,
+       .owner          = THIS_MODULE,
+       .release        = data_sock_release,
+       .ioctl          = data_sock_ioctl,
+       .bind           = data_sock_bind,
+       .getname        = data_sock_getname,
+       .sendmsg        = mISDN_sock_sendmsg,
+       .recvmsg        = mISDN_sock_recvmsg,
+       .poll           = datagram_poll,
+       .listen         = sock_no_listen,
+       .shutdown       = sock_no_shutdown,
+       .setsockopt     = data_sock_setsockopt,
+       .getsockopt     = data_sock_getsockopt,
+       .connect        = sock_no_connect,
+       .socketpair     = sock_no_socketpair,
+       .accept         = sock_no_accept,
+       .mmap           = sock_no_mmap
+};
+
+static int
+data_sock_create(struct net *net, struct socket *sock, int protocol)
+{
+       struct sock *sk;
+
+       if (sock->type != SOCK_DGRAM)
+               return -ESOCKTNOSUPPORT;
+
+       sk = sk_alloc(net, PF_ISDN, GFP_KERNEL, &mISDN_proto);
+       if (!sk)
+               return -ENOMEM;
+
+       sock_init_data(sock, sk);
+
+       sock->ops = &data_sock_ops;
+       sock->state = SS_UNCONNECTED;
+       sock_reset_flag(sk, SOCK_ZAPPED);
+
+       sk->sk_protocol = protocol;
+       sk->sk_state    = MISDN_OPEN;
+       mISDN_sock_link(&data_sockets, sk);
+
+       return 0;
+}
+
+static int
+base_sock_release(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+
+       printk(KERN_DEBUG "%s(%p) sk=%p\n", __func__, sock, sk);
+       if (!sk)
+               return 0;
+
+       mISDN_sock_unlink(&base_sockets, sk);
+       sock_orphan(sk);
+       sock_put(sk);
+
+       return 0;
+}
+
+static int
+base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       int                     err = 0, id;
+       struct mISDNdevice      *dev;
+       struct mISDNversion     ver;
+
+       switch (cmd) {
+       case IMGETVERSION:
+               ver.major = MISDN_MAJOR_VERSION;
+               ver.minor = MISDN_MINOR_VERSION;
+               ver.release = MISDN_RELEASE;
+               if (copy_to_user((void __user *)arg, &ver, sizeof(ver)))
+                       err = -EFAULT;
+               break;
+       case IMGETCOUNT:
+               id = get_mdevice_count();
+               if (put_user(id, (int __user *)arg))
+                       err = -EFAULT;
+               break;
+       case IMGETDEVINFO:
+               if (get_user(id, (int __user *)arg)) {
+                       err = -EFAULT;
+                       break;
+               }
+               dev = get_mdevice(id);
+               if (dev) {
+                       struct mISDN_devinfo di;
+
+                       di.id = dev->id;
+                       di.Dprotocols = dev->Dprotocols;
+                       di.Bprotocols = dev->Bprotocols | get_all_Bprotocols();
+                       di.protocol = dev->D.protocol;
+                       memcpy(di.channelmap, dev->channelmap,
+                               MISDN_CHMAP_SIZE * 4);
+                       di.nrbchan = dev->nrbchan;
+                       strcpy(di.name, dev->name);
+                       if (copy_to_user((void __user *)arg, &di, sizeof(di)))
+                               err = -EFAULT;
+               } else
+                       err = -ENODEV;
+               break;
+       default:
+               err = -EINVAL;
+       }
+       return err;
+}
+
+static int
+base_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
+{
+       struct sockaddr_mISDN *maddr = (struct sockaddr_mISDN *) addr;
+       struct sock *sk = sock->sk;
+       int err = 0;
+
+       if (!maddr || maddr->family != AF_ISDN)
+               return -EINVAL;
+
+       lock_sock(sk);
+
+       if (_pms(sk)->dev) {
+               err = -EALREADY;
+               goto done;
+       }
+
+       _pms(sk)->dev = get_mdevice(maddr->dev);
+       if (!_pms(sk)->dev) {
+               err = -ENODEV;
+               goto done;
+       }
+       sk->sk_state = MISDN_BOUND;
+
+done:
+       release_sock(sk);
+       return err;
+}
+
+static const struct proto_ops base_sock_ops = {
+       .family         = PF_ISDN,
+       .owner          = THIS_MODULE,
+       .release        = base_sock_release,
+       .ioctl          = base_sock_ioctl,
+       .bind           = base_sock_bind,
+       .getname        = sock_no_getname,
+       .sendmsg        = sock_no_sendmsg,
+       .recvmsg        = sock_no_recvmsg,
+       .poll           = sock_no_poll,
+       .listen         = sock_no_listen,
+       .shutdown       = sock_no_shutdown,
+       .setsockopt     = sock_no_setsockopt,
+       .getsockopt     = sock_no_getsockopt,
+       .connect        = sock_no_connect,
+       .socketpair     = sock_no_socketpair,
+       .accept         = sock_no_accept,
+       .mmap           = sock_no_mmap
+};
+
+
+static int
+base_sock_create(struct net *net, struct socket *sock, int protocol)
+{
+       struct sock *sk;
+
+       if (sock->type != SOCK_RAW)
+               return -ESOCKTNOSUPPORT;
+
+       sk = sk_alloc(net, PF_ISDN, GFP_KERNEL, &mISDN_proto);
+       if (!sk)
+               return -ENOMEM;
+
+       sock_init_data(sock, sk);
+       sock->ops = &base_sock_ops;
+       sock->state = SS_UNCONNECTED;
+       sock_reset_flag(sk, SOCK_ZAPPED);
+       sk->sk_protocol = protocol;
+       sk->sk_state    = MISDN_OPEN;
+       mISDN_sock_link(&base_sockets, sk);
+
+       return 0;
+}
+
+static int
+mISDN_sock_create(struct net *net, struct socket *sock, int proto)
+{
+       int err = -EPROTONOSUPPORT;
+
+       switch  (proto) {
+       case ISDN_P_BASE:
+               err = base_sock_create(net, sock, proto);
+               break;
+       case ISDN_P_TE_S0:
+       case ISDN_P_NT_S0:
+       case ISDN_P_TE_E1:
+       case ISDN_P_NT_E1:
+       case ISDN_P_LAPD_TE:
+       case ISDN_P_LAPD_NT:
+       case ISDN_P_B_RAW:
+       case ISDN_P_B_HDLC:
+       case ISDN_P_B_X75SLP:
+       case ISDN_P_B_L2DTMF:
+       case ISDN_P_B_L2DSP:
+       case ISDN_P_B_L2DSPHDLC:
+               err = data_sock_create(net, sock, proto);
+               break;
+       default:
+               return err;
+       }
+
+       return err;
+}
+
+static struct
+net_proto_family mISDN_sock_family_ops = {
+       .owner  = THIS_MODULE,
+       .family = PF_ISDN,
+       .create = mISDN_sock_create,
+};
+
+int
+misdn_sock_init(u_int *deb)
+{
+       int err;
+
+       debug = deb;
+       err = sock_register(&mISDN_sock_family_ops);
+       if (err)
+               printk(KERN_ERR "%s: error(%d)\n", __func__, err);
+       return err;
+}
+
+void
+misdn_sock_cleanup(void)
+{
+       sock_unregister(PF_ISDN);
+}
+
diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c
new file mode 100644 (file)
index 0000000..54cfddc
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ *
+ * Author      Karsten Keil <kkeil@novell.com>
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/mISDNif.h>
+#include <linux/kthread.h>
+#include "core.h"
+
+static u_int   *debug;
+
+static inline void
+_queue_message(struct mISDNstack *st, struct sk_buff *skb)
+{
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+
+       if (*debug & DEBUG_QUEUE_FUNC)
+               printk(KERN_DEBUG "%s prim(%x) id(%x) %p\n",
+                   __func__, hh->prim, hh->id, skb);
+       skb_queue_tail(&st->msgq, skb);
+       if (likely(!test_bit(mISDN_STACK_STOPPED, &st->status))) {
+               test_and_set_bit(mISDN_STACK_WORK, &st->status);
+               wake_up_interruptible(&st->workq);
+       }
+}
+
+int
+mISDN_queue_message(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       _queue_message(ch->st, skb);
+       return 0;
+}
+
+static struct mISDNchannel *
+get_channel4id(struct mISDNstack *st, u_int id)
+{
+       struct mISDNchannel     *ch;
+
+       mutex_lock(&st->lmutex);
+       list_for_each_entry(ch, &st->layer2, list) {
+               if (id == ch->nr)
+                       goto unlock;
+       }
+       ch = NULL;
+unlock:
+       mutex_unlock(&st->lmutex);
+       return ch;
+}
+
+static void
+send_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb)
+{
+       struct hlist_node       *node;
+       struct sock             *sk;
+       struct sk_buff          *cskb = NULL;
+
+       read_lock(&sl->lock);
+       sk_for_each(sk, node, &sl->head) {
+               if (sk->sk_state != MISDN_BOUND)
+                       continue;
+               if (!cskb)
+                       cskb = skb_copy(skb, GFP_KERNEL);
+               if (!cskb) {
+                       printk(KERN_WARNING "%s no skb\n", __func__);
+                       break;
+               }
+               if (!sock_queue_rcv_skb(sk, cskb))
+                       cskb = NULL;
+       }
+       read_unlock(&sl->lock);
+       if (cskb)
+               dev_kfree_skb(cskb);
+}
+
+static void
+send_layer2(struct mISDNstack *st, struct sk_buff *skb)
+{
+       struct sk_buff          *cskb;
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+       struct mISDNchannel     *ch;
+       int                     ret;
+
+       if (!st)
+               return;
+       mutex_lock(&st->lmutex);
+       if ((hh->id & MISDN_ID_ADDR_MASK) == MISDN_ID_ANY) { /* L2 for all */
+               list_for_each_entry(ch, &st->layer2, list) {
+                       if (list_is_last(&ch->list, &st->layer2)) {
+                               cskb = skb;
+                               skb = NULL;
+                       } else {
+                               cskb = skb_copy(skb, GFP_KERNEL);
+                       }
+                       if (cskb) {
+                               ret = ch->send(ch, cskb);
+                               if (ret) {
+                                       if (*debug & DEBUG_SEND_ERR)
+                                               printk(KERN_DEBUG
+                                                   "%s ch%d prim(%x) addr(%x)"
+                                                   " err %d\n",
+                                                   __func__, ch->nr,
+                                                   hh->prim, ch->addr, ret);
+                                       dev_kfree_skb(cskb);
+                               }
+                       } else {
+                               printk(KERN_WARNING "%s ch%d addr %x no mem\n",
+                                   __func__, ch->nr, ch->addr);
+                               goto out;
+                       }
+               }
+       } else {
+               list_for_each_entry(ch, &st->layer2, list) {
+                       if ((hh->id & MISDN_ID_ADDR_MASK) == ch->addr) {
+                               ret = ch->send(ch, skb);
+                               if (!ret)
+                                       skb = NULL;
+                               goto out;
+                       }
+               }
+               ret = st->dev->teimgr->ctrl(st->dev->teimgr, CHECK_DATA, skb);
+               if (!ret)
+                       skb = NULL;
+               else if (*debug & DEBUG_SEND_ERR)
+                       printk(KERN_DEBUG
+                           "%s ch%d mgr prim(%x) addr(%x) err %d\n",
+                           __func__, ch->nr, hh->prim, ch->addr, ret);
+       }
+out:
+       mutex_unlock(&st->lmutex);
+       if (skb)
+               dev_kfree_skb(skb);
+}
+
+static inline int
+send_msg_to_layer(struct mISDNstack *st, struct sk_buff *skb)
+{
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+       struct mISDNchannel     *ch;
+       int     lm;
+
+       lm = hh->prim & MISDN_LAYERMASK;
+       if (*debug & DEBUG_QUEUE_FUNC)
+               printk(KERN_DEBUG "%s prim(%x) id(%x) %p\n",
+                   __func__, hh->prim, hh->id, skb);
+       if (lm == 0x1) {
+               if (!hlist_empty(&st->l1sock.head)) {
+                       __net_timestamp(skb);
+                       send_socklist(&st->l1sock, skb);
+               }
+               return st->layer1->send(st->layer1, skb);
+       } else if (lm == 0x2) {
+               if (!hlist_empty(&st->l1sock.head))
+                       send_socklist(&st->l1sock, skb);
+               send_layer2(st, skb);
+               return 0;
+       } else if (lm == 0x4) {
+               ch = get_channel4id(st, hh->id);
+               if (ch)
+                       return ch->send(ch, skb);
+               else
+                       printk(KERN_WARNING
+                           "%s: dev(%s) prim(%x) id(%x) no channel\n",
+                           __func__, st->dev->name, hh->prim, hh->id);
+       } else if (lm == 0x8) {
+               WARN_ON(lm == 0x8);
+               ch = get_channel4id(st, hh->id);
+               if (ch)
+                       return ch->send(ch, skb);
+               else
+                       printk(KERN_WARNING
+                           "%s: dev(%s) prim(%x) id(%x) no channel\n",
+                           __func__, st->dev->name, hh->prim, hh->id);
+       } else {
+               /* broadcast not handled yet */
+               printk(KERN_WARNING "%s: dev(%s) prim %x not delivered\n",
+                   __func__, st->dev->name, hh->prim);
+       }
+       return -ESRCH;
+}
+
+static void
+do_clear_stack(struct mISDNstack *st)
+{
+}
+
+static int
+mISDNStackd(void *data)
+{
+       struct mISDNstack *st = data;
+       int err = 0;
+
+#ifdef CONFIG_SMP
+       lock_kernel();
+#endif
+       sigfillset(&current->blocked);
+#ifdef CONFIG_SMP
+       unlock_kernel();
+#endif
+       if (*debug & DEBUG_MSG_THREAD)
+               printk(KERN_DEBUG "mISDNStackd %s started\n", st->dev->name);
+
+       if (st->notify != NULL) {
+               complete(st->notify);
+               st->notify = NULL;
+       }
+
+       for (;;) {
+               struct sk_buff  *skb;
+
+               if (unlikely(test_bit(mISDN_STACK_STOPPED, &st->status))) {
+                       test_and_clear_bit(mISDN_STACK_WORK, &st->status);
+                       test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
+               } else
+                       test_and_set_bit(mISDN_STACK_RUNNING, &st->status);
+               while (test_bit(mISDN_STACK_WORK, &st->status)) {
+                       skb = skb_dequeue(&st->msgq);
+                       if (!skb) {
+                               test_and_clear_bit(mISDN_STACK_WORK,
+                                       &st->status);
+                               /* test if a race happens */
+                               skb = skb_dequeue(&st->msgq);
+                               if (!skb)
+                                       continue;
+                               test_and_set_bit(mISDN_STACK_WORK,
+                                   &st->status);
+                       }
+#ifdef MISDN_MSG_STATS
+                       st->msg_cnt++;
+#endif
+                       err = send_msg_to_layer(st, skb);
+                       if (unlikely(err)) {
+                               if (*debug & DEBUG_SEND_ERR)
+                                       printk(KERN_DEBUG
+                                           "%s: %s prim(%x) id(%x) "
+                                           "send call(%d)\n",
+                                           __func__, st->dev->name,
+                                           mISDN_HEAD_PRIM(skb),
+                                           mISDN_HEAD_ID(skb), err);
+                               dev_kfree_skb(skb);
+                               continue;
+                       }
+                       if (unlikely(test_bit(mISDN_STACK_STOPPED,
+                           &st->status))) {
+                               test_and_clear_bit(mISDN_STACK_WORK,
+                                   &st->status);
+                               test_and_clear_bit(mISDN_STACK_RUNNING,
+                                   &st->status);
+                               break;
+                       }
+               }
+               if (test_bit(mISDN_STACK_CLEARING, &st->status)) {
+                       test_and_set_bit(mISDN_STACK_STOPPED, &st->status);
+                       test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
+                       do_clear_stack(st);
+                       test_and_clear_bit(mISDN_STACK_CLEARING, &st->status);
+                       test_and_set_bit(mISDN_STACK_RESTART, &st->status);
+               }
+               if (test_and_clear_bit(mISDN_STACK_RESTART, &st->status)) {
+                       test_and_clear_bit(mISDN_STACK_STOPPED, &st->status);
+                       test_and_set_bit(mISDN_STACK_RUNNING, &st->status);
+                       if (!skb_queue_empty(&st->msgq))
+                               test_and_set_bit(mISDN_STACK_WORK,
+                                   &st->status);
+               }
+               if (test_bit(mISDN_STACK_ABORT, &st->status))
+                       break;
+               if (st->notify != NULL) {
+                       complete(st->notify);
+                       st->notify = NULL;
+               }
+#ifdef MISDN_MSG_STATS
+               st->sleep_cnt++;
+#endif
+               test_and_clear_bit(mISDN_STACK_ACTIVE, &st->status);
+               wait_event_interruptible(st->workq, (st->status &
+                   mISDN_STACK_ACTION_MASK));
+               if (*debug & DEBUG_MSG_THREAD)
+                       printk(KERN_DEBUG "%s: %s wake status %08lx\n",
+                           __func__, st->dev->name, st->status);
+               test_and_set_bit(mISDN_STACK_ACTIVE, &st->status);
+
+               test_and_clear_bit(mISDN_STACK_WAKEUP, &st->status);
+
+               if (test_bit(mISDN_STACK_STOPPED, &st->status)) {
+                       test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
+#ifdef MISDN_MSG_STATS
+                       st->stopped_cnt++;
+#endif
+               }
+       }
+#ifdef MISDN_MSG_STATS
+       printk(KERN_DEBUG "mISDNStackd daemon for %s proceed %d "
+           "msg %d sleep %d stopped\n",
+           st->dev->name, st->msg_cnt, st->sleep_cnt, st->stopped_cnt);
+       printk(KERN_DEBUG
+           "mISDNStackd daemon for %s utime(%ld) stime(%ld)\n",
+           st->dev->name, st->thread->utime, st->thread->stime);
+       printk(KERN_DEBUG
+           "mISDNStackd daemon for %s nvcsw(%ld) nivcsw(%ld)\n",
+           st->dev->name, st->thread->nvcsw, st->thread->nivcsw);
+       printk(KERN_DEBUG "mISDNStackd daemon for %s killed now\n",
+           st->dev->name);
+#endif
+       test_and_set_bit(mISDN_STACK_KILLED, &st->status);
+       test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
+       test_and_clear_bit(mISDN_STACK_ACTIVE, &st->status);
+       test_and_clear_bit(mISDN_STACK_ABORT, &st->status);
+       skb_queue_purge(&st->msgq);
+       st->thread = NULL;
+       if (st->notify != NULL) {
+               complete(st->notify);
+               st->notify = NULL;
+       }
+       return 0;
+}
+
+static int
+l1_receive(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       if (!ch->st)
+               return -ENODEV;
+       __net_timestamp(skb);
+       _queue_message(ch->st, skb);
+       return 0;
+}
+
+void
+set_channel_address(struct mISDNchannel *ch, u_int sapi, u_int tei)
+{
+       ch->addr = sapi | (tei << 8);
+}
+
+void
+__add_layer2(struct mISDNchannel *ch, struct mISDNstack *st)
+{
+       list_add_tail(&ch->list, &st->layer2);
+}
+
+void
+add_layer2(struct mISDNchannel *ch, struct mISDNstack *st)
+{
+       mutex_lock(&st->lmutex);
+       __add_layer2(ch, st);
+       mutex_unlock(&st->lmutex);
+}
+
+static int
+st_own_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       if (!ch->st || ch->st->layer1)
+               return -EINVAL;
+       return ch->st->layer1->ctrl(ch->st->layer1, cmd, arg);
+}
+
+int
+create_stack(struct mISDNdevice *dev)
+{
+       struct mISDNstack       *newst;
+       int                     err;
+       DECLARE_COMPLETION_ONSTACK(done);
+
+       newst = kzalloc(sizeof(struct mISDNstack), GFP_KERNEL);
+       if (!newst) {
+               printk(KERN_ERR "kmalloc mISDN_stack failed\n");
+               return -ENOMEM;
+       }
+       newst->dev = dev;
+       INIT_LIST_HEAD(&newst->layer2);
+       INIT_HLIST_HEAD(&newst->l1sock.head);
+       rwlock_init(&newst->l1sock.lock);
+       init_waitqueue_head(&newst->workq);
+       skb_queue_head_init(&newst->msgq);
+       mutex_init(&newst->lmutex);
+       dev->D.st = newst;
+       err = create_teimanager(dev);
+       if (err) {
+               printk(KERN_ERR "kmalloc teimanager failed\n");
+               kfree(newst);
+               return err;
+       }
+       dev->teimgr->peer = &newst->own;
+       dev->teimgr->recv = mISDN_queue_message;
+       dev->teimgr->st = newst;
+       newst->layer1 = &dev->D;
+       dev->D.recv = l1_receive;
+       dev->D.peer = &newst->own;
+       newst->own.st = newst;
+       newst->own.ctrl = st_own_ctrl;
+       newst->own.send = mISDN_queue_message;
+       newst->own.recv = mISDN_queue_message;
+       if (*debug & DEBUG_CORE_FUNC)
+               printk(KERN_DEBUG "%s: st(%s)\n", __func__, newst->dev->name);
+       newst->notify = &done;
+       newst->thread = kthread_run(mISDNStackd, (void *)newst, "mISDN_%s",
+               newst->dev->name);
+       if (IS_ERR(newst->thread)) {
+               err = PTR_ERR(newst->thread);
+               printk(KERN_ERR
+                       "mISDN:cannot create kernel thread for %s (%d)\n",
+                       newst->dev->name, err);
+               delete_teimanager(dev->teimgr);
+               kfree(newst);
+       } else
+               wait_for_completion(&done);
+       return err;
+}
+
+int
+connect_layer1(struct mISDNdevice *dev, struct mISDNchannel *ch,
+               u_int protocol, struct sockaddr_mISDN *adr)
+{
+       struct mISDN_sock       *msk = container_of(ch, struct mISDN_sock, ch);
+       struct channel_req      rq;
+       int                     err;
+
+
+       if (*debug &  DEBUG_CORE_FUNC)
+               printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
+                       __func__, dev->name, protocol, adr->dev, adr->channel,
+                        adr->sapi, adr->tei);
+       switch (protocol) {
+       case ISDN_P_NT_S0:
+       case ISDN_P_NT_E1:
+       case ISDN_P_TE_S0:
+       case ISDN_P_TE_E1:
+#ifdef PROTOCOL_CHECK
+               /* this should be enhanced */
+               if (!list_empty(&dev->D.st->layer2)
+                       && dev->D.protocol != protocol)
+                       return -EBUSY;
+               if (!hlist_empty(&dev->D.st->l1sock.head)
+                       && dev->D.protocol != protocol)
+                       return -EBUSY;
+#endif
+               ch->recv = mISDN_queue_message;
+               ch->peer = &dev->D.st->own;
+               ch->st = dev->D.st;
+               rq.protocol = protocol;
+               rq.adr.channel = 0;
+               err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq);
+               printk(KERN_DEBUG "%s: ret 1 %d\n", __func__, err);
+               if (err)
+                       return err;
+               write_lock_bh(&dev->D.st->l1sock.lock);
+               sk_add_node(&msk->sk, &dev->D.st->l1sock.head);
+               write_unlock_bh(&dev->D.st->l1sock.lock);
+               break;
+       default:
+               return -ENOPROTOOPT;
+       }
+       return 0;
+}
+
+int
+connect_Bstack(struct mISDNdevice *dev, struct mISDNchannel *ch,
+    u_int protocol, struct sockaddr_mISDN *adr)
+{
+       struct channel_req      rq, rq2;
+       int                     pmask, err;
+       struct Bprotocol        *bp;
+
+       if (*debug &  DEBUG_CORE_FUNC)
+               printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
+                       __func__, dev->name, protocol,
+                       adr->dev, adr->channel, adr->sapi,
+                       adr->tei);
+       ch->st = dev->D.st;
+       pmask = 1 << (protocol & ISDN_P_B_MASK);
+       if (pmask & dev->Bprotocols) {
+               rq.protocol = protocol;
+               rq.adr = *adr;
+               err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq);
+               if (err)
+                       return err;
+               ch->recv = rq.ch->send;
+               ch->peer = rq.ch;
+               rq.ch->recv = ch->send;
+               rq.ch->peer = ch;
+               rq.ch->st = dev->D.st;
+       } else {
+               bp = get_Bprotocol4mask(pmask);
+               if (!bp)
+                       return -ENOPROTOOPT;
+               rq2.protocol = protocol;
+               rq2.adr = *adr;
+               rq2.ch = ch;
+               err = bp->create(&rq2);
+               if (err)
+                       return err;
+               ch->recv = rq2.ch->send;
+               ch->peer = rq2.ch;
+               rq2.ch->st = dev->D.st;
+               rq.protocol = rq2.protocol;
+               rq.adr = *adr;
+               err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq);
+               if (err) {
+                       rq2.ch->ctrl(rq2.ch, CLOSE_CHANNEL, NULL);
+                       return err;
+               }
+               rq2.ch->recv = rq.ch->send;
+               rq2.ch->peer = rq.ch;
+               rq.ch->recv = rq2.ch->send;
+               rq.ch->peer = rq2.ch;
+               rq.ch->st = dev->D.st;
+       }
+       ch->protocol = protocol;
+       ch->nr = rq.ch->nr;
+       return 0;
+}
+
+int
+create_l2entity(struct mISDNdevice *dev, struct mISDNchannel *ch,
+    u_int protocol, struct sockaddr_mISDN *adr)
+{
+       struct channel_req      rq;
+       int                     err;
+
+       if (*debug &  DEBUG_CORE_FUNC)
+               printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
+                       __func__, dev->name, protocol,
+                       adr->dev, adr->channel, adr->sapi,
+                       adr->tei);
+       rq.protocol = ISDN_P_TE_S0;
+       if (dev->Dprotocols & (1 << ISDN_P_TE_E1))
+               rq.protocol = ISDN_P_TE_E1;
+       switch (protocol) {
+       case ISDN_P_LAPD_NT:
+               rq.protocol = ISDN_P_NT_S0;
+               if (dev->Dprotocols & (1 << ISDN_P_NT_E1))
+                       rq.protocol = ISDN_P_NT_E1;
+       case ISDN_P_LAPD_TE:
+#ifdef PROTOCOL_CHECK
+               /* this should be enhanced */
+               if (!list_empty(&dev->D.st->layer2)
+                       && dev->D.protocol != protocol)
+                       return -EBUSY;
+               if (!hlist_empty(&dev->D.st->l1sock.head)
+                       && dev->D.protocol != protocol)
+                       return -EBUSY;
+#endif
+               ch->recv = mISDN_queue_message;
+               ch->peer = &dev->D.st->own;
+               ch->st = dev->D.st;
+               rq.adr.channel = 0;
+               err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq);
+               printk(KERN_DEBUG "%s: ret 1 %d\n", __func__, err);
+               if (err)
+                       break;
+               rq.protocol = protocol;
+               rq.adr = *adr;
+               rq.ch = ch;
+               err = dev->teimgr->ctrl(dev->teimgr, OPEN_CHANNEL, &rq);
+               printk(KERN_DEBUG "%s: ret 2 %d\n", __func__, err);
+               if (!err) {
+                       if ((protocol == ISDN_P_LAPD_NT) && !rq.ch)
+                               break;
+                       add_layer2(rq.ch, dev->D.st);
+                       rq.ch->recv = mISDN_queue_message;
+                       rq.ch->peer = &dev->D.st->own;
+                       rq.ch->ctrl(rq.ch, OPEN_CHANNEL, NULL); /* can't fail */
+               }
+               break;
+       default:
+               err = -EPROTONOSUPPORT;
+       }
+       return err;
+}
+
+void
+delete_channel(struct mISDNchannel *ch)
+{
+       struct mISDN_sock       *msk = container_of(ch, struct mISDN_sock, ch);
+       struct mISDNchannel     *pch;
+
+       if (!ch->st) {
+               printk(KERN_WARNING "%s: no stack\n", __func__);
+               return;
+       }
+       if (*debug & DEBUG_CORE_FUNC)
+               printk(KERN_DEBUG "%s: st(%s) protocol(%x)\n", __func__,
+                   ch->st->dev->name, ch->protocol);
+       if (ch->protocol >= ISDN_P_B_START) {
+               if (ch->peer) {
+                       ch->peer->ctrl(ch->peer, CLOSE_CHANNEL, NULL);
+                       ch->peer = NULL;
+               }
+               return;
+       }
+       switch (ch->protocol) {
+       case ISDN_P_NT_S0:
+       case ISDN_P_TE_S0:
+       case ISDN_P_NT_E1:
+       case ISDN_P_TE_E1:
+               write_lock_bh(&ch->st->l1sock.lock);
+               sk_del_node_init(&msk->sk);
+               write_unlock_bh(&ch->st->l1sock.lock);
+               ch->st->dev->D.ctrl(&ch->st->dev->D, CLOSE_CHANNEL, NULL);
+               break;
+       case ISDN_P_LAPD_TE:
+               pch = get_channel4id(ch->st, ch->nr);
+               if (pch) {
+                       mutex_lock(&ch->st->lmutex);
+                       list_del(&pch->list);
+                       mutex_unlock(&ch->st->lmutex);
+                       pch->ctrl(pch, CLOSE_CHANNEL, NULL);
+                       pch = ch->st->dev->teimgr;
+                       pch->ctrl(pch, CLOSE_CHANNEL, NULL);
+               } else
+                       printk(KERN_WARNING "%s: no l2 channel\n",
+                           __func__);
+               break;
+       case ISDN_P_LAPD_NT:
+               pch = ch->st->dev->teimgr;
+               if (pch) {
+                       pch->ctrl(pch, CLOSE_CHANNEL, NULL);
+               } else
+                       printk(KERN_WARNING "%s: no l2 channel\n",
+                           __func__);
+               break;
+       default:
+               break;
+       }
+       return;
+}
+
+void
+delete_stack(struct mISDNdevice *dev)
+{
+       struct mISDNstack       *st = dev->D.st;
+       DECLARE_COMPLETION_ONSTACK(done);
+
+       if (*debug & DEBUG_CORE_FUNC)
+               printk(KERN_DEBUG "%s: st(%s)\n", __func__,
+                   st->dev->name);
+       if (dev->teimgr)
+               delete_teimanager(dev->teimgr);
+       if (st->thread) {
+               if (st->notify) {
+                       printk(KERN_WARNING "%s: notifier in use\n",
+                           __func__);
+                               complete(st->notify);
+               }
+               st->notify = &done;
+               test_and_set_bit(mISDN_STACK_ABORT, &st->status);
+               test_and_set_bit(mISDN_STACK_WAKEUP, &st->status);
+               wake_up_interruptible(&st->workq);
+               wait_for_completion(&done);
+       }
+       if (!list_empty(&st->layer2))
+               printk(KERN_WARNING "%s: layer2 list not empty\n",
+                   __func__);
+       if (!hlist_empty(&st->l1sock.head))
+               printk(KERN_WARNING "%s: layer1 list not empty\n",
+                   __func__);
+       kfree(st);
+}
+
+void
+mISDN_initstack(u_int *dp)
+{
+       debug = dp;
+}
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
new file mode 100644 (file)
index 0000000..6fbae42
--- /dev/null
@@ -0,0 +1,1340 @@
+/*
+ *
+ * Author      Karsten Keil <kkeil@novell.com>
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "layer2.h"
+#include <linux/random.h>
+#include "core.h"
+
+#define ID_REQUEST     1
+#define ID_ASSIGNED    2
+#define ID_DENIED      3
+#define ID_CHK_REQ     4
+#define ID_CHK_RES     5
+#define ID_REMOVE      6
+#define ID_VERIFY      7
+
+#define TEI_ENTITY_ID  0xf
+
+#define MGR_PH_ACTIVE  16
+#define MGR_PH_NOTREADY        17
+
+#define DATIMER_VAL    10000
+
+static         u_int   *debug;
+
+static struct Fsm deactfsm = {NULL, 0, 0, NULL, NULL};
+static struct Fsm teifsmu = {NULL, 0, 0, NULL, NULL};
+static struct Fsm teifsmn = {NULL, 0, 0, NULL, NULL};
+
+enum {
+       ST_L1_DEACT,
+       ST_L1_DEACT_PENDING,
+       ST_L1_ACTIV,
+};
+#define DEACT_STATE_COUNT (ST_L1_ACTIV+1)
+
+static char *strDeactState[] =
+{
+       "ST_L1_DEACT",
+       "ST_L1_DEACT_PENDING",
+       "ST_L1_ACTIV",
+};
+
+enum {
+       EV_ACTIVATE,
+       EV_ACTIVATE_IND,
+       EV_DEACTIVATE,
+       EV_DEACTIVATE_IND,
+       EV_UI,
+       EV_DATIMER,
+};
+
+#define DEACT_EVENT_COUNT (EV_DATIMER+1)
+
+static char *strDeactEvent[] =
+{
+       "EV_ACTIVATE",
+       "EV_ACTIVATE_IND",
+       "EV_DEACTIVATE",
+       "EV_DEACTIVATE_IND",
+       "EV_UI",
+       "EV_DATIMER",
+};
+
+static void
+da_debug(struct FsmInst *fi, char *fmt, ...)
+{
+       struct manager  *mgr = fi->userdata;
+       va_list va;
+
+       if (!(*debug & DEBUG_L2_TEIFSM))
+               return;
+       va_start(va, fmt);
+       printk(KERN_DEBUG "mgr(%d): ", mgr->ch.st->dev->id);
+       vprintk(fmt, va);
+       printk("\n");
+       va_end(va);
+}
+
+static void
+da_activate(struct FsmInst *fi, int event, void *arg)
+{
+       struct manager  *mgr = fi->userdata;
+
+       if (fi->state == ST_L1_DEACT_PENDING)
+               mISDN_FsmDelTimer(&mgr->datimer, 1);
+       mISDN_FsmChangeState(fi, ST_L1_ACTIV);
+}
+
+static void
+da_deactivate_ind(struct FsmInst *fi, int event, void *arg)
+{
+       mISDN_FsmChangeState(fi, ST_L1_DEACT);
+}
+
+static void
+da_deactivate(struct FsmInst *fi, int event, void *arg)
+{
+       struct manager  *mgr = fi->userdata;
+       struct layer2   *l2;
+       u_long          flags;
+
+       read_lock_irqsave(&mgr->lock, flags);
+       list_for_each_entry(l2, &mgr->layer2, list) {
+               if (l2->l2m.state > ST_L2_4) {
+                       /* have still activ TEI */
+                       read_unlock_irqrestore(&mgr->lock, flags);
+                       return;
+               }
+       }
+       read_unlock_irqrestore(&mgr->lock, flags);
+       /* All TEI are inactiv */
+       mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 1);
+       mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING);
+}
+
+static void
+da_ui(struct FsmInst *fi, int event, void *arg)
+{
+       struct manager  *mgr = fi->userdata;
+
+       /* restart da timer */
+       mISDN_FsmDelTimer(&mgr->datimer, 2);
+       mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 2);
+
+}
+
+static void
+da_timer(struct FsmInst *fi, int event, void *arg)
+{
+       struct manager  *mgr = fi->userdata;
+       struct layer2   *l2;
+       u_long          flags;
+
+       /* check again */
+       read_lock_irqsave(&mgr->lock, flags);
+       list_for_each_entry(l2, &mgr->layer2, list) {
+               if (l2->l2m.state > ST_L2_4) {
+                       /* have still activ TEI */
+                       read_unlock_irqrestore(&mgr->lock, flags);
+                       mISDN_FsmChangeState(fi, ST_L1_ACTIV);
+                       return;
+               }
+       }
+       read_unlock_irqrestore(&mgr->lock, flags);
+       /* All TEI are inactiv */
+       mISDN_FsmChangeState(fi, ST_L1_DEACT);
+       _queue_data(&mgr->ch, PH_DEACTIVATE_REQ, MISDN_ID_ANY, 0, NULL,
+           GFP_ATOMIC);
+}
+
+static struct FsmNode DeactFnList[] =
+{
+       {ST_L1_DEACT, EV_ACTIVATE_IND, da_activate},
+       {ST_L1_ACTIV, EV_DEACTIVATE_IND, da_deactivate_ind},
+       {ST_L1_ACTIV, EV_DEACTIVATE, da_deactivate},
+       {ST_L1_DEACT_PENDING, EV_ACTIVATE, da_activate},
+       {ST_L1_DEACT_PENDING, EV_UI, da_ui},
+       {ST_L1_DEACT_PENDING, EV_DATIMER, da_timer},
+};
+
+enum {
+       ST_TEI_NOP,
+       ST_TEI_IDREQ,
+       ST_TEI_IDVERIFY,
+};
+
+#define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
+
+static char *strTeiState[] =
+{
+       "ST_TEI_NOP",
+       "ST_TEI_IDREQ",
+       "ST_TEI_IDVERIFY",
+};
+
+enum {
+       EV_IDREQ,
+       EV_ASSIGN,
+       EV_ASSIGN_REQ,
+       EV_DENIED,
+       EV_CHKREQ,
+       EV_CHKRESP,
+       EV_REMOVE,
+       EV_VERIFY,
+       EV_TIMER,
+};
+
+#define TEI_EVENT_COUNT (EV_TIMER+1)
+
+static char *strTeiEvent[] =
+{
+       "EV_IDREQ",
+       "EV_ASSIGN",
+       "EV_ASSIGN_REQ",
+       "EV_DENIED",
+       "EV_CHKREQ",
+       "EV_CHKRESP",
+       "EV_REMOVE",
+       "EV_VERIFY",
+       "EV_TIMER",
+};
+
+static void
+tei_debug(struct FsmInst *fi, char *fmt, ...)
+{
+       struct teimgr   *tm = fi->userdata;
+       va_list va;
+
+       if (!(*debug & DEBUG_L2_TEIFSM))
+               return;
+       va_start(va, fmt);
+       printk(KERN_DEBUG "tei(%d): ", tm->l2->tei);
+       vprintk(fmt, va);
+       printk("\n");
+       va_end(va);
+}
+
+
+
+static int
+get_free_id(struct manager *mgr)
+{
+       u64             ids = 0;
+       int             i;
+       struct layer2   *l2;
+
+       list_for_each_entry(l2, &mgr->layer2, list) {
+               if (l2->ch.nr > 63) {
+                       printk(KERN_WARNING
+                           "%s: more as 63 layer2 for one device\n",
+                           __func__);
+                       return -EBUSY;
+               }
+               test_and_set_bit(l2->ch.nr, (u_long *)&ids);
+       }
+       for (i = 1; i < 64; i++)
+               if (!test_bit(i, (u_long *)&ids))
+                       return i;
+       printk(KERN_WARNING "%s: more as 63 layer2 for one device\n",
+           __func__);
+       return -EBUSY;
+}
+
+static int
+get_free_tei(struct manager *mgr)
+{
+       u64             ids = 0;
+       int             i;
+       struct layer2   *l2;
+
+       list_for_each_entry(l2, &mgr->layer2, list) {
+               if (l2->ch.nr == 0)
+                       continue;
+               if ((l2->ch.addr & 0xff) != 0)
+                       continue;
+               i = l2->ch.addr >> 8;
+               if (i < 64)
+                       continue;
+               i -= 64;
+
+               test_and_set_bit(i, (u_long *)&ids);
+       }
+       for (i = 0; i < 64; i++)
+               if (!test_bit(i, (u_long *)&ids))
+                       return i + 64;
+       printk(KERN_WARNING "%s: more as 63 dynamic tei for one device\n",
+           __func__);
+       return -1;
+}
+
+static void
+teiup_create(struct manager *mgr, u_int prim, int len, void *arg)
+{
+       struct sk_buff  *skb;
+       struct mISDNhead *hh;
+       int             err;
+
+       skb = mI_alloc_skb(len, GFP_ATOMIC);
+       if (!skb)
+               return;
+       hh = mISDN_HEAD_P(skb);
+       hh->prim = prim;
+       hh->id = (mgr->ch.nr << 16) | mgr->ch.addr;
+       if (len)
+               memcpy(skb_put(skb, len), arg, len);
+       err = mgr->up->send(mgr->up, skb);
+       if (err) {
+               printk(KERN_WARNING "%s: err=%d\n", __func__, err);
+               dev_kfree_skb(skb);
+       }
+}
+
+static u_int
+new_id(struct manager *mgr)
+{
+       u_int   id;
+
+       id = mgr->nextid++;
+       if (id == 0x7fff)
+               mgr->nextid = 1;
+       id <<= 16;
+       id |= GROUP_TEI << 8;
+       id |= TEI_SAPI;
+       return id;
+}
+
+static void
+do_send(struct manager *mgr)
+{
+       if (!test_bit(MGR_PH_ACTIVE, &mgr->options))
+               return;
+
+       if (!test_and_set_bit(MGR_PH_NOTREADY, &mgr->options)) {
+               struct sk_buff  *skb = skb_dequeue(&mgr->sendq);
+
+               if (!skb) {
+                       test_and_clear_bit(MGR_PH_NOTREADY, &mgr->options);
+                       return;
+               }
+               mgr->lastid = mISDN_HEAD_ID(skb);
+               mISDN_FsmEvent(&mgr->deact, EV_UI, NULL);
+               if (mgr->ch.recv(mgr->ch.peer, skb)) {
+                       dev_kfree_skb(skb);
+                       test_and_clear_bit(MGR_PH_NOTREADY, &mgr->options);
+                       mgr->lastid = MISDN_ID_NONE;
+               }
+       }
+}
+
+static void
+do_ack(struct manager *mgr, u_int id)
+{
+       if (test_bit(MGR_PH_NOTREADY, &mgr->options)) {
+               if (id == mgr->lastid) {
+                       if (test_bit(MGR_PH_ACTIVE, &mgr->options)) {
+                               struct sk_buff  *skb;
+
+                               skb = skb_dequeue(&mgr->sendq);
+                               if (skb) {
+                                       mgr->lastid = mISDN_HEAD_ID(skb);
+                                       if (!mgr->ch.recv(mgr->ch.peer, skb))
+                                               return;
+                                       dev_kfree_skb(skb);
+                               }
+                       }
+                       mgr->lastid = MISDN_ID_NONE;
+                       test_and_clear_bit(MGR_PH_NOTREADY, &mgr->options);
+               }
+       }
+}
+
+static void
+mgr_send_down(struct manager *mgr, struct sk_buff *skb)
+{
+       skb_queue_tail(&mgr->sendq, skb);
+       if (!test_bit(MGR_PH_ACTIVE, &mgr->options)) {
+               _queue_data(&mgr->ch, PH_ACTIVATE_REQ, MISDN_ID_ANY, 0,
+                   NULL, GFP_KERNEL);
+       } else {
+               do_send(mgr);
+       }
+}
+
+static int
+dl_unit_data(struct manager *mgr, struct sk_buff *skb)
+{
+       if (!test_bit(MGR_OPT_NETWORK, &mgr->options)) /* only net send UI */
+               return -EINVAL;
+       if (!test_bit(MGR_PH_ACTIVE, &mgr->options))
+               _queue_data(&mgr->ch, PH_ACTIVATE_REQ, MISDN_ID_ANY, 0,
+                   NULL, GFP_KERNEL);
+       skb_push(skb, 3);
+       skb->data[0] = 0x02; /* SAPI 0 C/R = 1 */
+       skb->data[1] = 0xff; /* TEI 127 */
+       skb->data[2] = UI;   /* UI frame */
+       mISDN_HEAD_PRIM(skb) = PH_DATA_REQ;
+       mISDN_HEAD_ID(skb) = new_id(mgr);
+       skb_queue_tail(&mgr->sendq, skb);
+       do_send(mgr);
+       return 0;
+}
+
+unsigned int
+random_ri(void)
+{
+       u16 x;
+
+       get_random_bytes(&x, sizeof(x));
+       return x;
+}
+
+static struct layer2 *
+findtei(struct manager *mgr, int tei)
+{
+       struct layer2   *l2;
+       u_long          flags;
+
+       read_lock_irqsave(&mgr->lock, flags);
+       list_for_each_entry(l2, &mgr->layer2, list) {
+               if ((l2->sapi == 0) && (l2->tei > 0) &&
+                   (l2->tei != GROUP_TEI) && (l2->tei == tei))
+                       goto done;
+       }
+       l2 = NULL;
+done:
+       read_unlock_irqrestore(&mgr->lock, flags);
+       return l2;
+}
+
+static void
+put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, u_char tei)
+{
+       struct sk_buff *skb;
+       u_char bp[8];
+
+       bp[0] = (TEI_SAPI << 2);
+       if (test_bit(MGR_OPT_NETWORK, &mgr->options))
+               bp[0] |= 2; /* CR:=1 for net command */
+       bp[1] = (GROUP_TEI << 1) | 0x1;
+       bp[2] = UI;
+       bp[3] = TEI_ENTITY_ID;
+       bp[4] = ri >> 8;
+       bp[5] = ri & 0xff;
+       bp[6] = m_id;
+       bp[7] = (tei << 1) | 1;
+       skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr),
+           8, bp, GFP_ATOMIC);
+       if (!skb) {
+               printk(KERN_WARNING "%s: no skb for tei msg\n", __func__);
+               return;
+       }
+       mgr_send_down(mgr, skb);
+}
+
+static void
+tei_id_request(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+
+       if (tm->l2->tei != GROUP_TEI) {
+               tm->tei_m.printdebug(&tm->tei_m,
+                       "assign request for allready assigned tei %d",
+                       tm->l2->tei);
+               return;
+       }
+       tm->ri = random_ri();
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(&tm->tei_m,
+                       "assign request ri %d", tm->ri);
+       put_tei_msg(tm->mgr, ID_REQUEST, tm->ri, GROUP_TEI);
+       mISDN_FsmChangeState(fi, ST_TEI_IDREQ);
+       mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 1);
+       tm->nval = 3;
+}
+
+static void
+tei_id_assign(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr   *tm = fi->userdata;
+       struct layer2   *l2;
+       u_char *dp = arg;
+       int ri, tei;
+
+       ri = ((unsigned int) *dp++ << 8);
+       ri += *dp++;
+       dp++;
+       tei = *dp >> 1;
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(fi, "identity assign ri %d tei %d",
+                       ri, tei);
+       l2 = findtei(tm->mgr, tei);
+       if (l2) {       /* same tei is in use */
+               if (ri != l2->tm->ri) {
+                       tm->tei_m.printdebug(fi,
+                               "possible duplicate assignment tei %d", tei);
+                       tei_l2(l2, MDL_ERROR_RSP, 0);
+               }
+       } else if (ri == tm->ri) {
+               mISDN_FsmDelTimer(&tm->timer, 1);
+               mISDN_FsmChangeState(fi, ST_TEI_NOP);
+               tei_l2(tm->l2, MDL_ASSIGN_REQ, tei);
+       }
+}
+
+static void
+tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr   *tm = fi->userdata;
+       struct layer2   *l2;
+       u_char *dp = arg;
+       int tei, ri;
+
+       ri = ((unsigned int) *dp++ << 8);
+       ri += *dp++;
+       dp++;
+       tei = *dp >> 1;
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(fi, "foreign identity assign ri %d tei %d",
+                       ri, tei);
+       l2 = findtei(tm->mgr, tei);
+       if (l2) {       /* same tei is in use */
+               if (ri != l2->tm->ri) { /* and it wasn't our request */
+                       tm->tei_m.printdebug(fi,
+                               "possible duplicate assignment tei %d", tei);
+                       mISDN_FsmEvent(&l2->tm->tei_m, EV_VERIFY, NULL);
+               }
+       }
+}
+
+static void
+tei_id_denied(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+       u_char *dp = arg;
+       int ri, tei;
+
+       ri = ((unsigned int) *dp++ << 8);
+       ri += *dp++;
+       dp++;
+       tei = *dp >> 1;
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(fi, "identity denied ri %d tei %d",
+                       ri, tei);
+}
+
+static void
+tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+       u_char *dp = arg;
+       int tei;
+
+       tei = *(dp+3) >> 1;
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(fi, "identity check req tei %d", tei);
+       if ((tm->l2->tei != GROUP_TEI) && ((tei == GROUP_TEI) ||
+           (tei == tm->l2->tei))) {
+               mISDN_FsmDelTimer(&tm->timer, 4);
+               mISDN_FsmChangeState(&tm->tei_m, ST_TEI_NOP);
+               put_tei_msg(tm->mgr, ID_CHK_RES, random_ri(), tm->l2->tei);
+       }
+}
+
+static void
+tei_id_remove(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+       u_char *dp = arg;
+       int tei;
+
+       tei = *(dp+3) >> 1;
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(fi, "identity remove tei %d", tei);
+       if ((tm->l2->tei != GROUP_TEI) &&
+           ((tei == GROUP_TEI) || (tei == tm->l2->tei))) {
+               mISDN_FsmDelTimer(&tm->timer, 5);
+               mISDN_FsmChangeState(&tm->tei_m, ST_TEI_NOP);
+               tei_l2(tm->l2, MDL_REMOVE_REQ, 0);
+       }
+}
+
+static void
+tei_id_verify(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(fi, "id verify request for tei %d",
+                       tm->l2->tei);
+       put_tei_msg(tm->mgr, ID_VERIFY, 0, tm->l2->tei);
+       mISDN_FsmChangeState(&tm->tei_m, ST_TEI_IDVERIFY);
+       mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 2);
+       tm->nval = 2;
+}
+
+static void
+tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+
+       if (--tm->nval) {
+               tm->ri = random_ri();
+               if (*debug & DEBUG_L2_TEI)
+                       tm->tei_m.printdebug(fi, "assign req(%d) ri %d",
+                               4 - tm->nval, tm->ri);
+               put_tei_msg(tm->mgr, ID_REQUEST, tm->ri, GROUP_TEI);
+               mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 3);
+       } else {
+               tm->tei_m.printdebug(fi, "assign req failed");
+               tei_l2(tm->l2, MDL_ERROR_RSP, 0);
+               mISDN_FsmChangeState(fi, ST_TEI_NOP);
+       }
+}
+
+static void
+tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+
+       if (--tm->nval) {
+               if (*debug & DEBUG_L2_TEI)
+                       tm->tei_m.printdebug(fi,
+                               "id verify req(%d) for tei %d",
+                               3 - tm->nval, tm->l2->tei);
+               put_tei_msg(tm->mgr, ID_VERIFY, 0, tm->l2->tei);
+               mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 4);
+       } else {
+               tm->tei_m.printdebug(fi, "verify req for tei %d failed",
+                       tm->l2->tei);
+               tei_l2(tm->l2, MDL_REMOVE_REQ, 0);
+               mISDN_FsmChangeState(fi, ST_TEI_NOP);
+       }
+}
+
+static struct FsmNode TeiFnListUser[] =
+{
+       {ST_TEI_NOP, EV_IDREQ, tei_id_request},
+       {ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
+       {ST_TEI_NOP, EV_VERIFY, tei_id_verify},
+       {ST_TEI_NOP, EV_REMOVE, tei_id_remove},
+       {ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
+       {ST_TEI_IDREQ, EV_TIMER, tei_id_req_tout},
+       {ST_TEI_IDREQ, EV_ASSIGN, tei_id_assign},
+       {ST_TEI_IDREQ, EV_DENIED, tei_id_denied},
+       {ST_TEI_IDVERIFY, EV_TIMER, tei_id_ver_tout},
+       {ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
+       {ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
+};
+
+static void
+tei_l2remove(struct layer2 *l2)
+{
+       put_tei_msg(l2->tm->mgr, ID_REMOVE, 0, l2->tei);
+       tei_l2(l2, MDL_REMOVE_REQ, 0);
+       list_del(&l2->ch.list);
+       l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
+}
+
+static void
+tei_assign_req(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+       u_char *dp = arg;
+
+       if (tm->l2->tei == GROUP_TEI) {
+               tm->tei_m.printdebug(&tm->tei_m,
+                       "net tei assign request without tei");
+               return;
+       }
+       tm->ri = ((unsigned int) *dp++ << 8);
+       tm->ri += *dp++;
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(&tm->tei_m,
+                       "net assign request ri %d teim %d", tm->ri, *dp);
+       put_tei_msg(tm->mgr, ID_ASSIGNED, tm->ri, tm->l2->tei);
+       mISDN_FsmChangeState(fi, ST_TEI_NOP);
+}
+
+static void
+tei_id_chk_req_net(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr   *tm = fi->userdata;
+
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(fi, "id check request for tei %d",
+                   tm->l2->tei);
+       tm->rcnt = 0;
+       put_tei_msg(tm->mgr, ID_CHK_REQ, 0, tm->l2->tei);
+       mISDN_FsmChangeState(&tm->tei_m, ST_TEI_IDVERIFY);
+       mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 2);
+       tm->nval = 2;
+}
+
+static void
+tei_id_chk_resp(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+       u_char *dp = arg;
+       int tei;
+
+       tei = dp[3] >> 1;
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(fi, "identity check resp tei %d", tei);
+       if (tei == tm->l2->tei)
+               tm->rcnt++;
+}
+
+static void
+tei_id_verify_net(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+       u_char *dp = arg;
+       int tei;
+
+       tei = dp[3] >> 1;
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(fi, "identity verify req tei %d/%d",
+                   tei, tm->l2->tei);
+       if (tei == tm->l2->tei)
+               tei_id_chk_req_net(fi, event, arg);
+}
+
+static void
+tei_id_ver_tout_net(struct FsmInst *fi, int event, void *arg)
+{
+       struct teimgr *tm = fi->userdata;
+
+       if (tm->rcnt == 1) {
+               if (*debug & DEBUG_L2_TEI)
+                       tm->tei_m.printdebug(fi,
+                           "check req for tei %d sucessful\n", tm->l2->tei);
+               mISDN_FsmChangeState(fi, ST_TEI_NOP);
+       } else if (tm->rcnt > 1) {
+               /* duplicate assignment; remove */
+               tei_l2remove(tm->l2);
+       } else if (--tm->nval) {
+               if (*debug & DEBUG_L2_TEI)
+                       tm->tei_m.printdebug(fi,
+                               "id check req(%d) for tei %d",
+                               3 - tm->nval, tm->l2->tei);
+               put_tei_msg(tm->mgr, ID_CHK_REQ, 0, tm->l2->tei);
+               mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 4);
+       } else {
+               tm->tei_m.printdebug(fi, "check req for tei %d failed",
+                       tm->l2->tei);
+               mISDN_FsmChangeState(fi, ST_TEI_NOP);
+               tei_l2remove(tm->l2);
+       }
+}
+
+static struct FsmNode TeiFnListNet[] =
+{
+       {ST_TEI_NOP, EV_ASSIGN_REQ, tei_assign_req},
+       {ST_TEI_NOP, EV_VERIFY, tei_id_verify_net},
+       {ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req_net},
+       {ST_TEI_IDVERIFY, EV_TIMER, tei_id_ver_tout_net},
+       {ST_TEI_IDVERIFY, EV_CHKRESP, tei_id_chk_resp},
+};
+
+static void
+tei_ph_data_ind(struct teimgr *tm, u_int mt, u_char *dp, int len)
+{
+       if (test_bit(FLG_FIXED_TEI, &tm->l2->flag))
+               return;
+       if (*debug & DEBUG_L2_TEI)
+               tm->tei_m.printdebug(&tm->tei_m, "tei handler mt %x", mt);
+       if (mt == ID_ASSIGNED)
+               mISDN_FsmEvent(&tm->tei_m, EV_ASSIGN, dp);
+       else if (mt == ID_DENIED)
+               mISDN_FsmEvent(&tm->tei_m, EV_DENIED, dp);
+       else if (mt == ID_CHK_REQ)
+               mISDN_FsmEvent(&tm->tei_m, EV_CHKREQ, dp);
+       else if (mt == ID_REMOVE)
+               mISDN_FsmEvent(&tm->tei_m, EV_REMOVE, dp);
+       else if (mt == ID_VERIFY)
+               mISDN_FsmEvent(&tm->tei_m, EV_VERIFY, dp);
+       else if (mt == ID_CHK_RES)
+               mISDN_FsmEvent(&tm->tei_m, EV_CHKRESP, dp);
+}
+
+static struct layer2 *
+create_new_tei(struct manager *mgr, int tei)
+{
+       u_long          opt = 0;
+       u_long          flags;
+       int             id;
+       struct layer2   *l2;
+
+       if (!mgr->up)
+               return NULL;
+       if (tei < 64)
+               test_and_set_bit(OPTION_L2_FIXEDTEI, &opt);
+       if (mgr->ch.st->dev->Dprotocols
+         & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
+               test_and_set_bit(OPTION_L2_PMX, &opt);
+       l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, (u_int)opt, (u_long)tei);
+       if (!l2) {
+               printk(KERN_WARNING "%s:no memory for layer2\n", __func__);
+               return NULL;
+       }
+       l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL);
+       if (!l2->tm) {
+               kfree(l2);
+               printk(KERN_WARNING "%s:no memory for teimgr\n", __func__);
+               return NULL;
+       }
+       l2->tm->mgr = mgr;
+       l2->tm->l2 = l2;
+       l2->tm->tei_m.debug = *debug & DEBUG_L2_TEIFSM;
+       l2->tm->tei_m.userdata = l2->tm;
+       l2->tm->tei_m.printdebug = tei_debug;
+       l2->tm->tei_m.fsm = &teifsmn;
+       l2->tm->tei_m.state = ST_TEI_NOP;
+       l2->tm->tval = 2000; /* T202  2 sec */
+       mISDN_FsmInitTimer(&l2->tm->tei_m, &l2->tm->timer);
+       write_lock_irqsave(&mgr->lock, flags);
+       id = get_free_id(mgr);
+       list_add_tail(&l2->list, &mgr->layer2);
+       write_unlock_irqrestore(&mgr->lock, flags);
+       if (id < 0) {
+               l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
+               printk(KERN_WARNING "%s:no free id\n", __func__);
+               return NULL;
+       } else {
+               l2->ch.nr = id;
+               __add_layer2(&l2->ch, mgr->ch.st);
+               l2->ch.recv = mgr->ch.recv;
+               l2->ch.peer = mgr->ch.peer;
+               l2->ch.ctrl(&l2->ch, OPEN_CHANNEL, NULL);
+       }
+       return l2;
+}
+
+static void
+new_tei_req(struct manager *mgr, u_char *dp)
+{
+       int             tei, ri;
+       struct layer2   *l2;
+
+       ri = dp[0] << 8;
+       ri += dp[1];
+       if (!mgr->up)
+               goto denied;
+       tei = get_free_tei(mgr);
+       if (tei < 0) {
+               printk(KERN_WARNING "%s:No free tei\n", __func__);
+               goto denied;
+       }
+       l2 = create_new_tei(mgr, tei);
+       if (!l2)
+               goto denied;
+       else
+               mISDN_FsmEvent(&l2->tm->tei_m, EV_ASSIGN_REQ, dp);
+       return;
+denied:
+       put_tei_msg(mgr, ID_DENIED, ri, GROUP_TEI);
+}
+
+static int
+ph_data_ind(struct manager *mgr, struct sk_buff *skb)
+{
+       int             ret = -EINVAL;
+       struct layer2   *l2;
+       u_long          flags;
+       u_char          mt;
+
+       if (skb->len < 8) {
+               if (*debug  & DEBUG_L2_TEI)
+                       printk(KERN_DEBUG "%s: short mgr frame %d/8\n",
+                           __func__, skb->len);
+               goto done;
+       }
+       if (*debug  & DEBUG_L2_TEI)
+
+       if ((skb->data[0] >> 2) != TEI_SAPI) /* not for us */
+               goto done;
+       if (skb->data[0] & 1) /* EA0 formal error */
+               goto done;
+       if (!(skb->data[1] & 1)) /* EA1 formal error */
+               goto done;
+       if ((skb->data[1] >> 1) != GROUP_TEI) /* not for us */
+               goto done;
+       if ((skb->data[2] & 0xef) != UI) /* not UI */
+               goto done;
+       if (skb->data[3] != TEI_ENTITY_ID) /* not tei entity */
+               goto done;
+       mt = skb->data[6];
+       switch (mt) {
+       case ID_REQUEST:
+       case ID_CHK_RES:
+       case ID_VERIFY:
+               if (!test_bit(MGR_OPT_NETWORK, &mgr->options))
+                       goto done;
+               break;
+       case ID_ASSIGNED:
+       case ID_DENIED:
+       case ID_CHK_REQ:
+       case ID_REMOVE:
+               if (test_bit(MGR_OPT_NETWORK, &mgr->options))
+                       goto done;
+               break;
+       default:
+               goto done;
+       }
+       ret = 0;
+       if (mt == ID_REQUEST) {
+               new_tei_req(mgr, &skb->data[4]);
+               goto done;
+       }
+       read_lock_irqsave(&mgr->lock, flags);
+       list_for_each_entry(l2, &mgr->layer2, list) {
+               tei_ph_data_ind(l2->tm, mt, &skb->data[4], skb->len - 4);
+       }
+       read_unlock_irqrestore(&mgr->lock, flags);
+done:
+       return ret;
+}
+
+int
+l2_tei(struct layer2 *l2, u_int cmd, u_long arg)
+{
+       struct teimgr   *tm = l2->tm;
+
+       if (test_bit(FLG_FIXED_TEI, &l2->flag))
+               return 0;
+       if (*debug & DEBUG_L2_TEI)
+               printk(KERN_DEBUG "%s: cmd(%x)\n", __func__, cmd);
+       switch (cmd) {
+       case MDL_ASSIGN_IND:
+               mISDN_FsmEvent(&tm->tei_m, EV_IDREQ, NULL);
+               break;
+       case MDL_ERROR_IND:
+               if (test_bit(MGR_OPT_NETWORK, &tm->mgr->options))
+                       mISDN_FsmEvent(&tm->tei_m, EV_CHKREQ, &l2->tei);
+               if (test_bit(MGR_OPT_USER, &tm->mgr->options))
+                       mISDN_FsmEvent(&tm->tei_m, EV_VERIFY, NULL);
+               break;
+       case MDL_STATUS_UP_IND:
+               if (test_bit(MGR_OPT_NETWORK, &tm->mgr->options))
+                       mISDN_FsmEvent(&tm->mgr->deact, EV_ACTIVATE, NULL);
+               break;
+       case MDL_STATUS_DOWN_IND:
+               if (test_bit(MGR_OPT_NETWORK, &tm->mgr->options))
+                       mISDN_FsmEvent(&tm->mgr->deact, EV_DEACTIVATE, NULL);
+               break;
+       case MDL_STATUS_UI_IND:
+               if (test_bit(MGR_OPT_NETWORK, &tm->mgr->options))
+                       mISDN_FsmEvent(&tm->mgr->deact, EV_UI, NULL);
+               break;
+       }
+       return 0;
+}
+
+void
+TEIrelease(struct layer2 *l2)
+{
+       struct teimgr   *tm = l2->tm;
+       u_long          flags;
+
+       mISDN_FsmDelTimer(&tm->timer, 1);
+       write_lock_irqsave(&tm->mgr->lock, flags);
+       list_del(&l2->list);
+       write_unlock_irqrestore(&tm->mgr->lock, flags);
+       l2->tm = NULL;
+       kfree(tm);
+}
+
+static int
+create_teimgr(struct manager *mgr, struct channel_req *crq)
+{
+       struct layer2   *l2;
+       u_long          opt = 0;
+       u_long          flags;
+       int             id;
+
+       if (*debug & DEBUG_L2_TEI)
+               printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
+                       __func__, mgr->ch.st->dev->name, crq->protocol,
+                       crq->adr.dev, crq->adr.channel, crq->adr.sapi,
+                       crq->adr.tei);
+       if (crq->adr.sapi != 0) /* not supported yet */
+               return -EINVAL;
+       if (crq->adr.tei > GROUP_TEI)
+               return -EINVAL;
+       if (crq->adr.tei < 64)
+               test_and_set_bit(OPTION_L2_FIXEDTEI, &opt);
+       if (crq->adr.tei == 0)
+               test_and_set_bit(OPTION_L2_PTP, &opt);
+       if (test_bit(MGR_OPT_NETWORK, &mgr->options)) {
+               if (crq->protocol == ISDN_P_LAPD_TE)
+                       return -EPROTONOSUPPORT;
+               if ((crq->adr.tei != 0) && (crq->adr.tei != 127))
+                       return -EINVAL;
+               if (mgr->up) {
+                       printk(KERN_WARNING
+                           "%s: only one network manager is allowed\n",
+                           __func__);
+                       return -EBUSY;
+               }
+       } else if (test_bit(MGR_OPT_USER, &mgr->options)) {
+               if (crq->protocol == ISDN_P_LAPD_NT)
+                       return -EPROTONOSUPPORT;
+               if ((crq->adr.tei >= 64) && (crq->adr.tei < GROUP_TEI))
+                       return -EINVAL; /* dyn tei */
+       } else {
+               if (crq->protocol == ISDN_P_LAPD_NT)
+                       test_and_set_bit(MGR_OPT_NETWORK, &mgr->options);
+               if (crq->protocol == ISDN_P_LAPD_TE)
+                       test_and_set_bit(MGR_OPT_USER, &mgr->options);
+       }
+       if (mgr->ch.st->dev->Dprotocols
+         & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
+               test_and_set_bit(OPTION_L2_PMX, &opt);
+       if ((crq->protocol == ISDN_P_LAPD_NT) && (crq->adr.tei == 127)) {
+               mgr->up = crq->ch;
+               id = DL_INFO_L2_CONNECT;
+               teiup_create(mgr, DL_INFORMATION_IND, sizeof(id), &id);
+               crq->ch = NULL;
+               if (!list_empty(&mgr->layer2)) {
+                       read_lock_irqsave(&mgr->lock, flags);
+                       list_for_each_entry(l2, &mgr->layer2, list) {
+                               l2->up = mgr->up;
+                               l2->ch.ctrl(&l2->ch, OPEN_CHANNEL, NULL);
+                       }
+                       read_unlock_irqrestore(&mgr->lock, flags);
+               }
+               return 0;
+       }
+       l2 = create_l2(crq->ch, crq->protocol, (u_int)opt,
+               (u_long)crq->adr.tei);
+       if (!l2)
+               return -ENOMEM;
+       l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL);
+       if (!l2->tm) {
+               kfree(l2);
+               printk(KERN_ERR "kmalloc teimgr failed\n");
+               return -ENOMEM;
+       }
+       l2->tm->mgr = mgr;
+       l2->tm->l2 = l2;
+       l2->tm->tei_m.debug = *debug & DEBUG_L2_TEIFSM;
+       l2->tm->tei_m.userdata = l2->tm;
+       l2->tm->tei_m.printdebug = tei_debug;
+       if (crq->protocol == ISDN_P_LAPD_TE) {
+               l2->tm->tei_m.fsm = &teifsmu;
+               l2->tm->tei_m.state = ST_TEI_NOP;
+               l2->tm->tval = 1000; /* T201  1 sec */
+       } else {
+               l2->tm->tei_m.fsm = &teifsmn;
+               l2->tm->tei_m.state = ST_TEI_NOP;
+               l2->tm->tval = 2000; /* T202  2 sec */
+       }
+       mISDN_FsmInitTimer(&l2->tm->tei_m, &l2->tm->timer);
+       write_lock_irqsave(&mgr->lock, flags);
+       id = get_free_id(mgr);
+       list_add_tail(&l2->list, &mgr->layer2);
+       write_unlock_irqrestore(&mgr->lock, flags);
+       if (id < 0) {
+               l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
+       } else {
+               l2->ch.nr = id;
+               l2->up->nr = id;
+               crq->ch = &l2->ch;
+               id = 0;
+       }
+       return id;
+}
+
+static int
+mgr_send(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct manager  *mgr;
+       struct mISDNhead        *hh =  mISDN_HEAD_P(skb);
+       int                     ret = -EINVAL;
+
+       mgr = container_of(ch, struct manager, ch);
+       if (*debug & DEBUG_L2_RECV)
+               printk(KERN_DEBUG "%s: prim(%x) id(%x)\n",
+                   __func__, hh->prim, hh->id);
+       switch (hh->prim) {
+       case PH_DATA_IND:
+               mISDN_FsmEvent(&mgr->deact, EV_UI, NULL);
+               ret = ph_data_ind(mgr, skb);
+               break;
+       case PH_DATA_CNF:
+               do_ack(mgr, hh->id);
+               ret = 0;
+               break;
+       case PH_ACTIVATE_IND:
+               test_and_set_bit(MGR_PH_ACTIVE, &mgr->options);
+               mISDN_FsmEvent(&mgr->deact, EV_ACTIVATE_IND, NULL);
+               do_send(mgr);
+               ret = 0;
+               break;
+       case PH_DEACTIVATE_IND:
+               test_and_clear_bit(MGR_PH_ACTIVE, &mgr->options);
+               mISDN_FsmEvent(&mgr->deact, EV_DEACTIVATE_IND, NULL);
+               ret = 0;
+               break;
+       case DL_UNITDATA_REQ:
+               return dl_unit_data(mgr, skb);
+       }
+       if (!ret)
+               dev_kfree_skb(skb);
+       return ret;
+}
+
+static int
+free_teimanager(struct manager *mgr)
+{
+       struct layer2   *l2, *nl2;
+
+       if (test_bit(MGR_OPT_NETWORK, &mgr->options)) {
+               /* not locked lock is taken in release tei */
+               mgr->up = NULL;
+               if (test_bit(OPTION_L2_CLEANUP, &mgr->options)) {
+                       list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) {
+                               put_tei_msg(mgr, ID_REMOVE, 0, l2->tei);
+                               mutex_lock(&mgr->ch.st->lmutex);
+                               list_del(&l2->ch.list);
+                               mutex_unlock(&mgr->ch.st->lmutex);
+                               l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
+                       }
+                       test_and_clear_bit(MGR_OPT_NETWORK, &mgr->options);
+               } else {
+                       list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) {
+                               l2->up = NULL;
+                       }
+               }
+       }
+       if (test_bit(MGR_OPT_USER, &mgr->options)) {
+               if (list_empty(&mgr->layer2))
+                       test_and_clear_bit(MGR_OPT_USER, &mgr->options);
+       }
+       mgr->ch.st->dev->D.ctrl(&mgr->ch.st->dev->D, CLOSE_CHANNEL, NULL);
+       return 0;
+}
+
+static int
+ctrl_teimanager(struct manager *mgr, void *arg)
+{
+       /* currently we only have one option */
+       int     clean = *((int *)arg);
+
+       if (clean)
+               test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options);
+       else
+               test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options);
+       return 0;
+}
+
+/* This function does create a L2 for fixed TEI in NT Mode */
+static int
+check_data(struct manager *mgr, struct sk_buff *skb)
+{
+       struct mISDNhead        *hh =  mISDN_HEAD_P(skb);
+       int                     ret, tei;
+       struct layer2           *l2;
+
+       if (*debug & DEBUG_L2_CTRL)
+               printk(KERN_DEBUG "%s: prim(%x) id(%x)\n",
+                   __func__, hh->prim, hh->id);
+       if (test_bit(MGR_OPT_USER, &mgr->options))
+               return -ENOTCONN;
+       if (hh->prim != PH_DATA_IND)
+               return -ENOTCONN;
+       if (skb->len != 3)
+               return -ENOTCONN;
+       if (skb->data[0] != 0)
+               /* only SAPI 0 command */
+               return -ENOTCONN;
+       if (!(skb->data[1] & 1)) /* invalid EA1 */
+               return -EINVAL;
+       tei = skb->data[1] >> 0;
+       if (tei > 63) /* not a fixed tei */
+               return -ENOTCONN;
+       if ((skb->data[2] & ~0x10) != SABME)
+               return -ENOTCONN;
+       /* We got a SABME for a fixed TEI */
+       l2 = create_new_tei(mgr, tei);
+       if (!l2)
+               return -ENOMEM;
+       ret = l2->ch.send(&l2->ch, skb);
+       return ret;
+}
+
+void
+delete_teimanager(struct mISDNchannel *ch)
+{
+       struct manager  *mgr;
+       struct layer2   *l2, *nl2;
+
+       mgr = container_of(ch, struct manager, ch);
+       /* not locked lock is taken in release tei */
+       list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) {
+               mutex_lock(&mgr->ch.st->lmutex);
+               list_del(&l2->ch.list);
+               mutex_unlock(&mgr->ch.st->lmutex);
+               l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
+       }
+       list_del(&mgr->ch.list);
+       list_del(&mgr->bcast.list);
+       skb_queue_purge(&mgr->sendq);
+       kfree(mgr);
+}
+
+static int
+mgr_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+       struct manager  *mgr;
+       int             ret = -EINVAL;
+
+       mgr = container_of(ch, struct manager, ch);
+       if (*debug & DEBUG_L2_CTRL)
+               printk(KERN_DEBUG "%s(%x, %p)\n", __func__, cmd, arg);
+       switch (cmd) {
+       case OPEN_CHANNEL:
+               ret = create_teimgr(mgr, arg);
+               break;
+       case CLOSE_CHANNEL:
+               ret = free_teimanager(mgr);
+               break;
+       case CONTROL_CHANNEL:
+               ret = ctrl_teimanager(mgr, arg);
+               break;
+       case CHECK_DATA:
+               ret = check_data(mgr, arg);
+               break;
+       }
+       return ret;
+}
+
+static int
+mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+       struct manager          *mgr = container_of(ch, struct manager, bcast);
+       struct mISDNhead        *hh = mISDN_HEAD_P(skb);
+       struct sk_buff          *cskb = NULL;
+       struct layer2           *l2;
+       u_long                  flags;
+       int                     ret;
+
+       read_lock_irqsave(&mgr->lock, flags);
+       list_for_each_entry(l2, &mgr->layer2, list) {
+               if ((hh->id & MISDN_ID_SAPI_MASK) ==
+                   (l2->ch.addr & MISDN_ID_SAPI_MASK)) {
+                       if (list_is_last(&l2->list, &mgr->layer2)) {
+                               cskb = skb;
+                               skb = NULL;
+                       } else {
+                               if (!cskb)
+                                       cskb = skb_copy(skb, GFP_KERNEL);
+                       }
+                       if (cskb) {
+                               ret = l2->ch.send(&l2->ch, cskb);
+                               if (ret) {
+                                       if (*debug & DEBUG_SEND_ERR)
+                                               printk(KERN_DEBUG
+                                                   "%s ch%d prim(%x) addr(%x)"
+                                                   " err %d\n",
+                                                   __func__, l2->ch.nr,
+                                                   hh->prim, l2->ch.addr, ret);
+                               } else
+                                       cskb = NULL;
+                       } else {
+                               printk(KERN_WARNING "%s ch%d addr %x no mem\n",
+                                   __func__, ch->nr, ch->addr);
+                               goto out;
+                       }
+               }
+       }
+out:
+       read_unlock_irqrestore(&mgr->lock, flags);
+       if (cskb)
+               dev_kfree_skb(cskb);
+       if (skb)
+               dev_kfree_skb(skb);
+       return 0;
+}
+
+static int
+mgr_bcast_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+
+       return -EINVAL;
+}
+
+int
+create_teimanager(struct mISDNdevice *dev)
+{
+       struct manager *mgr;
+
+       mgr = kzalloc(sizeof(struct manager), GFP_KERNEL);
+       if (!mgr)
+               return -ENOMEM;
+       INIT_LIST_HEAD(&mgr->layer2);
+       mgr->lock = __RW_LOCK_UNLOCKED(mgr->lock);
+       skb_queue_head_init(&mgr->sendq);
+       mgr->nextid = 1;
+       mgr->lastid = MISDN_ID_NONE;
+       mgr->ch.send = mgr_send;
+       mgr->ch.ctrl = mgr_ctrl;
+       mgr->ch.st = dev->D.st;
+       set_channel_address(&mgr->ch, TEI_SAPI, GROUP_TEI);
+       add_layer2(&mgr->ch, dev->D.st);
+       mgr->bcast.send = mgr_bcast;
+       mgr->bcast.ctrl = mgr_bcast_ctrl;
+       mgr->bcast.st = dev->D.st;
+       set_channel_address(&mgr->bcast, 0, GROUP_TEI);
+       add_layer2(&mgr->bcast, dev->D.st);
+       mgr->deact.debug = *debug & DEBUG_MANAGER;
+       mgr->deact.userdata = mgr;
+       mgr->deact.printdebug = da_debug;
+       mgr->deact.fsm = &deactfsm;
+       mgr->deact.state = ST_L1_DEACT;
+       mISDN_FsmInitTimer(&mgr->deact, &mgr->datimer);
+       dev->teimgr = &mgr->ch;
+       return 0;
+}
+
+int TEIInit(u_int *deb)
+{
+       debug = deb;
+       teifsmu.state_count = TEI_STATE_COUNT;
+       teifsmu.event_count = TEI_EVENT_COUNT;
+       teifsmu.strEvent = strTeiEvent;
+       teifsmu.strState = strTeiState;
+       mISDN_FsmNew(&teifsmu, TeiFnListUser, ARRAY_SIZE(TeiFnListUser));
+       teifsmn.state_count = TEI_STATE_COUNT;
+       teifsmn.event_count = TEI_EVENT_COUNT;
+       teifsmn.strEvent = strTeiEvent;
+       teifsmn.strState = strTeiState;
+       mISDN_FsmNew(&teifsmn, TeiFnListNet, ARRAY_SIZE(TeiFnListNet));
+       deactfsm.state_count =  DEACT_STATE_COUNT;
+       deactfsm.event_count = DEACT_EVENT_COUNT;
+       deactfsm.strEvent = strDeactEvent;
+       deactfsm.strState = strDeactState;
+       mISDN_FsmNew(&deactfsm, DeactFnList, ARRAY_SIZE(DeactFnList));
+       return 0;
+}
+
+void TEIFree(void)
+{
+       mISDN_FsmFree(&teifsmu);
+       mISDN_FsmFree(&teifsmn);
+       mISDN_FsmFree(&deactfsm);
+}
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c
new file mode 100644 (file)
index 0000000..b5fabc7
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ *
+ * general timer device for using in ISDN stacks
+ *
+ * Author      Karsten Keil <kkeil@novell.com>
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/poll.h>
+#include <linux/vmalloc.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mISDNif.h>
+
+static int     *debug;
+
+
+struct mISDNtimerdev {
+       int                     next_id;
+       struct list_head        pending;
+       struct list_head        expired;
+       wait_queue_head_t       wait;
+       u_int                   work;
+       spinlock_t              lock; /* protect lists */
+};
+
+struct mISDNtimer {
+       struct list_head        list;
+       struct  mISDNtimerdev   *dev;
+       struct timer_list       tl;
+       int                     id;
+};
+
+static int
+mISDN_open(struct inode *ino, struct file *filep)
+{
+       struct mISDNtimerdev    *dev;
+
+       if (*debug & DEBUG_TIMER)
+               printk(KERN_DEBUG "%s(%p,%p)\n", __func__, ino, filep);
+       dev = kmalloc(sizeof(struct mISDNtimerdev) , GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+       dev->next_id = 1;
+       INIT_LIST_HEAD(&dev->pending);
+       INIT_LIST_HEAD(&dev->expired);
+       spin_lock_init(&dev->lock);
+       dev->work = 0;
+       init_waitqueue_head(&dev->wait);
+       filep->private_data = dev;
+       __module_get(THIS_MODULE);
+       return 0;
+}
+
+static int
+mISDN_close(struct inode *ino, struct file *filep)
+{
+       struct mISDNtimerdev    *dev = filep->private_data;
+       struct mISDNtimer       *timer, *next;
+
+       if (*debug & DEBUG_TIMER)
+               printk(KERN_DEBUG "%s(%p,%p)\n", __func__, ino, filep);
+       list_for_each_entry_safe(timer, next, &dev->pending, list) {
+               del_timer(&timer->tl);
+               kfree(timer);
+       }
+       list_for_each_entry_safe(timer, next, &dev->expired, list) {
+               kfree(timer);
+       }
+       kfree(dev);
+       module_put(THIS_MODULE);
+       return 0;
+}
+
+static ssize_t
+mISDN_read(struct file *filep, char *buf, size_t count, loff_t *off)
+{
+       struct mISDNtimerdev    *dev = filep->private_data;
+       struct mISDNtimer       *timer;
+       u_long  flags;
+       int     ret = 0;
+
+       if (*debug & DEBUG_TIMER)
+               printk(KERN_DEBUG "%s(%p, %p, %d, %p)\n", __func__,
+                       filep, buf, (int)count, off);
+       if (*off != filep->f_pos)
+               return -ESPIPE;
+
+       if (list_empty(&dev->expired) && (dev->work == 0)) {
+               if (filep->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               wait_event_interruptible(dev->wait, (dev->work ||
+                   !list_empty(&dev->expired)));
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+       }
+       if (count < sizeof(int))
+               return -ENOSPC;
+       if (dev->work)
+               dev->work = 0;
+       if (!list_empty(&dev->expired)) {
+               spin_lock_irqsave(&dev->lock, flags);
+               timer = (struct mISDNtimer *)dev->expired.next;
+               list_del(&timer->list);
+               spin_unlock_irqrestore(&dev->lock, flags);
+               if (put_user(timer->id, (int *)buf))
+                       ret = -EFAULT;
+               else
+                       ret = sizeof(int);
+               kfree(timer);
+       }
+       return ret;
+}
+
+static loff_t
+mISDN_llseek(struct file *filep, loff_t offset, int orig)
+{
+       return -ESPIPE;
+}
+
+static ssize_t
+mISDN_write(struct file *filep, const char *buf, size_t count, loff_t *off)
+{
+       return -EOPNOTSUPP;
+}
+
+static unsigned int
+mISDN_poll(struct file *filep, poll_table *wait)
+{
+       struct mISDNtimerdev    *dev = filep->private_data;
+       unsigned int            mask = POLLERR;
+
+       if (*debug & DEBUG_TIMER)
+               printk(KERN_DEBUG "%s(%p, %p)\n", __func__, filep, wait);
+       if (dev) {
+               poll_wait(filep, &dev->wait, wait);
+               mask = 0;
+               if (dev->work || !list_empty(&dev->expired))
+                       mask |= (POLLIN | POLLRDNORM);
+               if (*debug & DEBUG_TIMER)
+                       printk(KERN_DEBUG "%s work(%d) empty(%d)\n", __func__,
+                               dev->work, list_empty(&dev->expired));
+       }
+       return mask;
+}
+
+static void
+dev_expire_timer(struct mISDNtimer *timer)
+{
+       u_long                  flags;
+
+       spin_lock_irqsave(&timer->dev->lock, flags);
+       list_del(&timer->list);
+       list_add_tail(&timer->list, &timer->dev->expired);
+       spin_unlock_irqrestore(&timer->dev->lock, flags);
+       wake_up_interruptible(&timer->dev->wait);
+}
+
+static int
+misdn_add_timer(struct mISDNtimerdev *dev, int timeout)
+{
+       int                     id;
+       u_long                  flags;
+       struct mISDNtimer       *timer;
+
+       if (!timeout) {
+               dev->work = 1;
+               wake_up_interruptible(&dev->wait);
+               id = 0;
+       } else {
+               timer = kzalloc(sizeof(struct mISDNtimer), GFP_KERNEL);
+               if (!timer)
+                       return -ENOMEM;
+               spin_lock_irqsave(&dev->lock, flags);
+               timer->id = dev->next_id++;
+               if (dev->next_id < 0)
+                       dev->next_id = 1;
+               list_add_tail(&timer->list, &dev->pending);
+               spin_unlock_irqrestore(&dev->lock, flags);
+               timer->dev = dev;
+               timer->tl.data = (long)timer;
+               timer->tl.function = (void *) dev_expire_timer;
+               init_timer(&timer->tl);
+               timer->tl.expires = jiffies + ((HZ * (u_long)timeout) / 1000);
+               add_timer(&timer->tl);
+               id = timer->id;
+       }
+       return id;
+}
+
+static int
+misdn_del_timer(struct mISDNtimerdev *dev, int id)
+{
+       u_long                  flags;
+       struct mISDNtimer       *timer;
+       int                     ret = 0;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       list_for_each_entry(timer, &dev->pending, list) {
+               if (timer->id == id) {
+                       list_del_init(&timer->list);
+                       del_timer(&timer->tl);
+                       ret = timer->id;
+                       kfree(timer);
+                       goto unlock;
+               }
+       }
+unlock:
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return ret;
+}
+
+static int
+mISDN_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
+    unsigned long arg)
+{
+       struct mISDNtimerdev    *dev = filep->private_data;
+       int                     id, tout, ret = 0;
+
+
+       if (*debug & DEBUG_TIMER)
+               printk(KERN_DEBUG "%s(%p, %x, %lx)\n", __func__,
+                   filep, cmd, arg);
+       switch (cmd) {
+       case IMADDTIMER:
+               if (get_user(tout, (int __user *)arg)) {
+                       ret = -EFAULT;
+                       break;
+               }
+               id = misdn_add_timer(dev, tout);
+               if (*debug & DEBUG_TIMER)
+                       printk(KERN_DEBUG "%s add %d id %d\n", __func__,
+                           tout, id);
+               if (id < 0) {
+                       ret = id;
+                       break;
+               }
+               if (put_user(id, (int __user *)arg))
+                       ret = -EFAULT;
+               break;
+       case IMDELTIMER:
+               if (get_user(id, (int __user *)arg)) {
+                       ret = -EFAULT;
+                       break;
+               }
+               if (*debug & DEBUG_TIMER)
+                       printk(KERN_DEBUG "%s del id %d\n", __func__, id);
+               id = misdn_del_timer(dev, id);
+               if (put_user(id, (int __user *)arg))
+                       ret = -EFAULT;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static struct file_operations mISDN_fops = {
+       .llseek         = mISDN_llseek,
+       .read           = mISDN_read,
+       .write          = mISDN_write,
+       .poll           = mISDN_poll,
+       .ioctl          = mISDN_ioctl,
+       .open           = mISDN_open,
+       .release        = mISDN_close,
+};
+
+static struct miscdevice mISDNtimer = {
+       .minor  = MISC_DYNAMIC_MINOR,
+       .name   = "mISDNtimer",
+       .fops   = &mISDN_fops,
+};
+
+int
+mISDN_inittimer(int *deb)
+{
+       int     err;
+
+       debug = deb;
+       err = misc_register(&mISDNtimer);
+       if (err)
+               printk(KERN_WARNING "mISDN: Could not register timer device\n");
+       return err;
+}
+
+void mISDN_timer_cleanup(void)
+{
+       misc_deregister(&mISDNtimer);
+}
index 86a369bc57d6d91c9137da6940904d6172cf9f90..9556262dda5aabba7b6474eee2b4e2a3b1a31906 100644 (file)
@@ -103,6 +103,14 @@ config LEDS_HP6XX
          This option enables led support for the handheld
          HP Jornada 620/660/680/690.
 
+config LEDS_PCA9532
+       tristate "LED driver for PCA9532 dimmer"
+       depends on LEDS_CLASS && I2C && INPUT && EXPERIMENTAL
+       help
+         This option enables support for NXP pca9532
+         led controller. It is generally only usefull
+         as a platform driver
+
 config LEDS_GPIO
        tristate "LED Support for GPIO connected LEDs"
        depends on LEDS_CLASS && GENERIC_GPIO
@@ -147,6 +155,14 @@ config LEDS_CLEVO_MAIL
          To compile this driver as a module, choose M here: the
          module will be called leds-clevo-mail.
 
+config LEDS_PCA955X
+       tristate "LED Support for PCA955x I2C chips"
+       depends on LEDS_CLASS && I2C
+       help
+         This option enables support for LEDs connected to PCA955x
+         LED driver chips accessed via the I2C bus.  Supported
+         devices include PCA9550, PCA9551, PCA9552, and PCA9553.
+
 comment "LED Triggers"
 
 config LEDS_TRIGGERS
index 973d626f5f4a98d582b02eeeb9113728ba605cf3..ff7982b44565d7fe674b0846916a8acb2d221666 100644 (file)
@@ -16,11 +16,13 @@ obj-$(CONFIG_LEDS_WRAP)                     += leds-wrap.o
 obj-$(CONFIG_LEDS_H1940)               += leds-h1940.o
 obj-$(CONFIG_LEDS_COBALT_QUBE)         += leds-cobalt-qube.o
 obj-$(CONFIG_LEDS_COBALT_RAQ)          += leds-cobalt-raq.o
+obj-$(CONFIG_LEDS_PCA9532)             += leds-pca9532.o
 obj-$(CONFIG_LEDS_GPIO)                        += leds-gpio.o
 obj-$(CONFIG_LEDS_CM_X270)              += leds-cm-x270.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)          += leds-clevo-mail.o
 obj-$(CONFIG_LEDS_HP6XX)               += leds-hp6xx.o
 obj-$(CONFIG_LEDS_FSG)                 += leds-fsg.o
+obj-$(CONFIG_LEDS_PCA955X)             += leds-pca955x.o
 
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)       += ledtrig-timer.o
index 0f242b3f09b6b7018354952e7a01bae8b37d6071..f910eaffe3a6f057cd835412204c304f1bd0af38 100644 (file)
@@ -111,16 +111,17 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
                        flags);
                if (led_cdev->trigger->deactivate)
                        led_cdev->trigger->deactivate(led_cdev);
+               led_cdev->trigger = NULL;
                led_set_brightness(led_cdev, LED_OFF);
        }
        if (trigger) {
                write_lock_irqsave(&trigger->leddev_list_lock, flags);
                list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);
                write_unlock_irqrestore(&trigger->leddev_list_lock, flags);
+               led_cdev->trigger = trigger;
                if (trigger->activate)
                        trigger->activate(led_cdev);
        }
-       led_cdev->trigger = trigger;
 }
 EXPORT_SYMBOL_GPL(led_trigger_set);
 
index 28db6c1444ed9f4b64c989fbbbbc05f49ff82f61..52297c3ab246c38a78e3580895c21e1c00d7b6f6 100644 (file)
@@ -37,7 +37,7 @@ static int __init pwmled_probe(struct platform_device *pdev)
 {
        const struct gpio_led_platform_data     *pdata;
        struct pwmled                           *leds;
-       unsigned                                i;
+       int                                     i;
        int                                     status;
 
        pdata = pdev->dev.platform_data;
index bcec42230389128cd03ce6294d13c8d018e288ab..73c70502168653d16b8f06e88cb43d912f6b53c3 100644 (file)
@@ -23,7 +23,8 @@
 /*
  * Green led.
  */
-void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value)
+static void h1940_greenled_set(struct led_classdev *led_dev,
+                              enum led_brightness value)
 {
        switch (value) {
        case LED_HALF:
@@ -52,7 +53,8 @@ static struct led_classdev h1940_greenled = {
 /*
  * Red led.
  */
-void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value)
+static void h1940_redled_set(struct led_classdev *led_dev,
+                            enum led_brightness value)
 {
        switch (value) {
        case LED_HALF:
@@ -82,7 +84,8 @@ static struct led_classdev h1940_redled = {
  * Blue led.
  * (it can only be blue flashing led)
  */
-void h1940_blueled_set(struct led_classdev *led_dev, enum led_brightness value)
+static void h1940_blueled_set(struct led_classdev *led_dev,
+                             enum led_brightness value)
 {
        if (value) {
                /* flashing Blue */
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
new file mode 100644 (file)
index 0000000..4064d4f
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * pca9532.c - 16-bit Led dimmer
+ *
+ * Copyright (C) 2008 Riku Voipio <riku.voipio@movial.fi>
+ *
+ * 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.
+ *
+ * Datasheet: http://www.nxp.com/acrobat/datasheets/PCA9532_3.pdf
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/mutex.h>
+#include <linux/leds-pca9532.h>
+
+static const unsigned short normal_i2c[] = { /*0x60,*/ I2C_CLIENT_END};
+I2C_CLIENT_INSMOD_1(pca9532);
+
+#define PCA9532_REG_PSC(i) (0x2+(i)*2)
+#define PCA9532_REG_PWM(i) (0x3+(i)*2)
+#define PCA9532_REG_LS0  0x6
+#define LED_REG(led) ((led>>2)+PCA9532_REG_LS0)
+#define LED_NUM(led) (led & 0x3)
+
+#define ldev_to_led(c)       container_of(c, struct pca9532_led, ldev)
+
+struct pca9532_data {
+       struct i2c_client *client;
+       struct pca9532_led leds[16];
+       struct mutex update_lock;
+       struct input_dev    *idev;
+       u8 pwm[2];
+       u8 psc[2];
+};
+
+static int pca9532_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+static int pca9532_remove(struct i2c_client *client);
+
+static const struct i2c_device_id pca9532_id[] = {
+       { "pca9532", 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, pca9532_id);
+
+static struct i2c_driver pca9532_driver = {
+       .driver = {
+               .name   = "pca9532",
+       },
+       .probe  = pca9532_probe,
+       .remove = pca9532_remove,
+       .id_table = pca9532_id,
+};
+
+/* We have two pwm/blinkers, but 16 possible leds to drive. Additionaly,
+ * the clever Thecus people are using one pwm to drive the beeper. So,
+ * as a compromise we average one pwm to the values requested by all
+ * leds that are not ON/OFF.
+ * */
+static int pca9532_setpwm(struct i2c_client *client, int pwm, int blink,
+       enum led_brightness value)
+{
+       int a = 0, b = 0, i = 0;
+       struct pca9532_data *data = i2c_get_clientdata(client);
+       for (i = 0; i < 16; i++) {
+               if (data->leds[i].type == PCA9532_TYPE_LED &&
+                       data->leds[i].state == PCA9532_PWM0+pwm) {
+                               a++;
+                               b += data->leds[i].ldev.brightness;
+               }
+       }
+       if (a == 0) {
+               dev_err(&client->dev,
+               "fear of division by zero %d/%d, wanted %d\n",
+                       b, a, value);
+               return -EINVAL;
+       }
+       b = b/a;
+       if (b > 0xFF)
+               return -EINVAL;
+       mutex_lock(&data->update_lock);
+       data->pwm[pwm] = b;
+       i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm),
+               data->pwm[pwm]);
+       data->psc[pwm] = blink;
+       i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm),
+               data->psc[pwm]);
+       mutex_unlock(&data->update_lock);
+       return 0;
+}
+
+/* Set LED routing */
+static void pca9532_setled(struct pca9532_led *led)
+{
+       struct i2c_client *client = led->client;
+       struct pca9532_data *data = i2c_get_clientdata(client);
+       char reg;
+
+       mutex_lock(&data->update_lock);
+       reg = i2c_smbus_read_byte_data(client, LED_REG(led->id));
+       /* zero led bits */
+       reg = reg & ~(0x3<<LED_NUM(led->id)*2);
+       /* set the new value */
+       reg = reg | (led->state << LED_NUM(led->id)*2);
+       i2c_smbus_write_byte_data(client, LED_REG(led->id), reg);
+       mutex_unlock(&data->update_lock);
+}
+
+static void pca9532_set_brightness(struct led_classdev *led_cdev,
+       enum led_brightness value)
+{
+       int err = 0;
+       struct pca9532_led *led = ldev_to_led(led_cdev);
+
+       if (value == LED_OFF)
+               led->state = PCA9532_OFF;
+       else if (value == LED_FULL)
+               led->state = PCA9532_ON;
+       else {
+               led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */
+               err = pca9532_setpwm(led->client, 0, 0, value);
+               if (err)
+                       return; /* XXX: led api doesn't allow error code? */
+       }
+       pca9532_setled(led);
+}
+
+static int pca9532_set_blink(struct led_classdev *led_cdev,
+       unsigned long *delay_on, unsigned long *delay_off)
+{
+       struct pca9532_led *led = ldev_to_led(led_cdev);
+       struct i2c_client *client = led->client;
+       int psc;
+
+       if (*delay_on == 0 && *delay_off == 0) {
+       /* led subsystem ask us for a blink rate */
+               *delay_on  = 1000;
+               *delay_off = 1000;
+       }
+       if (*delay_on != *delay_off || *delay_on > 1690 || *delay_on < 6)
+               return -EINVAL;
+
+       /* Thecus specific: only use PSC/PWM 0 */
+       psc = (*delay_on * 152-1)/1000;
+       return pca9532_setpwm(client, 0, psc, led_cdev->brightness);
+}
+
+int pca9532_event(struct input_dev *dev, unsigned int type, unsigned int code,
+       int value)
+{
+       struct pca9532_data *data = input_get_drvdata(dev);
+
+       if (type != EV_SND && (code != SND_BELL || code != SND_TONE))
+               return -1;
+
+       /* XXX: allow different kind of beeps with psc/pwm modifications */
+       if (value > 1 && value < 32767)
+               data->pwm[1] = 127;
+       else
+               data->pwm[1] = 0;
+
+       dev_info(&dev->dev, "setting beep to %d \n", data->pwm[1]);
+       mutex_lock(&data->update_lock);
+       i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1),
+               data->pwm[1]);
+       mutex_unlock(&data->update_lock);
+
+       return 0;
+}
+
+static int pca9532_configure(struct i2c_client *client,
+       struct pca9532_data *data, struct pca9532_platform_data *pdata)
+{
+       int i, err = 0;
+
+       for (i = 0; i < 2; i++) {
+               data->pwm[i] = pdata->pwm[i];
+               data->psc[i] = pdata->psc[i];
+               i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(i),
+                       data->pwm[i]);
+               i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(i),
+                       data->psc[i]);
+       }
+
+       for (i = 0; i < 16; i++) {
+               struct pca9532_led *led = &data->leds[i];
+               struct pca9532_led *pled = &pdata->leds[i];
+               led->client = client;
+               led->id = i;
+               led->type = pled->type;
+               switch (led->type) {
+               case PCA9532_TYPE_NONE:
+                       break;
+               case PCA9532_TYPE_LED:
+                       led->state = pled->state;
+                       led->name =  pled->name;
+                       led->ldev.name = led->name;
+                       led->ldev.brightness = LED_OFF;
+                       led->ldev.brightness_set = pca9532_set_brightness;
+                       led->ldev.blink_set = pca9532_set_blink;
+                       if (led_classdev_register(&client->dev,
+                               &led->ldev) < 0)        {
+                               dev_err(&client->dev,
+                                       "couldn't register LED %s\n",
+                                       led->name);
+                               goto exit;
+                       }
+                       pca9532_setled(led);
+                       break;
+               case PCA9532_TYPE_N2100_BEEP:
+                       BUG_ON(data->idev);
+                       led->state = PCA9532_PWM1;
+                       pca9532_setled(led);
+                       data->idev = input_allocate_device();
+                       if (data->idev == NULL) {
+                               err = -ENOMEM;
+                               goto exit;
+                       }
+                       data->idev->name = pled->name;
+                       data->idev->phys = "i2c/pca9532";
+                       data->idev->id.bustype = BUS_HOST;
+                       data->idev->id.vendor  = 0x001f;
+                       data->idev->id.product = 0x0001;
+                       data->idev->id.version = 0x0100;
+                       data->idev->evbit[0] = BIT_MASK(EV_SND);
+                       data->idev->sndbit[0] = BIT_MASK(SND_BELL) |
+                                               BIT_MASK(SND_TONE);
+                       data->idev->event = pca9532_event;
+                       input_set_drvdata(data->idev, data);
+                       err = input_register_device(data->idev);
+                       if (err) {
+                               input_free_device(data->idev);
+                               data->idev = NULL;
+                               goto exit;
+                       }
+                       break;
+               }
+       }
+       return 0;
+
+exit:
+       if (i > 0)
+               for (i = i - 1; i >= 0; i--)
+                       switch (data->leds[i].type) {
+                       case PCA9532_TYPE_NONE:
+                               break;
+                       case PCA9532_TYPE_LED:
+                               led_classdev_unregister(&data->leds[i].ldev);
+                               break;
+                       case PCA9532_TYPE_N2100_BEEP:
+                               if (data->idev != NULL) {
+                                       input_unregister_device(data->idev);
+                                       input_free_device(data->idev);
+                                       data->idev = NULL;
+                               }
+                               break;
+                       }
+
+       return err;
+
+}
+
+static int pca9532_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       struct pca9532_data *data = i2c_get_clientdata(client);
+       struct pca9532_platform_data *pca9532_pdata = client->dev.platform_data;
+
+       if (!i2c_check_functionality(client->adapter,
+               I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EIO;
+
+       data = kzalloc(sizeof(struct pca9532_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       dev_info(&client->dev, "setting platform data\n");
+       i2c_set_clientdata(client, data);
+       data->client = client;
+       mutex_init(&data->update_lock);
+
+       if (pca9532_pdata == NULL)
+               return -EIO;
+
+       pca9532_configure(client, data, pca9532_pdata);
+       return 0;
+
+}
+
+static int pca9532_remove(struct i2c_client *client)
+{
+       struct pca9532_data *data = i2c_get_clientdata(client);
+       int i;
+       for (i = 0; i < 16; i++)
+               switch (data->leds[i].type) {
+               case PCA9532_TYPE_NONE:
+                       break;
+               case PCA9532_TYPE_LED:
+                       led_classdev_unregister(&data->leds[i].ldev);
+                       break;
+               case PCA9532_TYPE_N2100_BEEP:
+                       if (data->idev != NULL) {
+                               input_unregister_device(data->idev);
+                               input_free_device(data->idev);
+                               data->idev = NULL;
+                       }
+                       break;
+               }
+
+       kfree(data);
+       i2c_set_clientdata(client, NULL);
+       return 0;
+}
+
+static int __init pca9532_init(void)
+{
+       return i2c_add_driver(&pca9532_driver);
+}
+
+static void __exit pca9532_exit(void)
+{
+       i2c_del_driver(&pca9532_driver);
+}
+
+MODULE_AUTHOR("Riku Voipio <riku.voipio@movial.fi>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PCA 9532 LED dimmer");
+
+module_init(pca9532_init);
+module_exit(pca9532_exit);
+
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
new file mode 100644 (file)
index 0000000..146c069
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright 2007-2008 Extreme Engineering Solutions, Inc.
+ *
+ * Author: Nate Case <ncase@xes-inc.com>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * LED driver for various PCA955x I2C LED drivers
+ *
+ * Supported devices:
+ *
+ *     Device          Description             7-bit slave address
+ *     ------          -----------             -------------------
+ *     PCA9550         2-bit driver            0x60 .. 0x61
+ *     PCA9551         8-bit driver            0x60 .. 0x67
+ *     PCA9552         16-bit driver           0x60 .. 0x67
+ *     PCA9553/01      4-bit driver            0x62
+ *     PCA9553/02      4-bit driver            0x63
+ *
+ * Philips PCA955x LED driver chips follow a register map as shown below:
+ *
+ *     Control Register                Description
+ *     ----------------                -----------
+ *     0x0                             Input register 0
+ *                                     ..
+ *     NUM_INPUT_REGS - 1              Last Input register X
+ *
+ *     NUM_INPUT_REGS                  Frequency prescaler 0
+ *     NUM_INPUT_REGS + 1              PWM register 0
+ *     NUM_INPUT_REGS + 2              Frequency prescaler 1
+ *     NUM_INPUT_REGS + 3              PWM register 1
+ *
+ *     NUM_INPUT_REGS + 4              LED selector 0
+ *     NUM_INPUT_REGS + 4
+ *         + NUM_LED_REGS - 1          Last LED selector
+ *
+ *  where NUM_INPUT_REGS and NUM_LED_REGS vary depending on how many
+ *  bits the chip supports.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+/* LED select registers determine the source that drives LED outputs */
+#define PCA955X_LS_LED_ON      0x0     /* Output LOW */
+#define PCA955X_LS_LED_OFF     0x1     /* Output HI-Z */
+#define PCA955X_LS_BLINK0      0x2     /* Blink at PWM0 rate */
+#define PCA955X_LS_BLINK1      0x3     /* Blink at PWM1 rate */
+
+enum pca955x_type {
+       pca9550,
+       pca9551,
+       pca9552,
+       pca9553,
+};
+
+struct pca955x_chipdef {
+       int                     bits;
+       u8                      slv_addr;       /* 7-bit slave address mask */
+       int                     slv_addr_shift; /* Number of bits to ignore */
+};
+
+static struct pca955x_chipdef pca955x_chipdefs[] = {
+       [pca9550] = {
+               .bits           = 2,
+               .slv_addr       = /* 110000x */ 0x60,
+               .slv_addr_shift = 1,
+       },
+       [pca9551] = {
+               .bits           = 8,
+               .slv_addr       = /* 1100xxx */ 0x60,
+               .slv_addr_shift = 3,
+       },
+       [pca9552] = {
+               .bits           = 16,
+               .slv_addr       = /* 1100xxx */ 0x60,
+               .slv_addr_shift = 3,
+       },
+       [pca9553] = {
+               .bits           = 4,
+               .slv_addr       = /* 110001x */ 0x62,
+               .slv_addr_shift = 1,
+       },
+};
+
+static const struct i2c_device_id pca955x_id[] = {
+       { "pca9550", pca9550 },
+       { "pca9551", pca9551 },
+       { "pca9552", pca9552 },
+       { "pca9553", pca9553 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pca955x_id);
+
+struct pca955x_led {
+       struct pca955x_chipdef  *chipdef;
+       struct i2c_client       *client;
+       struct work_struct      work;
+       spinlock_t              lock;
+       enum led_brightness     brightness;
+       struct led_classdev     led_cdev;
+       int                     led_num;        /* 0 .. 15 potentially */
+       char                    name[32];
+};
+
+/* 8 bits per input register */
+static inline int pca95xx_num_input_regs(int bits)
+{
+       return (bits + 7) / 8;
+}
+
+/* 4 bits per LED selector register */
+static inline int pca95xx_num_led_regs(int bits)
+{
+       return (bits + 3)  / 4;
+}
+
+/*
+ * Return an LED selector register value based on an existing one, with
+ * the appropriate 2-bit state value set for the given LED number (0-3).
+ */
+static inline u8 pca955x_ledsel(u8 oldval, int led_num, int state)
+{
+       return (oldval & (~(0x3 << (led_num << 1)))) |
+               ((state & 0x3) << (led_num << 1));
+}
+
+/*
+ * Write to frequency prescaler register, used to program the
+ * period of the PWM output.  period = (PSCx + 1) / 38
+ */
+static void pca955x_write_psc(struct i2c_client *client, int n, u8 val)
+{
+       struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+       i2c_smbus_write_byte_data(client,
+               pca95xx_num_input_regs(pca955x->chipdef->bits) + 2*n,
+               val);
+}
+
+/*
+ * Write to PWM register, which determines the duty cycle of the
+ * output.  LED is OFF when the count is less than the value of this
+ * register, and ON when it is greater.  If PWMx == 0, LED is always OFF.
+ *
+ * Duty cycle is (256 - PWMx) / 256
+ */
+static void pca955x_write_pwm(struct i2c_client *client, int n, u8 val)
+{
+       struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+       i2c_smbus_write_byte_data(client,
+               pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + 2*n,
+               val);
+}
+
+/*
+ * Write to LED selector register, which determines the source that
+ * drives the LED output.
+ */
+static void pca955x_write_ls(struct i2c_client *client, int n, u8 val)
+{
+       struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+       i2c_smbus_write_byte_data(client,
+               pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n,
+               val);
+}
+
+/*
+ * Read the LED selector register, which determines the source that
+ * drives the LED output.
+ */
+static u8 pca955x_read_ls(struct i2c_client *client, int n)
+{
+       struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+       return (u8) i2c_smbus_read_byte_data(client,
+               pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n);
+}
+
+static void pca955x_led_work(struct work_struct *work)
+{
+       struct pca955x_led *pca955x;
+       u8 ls;
+       int chip_ls;    /* which LSx to use (0-3 potentially) */
+       int ls_led;     /* which set of bits within LSx to use (0-3) */
+
+       pca955x = container_of(work, struct pca955x_led, work);
+       chip_ls = pca955x->led_num / 4;
+       ls_led = pca955x->led_num % 4;
+
+       ls = pca955x_read_ls(pca955x->client, chip_ls);
+
+       switch (pca955x->brightness) {
+       case LED_FULL:
+               ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
+               break;
+       case LED_OFF:
+               ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_OFF);
+               break;
+       case LED_HALF:
+               ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK0);
+               break;
+       default:
+               /*
+                * Use PWM1 for all other values.  This has the unwanted
+                * side effect of making all LEDs on the chip share the
+                * same brightness level if set to a value other than
+                * OFF, HALF, or FULL.  But, this is probably better than
+                * just turning off for all other values.
+                */
+               pca955x_write_pwm(pca955x->client, 1, 255-pca955x->brightness);
+               ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK1);
+               break;
+       }
+
+       pca955x_write_ls(pca955x->client, chip_ls, ls);
+}
+
+void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+       struct pca955x_led *pca955x;
+
+       pca955x = container_of(led_cdev, struct pca955x_led, led_cdev);
+
+       spin_lock(&pca955x->lock);
+       pca955x->brightness = value;
+
+       /*
+        * Must use workqueue for the actual I/O since I2C operations
+        * can sleep.
+        */
+       schedule_work(&pca955x->work);
+
+       spin_unlock(&pca955x->lock);
+}
+
+static int __devinit pca955x_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct pca955x_led *pca955x;
+       int i;
+       int err = -ENODEV;
+       struct pca955x_chipdef *chip;
+       struct i2c_adapter *adapter;
+       struct led_platform_data *pdata;
+
+       chip = &pca955x_chipdefs[id->driver_data];
+       adapter = to_i2c_adapter(client->dev.parent);
+       pdata = client->dev.platform_data;
+
+       /* Make sure the slave address / chip type combo given is possible */
+       if ((client->addr & ~((1 << chip->slv_addr_shift) - 1)) !=
+           chip->slv_addr) {
+               dev_err(&client->dev, "invalid slave address %02x\n",
+                               client->addr);
+               return -ENODEV;
+       }
+
+       printk(KERN_INFO "leds-pca955x: Using %s %d-bit LED driver at "
+                       "slave address 0x%02x\n",
+                       id->name, chip->bits, client->addr);
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+               return -EIO;
+
+       if (pdata) {
+               if (pdata->num_leds != chip->bits) {
+                       dev_err(&client->dev, "board info claims %d LEDs"
+                                       " on a %d-bit chip\n",
+                                       pdata->num_leds, chip->bits);
+                       return -ENODEV;
+               }
+       }
+
+       for (i = 0; i < chip->bits; i++) {
+               pca955x = kzalloc(sizeof(struct pca955x_led), GFP_KERNEL);
+               if (!pca955x) {
+                       err = -ENOMEM;
+                       goto exit;
+               }
+
+               pca955x->chipdef = chip;
+               pca955x->client = client;
+               pca955x->led_num = i;
+               /* Platform data can specify LED names and default triggers */
+               if (pdata) {
+                       if (pdata->leds[i].name)
+                               snprintf(pca955x->name, 32, "pca955x:%s",
+                                                       pdata->leds[i].name);
+                       if (pdata->leds[i].default_trigger)
+                               pca955x->led_cdev.default_trigger =
+                                       pdata->leds[i].default_trigger;
+               } else {
+                       snprintf(pca955x->name, 32, "pca955x:%d", i);
+               }
+               spin_lock_init(&pca955x->lock);
+
+               pca955x->led_cdev.name = pca955x->name;
+               pca955x->led_cdev.brightness_set =
+                               pca955x_led_set;
+
+               /*
+                * Client data is a pointer to the _first_ pca955x_led
+                * struct
+                */
+               if (i == 0)
+                       i2c_set_clientdata(client, pca955x);
+
+               INIT_WORK(&(pca955x->work), pca955x_led_work);
+
+               led_classdev_register(&client->dev, &(pca955x->led_cdev));
+       }
+
+       /* Turn off LEDs */
+       for (i = 0; i < pca95xx_num_led_regs(chip->bits); i++)
+               pca955x_write_ls(client, i, 0x55);
+
+       /* PWM0 is used for half brightness or 50% duty cycle */
+       pca955x_write_pwm(client, 0, 255-LED_HALF);
+
+       /* PWM1 is used for variable brightness, default to OFF */
+       pca955x_write_pwm(client, 1, 0);
+
+       /* Set to fast frequency so we do not see flashing */
+       pca955x_write_psc(client, 0, 0);
+       pca955x_write_psc(client, 1, 0);
+
+       return 0;
+exit:
+       return err;
+}
+
+static int __devexit pca955x_remove(struct i2c_client *client)
+{
+       struct pca955x_led *pca955x = i2c_get_clientdata(client);
+       int leds = pca955x->chipdef->bits;
+       int i;
+
+       for (i = 0; i < leds; i++) {
+               led_classdev_unregister(&(pca955x->led_cdev));
+               cancel_work_sync(&(pca955x->work));
+               kfree(pca955x);
+               pca955x = pca955x + 1;
+       }
+
+       return 0;
+}
+
+static struct i2c_driver pca955x_driver = {
+       .driver = {
+               .name   = "leds-pca955x",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = pca955x_probe,
+       .remove = __devexit_p(pca955x_remove),
+       .id_table = pca955x_id,
+};
+
+static int __init pca955x_leds_init(void)
+{
+       return i2c_add_driver(&pca955x_driver);
+}
+
+static void __exit pca955x_leds_exit(void)
+{
+       i2c_del_driver(&pca955x_driver);
+}
+
+module_init(pca955x_leds_init);
+module_exit(pca955x_leds_exit);
+
+MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>");
+MODULE_DESCRIPTION("PCA955x LED driver");
+MODULE_LICENSE("GPL v2");
index 5eea4356d70348b102ba2b62d9a3196e21bc7690..90663e01a56e0d4544b944da2fd81e5052a05a2f 100644 (file)
@@ -135,6 +135,7 @@ static void unmap_switcher(void)
        /* Now we just need to free the pages we copied the switcher into */
        for (i = 0; i < TOTAL_SWITCHER_PAGES; i++)
                __free_pages(switcher_page[i], 0);
+       kfree(switcher_page);
 }
 
 /*H:032
index 0414ddf875871729c00742c00cb6bf45a558eac8..a1039068f95c378cd85b2d6ff2f0f6729c003db2 100644 (file)
@@ -406,7 +406,8 @@ void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi)
  * deliver_trap() to bounce it back into the Guest. */
 static void default_idt_entry(struct desc_struct *idt,
                              int trap,
-                             const unsigned long handler)
+                             const unsigned long handler,
+                             const struct desc_struct *base)
 {
        /* A present interrupt gate. */
        u32 flags = 0x8e00;
@@ -415,6 +416,10 @@ static void default_idt_entry(struct desc_struct *idt,
         * the Guest to use the "int" instruction to trigger it. */
        if (trap == LGUEST_TRAP_ENTRY)
                flags |= (GUEST_PL << 13);
+       else if (base)
+               /* Copy priv. level from what Guest asked for.  This allows
+                * debug (int 3) traps from Guest userspace, for example. */
+               flags |= (base->b & 0x6000);
 
        /* Now pack it into the IDT entry in its weird format. */
        idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF);
@@ -428,7 +433,7 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
        unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(state->guest_idt); i++)
-               default_idt_entry(&state->guest_idt[i], i, def[i]);
+               default_idt_entry(&state->guest_idt[i], i, def[i], NULL);
 }
 
 /*H:240 We don't use the IDT entries in the "struct lguest" directly, instead
@@ -442,6 +447,8 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
        /* We can simply copy the direct traps, otherwise we use the default
         * ones in the Switcher: they will return to the Host. */
        for (i = 0; i < ARRAY_SIZE(cpu->arch.idt); i++) {
+               const struct desc_struct *gidt = &cpu->arch.idt[i];
+
                /* If no Guest can ever override this trap, leave it alone. */
                if (!direct_trap(i))
                        continue;
@@ -449,12 +456,15 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
                /* Only trap gates (type 15) can go direct to the Guest.
                 * Interrupt gates (type 14) disable interrupts as they are
                 * entered, which we never let the Guest do.  Not present
-                * entries (type 0x0) also can't go direct, of course. */
-               if (idt_type(cpu->arch.idt[i].a, cpu->arch.idt[i].b) == 0xF)
-                       idt[i] = cpu->arch.idt[i];
+                * entries (type 0x0) also can't go direct, of course.
+                *
+                * If it can't go direct, we still need to copy the priv. level:
+                * they might want to give userspace access to a software
+                * interrupt. */
+               if (idt_type(gidt->a, gidt->b) == 0xF)
+                       idt[i] = *gidt;
                else
-                       /* Reset it to the default. */
-                       default_idt_entry(&idt[i], i, def[i]);
+                       default_idt_entry(&idt[i], i, def[i], gidt);
        }
 }
 
index 1a8de57289eb97e5877b9016855cfe9e99adaac1..37344aaee22f3ab44910a18576489466c0b8c30d 100644 (file)
@@ -98,16 +98,20 @@ static u32 lg_get_features(struct virtio_device *vdev)
        return features;
 }
 
-static void lg_set_features(struct virtio_device *vdev, u32 features)
+static void lg_finalize_features(struct virtio_device *vdev)
 {
-       unsigned int i;
+       unsigned int i, bits;
        struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
        /* Second half of bitmap is features we accept. */
        u8 *out_features = lg_features(desc) + desc->feature_len;
 
+       /* Give virtio_ring a chance to accept features. */
+       vring_transport_features(vdev);
+
        memset(out_features, 0, desc->feature_len);
-       for (i = 0; i < min(desc->feature_len * 8, 32); i++) {
-               if (features & (1 << i))
+       bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8;
+       for (i = 0; i < bits; i++) {
+               if (test_bit(i, vdev->features))
                        out_features[i / 8] |= (1 << (i % 8));
        }
 }
@@ -297,7 +301,7 @@ static void lg_del_vq(struct virtqueue *vq)
 /* The ops structure which hooks everything together. */
 static struct virtio_config_ops lguest_config_ops = {
        .get_features = lg_get_features,
-       .set_features = lg_set_features,
+       .finalize_features = lg_finalize_features,
        .get = lg_get,
        .set = lg_set,
        .get_status = lg_get_status,
index 95dfda52b4f91d47fa19574fd56a1c278729174a..bf7942327bda5c2f122889e9881e1b7d90acaf44 100644 (file)
@@ -480,7 +480,7 @@ void __init lguest_arch_host_init(void)
                 * bit on its CPU, depending on the argument (0 == unset). */
                on_each_cpu(adjust_pge, (void *)0, 1);
                /* Turn off the feature in the global feature set. */
-               clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
+               clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
        }
        put_online_cpus();
 };
@@ -491,7 +491,7 @@ void __exit lguest_arch_host_fini(void)
        /* If we had PGE before we started, turn it back on now. */
        get_online_cpus();
        if (cpu_had_pge) {
-               set_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
+               set_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
                /* adjust_pge's argument "1" means set PGE. */
                on_each_cpu(adjust_pge, (void *)1, 1);
        }
index fea966d66f9838c140176a7dbd0ed8223e908f44..71dd65aa31b696aa37a894b0d7bd9cbdc2034123 100644 (file)
@@ -147,9 +147,12 @@ static struct priority_group *alloc_priority_group(void)
 static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
 {
        struct pgpath *pgpath, *tmp;
+       struct multipath *m = ti->private;
 
        list_for_each_entry_safe(pgpath, tmp, pgpaths, list) {
                list_del(&pgpath->list);
+               if (m->hw_handler_name)
+                       scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
                dm_put_device(ti, pgpath->path.dev);
                free_pgpath(pgpath);
        }
@@ -548,6 +551,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
 {
        int r;
        struct pgpath *p;
+       struct multipath *m = ti->private;
 
        /* we need at least a path arg */
        if (as->argc < 1) {
@@ -566,6 +570,15 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
                goto bad;
        }
 
+       if (m->hw_handler_name) {
+               r = scsi_dh_attach(bdev_get_queue(p->path.dev->bdev),
+                                  m->hw_handler_name);
+               if (r < 0) {
+                       dm_put_device(ti, p->path.dev);
+                       goto bad;
+               }
+       }
+
        r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error);
        if (r) {
                dm_put_device(ti, p->path.dev);
index 171afe7da6b60e9d66dd78259d987aada6eb0dfa..cf6a817d50594a21f76721f1c386b1b2d798418c 100644 (file)
@@ -563,7 +563,7 @@ int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev
 
        DEB_EE(("dev:%p\n",dev));
 
-       if( VFL_TYPE_GRABBER == (*vid)->type ) {
+       if ((*vid)->vfl_type == VFL_TYPE_GRABBER) {
                vv->video_minor = -1;
        } else {
                vv->vbi_minor = -1;
index a5e62750eea3cb59b976aec917e6b88ab2a1ed87..e8bc7abf24097d93b6b0b2135c72a2c3c9b198fd 100644 (file)
@@ -656,7 +656,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
 
                /* if we have a user buffer, the first page may not be
                   aligned to a page boundary. */
-               pt1->offset = list->offset;
+               pt1->offset = dma->sglist->offset;
                pt2->offset = pt1->offset+o1;
                pt3->offset = pt1->offset+o2;
 
@@ -958,21 +958,18 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
        case VIDIOC_ENUM_FMT:
        {
                struct v4l2_fmtdesc *f = arg;
-               int index;
 
                switch (f->type) {
                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY: {
-                       index = f->index;
-                       if (index < 0 || index >= NUM_FORMATS) {
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (f->index >= NUM_FORMATS)
                                return -EINVAL;
-                       }
-                       memset(f,0,sizeof(*f));
-                       f->index = index;
-                       strlcpy((char *)f->description,formats[index].name,sizeof(f->description));
-                       f->pixelformat = formats[index].pixelformat;
+                       strlcpy((char *)f->description, formats[f->index].name,
+                                       sizeof(f->description));
+                       f->pixelformat = formats[f->index].pixelformat;
+                       f->flags = 0;
+                       memset(f->reserved, 0, sizeof(f->reserved));
                        break;
-               }
                default:
                        return -EINVAL;
                }
index 850d5689b14dcded97ca5ac74adcb3db913da214..6f92beaa5ac8f11913631c96e87a3defdf2d5a48 100644 (file)
@@ -21,9 +21,8 @@ config MEDIA_TUNER
        tristate
        default VIDEO_MEDIA && I2C
        depends on VIDEO_MEDIA && I2C
-       select FW_LOADER if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
-       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
+       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
+       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE
        select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
        select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE
        select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE
@@ -138,8 +137,6 @@ config MEDIA_TUNER_QT1010
 config MEDIA_TUNER_XC2028
        tristate "XCeive xc2028/xc3028 tuners"
        depends on VIDEO_MEDIA && I2C
-       depends on HOTPLUG
-       select FW_LOADER
        default m if MEDIA_TUNER_CUSTOMIZE
        help
          Say Y here to include support for the xc2028/xc3028 tuners.
@@ -147,8 +144,6 @@ config MEDIA_TUNER_XC2028
 config MEDIA_TUNER_XC5000
        tristate "Xceive XC5000 silicon tuner"
        depends on VIDEO_MEDIA && I2C
-       depends on HOTPLUG
-       select FW_LOADER
        default m if DVB_FE_CUSTOMISE
        help
          A driver for the silicon tuner XC5000 from Xceive.
@@ -162,4 +157,11 @@ config MEDIA_TUNER_MXL5005S
        help
          A driver for the silicon tuner MXL5005S from MaxLinear.
 
+config MEDIA_TUNER_MXL5007T
+       tristate "MaxLinear MxL5007T silicon tuner"
+       depends on VIDEO_MEDIA && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A driver for the silicon tuner MxL5007T from MaxLinear.
+
 endif # MEDIA_TUNER_CUSTOMIZE
index 55f7e6706297106558a0c372c6b28fb5e6ff02b0..4dfbe5b8264ffbfcdb75cae344f8e1b1c0f51dc3 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
 obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
 obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
 obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o
+obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index fbcb28233737c86182b89b73c133a428083547cd..35b763a16d53748abc5aca07905f70981f576267 100644 (file)
@@ -148,7 +148,8 @@ static int mt2032_compute_freq(struct dvb_frontend *fe,
        tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
                  rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
 
-       if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
+       if (lo1a > 7 || lo1n < 17 || lo1n > 48 || lo2a > 7 || lo2n < 17 ||
+                       lo2n > 30) {
                tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
                           lo1a, lo1n, lo2a,lo2n);
                return(-1);
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c
new file mode 100644 (file)
index 0000000..cb25e43
--- /dev/null
@@ -0,0 +1,1030 @@
+/*
+ *  mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner
+ *
+ *  Copyright (C) 2008 Michael Krufky <mkrufky@linuxtv.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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include "tuner-i2c.h"
+#include "mxl5007t.h"
+
+static DEFINE_MUTEX(mxl5007t_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
+
+static int mxl5007t_debug;
+module_param_named(debug, mxl5007t_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level");
+
+/* ------------------------------------------------------------------------- */
+
+#define mxl_printk(kern, fmt, arg...) \
+       printk(kern "%s: " fmt "\n", __func__, ##arg)
+
+#define mxl_err(fmt, arg...) \
+       mxl_printk(KERN_ERR, "%d: " fmt, __LINE__, ##arg)
+
+#define mxl_warn(fmt, arg...) \
+       mxl_printk(KERN_WARNING, fmt, ##arg)
+
+#define mxl_info(fmt, arg...) \
+       mxl_printk(KERN_INFO, fmt, ##arg)
+
+#define mxl_debug(fmt, arg...)                         \
+({                                                     \
+       if (mxl5007t_debug)                             \
+               mxl_printk(KERN_DEBUG, fmt, ##arg);     \
+})
+
+#define mxl_fail(ret)                                                  \
+({                                                                     \
+       int __ret;                                                      \
+       __ret = (ret < 0);                                              \
+       if (__ret)                                                      \
+               mxl_printk(KERN_ERR, "error %d on line %d",             \
+                          ret, __LINE__);                              \
+       __ret;                                                          \
+})
+
+/* ------------------------------------------------------------------------- */
+
+#define MHz 1000000
+
+enum mxl5007t_mode {
+       MxL_MODE_OTA_DVBT_ATSC        =    0,
+       MxL_MODE_OTA_NTSC_PAL_GH      =    1,
+       MxL_MODE_OTA_PAL_IB           =    2,
+       MxL_MODE_OTA_PAL_D_SECAM_KL   =    3,
+       MxL_MODE_OTA_ISDBT            =    4,
+       MxL_MODE_CABLE_DIGITAL        = 0x10,
+       MxL_MODE_CABLE_NTSC_PAL_GH    = 0x11,
+       MxL_MODE_CABLE_PAL_IB         = 0x12,
+       MxL_MODE_CABLE_PAL_D_SECAM_KL = 0x13,
+       MxL_MODE_CABLE_SCTE40         = 0x14,
+};
+
+enum mxl5007t_chip_version {
+       MxL_UNKNOWN_ID     = 0x00,
+       MxL_5007_V1_F1     = 0x11,
+       MxL_5007_V1_F2     = 0x12,
+       MxL_5007_V2_100_F1 = 0x21,
+       MxL_5007_V2_100_F2 = 0x22,
+       MxL_5007_V2_200_F1 = 0x23,
+       MxL_5007_V2_200_F2 = 0x24,
+};
+
+struct reg_pair_t {
+       u8 reg;
+       u8 val;
+};
+
+/* ------------------------------------------------------------------------- */
+
+static struct reg_pair_t init_tab[] = {
+       { 0x0b, 0x44 }, /* XTAL */
+       { 0x0c, 0x60 }, /* IF */
+       { 0x10, 0x00 }, /* MISC */
+       { 0x12, 0xca }, /* IDAC */
+       { 0x16, 0x90 }, /* MODE */
+       { 0x32, 0x38 }, /* MODE Analog/Digital */
+       { 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
+       { 0x2c, 0x34 }, /* OVERRIDE */
+       { 0x4d, 0x40 }, /* OVERRIDE */
+       { 0x7f, 0x02 }, /* OVERRIDE */
+       { 0x9a, 0x52 }, /* OVERRIDE */
+       { 0x48, 0x5a }, /* OVERRIDE */
+       { 0x76, 0x1a }, /* OVERRIDE */
+       { 0x6a, 0x48 }, /* OVERRIDE */
+       { 0x64, 0x28 }, /* OVERRIDE */
+       { 0x66, 0xe6 }, /* OVERRIDE */
+       { 0x35, 0x0e }, /* OVERRIDE */
+       { 0x7e, 0x01 }, /* OVERRIDE */
+       { 0x83, 0x00 }, /* OVERRIDE */
+       { 0x04, 0x0b }, /* OVERRIDE */
+       { 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
+       { 0, 0 }
+};
+
+static struct reg_pair_t init_tab_cable[] = {
+       { 0x0b, 0x44 }, /* XTAL */
+       { 0x0c, 0x60 }, /* IF */
+       { 0x10, 0x00 }, /* MISC */
+       { 0x12, 0xca }, /* IDAC */
+       { 0x16, 0x90 }, /* MODE */
+       { 0x32, 0x38 }, /* MODE A/D */
+       { 0x71, 0x3f }, /* TOP1 */
+       { 0x72, 0x3f }, /* TOP2 */
+       { 0x74, 0x3f }, /* TOP3 */
+       { 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
+       { 0x2c, 0x34 }, /* OVERRIDE */
+       { 0x4d, 0x40 }, /* OVERRIDE */
+       { 0x7f, 0x02 }, /* OVERRIDE */
+       { 0x9a, 0x52 }, /* OVERRIDE */
+       { 0x48, 0x5a }, /* OVERRIDE */
+       { 0x76, 0x1a }, /* OVERRIDE */
+       { 0x6a, 0x48 }, /* OVERRIDE */
+       { 0x64, 0x28 }, /* OVERRIDE */
+       { 0x66, 0xe6 }, /* OVERRIDE */
+       { 0x35, 0x0e }, /* OVERRIDE */
+       { 0x7e, 0x01 }, /* OVERRIDE */
+       { 0x04, 0x0b }, /* OVERRIDE */
+       { 0x68, 0xb4 }, /* OVERRIDE */
+       { 0x36, 0x00 }, /* OVERRIDE */
+       { 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
+       { 0, 0 }
+};
+
+/* ------------------------------------------------------------------------- */
+
+static struct reg_pair_t reg_pair_rftune[] = {
+       { 0x11, 0x00 }, /* abort tune */
+       { 0x13, 0x15 },
+       { 0x14, 0x40 },
+       { 0x15, 0x0e },
+       { 0x11, 0x02 }, /* start tune */
+       { 0, 0 }
+};
+
+/* ------------------------------------------------------------------------- */
+
+struct mxl5007t_state {
+       struct list_head hybrid_tuner_instance_list;
+       struct tuner_i2c_props i2c_props;
+
+       struct mutex lock;
+
+       struct mxl5007t_config *config;
+
+       enum mxl5007t_chip_version chip_id;
+
+       struct reg_pair_t tab_init[ARRAY_SIZE(init_tab)];
+       struct reg_pair_t tab_init_cable[ARRAY_SIZE(init_tab_cable)];
+       struct reg_pair_t tab_rftune[ARRAY_SIZE(reg_pair_rftune)];
+
+       u32 frequency;
+       u32 bandwidth;
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* called by _init and _rftun to manipulate the register arrays */
+
+static void set_reg_bits(struct reg_pair_t *reg_pair, u8 reg, u8 mask, u8 val)
+{
+       unsigned int i = 0;
+
+       while (reg_pair[i].reg || reg_pair[i].val) {
+               if (reg_pair[i].reg == reg) {
+                       reg_pair[i].val &= ~mask;
+                       reg_pair[i].val |= val;
+               }
+               i++;
+
+       }
+       return;
+}
+
+static void copy_reg_bits(struct reg_pair_t *reg_pair1,
+                         struct reg_pair_t *reg_pair2)
+{
+       unsigned int i, j;
+
+       i = j = 0;
+
+       while (reg_pair1[i].reg || reg_pair1[i].val) {
+               while (reg_pair2[j].reg || reg_pair2[j].reg) {
+                       if (reg_pair1[i].reg != reg_pair2[j].reg) {
+                               j++;
+                               continue;
+                       }
+                       reg_pair2[j].val = reg_pair1[i].val;
+                       break;
+               }
+               i++;
+       }
+       return;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void mxl5007t_set_mode_bits(struct mxl5007t_state *state,
+                                  enum mxl5007t_mode mode,
+                                  s32 if_diff_out_level)
+{
+       switch (mode) {
+       case MxL_MODE_OTA_DVBT_ATSC:
+               set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);
+               set_reg_bits(state->tab_init, 0x35, 0xff, 0x0e);
+               break;
+       case MxL_MODE_OTA_ISDBT:
+               set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);
+               set_reg_bits(state->tab_init, 0x35, 0xff, 0x12);
+               break;
+       case MxL_MODE_OTA_NTSC_PAL_GH:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               break;
+       case MxL_MODE_OTA_PAL_IB:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               break;
+       case MxL_MODE_OTA_PAL_D_SECAM_KL:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               break;
+       case MxL_MODE_CABLE_DIGITAL:
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       case MxL_MODE_CABLE_NTSC_PAL_GH:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       case MxL_MODE_CABLE_PAL_IB:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       case MxL_MODE_CABLE_PAL_D_SECAM_KL:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       case MxL_MODE_CABLE_SCTE40:
+               set_reg_bits(state->tab_init_cable, 0x36, 0xff, 0x08);
+               set_reg_bits(state->tab_init_cable, 0x68, 0xff, 0xbc);
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       default:
+               mxl_fail(-EINVAL);
+       }
+       return;
+}
+
+static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
+                                     enum mxl5007t_if_freq if_freq,
+                                     int invert_if)
+{
+       u8 val;
+
+       switch (if_freq) {
+       case MxL_IF_4_MHZ:
+               val = 0x00;
+               break;
+       case MxL_IF_4_5_MHZ:
+               val = 0x20;
+               break;
+       case MxL_IF_4_57_MHZ:
+               val = 0x30;
+               break;
+       case MxL_IF_5_MHZ:
+               val = 0x40;
+               break;
+       case MxL_IF_5_38_MHZ:
+               val = 0x50;
+               break;
+       case MxL_IF_6_MHZ:
+               val = 0x60;
+               break;
+       case MxL_IF_6_28_MHZ:
+               val = 0x70;
+               break;
+       case MxL_IF_9_1915_MHZ:
+               val = 0x80;
+               break;
+       case MxL_IF_35_25_MHZ:
+               val = 0x90;
+               break;
+       case MxL_IF_36_15_MHZ:
+               val = 0xa0;
+               break;
+       case MxL_IF_44_MHZ:
+               val = 0xb0;
+               break;
+       default:
+               mxl_fail(-EINVAL);
+               return;
+       }
+       set_reg_bits(state->tab_init, 0x0c, 0xf0, val);
+
+       /* set inverted IF or normal IF */
+       set_reg_bits(state->tab_init, 0x0c, 0x08, invert_if ? 0x08 : 0x00);
+
+       return;
+}
+
+static void mxl5007t_set_xtal_freq_bits(struct mxl5007t_state *state,
+                                       enum mxl5007t_xtal_freq xtal_freq)
+{
+       u8 val;
+
+       switch (xtal_freq) {
+       case MxL_XTAL_16_MHZ:
+               val = 0x00; /* select xtal freq & Ref Freq */
+               break;
+       case MxL_XTAL_20_MHZ:
+               val = 0x11;
+               break;
+       case MxL_XTAL_20_25_MHZ:
+               val = 0x22;
+               break;
+       case MxL_XTAL_20_48_MHZ:
+               val = 0x33;
+               break;
+       case MxL_XTAL_24_MHZ:
+               val = 0x44;
+               break;
+       case MxL_XTAL_25_MHZ:
+               val = 0x55;
+               break;
+       case MxL_XTAL_25_14_MHZ:
+               val = 0x66;
+               break;
+       case MxL_XTAL_27_MHZ:
+               val = 0x77;
+               break;
+       case MxL_XTAL_28_8_MHZ:
+               val = 0x88;
+               break;
+       case MxL_XTAL_32_MHZ:
+               val = 0x99;
+               break;
+       case MxL_XTAL_40_MHZ:
+               val = 0xaa;
+               break;
+       case MxL_XTAL_44_MHZ:
+               val = 0xbb;
+               break;
+       case MxL_XTAL_48_MHZ:
+               val = 0xcc;
+               break;
+       case MxL_XTAL_49_3811_MHZ:
+               val = 0xdd;
+               break;
+       default:
+               mxl_fail(-EINVAL);
+               return;
+       }
+       set_reg_bits(state->tab_init, 0x0b, 0xff, val);
+
+       return;
+}
+
+static struct reg_pair_t *mxl5007t_calc_init_regs(struct mxl5007t_state *state,
+                                                 enum mxl5007t_mode mode)
+{
+       struct mxl5007t_config *cfg = state->config;
+
+       memcpy(&state->tab_init, &init_tab, sizeof(init_tab));
+       memcpy(&state->tab_init_cable, &init_tab_cable, sizeof(init_tab_cable));
+
+       mxl5007t_set_mode_bits(state, mode, cfg->if_diff_out_level);
+       mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if);
+       mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz);
+
+       set_reg_bits(state->tab_init, 0x10, 0x40, cfg->loop_thru_enable << 6);
+
+       set_reg_bits(state->tab_init, 0xd8, 0x08, cfg->clk_out_enable << 3);
+
+       set_reg_bits(state->tab_init, 0x10, 0x07, cfg->clk_out_amp);
+
+       /* set IDAC to automatic mode control by AGC */
+       set_reg_bits(state->tab_init, 0x12, 0x80, 0x00);
+
+       if (mode >= MxL_MODE_CABLE_DIGITAL) {
+               copy_reg_bits(state->tab_init, state->tab_init_cable);
+               return state->tab_init_cable;
+       } else
+               return state->tab_init;
+}
+
+/* ------------------------------------------------------------------------- */
+
+enum mxl5007t_bw_mhz {
+       MxL_BW_6MHz = 6,
+       MxL_BW_7MHz = 7,
+       MxL_BW_8MHz = 8,
+};
+
+static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,
+                                enum mxl5007t_bw_mhz bw)
+{
+       u8 val;
+
+       switch (bw) {
+       case MxL_BW_6MHz:
+               val = 0x15; /* set DIG_MODEINDEX, DIG_MODEINDEX_A,
+                            * and DIG_MODEINDEX_CSF */
+               break;
+       case MxL_BW_7MHz:
+               val = 0x21;
+               break;
+       case MxL_BW_8MHz:
+               val = 0x3f;
+               break;
+       default:
+               mxl_fail(-EINVAL);
+               return;
+       }
+       set_reg_bits(state->tab_rftune, 0x13, 0x3f, val);
+
+       return;
+}
+
+static struct
+reg_pair_t *mxl5007t_calc_rf_tune_regs(struct mxl5007t_state *state,
+                                      u32 rf_freq, enum mxl5007t_bw_mhz bw)
+{
+       u32 dig_rf_freq = 0;
+       u32 temp;
+       u32 frac_divider = 1000000;
+       unsigned int i;
+
+       memcpy(&state->tab_rftune, &reg_pair_rftune, sizeof(reg_pair_rftune));
+
+       mxl5007t_set_bw_bits(state, bw);
+
+       /* Convert RF frequency into 16 bits =>
+        * 10 bit integer (MHz) + 6 bit fraction */
+       dig_rf_freq = rf_freq / MHz;
+
+       temp = rf_freq % MHz;
+
+       for (i = 0; i < 6; i++) {
+               dig_rf_freq <<= 1;
+               frac_divider /= 2;
+               if (temp > frac_divider) {
+                       temp -= frac_divider;
+                       dig_rf_freq++;
+               }
+       }
+
+       /* add to have shift center point by 7.8124 kHz */
+       if (temp > 7812)
+               dig_rf_freq++;
+
+       set_reg_bits(state->tab_rftune, 0x14, 0xff, (u8)dig_rf_freq);
+       set_reg_bits(state->tab_rftune, 0x15, 0xff, (u8)(dig_rf_freq >> 8));
+
+       return state->tab_rftune;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_write_reg(struct mxl5007t_state *state, u8 reg, u8 val)
+{
+       u8 buf[] = { reg, val };
+       struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
+                              .buf = buf, .len = 2 };
+       int ret;
+
+       ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
+       if (ret != 1) {
+               mxl_err("failed!");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int mxl5007t_write_regs(struct mxl5007t_state *state,
+                              struct reg_pair_t *reg_pair)
+{
+       unsigned int i = 0;
+       int ret = 0;
+
+       while ((ret == 0) && (reg_pair[i].reg || reg_pair[i].val)) {
+               ret = mxl5007t_write_reg(state,
+                                        reg_pair[i].reg, reg_pair[i].val);
+               i++;
+       }
+       return ret;
+}
+
+static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
+{
+       struct i2c_msg msg[] = {
+               { .addr = state->i2c_props.addr, .flags = 0,
+                 .buf = &reg, .len = 1 },
+               { .addr = state->i2c_props.addr, .flags = I2C_M_RD,
+                 .buf = val, .len = 1 },
+       };
+       int ret;
+
+       ret = i2c_transfer(state->i2c_props.adap, msg, 2);
+       if (ret != 2) {
+               mxl_err("failed!");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int mxl5007t_soft_reset(struct mxl5007t_state *state)
+{
+       u8 d = 0xff;
+       struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
+                              .buf = &d, .len = 1 };
+
+       int ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
+
+       if (ret != 1) {
+               mxl_err("failed!");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int mxl5007t_tuner_init(struct mxl5007t_state *state,
+                              enum mxl5007t_mode mode)
+{
+       struct reg_pair_t *init_regs;
+       int ret;
+
+       ret = mxl5007t_soft_reset(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       /* calculate initialization reg array */
+       init_regs = mxl5007t_calc_init_regs(state, mode);
+
+       ret = mxl5007t_write_regs(state, init_regs);
+       if (mxl_fail(ret))
+               goto fail;
+       mdelay(1);
+
+       ret = mxl5007t_write_reg(state, 0x2c, 0x35);
+       mxl_fail(ret);
+fail:
+       return ret;
+}
+
+static int mxl5007t_tuner_rf_tune(struct mxl5007t_state *state, u32 rf_freq_hz,
+                                 enum mxl5007t_bw_mhz bw)
+{
+       struct reg_pair_t *rf_tune_regs;
+       int ret;
+
+       /* calculate channel change reg array */
+       rf_tune_regs = mxl5007t_calc_rf_tune_regs(state, rf_freq_hz, bw);
+
+       ret = mxl5007t_write_regs(state, rf_tune_regs);
+       if (mxl_fail(ret))
+               goto fail;
+       msleep(3);
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_synth_lock_status(struct mxl5007t_state *state,
+                                     int *rf_locked, int *ref_locked)
+{
+       u8 d;
+       int ret;
+
+       *rf_locked = 0;
+       *ref_locked = 0;
+
+       ret = mxl5007t_read_reg(state, 0xcf, &d);
+       if (mxl_fail(ret))
+               goto fail;
+
+       if ((d & 0x0c) == 0x0c)
+               *rf_locked = 1;
+
+       if ((d & 0x03) == 0x03)
+               *ref_locked = 1;
+fail:
+       return ret;
+}
+
+static int mxl5007t_check_rf_input_power(struct mxl5007t_state *state,
+                                        s32 *rf_input_level)
+{
+       u8 d1, d2;
+       int ret;
+
+       ret = mxl5007t_read_reg(state, 0xb7, &d1);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_read_reg(state, 0xbf, &d2);
+       if (mxl_fail(ret))
+               goto fail;
+
+       d2 = d2 >> 4;
+       if (d2 > 7)
+               d2 += 0xf0;
+
+       *rf_input_level = (s32)(d1 + d2 - 113);
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       int rf_locked, ref_locked;
+       s32 rf_input_level;
+       int ret;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = mxl5007t_synth_lock_status(state, &rf_locked, &ref_locked);
+       if (mxl_fail(ret))
+               goto fail;
+       mxl_debug("%s%s", rf_locked ? "rf locked " : "",
+                 ref_locked ? "ref locked" : "");
+
+       ret = mxl5007t_check_rf_input_power(state, &rf_input_level);
+       if (mxl_fail(ret))
+               goto fail;
+       mxl_debug("rf input power: %d", rf_input_level);
+fail:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_set_params(struct dvb_frontend *fe,
+                              struct dvb_frontend_parameters *params)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       enum mxl5007t_bw_mhz bw;
+       enum mxl5007t_mode mode;
+       int ret;
+       u32 freq = params->frequency;
+
+       if (fe->ops.info.type == FE_ATSC) {
+               switch (params->u.vsb.modulation) {
+               case VSB_8:
+               case VSB_16:
+                       mode = MxL_MODE_OTA_DVBT_ATSC;
+                       break;
+               case QAM_64:
+               case QAM_256:
+                       mode = MxL_MODE_CABLE_DIGITAL;
+                       break;
+               default:
+                       mxl_err("modulation not set!");
+                       return -EINVAL;
+               }
+               bw = MxL_BW_6MHz;
+       } else if (fe->ops.info.type == FE_OFDM) {
+               switch (params->u.ofdm.bandwidth) {
+               case BANDWIDTH_6_MHZ:
+                       bw = MxL_BW_6MHz;
+                       break;
+               case BANDWIDTH_7_MHZ:
+                       bw = MxL_BW_7MHz;
+                       break;
+               case BANDWIDTH_8_MHZ:
+                       bw = MxL_BW_8MHz;
+                       break;
+               default:
+                       mxl_err("bandwidth not set!");
+                       return -EINVAL;
+               }
+               mode = MxL_MODE_OTA_DVBT_ATSC;
+       } else {
+               mxl_err("modulation type not supported!");
+               return -EINVAL;
+       }
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       mutex_lock(&state->lock);
+
+       ret = mxl5007t_tuner_init(state, mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_tuner_rf_tune(state, freq, bw);
+       if (mxl_fail(ret))
+               goto fail;
+
+       state->frequency = freq;
+       state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
+               params->u.ofdm.bandwidth : 0;
+fail:
+       mutex_unlock(&state->lock);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+static int mxl5007t_set_analog_params(struct dvb_frontend *fe,
+                                     struct analog_parameters *params)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       enum mxl5007t_bw_mhz bw = 0; /* FIXME */
+       enum mxl5007t_mode cbl_mode;
+       enum mxl5007t_mode ota_mode;
+       char *mode_name;
+       int ret;
+       u32 freq = params->frequency * 62500;
+
+#define cable 1
+       if (params->std & V4L2_STD_MN) {
+               cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
+               ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
+               mode_name = "MN";
+       } else if (params->std & V4L2_STD_B) {
+               cbl_mode = MxL_MODE_CABLE_PAL_IB;
+               ota_mode = MxL_MODE_OTA_PAL_IB;
+               mode_name = "B";
+       } else if (params->std & V4L2_STD_GH) {
+               cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
+               ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
+               mode_name = "GH";
+       } else if (params->std & V4L2_STD_PAL_I) {
+               cbl_mode = MxL_MODE_CABLE_PAL_IB;
+               ota_mode = MxL_MODE_OTA_PAL_IB;
+               mode_name = "I";
+       } else if (params->std & V4L2_STD_DK) {
+               cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
+               ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
+               mode_name = "DK";
+       } else if (params->std & V4L2_STD_SECAM_L) {
+               cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
+               ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
+               mode_name = "L";
+       } else if (params->std & V4L2_STD_SECAM_LC) {
+               cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
+               ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
+               mode_name = "L'";
+       } else {
+               mode_name = "xx";
+               /* FIXME */
+               cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
+               ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
+       }
+       mxl_debug("setting mxl5007 to system %s", mode_name);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       mutex_lock(&state->lock);
+
+       ret = mxl5007t_tuner_init(state, cable ? cbl_mode : ota_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_tuner_rf_tune(state, freq, bw);
+       if (mxl_fail(ret))
+               goto fail;
+
+       state->frequency = freq;
+       state->bandwidth = 0;
+fail:
+       mutex_unlock(&state->lock);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_init(struct dvb_frontend *fe)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       int ret;
+       u8 d;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = mxl5007t_read_reg(state, 0x05, &d);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_write_reg(state, 0x05, d | 0x01);
+       mxl_fail(ret);
+fail:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+static int mxl5007t_sleep(struct dvb_frontend *fe)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       int ret;
+       u8 d;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = mxl5007t_read_reg(state, 0x05, &d);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_write_reg(state, 0x05, d & ~0x01);
+       mxl_fail(ret);
+fail:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       *frequency = state->frequency;
+       return 0;
+}
+
+static int mxl5007t_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       *bandwidth = state->bandwidth;
+       return 0;
+}
+
+static int mxl5007t_release(struct dvb_frontend *fe)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+
+       mutex_lock(&mxl5007t_list_mutex);
+
+       if (state)
+               hybrid_tuner_release_state(state);
+
+       mutex_unlock(&mxl5007t_list_mutex);
+
+       fe->tuner_priv = NULL;
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static struct dvb_tuner_ops mxl5007t_tuner_ops = {
+       .info = {
+               .name = "MaxLinear MxL5007T",
+       },
+       .init              = mxl5007t_init,
+       .sleep             = mxl5007t_sleep,
+       .set_params        = mxl5007t_set_params,
+       .set_analog_params = mxl5007t_set_analog_params,
+       .get_status        = mxl5007t_get_status,
+       .get_frequency     = mxl5007t_get_frequency,
+       .get_bandwidth     = mxl5007t_get_bandwidth,
+       .release           = mxl5007t_release,
+};
+
+static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
+{
+       char *name;
+       int ret;
+       u8 id;
+
+       ret = mxl5007t_read_reg(state, 0xd3, &id);
+       if (mxl_fail(ret))
+               goto fail;
+
+       switch (id) {
+       case MxL_5007_V1_F1:
+               name = "MxL5007.v1.f1";
+               break;
+       case MxL_5007_V1_F2:
+               name = "MxL5007.v1.f2";
+               break;
+       case MxL_5007_V2_100_F1:
+               name = "MxL5007.v2.100.f1";
+               break;
+       case MxL_5007_V2_100_F2:
+               name = "MxL5007.v2.100.f2";
+               break;
+       case MxL_5007_V2_200_F1:
+               name = "MxL5007.v2.200.f1";
+               break;
+       case MxL_5007_V2_200_F2:
+               name = "MxL5007.v2.200.f2";
+               break;
+       default:
+               name = "MxL5007T";
+               id = MxL_UNKNOWN_ID;
+       }
+       state->chip_id = id;
+       mxl_info("%s detected @ %d-%04x", name,
+                i2c_adapter_id(state->i2c_props.adap),
+                state->i2c_props.addr);
+       return 0;
+fail:
+       mxl_warn("unable to identify device @ %d-%04x",
+                i2c_adapter_id(state->i2c_props.adap),
+                state->i2c_props.addr);
+
+       state->chip_id = MxL_UNKNOWN_ID;
+       return ret;
+}
+
+struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
+                                    struct i2c_adapter *i2c, u8 addr,
+                                    struct mxl5007t_config *cfg)
+{
+       struct mxl5007t_state *state = NULL;
+       int instance, ret;
+
+       mutex_lock(&mxl5007t_list_mutex);
+       instance = hybrid_tuner_request_state(struct mxl5007t_state, state,
+                                             hybrid_tuner_instance_list,
+                                             i2c, addr, "mxl5007");
+       switch (instance) {
+       case 0:
+               goto fail;
+               break;
+       case 1:
+               /* new tuner instance */
+               state->config = cfg;
+
+               mutex_init(&state->lock);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               ret = mxl5007t_get_chip_id(state);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+
+               /* check return value of mxl5007t_get_chip_id */
+               if (mxl_fail(ret))
+                       goto fail;
+               break;
+       default:
+               /* existing tuner instance */
+               break;
+       }
+       fe->tuner_priv = state;
+       mutex_unlock(&mxl5007t_list_mutex);
+
+       memcpy(&fe->ops.tuner_ops, &mxl5007t_tuner_ops,
+              sizeof(struct dvb_tuner_ops));
+
+       return fe;
+fail:
+       mutex_unlock(&mxl5007t_list_mutex);
+
+       mxl5007t_release(fe);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(mxl5007t_attach);
+MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/common/tuners/mxl5007t.h b/drivers/media/common/tuners/mxl5007t.h
new file mode 100644 (file)
index 0000000..aa3eea0
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *  mxl5007t.h - driver for the MaxLinear MxL5007T silicon tuner
+ *
+ *  Copyright (C) 2008 Michael Krufky <mkrufky@linuxtv.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.
+ */
+
+#ifndef __MXL5007T_H__
+#define __MXL5007T_H__
+
+#include "dvb_frontend.h"
+
+/* ------------------------------------------------------------------------- */
+
+enum mxl5007t_if_freq {
+       MxL_IF_4_MHZ,      /*  4000000 */
+       MxL_IF_4_5_MHZ,    /*  4500000 */
+       MxL_IF_4_57_MHZ,   /*  4570000 */
+       MxL_IF_5_MHZ,      /*  5000000 */
+       MxL_IF_5_38_MHZ,   /*  5380000 */
+       MxL_IF_6_MHZ,      /*  6000000 */
+       MxL_IF_6_28_MHZ,   /*  6280000 */
+       MxL_IF_9_1915_MHZ, /*  9191500 */
+       MxL_IF_35_25_MHZ,  /* 35250000 */
+       MxL_IF_36_15_MHZ,  /* 36150000 */
+       MxL_IF_44_MHZ,     /* 44000000 */
+};
+
+enum mxl5007t_xtal_freq {
+       MxL_XTAL_16_MHZ,      /* 16000000 */
+       MxL_XTAL_20_MHZ,      /* 20000000 */
+       MxL_XTAL_20_25_MHZ,   /* 20250000 */
+       MxL_XTAL_20_48_MHZ,   /* 20480000 */
+       MxL_XTAL_24_MHZ,      /* 24000000 */
+       MxL_XTAL_25_MHZ,      /* 25000000 */
+       MxL_XTAL_25_14_MHZ,   /* 25140000 */
+       MxL_XTAL_27_MHZ,      /* 27000000 */
+       MxL_XTAL_28_8_MHZ,    /* 28800000 */
+       MxL_XTAL_32_MHZ,      /* 32000000 */
+       MxL_XTAL_40_MHZ,      /* 40000000 */
+       MxL_XTAL_44_MHZ,      /* 44000000 */
+       MxL_XTAL_48_MHZ,      /* 48000000 */
+       MxL_XTAL_49_3811_MHZ, /* 49381100 */
+};
+
+enum mxl5007t_clkout_amp {
+       MxL_CLKOUT_AMP_0_94V = 0,
+       MxL_CLKOUT_AMP_0_53V = 1,
+       MxL_CLKOUT_AMP_0_37V = 2,
+       MxL_CLKOUT_AMP_0_28V = 3,
+       MxL_CLKOUT_AMP_0_23V = 4,
+       MxL_CLKOUT_AMP_0_20V = 5,
+       MxL_CLKOUT_AMP_0_17V = 6,
+       MxL_CLKOUT_AMP_0_15V = 7,
+};
+
+struct mxl5007t_config {
+       s32 if_diff_out_level;
+       enum mxl5007t_clkout_amp clk_out_amp;
+       enum mxl5007t_xtal_freq xtal_freq_hz;
+       enum mxl5007t_if_freq if_freq_hz;
+       unsigned int invert_if:1;
+       unsigned int loop_thru_enable:1;
+       unsigned int clk_out_enable:1;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_MXL5007T) || (defined(CONFIG_MEDIA_TUNER_MXL5007T_MODULE) && defined(MODULE))
+extern struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
+                                           struct i2c_adapter *i2c, u8 addr,
+                                           struct mxl5007t_config *cfg);
+#else
+static inline struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
+                                                  struct i2c_adapter *i2c,
+                                                  u8 addr,
+                                                  struct mxl5007t_config *cfg)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+#endif /* __MXL5007T_H__ */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
index a0545ba957b05c5be756016ebb041d792088006d..72abf0b73486d19c3e69e4330b0213f1d963a9f3 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include "tuner-i2c.h"
index 266c255cf0d89241f2332e50ea8947329d13d311..597e47f5d69cde232fbf03bc52c685785ab72fc9 100644 (file)
@@ -6,7 +6,7 @@
  */
 #include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/tuner.h>
 #include <media/v4l2-common.h>
 #include <media/tuner-types.h>
index 7588db1319d0cd3d3d654af53dc972ee6dadb717..7e9c090fc04ea9ae2e7273890fce6f5c04241db1 100644 (file)
@@ -1,7 +1,6 @@
 config DVB_BT8XX
        tristate "BT8xx based PCI cards"
        depends on DVB_CORE && PCI && I2C && VIDEO_BT848
-       depends on HOTPLUG      # due to FW_LOADER
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_SP887X if !DVB_FE_CUSTOMISE
        select DVB_NXT6000 if !DVB_FE_CUSTOMISE
@@ -10,7 +9,6 @@ config DVB_BT8XX
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          Support for PCI cards based on the Bt8xx PCI bridge. Examples are
          the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
index a577c0f89f6745c421426a9b49f2af6888ba285e..e84152b7576d731940fc957b22c77b0e42f67a4f 100644 (file)
@@ -1,8 +1,6 @@
 config DVB_USB
        tristate "Support for various USB DVB devices"
        depends on DVB_CORE && USB && I2C && INPUT
-       depends on HOTPLUG      # due to FW_LOADER
-       select FW_LOADER
        help
          By enabling this you will be able to choose the various supported
          USB1.1 and USB2.0 DVB devices.
@@ -246,6 +244,14 @@ config DVB_USB_AF9005_REMOTE
          Say Y here to support the default remote control decoding for the
          Afatech AF9005 based receiver.
 
+config DVB_USB_DW2102
+       tristate "DvbWorld 2102 DVB-S USB2.0 receiver"
+       depends on DVB_USB
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_PLL if !DVB_FE_CUSTOMISE
+       help
+          Say Y here to support the DvbWorld 2102 DVB-S USB2.0 receiver.
+
 config DVB_USB_ANYSEE
        tristate "Anysee DVB-T/C USB2.0 support"
        depends on DVB_USB
index 44c11e45e564022ba889a5c9a7437a12a0f5ad87..e206f1ea0027c9804789525fa9a558c3bcaf6be1 100644 (file)
@@ -64,6 +64,9 @@ obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
 dvb-usb-anysee-objs = anysee.o
 obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
 
+dvb-usb-dw2102-objs = dw2102.o
+obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
index adfd4fc82efd53cfa106551ef9fad4e51a351bd8..2f408d2e1ef349be29c3ae6ba97ee09df9b49bc5 100644 (file)
@@ -43,7 +43,7 @@ module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-struct mutex anysee_usb_mutex;
+static struct mutex anysee_usb_mutex;
 
 static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
        u8 *rbuf, u8 rlen)
index e5238b31e946e1b26c426d5ea5a76cbabedb5520..029b437caf9a11d20896df531762e279d7378858 100644 (file)
 #define USB_PID_ASUS_U3000                             0x171f
 #define USB_PID_ASUS_U3100                             0x173f
 #define USB_PID_YUAN_EC372S                            0x1edc
+#define USB_PID_DW2102                                 0x2102
 
 #endif
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
new file mode 100644 (file)
index 0000000..a4d898b
--- /dev/null
@@ -0,0 +1,425 @@
+/* DVB USB framework compliant Linux driver for the DVBWorld DVB-S 2102 Card
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+*      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.
+*
+* see Documentation/dvb/README.dvb-usb for more information
+*/
+#include <linux/version.h>
+#include "dw2102.h"
+#include "stv0299.h"
+#include "z0194a.h"
+
+#ifndef USB_PID_DW2102
+#define USB_PID_DW2102 0x2102
+#endif
+
+#define DW2102_READ_MSG 0
+#define DW2102_WRITE_MSG 1
+
+#define REG_1F_SYMBOLRATE_BYTE0 0x1f
+#define REG_20_SYMBOLRATE_BYTE1 0x20
+#define REG_21_SYMBOLRATE_BYTE2 0x21
+
+#define DW2102_VOLTAGE_CTRL (0x1800)
+#define DW2102_RC_QUERY (0x1a00)
+
+struct dw2102_state {
+       u32 last_key_pressed;
+};
+struct dw2102_rc_keys {
+       u32 keycode;
+       u32 event;
+};
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int dw2102_op_rw(struct usb_device *dev, u8 request, u16 value,
+               u8 *data, u16 len, int flags)
+{
+       int ret;
+       u8 u8buf[len];
+
+       unsigned int pipe = (flags == DW2102_READ_MSG) ?
+               usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
+       u8 request_type = (flags == DW2102_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
+
+       if (flags == DW2102_WRITE_MSG)
+               memcpy(u8buf, data, len);
+       ret = usb_control_msg(dev, pipe, request,
+               request_type | USB_TYPE_VENDOR, value, 0 , u8buf, len, 2000);
+
+       if (flags == DW2102_READ_MSG)
+               memcpy(data, u8buf, len);
+       return ret;
+}
+
+/* I2C */
+
+static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+               int num)
+{
+struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int i = 0, ret = 0;
+       u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
+       u8 request;
+       u16 value;
+
+       if (!d)
+               return -ENODEV;
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       switch (num) {
+       case 2:
+               /* read stv0299 register */
+               request = 0xb5;
+               value = msg[0].buf[0];/* register */
+               for (i = 0; i < msg[1].len; i++) {
+                       value = value + i;
+                       ret = dw2102_op_rw(d->udev, 0xb5,
+                               value, buf6, 2, DW2102_READ_MSG);
+                       msg[1].buf[i] = buf6[0];
+
+               }
+               break;
+       case 1:
+               switch (msg[0].addr) {
+               case 0x68:
+                       /* write to stv0299 register */
+                       buf6[0] = 0x2a;
+                       buf6[1] = msg[0].buf[0];
+                       buf6[2] = msg[0].buf[1];
+                       ret = dw2102_op_rw(d->udev, 0xb2,
+                               0, buf6, 3, DW2102_WRITE_MSG);
+                       break;
+               case 0x60:
+                       if (msg[0].flags == 0) {
+                       /* write to tuner pll */
+                               buf6[0] = 0x2c;
+                               buf6[1] = 5;
+                               buf6[2] = 0xc0;
+                               buf6[3] = msg[0].buf[0];
+                               buf6[4] = msg[0].buf[1];
+                               buf6[5] = msg[0].buf[2];
+                               buf6[6] = msg[0].buf[3];
+                               ret = dw2102_op_rw(d->udev, 0xb2,
+                               0, buf6, 7, DW2102_WRITE_MSG);
+                       } else {
+                       /* write to tuner pll */
+                               ret = dw2102_op_rw(d->udev, 0xb5,
+                               0, buf6, 1, DW2102_READ_MSG);
+                               msg[0].buf[0] = buf6[0];
+                       }
+                       break;
+               case (DW2102_RC_QUERY):
+                       ret  = dw2102_op_rw(d->udev, 0xb8,
+                               0, buf6, 2, DW2102_READ_MSG);
+                       msg[0].buf[0] = buf6[0];
+                       msg[0].buf[1] = buf6[1];
+                       break;
+               case (DW2102_VOLTAGE_CTRL):
+                       buf6[0] = 0x30;
+                       buf6[1] = msg[0].buf[0];
+                       ret = dw2102_op_rw(d->udev, 0xb2,
+                               0, buf6, 2, DW2102_WRITE_MSG);
+                       break;
+               }
+
+               break;
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+       return num;
+}
+
+static u32 dw2102_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dw2102_i2c_algo = {
+       .master_xfer = dw2102_i2c_transfer,
+       .functionality = dw2102_i2c_func,
+};
+
+static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       static u8 command_13v[1] = {0x00};
+       static u8 command_18v[1] = {0x01};
+       struct i2c_msg msg[] = {
+               {.addr = DW2102_VOLTAGE_CTRL, .flags = 0,
+                       .buf = command_13v, .len = 1},
+       };
+
+       struct dvb_usb_adapter *udev_adap =
+               (struct dvb_usb_adapter *)(fe->dvb->priv);
+       if (voltage == SEC_VOLTAGE_18)
+               msg[0].buf = command_18v;
+       i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
+       return 0;
+}
+
+static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
+{
+       d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
+               &d->dev->i2c_adap);
+       if (d->fe != NULL) {
+               d->fe->ops.set_voltage = dw2102_set_voltage;
+               info("Attached stv0299!\n");
+               return 0;
+       }
+       return -EIO;
+}
+
+static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+               &adap->dev->i2c_adap, DVB_PLL_OPERA1);
+       return 0;
+}
+
+static struct dvb_usb_rc_key dw2102_rc_keys[] = {
+       { 0xf8, 0x0a, KEY_Q },          /*power*/
+       { 0xf8, 0x0c, KEY_M },          /*mute*/
+       { 0xf8, 0x11, KEY_1 },
+       { 0xf8, 0x12, KEY_2 },
+       { 0xf8, 0x13, KEY_3 },
+       { 0xf8, 0x14, KEY_4 },
+       { 0xf8, 0x15, KEY_5 },
+       { 0xf8, 0x16, KEY_6 },
+       { 0xf8, 0x17, KEY_7 },
+       { 0xf8, 0x18, KEY_8 },
+       { 0xf8, 0x19, KEY_9 },
+       { 0xf8, 0x10, KEY_0 },
+       { 0xf8, 0x1c, KEY_PAGEUP },     /*ch+*/
+       { 0xf8, 0x0f, KEY_PAGEDOWN },   /*ch-*/
+       { 0xf8, 0x1a, KEY_O },          /*vol+*/
+       { 0xf8, 0x0e, KEY_Z },          /*vol-*/
+       { 0xf8, 0x04, KEY_R },          /*rec*/
+       { 0xf8, 0x09, KEY_D },          /*fav*/
+       { 0xf8, 0x08, KEY_BACKSPACE },  /*rewind*/
+       { 0xf8, 0x07, KEY_A },          /*fast*/
+       { 0xf8, 0x0b, KEY_P },          /*pause*/
+       { 0xf8, 0x02, KEY_ESC },        /*cancel*/
+       { 0xf8, 0x03, KEY_G },          /*tab*/
+       { 0xf8, 0x00, KEY_UP },         /*up*/
+       { 0xf8, 0x1f, KEY_ENTER },      /*ok*/
+       { 0xf8, 0x01, KEY_DOWN },       /*down*/
+       { 0xf8, 0x05, KEY_C },          /*cap*/
+       { 0xf8, 0x06, KEY_S },          /*stop*/
+       { 0xf8, 0x40, KEY_F },          /*full*/
+       { 0xf8, 0x1e, KEY_W },          /*tvmode*/
+       { 0xf8, 0x1b, KEY_B },          /*recall*/
+
+};
+
+
+
+static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+       struct dw2102_state *st = d->priv;
+       u8 key[2];
+       struct i2c_msg msg[] = {
+               {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,
+               .len = 2},
+       };
+       int i;
+
+       *state = REMOTE_NO_KEY_PRESSED;
+       if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
+               for (i = 0; i < ARRAY_SIZE(dw2102_rc_keys); i++) {
+                       if (dw2102_rc_keys[i].data == msg[0].buf[0]) {
+                               *state = REMOTE_KEY_PRESSED;
+                               *event = dw2102_rc_keys[i].event;
+                               st->last_key_pressed =
+                                       dw2102_rc_keys[i].event;
+                               break;
+                       }
+               st->last_key_pressed = 0;
+               }
+       }
+       /* info("key: %x %x\n",key[0],key[1]); */
+       return 0;
+}
+
+static struct usb_device_id dw2102_table[] = {
+       {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
+       {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
+       { }
+};
+
+MODULE_DEVICE_TABLE(usb, dw2102_table);
+
+static int dw2102_load_firmware(struct usb_device *dev,
+                       const struct firmware *frmwr)
+{
+       u8 *b, *p;
+       int ret = 0, i;
+       u8 reset;
+       u8 reset16 [] = {0, 0, 0, 0, 0, 0, 0};
+       const struct firmware *fw;
+       const char *filename = "dvb-usb-dw2101.fw";
+       switch (dev->descriptor.idProduct) {
+       case 0x2101:
+               ret = request_firmware(&fw, filename, &dev->dev);
+               if (ret != 0) {
+                       err("did not find the firmware file. (%s) "
+                       "Please see linux/Documentation/dvb/ for more details "
+                       "on firmware-problems.", filename);
+                       return ret;
+               }
+               break;
+       case USB_PID_DW2102:
+               fw = frmwr;
+               break;
+       }
+       info("start downloading DW2102 firmware");
+       p = kmalloc(fw->size, GFP_KERNEL);
+       reset = 1;
+       /*stop the CPU*/
+       dw2102_op_rw(dev, 0xa0, 0x7f92, &reset, 1, DW2102_WRITE_MSG);
+       dw2102_op_rw(dev, 0xa0, 0xe600, &reset, 1, DW2102_WRITE_MSG);
+
+       if (p != NULL) {
+               memcpy(p, fw->data, fw->size);
+               for (i = 0; i < fw->size; i += 0x40) {
+                       b = (u8 *) p + i;
+                       if (dw2102_op_rw
+                               (dev, 0xa0, i, b , 0x40,
+                                       DW2102_WRITE_MSG) != 0x40
+                               ) {
+                               err("error while transferring firmware");
+                               ret = -EINVAL;
+                               break;
+                       }
+               }
+               /* restart the CPU */
+               reset = 0;
+               if (ret || dw2102_op_rw
+                       (dev, 0xa0, 0x7f92, &reset, 1,
+                       DW2102_WRITE_MSG) != 1) {
+                       err("could not restart the USB controller CPU.");
+                       ret = -EINVAL;
+               }
+               if (ret || dw2102_op_rw
+                       (dev, 0xa0, 0xe600, &reset, 1,
+                       DW2102_WRITE_MSG) != 1) {
+                       err("could not restart the USB controller CPU.");
+                       ret = -EINVAL;
+               }
+               /* init registers */
+               switch (dev->descriptor.idProduct) {
+               case USB_PID_DW2102:
+                       dw2102_op_rw
+                               (dev, 0xbf, 0x0040, &reset, 0,
+                               DW2102_WRITE_MSG);
+                       dw2102_op_rw
+                               (dev, 0xb9, 0x0000, &reset16[0], 2,
+                               DW2102_READ_MSG);
+                       break;
+               case 0x2101:
+                       dw2102_op_rw
+                               (dev, 0xbc, 0x0030, &reset16[0], 2,
+                               DW2102_READ_MSG);
+                       dw2102_op_rw
+                               (dev, 0xba, 0x0000, &reset16[0], 7,
+                               DW2102_READ_MSG);
+                       dw2102_op_rw
+                               (dev, 0xba, 0x0000, &reset16[0], 7,
+                               DW2102_READ_MSG);
+                       dw2102_op_rw
+                               (dev, 0xb9, 0x0000, &reset16[0], 2,
+                               DW2102_READ_MSG);
+                       break;
+               }
+               kfree(p);
+       }
+       return ret;
+}
+
+static struct dvb_usb_device_properties dw2102_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+       .usb_ctrl = DEVICE_SPECIFIC,
+       .firmware = "dvb-usb-dw2102.fw",
+       .size_of_priv = sizeof(struct dw2102_state),
+       .no_reconnect = 1,
+
+       .i2c_algo = &dw2102_i2c_algo,
+       .rc_key_map = dw2102_rc_keys,
+       .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys),
+       .rc_interval = 150,
+       .rc_query = dw2102_rc_query,
+
+       .generic_bulk_ctrl_endpoint = 0x81,
+       /* parameter for the MPEG2-data transfer */
+       .num_adapters = 1,
+       .download_firmware = dw2102_load_firmware,
+       .adapter = {
+               {
+                       .frontend_attach = dw2102_frontend_attach,
+                       .streaming_ctrl = NULL,
+                       .tuner_attach = dw2102_tuner_attach,
+                       .stream = {
+                               .type = USB_BULK,
+                               .count = 8,
+                               .endpoint = 0x82,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
+               }
+       },
+       .num_device_descs = 2,
+       .devices = {
+               {"DVBWorld DVB-S 2102 USB2.0",
+                       {&dw2102_table[0], NULL},
+                       {NULL},
+               },
+               {"DVBWorld DVB-S 2101 USB2.0",
+                       {&dw2102_table[1], NULL},
+                       {NULL},
+               },
+       }
+};
+
+static int dw2102_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       return dvb_usb_device_init(intf, &dw2102_properties,
+               THIS_MODULE, NULL, adapter_nr);
+}
+
+static struct usb_driver dw2102_driver = {
+       .name = "dw2102",
+       .probe = dw2102_probe,
+       .disconnect = dvb_usb_device_exit,
+       .id_table = dw2102_table,
+};
+
+static int __init dw2102_module_init(void)
+{
+       int ret =  usb_register(&dw2102_driver);
+       if (ret)
+               err("usb_register failed. Error number %d", ret);
+
+       return ret;
+}
+
+static void __exit dw2102_module_exit(void)
+{
+       usb_deregister(&dw2102_driver);
+}
+
+module_init(dw2102_module_init);
+module_exit(dw2102_module_exit);
+
+MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
+MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101 2102 USB2.0 device");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h
new file mode 100644 (file)
index 0000000..7a310f9
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _DW2102_H_
+#define _DW2102_H_
+
+#define DVB_USB_LOG_PREFIX "dw2102"
+#include "dvb-usb.h"
+
+extern int dvb_usb_dw2102_debug;
+#define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
+#endif
index c20553c4da1faa4645b44cf6d77417c897bf0bdb..574dffe91b6882b9280d70a1a035af9fcaa963a6 100644 (file)
@@ -97,9 +97,8 @@ comment "DVB-T (terrestrial) frontends"
 
 config DVB_SP8870
        tristate "Spase sp8870 based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       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.
 
@@ -110,9 +109,8 @@ config DVB_SP8870
 
 config DVB_SP887X
        tristate "Spase sp887x based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       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.
 
@@ -135,6 +133,20 @@ config DVB_CX22702
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
+config DVB_DRX397XD
+       tristate "Micronas DRX3975D/DRX3977D based"
+       depends on DVB_CORE && I2C && HOTPLUG
+       default m if DVB_FE_CUSTOMISE
+       select FW_LOADER
+       help
+         A DVB-T tuner module. Say Y when you want to support this frontend.
+
+         TODO:
+         This driver needs external firmware. Please use the command
+         "<kerneldir>/Documentation/dvb/get_dvb_firmware drx397xD" to
+         download/extract them, and then copy them to /usr/lib/hotplug/firmware
+         or /lib/firmware (depending on configuration of firmware hotplug).
+
 config DVB_L64781
        tristate "LSI L64781"
        depends on DVB_CORE && I2C
@@ -144,9 +156,8 @@ config DVB_L64781
 
 config DVB_TDA1004X
        tristate "Philips TDA10045H/TDA10046H based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       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.
 
@@ -211,9 +222,8 @@ config DVB_DIB7000P
 
 config DVB_TDA10048
        tristate "Philips TDA10048HN based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       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.
 
@@ -253,9 +263,8 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
 
 config DVB_NXT200X
        tristate "NxtWave Communications NXT2002/NXT2004 based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       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
          to support this frontend.
@@ -268,9 +277,8 @@ config DVB_NXT200X
 
 config DVB_OR51211
        tristate "Oren OR51211 based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       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.
 
@@ -281,9 +289,8 @@ config DVB_OR51211
 
 config DVB_OR51132
        tristate "Oren OR51132 based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       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
          to support this frontend.
@@ -297,9 +304,8 @@ config DVB_OR51132
 
 config DVB_BCM3510
        tristate "Broadcom BCM3510"
-       depends on DVB_CORE && I2C && HOTPLUG
+       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
          support this frontend.
index a89dc0fc4c6fe90dbb97d5fd22368a66b0c65000..028da55611c02cbad0c1b20404ad7326de2066e0 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
 obj-$(CONFIG_DVB_MT352) += mt352.o
 obj-$(CONFIG_DVB_ZL10353) += zl10353.o
 obj-$(CONFIG_DVB_CX22702) += cx22702.o
+obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o
 obj-$(CONFIG_DVB_TDA10021) += tda10021.o
 obj-$(CONFIG_DVB_TDA10023) += tda10023.o
 obj-$(CONFIG_DVB_STV0297) += stv0297.o
diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c
new file mode 100644 (file)
index 0000000..3cbed87
--- /dev/null
@@ -0,0 +1,1504 @@
+/*
+ * Driver for Micronas drx397xD demodulator
+ *
+ * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DEBUG                  /* uncomment if you want debugging output */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/firmware.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "drx397xD.h"
+
+static const char mod_name[] = "drx397xD";
+
+#define MAX_CLOCK_DRIFT                200     /* maximal 200 PPM allowed */
+
+#define F_SET_0D0h     1
+#define F_SET_0D4h     2
+
+typedef enum fw_ix {
+#define _FW_ENTRY(a, b)                b
+#include "drx397xD_fw.h"
+} fw_ix_t;
+
+/* chip specifics */
+struct drx397xD_state {
+       struct i2c_adapter *i2c;
+       struct dvb_frontend frontend;
+       struct drx397xD_config config;
+       fw_ix_t chip_rev;
+       int flags;
+       u32 bandwidth_parm;     /* internal bandwidth conversions */
+       u32 f_osc;              /* w90: actual osc frequency [Hz] */
+};
+
+/*******************************************************************************
+ * Firmware
+ ******************************************************************************/
+
+static const char *blob_name[] = {
+#define _BLOB_ENTRY(a, b)              a
+#include "drx397xD_fw.h"
+};
+
+typedef enum blob_ix {
+#define _BLOB_ENTRY(a, b)              b
+#include "drx397xD_fw.h"
+} blob_ix_t;
+
+static struct {
+       const char *name;
+       const struct firmware *file;
+       rwlock_t lock;
+       int refcnt;
+       const u8 *data[ARRAY_SIZE(blob_name)];
+} fw[] = {
+#define _FW_ENTRY(a, b)                {                       \
+                       .name   = a,                    \
+                       .file   = 0,                    \
+                       .lock   = RW_LOCK_UNLOCKED,     \
+                       .refcnt = 0,                    \
+                       .data   = { }           }
+#include "drx397xD_fw.h"
+};
+
+/* use only with writer lock aquired */
+static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
+{
+       memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
+       if (fw[ix].file)
+               release_firmware(fw[ix].file);
+}
+
+static void drx_release_fw(struct drx397xD_state *s)
+{
+       fw_ix_t ix = s->chip_rev;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       write_lock(&fw[ix].lock);
+       if (fw[ix].refcnt) {
+               fw[ix].refcnt--;
+               if (fw[ix].refcnt == 0)
+                       _drx_release_fw(s, ix);
+       }
+       write_unlock(&fw[ix].lock);
+}
+
+static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
+{
+       const u8 *data;
+       size_t size, len;
+       int i = 0, j, rc = -EINVAL;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if (ix < 0 || ix >= ARRAY_SIZE(fw))
+               return -EINVAL;
+       s->chip_rev = ix;
+
+       write_lock(&fw[ix].lock);
+       if (fw[ix].file) {
+               rc = 0;
+               goto exit_ok;
+       }
+       memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
+
+       if (request_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) {
+               printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
+                      mod_name, fw[ix].name);
+               rc = -ENOENT;
+               goto exit_err;
+       }
+
+       if (!fw[ix].file->data || fw[ix].file->size < 10)
+               goto exit_corrupt;
+
+       data = fw[ix].file->data;
+       size = fw[ix].file->size;
+
+       if (data[i++] != 2)     /* check firmware version */
+               goto exit_corrupt;
+
+       do {
+               switch (data[i++]) {
+               case 0x00:      /* bytecode */
+                       if (i >= size)
+                               break;
+                       i += data[i];
+               case 0x01:      /* reset */
+               case 0x02:      /* sleep */
+                       i++;
+                       break;
+               case 0xfe:      /* name */
+                       len = strnlen(&data[i], size - i);
+                       if (i + len + 1 >= size)
+                               goto exit_corrupt;
+                       if (data[i + len + 1] != 0)
+                               goto exit_corrupt;
+                       for (j = 0; j < ARRAY_SIZE(blob_name); j++) {
+                               if (strcmp(blob_name[j], &data[i]) == 0) {
+                                       fw[ix].data[j] = &data[i + len + 1];
+                                       pr_debug("Loading %s\n", blob_name[j]);
+                               }
+                       }
+                       i += len + 1;
+                       break;
+               case 0xff:      /* file terminator */
+                       if (i == size) {
+                               rc = 0;
+                               goto exit_ok;
+                       }
+               default:
+                       goto exit_corrupt;
+               }
+       } while (i < size);
+      exit_corrupt:
+       printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
+      exit_err:
+       _drx_release_fw(s, ix);
+       fw[ix].refcnt--;
+      exit_ok:
+       fw[ix].refcnt++;
+       write_unlock(&fw[ix].lock);
+       return rc;
+}
+
+/*******************************************************************************
+ * i2c bus IO
+ ******************************************************************************/
+
+static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
+{
+       struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 };
+       const u8 *data;
+       int len, rc = 0, i = 0;
+
+       if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
+               pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__);
+               return -EINVAL;
+       }
+       pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]);
+
+       read_lock(&fw[s->chip_rev].lock);
+       data = fw[s->chip_rev].data[ix];
+       if (!data) {
+               rc = -EINVAL;
+               goto exit_rc;
+       }
+
+       for (;;) {
+               switch (data[i++]) {
+               case 0: /* bytecode */
+                       len = data[i++];
+                       msg.len = len;
+                       msg.buf = (__u8 *) &data[i];
+                       if (i2c_transfer(s->i2c, &msg, 1) != 1) {
+                               rc = -EIO;
+                               goto exit_rc;
+                       }
+                       i += len;
+                       break;
+               case 1: /* reset */
+               case 2: /* sleep */
+                       i++;
+                       break;
+               default:
+                       goto exit_rc;
+               }
+       }
+      exit_rc:
+       read_unlock(&fw[s->chip_rev].lock);
+       return 0;
+}
+
+/* Function is not endian safe, use the RD16 wrapper below */
+static int _read16(struct drx397xD_state *s, u32 i2c_adr)
+{
+       int rc;
+       u8 a[4];
+       u16 v;
+       struct i2c_msg msg[2] = {
+               {
+                .addr = s->config.demod_address,
+                .flags = 0,
+                .buf = a,
+                .len = sizeof(a)
+                }
+               , {
+                  .addr = s->config.demod_address,
+                  .flags = I2C_M_RD,
+                  .buf = (u8 *) & v,
+                  .len = sizeof(v)
+                  }
+       };
+
+       *(u32 *) a = i2c_adr;
+
+       rc = i2c_transfer(s->i2c, msg, 2);
+       if (rc != 2)
+               return -EIO;
+
+       return le16_to_cpu(v);
+}
+
+/* Function is not endian safe, use the WR16.. wrappers below */
+static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
+{
+       u8 a[6];
+       int rc;
+       struct i2c_msg msg = {
+               .addr = s->config.demod_address,
+               .flags = 0,
+               .buf = a,
+               .len = sizeof(a)
+       };
+
+       *(u32 *) a = i2c_adr;
+       *(u16 *) & a[4] = val;
+
+       rc = i2c_transfer(s->i2c, &msg, 1);
+       if (rc != 1)
+               return -EIO;
+       return 0;
+}
+
+#define WR16(ss,adr, val) \
+               _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
+#define WR16_E0(ss,adr, val) \
+               _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
+#define RD16(ss,adr) \
+               _read16(ss, I2C_ADR_C0(adr))
+
+#define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc
+
+/*******************************************************************************
+ * Tuner callback
+ ******************************************************************************/
+
+static int PLL_Set(struct drx397xD_state *s,
+                  struct dvb_frontend_parameters *fep, int *df_tuner)
+{
+       struct dvb_frontend *fe = &s->frontend;
+       u32 f_tuner, f = fep->frequency;
+       int rc;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
+           (f < s->frontend.ops.tuner_ops.info.frequency_min))
+               return -EINVAL;
+
+       *df_tuner = 0;
+       if (!s->frontend.ops.tuner_ops.set_params ||
+           !s->frontend.ops.tuner_ops.get_frequency)
+               return -ENOSYS;
+
+       rc = s->frontend.ops.tuner_ops.set_params(fe, fep);
+       if (rc < 0)
+               return rc;
+
+       rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner);
+       if (rc < 0)
+               return rc;
+
+       *df_tuner = f_tuner - f;
+       pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f,
+                f_tuner);
+
+       return 0;
+}
+
+/*******************************************************************************
+ * Demodulator helper functions
+ ******************************************************************************/
+
+static int SC_WaitForReady(struct drx397xD_state *s)
+{
+       int cnt = 1000;
+       int rc;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       while (cnt--) {
+               rc = RD16(s, 0x820043);
+               if (rc == 0)
+                       return 0;
+       }
+       return -1;
+}
+
+static int SC_SendCommand(struct drx397xD_state *s, int cmd)
+{
+       int rc;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       WR16(s, 0x820043, cmd);
+       SC_WaitForReady(s);
+       rc = RD16(s, 0x820042);
+       if ((rc & 0xffff) == 0xffff)
+               return -1;
+       return 0;
+}
+
+static int HI_Command(struct drx397xD_state *s, u16 cmd)
+{
+       int rc, cnt = 1000;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       rc = WR16(s, 0x420032, cmd);
+       if (rc < 0)
+               return rc;
+
+       do {
+               rc = RD16(s, 0x420032);
+               if (rc == 0) {
+                       rc = RD16(s, 0x420031);
+                       return rc;
+               }
+               if (rc < 0)
+                       return rc;
+       } while (--cnt);
+       return rc;
+}
+
+static int HI_CfgCommand(struct drx397xD_state *s)
+{
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       WR16(s, 0x420033, 0x3973);
+       WR16(s, 0x420034, s->config.w50);       // code 4, log 4
+       WR16(s, 0x420035, s->config.w52);       // code 15,  log 9
+       WR16(s, 0x420036, s->config.demod_address << 1);
+       WR16(s, 0x420037, s->config.w56);       // code (set_i2c ??  initX 1 ), log 1
+//      WR16(s, 0x420033, 0x3973);
+       if ((s->config.w56 & 8) == 0)
+               return HI_Command(s, 3);
+       return WR16(s, 0x420032, 0x3);
+}
+
+static const u8 fastIncrDecLUT_15273[] = {
+       0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14,
+       0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f
+};
+
+static const u8 slowIncrDecLUT_15272[] = {
+       3, 4, 4, 5, 6
+};
+
+static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
+{
+       u16 w06 = agc->w06;
+       u16 w08 = agc->w08;
+       u16 w0A = agc->w0A;
+       u16 w0C = agc->w0C;
+       int quot, rem, i, rc = -EINVAL;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if (agc->w04 > 0x3ff)
+               goto exit_rc;
+
+       if (agc->d00 == 1) {
+               EXIT_RC(RD16(s, 0x0c20010));
+               rc &= ~0x10;
+               EXIT_RC(WR16(s, 0x0c20010, rc));
+               return WR16(s, 0x0c20030, agc->w04 & 0x7ff);
+       }
+
+       if (agc->d00 != 0)
+               goto exit_rc;
+       if (w0A < w08)
+               goto exit_rc;
+       if (w0A > 0x3ff)
+               goto exit_rc;
+       if (w0C > 0x3ff)
+               goto exit_rc;
+       if (w06 > 0x3ff)
+               goto exit_rc;
+
+       EXIT_RC(RD16(s, 0x0c20010));
+       rc |= 0x10;
+       EXIT_RC(WR16(s, 0x0c20010, rc));
+
+       EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff));
+       EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1));
+       EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff));
+
+       quot = w0C / 113;
+       rem = w0C % 113;
+       if (quot <= 8) {
+               quot = 8 - quot;
+       } else {
+               quot = 0;
+               rem += 113;
+       }
+
+       EXIT_RC(WR16(s, 0x0c20024, quot));
+
+       i = fastIncrDecLUT_15273[rem / 8];
+       EXIT_RC(WR16(s, 0x0c2002d, i));
+       EXIT_RC(WR16(s, 0x0c2002e, i));
+
+       i = slowIncrDecLUT_15272[rem / 28];
+       EXIT_RC(WR16(s, 0x0c2002b, i));
+       rc = WR16(s, 0x0c2002c, i);
+      exit_rc:
+       return rc;
+}
+
+static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
+{
+       u16 w04 = agc->w04;
+       u16 w06 = agc->w06;
+       int rc = -1;
+
+       pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06);
+
+       if (w04 > 0x3ff)
+               goto exit_rc;
+
+       switch (agc->d00) {
+       case 1:
+               if (w04 == 0x3ff)
+                       w04 = 0x400;
+
+               EXIT_RC(WR16(s, 0x0c20036, w04));
+               s->config.w9C &= ~2;
+               EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+               EXIT_RC(RD16(s, 0x0c20010));
+               rc &= 0xbfdf;
+               EXIT_RC(WR16(s, 0x0c20010, rc));
+               EXIT_RC(RD16(s, 0x0c20013));
+               rc &= ~2;
+               break;
+       case 0:
+               // loc_8000659
+               s->config.w9C &= ~2;
+               EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+               EXIT_RC(RD16(s, 0x0c20010));
+               rc &= 0xbfdf;
+               rc |= 0x4000;
+               EXIT_RC(WR16(s, 0x0c20010, rc));
+               EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f));
+               EXIT_RC(RD16(s, 0x0c20013));
+               rc &= ~2;
+               break;
+       default:
+               s->config.w9C |= 2;
+               EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+               EXIT_RC(RD16(s, 0x0c20010));
+               rc &= 0xbfdf;
+               EXIT_RC(WR16(s, 0x0c20010, rc));
+
+               EXIT_RC(WR16(s, 0x0c20036, 0));
+
+               EXIT_RC(RD16(s, 0x0c20013));
+               rc |= 2;
+       }
+       rc = WR16(s, 0x0c20013, rc);
+      exit_rc:
+       return rc;
+}
+
+static int GetLockStatus(struct drx397xD_state *s, int *lockstat)
+{
+       int rc;
+
+       *lockstat = 0;
+
+       rc = RD16(s, 0x082004b);
+       if (rc < 0)
+               return rc;
+
+       if (s->config.d60 != 2)
+               return 0;
+
+       if ((rc & 7) == 7)
+               *lockstat |= 1;
+       if ((rc & 3) == 3)
+               *lockstat |= 2;
+       if (rc & 1)
+               *lockstat |= 4;
+       return 0;
+}
+
+static int CorrectSysClockDeviation(struct drx397xD_state *s)
+{
+       int rc = -EINVAL;
+       int lockstat;
+       u32 clk, clk_limit;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if (s->config.d5C == 0) {
+               EXIT_RC(WR16(s, 0x08200e8, 0x010));
+               EXIT_RC(WR16(s, 0x08200e9, 0x113));
+               s->config.d5C = 1;
+               return rc;
+       }
+       if (s->config.d5C != 1)
+               goto exit_rc;
+
+       rc = RD16(s, 0x0820048);
+
+       rc = GetLockStatus(s, &lockstat);
+       if (rc < 0)
+               goto exit_rc;
+       if ((lockstat & 1) == 0)
+               goto exit_rc;
+
+       EXIT_RC(WR16(s, 0x0420033, 0x200));
+       EXIT_RC(WR16(s, 0x0420034, 0xc5));
+       EXIT_RC(WR16(s, 0x0420035, 0x10));
+       EXIT_RC(WR16(s, 0x0420036, 0x1));
+       EXIT_RC(WR16(s, 0x0420037, 0xa));
+       EXIT_RC(HI_Command(s, 6));
+       EXIT_RC(RD16(s, 0x0420040));
+       clk = rc;
+       EXIT_RC(RD16(s, 0x0420041));
+       clk |= rc << 16;
+
+       if (clk <= 0x26ffff)
+               goto exit_rc;
+       if (clk > 0x610000)
+               goto exit_rc;
+
+       if (!s->bandwidth_parm)
+               return -EINVAL;
+
+       /* round & convert to Hz */
+       clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21;
+       clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000;
+
+       if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
+               s->f_osc = clk;
+               pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__,
+                        s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
+       }
+       rc = WR16(s, 0x08200e8, 0);
+      exit_rc:
+       return rc;
+}
+
+static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
+{
+       int rc, si, bp;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       si = s->config.wA0;
+       if (s->config.w98 == 0) {
+               si |= 1;
+               bp = 0;
+       } else {
+               si &= ~1;
+               bp = 0x200;
+       }
+       if (s->config.w9A == 0) {
+               si |= 0x80;
+       } else {
+               si &= ~0x80;
+       }
+
+       EXIT_RC(WR16(s, 0x2150045, 0));
+       EXIT_RC(WR16(s, 0x2150010, si));
+       EXIT_RC(WR16(s, 0x2150011, bp));
+       rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
+      exit_rc:
+       return rc;
+}
+
+static int drx_tune(struct drx397xD_state *s,
+                   struct dvb_frontend_parameters *fep)
+{
+       u16 v22 = 0;
+       u16 v1C = 0;
+       u16 v1A = 0;
+       u16 v18 = 0;
+       u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
+       u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
+
+       int rc, df_tuner;
+       int a, b, c, d;
+       pr_debug("%s %d\n", __FUNCTION__, s->config.d60);
+
+       if (s->config.d60 != 2)
+               goto set_tuner;
+       rc = CorrectSysClockDeviation(s);
+       if (rc < 0)
+               goto set_tuner;
+
+       s->config.d60 = 1;
+       rc = ConfigureMPEGOutput(s, 0);
+       if (rc < 0)
+               goto set_tuner;
+      set_tuner:
+
+       rc = PLL_Set(s, fep, &df_tuner);
+       if (rc < 0) {
+               printk(KERN_ERR "Error in pll_set\n");
+               goto exit_rc;
+       }
+       msleep(200);
+
+       a = rc = RD16(s, 0x2150016);
+       if (rc < 0)
+               goto exit_rc;
+       b = rc = RD16(s, 0x2150010);
+       if (rc < 0)
+               goto exit_rc;
+       c = rc = RD16(s, 0x2150034);
+       if (rc < 0)
+               goto exit_rc;
+       d = rc = RD16(s, 0x2150035);
+       if (rc < 0)
+               goto exit_rc;
+       rc = WR16(s, 0x2150014, c);
+       rc = WR16(s, 0x2150015, d);
+       rc = WR16(s, 0x2150010, 0);
+       rc = WR16(s, 0x2150000, 2);
+       rc = WR16(s, 0x2150036, 0x0fff);
+       rc = WR16(s, 0x2150016, a);
+
+       rc = WR16(s, 0x2150010, 2);
+       rc = WR16(s, 0x2150007, 0);
+       rc = WR16(s, 0x2150000, 1);
+       rc = WR16(s, 0x2110000, 0);
+       rc = WR16(s, 0x0800000, 0);
+       rc = WR16(s, 0x2800000, 0);
+       rc = WR16(s, 0x2110010, 0x664);
+
+       rc = write_fw(s, DRXD_ResetECRAM);
+       rc = WR16(s, 0x2110000, 1);
+
+       rc = write_fw(s, DRXD_InitSC);
+       if (rc < 0)
+               goto exit_rc;
+
+       rc = SetCfgIfAgc(s, &s->config.ifagc);
+       if (rc < 0)
+               goto exit_rc;
+
+       rc = SetCfgRfAgc(s, &s->config.rfagc);
+       if (rc < 0)
+               goto exit_rc;
+
+       if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K)
+               v22 = 1;
+       switch (fep->u.ofdm.transmission_mode) {
+       case TRANSMISSION_MODE_8K:
+               edi = 1;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+
+               rc = WR16(s, 0x2010010, 0);
+               if (rc < 0)
+                       break;
+               v1C = 0x63;
+               v1A = 0x53;
+               v18 = 0x43;
+               break;
+       default:
+               edi = 0;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+
+               rc = WR16(s, 0x2010010, 1);
+               if (rc < 0)
+                       break;
+
+               v1C = 0x61;
+               v1A = 0x47;
+               v18 = 0x41;
+       }
+
+       switch (fep->u.ofdm.guard_interval) {
+       case GUARD_INTERVAL_1_4:
+               edi |= 0x0c;
+               break;
+       case GUARD_INTERVAL_1_8:
+               edi |= 0x08;
+               break;
+       case GUARD_INTERVAL_1_16:
+               edi |= 0x04;
+               break;
+       case GUARD_INTERVAL_1_32:
+               break;
+       default:
+               v22 |= 2;
+       }
+
+       ebx = 0;
+       ebp = 0;
+       v20 = 0;
+       v1E = 0;
+       v16 = 0;
+       v14 = 0;
+       v12 = 0;
+       v10 = 0;
+       v0E = 0;
+
+       switch (fep->u.ofdm.hierarchy_information) {
+       case HIERARCHY_1:
+               edi |= 0x40;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x1c10047, 1);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010012, 1);
+               if (rc < 0)
+                       goto exit_rc;
+               ebx = 0x19f;
+               ebp = 0x1fb;
+               v20 = 0x0c0;
+               v1E = 0x195;
+               v16 = 0x1d6;
+               v14 = 0x1ef;
+               v12 = 4;
+               v10 = 5;
+               v0E = 5;
+               break;
+       case HIERARCHY_2:
+               edi |= 0x80;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x1c10047, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010012, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               ebx = 0x08f;
+               ebp = 0x12f;
+               v20 = 0x0c0;
+               v1E = 0x11e;
+               v16 = 0x1d6;
+               v14 = 0x15e;
+               v12 = 4;
+               v10 = 5;
+               v0E = 5;
+               break;
+       case HIERARCHY_4:
+               edi |= 0xc0;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x1c10047, 3);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010012, 3);
+               if (rc < 0)
+                       goto exit_rc;
+               ebx = 0x14d;
+               ebp = 0x197;
+               v20 = 0x0c0;
+               v1E = 0x1ce;
+               v16 = 0x1d6;
+               v14 = 0x11a;
+               v12 = 4;
+               v10 = 6;
+               v0E = 5;
+               break;
+       default:
+               v22 |= 8;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x1c10047, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010012, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               //              QPSK    QAM16   QAM64
+               ebx = 0x19f;    //                 62
+               ebp = 0x1fb;    //                 15
+               v20 = 0x16a;    //  62
+               v1E = 0x195;    //         62
+               v16 = 0x1bb;    //  15
+               v14 = 0x1ef;    //         15
+               v12 = 5;        //  16
+               v10 = 5;        //         16
+               v0E = 5;        //                 16
+       }
+
+       switch (fep->u.ofdm.constellation) {
+       default:
+               v22 |= 4;
+       case QPSK:
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+
+               rc = WR16(s, 0x1c10046, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010011, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001a, 0x10);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001b, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001c, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10062, v20);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c1002a, v1C);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10015, v16);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10016, v12);
+               if (rc < 0)
+                       goto exit_rc;
+               break;
+       case QAM_16:
+               edi |= 0x10;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+
+               rc = WR16(s, 0x1c10046, 1);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010011, 1);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001a, 0x10);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001b, 4);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001c, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10062, v1E);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c1002a, v1A);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10015, v14);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10016, v10);
+               if (rc < 0)
+                       goto exit_rc;
+               break;
+       case QAM_64:
+               edi |= 0x20;
+               rc = WR16(s, 0x1c10046, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010011, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001a, 0x20);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001b, 8);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001c, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10062, ebx);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c1002a, v18);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10015, ebp);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10016, v0E);
+               if (rc < 0)
+                       goto exit_rc;
+               break;
+       }
+
+       if (s->config.s20d24 == 1) {
+               rc = WR16(s, 0x2010013, 0);
+       } else {
+               rc = WR16(s, 0x2010013, 1);
+               edi |= 0x1000;
+       }
+
+       switch (fep->u.ofdm.code_rate_HP) {
+       default:
+               v22 |= 0x10;
+       case FEC_1_2:
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 0);
+               break;
+       case FEC_2_3:
+               edi |= 0x200;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 1);
+               break;
+       case FEC_3_4:
+               edi |= 0x400;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 2);
+               break;
+       case FEC_5_6:           /* 5 */
+               edi |= 0x600;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 3);
+               break;
+       case FEC_7_8:           /* 7 */
+               edi |= 0x800;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 4);
+               break;
+       };
+       if (rc < 0)
+               goto exit_rc;
+
+       switch (fep->u.ofdm.bandwidth) {
+       default:
+               rc = -EINVAL;
+               goto exit_rc;
+       case BANDWIDTH_8_MHZ:   /* 0 */
+       case BANDWIDTH_AUTO:
+               rc = WR16(s, 0x0c2003f, 0x32);
+               s->bandwidth_parm = ebx = 0x8b8249;     // 9142857
+               edx = 0;
+               break;
+       case BANDWIDTH_7_MHZ:
+               rc = WR16(s, 0x0c2003f, 0x3b);
+               s->bandwidth_parm = ebx = 0x7a1200;     // 8000000
+               edx = 0x4807;
+               break;
+       case BANDWIDTH_6_MHZ:
+               rc = WR16(s, 0x0c2003f, 0x47);
+               s->bandwidth_parm = ebx = 0x68a1b6;     // 6857142
+               edx = 0x0f07;
+               break;
+       };
+
+       if (rc < 0)
+               goto exit_rc;
+
+       rc = WR16(s, 0x08200ec, edx);
+       if (rc < 0)
+               goto exit_rc;
+
+       rc = RD16(s, 0x0820050);
+       if (rc < 0)
+               goto exit_rc;
+       rc = WR16(s, 0x0820050, rc);
+
+       {
+               /* Configure bandwidth specific factor */
+               ebx = div64_u64(((u64) (s->f_osc) << 21) + (ebx >> 1),
+                                    (u64)ebx) - 0x800000;
+               EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff));
+               EXIT_RC(WR16(s, 0x0c50011, ebx >> 16));
+
+               /* drx397xD oscillator calibration */
+               ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) +
+                                    (s->f_osc >> 1), (u64)s->f_osc);
+       }
+       ebx &= 0xfffffff;
+       if (fep->inversion == INVERSION_ON)
+               ebx = 0x10000000 - ebx;
+
+       EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff));
+       EXIT_RC(WR16(s, 0x0c30011, ebx >> 16));
+
+       EXIT_RC(WR16(s, 0x0800000, 1));
+       EXIT_RC(RD16(s, 0x0800000));
+
+
+       EXIT_RC(SC_WaitForReady(s));
+       EXIT_RC(WR16(s, 0x0820042, 0));
+       EXIT_RC(WR16(s, 0x0820041, v22));
+       EXIT_RC(WR16(s, 0x0820040, edi));
+       EXIT_RC(SC_SendCommand(s, 3));
+
+       rc = RD16(s, 0x0800000);
+
+       SC_WaitForReady(s);
+       WR16(s, 0x0820042, 0);
+       WR16(s, 0x0820041, 1);
+       WR16(s, 0x0820040, 1);
+       SC_SendCommand(s, 1);
+
+//      rc = WR16(s, 0x2150000, 1);
+//      if (rc < 0) goto exit_rc;
+
+       rc = WR16(s, 0x2150000, 2);
+       rc = WR16(s, 0x2150016, a);
+       rc = WR16(s, 0x2150010, 4);
+       rc = WR16(s, 0x2150036, 0);
+       rc = WR16(s, 0x2150000, 1);
+       s->config.d60 = 2;
+      exit_rc:
+       return rc;
+}
+
+/*******************************************************************************
+ * DVB interface
+ ******************************************************************************/
+
+static int drx397x_init(struct dvb_frontend *fe)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+       int rc;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       s->config.rfagc.d00 = 2;        /* 0x7c */
+       s->config.rfagc.w04 = 0;
+       s->config.rfagc.w06 = 0x3ff;
+
+       s->config.ifagc.d00 = 0;        /* 0x68 */
+       s->config.ifagc.w04 = 0;
+       s->config.ifagc.w06 = 140;
+       s->config.ifagc.w08 = 0;
+       s->config.ifagc.w0A = 0x3ff;
+       s->config.ifagc.w0C = 0x388;
+
+       /* for signal strenght calculations */
+       s->config.ss76 = 820;
+       s->config.ss78 = 2200;
+       s->config.ss7A = 150;
+
+       /* HI_CfgCommand */
+       s->config.w50 = 4;
+       s->config.w52 = 9;      // 0xf;
+
+       s->config.f_if = 42800000;      /* d14: intermediate frequency [Hz]     */
+       s->config.f_osc = 48000;        /* s66 : oscillator frequency [kHz]     */
+       s->config.w92 = 12000;  // 20000;
+
+       s->config.w9C = 0x000e;
+       s->config.w9E = 0x0000;
+
+       /* ConfigureMPEGOutput params */
+       s->config.wA0 = 4;
+       s->config.w98 = 1;      // 0;
+       s->config.w9A = 1;
+
+       /* get chip revision */
+       rc = RD16(s, 0x2410019);
+       if (rc < 0)
+               return -ENODEV;
+
+       if (rc == 0) {
+               printk(KERN_INFO "%s: chip revision A2\n", mod_name);
+               rc = drx_load_fw(s, DRXD_FW_A2);
+       } else {
+
+               rc = (rc >> 12) - 3;
+               switch (rc) {
+               case 1:
+                       s->flags |= F_SET_0D4h;
+               case 0:
+               case 4:
+                       s->flags |= F_SET_0D0h;
+                       break;
+               case 2:
+               case 5:
+                       break;
+               case 3:
+                       s->flags |= F_SET_0D4h;
+                       break;
+               default:
+                       return -ENODEV;
+               };
+               printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc);
+               rc = drx_load_fw(s, DRXD_FW_B1);
+       }
+       if (rc < 0)
+               goto error;
+
+       rc = WR16(s, 0x0420033, 0x3973);
+       if (rc < 0)
+               goto error;
+
+       rc = HI_Command(s, 2);
+
+       msleep(1);
+
+       if (s->chip_rev == DRXD_FW_A2) {
+               rc = WR16(s, 0x043012d, 0x47F);
+               if (rc < 0)
+                       goto error;
+       }
+       rc = WR16_E0(s, 0x0400000, 0);
+       if (rc < 0)
+               goto error;
+
+       if (s->config.w92 > 20000 || s->config.w92 % 4000) {
+               printk(KERN_ERR "%s: invalid osc frequency\n", mod_name);
+               rc = -1;
+               goto error;
+       }
+
+       rc = WR16(s, 0x2410010, 1);
+       if (rc < 0)
+               goto error;
+       rc = WR16(s, 0x2410011, 0x15);
+       if (rc < 0)
+               goto error;
+       rc = WR16(s, 0x2410012, s->config.w92 / 4000);
+       if (rc < 0)
+               goto error;
+#ifdef ORIG_FW
+       rc = WR16(s, 0x2410015, 2);
+       if (rc < 0)
+               goto error;
+#endif
+       rc = WR16(s, 0x2410017, 0x3973);
+       if (rc < 0)
+               goto error;
+
+       s->f_osc = s->config.f_osc * 1000;      /* initial estimator */
+
+       s->config.w56 = 1;
+
+       rc = HI_CfgCommand(s);
+       if (rc < 0)
+               goto error;
+
+       rc = write_fw(s, DRXD_InitAtomicRead);
+       if (rc < 0)
+               goto error;
+
+       if (s->chip_rev == DRXD_FW_A2) {
+               rc = WR16(s, 0x2150013, 0);
+               if (rc < 0)
+                       goto error;
+       }
+
+       rc = WR16_E0(s, 0x0400002, 0);
+       if (rc < 0)
+               goto error;
+       rc = WR16(s, 0x0400002, 0);
+       if (rc < 0)
+               goto error;
+
+       if (s->chip_rev == DRXD_FW_A2) {
+               rc = write_fw(s, DRXD_ResetCEFR);
+               if (rc < 0)
+                       goto error;
+       }
+       rc = write_fw(s, DRXD_microcode);
+       if (rc < 0)
+               goto error;
+
+       s->config.w9C = 0x0e;
+       if (s->flags & F_SET_0D0h) {
+               s->config.w9C = 0;
+               rc = RD16(s, 0x0c20010);
+               if (rc < 0)
+                       goto write_DRXD_InitFE_1;
+
+               rc &= ~0x1000;
+               rc = WR16(s, 0x0c20010, rc);
+               if (rc < 0)
+                       goto write_DRXD_InitFE_1;
+
+               rc = RD16(s, 0x0c20011);
+               if (rc < 0)
+                       goto write_DRXD_InitFE_1;
+
+               rc &= ~0x8;
+               rc = WR16(s, 0x0c20011, rc);
+               if (rc < 0)
+                       goto write_DRXD_InitFE_1;
+
+               rc = WR16(s, 0x0c20012, 1);
+       }
+
+      write_DRXD_InitFE_1:
+
+       rc = write_fw(s, DRXD_InitFE_1);
+       if (rc < 0)
+               goto error;
+
+       rc = 1;
+       if (s->chip_rev == DRXD_FW_B1) {
+               if (s->flags & F_SET_0D0h)
+                       rc = 0;
+       } else {
+               if (s->flags & F_SET_0D0h)
+                       rc = 4;
+       }
+
+       rc = WR16(s, 0x0C20012, rc);
+       if (rc < 0)
+               goto error;
+
+       rc = WR16(s, 0x0C20013, s->config.w9E);
+       if (rc < 0)
+               goto error;
+       rc = WR16(s, 0x0C20015, s->config.w9C);
+       if (rc < 0)
+               goto error;
+
+       rc = write_fw(s, DRXD_InitFE_2);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitFT);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitCP);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitCE);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitEQ);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitEC);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitSC);
+       if (rc < 0)
+               goto error;
+
+       rc = SetCfgIfAgc(s, &s->config.ifagc);
+       if (rc < 0)
+               goto error;
+
+       rc = SetCfgRfAgc(s, &s->config.rfagc);
+       if (rc < 0)
+               goto error;
+
+       rc = ConfigureMPEGOutput(s, 1);
+       rc = WR16(s, 0x08201fe, 0x0017);
+       rc = WR16(s, 0x08201ff, 0x0101);
+
+       s->config.d5C = 0;
+       s->config.d60 = 1;
+       s->config.d48 = 1;
+      error:
+       return rc;
+}
+
+static int drx397x_get_frontend(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *params)
+{
+       return 0;
+}
+
+static int drx397x_set_frontend(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *params)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+
+       s->config.s20d24 = 1;   // 0;
+       return drx_tune(s, params);
+}
+
+static int drx397x_get_tune_settings(struct dvb_frontend *fe,
+                                    struct dvb_frontend_tune_settings
+                                    *fe_tune_settings)
+{
+       fe_tune_settings->min_delay_ms = 10000;
+       fe_tune_settings->step_size = 0;
+       fe_tune_settings->max_drift = 0;
+       return 0;
+}
+
+static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+       int lockstat;
+
+       GetLockStatus(s, &lockstat);
+       /* TODO */
+//      if (lockstat & 1)
+//      CorrectSysClockDeviation(s);
+
+       *status = 0;
+       if (lockstat & 2) {
+               CorrectSysClockDeviation(s);
+               ConfigureMPEGOutput(s, 1);
+               *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
+       }
+       if (lockstat & 4) {
+               *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+       }
+
+       return 0;
+}
+
+static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber)
+{
+       *ber = 0;
+       return 0;
+}
+
+static int drx397x_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+       *snr = 0;
+       return 0;
+}
+
+static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+       int rc;
+
+       if (s->config.ifagc.d00 == 2) {
+               *strength = 0xffff;
+               return 0;
+       }
+       rc = RD16(s, 0x0c20035);
+       if (rc < 0) {
+               *strength = 0;
+               return 0;
+       }
+       rc &= 0x3ff;
+       /* Signal strength is calculated using the following formula:
+        *
+        * a = 2200 * 150 / (2200 + 150);
+        * a = a * 3300 /  (a + 820);
+        * b = 2200 * 3300 / (2200 + 820);
+        * c = (((b-a) * rc) >> 10  + a) << 4;
+        * strength = ~c & 0xffff;
+        *
+        * The following does the same but with less rounding errors:
+        */
+       *strength = ~(7720 + (rc * 30744 >> 10));
+       return 0;
+}
+
+static int drx397x_read_ucblocks(struct dvb_frontend *fe,
+                                unsigned int *ucblocks)
+{
+       *ucblocks = 0;
+       return 0;
+}
+
+static int drx397x_sleep(struct dvb_frontend *fe)
+{
+       return 0;
+}
+
+static void drx397x_release(struct dvb_frontend *fe)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+       printk(KERN_INFO "%s: release demodulator\n", mod_name);
+       if (s) {
+               drx_release_fw(s);
+               kfree(s);
+       }
+
+}
+
+static struct dvb_frontend_ops drx397x_ops = {
+
+       .info = {
+                .name                  = "Micronas DRX397xD DVB-T Frontend",
+                .type                  = FE_OFDM,
+                .frequency_min         = 47125000,
+                .frequency_max         = 855250000,
+                .frequency_stepsize    = 166667,
+                .frequency_tolerance   = 0,
+                .caps =                                        /* 0x0C01B2EAE */
+                        FE_CAN_FEC_1_2                 |       // = 0x2,
+                        FE_CAN_FEC_2_3                 |       // = 0x4,
+                        FE_CAN_FEC_3_4                 |       // = 0x8,
+                        FE_CAN_FEC_5_6                 |       // = 0x20,
+                        FE_CAN_FEC_7_8                 |       // = 0x80,
+                        FE_CAN_FEC_AUTO                |       // = 0x200,
+                        FE_CAN_QPSK                    |       // = 0x400,
+                        FE_CAN_QAM_16                  |       // = 0x800,
+                        FE_CAN_QAM_64                  |       // = 0x2000,
+                        FE_CAN_QAM_AUTO                |       // = 0x10000,
+                        FE_CAN_TRANSMISSION_MODE_AUTO  |       // = 0x20000,
+                        FE_CAN_GUARD_INTERVAL_AUTO     |       // = 0x80000,
+                        FE_CAN_HIERARCHY_AUTO          |       // = 0x100000,
+                        FE_CAN_RECOVER                 |       // = 0x40000000,
+                        FE_CAN_MUTE_TS                         // = 0x80000000
+        },
+
+       .release = drx397x_release,
+       .init = drx397x_init,
+       .sleep = drx397x_sleep,
+
+       .set_frontend = drx397x_set_frontend,
+       .get_tune_settings = drx397x_get_tune_settings,
+       .get_frontend = drx397x_get_frontend,
+
+       .read_status = drx397x_read_status,
+       .read_snr = drx397x_read_snr,
+       .read_signal_strength = drx397x_read_signal_strength,
+       .read_ber = drx397x_read_ber,
+       .read_ucblocks = drx397x_read_ucblocks,
+};
+
+struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,
+                                    struct i2c_adapter *i2c)
+{
+       struct drx397xD_state *s = NULL;
+
+       /* allocate memory for the internal state */
+       s = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
+       if (s == NULL)
+               goto error;
+
+       /* setup the state */
+       s->i2c = i2c;
+       memcpy(&s->config, config, sizeof(struct drx397xD_config));
+
+       /* check if the demod is there */
+       if (RD16(s, 0x2410019) < 0)
+               goto error;
+
+       /* create dvb_frontend */
+       memcpy(&s->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops));
+       s->frontend.demodulator_priv = s;
+
+       return &s->frontend;
+      error:
+       kfree(s);
+       return NULL;
+}
+
+MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");
+MODULE_AUTHOR("Henk Vergonet");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(drx397xD_attach);
diff --git a/drivers/media/dvb/frontends/drx397xD.h b/drivers/media/dvb/frontends/drx397xD.h
new file mode 100644 (file)
index 0000000..ddc7a07
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ *  Driver for Micronas DVB-T drx397xD demodulator
+ *
+ *  Copyright (C) 2007 Henk vergonet <Henk.Vergonet@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef _DRX397XD_H_INCLUDED
+#define _DRX397XD_H_INCLUDED
+
+#include <linux/dvb/frontend.h>
+
+#define DRX_F_STEPSIZE 166667
+#define DRX_F_OFFSET   36000000
+
+#define I2C_ADR_C0(x) \
+(      (u32)cpu_to_le32( \
+               (u32)( \
+                       (((u32)(x) & (u32)0x000000ffUL)      ) | \
+                       (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
+                       (((u32)(x) & (u32)0x0fff0000UL) >>  8) | \
+                        (           (u32)0x00c00000UL)          \
+                     )) \
+)
+
+#define I2C_ADR_E0(x) \
+(      (u32)cpu_to_le32( \
+               (u32)( \
+                       (((u32)(x) & (u32)0x000000ffUL)      ) | \
+                       (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
+                       (((u32)(x) & (u32)0x0fff0000UL) >>  8) | \
+                        (           (u32)0x00e00000UL)          \
+                     )) \
+)
+
+struct drx397xD_CfgRfAgc       /* 0x7c */
+{
+       int d00;        /* 2 */
+       u16 w04;
+       u16 w06;
+};
+
+struct drx397xD_CfgIfAgc       /* 0x68 */
+{
+       int d00;        /* 0 */
+       u16 w04;        /* 0 */
+       u16 w06;
+       u16 w08;
+       u16 w0A;
+       u16 w0C;
+};
+
+struct drx397xD_s20 {
+       int d04;
+       u32 d18;
+       u32 d1C;
+       u32 d20;
+       u32 d14;
+       u32 d24;
+       u32 d0C;
+       u32 d08;
+};
+
+struct drx397xD_config
+{
+       /* demodulator's I2C address */
+       u8      demod_address;          /* 0x0f */
+
+       struct drx397xD_CfgIfAgc  ifagc;  /* 0x68 */
+       struct drx397xD_CfgRfAgc  rfagc;  /* 0x7c */
+       u32     s20d24;
+
+       /* HI_CfgCommand parameters */
+       u16     w50, w52, /* w54, */ w56;
+
+       int     d5C;
+       int     d60;
+       int     d48;
+       int     d28;
+
+       u32     f_if;   /* d14: intermediate frequency [Hz]             */
+                       /*      36000000 on Cinergy 2400i DT            */
+                       /*      42800000 on Pinnacle Hybrid PRO 330e    */
+
+       u16     f_osc;  /* s66: 48000 oscillator frequency [kHz]        */
+
+       u16     w92;    /* 20000 */
+
+       u16     wA0;
+       u16     w98;
+       u16     w9A;
+
+       u16     w9C;    /* 0xe0 */
+       u16     w9E;    /* 0x00 */
+
+       /* used for signal strength calculations in
+          drx397x_read_signal_strength
+       */
+       u16     ss78;   // 2200
+       u16     ss7A;   // 150
+       u16     ss76;   // 820
+};
+
+#if defined(CONFIG_DVB_DRX397XD) || (defined(CONFIG_DVB_DRX397XD_MODULE) && defined(MODULE))
+extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
+                                          struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
+                                          struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_DRX397XD */
+
+#endif /* _DRX397XD_H_INCLUDED */
diff --git a/drivers/media/dvb/frontends/drx397xD_fw.h b/drivers/media/dvb/frontends/drx397xD_fw.h
new file mode 100644 (file)
index 0000000..01de02a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Firmware definitions for Micronas drx397xD
+ *
+ * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef _FW_ENTRY
+       _FW_ENTRY("drx397xD.A2.fw",     DRXD_FW_A2 = 0          ),
+       _FW_ENTRY("drx397xD.B1.fw",     DRXD_FW_B1              ),
+#undef _FW_ENTRY
+#endif /* _FW_ENTRY */
+
+#ifdef _BLOB_ENTRY
+       _BLOB_ENTRY("InitAtomicRead",   DRXD_InitAtomicRead = 0 ),
+       _BLOB_ENTRY("InitCE",           DRXD_InitCE             ),
+       _BLOB_ENTRY("InitCP",           DRXD_InitCP             ),
+       _BLOB_ENTRY("InitEC",           DRXD_InitEC             ),
+       _BLOB_ENTRY("InitEQ",           DRXD_InitEQ             ),
+       _BLOB_ENTRY("InitFE_1",         DRXD_InitFE_1           ),
+       _BLOB_ENTRY("InitFE_2",         DRXD_InitFE_2           ),
+       _BLOB_ENTRY("InitFT",           DRXD_InitFT             ),
+       _BLOB_ENTRY("InitSC",           DRXD_InitSC             ),
+       _BLOB_ENTRY("ResetCEFR",        DRXD_ResetCEFR          ),
+       _BLOB_ENTRY("ResetECRAM",       DRXD_ResetECRAM         ),
+       _BLOB_ENTRY("microcode",        DRXD_microcode          ),
+#undef _BLOB_ENTRY
+#endif /* _BLOB_ENTRY */
diff --git a/drivers/media/dvb/frontends/z0194a.h b/drivers/media/dvb/frontends/z0194a.h
new file mode 100644 (file)
index 0000000..d2876d2
--- /dev/null
@@ -0,0 +1,97 @@
+/* z0194a.h Sharp z0194a tuner support
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+*      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.
+*
+* see Documentation/dvb/README.dvb-usb for more information
+*/
+
+#ifndef Z0194A
+#define Z0194A
+
+static int sharp_z0194a__set_symbol_rate(struct dvb_frontend *fe,
+                                        u32 srate, u32 ratio)
+{
+       u8 aclk = 0;
+       u8 bclk = 0;
+
+       if (srate < 1500000) {
+               aclk = 0xb7; bclk = 0x47; }
+       else if (srate < 3000000) {
+               aclk = 0xb7; bclk = 0x4b; }
+       else if (srate < 7000000) {
+               aclk = 0xb7; bclk = 0x4f; }
+       else if (srate < 14000000) {
+               aclk = 0xb7; bclk = 0x53; }
+       else if (srate < 30000000) {
+               aclk = 0xb6; bclk = 0x53; }
+       else if (srate < 45000000) {
+               aclk = 0xb4; bclk = 0x51; }
+
+       stv0299_writereg(fe, 0x13, aclk);
+       stv0299_writereg(fe, 0x14, bclk);
+       stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+       stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+       stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
+
+       return 0;
+}
+
+static u8 sharp_z0194a__inittab[] = {
+       0x01, 0x15,
+       0x02, 0x00,
+       0x03, 0x00,
+       0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+       0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
+       0x06, 0x40,   /* DAC not used, set to high impendance mode */
+       0x07, 0x00,   /* DAC LSB */
+       0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
+       0x09, 0x00,   /* FIFO */
+       0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+       0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
+       0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
+       0x10, 0x3f,   /* AGC2  0x3d */
+       0x11, 0x84,
+       0x12, 0xb9,
+       0x15, 0xc9,   /* lock detector threshold */
+       0x16, 0x00,
+       0x17, 0x00,
+       0x18, 0x00,
+       0x19, 0x00,
+       0x1a, 0x00,
+       0x1f, 0x50,
+       0x20, 0x00,
+       0x21, 0x00,
+       0x22, 0x00,
+       0x23, 0x00,
+       0x28, 0x00,  /* out imp: normal  out type: parallel FEC mode:0 */
+       0x29, 0x1e,  /* 1/2 threshold */
+       0x2a, 0x14,  /* 2/3 threshold */
+       0x2b, 0x0f,  /* 3/4 threshold */
+       0x2c, 0x09,  /* 5/6 threshold */
+       0x2d, 0x05,  /* 7/8 threshold */
+       0x2e, 0x01,
+       0x31, 0x1f,  /* test all FECs */
+       0x32, 0x19,  /* viterbi and synchro search */
+       0x33, 0xfc,  /* rs control */
+       0x34, 0x93,  /* error control */
+       0x0f, 0x52,
+       0xff, 0xff
+};
+
+static struct stv0299_config sharp_z0194a_config = {
+       .demod_address = 0x68,
+       .inittab = sharp_z0194a__inittab,
+       .mclk = 88000000UL,
+       .invert = 1,
+       .skip_reinit = 0,
+       .lock_output = STV0299_LOCKOUTPUT_1,
+       .volt13_op0_op1 = STV0299_VOLT13_OP1,
+       .min_delay_ms = 100,
+       .set_symbol_rate = sharp_z0194a__set_symbol_rate,
+};
+
+#endif
index 1360403b88b6953d778e300717e5e8c646bf2da0..a9653c63f4db8350b5fb66c4e184b6d44a16421f 100644 (file)
@@ -242,7 +242,7 @@ static int __devinit pluto_dma_map(struct pluto *pluto)
        pluto->dma_addr = pci_map_single(pluto->pdev, pluto->dma_buf,
                        TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
 
-       return pci_dma_mapping_error(pluto->dma_addr);
+       return pci_dma_mapping_error(pluto->pdev, pluto->dma_addr);
 }
 
 static void pluto_dma_unmap(struct pluto *pluto)
index b4b8ed795c95438cf34535ff18bb13ebd5f2fcd7..c5f45fed69dc41290a2300a5a90dfea701f87cdb 100644 (file)
@@ -110,12 +110,12 @@ struct smscore_registry_entry_t {
        enum sms_device_type_st type;
 };
 
-struct list_head g_smscore_notifyees;
-struct list_head g_smscore_devices;
-struct mutex g_smscore_deviceslock;
+static struct list_head g_smscore_notifyees;
+static struct list_head g_smscore_devices;
+static struct mutex g_smscore_deviceslock;
 
-struct list_head g_smscore_registry;
-struct mutex g_smscore_registrylock;
+static struct list_head g_smscore_registry;
+static struct mutex g_smscore_registrylock;
 
 static int default_mode = 4;
 
@@ -1187,7 +1187,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 }
 
 
-int smscore_module_init(void)
+static int __init smscore_module_init(void)
 {
        int rc = 0;
 
@@ -1209,7 +1209,7 @@ int smscore_module_init(void)
        return rc;
 }
 
-void smscore_module_exit(void)
+static void __exit smscore_module_exit(void)
 {
 
        kmutex_lock(&g_smscore_deviceslock);
index 6f9c1856386742c895727020547de72960e72f64..229274a14110515a8c00f020162c0310d1ab4d53 100644 (file)
@@ -27,8 +27,8 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-struct list_head g_smsdvb_clients;
-struct mutex g_smsdvb_clientslock;
+static struct list_head g_smsdvb_clients;
+static struct mutex g_smsdvb_clientslock;
 
 static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
 {
index 87c973ac668bde2aad93d1493a9b870175d4999c..41b5a988b619fb8016485a7e50e512c1a66b9356 100644 (file)
@@ -5,8 +5,6 @@ config TTPCI_EEPROM
 config DVB_AV7110
        tristate "AV7110 cards"
        depends on DVB_CORE && PCI && I2C
-       depends on HOTPLUG
-       select FW_LOADER if !DVB_AV7110_FIRMWARE
        select TTPCI_EEPROM
        select VIDEO_SAA7146_VV
        depends on VIDEO_DEV    # dependencies of VIDEO_SAA7146_VV
@@ -127,14 +125,12 @@ config DVB_BUDGET_AV
        depends on DVB_BUDGET_CORE && I2C
        select VIDEO_SAA7146_VV
        depends on VIDEO_DEV    # dependencies of VIDEO_SAA7146_VV
-       depends on HOTPLUG      # dependency of FW_LOADER
        select DVB_PLL if !DVB_FE_CUSTOMISE
        select DVB_STV0299 if !DVB_FE_CUSTOMISE
        select DVB_TDA1004X if !DVB_FE_CUSTOMISE
        select DVB_TDA10021 if !DVB_FE_CUSTOMISE
        select DVB_TDA10023 if !DVB_FE_CUSTOMISE
        select DVB_TUA6100 if !DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
index a23cc0aa17d30519c99ddb737989777d394145dc..d5f48a3102bdf5183d939d6be3002325fa1c8123 100644 (file)
@@ -1,8 +1,6 @@
 config DVB_TTUSB_DEC
        tristate "Technotrend/Hauppauge USB DEC devices"
        depends on DVB_CORE && USB && INPUT
-       depends on HOTPLUG      # due to FW_LOADER
-       select FW_LOADER
        select CRC32
        help
          Support for external USB adapters designed by Technotrend and
index 4e3f83e4e48f34f4f2878df5823c00f3f0729bc7..1ed88f3abe61084cc661a188afd829e2f54e0d79 100644 (file)
@@ -85,6 +85,7 @@
 #include <linux/input.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/usb.h>
 
 /*
@@ -444,14 +445,7 @@ static const struct file_operations usb_dsbr100_fops = {
        .llseek         = no_llseek,
 };
 
-/* V4L2 interface */
-static struct video_device dsbr100_videodev_template =
-{
-       .owner          = THIS_MODULE,
-       .name           = "D-Link DSB-R 100",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &usb_dsbr100_fops,
-       .release        = video_device_release,
+static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -466,6 +460,14 @@ static struct video_device dsbr100_videodev_template =
        .vidioc_s_input     = vidioc_s_input,
 };
 
+/* V4L2 interface */
+static struct video_device dsbr100_videodev_template = {
+       .name           = "D-Link DSB-R 100",
+       .fops           = &usb_dsbr100_fops,
+       .ioctl_ops      = &usb_dsbr100_ioctl_ops,
+       .release        = video_device_release,
+};
+
 /* check if the device is present and register with v4l and
 usb if it is */
 static int usb_dsbr100_probe(struct usb_interface *intf,
index 09fe6f1cdf14b124d8b10fcc64e91bc91625649e..7fd7ee2d32c11dd2214faf73c1c724be2ddfbabd 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include "oss/aci.h"
 #include "miropcm20-rds-core.h"
 
@@ -228,9 +229,7 @@ static const struct file_operations pcm20_fops = {
 };
 
 static struct video_device pcm20_radio = {
-       .owner          = THIS_MODULE,
        .name           = "Miro PCM 20 radio",
-       .type           = VID_TYPE_TUNER,
        .fops           = &pcm20_fops,
        .priv           = &pcm20_unit
 };
index 1ec18ed1a73365dbfad685238648f63faeba4177..eba9209b30240a3212d707da8bb3e79f54d67f9f 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>     /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
@@ -388,12 +389,7 @@ static const struct file_operations rtrack_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device rtrack_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "RadioTrack radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &rtrack_fops,
+static const struct v4l2_ioctl_ops rtrack_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -408,6 +404,12 @@ static struct video_device rtrack_radio=
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device rtrack_radio = {
+       .name           = "RadioTrack radio",
+       .fops           = &rtrack_fops,
+       .ioctl_ops      = &rtrack_ioctl_ops,
+};
+
 static int __init rtrack_init(void)
 {
        if(io==-1)
index 46cdb549eac736eb1321777e9616e2f7fe5070d8..3fe5504428c5b0099fa7aeba0a99bf91c509a4b8 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
@@ -352,12 +353,7 @@ static const struct file_operations aztech_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device aztech_radio=
-{
-       .owner              = THIS_MODULE,
-       .name               = "Aztech radio",
-       .type               = VID_TYPE_TUNER,
-       .fops               = &aztech_fops,
+static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -372,6 +368,12 @@ static struct video_device aztech_radio=
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device aztech_radio = {
+       .name               = "Aztech radio",
+       .fops               = &aztech_fops,
+       .ioctl_ops          = &aztech_ioctl_ops,
+};
+
 module_param_named(debug,aztech_radio.debug, int, 0644);
 MODULE_PARM_DESC(debug,"activates debug info");
 
index b14db53ea456514153ee49ae0a61759c3d522847..6166e726ed7203908adcd908be14199452c744aa 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* V4L2 API defs                */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/param.h>
 #include <linux/pnp.h>
 
@@ -569,12 +570,7 @@ static const struct file_operations cadet_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device cadet_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "Cadet radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &cadet_fops,
+static const struct v4l2_ioctl_ops cadet_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -589,6 +585,12 @@ static struct video_device cadet_radio=
        .vidioc_s_input     = vidioc_s_input,
 };
 
+static struct video_device cadet_radio = {
+       .name           = "Cadet radio",
+       .fops           = &cadet_fops,
+       .ioctl_ops      = &cadet_ioctl_ops,
+};
+
 #ifdef CONFIG_PNP
 
 static struct pnp_device_id cadet_pnp_devices[] = {
index de49be971480fd8ec1b569904f8d329fd3ee821f..36e754e3ffb2011cbdba08e88cdfce11cab7ec0f 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/pci.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/errno.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
@@ -374,11 +375,7 @@ static const struct file_operations gemtek_pci_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device vdev_template = {
-       .owner         = THIS_MODULE,
-       .name          = "Gemtek PCI Radio",
-       .type          = VID_TYPE_TUNER,
-       .fops          = &gemtek_pci_fops,
+static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -393,6 +390,12 @@ static struct video_device vdev_template = {
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device vdev_template = {
+       .name          = "Gemtek PCI Radio",
+       .fops          = &gemtek_pci_fops,
+       .ioctl_ops     = &gemtek_pci_ioctl_ops,
+};
+
 static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id )
 {
        struct gemtek_pci_card *card;
index 81f6aeb1cd1154d62e707d41d620381fa100c25c..2b1a6221de6d5f2108ff8ad0aaab04e515082002 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
+#include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
 #include <linux/spinlock.h>
 
@@ -552,11 +553,7 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
        return 0;
 }
 
-static struct video_device gemtek_radio = {
-       .owner                  = THIS_MODULE,
-       .name                   = "GemTek Radio card",
-       .type                   = VID_TYPE_TUNER,
-       .fops                   = &gemtek_fops,
+static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
        .vidioc_querycap        = vidioc_querycap,
        .vidioc_g_tuner         = vidioc_g_tuner,
        .vidioc_s_tuner         = vidioc_s_tuner,
@@ -571,6 +568,12 @@ static struct video_device gemtek_radio = {
        .vidioc_s_ctrl          = vidioc_s_ctrl
 };
 
+static struct video_device gemtek_radio = {
+       .name                   = "GemTek Radio card",
+       .fops                   = &gemtek_fops,
+       .ioctl_ops              = &gemtek_ioctl_ops,
+};
+
 /*
  * Initialization / cleanup related stuff.
  */
index bddd3c409aa95a84112b1930ea0844ab060b4150..0ada1c697e8a4834690ee2b442dcb87128f694fc 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/pci.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,6)
@@ -354,10 +355,7 @@ static u16 __devinit radio_power_on(struct radio_device *dev)
        return (ofreq == radio_bits_get(dev));
 }
 
-static struct video_device maestro_radio = {
-       .name           = "Maestro radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &maestro_fops,
+static const struct v4l2_ioctl_ops maestro_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -372,6 +370,12 @@ static struct video_device maestro_radio = {
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device maestro_radio = {
+       .name           = "Maestro radio",
+       .fops           = &maestro_fops,
+       .ioctl_ops      = &maestro_ioctl_ops,
+};
+
 static int __devinit maestro_probe(struct pci_dev *pdev,
        const struct pci_device_id *ent)
 {
index 0133ecf3e040b0905f157581283c384f6ec7b876..43c75497dc499ea02fdeebabfd0d57568458e896 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/pci.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #define DRIVER_VERSION "0.77"
 
@@ -373,13 +374,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
        return -EINVAL;
 }
 
-static struct video_device maxiradio_radio =
-{
-       .owner              = THIS_MODULE,
-       .name               = "Maxi Radio FM2000 radio",
-       .type               = VID_TYPE_TUNER,
-       .fops               = &maxiradio_fops,
-
+static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -394,6 +389,12 @@ static struct video_device maxiradio_radio =
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device maxiradio_radio = {
+       .name               = "Maxi Radio FM2000 radio",
+       .fops               = &maxiradio_fops,
+       .ioctl_ops          = &maxiradio_ioctl_ops,
+};
+
 static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        if(!request_region(pci_resource_start(pdev, 0),
index 070802103dc34d52176b87fa78c43511f2ce3798..e2dde0807268374f404db090b6c0b412548d0b40 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/spinlock.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
@@ -294,12 +295,7 @@ static const struct file_operations rtrack2_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device rtrack2_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "RadioTrack II radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &rtrack2_fops,
+static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -314,6 +310,12 @@ static struct video_device rtrack2_radio=
        .vidioc_s_input     = vidioc_s_input,
 };
 
+static struct video_device rtrack2_radio = {
+       .name           = "RadioTrack II radio",
+       .fops           = &rtrack2_fops,
+       .ioctl_ops      = &rtrack2_ioctl_ops,
+};
+
 static int __init rtrack2_init(void)
 {
        if(io==-1)
index 66e052fd3909aa3531ce5e7b1e22bfe91f865537..bb5d92f104af000177afab5c202652adafc7a0f8 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/delay.h>       /* udelay                       */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/isapnp.h>
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
@@ -294,12 +295,7 @@ static const struct file_operations fmi_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device fmi_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "SF16FMx radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &fmi_fops,
+static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -314,6 +310,12 @@ static struct video_device fmi_radio=
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device fmi_radio = {
+       .name           = "SF16FMx radio",
+       .fops           = &fmi_fops,
+       .ioctl_ops      = &fmi_ioctl_ops,
+};
+
 /* ladis: this is my card. does any other types exist? */
 static struct isapnp_device_id id_table[] __devinitdata = {
        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
index b0ccf7cb5952a8c0edda2ef0588a0800fe1a6682..6290553d24beef56cf55ecfbe55aab32ae0ad620 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 
 static struct mutex lock;
@@ -410,12 +411,7 @@ static const struct file_operations fmr2_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device fmr2_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "SF16FMR2 radio",
-       . type          = VID_TYPE_TUNER,
-       .fops           = &fmr2_fops,
+static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -430,6 +426,12 @@ static struct video_device fmr2_radio=
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device fmr2_radio = {
+       .name           = "SF16FMR2 radio",
+       .fops           = &fmr2_fops,
+       .ioctl_ops      = &fmr2_ioctl_ops,
+};
+
 static int __init fmr2_init(void)
 {
        fmr2_unit.port = io;
index dc93a882b38595114169bb575820cf023155a460..a4984ff87c9c8328bd7e59b92022adf994d74430 100644 (file)
 #include <linux/videodev2.h>
 #include <linux/mutex.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/rds.h>
 #include <asm/unaligned.h>
 
@@ -1585,15 +1586,7 @@ done:
        return retval;
 }
 
-
-/*
- * si470x_viddev_tamples - video device interface
- */
-static struct video_device si470x_viddev_template = {
-       .fops                   = &si470x_fops,
-       .name                   = DRIVER_NAME,
-       .type                   = VID_TYPE_TUNER,
-       .release                = video_device_release,
+static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
        .vidioc_querycap        = si470x_vidioc_querycap,
        .vidioc_g_input         = si470x_vidioc_g_input,
        .vidioc_s_input         = si470x_vidioc_s_input,
@@ -1607,7 +1600,16 @@ static struct video_device si470x_viddev_template = {
        .vidioc_g_frequency     = si470x_vidioc_g_frequency,
        .vidioc_s_frequency     = si470x_vidioc_s_frequency,
        .vidioc_s_hw_freq_seek  = si470x_vidioc_s_hw_freq_seek,
-       .owner                  = THIS_MODULE,
+};
+
+/*
+ * si470x_viddev_tamples - video device interface
+ */
+static struct video_device si470x_viddev_template = {
+       .fops                   = &si470x_fops,
+       .ioctl_ops              = &si470x_ioctl_ops,
+       .name                   = DRIVER_NAME,
+       .release                = video_device_release,
 };
 
 
index acc32080e9bdefef40bc84d0e2e0bbf09f758a42..cefa44fc5aed84a42900591d99ac40a0878012fc 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/spinlock.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
@@ -366,12 +367,7 @@ static const struct file_operations terratec_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device terratec_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "TerraTec ActiveRadio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &terratec_fops,
+static const struct v4l2_ioctl_ops terratec_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -386,6 +382,12 @@ static struct video_device terratec_radio=
        .vidioc_s_input     = vidioc_s_input,
 };
 
+static struct video_device terratec_radio = {
+       .name           = "TerraTec ActiveRadio",
+       .fops           = &terratec_fops,
+       .ioctl_ops      = &terratec_ioctl_ops,
+};
+
 static int __init terratec_init(void)
 {
        if(io==-1)
index 4ebdfbadeb9ce6160d7d7ea023b87cc6d13860c3..d70172d23edb431f0460dbecd2a562a740a28e9e 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/uaccess.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
@@ -346,12 +347,7 @@ static const struct file_operations trust_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device trust_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "Trust FM Radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &trust_fops,
+static const struct v4l2_ioctl_ops trust_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -366,6 +362,12 @@ static struct video_device trust_radio=
        .vidioc_s_input     = vidioc_s_input,
 };
 
+static struct video_device trust_radio = {
+       .name           = "Trust FM Radio",
+       .fops           = &trust_fops,
+       .ioctl_ops      = &trust_ioctl_ops,
+};
+
 static int __init trust_init(void)
 {
        if(io == -1) {
index 18f2abd7e2552e985d670551b1abc729c0d24d5f..f8d62cfea7745d28cdda0c5be81667e4fb571c09 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/uaccess.h>       /* copy to/from user              */
 #include <linux/videodev2.h>   /* kernel radio structs           */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,1,1)
@@ -344,12 +345,7 @@ static const struct file_operations typhoon_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device typhoon_radio =
-{
-       .owner          = THIS_MODULE,
-       .name           = "Typhoon Radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &typhoon_fops,
+static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -364,6 +360,12 @@ static struct video_device typhoon_radio =
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device typhoon_radio = {
+       .name           = "Typhoon Radio",
+       .fops           = &typhoon_fops,
+       .ioctl_ops      = &typhoon_ioctl_ops,
+};
+
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
 
 static int typhoon_proc_show(struct seq_file *m, void *v)
index 43773c56c62f0fcd45e25f87629591d51fb5d5ce..9f17a332fa1173b5efa41dd298b84d614d6216e6 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/uaccess.h>       /* copy to/from user              */
 #include <linux/videodev2.h>   /* kernel radio structs           */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
@@ -407,12 +408,7 @@ static const struct file_operations zoltrix_fops =
        .llseek         = no_llseek,
 };
 
-static struct video_device zoltrix_radio =
-{
-       .owner          = THIS_MODULE,
-       .name           = "Zoltrix Radio Plus",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &zoltrix_fops,
+static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -427,6 +423,12 @@ static struct video_device zoltrix_radio =
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device zoltrix_radio = {
+       .name           = "Zoltrix Radio Plus",
+       .fops           = &zoltrix_fops,
+       .ioctl_ops      = &zoltrix_ioctl_ops,
+};
+
 static int __init zoltrix_init(void)
 {
        if (io == -1) {
index f606d2951fde5a44fb650df92187ff71cd5ea3ad..d4a6e56a71358842b58a87146fc2672e43ba418d 100644 (file)
@@ -487,17 +487,6 @@ config VIDEO_PMS
          To compile this driver as a module, choose M here: the
          module will be called pms.
 
-config VIDEO_PLANB
-       tristate "PlanB Video-In on PowerMac"
-       depends on PPC_PMAC && VIDEO_V4L1 && BROKEN
-       help
-         PlanB is the V4L driver for the PowerMac 7x00/8x00 series video
-         input hardware. If you want to experiment with this, say Y.
-         Otherwise, or if you don't understand a word, say N. See
-         <http://www.cpu.lu/~mlan/linux/dev/planb.html> for more info.
-
-         Saying M will compile this driver as a module (planb).
-
 config VIDEO_BWQCAM
        tristate "Quickcam BW Video For Linux"
        depends on PARPORT && VIDEO_V4L1
@@ -806,13 +795,7 @@ menuconfig V4L_USB_DRIVERS
 
 if V4L_USB_DRIVERS && USB
 
-config USB_VIDEO_CLASS
-       tristate "USB Video Class (UVC)"
-       ---help---
-         Support for the USB Video Class (UVC).  Currently only video
-         input devices, such as webcams, are supported.
-
-         For more information see: <http://linux-uvc.berlios.de/>
+source "drivers/media/video/uvc/Kconfig"
 
 source "drivers/media/video/gspca/Kconfig"
 
index 45d5db5abb1eabe445c8af4cf8182e0f1728c6f9..bbc6f8b82297e7a62dfc7d1e6ada130dff48d2d0 100644 (file)
@@ -10,6 +10,8 @@ msp3400-objs  :=      msp3400-driver.o msp3400-kthreads.o
 
 stkwebcam-objs :=      stk-webcam.o stk-sensor.o
 
+videodev-objs  :=      v4l2-dev.o v4l2-ioctl.o
+
 obj-$(CONFIG_VIDEO_DEV) += videodev.o compat_ioctl32.o v4l2-int-device.o
 
 obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
@@ -55,7 +57,6 @@ 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 indycam.o
 obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
 obj-$(CONFIG_VIDEO_CPIA) += cpia.o
index 8c7d1958856b600f515c51716d960b2aaaf7f167..56ebfd5ef6fafc193a3b00ed11520c5d81f0c20b 100644 (file)
@@ -754,7 +754,6 @@ static const struct file_operations ar_fops = {
 };
 
 static struct video_device ar_template = {
-       .owner          = THIS_MODULE,
        .name           = "Colour AR VGA",
        .type           = VID_TYPE_CAPTURE,
        .fops           = &ar_fops,
index 52b2491581a835784790d7bec436693fe2854160..ed9a50f189fc8325cfd52f470997c55d10b69a16 100644 (file)
@@ -6,6 +6,7 @@ config VIDEO_AU0828
        select VIDEO_TVEEPROM
        select DVB_AU8522 if !DVB_FE_CUSTOMIZE
        select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE
        ---help---
          This is a video4linux driver for Auvitek's USB device.
 
index 898e12395e7c26e1f829beff5f773c85cd5671f8..443e590097628873a7f6ad490ecbcb15a97dbce4 100644 (file)
@@ -32,6 +32,9 @@ struct au0828_board au0828_boards[] = {
        [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
                .name   = "Hauppauge HVR950Q",
        },
+       [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
+               .name   = "Hauppauge HVR950Q rev xxF8",
+       },
        [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
                .name   = "DViCO FusionHDTV USB",
        },
@@ -49,6 +52,7 @@ int au0828_tuner_callback(void *priv, int command, int arg)
        switch (dev->board) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
        case AU0828_BOARD_DVICO_FUSIONHDTV7:
                if (command == 0) {
                        /* Tuner Reset Command from xc5000 */
@@ -110,6 +114,7 @@ void au0828_card_setup(struct au0828_dev *dev)
        switch (dev->board) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
                if (dev->i2c_rc == 0)
                        hauppauge_eeprom(dev, eeprom+0xa0);
                break;
@@ -128,6 +133,7 @@ void au0828_gpio_setup(struct au0828_dev *dev)
        switch (dev->board) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
                /* GPIO's
                 * 4 - CS5340
                 * 5 - AU8522 Demodulator
@@ -193,6 +199,12 @@ struct usb_device_id au0828_usb_id_table [] = {
                .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
        { USB_DEVICE(0x0fd9, 0x0008),
                .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7201),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
+       { USB_DEVICE(0x2040, 0x7211),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
+       { USB_DEVICE(0x2040, 0x7281),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
        { },
 };
 
index e26f54a961d0f79dfb772739ba51d802fe235a84..c37f5fd0fa801b2f0932258687dd8bc62ab5df77 100644 (file)
@@ -23,3 +23,4 @@
 #define AU0828_BOARD_HAUPPAUGE_HVR950Q 1
 #define AU0828_BOARD_HAUPPAUGE_HVR850  2
 #define AU0828_BOARD_DVICO_FUSIONHDTV7 3
+#define AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL     4
index c6d47059038029f6d039b071512a3f343d633043..584a83a94a2a276501f77864321c67f1ce065ca2 100644 (file)
@@ -28,6 +28,7 @@
 #include "au0828.h"
 #include "au8522.h"
 #include "xc5000.h"
+#include "mxl5007t.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -45,6 +46,11 @@ static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
        .tuner_callback   = au0828_tuner_callback
 };
 
+static struct mxl5007t_config mxl5007t_hvr950q_config = {
+       .xtal_freq_hz = MxL_XTAL_24_MHZ,
+       .if_freq_hz = MxL_IF_6_MHZ,
+};
+
 /*-------------------------------------------------------------------*/
 static void urb_completion(struct urb *purb)
 {
@@ -342,6 +348,15 @@ int au0828_dvb_register(struct au0828_dev *dev)
                                &dev->i2c_adap,
                                &hauppauge_hvr950q_tunerconfig, dev);
                break;
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &hauppauge_hvr950q_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL)
+                       dvb_attach(mxl5007t_attach, dvb->frontend,
+                                  &dev->i2c_adap, 0x60,
+                                  &mxl5007t_hvr950q_config);
+               break;
        default:
                printk(KERN_WARNING "The frontend of your DVB/ATSC card "
                       "isn't supported yet\n");
index 24a34fc1f2b3bf9821359ce6e52878b3f5abeaba..ce71e8e7b8355bd8fe59af2397b537bd7202a693 100644 (file)
@@ -1,9 +1,7 @@
 config VIDEO_BT848
        tristate "BT848 Video For Linux"
        depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT
-       depends on HOTPLUG      # due to FW_LOADER
        select I2C_ALGOBIT
-       select FW_LOADER
        select VIDEO_BTCX
        select VIDEOBUF_DMA_SG
        select VIDEO_IR
index 0ea559a7fe59ea3dba50fc435dfd57900477592f..85bf31ab8789db097df2f29b0aaf77f8578b86f8 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/kdev_t.h>
 #include "bttvp.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/tvaudio.h>
 #include <media/msp3400.h>
 
@@ -163,8 +164,8 @@ MODULE_LICENSE("GPL");
 static ssize_t show_card(struct device *cd,
                         struct device_attribute *attr, char *buf)
 {
-       struct video_device *vfd = container_of(cd, struct video_device, class_dev);
-       struct bttv *btv = dev_get_drvdata(vfd->dev);
+       struct video_device *vfd = container_of(cd, struct video_device, dev);
+       struct bttv *btv = dev_get_drvdata(vfd->parent);
        return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
 }
 static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
@@ -3357,10 +3358,7 @@ static const struct file_operations bttv_fops =
        .poll     = bttv_poll,
 };
 
-static struct video_device bttv_video_template =
-{
-       .fops     = &bttv_fops,
-       .minor    = -1,
+static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
        .vidioc_querycap                = bttv_querycap,
        .vidioc_enum_fmt_vid_cap        = bttv_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap           = bttv_g_fmt_vid_cap,
@@ -3411,8 +3409,14 @@ static struct video_device bttv_video_template =
        .vidioc_g_register              = bttv_g_register,
        .vidioc_s_register              = bttv_s_register,
 #endif
-       .tvnorms                        = BTTV_NORMS,
-       .current_norm                   = V4L2_STD_PAL,
+};
+
+static struct video_device bttv_video_template = {
+       .fops         = &bttv_fops,
+       .minor        = -1,
+       .ioctl_ops    = &bttv_ioctl_ops,
+       .tvnorms      = BTTV_NORMS,
+       .current_norm = V4L2_STD_PAL,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -3635,10 +3639,7 @@ static const struct file_operations radio_fops =
        .poll     = radio_poll,
 };
 
-static struct video_device radio_template =
-{
-       .fops     = &radio_fops,
-       .minor    = -1,
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
        .vidioc_querycap        = radio_querycap,
        .vidioc_g_tuner         = radio_g_tuner,
        .vidioc_enum_input      = radio_enum_input,
@@ -3655,6 +3656,12 @@ static struct video_device radio_template =
        .vidioc_s_frequency     = bttv_s_frequency,
 };
 
+static struct video_device radio_template = {
+       .fops      = &radio_fops,
+       .minor     = -1,
+       .ioctl_ops = &radio_ioctl_ops,
+};
+
 /* ----------------------------------------------------------------------- */
 /* some debug code                                                         */
 
@@ -4175,8 +4182,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
 
 static struct video_device *vdev_init(struct bttv *btv,
                                      const struct video_device *template,
-                                     const char *type_name,
-                                     const int type)
+                                     const char *type_name)
 {
        struct video_device *vfd;
 
@@ -4185,9 +4191,8 @@ static struct video_device *vdev_init(struct bttv *btv,
                return NULL;
        *vfd = *template;
        vfd->minor   = -1;
-       vfd->dev     = &btv->c.pci->dev;
+       vfd->parent  = &btv->c.pci->dev;
        vfd->release = video_device_release;
-       vfd->type    = type;
        vfd->debug   = bttv_debug;
        snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
                 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
@@ -4223,20 +4228,11 @@ static void bttv_unregister_video(struct bttv *btv)
 /* register video4linux devices */
 static int __devinit bttv_register_video(struct bttv *btv)
 {
-       int video_type = VID_TYPE_CAPTURE |
-                        VID_TYPE_TUNER   |
-                        VID_TYPE_CLIPPING|
-                        VID_TYPE_SCALES;
-
-       if (no_overlay <= 0) {
-               bttv_video_template.type |= VID_TYPE_OVERLAY;
-       } else {
+       if (no_overlay > 0)
                printk("bttv: Overlay support disabled.\n");
-       }
 
        /* video */
-       btv->video_dev = vdev_init(btv, &bttv_video_template,
-                                  "video", video_type);
+       btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
 
        if (NULL == btv->video_dev)
                goto err;
@@ -4244,7 +4240,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
                goto err;
        printk(KERN_INFO "bttv%d: registered device video%d\n",
               btv->c.nr,btv->video_dev->minor & 0x1f);
-       if (device_create_file(&btv->video_dev->class_dev,
+       if (device_create_file(&btv->video_dev->dev,
                                     &dev_attr_card)<0) {
                printk(KERN_ERR "bttv%d: device_create_file 'card' "
                       "failed\n", btv->c.nr);
@@ -4252,8 +4248,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
        }
 
        /* vbi */
-       btv->vbi_dev = vdev_init(btv, &bttv_video_template,
-                                "vbi", VID_TYPE_TUNER | VID_TYPE_TELETEXT);
+       btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
 
        if (NULL == btv->vbi_dev)
                goto err;
@@ -4265,8 +4260,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
        if (!btv->has_radio)
                return 0;
        /* radio */
-       btv->radio_dev = vdev_init(btv, &radio_template,
-                                  "radio", VID_TYPE_TUNER);
+       btv->radio_dev = vdev_init(btv, &radio_template, "radio");
        if (NULL == btv->radio_dev)
                goto err;
        if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0)
index 0af586876e72f6f7f01295cb99381f159feec47e..649682aac1acebf4ff3a4bc45033f897258f875f 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <media/v4l2-ioctl.h>
 
 #include "bttvp.h"
 
index 68f28e5fa0409307c460546e511dbbb68b7a04e0..6819e21a3773ea747a7ef8e5762076d097f9d008 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/kdev_t.h>
+#include <media/v4l2-ioctl.h>
 #include <asm/io.h>
 #include "bttvp.h"
 
index b364adaae78d8e8262043a5e2c3734249ca01c51..d3b3268bace8795dcde4e8d6f1e002d61fa24b7f 100644 (file)
@@ -74,6 +74,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <linux/sched.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 
@@ -906,9 +907,7 @@ static const struct file_operations qcam_fops = {
 };
 static struct video_device qcam_template=
 {
-       .owner          = THIS_MODULE,
        .name           = "Connectix Quickcam",
-       .type           = VID_TYPE_CAPTURE,
        .fops           = &qcam_fops,
 };
 
index fe1e67bb1ca860b6a946afb0ed6804654c8bf4ce..fe9379b282d36b10e7b3043ab46f1f243a2fa8ed 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/sched.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
 
@@ -701,9 +702,7 @@ static const struct file_operations qcam_fops = {
 
 static struct video_device qcam_template=
 {
-       .owner          = THIS_MODULE,
        .name           = "Colour QuickCam",
-       .type           = VID_TYPE_CAPTURE,
        .fops           = &qcam_fops,
 };
 
index d99453faaab79715d3723492e99a9ea9d9a92116..c149b7d712e5a703d5f277ebed607aafe6202202 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/spinlock.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/v4l2-chip-ident.h>
 #include <linux/device.h>
 #include <linux/wait.h>
@@ -1768,17 +1769,7 @@ static const struct file_operations cafe_v4l_fops = {
        .llseek = no_llseek,
 };
 
-static struct video_device cafe_v4l_template = {
-       .name = "cafe",
-       .type = VFL_TYPE_GRABBER,
-       .type2 = VID_TYPE_CAPTURE,
-       .minor = -1, /* Get one dynamically */
-       .tvnorms = V4L2_STD_NTSC_M,
-       .current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
-
-       .fops = &cafe_v4l_fops,
-       .release = cafe_v4l_dev_release,
-
+static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
        .vidioc_querycap        = cafe_vidioc_querycap,
        .vidioc_enum_fmt_vid_cap = cafe_vidioc_enum_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap = cafe_vidioc_try_fmt_vid_cap,
@@ -1801,6 +1792,17 @@ static struct video_device cafe_v4l_template = {
        .vidioc_s_parm          = cafe_vidioc_s_parm,
 };
 
+static struct video_device cafe_v4l_template = {
+       .name = "cafe",
+       .minor = -1, /* Get one dynamically */
+       .tvnorms = V4L2_STD_NTSC_M,
+       .current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
+
+       .fops = &cafe_v4l_fops,
+       .ioctl_ops = &cafe_v4l_ioctl_ops,
+       .release = cafe_v4l_dev_release,
+};
+
 
 
 
@@ -2157,7 +2159,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
        cam->v4ldev = cafe_v4l_template;
        cam->v4ldev.debug = 0;
 //     cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG;
-       cam->v4ldev.dev = &pdev->dev;
+       cam->v4ldev.parent = &pdev->dev;
        ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1);
        if (ret)
                goto out_smbus;
index 54de0cd482e926c1f31f230ea823b90e3e77d078..bd5d9de5a008eacfc6b493e5813d49d3fd668a57 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/videodev2.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
-#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #ifdef CONFIG_COMPAT
 
index 2a81376ef5038dadaf621e2441588bab05eed4c6..dc8cc6115e2f13f1eea59c69d177afd5d051ecdd 100644 (file)
@@ -3799,9 +3799,7 @@ static const struct file_operations cpia_fops = {
 };
 
 static struct video_device cpia_template = {
-       .owner          = THIS_MODULE,
        .name           = "CPiA Camera",
-       .type           = VID_TYPE_CAPTURE,
        .fops           = &cpia_fops,
 };
 
index 5096058bf5793a68b3ea69d748913cd34caaa3e6..8f0cfee4b8a110be08eba133866568816be1ee0b 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 
index f2e8b1c82c66da6e10a347f1195950ed9ba6d3d4..af8b9ec8e3587bd64ff37cf2c29a4df1fe5118fa 100644 (file)
@@ -32,6 +32,7 @@
 #include "cpia2.h"
 
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/firmware.h>
 
index 7ce2789fa976213188419ced61d709339fbf134e..515c8b57a60d8772c7b156fb1e0fd11c02f9d2d3 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <media/v4l2-ioctl.h>
 
 #include "cpia2.h"
 #include "cpia2dev.h"
@@ -1935,11 +1936,7 @@ static const struct file_operations fops_template = {
 
 static struct video_device cpia2_template = {
        /* I could not find any place for the old .initialize initializer?? */
-       .owner=         THIS_MODULE,
        .name=          "CPiA2 Camera",
-       .type=          VID_TYPE_CAPTURE,
-       .type2 =        V4L2_CAP_VIDEO_CAPTURE |
-                       V4L2_CAP_STREAMING,
        .minor=         -1,
        .fops=          &fops_template,
        .release=       video_device_release,
index 1c3fa3a7470a3f9b7dd3f316aa14fe810d51631a..61d14d26686fdc05dffa7f1baf8185a861115d27 100644 (file)
@@ -111,7 +111,7 @@ static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg)
                if (cmd == VIDIOC_DBG_G_REGISTER)
                        reg->val = cs5345_read(client, reg->reg & 0x1f);
                else
-                       cs5345_write(client, reg->reg & 0x1f, reg->val & 0x1f);
+                       cs5345_write(client, reg->reg & 0x1f, reg->val & 0xff);
                break;
        }
 #endif
index 645b339152d34aced2623d59974286736ce9e089..e30a589c0e18187b095e6a23ee418c505b8f31ed 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-i2c-drv-legacy.h>
index 9aefdc5ea79a960983c9c78d5c3cd5e4348e1311..ef48565de7f1b7c5fdcd61e69fdb6e78b9ca9f83 100644 (file)
@@ -2,9 +2,7 @@ config VIDEO_CX18
        tristate "Conexant cx23418 MPEG encoder support"
        depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
        depends on INPUT        # due to VIDEO_IR
-       depends on HOTPLUG      # due to FW_LOADER
        select I2C_ALGOBIT
-       select FW_LOADER
        select VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
index c40a286de1b97a261542662fc114606a598f8f2d..0b55837880a711d5ef11805a01371c6e91bd122a 100644 (file)
@@ -30,7 +30,6 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
        if (freq != 32000 && freq != 44100 && freq != 48000)
                return -EINVAL;
 
-       /* common for all inputs and rates */
        /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
        cx18_av_write(cx, 0x127, 0x50);
 
@@ -38,15 +37,30 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                switch (freq) {
                case 32000:
                        /* VID_PLL and AUX_PLL */
-                       cx18_av_write4(cx, 0x108, 0x1006040f);
+                       cx18_av_write4(cx, 0x108, 0x1408040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x01bb39ee);
+                       /* 0x8.9504318a * 28,636,363.636 / 0x14 = 32000 * 384 */
+                       cx18_av_write4(cx, 0x110, 0x012a0863);
 
-                       /* src3/4/6_ctl = 0x0801f77f */
+                       /* src3/4/6_ctl */
+                       /* 0x1.f77f = (4 * 15734.26) / 32000 */
                        cx18_av_write4(cx, 0x900, 0x0801f77f);
                        cx18_av_write4(cx, 0x904, 0x0801f77f);
                        cx18_av_write4(cx, 0x90c, 0x0801f77f);
+
+                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
+                       cx18_av_write(cx, 0x127, 0x54);
+
+                       /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11202fff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+                        *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa10d2ef8);
                        break;
 
                case 44100:
@@ -54,12 +68,24 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x1009040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+                       /* 0x9.7635e7 * 28,636,363.63 / 0x10 = 44100 * 384 */
+                       cx18_av_write4(cx, 0x110, 0x00ec6bce);
 
-                       /* src3/4/6_ctl = 0x08016d59 */
+                       /* src3/4/6_ctl */
+                       /* 0x1.6d59 = (4 * 15734.26) / 44100 */
                        cx18_av_write4(cx, 0x900, 0x08016d59);
                        cx18_av_write4(cx, 0x904, 0x08016d59);
                        cx18_av_write4(cx, 0x90c, 0x08016d59);
+
+                       /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x112092ff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+                        *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa11d4bf8);
                        break;
 
                case 48000:
@@ -67,12 +93,24 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x100a040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x0098d6e5);
+                       /* 0xa.4c6b6ea * 28,636,363.63 / 0x10 = 48000 * 384 */
+                       cx18_av_write4(cx, 0x110, 0x0098d6dd);
 
-                       /* src3/4/6_ctl = 0x08014faa */
+                       /* src3/4/6_ctl */
+                       /* 0x1.4faa = (4 * 15734.26) / 48000 */
                        cx18_av_write4(cx, 0x900, 0x08014faa);
                        cx18_av_write4(cx, 0x904, 0x08014faa);
                        cx18_av_write4(cx, 0x90c, 0x08014faa);
+
+                       /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11205fff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+                        *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa11193f8);
                        break;
                }
        } else {
@@ -82,18 +120,31 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x1e08040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x012a0869);
+                       /* 0x8.9504318 * 28,636,363.63 / 0x1e = 32000 * 256 */
+                       cx18_av_write4(cx, 0x110, 0x012a0863);
 
-                       /* src1_ctl = 0x08010000 */
+                       /* src1_ctl */
+                       /* 0x1.0000 = 32000/32000 */
                        cx18_av_write4(cx, 0x8f8, 0x08010000);
 
-                       /* src3/4/6_ctl = 0x08020000 */
+                       /* src3/4/6_ctl */
+                       /* 0x2.0000 = 2 * (32000/32000) */
                        cx18_av_write4(cx, 0x900, 0x08020000);
                        cx18_av_write4(cx, 0x904, 0x08020000);
                        cx18_av_write4(cx, 0x90c, 0x08020000);
 
                        /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
                        cx18_av_write(cx, 0x127, 0x54);
+
+                       /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11201fff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+                        *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa10d2ef8);
                        break;
 
                case 44100:
@@ -101,15 +152,28 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x1809040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+                       /* 0x9.7635e74 * 28,636,363.63 / 0x18 = 44100 * 256 */
+                       cx18_av_write4(cx, 0x110, 0x00ec6bce);
 
-                       /* src1_ctl = 0x08010000 */
+                       /* src1_ctl */
+                       /* 0x1.60cd = 44100/32000 */
                        cx18_av_write4(cx, 0x8f8, 0x080160cd);
 
-                       /* src3/4/6_ctl = 0x08020000 */
+                       /* src3/4/6_ctl */
+                       /* 0x1.7385 = 2 * (32000/44100) */
                        cx18_av_write4(cx, 0x900, 0x08017385);
                        cx18_av_write4(cx, 0x904, 0x08017385);
                        cx18_av_write4(cx, 0x90c, 0x08017385);
+
+                       /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x112061ff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+                        *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa11d4bf8);
                        break;
 
                case 48000:
@@ -117,15 +181,28 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x180a040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x0098d6e5);
+                       /* 0xa.4c6b6ea * 28,636,363.63 / 0x18 = 48000 * 256 */
+                       cx18_av_write4(cx, 0x110, 0x0098d6dd);
 
-                       /* src1_ctl = 0x08010000 */
+                       /* src1_ctl */
+                       /* 0x1.8000 = 48000/32000 */
                        cx18_av_write4(cx, 0x8f8, 0x08018000);
 
-                       /* src3/4/6_ctl = 0x08020000 */
+                       /* src3/4/6_ctl */
+                       /* 0x1.5555 = 2 * (32000/48000) */
                        cx18_av_write4(cx, 0x900, 0x08015555);
                        cx18_av_write4(cx, 0x904, 0x08015555);
                        cx18_av_write4(cx, 0x90c, 0x08015555);
+
+                       /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11203fff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+                        *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa11193f8);
                        break;
                }
        }
index 45e31b04730e2c2780c9253d938cac4891a95e7b..4801bc7fb5b224336c2cd4ba609df9fde7368bb6 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/dvb/video.h>
 #include <linux/dvb/audio.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/tuner.h>
 #include "cx18-mailbox.h"
 #include "cx18-av-core.h"
index 2d630d9f7496b8c2e6b8989f11f64d44903437ff..78fadd2ada5d72a4a1d45708ebe352e03cb099d0 100644 (file)
 
 #define CX18_DSP0_INTERRUPT_MASK       0xd0004C
 
-/* Encoder/decoder firmware sizes */
-#define CX18_FW_CPU_SIZE               (158332)
-#define CX18_FW_APU_SIZE               (141200)
-
 #define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
 #define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
 
@@ -100,35 +96,22 @@ struct cx18_apu_rom_seghdr {
        u32 size;
 };
 
-static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx, long size)
+static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
 {
        const struct firmware *fw = NULL;
-       int retries = 3;
        int i, j;
+       unsigned size;
        u32 __iomem *dst = (u32 __iomem *)mem;
        const u32 *src;
 
-retry:
-       if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
-               CX18_ERR("Unable to open firmware %s (must be %ld bytes)\n",
-                               fn, size);
+       if (request_firmware(&fw, fn, &cx->dev->dev)) {
+               CX18_ERR("Unable to open firmware %s\n", fn);
                CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
                return -ENOMEM;
        }
 
        src = (const u32 *)fw->data;
 
-       if (fw->size != size) {
-               /* Due to race conditions in firmware loading (esp. with
-                  udev <0.95) the wrong file was sometimes loaded. So we check
-                  filesizes to see if at least the right-sized file was
-                  loaded. If not, then we retry. */
-               CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
-                               fn, size, fw->size);
-               release_firmware(fw);
-               retries--;
-               goto retry;
-       }
        for (i = 0; i < fw->size; i += 4096) {
                setup_page(i);
                for (j = i; j < fw->size && j < i + 4096; j += 4) {
@@ -145,15 +128,16 @@ retry:
        }
        if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
                CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
+       size = fw->size;
        release_firmware(fw);
        return size;
 }
 
-static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, long size)
+static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
 {
        const struct firmware *fw = NULL;
-       int retries = 3;
        int i, j;
+       unsigned size;
        const u32 *src;
        struct cx18_apu_rom_seghdr seghdr;
        const u8 *vers;
@@ -161,10 +145,8 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
        u32 apu_version = 0;
        int sz;
 
-retry:
-       if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
-               CX18_ERR("unable to open firmware %s (must be %ld bytes)\n",
-                               fn, size);
+       if (request_firmware(&fw, fn, &cx->dev->dev)) {
+               CX18_ERR("unable to open firmware %s\n", fn);
                CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
                return -ENOMEM;
        }
@@ -173,19 +155,8 @@ retry:
        vers = fw->data + sizeof(seghdr);
        sz = fw->size;
 
-       if (fw->size != size) {
-               /* Due to race conditions in firmware loading (esp. with
-                  udev <0.95) the wrong file was sometimes loaded. So we check
-                  filesizes to see if at least the right-sized file was
-                  loaded. If not, then we retry. */
-               CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
-                              fn, size, fw->size);
-               release_firmware(fw);
-               retries--;
-               goto retry;
-       }
        apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
-       while (offset + sizeof(seghdr) < size) {
+       while (offset + sizeof(seghdr) < fw->size) {
                /* TODO: byteswapping */
                memcpy(&seghdr, src + offset / 4, sizeof(seghdr));
                offset += sizeof(seghdr);
@@ -215,6 +186,7 @@ retry:
        if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
                CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
                                fn, apu_version, fw->size);
+       size = fw->size;
        release_firmware(fw);
        /* Clear bit0 for APU to start from 0 */
        write_reg(read_reg(0xc72030) & ~1, 0xc72030);
@@ -340,7 +312,7 @@ int cx18_firmware_init(struct cx18 *cx)
        /* Only if the processor is not running */
        if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
                int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
-                              cx->enc_mem, cx, CX18_FW_APU_SIZE);
+                              cx->enc_mem, cx);
 
                write_enc(0xE51FF004, 0);
                write_enc(0xa00000, 4);  /* todo: not hardcoded */
@@ -348,7 +320,7 @@ int cx18_firmware_init(struct cx18 *cx)
                cx18_msleep_timeout(500, 0);
 
                sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
-                                       cx->enc_mem, cx, CX18_FW_CPU_SIZE);
+                                       cx->enc_mem, cx);
 
                if (sz > 0) {
                        int retries = 0;
index 0d74e59e503eb58a47b7fcf53596f33bfa76a696..a7f839631d6a6a5c2932385e956b6716b8059309 100644 (file)
@@ -787,50 +787,54 @@ int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        return res;
 }
 
-void cx18_set_funcs(struct video_device *vdev)
-{
-       vdev->vidioc_querycap                = cx18_querycap;
-       vdev->vidioc_g_priority              = cx18_g_priority;
-       vdev->vidioc_s_priority              = cx18_s_priority;
-       vdev->vidioc_s_audio                 = cx18_s_audio;
-       vdev->vidioc_g_audio                 = cx18_g_audio;
-       vdev->vidioc_enumaudio               = cx18_enumaudio;
-       vdev->vidioc_enum_input              = cx18_enum_input;
-       vdev->vidioc_cropcap                 = cx18_cropcap;
-       vdev->vidioc_s_crop                  = cx18_s_crop;
-       vdev->vidioc_g_crop                  = cx18_g_crop;
-       vdev->vidioc_g_input                 = cx18_g_input;
-       vdev->vidioc_s_input                 = cx18_s_input;
-       vdev->vidioc_g_frequency             = cx18_g_frequency;
-       vdev->vidioc_s_frequency             = cx18_s_frequency;
-       vdev->vidioc_s_tuner                 = cx18_s_tuner;
-       vdev->vidioc_g_tuner                 = cx18_g_tuner;
-       vdev->vidioc_g_enc_index             = cx18_g_enc_index;
-       vdev->vidioc_g_std                   = cx18_g_std;
-       vdev->vidioc_s_std                   = cx18_s_std;
-       vdev->vidioc_log_status              = cx18_log_status;
-       vdev->vidioc_enum_fmt_vid_cap        = cx18_enum_fmt_vid_cap;
-       vdev->vidioc_encoder_cmd             = cx18_encoder_cmd;
-       vdev->vidioc_try_encoder_cmd         = cx18_try_encoder_cmd;
-       vdev->vidioc_g_fmt_vid_cap           = cx18_g_fmt_vid_cap;
-       vdev->vidioc_g_fmt_vbi_cap           = cx18_g_fmt_vbi_cap;
-       vdev->vidioc_g_fmt_sliced_vbi_cap    = cx18_g_fmt_sliced_vbi_cap;
-       vdev->vidioc_s_fmt_vid_cap           = cx18_s_fmt_vid_cap;
-       vdev->vidioc_s_fmt_vbi_cap           = cx18_s_fmt_vbi_cap;
-       vdev->vidioc_s_fmt_sliced_vbi_cap    = cx18_s_fmt_sliced_vbi_cap;
-       vdev->vidioc_try_fmt_vid_cap         = cx18_try_fmt_vid_cap;
-       vdev->vidioc_try_fmt_vbi_cap         = cx18_try_fmt_vbi_cap;
-       vdev->vidioc_try_fmt_sliced_vbi_cap  = cx18_try_fmt_sliced_vbi_cap;
-       vdev->vidioc_g_sliced_vbi_cap        = cx18_g_sliced_vbi_cap;
-       vdev->vidioc_g_chip_ident            = cx18_g_chip_ident;
+static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
+       .vidioc_querycap                = cx18_querycap,
+       .vidioc_g_priority              = cx18_g_priority,
+       .vidioc_s_priority              = cx18_s_priority,
+       .vidioc_s_audio                 = cx18_s_audio,
+       .vidioc_g_audio                 = cx18_g_audio,
+       .vidioc_enumaudio               = cx18_enumaudio,
+       .vidioc_enum_input              = cx18_enum_input,
+       .vidioc_cropcap                 = cx18_cropcap,
+       .vidioc_s_crop                  = cx18_s_crop,
+       .vidioc_g_crop                  = cx18_g_crop,
+       .vidioc_g_input                 = cx18_g_input,
+       .vidioc_s_input                 = cx18_s_input,
+       .vidioc_g_frequency             = cx18_g_frequency,
+       .vidioc_s_frequency             = cx18_s_frequency,
+       .vidioc_s_tuner                 = cx18_s_tuner,
+       .vidioc_g_tuner                 = cx18_g_tuner,
+       .vidioc_g_enc_index             = cx18_g_enc_index,
+       .vidioc_g_std                   = cx18_g_std,
+       .vidioc_s_std                   = cx18_s_std,
+       .vidioc_log_status              = cx18_log_status,
+       .vidioc_enum_fmt_vid_cap        = cx18_enum_fmt_vid_cap,
+       .vidioc_encoder_cmd             = cx18_encoder_cmd,
+       .vidioc_try_encoder_cmd         = cx18_try_encoder_cmd,
+       .vidioc_g_fmt_vid_cap           = cx18_g_fmt_vid_cap,
+       .vidioc_g_fmt_vbi_cap           = cx18_g_fmt_vbi_cap,
+       .vidioc_g_fmt_sliced_vbi_cap    = cx18_g_fmt_sliced_vbi_cap,
+       .vidioc_s_fmt_vid_cap           = cx18_s_fmt_vid_cap,
+       .vidioc_s_fmt_vbi_cap           = cx18_s_fmt_vbi_cap,
+       .vidioc_s_fmt_sliced_vbi_cap    = cx18_s_fmt_sliced_vbi_cap,
+       .vidioc_try_fmt_vid_cap         = cx18_try_fmt_vid_cap,
+       .vidioc_try_fmt_vbi_cap         = cx18_try_fmt_vbi_cap,
+       .vidioc_try_fmt_sliced_vbi_cap  = cx18_try_fmt_sliced_vbi_cap,
+       .vidioc_g_sliced_vbi_cap        = cx18_g_sliced_vbi_cap,
+       .vidioc_g_chip_ident            = cx18_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       vdev->vidioc_g_register              = cx18_g_register;
-       vdev->vidioc_s_register              = cx18_s_register;
+       .vidioc_g_register              = cx18_g_register,
+       .vidioc_s_register              = cx18_s_register,
 #endif
-       vdev->vidioc_default                 = cx18_default;
-       vdev->vidioc_queryctrl               = cx18_queryctrl;
-       vdev->vidioc_querymenu               = cx18_querymenu;
-       vdev->vidioc_g_ext_ctrls             = cx18_g_ext_ctrls;
-       vdev->vidioc_s_ext_ctrls             = cx18_s_ext_ctrls;
-       vdev->vidioc_try_ext_ctrls           = cx18_try_ext_ctrls;
+       .vidioc_default                 = cx18_default,
+       .vidioc_queryctrl               = cx18_queryctrl,
+       .vidioc_querymenu               = cx18_querymenu,
+       .vidioc_g_ext_ctrls             = cx18_g_ext_ctrls,
+       .vidioc_s_ext_ctrls             = cx18_s_ext_ctrls,
+       .vidioc_try_ext_ctrls           = cx18_try_ext_ctrls,
+};
+
+void cx18_set_funcs(struct video_device *vdev)
+{
+       vdev->ioctl_ops = &cx18_ioctl_ops;
 }
index 1728b1d832a9ca2eef5f147553da2e1d97a9e4f3..0da57f583bf75a90207b6b82bd5b762f95c742c6 100644 (file)
@@ -187,14 +187,11 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
                return -ENOMEM;
        }
 
-       s->v4l2dev->type =
-               VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT |
-               VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER;
        snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d",
                        cx->num);
 
        s->v4l2dev->minor = minor;
-       s->v4l2dev->dev = &cx->dev->dev;
+       s->v4l2dev->parent = &cx->dev->dev;
        s->v4l2dev->fops = cx18_stream_info[type].fops;
        s->v4l2dev->release = video_device_release;
        s->v4l2dev->tvnorms = V4L2_STD_ALL;
index 5cfb46bbdaa91a3a28613ef3f1ad5d2d4e48111e..e60bd31b51a359cbc98857383cc76be0cfa0bc51 100644 (file)
@@ -1,9 +1,7 @@
 config VIDEO_CX23885
        tristate "Conexant cx23885 (2388x successor) support"
        depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
-       depends on HOTPLUG      # due to FW_LOADER
        select I2C_ALGOBIT
-       select FW_LOADER
        select VIDEO_BTCX
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
index e7ef093265af0d2275ca149a98355f0423d7949c..8118091568fc62ee711bc88d06c5c193751df4a7 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/cx2341x.h>
 
 #include "cx23885.h"
@@ -1699,14 +1700,7 @@ static struct file_operations mpeg_fops = {
        .llseek        = no_llseek,
 };
 
-static struct video_device cx23885_mpeg_template = {
-       .name          = "cx23885",
-       .type          = VID_TYPE_CAPTURE |
-                               VID_TYPE_TUNER |
-                               VID_TYPE_SCALES |
-                               VID_TYPE_MPEG_ENCODER,
-       .fops          = &mpeg_fops,
-       .minor         = -1,
+static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
        .vidioc_s_std            = vidioc_s_std,
        .vidioc_enum_input       = vidioc_enum_input,
        .vidioc_g_input          = vidioc_g_input,
@@ -1735,6 +1729,13 @@ static struct video_device cx23885_mpeg_template = {
        .vidioc_queryctrl        = vidioc_queryctrl,
 };
 
+static struct video_device cx23885_mpeg_template = {
+       .name          = "cx23885",
+       .fops          = &mpeg_fops,
+       .ioctl_ops     = &mpeg_ioctl_ops,
+       .minor         = -1,
+};
+
 void cx23885_417_unregister(struct cx23885_dev *dev)
 {
        dprintk(1, "%s()\n", __func__);
@@ -1766,7 +1767,7 @@ static struct video_device *cx23885_video_dev_alloc(
        vfd->minor   = -1;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
                type, cx23885_boards[tsport->dev->board].name);
-       vfd->dev     = &pci->dev;
+       vfd->parent  = &pci->dev;
        vfd->release = video_device_release;
        return vfd;
 }
index fd7112c11d35bfc8658628e7ca15d796d7d6c3a9..a19de850955dbacb9c69fa1d1592ed9f1d959291 100644 (file)
@@ -145,6 +145,7 @@ struct cx23885_board cx23885_boards[] = {
        },
        [CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP] = {
                .name           = "DViCO FusionHDTV7 Dual Express",
+               .portb          = CX23885_MPEG_DVB,
                .portc          = CX23885_MPEG_DVB,
        },
 };
@@ -325,25 +326,41 @@ int cx23885_tuner_callback(void *priv, int command, int arg)
 {
        struct cx23885_i2c *bus = priv;
        struct cx23885_dev *dev = bus->dev;
+       u32 bitmask = 0;
+
+       if (command != 0) {
+               printk(KERN_ERR "%s(): Unknown command 0x%x.\n",
+                       __func__, command);
+               return -EINVAL;
+       }
 
        switch(dev->board) {
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
-               if(command == 0) {      /* Tuner Reset Command from xc5000 */
-                       /* Drive the tuner into reset and out */
-                       cx_clear(GP0_IO, 0x00000004);
-                       mdelay(200);
-                       cx_set(GP0_IO, 0x00000004);
-                       return 0;
-               }
-               else {
-                       printk(KERN_ERR
-                               "%s(): Unknow command.\n", __func__);
-                       return -EINVAL;
+               /* Tuner Reset Command from xc5000 */
+               if (command == 0)
+                       bitmask = 0x04;
+               break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+               if (command == 0) {
+
+                       /* Two identical tuners on two different i2c buses,
+                        * we need to reset the correct gpio. */
+                       if (bus->nr == 0)
+                               bitmask = 0x01;
+                       else if (bus->nr == 1)
+                               bitmask = 0x04;
                }
                break;
        }
 
-       return 0; /* Should never be here */
+       if (bitmask) {
+               /* Drive the tuner into reset and back out */
+               cx_clear(GP0_IO, bitmask);
+               mdelay(200);
+               cx_set(GP0_IO, bitmask);
+       }
+
+       return 0;
 }
 
 void cx23885_gpio_setup(struct cx23885_dev *dev)
@@ -435,6 +452,19 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                mdelay(20);
                cx_set(GP0_IO, 0x00050005);
                break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+               /* GPIO-0 xc5000 tuner reset i2c bus 0 */
+               /* GPIO-1 s5h1409 demod reset i2c bus 0 */
+               /* GPIO-2 xc5000 tuner reset i2c bus 1 */
+               /* GPIO-3 s5h1409 demod reset i2c bus 0 */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x000f0000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x0000000f);
+               mdelay(20);
+               cx_set(GP0_IO, 0x000f000f);
+               break;
        }
 }
 
index d17343ea0d33bc097ef9f144bb2c45b83c7f7113..6286a9cf957ef5751492ccf8d8ca8e902a8c8f53 100644 (file)
@@ -76,6 +76,117 @@ LIST_HEAD(cx23885_devlist);
  * 0x00010ea0 0x00010xxx Free
  */
 
+static struct sram_channel cx23885_sram_channels[] = {
+       [SRAM_CH01] = {
+               .name           = "VID A",
+               .cmds_start     = 0x10000,
+               .ctrl_start     = 0x10380,
+               .cdt            = 0x104c0,
+               .fifo_start     = 0x40,
+               .fifo_size      = 0x2800,
+               .ptr1_reg       = DMA1_PTR1,
+               .ptr2_reg       = DMA1_PTR2,
+               .cnt1_reg       = DMA1_CNT1,
+               .cnt2_reg       = DMA1_CNT2,
+       },
+       [SRAM_CH02] = {
+               .name           = "ch2",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA2_PTR1,
+               .ptr2_reg       = DMA2_PTR2,
+               .cnt1_reg       = DMA2_CNT1,
+               .cnt2_reg       = DMA2_CNT2,
+       },
+       [SRAM_CH03] = {
+               .name           = "TS1 B",
+               .cmds_start     = 0x100A0,
+               .ctrl_start     = 0x10400,
+               .cdt            = 0x10580,
+               .fifo_start     = 0x5000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA3_PTR1,
+               .ptr2_reg       = DMA3_PTR2,
+               .cnt1_reg       = DMA3_CNT1,
+               .cnt2_reg       = DMA3_CNT2,
+       },
+       [SRAM_CH04] = {
+               .name           = "ch4",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA4_PTR1,
+               .ptr2_reg       = DMA4_PTR2,
+               .cnt1_reg       = DMA4_CNT1,
+               .cnt2_reg       = DMA4_CNT2,
+       },
+       [SRAM_CH05] = {
+               .name           = "ch5",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA5_PTR1,
+               .ptr2_reg       = DMA5_PTR2,
+               .cnt1_reg       = DMA5_CNT1,
+               .cnt2_reg       = DMA5_CNT2,
+       },
+       [SRAM_CH06] = {
+               .name           = "TS2 C",
+               .cmds_start     = 0x10140,
+               .ctrl_start     = 0x10440,
+               .cdt            = 0x105e0,
+               .fifo_start     = 0x6000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA5_PTR1,
+               .ptr2_reg       = DMA5_PTR2,
+               .cnt1_reg       = DMA5_CNT1,
+               .cnt2_reg       = DMA5_CNT2,
+       },
+       [SRAM_CH07] = {
+               .name           = "ch7",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA6_PTR1,
+               .ptr2_reg       = DMA6_PTR2,
+               .cnt1_reg       = DMA6_CNT1,
+               .cnt2_reg       = DMA6_CNT2,
+       },
+       [SRAM_CH08] = {
+               .name           = "ch8",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA7_PTR1,
+               .ptr2_reg       = DMA7_PTR2,
+               .cnt1_reg       = DMA7_CNT1,
+               .cnt2_reg       = DMA7_CNT2,
+       },
+       [SRAM_CH09] = {
+               .name           = "ch9",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA8_PTR1,
+               .ptr2_reg       = DMA8_PTR2,
+               .cnt1_reg       = DMA8_CNT1,
+               .cnt2_reg       = DMA8_CNT2,
+       },
+};
+
 static struct sram_channel cx23887_sram_channels[] = {
        [SRAM_CH01] = {
                .name           = "VID A",
@@ -104,8 +215,8 @@ static struct sram_channel cx23887_sram_channels[] = {
        [SRAM_CH03] = {
                .name           = "TS1 B",
                .cmds_start     = 0x100A0,
-               .ctrl_start     = 0x10780,
-               .cdt            = 0x10400,
+               .ctrl_start     = 0x10630,
+               .cdt            = 0x10870,
                .fifo_start     = 0x5000,
                .fifo_size      = 0x1000,
                .ptr1_reg       = DMA3_PTR1,
@@ -140,7 +251,7 @@ static struct sram_channel cx23887_sram_channels[] = {
        [SRAM_CH06] = {
                .name           = "TS2 C",
                .cmds_start     = 0x10140,
-               .ctrl_start     = 0x10680,
+               .ctrl_start     = 0x10670,
                .cdt            = 0x108d0,
                .fifo_start     = 0x6000,
                .fifo_size      = 0x1000,
@@ -460,6 +571,7 @@ static void cx23885_reset(struct cx23885_dev *dev)
        cx_write(AUDIO_INT_INT_STAT, 0xffffffff);
        cx_write(AUDIO_EXT_INT_STAT, 0xffffffff);
        cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+       cx_write(PAD_CTRL, 0x00500300);
 
        mdelay(100);
 
@@ -625,7 +737,6 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        atomic_inc(&dev->refcount);
 
        dev->nr = cx23885_devcount++;
-       dev->sram_channels = cx23887_sram_channels;
        sprintf(dev->name, "cx23885[%d]", dev->nr);
 
        mutex_lock(&devlist);
@@ -637,11 +748,13 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
                dev->bridge = CX23885_BRIDGE_887;
                /* Apply a sensible clock frequency for the PCIe bridge */
                dev->clk_freq = 25000000;
+               dev->sram_channels = cx23887_sram_channels;
        } else
        if(dev->pci->device == 0x8852) {
                dev->bridge = CX23885_BRIDGE_885;
                /* Apply a sensible clock frequency for the PCIe bridge */
                dev->clk_freq = 28000000;
+               dev->sram_channels = cx23885_sram_channels;
        } else
                BUG();
 
@@ -1010,8 +1123,9 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
                port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
        dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __func__,
                port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
-       dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __func__,
-               port->reg_src_sel, cx_read(port->reg_src_sel));
+       if (port->reg_src_sel)
+               dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __func__,
+                       port->reg_src_sel, cx_read(port->reg_src_sel));
        dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __func__,
                port->reg_lngth, cx_read(port->reg_lngth));
        dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __func__,
@@ -1042,6 +1156,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
        dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
                buf->vb.width, buf->vb.height, buf->vb.field);
 
+       /* Stop the fifo and risc engine for this port */
+       cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+
        /* setup fifo + format */
        cx23885_sram_channel_setup(dev,
                                   &dev->sram_channels[ port->sram_chno ],
@@ -1083,7 +1200,21 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
        cx_write(port->reg_gpcnt_ctl, 3);
        q->count = 1;
 
-       if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+       /* Set VIDB pins to input */
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+               reg = cx_read(PAD_CTRL);
+               reg &= ~0x3; /* Clear TS1_OE & TS1_SOP_OE */
+               cx_write(PAD_CTRL, reg);
+       }
+
+       /* Set VIDC pins to input */
+       if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+               reg = cx_read(PAD_CTRL);
+               reg &= ~0x4; /* Clear TS2_SOP_OE */
+               cx_write(PAD_CTRL, reg);
+       }
+
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
 
                reg = cx_read(PAD_CTRL);
                reg = reg & ~0x1;    /* Clear TS1_OE */
@@ -1133,7 +1264,7 @@ static int cx23885_stop_dma(struct cx23885_tsport *port)
        cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
        cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
 
-       if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
 
                reg = cx_read(PAD_CTRL);
 
index 043fc4e5c586c82ec547d595a48e8a6ed0580edf..ad2235dab5b1450c1f958973556bce77faf5febf 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "cx23885.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
 /* Include V4L1 specific functions. Should be removed soon */
@@ -326,7 +327,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
                return NULL;
        *vfd = *template;
        vfd->minor   = -1;
-       vfd->dev     = &pci->dev;
+       vfd->parent  = &pci->dev;
        vfd->release = video_device_release;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
                 dev->name, type, cx23885_boards[dev->board].name);
@@ -1433,12 +1434,7 @@ static const struct file_operations video_fops = {
        .llseek        = no_llseek,
 };
 
-static struct video_device cx23885_vbi_template;
-static struct video_device cx23885_video_template = {
-       .name                 = "cx23885-video",
-       .type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
-       .fops                 = &video_fops,
-       .minor                = -1,
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_querycap      = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
@@ -1471,6 +1467,14 @@ static struct video_device cx23885_video_template = {
        .vidioc_g_register    = vidioc_g_register,
        .vidioc_s_register    = vidioc_s_register,
 #endif
+};
+
+static struct video_device cx23885_vbi_template;
+static struct video_device cx23885_video_template = {
+       .name                 = "cx23885-video",
+       .fops                 = &video_fops,
+       .minor                = -1,
+       .ioctl_ops            = &video_ioctl_ops,
        .tvnorms              = CX23885_NORMS,
        .current_norm         = V4L2_STD_NTSC_M,
 };
@@ -1512,7 +1516,6 @@ int cx23885_video_register(struct cx23885_dev *dev)
        memcpy(&cx23885_vbi_template, &cx23885_video_template,
                sizeof(cx23885_vbi_template));
        strcpy(cx23885_vbi_template.name, "cx23885-vbi");
-       cx23885_vbi_template.type = VID_TYPE_TELETEXT|VID_TYPE_TUNER;
 
        dev->tvnorm = cx23885_video_template.current_norm;
 
index 448f4cd0ce345e67f87c024683d7c6ec81dc2549..de515dadadc2e2062f3c655c2821874675d581f1 100644 (file)
@@ -1,8 +1,6 @@
 config VIDEO_CX25840
        tristate "Conexant CX2584x audio/video decoders"
        depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
-       depends on HOTPLUG # due to FW_LOADER
-       select FW_LOADER
        ---help---
          Support for the Conexant CX2584x audio/video decoders.
 
index e7bf4f4c1319a220f448f4b352aaace26e92c5c4..209d3bcb5dbb9a3de89978117aeaf336862ae111 100644 (file)
@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL");
 
 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
 
-int cx25840_debug;
+static int cx25840_debug;
 
 module_param_named(debug,cx25840_debug, int, 0644);
 
index 72916ba975a8a24108773a2f9487703114c414d4..b87337e590b43334a3b4b345ede4199ea5ae1924 100644 (file)
@@ -24,8 +24,6 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 
-extern int cx25840_debug;
-
 /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is
    present in Hauppauge PVR-150 (and possibly PVR-500) cards that have
    certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The
index 10e20d8196dcfcf8cdb890269303dc43e600440e..9dd7bdf659b96a066d05dee8d6f87d0dcc4e85ed 100644 (file)
@@ -33,9 +33,8 @@ config VIDEO_CX88_ALSA
 
 config VIDEO_CX88_BLACKBIRD
        tristate "Blackbird MPEG encoder support (cx2388x + cx23416)"
-       depends on VIDEO_CX88 && HOTPLUG
+       depends on VIDEO_CX88
        select VIDEO_CX2341X
-       select FW_LOADER
        ---help---
          This adds support for MPEG encoder cards based on the
          Blackbird reference design, using the Conexant 2388x
index bfdca5847764fde66852c48a5ab85712d8340a63..9a1374a38ec75a315463c02e83f5c6ad113b6fb4 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/cx2341x.h>
 
 #include "cx88.h"
@@ -1174,12 +1175,7 @@ static const struct file_operations mpeg_fops =
        .llseek        = no_llseek,
 };
 
-static struct video_device cx8802_mpeg_template =
-{
-       .name                 = "cx8802",
-       .type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
-       .fops                 = &mpeg_fops,
-       .minor                = -1,
+static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
        .vidioc_querymenu     = vidioc_querymenu,
        .vidioc_querycap      = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
@@ -1207,6 +1203,13 @@ static struct video_device cx8802_mpeg_template =
        .vidioc_g_tuner       = vidioc_g_tuner,
        .vidioc_s_tuner       = vidioc_s_tuner,
        .vidioc_s_std         = vidioc_s_std,
+};
+
+static struct video_device cx8802_mpeg_template = {
+       .name                 = "cx8802",
+       .fops                 = &mpeg_fops,
+       .ioctl_ops            = &mpeg_ioctl_ops,
+       .minor                = -1,
        .tvnorms              = CX88_NORMS,
        .current_norm         = V4L2_STD_NTSC_M,
 };
index fa6d398e97b9f44015527027e43771ad2de1ac79..de199a206a152bdc7e9a9fa381f2c623fd76a775 100644 (file)
@@ -1348,7 +1348,7 @@ static const struct cx88_board cx88_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
-               .audio_chip     = AUDIO_CHIP_WM8775,
+               .audio_chip     = V4L2_IDENT_WM8775,
                .input          = {{
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
index 60eeda3057e9e8552bf0bb5361987e6f8d7b04d7..d656fec5901086469fb750eeced37588b7702ccc 100644 (file)
@@ -40,6 +40,7 @@
 
 #include "cx88.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -1006,7 +1007,7 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
                return NULL;
        *vfd = *template;
        vfd->minor   = -1;
-       vfd->dev     = &pci->dev;
+       vfd->parent  = &pci->dev;
        vfd->release = video_device_release;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
                 core->name, type, core->board.name);
index 0fed5cd2cceaa7caa808afba923e70e47c765b8f..ef4d56ea00278bf4183ac932fd7f46edda8b1618 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "cx88.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
 /* Include V4L1 specific functions. Should be removed soon */
@@ -447,7 +448,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
                   the initialization. Some boards may use different
                   routes for different inputs. HVR-1300 surely does */
                if (core->board.audio_chip &&
-                   core->board.audio_chip == AUDIO_CHIP_WM8775) {
+                   core->board.audio_chip == V4L2_IDENT_WM8775) {
                        struct v4l2_routing route;
 
                        route.input = INPUT(input).audioroute;
@@ -1682,13 +1683,7 @@ static const struct file_operations video_fops =
        .llseek        = no_llseek,
 };
 
-static struct video_device cx8800_vbi_template;
-static struct video_device cx8800_video_template =
-{
-       .name                 = "cx8800-video",
-       .type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
-       .fops                 = &video_fops,
-       .minor                = -1,
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_querycap      = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
@@ -1721,6 +1716,15 @@ static struct video_device cx8800_video_template =
        .vidioc_g_register    = vidioc_g_register,
        .vidioc_s_register    = vidioc_s_register,
 #endif
+};
+
+static struct video_device cx8800_vbi_template;
+
+static struct video_device cx8800_video_template = {
+       .name                 = "cx8800-video",
+       .fops                 = &video_fops,
+       .minor                = -1,
+       .ioctl_ops            = &video_ioctl_ops,
        .tvnorms              = CX88_NORMS,
        .current_norm         = V4L2_STD_NTSC_M,
 };
@@ -1735,12 +1739,7 @@ static const struct file_operations radio_fops =
        .llseek        = no_llseek,
 };
 
-static struct video_device cx8800_radio_template =
-{
-       .name                 = "cx8800-radio",
-       .type                 = VID_TYPE_TUNER,
-       .fops                 = &radio_fops,
-       .minor                = -1,
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
        .vidioc_querycap      = radio_querycap,
        .vidioc_g_tuner       = radio_g_tuner,
        .vidioc_enum_input    = radio_enum_input,
@@ -1759,6 +1758,13 @@ static struct video_device cx8800_radio_template =
 #endif
 };
 
+static struct video_device cx8800_radio_template = {
+       .name                 = "cx8800-radio",
+       .fops                 = &radio_fops,
+       .minor                = -1,
+       .ioctl_ops            = &radio_ioctl_ops,
+};
+
 /* ----------------------------------------------------------- */
 
 static void cx8800_unregister_video(struct cx8800_dev *dev)
@@ -1830,7 +1836,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
        memcpy( &cx8800_vbi_template, &cx8800_video_template,
                sizeof(cx8800_vbi_template) );
        strcpy(cx8800_vbi_template.name,"cx8800-vbi");
-       cx8800_vbi_template.type = VID_TYPE_TELETEXT|VID_TYPE_TUNER;
 
        /* initialize driver struct */
        spin_lock_init(&dev->slock);
@@ -1866,7 +1871,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
 
        /* load and configure helper modules */
 
-       if (core->board.audio_chip == AUDIO_CHIP_WM8775)
+       if (core->board.audio_chip == V4L2_IDENT_WM8775)
                request_module("wm8775");
 
        switch (core->boardnr) {
index 14ac173f40711e66ca3a2ad51a82dc7c4c222a7d..54fe650947115e490c6334ff489451e5f98576ca 100644 (file)
@@ -29,8 +29,8 @@
 #include <media/tuner.h>
 #include <media/tveeprom.h>
 #include <media/videobuf-dma-sg.h>
+#include <media/v4l2-chip-ident.h>
 #include <media/cx2341x.h>
-#include <media/audiochip.h>
 #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
 #include <media/videobuf-dvb.h>
 #endif
@@ -252,7 +252,7 @@ struct cx88_board {
        struct cx88_input       input[MAX_CX88_INPUT];
        struct cx88_input       radio;
        enum cx88_board_type    mpeg;
-       enum audiochip          audio_chip;
+       unsigned int            audio_chip;
 };
 
 struct cx88_subid {
index 05f0d5a1505843edcdad70beec452456a52d17dd..476ae44a62d2225ab076bd5c01328c3243955f96 100644 (file)
@@ -32,8 +32,8 @@
 #include <media/saa7115.h>
 #include <media/tvp5150.h>
 #include <media/tveeprom.h>
-#include <media/audiochip.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
 
 #include "em28xx.h"
 
@@ -52,6 +52,15 @@ struct em28xx_hash_table {
 };
 
 struct em28xx_board em28xx_boards[] = {
+       [EM2750_BOARD_UNKNOWN] = {
+               .name          = "Unknown EM2750/EM2751 webcam grabber",
+               .vchannels     = 1,
+               .input         = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = 0,
+               } },
+       },
        [EM2800_BOARD_UNKNOWN] = {
                .name         = "Unknown EM2800 video grabber",
                .is_em2800    = 1,
@@ -73,6 +82,39 @@ struct em28xx_board em28xx_boards[] = {
                .is_em2800    = 0,
                .tuner_type   = TUNER_ABSENT,
        },
+       [EM2750_BOARD_DLCW_130] = {
+               /* Beijing Huaqi Information Digital Technology Co., Ltd */
+               .name          = "Huaqi DLCW-130",
+               .valid         = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels     = 1,
+               .input         = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = 0,
+               } },
+       },
+       [EM2800_BOARD_KWORLD_USB2800] = {
+               .name         = "Kworld USB2800",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .is_em2800    = 1,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_PHILIPS_FCV1236D,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
        [EM2820_BOARD_KWORLD_PVRTV2800RF] = {
                .name         = "Kworld PVR TV 2800 RF",
                .is_em2800    = 0,
@@ -151,13 +193,251 @@ struct em28xx_board em28xx_boards[] = {
                                        MSP_DSP_IN_SCART, MSP_DSP_IN_SCART),
                } },
        },
-       [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
-               .name         = "Hauppauge WinTV HVR 900",
+       [EM2820_BOARD_DLINK_USB_TV] = {
+               .name         = "D-Link DUB-T210 TV Tuner",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .is_em2800    = 0,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2820_BOARD_HERCULES_SMART_TV_USB2] = {
+               .name         = "Hercules Smart TV USB 2.0",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2820_BOARD_PINNACLE_USB_2_FM1216ME] = {
+               .name         = "Pinnacle PCTV USB 2 (Philips FM1216ME)",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .is_em2800    = 0,
+               .tuner_type   = TUNER_PHILIPS_FM1216ME_MK3,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2820_BOARD_GADMEI_UTV310] = {
+               .name         = "Gadmei UTV310",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_TNF_5335MF,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE] = {
+               .name         = "Leadtek Winfast USB II Deluxe",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_PHILIPS_FM1216ME_MK3,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7114,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = 2,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = 9,
+                       .amux     = 1,
+               } },
+       },
+       [EM2820_BOARD_PINNACLE_DVC_100] = {
+               .name         = "Pinnacle Dazzle DVC 100",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = {
+               .name          = "Videology 20K14XUSB USB2.0",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels     = 1,
+               .input         = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = 0,
+               } },
+       },
+       [EM2821_BOARD_PROLINK_PLAYTV_USB2] = {
+               .name         = "SIIG AVTuner-PVR/Prolink PlayTV USB 2.0",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .is_em2800    = 0,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,  /* unknown? */
+               .tda9887_conf = TDA9887_PRESENT,        /* unknown? */
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2821_BOARD_SUPERCOMP_USB_2] = {
+               .name         = "Supercomp USB 2.0 TV",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .is_em2800    = 0,
+               .tuner_type   = TUNER_PHILIPS_FM1236_MK3,
+               .tda9887_conf = TDA9887_PRESENT |
+                               TDA9887_PORT1_ACTIVE |
+                               TDA9887_PORT2_ACTIVE,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2821_BOARD_USBGEAR_VD204] = {
+               .name          = "Usbgear VD204v9",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels     = 2,
+               .decoder       = EM28XX_SAA7113,
+               .input          = { {
+                       .type  = EM28XX_VMUX_COMPOSITE1,
+                       .vmux  = SAA7115_COMPOSITE0,
+                       .amux  = 1,
+               }, {
+                       .type  = EM28XX_VMUX_SVIDEO,
+                       .vmux  = SAA7115_SVIDEO3,
+                       .amux  = 1,
+               } },
+       },
+       [EM2860_BOARD_NETGMBH_CAM] = {
+               /* Beijing Huaqi Information Digital Technology Co., Ltd */
+               .name          = "NetGMBH Cam",
+               .valid       = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels     = 1,
+               .input         = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = 0,
+               } },
+       },
+       [EM2860_BOARD_TYPHOON_DVD_MAKER] = {
+               .name          = "Typhoon DVD Maker",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels     = 2,
+               .decoder       = EM28XX_SAA7113,
+               .input          = { {
+                       .type  = EM28XX_VMUX_COMPOSITE1,
+                       .vmux  = SAA7115_COMPOSITE0,
+                       .amux  = 1,
+               }, {
+                       .type  = EM28XX_VMUX_SVIDEO,
+                       .vmux  = SAA7115_SVIDEO3,
+                       .amux  = 1,
+               } },
+       },
+       [EM2860_BOARD_GADMEI_UTV330] = {
+               .name         = "Gadmei UTV330",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
+               .tuner_type   = TUNER_TNF_5335MF,
                .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2860_BOARD_TERRATEC_HYBRID_XS] = {
+               .name         = "Terratec Cinergy A Hybrid XS",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
                .tuner_type   = TUNER_XC2028,
-               .mts_firmware = 1,
-               .has_dvb        = 1,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -173,12 +453,101 @@ struct em28xx_board em28xx_boards[] = {
                        .amux     = 1,
                } },
        },
-       [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = {
-               .name         = "Hauppauge WinTV HVR 900 (R2)",
+       [EM2861_BOARD_KWORLD_PVRTV_300U] = {
+               .name         = "KWorld PVRTV 300U",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       [EM2861_BOARD_YAKUMO_MOVIE_MIXER] = {
+               .name          = "Yakumo MovieMixer",
+               .valid       = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels     = 1,
+               .decoder       = EM28XX_TVP5150,
+               .input         = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       [EM2861_BOARD_PLEXTOR_PX_TV100U] = {
+               .name         = "Plextor ConvertX PX-TV100U",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
+               .tuner_type   = TUNER_TNF_5335MF,
                .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       [EM2870_BOARD_TERRATEC_XS] = {
+               .name         = "Terratec Cinergy T XS",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_XC2028,
+       },
+       [EM2870_BOARD_TERRATEC_XS_MT2060] = {
+               .name         = "Terratec Cinergy T XS (MT2060)",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT, /* MT2060 */
+       },
+       [EM2870_BOARD_KWORLD_350U] = {
+               .name         = "Kworld 350 U DVB-T",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_XC2028,
+       },
+       [EM2870_BOARD_KWORLD_355U] = {
+               .name         = "Kworld 355 U DVB-T",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+       },
+       [EM2870_BOARD_PINNACLE_PCTV_DVB] = {
+               .name         = "Pinnacle PCTV DVB-T",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT, /* MT2060 */
+       },
+       [EM2870_BOARD_COMPRO_VIDEOMATE] = {
+               .name         = "Compro, VideoMate U3",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT, /* MT2060 */
+       },
+       [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = {
+               .name         = "Terratec Hybrid XS Secam",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .has_msp34xx  = 1,
                .tuner_type   = TUNER_XC2028,
-               .mts_firmware = 1,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -194,8 +563,97 @@ struct em28xx_board em28xx_boards[] = {
                        .amux     = 1,
                } },
        },
-       [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950] = {
-               .name           = "Hauppauge WinTV HVR 950",
+       [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
+               .name         = "Hauppauge WinTV HVR 900",
+               .vchannels    = 3,
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_XC2028,
+               .mts_firmware = 1,
+               .has_dvb        = 1,
+               .decoder      = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = {
+               .name         = "Hauppauge WinTV HVR 900 (R2)",
+               .vchannels    = 3,
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_XC2028,
+               .mts_firmware = 1,
+               .decoder      = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = {
+               .name           = "Hauppauge WinTV HVR 950",
+               .vchannels      = 3,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .tuner_type     = TUNER_XC2028,
+               .mts_firmware   = 1,
+               .has_12mhz_i2s  = 1,
+               .has_dvb        = 1,
+               .decoder        = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = {
+               .name           = "Pinnacle PCTV HD Pro Stick",
+               .vchannels      = 3,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .tuner_type     = TUNER_XC2028,
+               .mts_firmware   = 1,
+               .has_12mhz_i2s  = 1,
+               .has_dvb        = 1,
+               .decoder        = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = {
+               .name           = "AMD ATI TV Wonder HD 600",
                .vchannels      = 3,
                .tda9887_conf   = TDA9887_PRESENT,
                .tuner_type     = TUNER_XC2028,
@@ -217,15 +675,247 @@ struct em28xx_board em28xx_boards[] = {
                        .amux     = 1,
                } },
        },
-       [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = {
-               .name           = "Pinnacle PCTV HD Pro Stick",
-               .vchannels      = 3,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .tuner_type     = TUNER_XC2028,
-               .mts_firmware   = 1,
-               .has_12mhz_i2s  = 1,
-               .has_dvb        = 1,
-               .decoder        = EM28XX_TVP5150,
+       [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
+               .name         = "Terratec Hybrid XS",
+               .vchannels    = 3,
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
+               .has_dvb        = 1,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       /* maybe there's a reason behind it why Terratec sells the Hybrid XS
+          as Prodigy XS with a different PID, let's keep it separated for now
+          maybe we'll need it lateron */
+       [EM2880_BOARD_TERRATEC_PRODIGY_XS] = {
+               .name         = "Terratec Prodigy XS",
+               .vchannels    = 3,
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       [EM2820_BOARD_MSI_VOX_USB_2] = {
+               .name              = "MSI VOX USB 2.0",
+               .vchannels         = 3,
+               .tuner_type        = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf      = TDA9887_PRESENT      |
+                                    TDA9887_PORT1_ACTIVE |
+                                    TDA9887_PORT2_ACTIVE,
+               .max_range_640_480 = 1,
+
+               .decoder           = EM28XX_SAA7114,
+               .input             = { {
+                       .type      = EM28XX_VMUX_TELEVISION,
+                       .vmux      = SAA7115_COMPOSITE4,
+                       .amux      = 0,
+               }, {
+                       .type      = EM28XX_VMUX_COMPOSITE1,
+                       .vmux      = SAA7115_COMPOSITE0,
+                       .amux      = 1,
+               }, {
+                       .type      = EM28XX_VMUX_SVIDEO,
+                       .vmux      = SAA7115_SVIDEO3,
+                       .amux      = 1,
+               } },
+       },
+       [EM2800_BOARD_TERRATEC_CINERGY_200] = {
+               .name         = "Terratec Cinergy 200 USB",
+               .is_em2800    = 1,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2800_BOARD_GRABBEEX_USB2800] = {
+               .name         = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder",
+               .is_em2800    = 1,
+               .vchannels    = 2,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2800_BOARD_LEADTEK_WINFAST_USBII] = {
+               .name         = "Leadtek Winfast USB II",
+               .is_em2800    = 1,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2800_BOARD_KWORLD_USB2800] = {
+               .name         = "Kworld USB2800",
+               .is_em2800    = 1,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_PHILIPS_FCV1236D,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2820_BOARD_PINNACLE_DVC_90] = {
+               .name         = "Pinnacle Dazzle DVC 90/DVC 100",
+               .vchannels    = 3,
+               .tuner_type   = TUNER_ABSENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2800_BOARD_VGEAR_POCKETTV] = {
+               .name         = "V-Gear PocketTV",
+               .is_em2800    = 1,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 1,
+               } },
+       },
+       [EM2820_BOARD_PROLINK_PLAYTV_USB2] = {
+               .name         = "Pixelview Prolink PlayTV USB 2.0",
+               .vchannels    = 3,
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_YMEC_TVF_5533MF,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA] = {
+               .name         = "PointNix Intra-Oral Camera",
+               .has_snapshot_button = 1,
+               .vchannels    = 1,
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_ABSENT,
+               .decoder      = EM28XX_SAA7113,
+               .input          = { {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = 0,
+               } },
+       },
+       [EM2880_BOARD_MSI_DIGIVOX_AD] = {
+               .name         = "MSI DigiVox A/D",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
+               } },
+       },
+       [EM2880_BOARD_MSI_DIGIVOX_AD_II] = {
+               .name         = "MSI DigiVox A/D II",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .vchannels    = 3,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
                        .vmux     = TVP5150_COMPOSITE0,
@@ -240,10 +930,10 @@ struct em28xx_board em28xx_boards[] = {
                        .amux     = 1,
                } },
        },
-       [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
-               .name         = "Terratec Hybrid XS",
+       [EM2880_BOARD_KWORLD_DVB_305U] = {
+               .name         = "KWorld DVB-T 305U",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
-               .tda9887_conf = TDA9887_PRESENT,
                .tuner_type   = TUNER_XC2028,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
@@ -260,13 +950,10 @@ struct em28xx_board em28xx_boards[] = {
                        .amux     = 1,
                } },
        },
-       /* maybe there's a reason behind it why Terratec sells the Hybrid XS
-          as Prodigy XS with a different PID, let's keep it separated for now
-          maybe we'll need it lateron */
-       [EM2880_BOARD_TERRATEC_PRODIGY_XS] = {
-               .name         = "Terratec Prodigy XS",
+       [EM2880_BOARD_KWORLD_DVB_310U] = {
+               .name         = "KWorld DVB-T 310U",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
-               .tda9887_conf = TDA9887_PRESENT,
                .tuner_type   = TUNER_XC2028,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
@@ -283,160 +970,141 @@ struct em28xx_board em28xx_boards[] = {
                        .amux     = 1,
                } },
        },
-       [EM2820_BOARD_MSI_VOX_USB_2] = {
-               .name              = "MSI VOX USB 2.0",
-               .vchannels         = 3,
-               .tuner_type        = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf      = TDA9887_PRESENT      |
-                                    TDA9887_PORT1_ACTIVE |
-                                    TDA9887_PORT2_ACTIVE,
-               .max_range_640_480 = 1,
-
-               .decoder           = EM28XX_SAA7114,
-               .input             = { {
-                       .type      = EM28XX_VMUX_TELEVISION,
-                       .vmux      = SAA7115_COMPOSITE4,
-                       .amux      = 0,
-               }, {
-                       .type      = EM28XX_VMUX_COMPOSITE1,
-                       .vmux      = SAA7115_COMPOSITE0,
-                       .amux      = 1,
-               }, {
-                       .type      = EM28XX_VMUX_SVIDEO,
-                       .vmux      = SAA7115_SVIDEO3,
-                       .amux      = 1,
-               } },
-       },
-       [EM2800_BOARD_TERRATEC_CINERGY_200] = {
-               .name         = "Terratec Cinergy 200 USB",
-               .is_em2800    = 1,
+       [EM2881_BOARD_DNT_DA2_HYBRID] = {
+               .name         = "DNT DA2 Hybrid",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA7113,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
+                       .vmux     = TVP5150_COMPOSITE0,
                        .amux     = 0,
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
+                       .vmux     = TVP5150_COMPOSITE1,
                        .amux     = 1,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
+                       .vmux     = TVP5150_SVIDEO,
                        .amux     = 1,
                } },
        },
-       [EM2800_BOARD_LEADTEK_WINFAST_USBII] = {
-               .name         = "Leadtek Winfast USB II",
-               .is_em2800    = 1,
+       [EM2881_BOARD_PINNACLE_HYBRID_PRO] = {
+               .name         = "Pinnacle Hybrid Pro",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA7113,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
+                       .vmux     = TVP5150_COMPOSITE0,
                        .amux     = 0,
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
+                       .vmux     = TVP5150_COMPOSITE1,
                        .amux     = 1,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
+                       .vmux     = TVP5150_SVIDEO,
                        .amux     = 1,
                } },
        },
-       [EM2800_BOARD_KWORLD_USB2800] = {
-               .name         = "Kworld USB2800",
-               .is_em2800    = 1,
+       [EM2882_BOARD_PINNACLE_HYBRID_PRO] = {
+               .name         = "Pinnacle Hybrid Pro (2)",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
-               .tuner_type   = TUNER_PHILIPS_FCV1236D,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA7113,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
+                       .vmux     = TVP5150_COMPOSITE0,
                        .amux     = 0,
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
+                       .vmux     = TVP5150_COMPOSITE1,
                        .amux     = 1,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
+                       .vmux     = TVP5150_SVIDEO,
                        .amux     = 1,
                } },
        },
-       [EM2820_BOARD_PINNACLE_DVC_90] = {
-               .name         = "Pinnacle Dazzle DVC 90/DVC 100",
+       [EM2882_BOARD_KWORLD_VS_DVBT] = {
+               .name         = "Kworld VS-DVB-T 323UR",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
-               .tuner_type   = TUNER_ABSENT,
-               .decoder      = EM28XX_SAA7113,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
                .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
+               }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
+                       .vmux     = TVP5150_COMPOSITE1,
                        .amux     = 1,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
+                       .vmux     = TVP5150_SVIDEO,
                        .amux     = 1,
                } },
        },
-       [EM2800_BOARD_VGEAR_POCKETTV] = {
-               .name         = "V-Gear PocketTV",
-               .is_em2800    = 1,
+       [EM2882_BOARD_TERRATEC_HYBRID_XS] = {
+               .name         = "Terratec Hybrid XS (em2882)",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA7113,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
+                       .vmux     = TVP5150_COMPOSITE0,
                        .amux     = 0,
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
+                       .vmux     = TVP5150_COMPOSITE1,
                        .amux     = 1,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
+                       .vmux     = TVP5150_SVIDEO,
                        .amux     = 1,
                } },
        },
-       [EM2820_BOARD_PROLINK_PLAYTV_USB2] = {
-               .name         = "Pixelview Prolink PlayTV USB 2.0",
+       [EM2883_BOARD_KWORLD_HYBRID_A316] = {
+               .name         = "Kworld PlusTV HD Hybrid 330",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
-               .tda9887_conf = TDA9887_PRESENT,
-               .tuner_type   = TUNER_YMEC_TVF_5533MF,
-               .decoder      = EM28XX_SAA7113,
+               .is_em2800    = 0,
+               .tuner_type   = TUNER_XC2028,
+               .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = 0,
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = 1,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = 1,
                } },
        },
-       [EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA] = {
-               .name         = "PointNix Intra-Oral Camera",
-               .has_snapshot_button = 1,
-               .vchannels    = 1,
+       [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = {
+               .name         = "Compro VideoMate ForYou/Stereo",
+               .vchannels    = 2,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
                .tda9887_conf = TDA9887_PRESENT,
-               .tuner_type   = TUNER_ABSENT,
-               .decoder      = EM28XX_SAA7113,
+               .decoder      = EM28XX_TVP5150,
                .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = 0,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
                } },
        },
 };
@@ -445,7 +1113,9 @@ const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
 /* table of devices that work with this driver */
 struct usb_device_id em28xx_id_table [] = {
        { USB_DEVICE(0xeb1a, 0x2750),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
+                       .driver_info = EM2750_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2751),
+                       .driver_info = EM2750_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2800),
                        .driver_info = EM2800_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2820),
@@ -462,36 +1132,78 @@ struct usb_device_id em28xx_id_table [] = {
                        .driver_info = EM2820_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2883),
                        .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0xe300),
+                       .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U },
+       { USB_DEVICE(0xeb1a, 0xe305),
+                       .driver_info = EM2880_BOARD_KWORLD_DVB_305U },
+       { USB_DEVICE(0xeb1a, 0xe310),
+                       .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD },
+       { USB_DEVICE(0xeb1a, 0xa316),
+                       .driver_info = EM2883_BOARD_KWORLD_HYBRID_A316 },
+       { USB_DEVICE(0xeb1a, 0xe320),
+                       .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II },
+       { USB_DEVICE(0xeb1a, 0xe323),
+                       .driver_info = EM2882_BOARD_KWORLD_VS_DVBT },
+       { USB_DEVICE(0xeb1a, 0xe350),
+                       .driver_info = EM2870_BOARD_KWORLD_350U },
+       { USB_DEVICE(0xeb1a, 0xe355),
+                       .driver_info = EM2870_BOARD_KWORLD_355U },
+       { USB_DEVICE(0xeb1a, 0x2801),
+                       .driver_info = EM2800_BOARD_GRABBEEX_USB2800 },
+       { USB_DEVICE(0xeb1a, 0xe357),
+                       .driver_info = EM2870_BOARD_KWORLD_355U },
        { USB_DEVICE(0x0ccd, 0x0036),
                        .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 },
-       { USB_DEVICE(0x2304, 0x0208),
-                       .driver_info = EM2820_BOARD_PINNACLE_USB_2 },
+       { USB_DEVICE(0x0ccd, 0x004c),
+                       .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS_FR },
+       { USB_DEVICE(0x0ccd, 0x004f),
+                       .driver_info = EM2860_BOARD_TERRATEC_HYBRID_XS },
+       { USB_DEVICE(0x0ccd, 0x005e),
+                       .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
+       { USB_DEVICE(0x0ccd, 0x0042),
+                       .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS },
+       { USB_DEVICE(0x0ccd, 0x0043),
+                       .driver_info = EM2870_BOARD_TERRATEC_XS },
+       { USB_DEVICE(0x0ccd, 0x0047),
+                       .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS },
+       { USB_DEVICE(0x185b, 0x2870),
+                       .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE },
+       { USB_DEVICE(0x185b, 0x2041),
+                       .driver_info = EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU },
        { USB_DEVICE(0x2040, 0x4200),
                        .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
        { USB_DEVICE(0x2040, 0x4201),
                        .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
-       { USB_DEVICE(0x2304, 0x0207),
-                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
-       { USB_DEVICE(0x2304, 0x021a),
-                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
-       { USB_DEVICE(0x2304, 0x0227),
-                       .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
        { USB_DEVICE(0x2040, 0x6500),
                        .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
        { USB_DEVICE(0x2040, 0x6502),
                        .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 },
        { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */
-                       .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
        { USB_DEVICE(0x2040, 0x6517), /* HP  HVR-950 */
-                       .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
        { USB_DEVICE(0x2040, 0x651b), /* RP  HVR-950 */
-                       .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
        { USB_DEVICE(0x2040, 0x651f), /* HCW HVR-850 */
-                       .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
-       { USB_DEVICE(0x0ccd, 0x0042),
-                       .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS },
-       { USB_DEVICE(0x0ccd, 0x0047),
-                       .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS },
+                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+       { USB_DEVICE(0x0438, 0xb002),
+                       .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 },
+       { USB_DEVICE(0x2001, 0xf112),
+                       .driver_info = EM2820_BOARD_DLINK_USB_TV },
+       { USB_DEVICE(0x2304, 0x0207),
+                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
+       { USB_DEVICE(0x2304, 0x0208),
+                       .driver_info = EM2820_BOARD_PINNACLE_USB_2 },
+       { USB_DEVICE(0x2304, 0x021a),
+                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
+       { USB_DEVICE(0x2304, 0x0226),
+                       .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO },
+       { USB_DEVICE(0x2304, 0x0227),
+                       .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
+       { USB_DEVICE(0x0413, 0x6023),
+                       .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII },
+       { USB_DEVICE(0x093b, 0xa005),
+                       .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U },
        { },
 };
 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -500,6 +1212,18 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table);
  *  Reset sequences for analog/digital modes
  */
 
+/* Reset for the most [analog] boards */
+static struct em28xx_reg_seq default_analog[] = {
+       {EM28XX_R08_GPIO,       0x6d,   ~EM_GPIO_4,     10},
+       {       -1,             -1,     -1,             -1},
+};
+
+/* Reset for the most [digital] boards */
+static struct em28xx_reg_seq default_digital[] = {
+       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
+       {       -1,             -1,     -1,             -1},
+};
+
 /* Board Hauppauge WinTV HVR 900 analog */
 static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
        {EM28XX_R08_GPIO,       0x2d,   ~EM_GPIO_4,     10},
@@ -515,14 +1239,42 @@ static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
        { -1,                   -1,     -1,             -1},
 };
 
-/* Board Hauppauge WinTV HVR 900 tuner_callback */
-static struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = {
+/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */
+static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = {
+       {EM28XX_R08_GPIO,       0x69,   ~EM_GPIO_4,      10},
+       {       -1,             -1,     -1,              -1},
+};
+
+/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */
+static struct em28xx_reg_seq em2880_msi_digivox_ad_digital[] = {
+       {EM28XX_R08_GPIO,       0x6a,   ~EM_GPIO_4,     10},
+       {       -1,             -1,     -1,             -1},
+};
+
+/* Board  - EM2870 Kworld 355u
+   Analog - No input analog */
+static struct em28xx_reg_seq em2870_kworld_355u_digital[] = {
+       {EM2880_R04_GPO,        0x01,   0xff,           10},
+       {  -1,                  -1,     -1,             -1},
+};
+
+/* Callback for the most boards */
+static struct em28xx_reg_seq default_callback[] = {
        {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
        {EM28XX_R08_GPIO,       0,              EM_GPIO_4,      10},
        {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
        {  -1,                  -1,             -1,             -1},
 };
 
+/* Callback for EM2882 TERRATEC HYBRID XS */
+static struct em28xx_reg_seq em2882_terratec_hybrid_xs_digital[] = {
+       {EM28XX_R08_GPIO,       0x2e,   0xff,              6},
+       {EM28XX_R08_GPIO,       0x3e,   ~EM_GPIO_4,        6},
+       {EM2880_R04_GPO,        0x04,   0xff,             10},
+       {EM2880_R04_GPO,        0x0c,   0xff,             10},
+       {  -1,                  -1,     -1,               -1},
+};
+
 /*
  * EEPROM hash table for devices with generic USB IDs
  */
@@ -569,6 +1321,7 @@ static void em28xx_set_model(struct em28xx *dev)
        dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
        dev->has_dvb = em28xx_boards[dev->model].has_dvb;
        dev->has_snapshot_button = em28xx_boards[dev->model].has_snapshot_button;
+       dev->valid = em28xx_boards[dev->model].valid;
 }
 
 /* Since em28xx_pre_card_setup() requires a proper dev->model,
@@ -604,19 +1357,171 @@ void em28xx_pre_card_setup(struct em28xx *dev)
        case EM2880_BOARD_TERRATEC_PRODIGY_XS:
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
-       case EM2880_BOARD_TERRATEC_HYBRID_XS:
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+       case EM2860_BOARD_TERRATEC_HYBRID_XS:
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
        case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
+       case EM2882_BOARD_PINNACLE_HYBRID_PRO:
+       case EM2883_BOARD_KWORLD_HYBRID_A316:
+       case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK,    "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               msleep(50);
+
+               /* Sets GPO/GPIO sequences for this device */
+               dev->analog_gpio      = hauppauge_wintv_hvr_900_analog;
+               dev->digital_gpio     = hauppauge_wintv_hvr_900_digital;
+               dev->tun_analog_gpio  = default_callback;
+               dev->tun_digital_gpio = default_callback;
+               break;
+
+       case EM2882_BOARD_TERRATEC_HYBRID_XS:
                em28xx_write_regs(dev, EM28XX_R0F_XCLK,    "\x27", 1);
                em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
                msleep(50);
 
+               /* should be added ir_codes here */
+
                /* Sets GPO/GPIO sequences for this device */
                dev->analog_gpio      = hauppauge_wintv_hvr_900_analog;
                dev->digital_gpio     = hauppauge_wintv_hvr_900_digital;
-               dev->tun_analog_gpio  = hauppauge_wintv_hvr_900_tuner_callback;
-               dev->tun_digital_gpio = hauppauge_wintv_hvr_900_tuner_callback;
+               dev->tun_analog_gpio  = default_callback;
+               dev->tun_digital_gpio = em2882_terratec_hybrid_xs_digital;
+               break;
+
+       case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
+       case EM2880_BOARD_TERRATEC_HYBRID_XS:
+       case EM2870_BOARD_TERRATEC_XS:
+       case EM2881_BOARD_PINNACLE_HYBRID_PRO:
+       case EM2880_BOARD_KWORLD_DVB_310U:
+       case EM2870_BOARD_KWORLD_350U:
+       case EM2881_BOARD_DNT_DA2_HYBRID:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK,    "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               msleep(50);
+
+               /* NOTE: EM2881_DNT_DA2_HYBRID spend 140 msleep for digital
+                        and analog commands. If this commands doesn't work,
+                        add this timer. */
+
+               /* Sets GPO/GPIO sequences for this device */
+               dev->analog_gpio      = default_analog;
+               dev->digital_gpio     = default_digital;
+               dev->tun_analog_gpio  = default_callback;
+               dev->tun_digital_gpio = default_callback;
+               break;
+
+       case EM2880_BOARD_MSI_DIGIVOX_AD:
+       case EM2880_BOARD_MSI_DIGIVOX_AD_II:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK,    "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               msleep(50);
+
+               /* Sets GPO/GPIO sequences for this device */
+               dev->analog_gpio      = em2880_msi_digivox_ad_analog;
+               dev->digital_gpio     = em2880_msi_digivox_ad_digital;
+               dev->tun_analog_gpio  = default_callback;
+               dev->tun_digital_gpio = default_callback;
+               break;
+
+       case EM2750_BOARD_UNKNOWN:
+       case EM2750_BOARD_DLCW_130:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x0a", 1);
+               break;
+
+       case EM2861_BOARD_PLEXTOR_PX_TV100U:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               /* FIXME guess */
+               /* Turn on analog audio output */
+               em28xx_write_regs_req(dev, 0x00, 0x08, "\xfd", 1);
+               break;
+
+       case EM2861_BOARD_KWORLD_PVRTV_300U:
+       case EM2880_BOARD_KWORLD_DVB_305U:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x4c", 1);
+               msleep(10);
+               em28xx_write_regs(dev, 0x08, "\x6d", 1);
+               msleep(10);
+               em28xx_write_regs(dev, 0x08, "\x7d", 1);
+               msleep(10);
+               break;
+
+       case EM2870_BOARD_KWORLD_355U:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               msleep(50);
+
+               /* Sets GPO/GPIO sequences for this device */
+               dev->digital_gpio     = em2870_kworld_355u_digital;
+               break;
+
+       case EM2870_BOARD_COMPRO_VIDEOMATE:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               /* TODO: someone can do some cleanup here...
+                        not everything's needed */
+               em28xx_write_regs(dev, 0x04, "\x00", 1);
+               msleep(10);
+               em28xx_write_regs(dev, 0x04, "\x01", 1);
+               msleep(10);
+               em28xx_write_regs(dev, 0x08, "\xfd", 1);
+               mdelay(70);
+               em28xx_write_regs(dev, 0x08, "\xfc", 1);
+               mdelay(70);
+               em28xx_write_regs(dev, 0x08, "\xdc", 1);
+               mdelay(70);
+               em28xx_write_regs(dev, 0x08, "\xfc", 1);
+               mdelay(70);
+               break;
+
+       case EM2870_BOARD_TERRATEC_XS_MT2060:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               /* this device needs some gpio writes to get the DVB-T
+                  demod work */
+               em28xx_write_regs(dev, 0x08, "\xfe", 1);
+               mdelay(70);
+               em28xx_write_regs(dev, 0x08, "\xde", 1);
+               mdelay(70);
+               dev->em28xx_write_regs(dev, 0x08, "\xfe", 1);
+               mdelay(70);
+               break;
+
+       case EM2870_BOARD_PINNACLE_PCTV_DVB:
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               /* this device needs some gpio writes to get the
+                  DVB-T demod work */
+               em28xx_write_regs(dev, 0x08, "\xfe", 1);
+               mdelay(70);
+               em28xx_write_regs(dev, 0x08, "\xde", 1);
+               mdelay(70);
+               em28xx_write_regs(dev, 0x08, "\xfe", 1);
+               mdelay(70);
+               /* switch em2880 rc protocol */
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x22", 1);
+               /* should be added ir_codes here */
+               break;
+
+       case EM2820_BOARD_GADMEI_UTV310:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               /* Turn on analog audio output */
+               em28xx_write_regs_req(dev, 0x00, 0x08, "\xfd", 1);
+               break;
+
+       case EM2860_BOARD_GADMEI_UTV330:
+               /* Turn on IR */
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               /* should be added ir_codes here */
+               break;
 
+       case EM2820_BOARD_MSI_VOX_USB_2:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               /* enables audio for that device */
+               em28xx_write_regs_req(dev, 0x00, 0x08, "\xfd", 1);
                break;
        }
 
@@ -639,12 +1544,16 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
                ctl->demod = XC3028_FE_ZARLINK456;
                break;
+       case EM2880_BOARD_TERRATEC_HYBRID_XS:
+               ctl->demod = XC3028_FE_ZARLINK456;
+               break;
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
                /* djh - Not sure which demod we need here */
                ctl->demod = XC3028_FE_DEFAULT;
                break;
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
        case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
+       case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
                /* FIXME: Better to specify the needed IF */
                ctl->demod = XC3028_FE_DEFAULT;
                break;
@@ -809,6 +1718,8 @@ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
                break;
        case (EM2800_BOARD_KWORLD_USB2800):
                break;
+       case (EM2800_BOARD_GRABBEEX_USB2800):
+               break;
        }
 }
 
@@ -823,7 +1734,7 @@ void em28xx_card_setup(struct em28xx *dev)
        case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
        {
                struct tveeprom tv;
 #ifdef CONFIG_MODULES
@@ -836,7 +1747,7 @@ void em28xx_card_setup(struct em28xx *dev)
 
                dev->tuner_type = tv.tuner_type;
 
-               if (tv.audio_processor == AUDIO_CHIP_MSP34XX) {
+               if (tv.audio_processor == V4L2_IDENT_MSPX4XX) {
                        dev->i2s_speed = 2048000;
                        dev->has_msp34xx = 1;
                }
@@ -854,11 +1765,21 @@ void em28xx_card_setup(struct em28xx *dev)
        case EM2800_BOARD_UNKNOWN:
                if (!em28xx_hint_board(dev))
                        em28xx_set_model(dev);
+               break;
        }
 
        if (dev->has_snapshot_button)
                em28xx_register_snapshot_button(dev);
 
+       if (dev->valid == EM28XX_BOARD_NOT_VALIDATED) {
+               em28xx_errdev("\n\n");
+               em28xx_errdev("The support for this board weren't "
+                             "valid yet.\n");
+               em28xx_errdev("Please send a report of having this working\n");
+               em28xx_errdev("not to V4L mailing list (and/or to other "
+                               "addresses)\n\n");
+       }
+
        /* Allow override tuner type by a module parameter */
        if (tuner >= 0)
                dev->tuner_type = tuner;
index cc61cfb23a4a6213e77a6e8e703491cbbe4bb1c8..4b992bc0083c91954f834afb7a60e95652544cab 100644 (file)
@@ -6,6 +6,7 @@
  (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
        - Fixes for the driver to properly work with HVR-950
        - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick
+       - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600
 
  (c) 2008 Aidan Thornton <makosoft@googlemail.com>
 
@@ -409,8 +410,9 @@ static int dvb_init(struct em28xx *dev)
        em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
        /* init frontend */
        switch (dev->model) {
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
        case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
+       case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
                dvb->frontend = dvb_attach(lgdt330x_attach,
                                           &em2880_lgdt3303_dev,
                                           &dev->i2c_adap);
@@ -441,6 +443,15 @@ static int dvb_init(struct em28xx *dev)
                }
                break;
 #endif
+       case EM2880_BOARD_TERRATEC_HYBRID_XS:
+               dvb->frontend = dvb_attach(zl10353_attach,
+                                               &em28xx_zl10353_with_xc3028,
+                                               &dev->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0) {
+                        result = -EINVAL;
+                       goto out_free;
+               }
+               break;
        default:
                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
                                " isn't supported yet\n",
index 2d9f14d2a00b817119abeb1d5f29a2886014232d..49ab0629702e289bb2a8360a00c0703e3d60f694 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "em28xx.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/msp3400.h>
 #include <media/tuner.h>
 
@@ -1763,20 +1764,7 @@ static const struct file_operations em28xx_v4l_fops = {
        .compat_ioctl  = v4l_compat_ioctl32,
 };
 
-static const struct file_operations radio_fops = {
-       .owner         = THIS_MODULE,
-       .open          = em28xx_v4l2_open,
-       .release       = em28xx_v4l2_close,
-       .ioctl         = video_ioctl2,
-       .compat_ioctl  = v4l_compat_ioctl32,
-       .llseek        = no_llseek,
-};
-
-static const struct video_device em28xx_video_template = {
-       .fops                       = &em28xx_v4l_fops,
-       .release                    = video_device_release,
-
-       .minor                      = -1,
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_querycap            = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
@@ -1814,16 +1802,29 @@ static const struct video_device em28xx_video_template = {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        .vidiocgmbuf                = vidiocgmbuf,
 #endif
+};
+
+static const struct video_device em28xx_video_template = {
+       .fops                       = &em28xx_v4l_fops,
+       .release                    = video_device_release,
+       .ioctl_ops                  = &video_ioctl_ops,
+
+       .minor                      = -1,
 
        .tvnorms                    = V4L2_STD_ALL,
        .current_norm               = V4L2_STD_PAL,
 };
 
-static struct video_device em28xx_radio_template = {
-       .name                 = "em28xx-radio",
-       .type                 = VID_TYPE_TUNER,
-       .fops                 = &radio_fops,
-       .minor                = -1,
+static const struct file_operations radio_fops = {
+       .owner         = THIS_MODULE,
+       .open          = em28xx_v4l2_open,
+       .release       = em28xx_v4l2_close,
+       .ioctl         = video_ioctl2,
+       .compat_ioctl  = v4l_compat_ioctl32,
+       .llseek        = no_llseek,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
        .vidioc_querycap      = radio_querycap,
        .vidioc_g_tuner       = radio_g_tuner,
        .vidioc_enum_input    = radio_enum_input,
@@ -1842,6 +1843,13 @@ static struct video_device em28xx_radio_template = {
 #endif
 };
 
+static struct video_device em28xx_radio_template = {
+       .name                 = "em28xx-radio",
+       .fops                 = &radio_fops,
+       .ioctl_ops            = &radio_ioctl_ops,
+       .minor                = -1,
+};
+
 /******************************** usb interface ******************************/
 
 
@@ -1882,7 +1890,6 @@ EXPORT_SYMBOL(em28xx_unregister_extension);
 
 static struct video_device *em28xx_vdev_init(struct em28xx *dev,
                                             const struct video_device *template,
-                                            const int type,
                                             const char *type_name)
 {
        struct video_device *vfd;
@@ -1892,9 +1899,8 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
                return NULL;
        *vfd = *template;
        vfd->minor   = -1;
-       vfd->dev = &dev->udev->dev;
+       vfd->parent = &dev->udev->dev;
        vfd->release = video_device_release;
-       vfd->type = type;
        vfd->debug = video_debug;
 
        snprintf(vfd->name, sizeof(vfd->name), "%s %s",
@@ -1972,14 +1978,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        list_add_tail(&dev->devlist, &em28xx_devlist);
 
        /* allocate and fill video video_device struct */
-       dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template,
-                                         VID_TYPE_CAPTURE, "video");
+       dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
        if (NULL == dev->vdev) {
                em28xx_errdev("cannot allocate video_device.\n");
                goto fail_unreg;
        }
-       if (dev->tuner_type != TUNER_ABSENT)
-               dev->vdev->type |= VID_TYPE_TUNER;
 
        /* register v4l2 video video_device */
        retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
@@ -1991,8 +1994,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        }
 
        /* Allocate and fill vbi video_device struct */
-       dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
-                                         VFL_TYPE_VBI, "vbi");
+       dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi");
        /* register v4l2 vbi video_device */
        if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
                                        vbi_nr[dev->devno]) < 0) {
@@ -2002,8 +2004,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        }
 
        if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
-               dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
-                                       VFL_TYPE_RADIO, "radio");
+               dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio");
                if (NULL == dev->radio_dev) {
                        em28xx_errdev("cannot allocate video_device.\n");
                        goto fail_unreg;
index 89842c5d64a13da3e1204b41dace3fdc07eba8c0..9a3310748685c9c3ec63c84522272b463d491287 100644 (file)
 #define EM2880_BOARD_TERRATEC_PRODIGY_XS       13
 #define EM2820_BOARD_PROLINK_PLAYTV_USB2       14
 #define EM2800_BOARD_VGEAR_POCKETTV             15
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950   16
+#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950   16
 #define EM2880_BOARD_PINNACLE_PCTV_HD_PRO      17
 #define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2        18
 #define EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA  19
+#define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600   20
+#define EM2800_BOARD_GRABBEEX_USB2800           21
+#define EM2750_BOARD_UNKNOWN                     22
+#define EM2750_BOARD_DLCW_130                    23
+#define EM2820_BOARD_DLINK_USB_TV                24
+#define EM2820_BOARD_GADMEI_UTV310               25
+#define EM2820_BOARD_HERCULES_SMART_TV_USB2      26
+#define EM2820_BOARD_PINNACLE_USB_2_FM1216ME     27
+#define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28
+#define EM2820_BOARD_PINNACLE_DVC_100            29
+#define EM2820_BOARD_VIDEOLOGY_20K14XUSB         30
+#define EM2821_BOARD_USBGEAR_VD204               31
+#define EM2821_BOARD_SUPERCOMP_USB_2             32
+#define EM2821_BOARD_PROLINK_PLAYTV_USB2         33
+#define EM2860_BOARD_TERRATEC_HYBRID_XS                  34
+#define EM2860_BOARD_TYPHOON_DVD_MAKER           35
+#define EM2860_BOARD_NETGMBH_CAM                 36
+#define EM2860_BOARD_GADMEI_UTV330               37
+#define EM2861_BOARD_YAKUMO_MOVIE_MIXER                  38
+#define EM2861_BOARD_KWORLD_PVRTV_300U           39
+#define EM2861_BOARD_PLEXTOR_PX_TV100U           40
+#define EM2870_BOARD_KWORLD_350U                 41
+#define EM2870_BOARD_KWORLD_355U                 42
+#define EM2870_BOARD_TERRATEC_XS                 43
+#define EM2870_BOARD_TERRATEC_XS_MT2060                  44
+#define EM2870_BOARD_PINNACLE_PCTV_DVB           45
+#define EM2870_BOARD_COMPRO_VIDEOMATE            46
+#define EM2880_BOARD_KWORLD_DVB_305U             47
+#define EM2880_BOARD_KWORLD_DVB_310U             48
+#define EM2880_BOARD_MSI_DIGIVOX_AD              49
+#define EM2880_BOARD_MSI_DIGIVOX_AD_II           50
+#define EM2880_BOARD_TERRATEC_HYBRID_XS_FR       51
+#define EM2881_BOARD_DNT_DA2_HYBRID              52
+#define EM2881_BOARD_PINNACLE_HYBRID_PRO         53
+#define EM2882_BOARD_KWORLD_VS_DVBT              54
+#define EM2882_BOARD_TERRATEC_HYBRID_XS                  55
+#define EM2882_BOARD_PINNACLE_HYBRID_PRO         56
+#define EM2883_BOARD_KWORLD_HYBRID_A316                  57
+#define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU     58
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
 #define EM28XX_DEF_BUF 8
 
+/* Params for validated field */
+#define EM28XX_BOARD_NOT_VALIDATED 1
+#define EM28XX_BOARD_VALIDATED    0
+
 /* maximum number of em28xx boards */
 #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
 
@@ -251,6 +294,7 @@ struct em28xx_board {
        unsigned int max_range_640_480:1;
        unsigned int has_dvb:1;
        unsigned int has_snapshot_button:1;
+       unsigned int valid:1;
 
        enum em28xx_decoder decoder;
 
@@ -331,6 +375,7 @@ struct em28xx {
        unsigned int max_range_640_480:1;
        unsigned int has_dvb:1;
        unsigned int has_snapshot_button:1;
+       unsigned int valid:1;           /* report for validated boards */
 
        /* Some older em28xx chips needs a waiting time after writing */
        unsigned int wait_after_write;
@@ -360,7 +405,7 @@ struct em28xx {
        v4l2_std_id norm;       /* selected tv norm */
        int ctl_freq;           /* selected frequency */
        unsigned int ctl_input; /* selected input */
-       unsigned int ctl_ainput;        /* slected audio input */
+       unsigned int ctl_ainput;/* selected audio input */
        int mute;
        int volume;
        /* frame properties */
index 15d037ae25c5fed1700bdf589b9f8bb6136b5173..2d170d101c2197f348f1e2c2a111891144b46bd2 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/page-flags.h>
+#include <media/v4l2-ioctl.h>
 #include <asm/byteorder.h>
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -985,7 +986,7 @@ static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
 
 static int et61x251_create_sysfs(struct et61x251_device* cam)
 {
-       struct device *classdev = &(cam->v4ldev->class_dev);
+       struct device *classdev = &(cam->v4ldev->dev);
        int err = 0;
 
        if ((err = device_create_file(classdev, &dev_attr_reg)))
@@ -2584,8 +2585,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        }
 
        strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera");
-       cam->v4ldev->owner = THIS_MODULE;
-       cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
        cam->v4ldev->fops = &et61x251_fops;
        cam->v4ldev->minor = video_nr[dev_nr];
        cam->v4ldev->release = video_device_release;
index 013d593b0c678979faff6075900bdac237d08508..44b0bffeb20e3739aa4e6e49883258906c8809af 100644 (file)
@@ -25,9 +25,6 @@
 #define CONEX_CAM 1            /* special JPEG header */
 #include "jpeg.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
 MODULE_LICENSE("GPL");
@@ -818,7 +815,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        cam->cam_mode = vga_mode;
        cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
@@ -1011,9 +1007,8 @@ static struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0572, 0x0041), DVNM("Creative Notebook cx11646")},
+       {USB_DEVICE(0x0572, 0x0041)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1038,7 +1033,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index 8ab4ea7201a90e2ac5c127d5624128521001fc12..c8c2f02fcf00b2d7d2286a122fe5b08f631a02d3 100644 (file)
@@ -22,9 +22,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("Etoms USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -602,26 +599,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
-       __u16 vendor;
-       __u16 product;
-
-       vendor = id->idVendor;
-       product = id->idProduct;
-/*     switch (vendor) { */
-/*     case 0x102c:            * Etoms */
-               switch (product) {
-               case 0x6151:
-                       sd->sensor = SENSOR_PAS106;     /* Etoms61x151 */
-                       break;
-               case 0x6251:
-                       sd->sensor = SENSOR_TAS5130CXX; /* Etoms61x251 */
-                       break;
-/*             } */
-/*             break; */
-       }
+
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 1;
+       sd->sensor = id->driver_info;
        if (sd->sensor == SENSOR_PAS106) {
                cam->cam_mode = sif_mode;
                cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
@@ -911,12 +892,11 @@ static struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static __devinitdata struct usb_device_id device_table[] = {
 #ifndef CONFIG_USB_ET61X251
-       {USB_DEVICE(0x102c, 0x6151), DVNM("Qcam Sangha CIF")},
+       {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
 #endif
-       {USB_DEVICE(0x102c, 0x6251), DVNM("Qcam xxxxxx VGA")},
+       {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
        {}
 };
 
@@ -942,7 +922,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 
index 16e367cec76077981c2d398754d0ff1e3018e98c..3a051c925ff6eda699f4b05378a473b7e34a05f9 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/page.h>
 #include <linux/uaccess.h>
 #include <linux/jiffies.h>
+#include <media/v4l2-ioctl.h>
 
 #include "gspca.h"
 
@@ -42,8 +43,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("GSPCA USB Camera Driver");
 MODULE_LICENSE("GPL");
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
+#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 2, 0)
 
 static int video_nr = -1;
 
@@ -209,6 +209,8 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
                                   &frame->v4l2_buf.timestamp);
                frame->v4l2_buf.sequence = ++gspca_dev->sequence;
        } else if (gspca_dev->last_packet_type == DISCARD_PACKET) {
+               if (packet_type == LAST_PACKET)
+                       gspca_dev->last_packet_type = packet_type;
                return frame;
        }
 
@@ -399,7 +401,7 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
  * This routine may be called many times when the bandwidth is too small
  * (the bandwidth is checked on urb submit).
  */
-struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
+static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
 {
        struct usb_interface *intf;
        struct usb_host_endpoint *ep;
@@ -832,7 +834,16 @@ static int vidioc_querycap(struct file *file, void  *priv,
 
        memset(cap, 0, sizeof *cap);
        strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
-       strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card);
+/*     strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card); */
+       if (gspca_dev->dev->product != NULL) {
+               strncpy(cap->card, gspca_dev->dev->product,
+                       sizeof cap->card);
+       } else {
+               snprintf(cap->card, sizeof cap->card,
+                       "USB Camera (%04x:%04x)",
+                       le16_to_cpu(gspca_dev->dev->descriptor.idVendor),
+                       le16_to_cpu(gspca_dev->dev->descriptor.idProduct));
+       }
        strncpy(cap->bus_info, gspca_dev->dev->bus->bus_name,
                sizeof cap->bus_info);
        cap->version = DRIVER_VERSION_NUMBER;
@@ -1649,12 +1660,7 @@ static struct file_operations dev_fops = {
        .poll   = dev_poll,
 };
 
-static struct video_device gspca_template = {
-       .name = "gspca main driver",
-       .type = VID_TYPE_CAPTURE,
-       .fops = &dev_fops,
-       .release = dev_release,         /* mandatory */
-       .minor = -1,
+static const struct v4l2_ioctl_ops dev_ioctl_ops = {
        .vidioc_querycap        = vidioc_querycap,
        .vidioc_dqbuf           = vidioc_dqbuf,
        .vidioc_qbuf            = vidioc_qbuf,
@@ -1683,6 +1689,14 @@ static struct video_device gspca_template = {
 #endif
 };
 
+static struct video_device gspca_template = {
+       .name = "gspca main driver",
+       .fops = &dev_fops,
+       .ioctl_ops = &dev_ioctl_ops,
+       .release = dev_release,         /* mandatory */
+       .minor = -1,
+};
+
 /*
  * probe and create a new gspca device
  *
@@ -1740,10 +1754,11 @@ int gspca_dev_probe(struct usb_interface *intf,
 
        /* init video stuff */
        memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
-       gspca_dev->vdev.dev = &dev->dev;
+       gspca_dev->vdev.parent = &dev->dev;
        memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops);
        gspca_dev->vdev.fops = &gspca_dev->fops;
        gspca_dev->fops.owner = module;         /* module protection */
+       gspca_dev->present = 1;
        ret = video_register_device(&gspca_dev->vdev,
                                  VFL_TYPE_GRABBER,
                                  video_nr);
@@ -1752,7 +1767,6 @@ int gspca_dev_probe(struct usb_interface *intf,
                goto out;
        }
 
-       gspca_dev->present = 1;
        usb_set_intfdata(intf, gspca_dev);
        PDEBUG(D_PROBE, "probe ok");
        return 0;
@@ -1885,7 +1899,10 @@ EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
 /* -- module insert / remove -- */
 static int __init gspca_init(void)
 {
-       info("main v%s registered", version);
+       info("main v%d.%d.%d registered",
+               (DRIVER_VERSION_NUMBER >> 16) & 0xff,
+               (DRIVER_VERSION_NUMBER >> 8) & 0xff,
+               DRIVER_VERSION_NUMBER & 0xff);
        return 0;
 }
 static void __exit gspca_exit(void)
index 88c2b02f380a191064b32de47454842595021d00..21c4ee56a10aaef3702d8b3a79cce7ddda884c5a 100644 (file)
@@ -24,9 +24,6 @@
 #include "gspca.h"
 #include "jpeg.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -140,7 +137,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        cam->cam_mode = vga_mode;
        cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
@@ -424,9 +420,8 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x093a, 0x050f), DVNM("Mars-Semi Pc-Camera")},
+       {USB_DEVICE(0x093a, 0x050f)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -451,7 +446,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index 08d99c3b78e2ddafcae52d32aa4aa70615c27e5d..83139efc462935de68331cd5b8c0a1959425d746 100644 (file)
@@ -24,9 +24,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("OV519 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -1375,7 +1372,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
                cam->cam_mode = sif_mode;
                cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
        }
-       cam->dev_name = (char *) id->driver_info;
        sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
        sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
        sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
@@ -2129,21 +2125,20 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x4052), DVNM("Creative Live! VISTA IM")},
-       {USB_DEVICE(0x041e, 0x405f), DVNM("Creative Live! VISTA VF0330")},
-       {USB_DEVICE(0x041e, 0x4060), DVNM("Creative Live! VISTA VF0350")},
-       {USB_DEVICE(0x041e, 0x4061), DVNM("Creative Live! VISTA VF0400")},
-       {USB_DEVICE(0x041e, 0x4064), DVNM("Creative Live! VISTA VF0420")},
-       {USB_DEVICE(0x041e, 0x4068), DVNM("Creative Live! VISTA VF0470")},
-       {USB_DEVICE(0x045e, 0x028c), DVNM("Microsoft xbox cam")},
-       {USB_DEVICE(0x054c, 0x0154), DVNM("Sonny toy4")},
-       {USB_DEVICE(0x054c, 0x0155), DVNM("Sonny toy5")},
-       {USB_DEVICE(0x05a9, 0x0519), DVNM("OmniVision")},
-       {USB_DEVICE(0x05a9, 0x0530), DVNM("OmniVision")},
-       {USB_DEVICE(0x05a9, 0x4519), DVNM("OmniVision")},
-       {USB_DEVICE(0x05a9, 0x8519), DVNM("OmniVision")},
+       {USB_DEVICE(0x041e, 0x4052)},
+       {USB_DEVICE(0x041e, 0x405f)},
+       {USB_DEVICE(0x041e, 0x4060)},
+       {USB_DEVICE(0x041e, 0x4061)},
+       {USB_DEVICE(0x041e, 0x4064)},
+       {USB_DEVICE(0x041e, 0x4068)},
+       {USB_DEVICE(0x045e, 0x028c)},
+       {USB_DEVICE(0x054c, 0x0154)},
+       {USB_DEVICE(0x054c, 0x0155)},
+       {USB_DEVICE(0x05a9, 0x0519)},
+       {USB_DEVICE(0x05a9, 0x0530)},
+       {USB_DEVICE(0x05a9, 0x4519)},
+       {USB_DEVICE(0x05a9, 0x8519)},
        {}
 };
 #undef DVNAME
@@ -2169,7 +2164,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index fa7abc411090c48e7803be522bda37640c36eea2..7ef18d57881156de5cd5f125d410e9632e7112b3 100644 (file)
@@ -27,9 +27,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
 MODULE_DESCRIPTION("Pixart PAC207");
 MODULE_LICENSE("GPL");
@@ -208,7 +205,7 @@ static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
 }
 
 
-int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
+static int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
 {
        struct usb_device *udev = gspca_dev->dev;
        int err;
@@ -223,8 +220,7 @@ int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
        return err;
 }
 
-
-int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
+static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
 {
        struct usb_device *udev = gspca_dev->dev;
        int res;
@@ -574,17 +570,16 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x4028), DVNM("Creative Webcam Vista Plus")},
-       {USB_DEVICE(0x093a, 0x2460), DVNM("Q-Tec Webcam 100")},
-       {USB_DEVICE(0x093a, 0x2463), DVNM("Philips spc200nc pac207")},
-       {USB_DEVICE(0x093a, 0x2464), DVNM("Labtec Webcam 1200")},
-       {USB_DEVICE(0x093a, 0x2468), DVNM("PAC207")},
-       {USB_DEVICE(0x093a, 0x2470), DVNM("Genius GF112")},
-       {USB_DEVICE(0x093a, 0x2471), DVNM("Genius VideoCam GE111")},
-       {USB_DEVICE(0x093a, 0x2472), DVNM("Genius VideoCam GE110")},
-       {USB_DEVICE(0x2001, 0xf115), DVNM("D-Link DSB-C120")},
+       {USB_DEVICE(0x041e, 0x4028)},
+       {USB_DEVICE(0x093a, 0x2460)},
+       {USB_DEVICE(0x093a, 0x2463)},
+       {USB_DEVICE(0x093a, 0x2464)},
+       {USB_DEVICE(0x093a, 0x2468)},
+       {USB_DEVICE(0x093a, 0x2470)},
+       {USB_DEVICE(0x093a, 0x2471)},
+       {USB_DEVICE(0x093a, 0x2472)},
+       {USB_DEVICE(0x2001, 0xf115)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -609,7 +604,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index 5c052e31be4adad49b2eb93e496e0d8c2e89e5a7..ea3d7021f40181287177df3b48d2f84f20b61dca 100644 (file)
@@ -23,9 +23,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
 MODULE_DESCRIPTION("Pixart PAC7311");
 MODULE_LICENSE("GPL");
@@ -266,7 +263,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        reg_w(gspca_dev, 0x3e, 0x20);
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x05;
        cam->cam_mode = vga_mode;
        cam->nmodes = ARRAY_SIZE(vga_mode);
@@ -713,16 +709,14 @@ static struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
-       {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
-       {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
-       {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
-       {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera")},
-                       /* and also ', Trust WB-3350p, SIGMA cam 2350' */
-       {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
-       {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
+       {USB_DEVICE(0x093a, 0x2600)},
+       {USB_DEVICE(0x093a, 0x2601)},
+       {USB_DEVICE(0x093a, 0x2603)},
+       {USB_DEVICE(0x093a, 0x2608)},
+       {USB_DEVICE(0x093a, 0x260e)},
+       {USB_DEVICE(0x093a, 0x260f)},
+       {USB_DEVICE(0x093a, 0x2621)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -747,7 +741,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index dbeebe8625c59189021660462d4326c73f820715..e18748c5a14d4cf3df8a285586523824c10d22bf 100644 (file)
@@ -24,9 +24,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 8)
-static const char version[] = "2.1.8";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -44,25 +41,29 @@ struct sd {
        unsigned char brightness;
        unsigned char autogain;
        unsigned char autogain_ignore_frames;
+       unsigned char frames_to_drop;
        unsigned char freq;             /* light freq filter setting */
-       unsigned char saturation;
-       unsigned char hue;
-       unsigned char contrast;
 
        unsigned char fr_h_sz;          /* size of frame header */
        char sensor;                    /* Type of image sensor chip */
 #define SENSOR_HV7131R 0
 #define SENSOR_OV6650 1
 #define SENSOR_OV7630 2
-#define SENSOR_OV7630_3 3
-#define SENSOR_PAS106 4
-#define SENSOR_PAS202 5
-#define SENSOR_TAS5110 6
-#define SENSOR_TAS5130CXX 7
+#define SENSOR_PAS106 3
+#define SENSOR_PAS202 4
+#define SENSOR_TAS5110 5
+#define SENSOR_TAS5130CXX 6
        char sensor_has_gain;
        __u8 sensor_addr;
+       __u8 reg11;
 };
 
+/* flags used in the device id table */
+#define F_GAIN 0x01            /* has gain */
+#define F_AUTO 0x02            /* has autogain */
+#define F_SIF  0x04            /* sif or vga */
+#define F_H18  0x08            /* long (18 b) or short (12 b) frame header */
+
 #define COMP2 0x8f
 #define COMP 0xc7              /* 0x87 //0x07 */
 #define COMP1 0xc9             /* 0x89 //0x09 */
@@ -92,12 +93,6 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
        {
@@ -174,48 +169,6 @@ static struct ctrl sd_ctrls[] = {
                .set = sd_setfreq,
                .get = sd_getfreq,
        },
-       {
-               {
-                       .id      = V4L2_CID_SATURATION,
-                       .type    = V4L2_CTRL_TYPE_INTEGER,
-                       .name    = "Saturation",
-                       .minimum = 0,
-                       .maximum = 255,
-                       .step    = 1,
-#define SATURATION_DEF 127
-                       .default_value = SATURATION_DEF,
-               },
-               .set = sd_setsaturation,
-               .get = sd_getsaturation,
-       },
-       {
-               {
-                       .id      = V4L2_CID_HUE,
-                       .type    = V4L2_CTRL_TYPE_INTEGER,
-                       .name    = "Hue",
-                       .minimum = 0,
-                       .maximum = 255,
-                       .step    = 1,
-#define HUE_DEF 127
-                       .default_value = HUE_DEF,
-               },
-               .set = sd_sethue,
-               .get = sd_gethue,
-       },
-       {
-               {
-                       .id      = V4L2_CID_CONTRAST,
-                       .type    = V4L2_CTRL_TYPE_INTEGER,
-                       .name    = "Contrast",
-                       .minimum = 0,
-                       .maximum = 255,
-                       .step    = 1,
-#define CONTRAST_DEF 127
-                       .default_value = CONTRAST_DEF,
-               },
-               .set = sd_setcontrast,
-               .get = sd_getcontrast,
-       },
 };
 
 static struct v4l2_pix_format vga_mode[] = {
@@ -248,8 +201,6 @@ static struct v4l2_pix_format sif_mode[] = {
                .priv = 0},
 };
 
-static const __u8 probe_ov7630[] = {0x08, 0x44};
-
 static const __u8 initHv7131[] = {
        0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
        0x00, 0x00,
@@ -321,7 +272,7 @@ static const __u8 initOv7630_3[] = {
        0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
        0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff  /* r29 .. r30 */
 };
-static const __u8 ov7630_sensor_init_com[][8] = {
+static const __u8 ov7630_sensor_init[][8] = {
        {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
        {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
 /*     {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10},          jfm */
@@ -342,17 +293,6 @@ static const __u8 ov7630_sensor_init_com[][8] = {
        {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
        {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
 };
-static const __u8 ov7630_sensor_init[][8] = {
-       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
-       {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10},       /* jfm */
-       {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
-       {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
-       {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15},       /* gain */
-};
-static const __u8 ov7630_sensor_init_3[][8] = {
-       {0xa0, 0x21, 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x10},
-};
 
 static const __u8 initPas106[] = {
        0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
@@ -542,7 +482,6 @@ static void setbrightness(struct gspca_dev *gspca_dev)
 
        switch (sd->sensor) {
        case  SENSOR_OV6650:
-       case  SENSOR_OV7630_3:
        case  SENSOR_OV7630: {
                __u8 i2cOV[] =
                        {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
@@ -635,7 +574,7 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
        case SENSOR_OV6650:
                gain >>= 1;
                /* fall thru */
-       case SENSOR_OV7630_3: {
+       case SENSOR_OV7630: {
                __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
 
                i2c[1] = sd->sensor_addr;
@@ -690,7 +629,7 @@ static void setexposure(struct gspca_dev *gspca_dev)
                break;
            }
        case SENSOR_OV6650:
-       case SENSOR_OV7630_3: {
+       case SENSOR_OV7630: {
                /* The ov6650 / ov7630 have 2 registers which both influence
                   exposure, register 11, whose low nibble sets the nr off fps
                   according to: fps = 30 / (low_nibble + 1)
@@ -705,16 +644,20 @@ static void setexposure(struct gspca_dev *gspca_dev)
                   The code maps our 0 - 510 ms exposure ctrl to these 2
                   registers, trying to keep fps as high as possible.
                */
-               __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
-               int reg10, reg11;
+               __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
+               int reg10, reg11, reg10_max;
+
                /* ov6645 datasheet says reg10_max is 9a, but that uses
                   tline * 2 * reg10 as formula for calculating texpo, the
                   ov6650 probably uses the same formula as the 7730 which uses
                   tline * 4 * reg10, which explains why the reg10max we've
                   found experimentally for the ov6650 is exactly half that of
                   the ov6645. The ov7630 datasheet says the max is 0x41. */
-               const int reg10_max = (sd->sensor == SENSOR_OV6650)
-                               ? 0x4d : 0x41;
+               if (sd->sensor == SENSOR_OV6650) {
+                       reg10_max = 0x4d;
+                       i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
+               } else
+                       reg10_max = 0x41;
 
                reg11 = (60 * sd->exposure + 999) / 1000;
                if (reg11 < 1)
@@ -735,20 +678,23 @@ static void setexposure(struct gspca_dev *gspca_dev)
                else if (reg10 > reg10_max)
                        reg10 = reg10_max;
 
+               /* In 640x480, if the reg11 has less than 3, the image is
+                  unstable (not enough bandwidth). */
+               if (gspca_dev->width == 640 && reg11 < 3)
+                       reg11 = 3;
+
                /* Write reg 10 and reg11 low nibble */
                i2c[1] = sd->sensor_addr;
                i2c[3] = reg10;
                i2c[4] |= reg11 - 1;
-               if (sd->sensor == SENSOR_OV7630_3) {
-                       __u8 reg76 = reg10 & 0x03;
-                       __u8 i2c_reg76[] = {0xa0, 0x21, 0x76, 0x00,
-                                           0x00, 0x00, 0x00, 0x10};
-                       reg10 >>= 2;
-                       i2c_reg76[3] = reg76;
-                       if (i2c_w(gspca_dev, i2c_reg76) < 0)
-                               PDEBUG(D_ERR, "i2c error exposure");
-               }
-               if (i2c_w(gspca_dev, i2c) < 0)
+
+               /* If register 11 didn't change, don't change it */
+               if (sd->reg11 == reg11 )
+                       i2c[0] = 0xa0;
+
+               if (i2c_w(gspca_dev, i2c) == 0)
+                       sd->reg11 = reg11;
+               else
                        PDEBUG(D_ERR, "i2c error exposure");
                break;
            }
@@ -761,11 +707,11 @@ static void setfreq(struct gspca_dev *gspca_dev)
 
        switch (sd->sensor) {
        case SENSOR_OV6650:
-       case SENSOR_OV7630_3: {
+       case SENSOR_OV7630: {
                /* Framerate adjust register for artificial light 50 hz flicker
-                  compensation, identical to ov6630 0x2b register, see ov6630
-                  datasheet.
-                  0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
+                  compensation, for the ov6650 this is identical to ov6630
+                  0x2b register, see ov6630 datasheet.
+                  0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
                __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
                switch (sd->freq) {
                default:
@@ -786,69 +732,6 @@ static void setfreq(struct gspca_dev *gspca_dev)
        }
 }
 
-static void setsaturation(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->sensor) {
-/*     case SENSOR_OV6650: */
-       case SENSOR_OV7630_3:
-       case SENSOR_OV7630: {
-               __u8 i2c[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10};
-               i2c[1] = sd->sensor_addr;
-               i2c[3] = sd->saturation & 0xf0;
-               if (i2c_w(gspca_dev, i2c) < 0)
-                       PDEBUG(D_ERR, "i2c error setsaturation");
-               else
-                       PDEBUG(D_CONF, "saturation set to: %d",
-                               (int)sd->saturation);
-               break;
-           }
-       }
-}
-
-static void sethue(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->sensor) {
-/*     case SENSOR_OV6650: */
-       case SENSOR_OV7630_3:
-       case SENSOR_OV7630: {
-               __u8 i2c[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10};
-               i2c[1] = sd->sensor_addr;
-               i2c[3] = 0x20 | (sd->hue >> 3);
-               if (i2c_w(gspca_dev, i2c) < 0)
-                       PDEBUG(D_ERR, "i2c error setsaturation");
-               else
-                       PDEBUG(D_CONF, "hue set to: %d", (int)sd->hue);
-               break;
-           }
-       }
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->sensor) {
-/*     case SENSOR_OV6650: */
-       case SENSOR_OV7630_3:
-       case SENSOR_OV7630: {
-               __u8 i2c[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10};
-               i2c[1] = sd->sensor_addr;
-               i2c[3] = 0x20 | (sd->contrast >> 3);
-               if (i2c_w(gspca_dev, i2c) < 0)
-                       PDEBUG(D_ERR, "i2c error setcontrast");
-               else
-                       PDEBUG(D_CONF, "contrast set to: %d",
-                               (int)sd->contrast);
-               break;
-           }
-       }
-}
-
-
 static void do_autogain(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -874,88 +757,32 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
-       __u16 product;
        int sif = 0;
 
        /* nctrls depends upon the sensor, so we use a per cam copy */
        memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
        gspca_dev->sd_desc = &sd->sd_desc;
 
-       sd->fr_h_sz = 12;               /* default size of the frame header */
-       sd->sd_desc.nctrls = 2;         /* default nb of ctrls */
-       sd->autogain = AUTOGAIN_DEF;    /* default is autogain active */
-
-       product = id->idProduct;
-/*     switch (id->idVendor) { */
-/*     case 0x0c45:                             * Sonix */
-               switch (product) {
-               case 0x6001:                    /* SN9C102 */
-               case 0x6005:                    /* SN9C101 */
-               case 0x6007:                    /* SN9C101 */
-                       sd->sensor = SENSOR_TAS5110;
-                       sd->sensor_has_gain = 1;
-                       sd->sd_desc.nctrls = 4;
-                       sd->sd_desc.dq_callback = do_autogain;
-                       sif = 1;
-                       break;
-               case 0x6009:                    /* SN9C101 */
-               case 0x600d:                    /* SN9C101 */
-               case 0x6029:                    /* SN9C101 */
-                       sd->sensor = SENSOR_PAS106;
-                       sif = 1;
-                       break;
-               case 0x6011:                    /* SN9C101 - SN9C101G */
-                       sd->sensor = SENSOR_OV6650;
-                       sd->sensor_has_gain = 1;
-                       sd->sensor_addr = 0x60;
-                       sd->sd_desc.nctrls = 5;
-                       sd->sd_desc.dq_callback = do_autogain;
-                       sif = 1;
-                       break;
-               case 0x6019:                    /* SN9C101 */
-               case 0x602c:                    /* SN9C102 */
-               case 0x602e:                    /* SN9C102 */
-                       sd->sensor = SENSOR_OV7630;
-                       sd->sensor_addr = 0x21;
-                       break;
-               case 0x60b0:                    /* SN9C103 */
-                       sd->sensor = SENSOR_OV7630_3;
-                       sd->sensor_addr = 0x21;
-                       sd->fr_h_sz = 18;       /* size of frame header */
-                       sd->sensor_has_gain = 1;
-                       sd->sd_desc.nctrls = 8;
-                       sd->sd_desc.dq_callback = do_autogain;
-                       sd->autogain = 0;
-                       break;
-               case 0x6024:                    /* SN9C102 */
-               case 0x6025:                    /* SN9C102 */
-                       sd->sensor = SENSOR_TAS5130CXX;
-                       break;
-               case 0x6028:                    /* SN9C102 */
-                       sd->sensor = SENSOR_PAS202;
-                       break;
-               case 0x602d:                    /* SN9C102 */
-                       sd->sensor = SENSOR_HV7131R;
-                       break;
-               case 0x60af:                    /* SN9C103 */
-                       sd->sensor = SENSOR_PAS202;
-                       sd->fr_h_sz = 18;       /* size of frame header (?) */
-                       break;
-               }
-/*             break; */
-/*     } */
+       /* copy the webcam info from the device id */
+       sd->sensor = (id->driver_info >> 24) & 0xff;
+       if (id->driver_info & (F_GAIN << 16))
+               sd->sensor_has_gain = 1;
+       if (id->driver_info & (F_AUTO << 16))
+               sd->sd_desc.dq_callback = do_autogain;
+       if (id->driver_info & (F_SIF << 16))
+               sif = 1;
+       if (id->driver_info & (F_H18 << 16))
+               sd->fr_h_sz = 18;               /* size of frame header */
+       else
+               sd->fr_h_sz = 12;
+       sd->sd_desc.nctrls = (id->driver_info >> 8) & 0xff;
+       sd->sensor_addr = id->driver_info & 0xff;
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        if (!sif) {
                cam->cam_mode = vga_mode;
                cam->nmodes = ARRAY_SIZE(vga_mode);
-               if (sd->sensor == SENSOR_OV7630_3) {
-                       /* We only have 320x240 & 640x480 */
-                       cam->cam_mode++;
-                       cam->nmodes--;
-               }
        } else {
                cam->cam_mode = sif_mode;
                cam->nmodes = ARRAY_SIZE(sif_mode);
@@ -963,12 +790,9 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->brightness = BRIGHTNESS_DEF;
        sd->gain = GAIN_DEF;
        sd->exposure = EXPOSURE_DEF;
+       sd->autogain = AUTOGAIN_DEF;
        sd->freq = FREQ_DEF;
-       sd->contrast = CONTRAST_DEF;
-       sd->saturation = SATURATION_DEF;
-       sd->hue = HUE_DEF;
-       if (sd->sensor == SENSOR_OV7630_3)      /* jfm: from win trace */
-               reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
+
        return 0;
 }
 
@@ -1002,9 +826,8 @@ static void pas106_i2cinit(struct gspca_dev *gspca_dev)
 static void sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       int mode, l;
+       int mode, l = 0x1f;
        const __u8 *sn9c10x;
-       __u8 reg01, reg17;
        __u8 reg17_19[3];
 
        mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
@@ -1022,13 +845,11 @@ static void sd_start(struct gspca_dev *gspca_dev)
                reg17_19[2] = 0x20;
                break;
        case SENSOR_OV7630:
-               sn9c10x = initOv7630;
-               reg17_19[0] = 0x68;
-               reg17_19[1] = (mode << 4) | COMP2;
-               reg17_19[2] = MCK_INIT1;
-               break;
-       case SENSOR_OV7630_3:
-               sn9c10x = initOv7630_3;
+               if (sd->fr_h_sz == 18) { /* SN9C103 */
+                       sn9c10x = initOv7630_3;
+                       l = sizeof initOv7630_3;
+               } else
+                       sn9c10x = initOv7630;
                reg17_19[0] = 0x68;
                reg17_19[1] = (mode << 4) | COMP2;
                reg17_19[2] = MCK_INIT1;
@@ -1059,30 +880,11 @@ static void sd_start(struct gspca_dev *gspca_dev)
                reg17_19[2] = mode ? 0x23 : 0x43;
                break;
        }
-       switch (sd->sensor) {
-       case SENSOR_OV7630:
-               reg01 = 0x06;
-               reg17 = 0x29;
-               l = sizeof initOv7630;
-               break;
-       case SENSOR_OV7630_3:
-               reg01 = 0x44;
-               reg17 = 0x68;
-               l = sizeof initOv7630_3;
-               break;
-       default:
-               reg01 = sn9c10x[0];
-               reg17 = sn9c10x[0x17 - 1];
-               l = 0x1f;
-               break;
-       }
 
        /* reg 0x01 bit 2 video transfert on */
-       reg_w(gspca_dev, 0x01, &reg01, 1);
+       reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
        /* reg 0x17 SensorClk enable inv Clk 0x60 */
-       reg_w(gspca_dev, 0x17, &reg17, 1);
-/*fixme: for ov7630 102
-       reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
+       reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
        /* Set the registers from the template */
        reg_w_big(gspca_dev, 0x01, sn9c10x, l);
        switch (sd->sensor) {
@@ -1095,17 +897,13 @@ static void sd_start(struct gspca_dev *gspca_dev)
                                sizeof ov6650_sensor_init);
                break;
        case SENSOR_OV7630:
-               i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
-                               sizeof ov7630_sensor_init_com);
-               msleep(200);
                i2c_w_vector(gspca_dev, ov7630_sensor_init,
                                sizeof ov7630_sensor_init);
-               break;
-       case SENSOR_OV7630_3:
-               i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
-                               sizeof ov7630_sensor_init_com);
-               msleep(200);
-               i2c_w(gspca_dev, ov7630_sensor_init_3[mode]);
+               if (sd->fr_h_sz == 18) { /* SN9C103 */
+                       const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
+                                               0x00, 0x00, 0x10 };
+                       i2c_w(gspca_dev, i2c);
+               }
                break;
        case SENSOR_PAS106:
                pas106_i2cinit(gspca_dev);
@@ -1145,14 +943,14 @@ static void sd_start(struct gspca_dev *gspca_dev)
        reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
        msleep(20);
 
+       sd->reg11 = -1;
+
        setgain(gspca_dev);
        setbrightness(gspca_dev);
        setexposure(gspca_dev);
        setfreq(gspca_dev);
-       setsaturation(gspca_dev);
-       sethue(gspca_dev);
-       setcontrast(gspca_dev);
 
+       sd->frames_to_drop = 0;
        sd->autogain_ignore_frames = 0;
        atomic_set(&sd->avg_lum, -1);
 }
@@ -1198,21 +996,31 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                            && data[3 + i] == 0xc4
                            && data[4 + i] == 0xc4
                            && data[5 + i] == 0x96) {   /* start of frame */
-                               frame = gspca_frame_add(gspca_dev, LAST_PACKET,
-                                                       frame, data, 0);
+                               int lum = -1;
+                               int pkt_type = LAST_PACKET;
+
                                if (len - i < sd->fr_h_sz) {
-                                       atomic_set(&sd->avg_lum, -1);
                                        PDEBUG(D_STREAM, "packet too short to"
                                                " get avg brightness");
                                } else if (sd->fr_h_sz == 12) {
-                                       atomic_set(&sd->avg_lum,
-                                               data[i + 8] +
-                                                       (data[i + 9] << 8));
+                                       lum = data[i + 8] + (data[i + 9] << 8);
                                } else {
-                                       atomic_set(&sd->avg_lum,
-                                               data[i + 9] +
-                                                       (data[i + 10] << 8));
+                                       lum = data[i + 9] +
+                                               (data[i + 10] << 8);
+                               }
+                               if (lum == 0) {
+                                       lum = -1;
+                                       sd->frames_to_drop = 2;
+                               }
+                               atomic_set(&sd->avg_lum, lum);
+
+                               if (sd->frames_to_drop) {
+                                       sd->frames_to_drop--;
+                                       pkt_type = DISCARD_PACKET;
                                }
+
+                               frame = gspca_frame_add(gspca_dev, pkt_type,
+                                                       frame, data, 0);
                                data += i + sd->fr_h_sz;
                                len -= i + sd->fr_h_sz;
                                gspca_frame_add(gspca_dev, FIRST_PACKET,
@@ -1327,60 +1135,6 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
-static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->saturation = val;
-       if (gspca_dev->streaming)
-               setsaturation(gspca_dev);
-       return 0;
-}
-
-static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       *val = sd->saturation;
-       return 0;
-}
-
-static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->hue = val;
-       if (gspca_dev->streaming)
-               sethue(gspca_dev);
-       return 0;
-}
-
-static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       *val = sd->hue;
-       return 0;
-}
-
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->contrast = val;
-       if (gspca_dev->streaming)
-               setcontrast(gspca_dev);
-       return 0;
-}
-
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       *val = sd->contrast;
-       return 0;
-}
-
 static int sd_querymenu(struct gspca_dev *gspca_dev,
                        struct v4l2_querymenu *menu)
 {
@@ -1418,27 +1172,47 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
+#define SFCI(sensor, flags, nctrls, i2c_addr) \
+       .driver_info = (SENSOR_ ## sensor << 24) \
+                       | ((flags) << 16) \
+                       | ((nctrls) << 8) \
+                       | (i2c_addr)
 static __devinitdata struct usb_device_id device_table[] = {
 #ifndef CONFIG_USB_SN9C102
-       {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
-       {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
-       {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
-       {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
-       {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
+       {USB_DEVICE(0x0c45, 0x6001),                    /* SN9C102 */
+                       SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
+       {USB_DEVICE(0x0c45, 0x6005),                    /* SN9C101 */
+                       SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
+       {USB_DEVICE(0x0c45, 0x6007),                    /* SN9C101 */
+                       SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
+       {USB_DEVICE(0x0c45, 0x6009),                    /* SN9C101 */
+                       SFCI(PAS106, F_SIF, 2, 0)},
+       {USB_DEVICE(0x0c45, 0x600d),                    /* SN9C101 */
+                       SFCI(PAS106, F_SIF, 2, 0)},
 #endif
-       {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
+       {USB_DEVICE(0x0c45, 0x6011),            /* SN9C101 - SN9C101G */
+                       SFCI(OV6650, F_GAIN|F_AUTO|F_SIF, 5, 0x60)},
 #ifndef CONFIG_USB_SN9C102
-       {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
-       {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
-       {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
-       {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
-       {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
-       {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
-       {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
-       {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
-       {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
-       {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
+       {USB_DEVICE(0x0c45, 0x6019),                    /* SN9C101 */
+                       SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
+       {USB_DEVICE(0x0c45, 0x6024),                    /* SN9C102 */
+                       SFCI(TAS5130CXX, 0, 2, 0)},
+       {USB_DEVICE(0x0c45, 0x6025),                    /* SN9C102 */
+                       SFCI(TAS5130CXX, 0, 2, 0)},
+       {USB_DEVICE(0x0c45, 0x6028),                    /* SN9C102 */
+                       SFCI(PAS202, 0, 2, 0)},
+       {USB_DEVICE(0x0c45, 0x6029),                    /* SN9C101 */
+                       SFCI(PAS106, F_SIF, 2, 0)},
+       {USB_DEVICE(0x0c45, 0x602c),                    /* SN9C102 */
+                       SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
+       {USB_DEVICE(0x0c45, 0x602d),                    /* SN9C102 */
+                       SFCI(HV7131R, 0, 2, 0)},
+       {USB_DEVICE(0x0c45, 0x602e),                    /* SN9C102 */
+                       SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
+       {USB_DEVICE(0x0c45, 0x60af),                    /* SN9C103 */
+                       SFCI(PAS202, F_H18, 2, 0)},
+       {USB_DEVICE(0x0c45, 0x60b0),                    /* SN9C103 */
+                       SFCI(OV7630, F_GAIN|F_AUTO|F_H18, 5, 0x21)},
 #endif
        {}
 };
@@ -1464,7 +1238,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index 3e68b992695676b5bdaf3147367a6ecca26da9be..33a3df1f69150f6200635839ddc2ff92e5e81c46 100644 (file)
@@ -24,9 +24,6 @@
 #include "gspca.h"
 #include "jpeg.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -361,6 +358,7 @@ static const __u8 mo4000_sensor_init[][8] = {
 };
 static const __u8 ov7660_sensor_init[][8] = {
        {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
+/*             (delay 20ms) */
        {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
                                                /* Outformat ?? rawRGB */
        {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
@@ -539,13 +537,31 @@ static void reg_r(struct gspca_dev *gspca_dev,
                        value, 0,
                        gspca_dev->usb_buf, len,
                        500);
+       PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
 }
 
+static void reg_w1(struct gspca_dev *gspca_dev,
+                  __u16 value,
+                  __u8 data)
+{
+       PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
+       gspca_dev->usb_buf[0] = data;
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       value,
+                       0,
+                       gspca_dev->usb_buf, 1,
+                       500);
+}
 static void reg_w(struct gspca_dev *gspca_dev,
                          __u16 value,
                          const __u8 *buffer,
                          int len)
 {
+       PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
+               value, buffer[0], buffer[1]);
        if (len <= sizeof gspca_dev->usb_buf) {
                memcpy(gspca_dev->usb_buf, buffer, len);
                usb_control_msg(gspca_dev->dev,
@@ -571,31 +587,42 @@ static void reg_w(struct gspca_dev *gspca_dev,
        }
 }
 
-/* I2C write 2 bytes */
-static void i2c_w2(struct gspca_dev *gspca_dev,
-                  const __u8 *buffer)
+/* I2C write 1 byte */
+static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       __u8 mode[8];
 
-       /* is i2c ready */
-       mode[0] = 0x81 | (2 << 4);
-       mode[1] = sd->i2c_base;
-       mode[2] = buffer[0];
-       mode[3] = buffer[1];
-       mode[4] = 0;
-       mode[5] = 0;
-       mode[6] = 0;
-       mode[7] = 0x10;
-       reg_w(gspca_dev, 0x08, mode, 8);
+       PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
+       gspca_dev->usb_buf[0] = 0x81 | (2 << 4);        /* = a1 */
+       gspca_dev->usb_buf[1] = sd->i2c_base;
+       gspca_dev->usb_buf[2] = reg;
+       gspca_dev->usb_buf[3] = val;
+       gspca_dev->usb_buf[4] = 0;
+       gspca_dev->usb_buf[5] = 0;
+       gspca_dev->usb_buf[6] = 0;
+       gspca_dev->usb_buf[7] = 0x10;
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0x08,                   /* value = i2c */
+                       0,
+                       gspca_dev->usb_buf, 8,
+                       500);
 }
 
 /* I2C write 8 bytes */
 static void i2c_w8(struct gspca_dev *gspca_dev,
                   const __u8 *buffer)
 {
-       reg_w(gspca_dev, 0x08, buffer, 8);
-       msleep(1);
+       memcpy(gspca_dev->usb_buf, buffer, 8);
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0x08, 0,                /* value, index */
+                       gspca_dev->usb_buf, 8,
+                       500);
 }
 
 /* read 5 bytes in gspca_dev->usb_buf */
@@ -613,24 +640,21 @@ static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
        mode[6] = 0;
        mode[7] = 0x10;
        i2c_w8(gspca_dev, mode);
+       msleep(2);
        mode[0] = 0x81 | (5 << 4) | 0x02;
        mode[2] = 0;
        i2c_w8(gspca_dev, mode);
+       msleep(2);
        reg_r(gspca_dev, 0x0a, 5);
 }
 
 static int probesensor(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       __u8 reg02;
-       static const __u8 datasend[] = { 2, 0 };
-       /* reg val1 val2 val3 val4 */
 
-       i2c_w2(gspca_dev, datasend);
-/* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
+       i2c_w1(gspca_dev, 0x02, 0);                     /* sensor wakeup */
        msleep(10);
-       reg02 = 0x66;
-       reg_w(gspca_dev, 0x02, &reg02, 1);              /* Gpio on */
+       reg_w1(gspca_dev, 0x02, 0x66);                  /* Gpio on */
        msleep(10);
        i2c_r5(gspca_dev, 0);                           /* read sensor id */
        if (gspca_dev->usb_buf[0] == 0x02
@@ -642,7 +666,7 @@ static int probesensor(struct gspca_dev *gspca_dev)
                sd->sensor = SENSOR_HV7131R;
                return SENSOR_HV7131R;
        }
-       PDEBUG(D_PROBE, "Find Sensor %d %d %d",
+       PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
                gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
                gspca_dev->usb_buf[2]);
        PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
@@ -653,8 +677,6 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
                          const __u8 *sn9c1xx)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       __u8 data;
-       __u8 regF1;
        const __u8 *reg9a;
        static const __u8 reg9a_def[] =
                {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
@@ -663,15 +685,13 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
        static const __u8 reg9a_sn9c325[] =
                {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
 
-
-       regF1 = 0x00;
-       reg_w(gspca_dev, 0xf1, &regF1, 1);
-       reg_w(gspca_dev, 0x01, &sn9c1xx[0], 1); /*fixme:jfm was [1] en v1*/
+       reg_w1(gspca_dev, 0xf1, 0x00);
+       reg_w1(gspca_dev, 0x01, sn9c1xx[0]);    /*fixme:jfm was [1] en v1*/
 
        /* configure gpio */
        reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
        reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
-       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);      /* jfm was 3 */
+       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);      /* jfm len was 3 */
        switch (sd->bridge) {
        case BRIDGE_SN9C325:
                reg9a = reg9a_sn9c325;
@@ -685,35 +705,25 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
        }
        reg_w(gspca_dev, 0x9a, reg9a, 6);
 
-       data = 0x60;                            /*fixme:jfm 60 00 00 (3) */
-       reg_w(gspca_dev, 0xd4, &data, 1);
+       reg_w1(gspca_dev, 0xd4, 0x60);  /*fixme:jfm 60 00 00 (3) ? */
 
        reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
 
        switch (sd->bridge) {
        case BRIDGE_SN9C120:                    /* from win trace */
-               data = 0x61;
-               reg_w(gspca_dev, 0x01, &data, 1);
-               data = 0x20;
-               reg_w(gspca_dev, 0x17, &data, 1);
-               data = 0x60;
-               reg_w(gspca_dev, 0x01, &data, 1);
+               reg_w1(gspca_dev, 0x01, 0x61);
+               reg_w1(gspca_dev, 0x17, 0x20);
+               reg_w1(gspca_dev, 0x01, 0x60);
                break;
        case BRIDGE_SN9C325:
-               data = 0x43;
-               reg_w(gspca_dev, 0x01, &data, 1);
-               data = 0xae;
-               reg_w(gspca_dev, 0x17, &data, 1);
-               data = 0x42;
-               reg_w(gspca_dev, 0x01, &data, 1);
+               reg_w1(gspca_dev, 0x01, 0x43);
+               reg_w1(gspca_dev, 0x17, 0xae);
+               reg_w1(gspca_dev, 0x01, 0x42);
                break;
        default:
-               data = 0x43;
-               reg_w(gspca_dev, 0x01, &data, 1);
-               data = 0x61;
-               reg_w(gspca_dev, 0x17, &data, 1);
-               data = 0x42;
-               reg_w(gspca_dev, 0x01, &data, 1);
+               reg_w1(gspca_dev, 0x01, 0x43);
+               reg_w1(gspca_dev, 0x17, 0x61);
+               reg_w1(gspca_dev, 0x01, 0x42);
        }
 
        if (sd->sensor == SENSOR_HV7131R) {
@@ -770,6 +780,9 @@ static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
 {
        int i = 0;
 
+       i2c_w8(gspca_dev, ov7660_sensor_init[i]);       /* reset SCCB */
+       i++;
+       msleep(20);
        while (ov7660_sensor_init[i][0]) {
                i2c_w8(gspca_dev, ov7660_sensor_init[i]);
                i++;
@@ -782,194 +795,16 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
-       __u16 vendor;
-       __u16 product;
-
-       vendor = id->idVendor;
-       product = id->idProduct;
-       sd->sensor = -1;
-       switch (vendor) {
-       case 0x0458:                            /* Genius */
-/*             switch (product) {
-               case 0x7025: */
-                       sd->bridge = BRIDGE_SN9C120;
-                       sd->sensor = SENSOR_MI0360;
-                       sd->i2c_base = 0x5d;
-/*                     break;
-               } */
-               break;
-       case 0x045e:
-/*             switch (product) {
-               case 0x00f5:
-               case 0x00f7: */
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_OV7660;
-                       sd->i2c_base = 0x21;
-/*                     break;
-               } */
-               break;
-       case 0x0471:                            /* Philips */
-/*             switch (product) {
-               case 0x0327:
-               case 0x0328:
-               case 0x0330: */
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_MI0360;
-                       sd->i2c_base = 0x5d;
-/*                     break;
-               } */
-               break;
-       case 0x0c45:                            /* Sonix */
-               switch (product) {
-               case 0x6040:
-                       sd->bridge = BRIDGE_SN9C102P;
-/*                     sd->sensor = SENSOR_MI0360;      * from BW600.inf */
-/*fixme: MI0360 base=5d ? */
-                       sd->sensor = SENSOR_HV7131R;    /* gspcav1 value */
-                       sd->i2c_base = 0x11;
-                       break;
-/*             case 0x607a:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C102P;
-                       sd->sensor = SENSOR_OV7648;
-                       sd->i2c_base = 0x??;
-                       break; */
-               case 0x607c:
-                       sd->bridge = BRIDGE_SN9C102P;
-                       sd->sensor = SENSOR_HV7131R;
-                       sd->i2c_base = 0x11;
-                       break;
-/*             case 0x607e:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C102P;
-                       sd->sensor = SENSOR_OV7630;
-                       sd->i2c_base = 0x??;
-                       break; */
-               case 0x60c0:
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_MI0360;
-                       sd->i2c_base = 0x5d;
-                       break;
-/*             case 0x60c8:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_OM6801;
-                       sd->i2c_base = 0x??;
-                       break; */
-/*             case 0x60cc:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_HV7131GP;
-                       sd->i2c_base = 0x??;
-                       break; */
-               case 0x60ec:
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_MO4000;
-                       sd->i2c_base = 0x21;
-                       break;
-/*             case 0x60ef:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_ICM105C;
-                       sd->i2c_base = 0x??;
-                       break; */
-/*             case 0x60fa:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_OV7648;
-                       sd->i2c_base = 0x??;
-                       break; */
-               case 0x60fb:
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_OV7660;
-                       sd->i2c_base = 0x21;
-                       break;
-               case 0x60fc:
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_HV7131R;
-                       sd->i2c_base = 0x11;
-                       break;
-/*             case 0x60fe:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C105;
-                       sd->sensor = SENSOR_OV7630;
-                       sd->i2c_base = 0x??;
-                       break; */
-/*             case 0x6108:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C120;
-                       sd->sensor = SENSOR_OM6801;
-                       sd->i2c_base = 0x??;
-                       break; */
-/*             case 0x6122:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C110;
-                       sd->sensor = SENSOR_ICM105C;
-                       sd->i2c_base = 0x??;
-                       break; */
-               case 0x612a:
-/*                     sd->bridge = BRIDGE_SN9C110;     * in BW600.inf */
-                       sd->bridge = BRIDGE_SN9C325;
-                       sd->sensor = SENSOR_OV7648;
-                       sd->i2c_base = 0x21;
-/*fixme: sensor_init has base = 00 et 6e!*/
-                       break;
-/*             case 0x6123:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C110;
-                       sd->sensor = SENSOR_SanyoCCD;
-                       sd->i2c_base = 0x??;
-                       break; */
-               case 0x612c:
-                       sd->bridge = BRIDGE_SN9C110;
-                       sd->sensor = SENSOR_MO4000;
-                       sd->i2c_base = 0x21;
-                       break;
-/*             case 0x612e:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C110;
-                       sd->sensor = SENSOR_OV7630;
-                       sd->i2c_base = 0x??;
-                       break; */
-/*             case 0x612f:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C110;
-                       sd->sensor = SENSOR_ICM105C;
-                       sd->i2c_base = 0x??;
-                       break; */
-               case 0x6130:
-                       sd->bridge = BRIDGE_SN9C120;
-                       sd->sensor = SENSOR_MI0360;
-                       sd->i2c_base = 0x5d;
-                       break;
-               case 0x6138:
-                       sd->bridge = BRIDGE_SN9C120;
-                       sd->sensor = SENSOR_MO4000;
-                       sd->i2c_base = 0x21;
-                       break;
-/*             case 0x613a:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C120;
-                       sd->sensor = SENSOR_OV7648;
-                       sd->i2c_base = 0x??;
-                       break; */
-               case 0x613b:
-                       sd->bridge = BRIDGE_SN9C120;
-                       sd->sensor = SENSOR_OV7660;
-                       sd->i2c_base = 0x21;
-                       break;
-               case 0x613c:
-                       sd->bridge = BRIDGE_SN9C120;
-                       sd->sensor = SENSOR_HV7131R;
-                       sd->i2c_base = 0x11;
-                       break;
-/*             case 0x613e:                            * from BW600.inf
-                       sd->bridge = BRIDGE_SN9C120;
-                       sd->sensor = SENSOR_OV7630;
-                       sd->i2c_base = 0x??;
-                       break; */
-               }
-               break;
-       }
-       if (sd->sensor < 0) {
-               PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
-                       vendor, product);
-               return -EINVAL;
-       }
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        cam->cam_mode = vga_mode;
        cam->nmodes = ARRAY_SIZE(vga_mode);
 
+       sd->bridge = id->driver_info >> 16;
+       sd->sensor = id->driver_info >> 8;
+       sd->i2c_base = id->driver_info;
+
        sd->qindex = 4;                 /* set the quantization table */
        sd->brightness = BRIGHTNESS_DEF;
        sd->contrast = CONTRAST_DEF;
@@ -983,34 +818,26 @@ static int sd_open(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 /*     const __u8 *sn9c1xx; */
-       __u8 regF1;
        __u8 regGpio[] = { 0x29, 0x74 };
+       __u8 regF1;
 
        /* setup a selector by bridge */
-       regF1 = 0x01;
-       reg_w(gspca_dev, 0xf1, &regF1, 1);
+       reg_w1(gspca_dev, 0xf1, 0x01);
        reg_r(gspca_dev, 0x00, 1);              /* -> regF1 = 0x00 */
-       regF1 = gspca_dev->usb_buf[0];
-       reg_w(gspca_dev, 0xf1, &regF1, 1);
+       reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
        reg_r(gspca_dev, 0x00, 1);
        regF1 = gspca_dev->usb_buf[0];
        switch (sd->bridge) {
        case BRIDGE_SN9C102P:
                if (regF1 != 0x11)
                        return -ENODEV;
-               reg_w(gspca_dev, 0x02, &regGpio[1], 1);
+               reg_w1(gspca_dev, 0x02, regGpio[1]);
                break;
        case BRIDGE_SN9C105:
                if (regF1 != 0x11)
                        return -ENODEV;
                reg_w(gspca_dev, 0x02, regGpio, 2);
                break;
-       case BRIDGE_SN9C110:
-               if (regF1 != 0x12)
-                       return -ENODEV;
-               regGpio[1] = 0x62;
-               reg_w(gspca_dev, 0x02, &regGpio[1], 1);
-               break;
        case BRIDGE_SN9C120:
                if (regF1 != 0x12)
                        return -ENODEV;
@@ -1018,16 +845,15 @@ static int sd_open(struct gspca_dev *gspca_dev)
                reg_w(gspca_dev, 0x02, regGpio, 2);
                break;
        default:
+/*     case BRIDGE_SN9C110: */
 /*     case BRIDGE_SN9C325: */
                if (regF1 != 0x12)
                        return -ENODEV;
-               regGpio[1] = 0x62;
-               reg_w(gspca_dev, 0x02, &regGpio[1], 1);
+               reg_w1(gspca_dev, 0x02, 0x62);
                break;
        }
 
-       regF1 = 0x01;
-       reg_w(gspca_dev, 0xf1, &regF1, 1);
+       reg_w1(gspca_dev, 0xf1, 0x01);
 
        return 0;
 }
@@ -1123,7 +949,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
        }
 
        k2 = sd->brightness >> 10;
-       reg_w(gspca_dev, 0x96, &k2, 1);
+       reg_w1(gspca_dev, 0x96, k2);
 }
 
 static void setcontrast(struct gspca_dev *gspca_dev)
@@ -1152,7 +978,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
                data = (colour + 32) & 0x7f;    /* blue */
        else
                data = (-colour + 32) & 0x7f;   /* red */
-       reg_w(gspca_dev, 0x05, &data, 1);
+       reg_w1(gspca_dev, 0x05, data);
 }
 
 /* -- start the camera -- */
@@ -1165,7 +991,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
        __u8 reg17;
        const __u8 *sn9c1xx;
        int mode;
-       static const __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
        static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
        static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
        static const __u8 CA_sn9c120[] =
@@ -1179,21 +1004,20 @@ static void sd_start(struct gspca_dev *gspca_dev)
 
 /*fixme:jfm this sequence should appear at end of sd_start */
 /* with
-       data = 0x44;
-       reg_w(gspca_dev, 0x01, &data, 1); */
-       reg_w(gspca_dev, 0x15, &sn9c1xx[0x15], 1);
-       reg_w(gspca_dev, 0x16, &sn9c1xx[0x16], 1);
-       reg_w(gspca_dev, 0x12, &sn9c1xx[0x12], 1);
-       reg_w(gspca_dev, 0x13, &sn9c1xx[0x13], 1);
-       reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
-       reg_w(gspca_dev, 0xd2, &DC29[0], 1);
-       reg_w(gspca_dev, 0xd3, &DC29[1], 1);
-       reg_w(gspca_dev, 0xc6, &DC29[2], 1);
-       reg_w(gspca_dev, 0xc7, &DC29[3], 1);
-       reg_w(gspca_dev, 0xc8, &DC29[4], 1);
-       reg_w(gspca_dev, 0xc9, &DC29[5], 1);
+       reg_w1(gspca_dev, 0x01, 0x44); */
+       reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
+       reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
+       reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
+       reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
+       reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
+       reg_w1(gspca_dev, 0xd2, 0x6a);          /* DC29 */
+       reg_w1(gspca_dev, 0xd3, 0x50);
+       reg_w1(gspca_dev, 0xc6, 0x00);
+       reg_w1(gspca_dev, 0xc7, 0x00);
+       reg_w1(gspca_dev, 0xc8, 0x50);
+       reg_w1(gspca_dev, 0xc9, 0x3c);
 /*fixme:jfm end of ending sequence */
-       reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
+       reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
        switch (sd->bridge) {
        case BRIDGE_SN9C325:
                data = 0xae;
@@ -1205,11 +1029,11 @@ static void sd_start(struct gspca_dev *gspca_dev)
                data = 0x60;
                break;
        }
-       reg_w(gspca_dev, 0x17, &data, 1);
-       reg_w(gspca_dev, 0x05, &sn9c1xx[5], 1);
-       reg_w(gspca_dev, 0x07, &sn9c1xx[7], 1);
-       reg_w(gspca_dev, 0x06, &sn9c1xx[6], 1);
-       reg_w(gspca_dev, 0x14, &sn9c1xx[0x14], 1);
+       reg_w1(gspca_dev, 0x17, data);
+       reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
+       reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
+       reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
+       reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
        switch (sd->bridge) {
        case BRIDGE_SN9C325:
                reg_w(gspca_dev, 0x20, regsn20_sn9c325,
@@ -1217,10 +1041,8 @@ static void sd_start(struct gspca_dev *gspca_dev)
                for (i = 0; i < 8; i++)
                        reg_w(gspca_dev, 0x84, reg84_sn9c325,
                                        sizeof reg84_sn9c325);
-               data = 0x0a;
-               reg_w(gspca_dev, 0x9a, &data, 1);
-               data = 0x60;
-               reg_w(gspca_dev, 0x99, &data, 1);
+               reg_w1(gspca_dev, 0x9a, 0x0a);
+               reg_w1(gspca_dev, 0x99, 0x60);
                break;
        case BRIDGE_SN9C120:
                reg_w(gspca_dev, 0x20, regsn20_sn9c120,
@@ -1233,39 +1055,30 @@ static void sd_start(struct gspca_dev *gspca_dev)
                                        sizeof reg84_sn9c120_2);
                reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
                                sizeof reg84_sn9c120_3);
-               data = 0x05;
-               reg_w(gspca_dev, 0x9a, &data, 1);
-               data = 0x5b;
-               reg_w(gspca_dev, 0x99, &data, 1);
+               reg_w1(gspca_dev, 0x9a, 0x05);
+               reg_w1(gspca_dev, 0x99, 0x5b);
                break;
        default:
                reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
                for (i = 0; i < 8; i++)
                        reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
-               data = 0x08;
-               reg_w(gspca_dev, 0x9a, &data, 1);
-               data = 0x59;
-               reg_w(gspca_dev, 0x99, &data, 1);
+               reg_w1(gspca_dev, 0x9a, 0x08);
+               reg_w1(gspca_dev, 0x99, 0x59);
                break;
        }
 
        mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-       reg1 = 0x02;
+       if (mode)
+               reg1 = 0x46;    /* 320 clk 48Mhz */
+       else
+               reg1 = 0x06;    /* 640 clk 24Mz */
        reg17 = 0x61;
        switch (sd->sensor) {
        case SENSOR_HV7131R:
                hv7131R_InitSensor(gspca_dev);
-               if (mode)
-                       reg1 = 0x46;    /* 320 clk 48Mhz */
-               else
-                       reg1 = 0x06;    /* 640 clk 24Mz */
                break;
        case SENSOR_MI0360:
                mi0360_InitSensor(gspca_dev);
-               if (mode)
-                       reg1 = 0x46;    /* 320 clk 48Mhz */
-               else
-                       reg1 = 0x06;    /* 640 clk 24Mz */
                break;
        case SENSOR_MO4000:
                mo4000_InitSensor(gspca_dev);
@@ -1274,13 +1087,13 @@ static void sd_start(struct gspca_dev *gspca_dev)
                        reg1 = 0x06;    /* clk 24Mz */
                } else {
                        reg17 = 0x22;   /* 640 MCKSIZE */
-                       reg1 = 0x06;    /* 640 clk 24Mz */
+/*                     reg1 = 0x06;     * 640 clk 24Mz (done) */
                }
                break;
        case SENSOR_OV7648:
+               ov7648_InitSensor(gspca_dev);
                reg17 = 0xa2;
                reg1 = 0x44;
-               ov7648_InitSensor(gspca_dev);
 /*             if (mode)
                        ;                * 320x2...
                else
@@ -1292,7 +1105,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                if (mode) {
 /*                     reg17 = 0x21;    * 320 */
 /*                     reg1 = 0x44; */
-                       reg1 = 0x46;
+/*                     reg1 = 0x46;    (done) */
                } else {
                        reg17 = 0xa2;   /* 640 */
                        reg1 = 0x40;
@@ -1321,16 +1134,16 @@ static void sd_start(struct gspca_dev *gspca_dev)
 
        /* here change size mode 0 -> VGA; 1 -> CIF */
        data = 0x40 | sn9c1xx[0x18] | (mode << 4);
-       reg_w(gspca_dev, 0x18, &data, 1);
+       reg_w1(gspca_dev, 0x18, data);
 
        reg_w(gspca_dev, 0x100, qtable4, 0x40);
        reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
 
        data = sn9c1xx[0x18] | (mode << 4);
-       reg_w(gspca_dev, 0x18, &data, 1);
+       reg_w1(gspca_dev, 0x18, data);
 
-       reg_w(gspca_dev, 0x17, &reg17, 1);
-       reg_w(gspca_dev, 0x01, &reg1, 1);
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg_w1(gspca_dev, 0x01, reg1);
        setbrightness(gspca_dev);
        setcontrast(gspca_dev);
 }
@@ -1342,7 +1155,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
        static const __u8 stopmi0360[] =
                { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
-       __u8 regF1;
        __u8 data;
        const __u8 *sn9c1xx;
 
@@ -1366,12 +1178,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                break;
        }
        sn9c1xx = sn_tb[(int) sd->sensor];
-       reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
-       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 1);
-       reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
-       reg_w(gspca_dev, 0x01, &data, 1);
-       regF1 = 0x01;
-       reg_w(gspca_dev, 0xf1, &regF1, 1);
+       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
+       reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
+       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
+       reg_w1(gspca_dev, 0x01, data);
+       reg_w1(gspca_dev, 0xf1, 0x01);
 }
 
 static void sd_stop0(struct gspca_dev *gspca_dev)
@@ -1610,30 +1421,53 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
+#define BSI(bridge, sensor, i2c_addr) \
+       .driver_info = (BRIDGE_ ## bridge << 16) \
+                       | (SENSOR_ ## sensor << 8) \
+                       | (i2c_addr)
 static const __devinitdata struct usb_device_id device_table[] = {
 #ifndef CONFIG_USB_SN9C102
-       {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
-       {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
-       {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
-       {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
-       {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
+       {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
+       {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
+       {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
+       {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
+       {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
 #endif
-       {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
-       {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
-       {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
-       {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
-       {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
-       {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
-       {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
-       {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
-       {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
+       {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
+       {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
+/* bw600.inf:
+       {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
+/*     {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
+/*     {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
+       {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
+/*     {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
+       {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
+/*     {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
+/*     {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
+       {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
+/*     {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
+/*     {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
+       {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
+       {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
+/*     {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
+/*     {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
+/*     {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
+/*     {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
+       {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
+/* bw600.inf:
+       {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
+       {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
+/*     {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
+/*     {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
 #ifndef CONFIG_USB_SN9C102
-       {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
-       {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
-       {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
-       {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
+       {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
+       {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
+/*     {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
+       {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
+       {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
+/*     {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
 #endif
+       {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1658,7 +1492,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       info("v%s registered", version);
+       info("registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index 15620611879555a7797cd8c4675530ac0e77c4cb..17fe2c2a440d8f222f434c4c2692db093ef4e50d 100644 (file)
@@ -24,9 +24,6 @@
 #include "gspca.h"
 #include "jpeg.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -630,109 +627,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
-       __u16 vendor;
-       __u16 product;
-
-       vendor = id->idVendor;
-       product = id->idProduct;
-       switch (vendor) {
-       case 0x040a:            /* Kodak cameras */
-/*             switch (product) { */
-/*             case 0x0300: */
-                       sd->subtype = KodakEZ200;
-/*                     break; */
-/*             } */
-               break;
-       case 0x041e:            /* Creative cameras */
-/*             switch (product) { */
-/*             case 0x400a: */
-                       sd->subtype = CreativePCCam300;
-/*                     break; */
-/*             } */
-               break;
-       case 0x046d:            /* Logitech Labtec */
-               switch (product) {
-               case 0x0890:
-                       sd->subtype = LogitechTraveler;
-                       break;
-               case 0x0900:
-                       sd->subtype = LogitechClickSmart310;
-                       break;
-               case 0x0901:
-                       sd->subtype = LogitechClickSmart510;
-                       break;
-               }
-               break;
-       case 0x04a5:            /* Benq */
-/*             switch (product) { */
-/*             case 0x300c: */
-                       sd->subtype = BenqDC1016;
-/*                     break; */
-/*             } */
-               break;
-       case 0x04fc:            /* SunPlus */
-/*             switch (product) { */
-/*             case 0x7333: */
-                       sd->subtype = PalmPixDC85;
-/*                     break; */
-/*             } */
-               break;
-       case 0x055f:            /* Mustek cameras */
-               switch (product) {
-               case 0xc200:
-                       sd->subtype = MustekGsmart300;
-                       break;
-               case 0xc220:
-                       sd->subtype = Gsmartmini;
-                       break;
-               }
-               break;
-       case 0x06bd:            /* Agfa Cl20 */
-/*             switch (product) { */
-/*             case 0x0404: */
-                       sd->subtype = AgfaCl20;
-/*                     break; */
-/*             } */
-               break;
-       case 0x06be:            /* Optimedia */
-/*             switch (product) { */
-/*             case 0x0800: */
-                       sd->subtype = Optimedia;
-/*                     break; */
-/*             } */
-               break;
-       case 0x084d:            /* D-Link / Minton */
-/*             switch (product) { */
-/*             case 0x0003:     * DSC-350 / S-Cam F5 */
-                       sd->subtype = DLinkDSC350;
-/*                     break; */
-/*             } */
-               break;
-       case 0x08ca:            /* Aiptek */
-/*             switch (product) { */
-/*             case 0x0103: */
-                       sd->subtype = AiptekPocketDV;
-/*                     break; */
-/*             } */
-               break;
-       case 0x2899:            /* ToptroIndustrial */
-/*             switch (product) { */
-/*             case 0x012c: */
-                       sd->subtype = ToptroIndus;
-/*                     break; */
-/*             } */
-               break;
-       case 0x8086:            /* Intel */
-/*             switch (product) { */
-/*             case 0x0630:     * Pocket PC Camera */
-                       sd->subtype = IntelPocketPCCamera;
-/*                     break; */
-/*             } */
-               break;
-       }
+
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
+       sd->subtype = id->driver_info;
        if (sd->subtype != LogitechClickSmart310) {
                cam->cam_mode = vga_mode;
                cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
@@ -1162,23 +1060,22 @@ static struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x040a, 0x0300), DVNM("Kodak EZ200")},
-       {USB_DEVICE(0x041e, 0x400a), DVNM("Creative PC-CAM 300")},
-       {USB_DEVICE(0x046d, 0x0890), DVNM("Logitech QuickCam traveler")},
-       {USB_DEVICE(0x046d, 0x0900), DVNM("Logitech Inc. ClickSmart 310")},
-       {USB_DEVICE(0x046d, 0x0901), DVNM("Logitech Inc. ClickSmart 510")},
-       {USB_DEVICE(0x04a5, 0x300c), DVNM("Benq DC1016")},
-       {USB_DEVICE(0x04fc, 0x7333), DVNM("PalmPixDC85")},
-       {USB_DEVICE(0x055f, 0xc200), DVNM("Mustek Gsmart 300")},
-       {USB_DEVICE(0x055f, 0xc220), DVNM("Gsmart Mini")},
-       {USB_DEVICE(0x06bd, 0x0404), DVNM("Agfa CL20")},
-       {USB_DEVICE(0x06be, 0x0800), DVNM("Optimedia")},
-       {USB_DEVICE(0x084d, 0x0003), DVNM("D-Link DSC-350")},
-       {USB_DEVICE(0x08ca, 0x0103), DVNM("Aiptek PocketDV")},
-       {USB_DEVICE(0x2899, 0x012c), DVNM("Toptro Industrial")},
-       {USB_DEVICE(0x8086, 0x0630), DVNM("Intel Pocket PC Camera")},
+       {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
+       {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
+       {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
+       {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
+       {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
+       {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
+       {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
+       {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
+       {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
+       {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
+       {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
+       {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
+       {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
+       {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
+       {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1203,7 +1100,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index 50e929de02036c78d259d96587e937835bca30f3..51a3c3429ef0c26b2f71cb2e9439eec3d1b98921 100644 (file)
@@ -23,9 +23,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SPCA501 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -1923,63 +1920,12 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
-       __u16 vendor;
-       __u16 product;
-
-       vendor = id->idVendor;
-       product = id->idProduct;
-       switch (vendor) {
-       case 0x0000:            /* Unknow Camera */
-/*             switch (product) { */
-/*             case 0x0000: */
-                       sd->subtype = MystFromOriUnknownCamera;
-/*                     break; */
-/*             } */
-               break;
-       case 0x040a:            /* Kodak cameras */
-/*             switch (product) { */
-/*             case 0x0002: */
-                       sd->subtype = KodakDVC325;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0497:            /* Smile International */
-/*             switch (product) { */
-/*             case 0xc001: */
-                       sd->subtype = SmileIntlCamera;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0506:            /* 3COM cameras */
-/*             switch (product) { */
-/*             case 0x00df: */
-                       sd->subtype = ThreeComHomeConnectLite;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0733:    /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
-               switch (product) {
-               case 0x0401:
-                       sd->subtype = IntelCreateAndShare;
-                       break;
-               case 0x0402:
-                       sd->subtype = ViewQuestM318B;
-                       break;
-               }
-               break;
-       case 0x1776:            /* Arowana */
-/*             switch (product) { */
-/*             case 0x501c: */
-                       sd->subtype = Arowana300KCMOSCamera;
-/*                     break; */
-/*             } */
-               break;
-       }
+
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        cam->cam_mode = vga_mode;
        cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+       sd->subtype = id->driver_info;
        sd->brightness = sd_ctrls[MY_BRIGHTNESS].qctrl.default_value;
        sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value;
        sd->colors = sd_ctrls[MY_COLOR].qctrl.default_value;
@@ -2183,15 +2129,14 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x040a, 0x0002), DVNM("Kodak DVC-325")},
-       {USB_DEVICE(0x0497, 0xc001), DVNM("Smile International")},
-       {USB_DEVICE(0x0506, 0x00df), DVNM("3Com HomeConnect Lite")},
-       {USB_DEVICE(0x0733, 0x0401), DVNM("Intel Create and Share")},
-       {USB_DEVICE(0x0733, 0x0402), DVNM("ViewQuest M318B")},
-       {USB_DEVICE(0x1776, 0x501c), DVNM("Arowana 300K CMOS Camera")},
-       {USB_DEVICE(0x0000, 0x0000), DVNM("MystFromOri Unknow Camera")},
+       {USB_DEVICE(0x040a, 0x0002), .driver_info = KodakDVC325},
+       {USB_DEVICE(0x0497, 0xc001), .driver_info = SmileIntlCamera},
+       {USB_DEVICE(0x0506, 0x00df), .driver_info = ThreeComHomeConnectLite},
+       {USB_DEVICE(0x0733, 0x0401), .driver_info = IntelCreateAndShare},
+       {USB_DEVICE(0x0733, 0x0402), .driver_info = ViewQuestM318B},
+       {USB_DEVICE(0x1776, 0x501c), .driver_info = Arowana300KCMOSCamera},
+       {USB_DEVICE(0x0000, 0x0000), .driver_info = MystFromOriUnknownCamera},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -2216,7 +2161,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index ddea6e140aa833bbc1d7b7167da0354828834406..3c2be80cbd65033c0ba507fc0068948a88c2ffbf 100644 (file)
@@ -23,9 +23,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -34,10 +31,6 @@ MODULE_LICENSE("GPL");
 struct sd {
        struct gspca_dev gspca_dev;             /* !! must be the first item */
 
-       int buflen;
-       unsigned char tmpbuf[640 * 480 * 3 / 2]; /* YYUV per line */
-       unsigned char tmpbuf2[640 * 480 * 2];   /* YUYV */
-
        unsigned char brightness;
 
        char subtype;
@@ -67,29 +60,29 @@ static struct ctrl sd_ctrls[] = {
 };
 
 static struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 160 * 2,
-               .sizeimage = 160 * 120 * 2,
+       {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 160 * 3,
+               .sizeimage = 160 * 120 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 5},
-       {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 176 * 2,
-               .sizeimage = 176 * 144 * 2,
+       {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 176 * 3,
+               .sizeimage = 176 * 144 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 4},
-       {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 320 * 2,
-               .sizeimage = 320 * 240 * 2,
+       {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 320 * 3,
+               .sizeimage = 320 * 240 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 2},
-       {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 352 * 2,
-               .sizeimage = 352 * 288 * 2,
+       {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 352 * 3,
+               .sizeimage = 352 * 288 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 1},
-       {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 640 * 2,
-               .sizeimage = 640 * 480 * 2,
+       {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 640 * 3,
+               .sizeimage = 640 * 480 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 0},
 };
@@ -641,33 +634,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
-       __u16 vendor;
-       __u16 product;
-
-       vendor = id->idVendor;
-       product = id->idProduct;
-       switch (vendor) {
-       case 0x041e:            /* Creative cameras */
-/*             switch (product) { */
-/*             case 0x401d:     * here505b */
-                       sd->subtype = Nxultra;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0733:    /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
-/*             switch (product) { */
-/*             case 0x0430: */
-/*             fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
-                       sd->subtype = IntelPCCameraPro;
-/*                     break; */
-/*             } */
-               break;
-       }
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        cam->cam_mode = vga_mode;
+       sd->subtype = id->driver_info;
        if (sd->subtype != IntelPCCameraPro)
                cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
        else                    /* no 640x480 for IntelPCCameraPro */
@@ -785,77 +756,30 @@ static void sd_close(struct gspca_dev *gspca_dev)
        reg_write(gspca_dev->dev, 0x05, 0x11, 0xf);
 }
 
-/* convert YYUV per line to YUYV (YUV 4:2:2) */
-static void yyuv_decode(unsigned char *out,
-                       unsigned char *in,
-                       int width,
-                       int height)
-{
-       unsigned char *Ui, *Vi, *yi, *yi1;
-       unsigned char *out1;
-       int i, j;
-
-       yi = in;
-       for (i = height / 2; --i >= 0; ) {
-               out1 = out + width * 2;         /* next line */
-               yi1 = yi + width;
-               Ui = yi1 + width;
-               Vi = Ui + width / 2;
-               for (j = width / 2; --j >= 0; ) {
-                       *out++ = 128 + *yi++;
-                       *out++ = 128 + *Ui;
-                       *out++ = 128 + *yi++;
-                       *out++ = 128 + *Vi;
-
-                       *out1++ = 128 + *yi1++;
-                       *out1++ = 128 + *Ui++;
-                       *out1++ = 128 + *yi1++;
-                       *out1++ = 128 + *Vi++;
-               }
-               yi += width * 2;
-               out = out1;
-       }
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
                        int len)                        /* iso packet length */
 {
-       struct sd *sd = (struct sd *) gspca_dev;
-
        switch (data[0]) {
        case 0:                         /* start of frame */
-               if (gspca_dev->last_packet_type == FIRST_PACKET) {
-                       yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
-                                       gspca_dev->width,
-                                       gspca_dev->height);
-                       frame = gspca_frame_add(gspca_dev,
-                                               LAST_PACKET,
-                                               frame,
-                                               sd->tmpbuf2,
-                                               gspca_dev->width
-                                                       * gspca_dev->height
-                                                       * 2);
-               }
-               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
-                               data, 0);
+               frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+                                       data, 0);
                data += SPCA50X_OFFSET_DATA;
                len -= SPCA50X_OFFSET_DATA;
-               if (len > 0)
-                       memcpy(sd->tmpbuf, data, len);
-               else
-                       len = 0;
-               sd->buflen = len;
-               return;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                               data, len);
+               break;
        case 0xff:                      /* drop */
 /*             gspca_dev->last_packet_type = DISCARD_PACKET; */
-               return;
+               break;
+       default:
+               data += 1;
+               len -= 1;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                               data, len);
+               break;
        }
-       data += 1;
-       len -= 1;
-       memcpy(&sd->tmpbuf[sd->buflen], data, len);
-       sd->buflen += len;
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev)
@@ -910,10 +834,10 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x401d), DVNM("Creative Webcam NX ULTRA")},
-       {USB_DEVICE(0x0733, 0x0430), DVNM("Intel PC Camera Pro")},
+       {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
+       {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
+/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -938,7 +862,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index 143203c1fd9fbf92772f26714321e31ce8097561..6fe715c80ad2b0757f22b759fb7b22253a77c141 100644 (file)
@@ -25,9 +25,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -36,10 +33,6 @@ MODULE_LICENSE("GPL");
 struct sd {
        struct gspca_dev gspca_dev;     /* !! must be the first item */
 
-       int buflen;
-       __u8 tmpbuf[640 * 480 * 3];     /* YYUV per line */
-       __u8 tmpbuf2[640 * 480 * 2];    /* YUYV */
-
        unsigned char brightness;
        unsigned char contrast;
        unsigned char colors;
@@ -118,29 +111,29 @@ static struct ctrl sd_ctrls[] = {
 };
 
 static struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 160 * 2,
-               .sizeimage = 160 * 120 * 2,
+       {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 160 * 3,
+               .sizeimage = 160 * 120 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 5},
-       {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 176 * 2,
-               .sizeimage = 176 * 144 * 2,
+       {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 176 * 3,
+               .sizeimage = 176 * 144 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 4},
-       {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 320 * 2,
-               .sizeimage = 320 * 240 * 2,
+       {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 320 * 3,
+               .sizeimage = 320 * 240 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 2},
-       {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 352 * 2,
-               .sizeimage = 352 * 288 * 2,
+       {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 352 * 3,
+               .sizeimage = 352 * 288 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 1},
-       {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 640 * 2,
-               .sizeimage = 640 * 480 * 2,
+       {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 640 * 3,
+               .sizeimage = 640 * 480 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 0},
 };
@@ -310,7 +303,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        cam->cam_mode = vga_mode;
        cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
@@ -576,77 +568,30 @@ static void sd_close(struct gspca_dev *gspca_dev)
 {
 }
 
-/* convert YYUV per line to YUYV (YUV 4:2:2) */
-static void yyuv_decode(unsigned char *out,
-                       unsigned char *in,
-                       int width,
-                       int height)
-{
-       unsigned char *Ui, *Vi, *yi, *yi1;
-       unsigned char *out1;
-       int i, j;
-
-       yi = in;
-       for (i = height / 2; --i >= 0; ) {
-               out1 = out + width * 2;         /* next line */
-               yi1 = yi + width;
-               Ui = yi1 + width;
-               Vi = Ui + width / 2;
-               for (j = width / 2; --j >= 0; ) {
-                       *out++ = 128 + *yi++;
-                       *out++ = 128 + *Ui;
-                       *out++ = 128 + *yi++;
-                       *out++ = 128 + *Vi;
-
-                       *out1++ = 128 + *yi1++;
-                       *out1++ = 128 + *Ui++;
-                       *out1++ = 128 + *yi1++;
-                       *out1++ = 128 + *Vi++;
-               }
-               yi += width * 2;
-               out = out1;
-       }
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
                        int len)                        /* iso packet length */
 {
-       struct sd *sd = (struct sd *) gspca_dev;
-
        switch (data[0]) {
        case 0:                         /* start of frame */
-               if (gspca_dev->last_packet_type == FIRST_PACKET) {
-                       yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
-                                       gspca_dev->width,
-                                       gspca_dev->height);
-                       frame = gspca_frame_add(gspca_dev,
-                                               LAST_PACKET,
-                                               frame,
-                                               sd->tmpbuf2,
-                                               gspca_dev->width
-                                                       * gspca_dev->height
-                                                       * 2);
-               }
-               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
-                               data, 0);
+               frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+                                       data, 0);
                data += SPCA50X_OFFSET_DATA;
                len -= SPCA50X_OFFSET_DATA;
-               if (len > 0)
-                       memcpy(sd->tmpbuf, data, len);
-               else
-                       len = 0;
-               sd->buflen = len;
-               return;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                               data, len);
+               break;
        case 0xff:                      /* drop */
 /*             gspca_dev->last_packet_type = DISCARD_PACKET; */
-               return;
+               break;
+       default:
+               data += 1;
+               len -= 1;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                               data, len);
+               break;
        }
-       data += 1;
-       len -= 1;
-       memcpy(&sd->tmpbuf[sd->buflen], data, len);
-       sd->buflen += len;
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev)
@@ -804,12 +749,12 @@ static struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x06e1, 0xa190), DVNM("ADS Instant VCD")},
-/*     {USB_DEVICE(0x0733, 0x0430), DVNM("UsbGrabber PV321c")}, */
-       {USB_DEVICE(0x0734, 0x043b), DVNM("3DeMon USB Capture aka")},
-       {USB_DEVICE(0x99fa, 0x8988), DVNM("Grandtec V.cap")},
+       {USB_DEVICE(0x06e1, 0xa190)},
+/*fixme: may be IntelPCCameraPro BRIDGE_SPCA505
+       {USB_DEVICE(0x0733, 0x0430)}, */
+       {USB_DEVICE(0x0734, 0x043b)},
+       {USB_DEVICE(0x99fa, 0x8988)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -834,7 +779,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index d8cd93866a4a6c6b9aec8f73c844ceca0420eceb..b608a27ad1156e87267b5c75620292f7285bf1f0 100644 (file)
@@ -22,9 +22,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -33,10 +30,6 @@ MODULE_LICENSE("GPL");
 struct sd {
        struct gspca_dev gspca_dev;             /* !! must be the first item */
 
-       int buflen;
-       unsigned char tmpbuf[352 * 288 * 3 / 2]; /* YUVY per line */
-       unsigned char tmpbuf2[352 * 288 * 2];   /* YUYV */
-
        unsigned char brightness;
 
        char subtype;
@@ -71,23 +64,23 @@ static struct ctrl sd_ctrls[] = {
 
 static struct v4l2_pix_format sif_mode[] = {
        {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 160 * 2,
-               .sizeimage = 160 * 120 * 2,
+               .bytesperline = 160 * 3,
+               .sizeimage = 160 * 120 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 3},
        {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 176 * 2,
-               .sizeimage = 176 * 144 * 2,
+               .bytesperline = 176 * 3,
+               .sizeimage = 176 * 144 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 2},
        {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 320 * 2,
-               .sizeimage = 320 * 240 * 2,
+               .bytesperline = 320 * 3,
+               .sizeimage = 320 * 240 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 1},
        {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 352 * 2,
-               .sizeimage = 352 * 288 * 2,
+               .bytesperline = 352 * 3,
+               .sizeimage = 352 * 288 * 3 / 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 0},
 };
@@ -1476,58 +1469,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
-       __u16 product;
        int data1, data2;
 
-       product = id->idProduct;
-       switch (id->idVendor) {
-       case 0x0130:            /* Clone webcam */
-/*             switch (product) { */
-/*             case 0x0130: */
-                       sd->subtype = HamaUSBSightcam;  /* same as Hama 0010 */
-/*                     break; */
-/*             } */
-               break;
-       case 0x041e:            /* Creative cameras */
-/*             switch (product) { */
-/*             case 0x4018: */
-                       sd->subtype = CreativeVista;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0461:            /* MicroInnovation */
-/*             switch (product) { */
-/*             case 0x0815: */
-                       sd->subtype = MicroInnovationIC200;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0733:    /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
-/*             switch (product) { */
-/*             case 0x110: */
-                       sd->subtype = ViewQuestVQ110;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0af9:            /* Hama cameras */
-               switch (product) {
-               case 0x0010:
-                       sd->subtype = HamaUSBSightcam;
-                       break;
-               case 0x0011:
-                       sd->subtype = HamaUSBSightcam2;
-                       break;
-               }
-               break;
-       case 0x8086:            /* Intel */
-/*             switch (product) { */
-/*             case 0x0110: */
-                       sd->subtype = IntelEasyPCCamera;
-/*                     break; */
-/*             } */
-               break;
-       }
-
        /* Read from global register the USB product and vendor IDs, just to
         * prove that we can communicate with the device.  This works, which
         * confirms at we are communicating properly and that the device
@@ -1544,10 +1487,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
        PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        cam->cam_mode = sif_mode;
        cam->nmodes = ARRAY_SIZE(sif_mode);
+
+       sd->subtype = id->driver_info;
        sd->brightness = BRIGHTNESS_DEF;
 
        switch (sd->subtype) {
@@ -1619,77 +1563,30 @@ static void sd_close(struct gspca_dev *gspca_dev)
 {
 }
 
-/* convert YUVY per line to YUYV (YUV 4:2:2) */
-static void yuvy_decode(unsigned char *out,
-                       unsigned char *in,
-                       int width,
-                       int height)
-{
-       unsigned char *Ui, *Vi, *yi, *yi1;
-       unsigned char *out1;
-       int i, j;
-
-       yi = in;
-       for (i = height / 2; --i >= 0; ) {
-               out1 = out + width * 2;         /* next line */
-               Ui = yi + width;
-               Vi = Ui + width / 2;
-               yi1 = Vi + width / 2;
-               for (j = width / 2; --j >= 0; ) {
-                       *out++ = 128 + *yi++;
-                       *out++ = 128 + *Ui;
-                       *out++ = 128 + *yi++;
-                       *out++ = 128 + *Vi;
-
-                       *out1++ = 128 + *yi1++;
-                       *out1++ = 128 + *Ui++;
-                       *out1++ = 128 + *yi1++;
-                       *out1++ = 128 + *Vi++;
-               }
-               yi += width * 2;
-               out = out1;
-       }
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
                        int len)                        /* iso packet length */
 {
-       struct sd *sd = (struct sd *) gspca_dev;
-
        switch (data[0]) {
        case 0:                         /* start of frame */
-               if (gspca_dev->last_packet_type == FIRST_PACKET) {
-                       yuvy_decode(sd->tmpbuf2, sd->tmpbuf,
-                                       gspca_dev->width,
-                                       gspca_dev->height);
-                       frame = gspca_frame_add(gspca_dev,
-                                               LAST_PACKET,
-                                               frame,
-                                               sd->tmpbuf2,
-                                               gspca_dev->width
-                                                       * gspca_dev->height
-                                                       * 2);
-               }
-               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
-                               data, 0);
+               frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+                                       data, 0);
                data += SPCA508_OFFSET_DATA;
                len -= SPCA508_OFFSET_DATA;
-               if (len > 0)
-                       memcpy(sd->tmpbuf, data, len);
-               else
-                       len = 0;
-               sd->buflen = len;
-               return;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                               data, len);
+               break;
        case 0xff:                      /* drop */
 /*             gspca_dev->last_packet_type = DISCARD_PACKET; */
-               return;
+               break;
+       default:
+               data += 1;
+               len -= 1;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                               data, len);
+               break;
        }
-       data += 1;
-       len -= 1;
-       memcpy(&sd->tmpbuf[sd->buflen], data, len);
-       sd->buflen += len;
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev)
@@ -1745,15 +1642,14 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0130, 0x0130), DVNM("Clone Digital Webcam 11043")},
-       {USB_DEVICE(0x041e, 0x4018), DVNM("Creative Webcam Vista (PD1100)")},
-       {USB_DEVICE(0x0461, 0x0815), DVNM("Micro Innovation IC200")},
-       {USB_DEVICE(0x0733, 0x0110), DVNM("ViewQuest VQ110")},
-       {USB_DEVICE(0x0af9, 0x0010), DVNM("Hama USB Sightcam 100")},
-       {USB_DEVICE(0x0af9, 0x0011), DVNM("Hama USB Sightcam 100")},
-       {USB_DEVICE(0x8086, 0x0110), DVNM("Intel Easy PC Camera")},
+       {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
+       {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
+       {USB_DEVICE(0x0461, 0x0815), .driver_info = MicroInnovationIC200},
+       {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
+       {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
+       {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
+       {USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1778,7 +1674,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index b659bd0f788da4d86afbbf2b21787ab443756637..a26174508cb990588dbe95d27f1ac954ab6fdb4e 100644 (file)
@@ -24,9 +24,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -582,35 +579,15 @@ static int sd_config(struct gspca_dev *gspca_dev,
                PDEBUG(D_PROBE, "Bad vendor / product from device");
                return -EINVAL;
        }
-       switch (product) {
-       case 0x0928:
-       case 0x0929:
-       case 0x092a:
-       case 0x092b:
-       case 0x092c:
-       case 0x092d:
-       case 0x092e:
-       case 0x092f:
-       case 0x403b:
-               sd->chip_revision = Rev012A;
-               break;
-       default:
-/*     case 0x0561:
-       case 0x0815:                    * ?? in spca508.c
-       case 0x401a:
-       case 0x7004:
-       case 0x7e50:
-       case 0xa001:
-       case 0xcdee: */
-               sd->chip_revision = Rev072A;
-               break;
-       }
+
        cam = &gspca_dev->cam;
        cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        gspca_dev->nbalt = 7 + 1;       /* choose alternate 7 first */
        cam->cam_mode = sif_mode;
        cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
+
+       sd->chip_revision = id->driver_info;
        sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
        sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
        sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
@@ -997,23 +974,22 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x401a), DVNM("Creative Webcam Vista (PD1100)")},
-       {USB_DEVICE(0x041e, 0x403b),  DVNM("Creative Webcam Vista (VF0010)")},
-       {USB_DEVICE(0x0458, 0x7004), DVNM("Genius VideoCAM Express V2")},
-       {USB_DEVICE(0x046d, 0x0928), DVNM("Logitech QC Express Etch2")},
-       {USB_DEVICE(0x046d, 0x0929), DVNM("Labtec Webcam Elch2")},
-       {USB_DEVICE(0x046d, 0x092a), DVNM("Logitech QC for Notebook")},
-       {USB_DEVICE(0x046d, 0x092b), DVNM("Labtec Webcam Plus")},
-       {USB_DEVICE(0x046d, 0x092c), DVNM("Logitech QC chat Elch2")},
-       {USB_DEVICE(0x046d, 0x092d), DVNM("Logitech QC Elch2")},
-       {USB_DEVICE(0x046d, 0x092e), DVNM("Logitech QC Elch2")},
-       {USB_DEVICE(0x046d, 0x092f), DVNM("Logitech QC Elch2")},
-       {USB_DEVICE(0x04fc, 0x0561), DVNM("Flexcam 100")},
-       {USB_DEVICE(0x060b, 0xa001), DVNM("Maxell Compact Pc PM3")},
-       {USB_DEVICE(0x10fd, 0x7e50), DVNM("FlyCam Usb 100")},
-       {USB_DEVICE(0xabcd, 0xcdee), DVNM("Petcam")},
+       {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
+       {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
+       {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
+       {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},
+       {USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},
+       {USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},
+       {USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},
+       {USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},
        {}
 };
 
@@ -1039,7 +1015,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index c78ee0d3e59bface920e16ac31539af824d839b1..16219cf6a6d5105b555126b5c381f7d1024bc0b7 100644 (file)
@@ -23,9 +23,6 @@
 #include "gspca.h"
 #include "jpeg.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -299,7 +296,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam = &gspca_dev->cam;
 
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x02;
        gspca_dev->cam.cam_mode = vga_mode;
        gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
@@ -549,9 +545,8 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x05e1, 0x0893), DVNM("Syntek DV4000")},
+       {USB_DEVICE(0x05e1, 0x0893)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -576,7 +571,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       info("v%s registered", version);
+       info("registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index abd7bef9b3d1b270484f6bc9d555e46fbc426b23..54efa48bee014cd55d3cde1912debbe6c348cd9b 100644 (file)
@@ -24,9 +24,6 @@
 #include "gspca.h"
 #include "jpeg.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 8)
-static const char version[] = "2.1.8";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -804,229 +801,29 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct sd *sd = (struct sd *) gspca_dev;
        struct usb_device *dev = gspca_dev->dev;
        struct cam *cam;
-       __u16 vendor;
-       __u16 product;
-       __u8 fw;
-
-       vendor = id->idVendor;
-       product = id->idProduct;
-       switch (vendor) {
-       case 0x041e:            /* Creative cameras */
-/*             switch (product) { */
-/*             case 0x400b: */
-/*             case 0x4012: */
-/*             case 0x4013: */
-/*                     sd->bridge = BRIDGE_SPCA504C; */
-/*                     break; */
-/*             } */
-               break;
-       case 0x0458:            /* Genius KYE cameras */
-/*             switch (product) { */
-/*             case 0x7006: */
-                       sd->bridge = BRIDGE_SPCA504B;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0461:            /* MicroInnovation */
-/*             switch (product) { */
-/*             case 0x0821: */
-                       sd->bridge = BRIDGE_SPCA533;
-/*                     break; */
-/*             } */
-               break;
-       case 0x046d:            /* Logitech Labtec */
-               switch (product) {
-               case 0x0905:
-                       sd->subtype = LogitechClickSmart820;
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0x0960:
-                       sd->subtype = LogitechClickSmart420;
-                       sd->bridge = BRIDGE_SPCA504C;
-                       break;
-               }
-               break;
-       case 0x0471:                            /* Philips */
-/*             switch (product) { */
-/*             case 0x0322: */
-                       sd->bridge = BRIDGE_SPCA504B;
-/*                     break; */
-/*             } */
-               break;
-       case 0x04a5:            /* Benq */
-               switch (product) {
-               case 0x3003:
-                       sd->bridge = BRIDGE_SPCA504B;
-                       break;
-               case 0x3008:
-               case 0x300a:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               }
-               break;
-       case 0x04f1:            /* JVC */
-/*             switch (product) { */
-/*             case 0x1001: */
-                       sd->bridge = BRIDGE_SPCA504B;
-/*                     break; */
-/*             } */
-               break;
-       case 0x04fc:            /* SunPlus */
-               switch (product) {
-               case 0x500c:
-                       sd->bridge = BRIDGE_SPCA504B;
-                       break;
-               case 0x504a:
+
+       cam = &gspca_dev->cam;
+       cam->epaddr = 0x01;
+
+       sd->bridge = id->driver_info >> 8;
+       sd->subtype = id->driver_info;
+
+       if (sd->subtype == AiptekMiniPenCam13) {
 /* try to get the firmware as some cam answer 2.0.1.2.2
  * and should be a spca504b then overwrite that setting */
-                       reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
-                       fw = gspca_dev->usb_buf[0];
-                       if (fw == 1) {
-                               sd->subtype = AiptekMiniPenCam13;
-                               sd->bridge = BRIDGE_SPCA504;
-                       } else if (fw == 2) {
-                               sd->bridge = BRIDGE_SPCA504B;
-                       } else
-                               return -ENODEV;
-                       break;
-               case 0x504b:
-                       sd->bridge = BRIDGE_SPCA504B;
-                       break;
-               case 0x5330:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0x5360:
-                       sd->bridge = BRIDGE_SPCA536;
-                       break;
-               case 0xffff:
-                       sd->bridge = BRIDGE_SPCA504B;
-                       break;
-               }
-               break;
-       case 0x052b:            /* ?? Megapix */
-/*             switch (product) { */
-/*             case 0x1513: */
-                       sd->subtype = MegapixV4;
-                       sd->bridge = BRIDGE_SPCA533;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0546:            /* Polaroid */
-               switch (product) {
-               case 0x3155:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0x3191:
-               case 0x3273:
-                       sd->bridge = BRIDGE_SPCA504B;
-                       break;
-               }
-               break;
-       case 0x055f:            /* Mustek cameras */
-               switch (product) {
-               case 0xc211:
-                       sd->bridge = BRIDGE_SPCA536;
-                       break;
-               case 0xc230:
-               case 0xc232:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0xc360:
-                       sd->bridge = BRIDGE_SPCA536;
-                       break;
-               case 0xc420:
-                       sd->bridge = BRIDGE_SPCA504;
-                       break;
-               case 0xc430:
-               case 0xc440:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0xc520:
-                       sd->bridge = BRIDGE_SPCA504;
-                       break;
-               case 0xc530:
-               case 0xc540:
-               case 0xc630:
-               case 0xc650:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               }
-               break;
-       case 0x05da:            /* Digital Dream cameras */
-/*             switch (product) { */
-/*             case 0x1018: */
+               reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
+               switch (gspca_dev->usb_buf[0]) {
+               case 1:
+                       break;          /* (right bridge/subtype) */
+               case 2:
                        sd->bridge = BRIDGE_SPCA504B;
-/*                     break; */
-/*             } */
-               break;
-       case 0x06d6:            /* Trust */
-/*             switch (product) { */
-/*             case 0x0031: */
-                       sd->bridge = BRIDGE_SPCA533;    /* SPCA533A */
-/*                     break; */
-/*             } */
-               break;
-       case 0x0733:    /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
-               switch (product) {
-               case 0x1311:
-               case 0x1314:
-               case 0x2211:
-               case 0x2221:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0x3261:
-               case 0x3281:
-                       sd->bridge = BRIDGE_SPCA536;
-                       break;
-               }
-               break;
-       case 0x08ca:            /* Aiptek */
-               switch (product) {
-               case 0x0104:
-               case 0x0106:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0x2008:
-                       sd->bridge = BRIDGE_SPCA504B;
-                       break;
-               case 0x2010:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0x2016:
-               case 0x2018:
-                       sd->bridge = BRIDGE_SPCA504B;
-                       break;
-               case 0x2020:
-               case 0x2022:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0x2024:
-                       sd->bridge = BRIDGE_SPCA536;
-                       break;
-               case 0x2028:
-                       sd->bridge = BRIDGE_SPCA533;
-                       break;
-               case 0x2040:
-               case 0x2042:
-               case 0x2050:
-               case 0x2060:
-                       sd->bridge = BRIDGE_SPCA536;
+                       sd->subtype = 0;
                        break;
+               default:
+                       return -ENODEV;
                }
-               break;
-       case 0x0d64:            /* SunPlus */
-/*             switch (product) { */
-/*             case 0x0303: */
-                       sd->bridge = BRIDGE_SPCA536;
-/*                     break; */
-/*             } */
-               break;
        }
 
-       cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
-       cam->epaddr = 0x01;
-
        switch (sd->bridge) {
        default:
 /*     case BRIDGE_SPCA504B: */
@@ -1581,65 +1378,67 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
+#define BS(bridge, subtype) \
+       .driver_info = (BRIDGE_ ## bridge << 8) \
+                       | (subtype)
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
-       {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
-       {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
-       {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
-       {USB_DEVICE(0x0461, 0x0821), DVNM("Fujifilm MV-1")},
-       {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
-       {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
-       {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
-       {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
-       {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
-       {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
-       {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
-       {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
-       {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
-       {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
-       {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
-       {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
-       {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
-       {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
-       {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
-       {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
-       {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
-       {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
-       {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
-       {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
-       {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
-       {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
-       {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
-       {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
-       {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
-       {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
-       {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
-       {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
-       {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
-       {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
-       {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
-       {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
-       {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
-       {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
-       {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
-       {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
-       {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
-       {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
-       {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
-       {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
-       {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
-       {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
-       {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
-       {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
-       {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
-       {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
-       {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
-       {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
-       {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
-       {USB_DEVICE(0x08ca, 0x2050), DVNM("Medion MD 41437")},
-       {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
-       {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
+       {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
+       {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
+       {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
+       {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
+       {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
+       {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
+       {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
+       {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
+       {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
+       {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
+       {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
+       {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
+       {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
+       {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
+       {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
+       {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
+       {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
+       {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
+       {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
+       {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1664,7 +1463,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index 00f47e463a05b8ccef3449ec3640fe45fe03e680..91b555c34c68ff7509b50796cfd03dd4d9ac200a 100644 (file)
@@ -1,12 +1,4 @@
 /*
- *Notes: * t613  + tas5130A
- *     * Focus to light do not balance well as in win.
- *       Quality in win is not good, but its kinda better.
- *      * Fix some "extraneous bytes", most of apps will show the image anyway
- *      * Gamma table, is there, but its really doing something?
- *      * 7~8 Fps, its ok, max on win its 10.
- *                     Costantino Leandro
- *
  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * 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
+ *
+ *Notes: * t613  + tas5130A
+ *     * Focus to light do not balance well as in win.
+ *       Quality in win is not good, but its kinda better.
+ *      * Fix some "extraneous bytes", most of apps will show the image anyway
+ *      * Gamma table, is there, but its really doing something?
+ *      * 7~8 Fps, its ok, max on win its 10.
+ *                     Costantino Leandro
  */
 
 #define MODULE_NAME "t613"
+
 #include "gspca.h"
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
 
 #define MAX_GAMMA 0x10         /* 0 to 15 */
 
-/* From LUVCVIEW */
 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
 
 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
@@ -424,7 +422,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
 
        cam->cam_mode = vga_mode_t16;
@@ -998,9 +995,8 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
+       {USB_DEVICE(0x17a1, 0x0128)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1025,7 +1021,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index 0b793899095f29d09a6e4e99b415495c8ea2b617..1ff8ba2f7fe54ca83cb10a6428483bcf8b7bd694 100644 (file)
@@ -22,9 +22,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("TV8532 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -249,7 +246,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        tv_8532WriteEEprom(gspca_dev);
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 1;
        cam->cam_mode = sif_mode;
        cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
@@ -624,13 +620,12 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x046d, 0x0920), DVNM("QC Express")},
-       {USB_DEVICE(0x046d, 0x0921), DVNM("Labtec Webcam")},
-       {USB_DEVICE(0x0545, 0x808b), DVNM("Veo Stingray")},
-       {USB_DEVICE(0x0545, 0x8333), DVNM("Veo Stingray")},
-       {USB_DEVICE(0x0923, 0x010f), DVNM("ICM532 cams")},
+       {USB_DEVICE(0x046d, 0x0920)},
+       {USB_DEVICE(0x046d, 0x0921)},
+       {USB_DEVICE(0x0545, 0x808b)},
+       {USB_DEVICE(0x0545, 0x8333)},
+       {USB_DEVICE(0x0923, 0x010f)},
        {}
 };
 
@@ -656,7 +651,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 
index fcf2c9e32573a5d8a2a23a94c5a49fed086c8fa4..a4221753e1bf7433e6724873ea85b1dd2afdf3ad 100644 (file)
@@ -24,9 +24,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/VC032X USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -1419,30 +1416,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct usb_device *dev = gspca_dev->dev;
        struct cam *cam;
        int sensor;
-       __u16 product;
-
-       product = id->idProduct;
-       sd->bridge = BRIDGE_VC0321;
-       switch (id->idVendor) {
-       case 0x0ac8:            /* Vimicro z-star */
-               switch (product) {
-               case 0x0323:
-                       sd->bridge = BRIDGE_VC0323;
-                       break;
-               }
-               break;
-       case 0x17ef:            /* Lenovo */
-/*             switch (product) { */
-/*             case 0x4802:     * Lenovo MI1310_SOC */
-                       sd->bridge = BRIDGE_VC0323;
-/*                     break; */
-/*             } */
-               break;
-       }
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x02;
+       sd->bridge = id->driver_info;
        if (sd->bridge == BRIDGE_VC0321) {
                cam->cam_mode = vc0321_mode;
                cam->nmodes = ARRAY_SIZE(vc0321_mode);
@@ -1771,16 +1748,15 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x046d, 0x0892), DVNM("Logitech Orbicam")},
-       {USB_DEVICE(0x046d, 0x0896), DVNM("Logitech Orbicam")},
-       {USB_DEVICE(0x0ac8, 0x0321), DVNM("Vimicro generic vc0321")},
-       {USB_DEVICE(0x0ac8, 0x0323), DVNM("Vimicro Vc0323")},
-       {USB_DEVICE(0x0ac8, 0x0328), DVNM("A4Tech PK-130MG")},
-       {USB_DEVICE(0x0ac8, 0xc001), DVNM("Sony embedded vimicro")},
-       {USB_DEVICE(0x0ac8, 0xc002), DVNM("Sony embedded vimicro")},
-       {USB_DEVICE(0x17ef, 0x4802), DVNM("Lenovo Vc0323+MI1310_SOC")},
+       {USB_DEVICE(0x046d, 0x0892), .driver_info = BRIDGE_VC0321},
+       {USB_DEVICE(0x046d, 0x0896), .driver_info = BRIDGE_VC0321},
+       {USB_DEVICE(0x0ac8, 0x0321), .driver_info = BRIDGE_VC0321},
+       {USB_DEVICE(0x0ac8, 0x0323), .driver_info = BRIDGE_VC0323},
+       {USB_DEVICE(0x0ac8, 0x0328), .driver_info = BRIDGE_VC0321},
+       {USB_DEVICE(0x0ac8, 0xc001), .driver_info = BRIDGE_VC0321},
+       {USB_DEVICE(0x0ac8, 0xc002), .driver_info = BRIDGE_VC0321},
+       {USB_DEVICE(0x17ef, 0x4802), .driver_info = BRIDGE_VC0323},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1805,7 +1781,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)
index b761b11c5c6a45d8f9eba88b2620b127c322b456..22a994ccb1d5022fbb645395d72397f0fe1372d2 100644 (file)
@@ -24,9 +24,6 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>, "
                "Serge A. Suchkov <Serge.A.S@tochka.ru>");
 MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver");
@@ -49,7 +46,7 @@ struct sd {
        __u8 sharpness;
 
        char qindex;
-       char sensor;                    /* Type of image sensor chip */
+       signed char sensor;             /* Type of image sensor chip */
 /* !! values used in different tables */
 #define SENSOR_CS2102 0
 #define SENSOR_CS2102K 1
@@ -2205,10 +2202,10 @@ static const struct usb_action hdcs2020xb_InitialScale[] = {
 };
 static const struct usb_action hdcs2020b_50HZ[] = {
        {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x13, 0x0018}, /* 00,13,18,aa */
-       {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
-       {0xaa, 0x0e, 0x0005}, /* 00,0e,05,aa */
-       {0xaa, 0x19, 0x001f}, /* 00,19,1f,aa */
+       {0xaa, 0x13, 0x0018},                   /* 00,13,18,aa */
+       {0xaa, 0x14, 0x0001},                   /* 00,14,01,aa */
+       {0xaa, 0x0e, 0x0005},                   /* 00,0e,05,aa */
+       {0xaa, 0x19, 0x001f},                   /* 00,19,1f,aa */
        {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
        {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
        {0xa0, 0x76, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,76,cc */
@@ -2226,10 +2223,10 @@ static const struct usb_action hdcs2020b_50HZ[] = {
 };
 static const struct usb_action hdcs2020b_60HZ[] = {
        {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x13, 0x0031}, /* 00,13,31,aa */
-       {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
-       {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
-       {0xaa, 0x19, 0x00cd}, /* 00,19,cd,aa */
+       {0xaa, 0x13, 0x0031},                   /* 00,13,31,aa */
+       {0xaa, 0x14, 0x0001},                   /* 00,14,01,aa */
+       {0xaa, 0x0e, 0x0004},                   /* 00,0e,04,aa */
+       {0xaa, 0x19, 0x00cd},                   /* 00,19,cd,aa */
        {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
        {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
        {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,62,cc */
@@ -2247,10 +2244,10 @@ static const struct usb_action hdcs2020b_60HZ[] = {
 };
 static const struct usb_action hdcs2020b_NoFliker[] = {
        {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x13, 0x0010}, /* 00,13,10,aa */
-       {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
-       {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
-       {0xaa, 0x19, 0x0000}, /* 00,19,00,aa */
+       {0xaa, 0x13, 0x0010},                   /* 00,13,10,aa */
+       {0xaa, 0x14, 0x0001},                   /* 00,14,01,aa */
+       {0xaa, 0x0e, 0x0004},                   /* 00,0e,04,aa */
+       {0xaa, 0x19, 0x0000},                   /* 00,19,00,aa */
        {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
        {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
        {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
@@ -4102,27 +4099,27 @@ static const struct usb_action pas106b_Initial_com[] = {
 
 static const struct usb_action pas106b_Initial[] = {   /* 176x144 */
 /* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},          /* ClockSetting */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
 /* Sream and Sensor specific */
-       {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},      /* CMOSSensorSelect */
+       {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
 /* Picture size */
-       {0xa0, 0x00, ZC3XX_R003_FRAMEWIDTHHIGH},  /* FrameWidthHigh 00 */
-       {0xa0, 0xb0, ZC3XX_R004_FRAMEWIDTHLOW},   /* FrameWidthLow B0 */
-       {0xa0, 0x00, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* FrameHeightHigh 00 */
-       {0xa0, 0x90, ZC3XX_R006_FRAMEHEIGHTLOW},  /* FrameHightLow 90 */
+       {0xa0, 0x00, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0xb0, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x00, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0x90, ZC3XX_R006_FRAMEHEIGHTLOW},
 /* System */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* SystemOperating */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
 /* Sream and Sensor specific */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
 /* Sensor Interface */
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},  /* Compatibily Mode */
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
 /* Window inside sensor array */
-       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},  /* WinXStartLow */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* FirstYLow */
-       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},     /* FirstxLow */
-       {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},  /* WinHeightLow */
-       {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},   /* WinWidthLow */
+       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
 /* Init the sensor */
        {0xaa, 0x02, 0x0004},
        {0xaa, 0x08, 0x0000},
@@ -4135,40 +4132,40 @@ static const struct usb_action pas106b_Initial[] = {    /* 176x144 */
        {0xaa, 0x14, 0x0081},
 
 /* Other registors */
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* SensorCorrection */
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
 /* Frame retreiving */
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* AutoAdjustFPS */
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
 /* Gains */
-       {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},   /* DigitalGain */
+       {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
 /* Unknown */
        {0xa0, 0x00, 0x01ad},
 /* Sharpness */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* SharpnessMode */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},   /* Sharpness05 */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
 /* Other registors */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
 /* Auto exposure and white balance */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},     /* AWBStatus */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
 /*Dead pixels */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
 /* EEPROM */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* EEPROMAccess */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
 /* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* ClockSetting */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
 /* Other registers */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
 /* Auto exposure and white balance */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},     /* AWBStatus */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
 /*Dead pixels */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
 /* EEPROM */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* EEPROMAccess */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
 /* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* ClockSetting */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
 
        {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
        {0xa0, 0xf4, ZC3XX_R10B_RGB01},
@@ -4180,67 +4177,67 @@ static const struct usb_action pas106b_Initial[] = {    /* 176x144 */
        {0xa0, 0xf4, ZC3XX_R111_RGB21},
        {0xa0, 0x58, ZC3XX_R112_RGB22},
 /* Auto correction */
-       {0xa0, 0x03, ZC3XX_R181_WINXSTART},     /* WinXstart */
-       {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},     /* WinXWidth */
-       {0xa0, 0x16, ZC3XX_R183_WINXCENTER},    /* WinXCenter */
-       {0xa0, 0x03, ZC3XX_R184_WINYSTART},     /* WinYStart */
-       {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},     /* WinYWidth */
-       {0xa0, 0x14, ZC3XX_R186_WINYCENTER},    /* WinYCenter */
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
+       {0xa0, 0x03, ZC3XX_R181_WINXSTART},
+       {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
+       {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
+       {0xa0, 0x03, ZC3XX_R184_WINYSTART},
+       {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
+       {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
 
 /* Auto exposure and white balance */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* ExposureLimitHigh */
-       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},      /* ExposureLimitMid */
-       {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},      /* ExposureLimitLow */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* AntiFlickerHigh */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* AntiFlickerLow */
-       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},        /* AntiFlickerLow */
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},              /* AEBFreeze */
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},            /* AEBUnfreeze */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
 /* sensor on */
        {0xaa, 0x07, 0x00b1},
        {0xaa, 0x05, 0x0003},
        {0xaa, 0x04, 0x0001},
        {0xaa, 0x03, 0x003b},
 /* Gains */
-       {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* DigitalLimitDiff */
-       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},       /* DigitalGainStep */
-       {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN},            /* GlobalGain */
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},            /* GlobalGain */
+       {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
 /* Auto correction */
-       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},     /* AutoCorrectEnable */
+       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
        {0xa1, 0x01, 0x0180},                           /* AutoCorrectEnable */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* AutoCorrectEnable */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
 /* Gains */
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},                 /* RGain */
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},                 /* GGain */
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},                 /* BGain */
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
        {}
 };
 
 static const struct usb_action pas106b_InitialScale[] = {      /* 352x288 */
 /* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},          /* ClockSetting */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
 /* Sream and Sensor specific */
-       {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},      /* CMOSSensorSelect */
+       {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
 /* Picture size */
-       {0xa0, 0x01, ZC3XX_R003_FRAMEWIDTHHIGH},        /* FrameWidthHigh */
-       {0xa0, 0x60, ZC3XX_R004_FRAMEWIDTHLOW},         /* FrameWidthLow */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* FrameHeightHigh */
-       {0xa0, 0x20, ZC3XX_R006_FRAMEHEIGHTLOW},        /* FrameHightLow */
+       {0xa0, 0x01, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x60, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0x20, ZC3XX_R006_FRAMEHEIGHTLOW},
 /* System */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* SystemOperating */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
 /* Sream and Sensor specific */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
 /* Sensor Interface */
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},       /* Compatibily Mode */
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
 /* Window inside sensor array */
-       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},  /* WinXStartLow */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* FirstYLow */
-       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},     /* FirstxLow */
-       {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},  /* WinHeightLow */
-       {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},   /* WinWidthLow */
+       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
 /* Init the sensor */
        {0xaa, 0x02, 0x0004},
        {0xaa, 0x08, 0x0000},
@@ -4253,41 +4250,41 @@ static const struct usb_action pas106b_InitialScale[] = {       /* 352x288 */
        {0xaa, 0x14, 0x0081},
 
 /* Other registors */
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* SensorCorrection */
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
 /* Frame retreiving */
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* AutoAdjustFPS */
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
 /* Gains */
-       {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},   /* DigitalGain */
+       {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
 /* Unknown */
        {0xa0, 0x00, 0x01ad},
 /* Sharpness */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* SharpnessMode */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},   /* Sharpness05 */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
 /* Other registors */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
 /* Auto exposure and white balance */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},     /* AWBStatus */
-       {0xa0, 0x80, ZC3XX_R18D_YTARGET},       /* ????????? */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
 /*Dead pixels */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
 /* EEPROM */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* EEPROMAccess */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
 /* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* ClockSetting */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
 /* Other registers */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
 /* Auto exposure and white balance */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},     /* AWBStatus */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
 /*Dead pixels */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
 /* EEPROM */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* EEPROMAccess */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
 /* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* ClockSetting */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
 
        {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
        {0xa0, 0xf4, ZC3XX_R10B_RGB01},
@@ -4299,43 +4296,43 @@ static const struct usb_action pas106b_InitialScale[] = {       /* 352x288 */
        {0xa0, 0xf4, ZC3XX_R111_RGB21},
        {0xa0, 0x58, ZC3XX_R112_RGB22},
 /* Auto correction */
-       {0xa0, 0x03, ZC3XX_R181_WINXSTART},     /* WinXstart */
-       {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},     /* WinXWidth */
-       {0xa0, 0x16, ZC3XX_R183_WINXCENTER},    /* WinXCenter */
-       {0xa0, 0x03, ZC3XX_R184_WINYSTART},     /* WinYStart */
-       {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},     /* WinYWidth */
-       {0xa0, 0x14, ZC3XX_R186_WINYCENTER},    /* WinYCenter */
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
+       {0xa0, 0x03, ZC3XX_R181_WINXSTART},
+       {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
+       {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
+       {0xa0, 0x03, ZC3XX_R184_WINYSTART},
+       {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
+       {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
 
 /* Auto exposure and white balance */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* ExposureLimitHigh 0 */
-       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},  /* ExposureLimitMid */
-       {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},  /* ExposureLimitLow 0xb1 */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
 
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},   /* AntiFlickerHigh 0x00 */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},    /* AntiFlickerLow 0x00 */
-       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},    /* AntiFlickerLow 0x87 */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
 
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* AEBFreeze 0x10 0x0c */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},    /* AEBUnfreeze 0x30 0x18 */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
 /* sensor on */
        {0xaa, 0x07, 0x00b1},
        {0xaa, 0x05, 0x0003},
        {0xaa, 0x04, 0x0001},
        {0xaa, 0x03, 0x003b},
 /* Gains */
-       {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* DigitalLimitDiff */
-       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},       /* DigitalGainStep */
-       {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN},    /* GlobalGain */
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},    /* GlobalGain */
+       {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
 /* Auto correction */
-       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},     /* AutoCorrectEnable */
+       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
        {0xa1, 0x01, 0x0180},                           /* AutoCorrectEnable */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* AutoCorrectEnable */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
 /* Gains */
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},         /* RGain */
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},         /* GGain */
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},         /* BGain */
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
 
        {0xa0, 0x00, 0x0007},                   /* AutoCorrectEnable */
        {0xa0, 0xff, ZC3XX_R018_FRAMELOST},     /* Frame adjust */
@@ -4459,8 +4456,8 @@ static const struct usb_action pb03303x_Initial[] = {
        {0xa0, 0x50, ZC3XX_R112_RGB22},
 
        {0xa1, 0x01, 0x0008},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
        {0xa1, 0x01, 0x01c8},
        {0xa1, 0x01, 0x01c9},
        {0xa1, 0x01, 0x01ca},
@@ -5984,7 +5981,7 @@ static const struct usb_action tas5130c_vf0250_Initial[] = {
        {0xaa, 0x1b, 0x0000},           /* 00,1b,00,aa, */
        {0xaa, 0x13, 0x0002},           /* 00,13,02,aa, */
        {0xaa, 0x15, 0x0004},           /* 00,15,04,aa */
-       {0xaa, 0x01, 0x0000},
+/*??   {0xaa, 0x01, 0x0000}, */
        {0xaa, 0x01, 0x0000},
        {0xaa, 0x1a, 0x0000},           /* 00,1a,00,aa, */
        {0xaa, 0x1c, 0x0017},           /* 00,1c,17,aa, */
@@ -6000,8 +5997,8 @@ static const struct usb_action tas5130c_vf0250_Initial[] = {
        {0xaa, 0x0f, 0x00a0},           /* 00,0f,a0,aa, */
        {0xaa, 0x10, 0x0000},           /* 00,10,00,aa, */
        {0xaa, 0x11, 0x00a0},           /* 00,11,a0,aa, */
-       {0xa0, 0x00, 0x0039},
-       {0xa1, 0x01, 0x0037},
+/*??   {0xa0, 0x00, 0x0039},
+       {0xa1, 0x01, 0x0037}, */
        {0xaa, 0x16, 0x0001},           /* 00,16,01,aa, */
        {0xaa, 0x17, 0x00e8},           /* 00,17,e6,aa, (e6 -> e8) */
        {0xaa, 0x18, 0x0002},           /* 00,18,02,aa, */
@@ -6272,7 +6269,7 @@ static void reg_w(struct usb_device *dev,
                        __u8 value,
                        __u16 index)
 {
-       PDEBUG(D_USBO, "reg w %02x -> [%04x]", value, index);
+       PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value);
        reg_w_i(dev, value, index);
 }
 
@@ -6280,17 +6277,17 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev,
                        __u8 reg)
 {
        __u8 retbyte;
-       __u8 retval[2];
+       __u16 retval;
 
        reg_w_i(gspca_dev->dev, reg, 0x92);
        reg_w_i(gspca_dev->dev, 0x02, 0x90);            /* <- read command */
        msleep(25);
        retbyte = reg_r_i(gspca_dev, 0x0091);           /* read status */
-       retval[0] = reg_r_i(gspca_dev, 0x0095);         /* read Lowbyte */
-       retval[1] = reg_r_i(gspca_dev, 0x0096);         /* read Hightbyte */
-       PDEBUG(D_USBO, "i2c r [%02x] -> (%02x) %02x%02x",
-                       reg, retbyte, retval[1], retval[0]);
-       return (retval[1] << 8) | retval[0];
+       retval = reg_r_i(gspca_dev, 0x0095);            /* read Lowbyte */
+       retval |= reg_r_i(gspca_dev, 0x0096) << 8;      /* read Hightbyte */
+       PDEBUG(D_USBO, "i2c r [%02x] -> %04x (%02x)",
+                       reg, retval, retbyte);
+       return retval;
 }
 
 static __u8 i2c_write(struct gspca_dev *gspca_dev,
@@ -6306,7 +6303,7 @@ static __u8 i2c_write(struct gspca_dev *gspca_dev,
        reg_w_i(gspca_dev->dev, 0x01, 0x90);            /* <- write command */
        msleep(5);
        retbyte = reg_r_i(gspca_dev, 0x0091);           /* read status */
-       PDEBUG(D_USBO, "i2c w [%02x] %02x%02x (%02x)",
+       PDEBUG(D_USBO, "i2c w [%02x] %02x%02x (%02x)",
                        reg, valH, valL, retbyte);
        return retbyte;
 }
@@ -6349,6 +6346,8 @@ static void setmatrix(struct gspca_dev *gspca_dev)
                {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58};
        static const __u8 po2030_matrix[9] =
                {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60};
+       static const __u8 vf0250_matrix[9] =
+               {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b};
 
        switch (sd->sensor) {
        case SENSOR_GC0305:
@@ -6363,8 +6362,9 @@ static void setmatrix(struct gspca_dev *gspca_dev)
        case SENSOR_PO2030:
                matrix = po2030_matrix;
                break;
-       case SENSOR_TAS5130C_VF0250:    /* no matrix? */
-               return;
+       case SENSOR_TAS5130C_VF0250:
+               matrix = vf0250_matrix;
+               break;
        default:                /* matrix already loaded */
                return;
        }
@@ -6744,7 +6744,7 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev)
                return 0x04;                    /* CS2102 */
 
        start_2wr_probe(dev, 0x06);             /* OmniVision */
-       reg_w(dev, 0x08, 0x8d);
+       reg_w(dev, 0x08, 0x008d);
        i2c_write(gspca_dev, 0x11, 0xaa, 0x00);
        retbyte = i2c_read(gspca_dev, 0x11);
        if (retbyte != 0) {
@@ -6778,7 +6778,7 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev)
                return 0x0c;                    /* ICM105A */
 
        start_2wr_probe(dev, 0x0e);             /* PAS202BCB */
-       reg_w(dev, 0x08, 0x8d);
+       reg_w(dev, 0x08, 0x008d);
        i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
        msleep(500);
        retbyte = i2c_read(gspca_dev, 0x03);
@@ -6830,7 +6830,6 @@ static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
        {0x8001, 0x13},
        {0x8000, 0x14},         /* CS2102K */
        {0x8400, 0x15},         /* TAS5130K */
-       {0, 0}
 };
 
 static int vga_3wr_probe(struct gspca_dev *gspca_dev)
@@ -6843,7 +6842,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
 
 /*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
        reg_w(dev, 0x02, 0x0010);
-       reg_r(gspca_dev, 0x10);
+       reg_r(gspca_dev, 0x0010);
        reg_w(dev, 0x01, 0x0000);
        reg_w(dev, 0x00, 0x0010);
        reg_w(dev, 0x01, 0x0001);
@@ -6869,17 +6868,15 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
        PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", checkword);
        reg_r(gspca_dev, 0x0010);
        /* this is tested only once anyway */
-       i = 0;
-       while (chipset_revision_sensor[i].revision) {
+       for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
                if (chipset_revision_sensor[i].revision == checkword) {
                        sd->chip_revision = checkword;
                        send_unknown(dev, SENSOR_PB0330);
                        return chipset_revision_sensor[i].internal_sensor_id;
                }
-               i++;
        }
 
-       reg_w(dev, 0x01, 0x0000);
+       reg_w(dev, 0x01, 0x0000);       /* check ?? */
        reg_w(dev, 0x01, 0x0001);
        reg_w(dev, 0xdd, 0x008b);
        reg_w(dev, 0x0a, 0x0010);
@@ -6901,8 +6898,11 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
        retbyte = i2c_read(gspca_dev, 0x00);
        if (retbyte != 0) {
                PDEBUG(D_PROBE, "probe 3wr vga type %02x", retbyte);
-               send_unknown(dev, SENSOR_GC0305);
-               return retbyte;         /* 0x29 = gc0305 - should continue? */
+               if (retbyte == 0x11)                    /* VF0250 */
+                       return 0x0250;
+               if (retbyte == 0x29)                    /* gc0305 */
+                       send_unknown(dev, SENSOR_GC0305);
+               return retbyte;
        }
 
        reg_w(dev, 0x01, 0x0000);       /* check OmniVision */
@@ -6918,18 +6918,18 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
                return 0x06;            /* OmniVision confirm ? */
        }
 
-       reg_w(dev, 0x01, 0x00);
-       reg_w(dev, 0x00, 0x02);
-       reg_w(dev, 0x01, 0x10);
-       reg_w(dev, 0x01, 0x01);
-       reg_w(dev, 0xee, 0x8b);
-       reg_w(dev, 0x03, 0x12);
+       reg_w(dev, 0x01, 0x0000);
+       reg_w(dev, 0x00, 0x0002);
+       reg_w(dev, 0x01, 0x0010);
+       reg_w(dev, 0x01, 0x0001);
+       reg_w(dev, 0xee, 0x008b);
+       reg_w(dev, 0x03, 0x0012);
 /*     msleep(150); */
-       reg_w(dev, 0x01, 0x12);
-       reg_w(dev, 0x05, 0x12);
-       retbyte = i2c_read(gspca_dev, 0x00);            /* ID 0 */
+       reg_w(dev, 0x01, 0x0012);
+       reg_w(dev, 0x05, 0x0012);
+       retbyte = i2c_read(gspca_dev, 0x0000);          /* ID 0 */
        checkword = retbyte << 8;
-       retbyte = i2c_read(gspca_dev, 0x01);            /* ID 1 */
+       retbyte = i2c_read(gspca_dev, 0x0001);          /* ID 1 */
        checkword |= retbyte;
        PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", checkword);
        if (checkword == 0x2030) {
@@ -6939,14 +6939,14 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
                return checkword;
        }
 
-       reg_w(dev, 0x01, 0x00);
-       reg_w(dev, 0x0a, 0x10);
-       reg_w(dev, 0xd3, 0x8b);
-       reg_w(dev, 0x01, 0x01);
-       reg_w(dev, 0x03, 0x12);
-       reg_w(dev, 0x01, 0x12);
-       reg_w(dev, 0x05, 0x01);
-       reg_w(dev, 0xd3, 0x8b);
+       reg_w(dev, 0x01, 0x0000);
+       reg_w(dev, 0x0a, 0x0010);
+       reg_w(dev, 0xd3, 0x008b);
+       reg_w(dev, 0x01, 0x0001);
+       reg_w(dev, 0x03, 0x0012);
+       reg_w(dev, 0x01, 0x0012);
+       reg_w(dev, 0x05, 0x0001);
+       reg_w(dev, 0xd3, 0x008b);
        retbyte = i2c_read(gspca_dev, 0x01);
        if (retbyte != 0) {
                PDEBUG(D_PROBE, "probe 3wr vga type 0a ?");
@@ -6962,7 +6962,9 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
 
        switch (sd->sensor) {
        case SENSOR_MC501CB:
+               return -1;              /* don't probe */
        case SENSOR_TAS5130C_VF0250:
+                               /* may probe but with write in reg 0x0010 */
                return -1;              /* don't probe */
        }
        sensor = vga_2wr_probe(gspca_dev);
@@ -7010,30 +7012,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
 
        /* define some sensors from the vendor/product */
        sd->sharpness = 2;
-       switch (id->idVendor) {
-       case 0x041e:                            /* Creative */
-               switch (id->idProduct) {
-               case 0x4051:                    /* zc301 chips */
-               case 0x4053:
-                       sd->sensor = SENSOR_TAS5130C_VF0250;
-                       break;
-               }
-               break;
-       case 0x046d:                            /* Logitech Labtec */
-               switch (id->idProduct) {
-               case 0x08dd:
-                       sd->sensor = SENSOR_MC501CB;
-                       break;
-               }
-               break;
-       case 0x0ac8:                            /* Vimicro z-star */
-               switch (id->idProduct) {
-               case 0x305b:
-                       sd->sensor = SENSOR_TAS5130C_VF0250;
-                       break;
-               }
-               break;
-       }
+       sd->sensor = id->driver_info;
        sensor = zcxx_probeSensor(gspca_dev);
        if (sensor >= 0)
                PDEBUG(D_PROBE, "probe sensor -> %02x", sensor);
@@ -7119,6 +7098,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
                        PDEBUG(D_PROBE, "Find Sensor GC0305");
                        sd->sensor = SENSOR_GC0305;
                        break;
+               case 0x0250:
+                       PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)");
+                       sd->sensor =  SENSOR_TAS5130C_VF0250;
+                       break;
                case 0x2030:
                        PDEBUG(D_PROBE, "Find Sensor PO2030");
                        sd->sensor = SENSOR_PO2030;
@@ -7146,7 +7129,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        }
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
 /*fixme:test*/
        gspca_dev->nbalt--;
@@ -7235,6 +7217,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
        case SENSOR_GC0305:
        case SENSOR_OV7620:
        case SENSOR_PO2030:
+       case SENSOR_TAS5130C_VF0250:
                msleep(100);                    /* ?? */
                reg_r(gspca_dev, 0x0002);       /* --> 0x40 */
                reg_w(dev, 0x09, 0x01ad);       /* (from win traces) */
@@ -7515,70 +7498,69 @@ static const struct sd_desc sd_desc = {
        .querymenu = sd_querymenu,
 };
 
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x041e), DVNM("Creative WebCam Live!")},
+       {USB_DEVICE(0x041e, 0x041e)},
 #ifndef CONFIG_USB_ZC0301
-       {USB_DEVICE(0x041e, 0x4017), DVNM("Creative Webcam Mobile PD1090")},
-       {USB_DEVICE(0x041e, 0x401c), DVNM("Creative NX")},
-       {USB_DEVICE(0x041e, 0x401e), DVNM("Creative Nx Pro")},
-       {USB_DEVICE(0x041e, 0x401f), DVNM("Creative Webcam Notebook PD1171")},
+       {USB_DEVICE(0x041e, 0x4017)},
+       {USB_DEVICE(0x041e, 0x401c)},
+       {USB_DEVICE(0x041e, 0x401e)},
+       {USB_DEVICE(0x041e, 0x401f)},
 #endif
-       {USB_DEVICE(0x041e, 0x4029), DVNM("Creative WebCam Vista Pro")},
+       {USB_DEVICE(0x041e, 0x4029)},
 #ifndef CONFIG_USB_ZC0301
-       {USB_DEVICE(0x041e, 0x4034), DVNM("Creative Instant P0620")},
-       {USB_DEVICE(0x041e, 0x4035), DVNM("Creative Instant P0620D")},
-       {USB_DEVICE(0x041e, 0x4036), DVNM("Creative Live !")},
-       {USB_DEVICE(0x041e, 0x403a), DVNM("Creative Nx Pro 2")},
+       {USB_DEVICE(0x041e, 0x4034)},
+       {USB_DEVICE(0x041e, 0x4035)},
+       {USB_DEVICE(0x041e, 0x4036)},
+       {USB_DEVICE(0x041e, 0x403a)},
 #endif
-       {USB_DEVICE(0x041e, 0x4051), DVNM("Creative Notebook Pro (VF0250)")},
-       {USB_DEVICE(0x041e, 0x4053), DVNM("Creative Live!Cam Video IM")},
+       {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250},
+       {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250},
 #ifndef CONFIG_USB_ZC0301
-       {USB_DEVICE(0x0458, 0x7007), DVNM("Genius VideoCam V2")},
-       {USB_DEVICE(0x0458, 0x700c), DVNM("Genius VideoCam V3")},
-       {USB_DEVICE(0x0458, 0x700f), DVNM("Genius VideoCam Web V2")},
+       {USB_DEVICE(0x0458, 0x7007)},
+       {USB_DEVICE(0x0458, 0x700c)},
+       {USB_DEVICE(0x0458, 0x700f)},
 #endif
-       {USB_DEVICE(0x0461, 0x0a00), DVNM("MicroInnovation WebCam320")},
-       {USB_DEVICE(0x046d, 0x08a0), DVNM("Logitech QC IM")},
-       {USB_DEVICE(0x046d, 0x08a1), DVNM("Logitech QC IM 0x08A1 +sound")},
-       {USB_DEVICE(0x046d, 0x08a2), DVNM("Labtec Webcam Pro")},
-       {USB_DEVICE(0x046d, 0x08a3), DVNM("Logitech QC Chat")},
-       {USB_DEVICE(0x046d, 0x08a6), DVNM("Logitech QCim")},
-       {USB_DEVICE(0x046d, 0x08a7), DVNM("Logitech QuickCam Image")},
-       {USB_DEVICE(0x046d, 0x08a9), DVNM("Logitech Notebook Deluxe")},
-       {USB_DEVICE(0x046d, 0x08aa), DVNM("Labtec Webcam Notebook")},
-       {USB_DEVICE(0x046d, 0x08ac), DVNM("Logitech QuickCam Cool")},
-       {USB_DEVICE(0x046d, 0x08ad), DVNM("Logitech QCCommunicate STX")},
+       {USB_DEVICE(0x0461, 0x0a00)},
+       {USB_DEVICE(0x046d, 0x08a0)},
+       {USB_DEVICE(0x046d, 0x08a1)},
+       {USB_DEVICE(0x046d, 0x08a2)},
+       {USB_DEVICE(0x046d, 0x08a3)},
+       {USB_DEVICE(0x046d, 0x08a6)},
+       {USB_DEVICE(0x046d, 0x08a7)},
+       {USB_DEVICE(0x046d, 0x08a9)},
+       {USB_DEVICE(0x046d, 0x08aa)},
+       {USB_DEVICE(0x046d, 0x08ac)},
+       {USB_DEVICE(0x046d, 0x08ad)},
 #ifndef CONFIG_USB_ZC0301
-       {USB_DEVICE(0x046d, 0x08ae), DVNM("Logitech QuickCam for Notebooks")},
+       {USB_DEVICE(0x046d, 0x08ae)},
 #endif
-       {USB_DEVICE(0x046d, 0x08af), DVNM("Logitech QuickCam Cool")},
-       {USB_DEVICE(0x046d, 0x08b9), DVNM("Logitech QC IM ???")},
-       {USB_DEVICE(0x046d, 0x08d7), DVNM("Logitech QCam STX")},
-       {USB_DEVICE(0x046d, 0x08d9), DVNM("Logitech QuickCam IM/Connect")},
-       {USB_DEVICE(0x046d, 0x08d8), DVNM("Logitech Notebook Deluxe")},
-       {USB_DEVICE(0x046d, 0x08da), DVNM("Logitech QuickCam Messenger")},
-       {USB_DEVICE(0x046d, 0x08dd), DVNM("Logitech QuickCam for Notebooks")},
-       {USB_DEVICE(0x0471, 0x0325), DVNM("Philips SPC 200 NC")},
-       {USB_DEVICE(0x0471, 0x0326), DVNM("Philips SPC 300 NC")},
-       {USB_DEVICE(0x0471, 0x032d), DVNM("Philips spc210nc")},
-       {USB_DEVICE(0x0471, 0x032e), DVNM("Philips spc315nc")},
-       {USB_DEVICE(0x055f, 0xc005), DVNM("Mustek Wcam300A")},
+       {USB_DEVICE(0x046d, 0x08af)},
+       {USB_DEVICE(0x046d, 0x08b9)},
+       {USB_DEVICE(0x046d, 0x08d7)},
+       {USB_DEVICE(0x046d, 0x08d9)},
+       {USB_DEVICE(0x046d, 0x08d8)},
+       {USB_DEVICE(0x046d, 0x08da)},
+       {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB},
+       {USB_DEVICE(0x0471, 0x0325)},
+       {USB_DEVICE(0x0471, 0x0326)},
+       {USB_DEVICE(0x0471, 0x032d)},
+       {USB_DEVICE(0x0471, 0x032e)},
+       {USB_DEVICE(0x055f, 0xc005)},
 #ifndef CONFIG_USB_ZC0301
-       {USB_DEVICE(0x055f, 0xd003), DVNM("Mustek WCam300A")},
-       {USB_DEVICE(0x055f, 0xd004), DVNM("Mustek WCam300 AN")},
+       {USB_DEVICE(0x055f, 0xd003)},
+       {USB_DEVICE(0x055f, 0xd004)},
 #endif
-       {USB_DEVICE(0x0698, 0x2003), DVNM("CTX M730V built in")},
-       {USB_DEVICE(0x0ac8, 0x0302), DVNM("Z-star Vimicro zc0302")},
+       {USB_DEVICE(0x0698, 0x2003)},
+       {USB_DEVICE(0x0ac8, 0x0302)},
 #ifndef CONFIG_USB_ZC0301
-       {USB_DEVICE(0x0ac8, 0x301b), DVNM("Z-Star zc301b")},
-       {USB_DEVICE(0x0ac8, 0x303b), DVNM("Vimicro 0x303b")},
+       {USB_DEVICE(0x0ac8, 0x301b)},
+       {USB_DEVICE(0x0ac8, 0x303b)},
 #endif
-       {USB_DEVICE(0x0ac8, 0x305b), DVNM("Z-star Vimicro zc0305b")},
+       {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250},
 #ifndef CONFIG_USB_ZC0301
-       {USB_DEVICE(0x0ac8, 0x307b), DVNM("Z-Star 307b")},
-       {USB_DEVICE(0x10fd, 0x0128), DVNM("Typhoon Webshot II 300k 0x0128")},
-       {USB_DEVICE(0x10fd, 0x8050), DVNM("Typhoon Webshot II USB 300k")},
+       {USB_DEVICE(0x0ac8, 0x307b)},
+       {USB_DEVICE(0x10fd, 0x0128)},
+       {USB_DEVICE(0x10fd, 0x8050)},
 #endif
        {}                      /* end of entry */
 };
@@ -7605,7 +7587,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 
index 5d7ee8fcdd50b3fd4b788ed0a48078a64e68d9ec..0069898bddabffe925b540bc99ad93dd739d919a 100644 (file)
@@ -2,9 +2,7 @@ config VIDEO_IVTV
        tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
        depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL
        depends on INPUT   # due to VIDEO_IR
-       depends on HOTPLUG # due to FW_LOADER
        select I2C_ALGOBIT
-       select FW_LOADER
        select VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
index 41fd79279bb53eaab172621d3a0ef2c82f94c047..aea1664948ce16beaa7cfff28cb7c0cf05e5d02d 100644 (file)
@@ -465,9 +465,8 @@ static void ivtv_process_eeprom(struct ivtv *itv)
        if (itv->options.radio == -1)
                itv->options.radio = (tv.has_radio != 0);
        /* only enable newi2c if an IR blaster is present */
-       /* FIXME: for 2.6.20 the test against 2 should be removed */
-       if (itv->options.newi2c == -1 && tv.has_ir != -1 && tv.has_ir != 2) {
-               itv->options.newi2c = (tv.has_ir & 2) ? 1 : 0;
+       if (itv->options.newi2c == -1 && tv.has_ir) {
+               itv->options.newi2c = (tv.has_ir & 4) ? 1 : 0;
                if (itv->options.newi2c) {
                    IVTV_INFO("Reopen i2c bus for IR-blaster support\n");
                    exit_ivtv_i2c(itv);
index a08bb3331cfbd05f7926912dd3fab6bd8daac569..ab287b48fc2b91a7940bd1f158ddbf438f78b1bd 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/dvb/video.h>
 #include <linux/dvb/audio.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/tuner.h>
 #include <media/cx2341x.h>
 
index 52e00a7f3110e7835ac2dfea5d674eacc14486b0..61030309d0ad876b696478355b5ba683eb832879 100644 (file)
@@ -1842,69 +1842,73 @@ int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        return res;
 }
 
-void ivtv_set_funcs(struct video_device *vdev)
-{
-       vdev->vidioc_querycap               = ivtv_querycap;
-       vdev->vidioc_g_priority             = ivtv_g_priority;
-       vdev->vidioc_s_priority             = ivtv_s_priority;
-       vdev->vidioc_s_audio                = ivtv_s_audio;
-       vdev->vidioc_g_audio                = ivtv_g_audio;
-       vdev->vidioc_enumaudio              = ivtv_enumaudio;
-       vdev->vidioc_s_audout               = ivtv_s_audout;
-       vdev->vidioc_g_audout               = ivtv_g_audout;
-       vdev->vidioc_enum_input             = ivtv_enum_input;
-       vdev->vidioc_enum_output            = ivtv_enum_output;
-       vdev->vidioc_enumaudout             = ivtv_enumaudout;
-       vdev->vidioc_cropcap                = ivtv_cropcap;
-       vdev->vidioc_s_crop                 = ivtv_s_crop;
-       vdev->vidioc_g_crop                 = ivtv_g_crop;
-       vdev->vidioc_g_input                = ivtv_g_input;
-       vdev->vidioc_s_input                = ivtv_s_input;
-       vdev->vidioc_g_output               = ivtv_g_output;
-       vdev->vidioc_s_output               = ivtv_s_output;
-       vdev->vidioc_g_frequency            = ivtv_g_frequency;
-       vdev->vidioc_s_frequency            = ivtv_s_frequency;
-       vdev->vidioc_s_tuner                = ivtv_s_tuner;
-       vdev->vidioc_g_tuner                = ivtv_g_tuner;
-       vdev->vidioc_g_enc_index            = ivtv_g_enc_index;
-       vdev->vidioc_g_fbuf                 = ivtv_g_fbuf;
-       vdev->vidioc_s_fbuf                 = ivtv_s_fbuf;
-       vdev->vidioc_g_std                  = ivtv_g_std;
-       vdev->vidioc_s_std                  = ivtv_s_std;
-       vdev->vidioc_overlay                = ivtv_overlay;
-       vdev->vidioc_log_status             = ivtv_log_status;
-       vdev->vidioc_enum_fmt_vid_cap       = ivtv_enum_fmt_vid_cap;
-       vdev->vidioc_encoder_cmd            = ivtv_encoder_cmd;
-       vdev->vidioc_try_encoder_cmd        = ivtv_try_encoder_cmd;
-       vdev->vidioc_enum_fmt_vid_out       = ivtv_enum_fmt_vid_out;
-       vdev->vidioc_g_fmt_vid_cap          = ivtv_g_fmt_vid_cap;
-       vdev->vidioc_g_fmt_vbi_cap          = ivtv_g_fmt_vbi_cap;
-       vdev->vidioc_g_fmt_sliced_vbi_cap   = ivtv_g_fmt_sliced_vbi_cap;
-       vdev->vidioc_g_fmt_vid_out          = ivtv_g_fmt_vid_out;
-       vdev->vidioc_g_fmt_vid_out_overlay  = ivtv_g_fmt_vid_out_overlay;
-       vdev->vidioc_g_fmt_sliced_vbi_out   = ivtv_g_fmt_sliced_vbi_out;
-       vdev->vidioc_s_fmt_vid_cap          = ivtv_s_fmt_vid_cap;
-       vdev->vidioc_s_fmt_vbi_cap          = ivtv_s_fmt_vbi_cap;
-       vdev->vidioc_s_fmt_sliced_vbi_cap   = ivtv_s_fmt_sliced_vbi_cap;
-       vdev->vidioc_s_fmt_vid_out          = ivtv_s_fmt_vid_out;
-       vdev->vidioc_s_fmt_vid_out_overlay  = ivtv_s_fmt_vid_out_overlay;
-       vdev->vidioc_s_fmt_sliced_vbi_out   = ivtv_s_fmt_sliced_vbi_out;
-       vdev->vidioc_try_fmt_vid_cap        = ivtv_try_fmt_vid_cap;
-       vdev->vidioc_try_fmt_vbi_cap        = ivtv_try_fmt_vbi_cap;
-       vdev->vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap;
-       vdev->vidioc_try_fmt_vid_out        = ivtv_try_fmt_vid_out;
-       vdev->vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay;
-       vdev->vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out;
-       vdev->vidioc_g_sliced_vbi_cap       = ivtv_g_sliced_vbi_cap;
-       vdev->vidioc_g_chip_ident           = ivtv_g_chip_ident;
+static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
+       .vidioc_querycap                    = ivtv_querycap,
+       .vidioc_g_priority                  = ivtv_g_priority,
+       .vidioc_s_priority                  = ivtv_s_priority,
+       .vidioc_s_audio                     = ivtv_s_audio,
+       .vidioc_g_audio                     = ivtv_g_audio,
+       .vidioc_enumaudio                   = ivtv_enumaudio,
+       .vidioc_s_audout                    = ivtv_s_audout,
+       .vidioc_g_audout                    = ivtv_g_audout,
+       .vidioc_enum_input                  = ivtv_enum_input,
+       .vidioc_enum_output                 = ivtv_enum_output,
+       .vidioc_enumaudout                  = ivtv_enumaudout,
+       .vidioc_cropcap                     = ivtv_cropcap,
+       .vidioc_s_crop                      = ivtv_s_crop,
+       .vidioc_g_crop                      = ivtv_g_crop,
+       .vidioc_g_input                     = ivtv_g_input,
+       .vidioc_s_input                     = ivtv_s_input,
+       .vidioc_g_output                    = ivtv_g_output,
+       .vidioc_s_output                    = ivtv_s_output,
+       .vidioc_g_frequency                 = ivtv_g_frequency,
+       .vidioc_s_frequency                 = ivtv_s_frequency,
+       .vidioc_s_tuner                     = ivtv_s_tuner,
+       .vidioc_g_tuner                     = ivtv_g_tuner,
+       .vidioc_g_enc_index                 = ivtv_g_enc_index,
+       .vidioc_g_fbuf                      = ivtv_g_fbuf,
+       .vidioc_s_fbuf                      = ivtv_s_fbuf,
+       .vidioc_g_std                       = ivtv_g_std,
+       .vidioc_s_std                       = ivtv_s_std,
+       .vidioc_overlay                     = ivtv_overlay,
+       .vidioc_log_status                  = ivtv_log_status,
+       .vidioc_enum_fmt_vid_cap            = ivtv_enum_fmt_vid_cap,
+       .vidioc_encoder_cmd                 = ivtv_encoder_cmd,
+       .vidioc_try_encoder_cmd             = ivtv_try_encoder_cmd,
+       .vidioc_enum_fmt_vid_out            = ivtv_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_cap               = ivtv_g_fmt_vid_cap,
+       .vidioc_g_fmt_vbi_cap               = ivtv_g_fmt_vbi_cap,
+       .vidioc_g_fmt_sliced_vbi_cap        = ivtv_g_fmt_sliced_vbi_cap,
+       .vidioc_g_fmt_vid_out               = ivtv_g_fmt_vid_out,
+       .vidioc_g_fmt_vid_out_overlay       = ivtv_g_fmt_vid_out_overlay,
+       .vidioc_g_fmt_sliced_vbi_out        = ivtv_g_fmt_sliced_vbi_out,
+       .vidioc_s_fmt_vid_cap               = ivtv_s_fmt_vid_cap,
+       .vidioc_s_fmt_vbi_cap               = ivtv_s_fmt_vbi_cap,
+       .vidioc_s_fmt_sliced_vbi_cap        = ivtv_s_fmt_sliced_vbi_cap,
+       .vidioc_s_fmt_vid_out               = ivtv_s_fmt_vid_out,
+       .vidioc_s_fmt_vid_out_overlay       = ivtv_s_fmt_vid_out_overlay,
+       .vidioc_s_fmt_sliced_vbi_out        = ivtv_s_fmt_sliced_vbi_out,
+       .vidioc_try_fmt_vid_cap             = ivtv_try_fmt_vid_cap,
+       .vidioc_try_fmt_vbi_cap             = ivtv_try_fmt_vbi_cap,
+       .vidioc_try_fmt_sliced_vbi_cap      = ivtv_try_fmt_sliced_vbi_cap,
+       .vidioc_try_fmt_vid_out             = ivtv_try_fmt_vid_out,
+       .vidioc_try_fmt_vid_out_overlay     = ivtv_try_fmt_vid_out_overlay,
+       .vidioc_try_fmt_sliced_vbi_out      = ivtv_try_fmt_sliced_vbi_out,
+       .vidioc_g_sliced_vbi_cap            = ivtv_g_sliced_vbi_cap,
+       .vidioc_g_chip_ident                = ivtv_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       vdev->vidioc_g_register             = ivtv_g_register;
-       vdev->vidioc_s_register             = ivtv_s_register;
+       .vidioc_g_register                  = ivtv_g_register,
+       .vidioc_s_register                  = ivtv_s_register,
 #endif
-       vdev->vidioc_default                = ivtv_default;
-       vdev->vidioc_queryctrl              = ivtv_queryctrl;
-       vdev->vidioc_querymenu              = ivtv_querymenu;
-       vdev->vidioc_g_ext_ctrls            = ivtv_g_ext_ctrls;
-       vdev->vidioc_s_ext_ctrls            = ivtv_s_ext_ctrls;
-       vdev->vidioc_try_ext_ctrls          = ivtv_try_ext_ctrls;
+       .vidioc_default                     = ivtv_default,
+       .vidioc_queryctrl                   = ivtv_queryctrl,
+       .vidioc_querymenu                   = ivtv_querymenu,
+       .vidioc_g_ext_ctrls                 = ivtv_g_ext_ctrls,
+       .vidioc_s_ext_ctrls                 = ivtv_s_ext_ctrls,
+       .vidioc_try_ext_ctrls               = ivtv_try_ext_ctrls,
+};
+
+void ivtv_set_funcs(struct video_device *vdev)
+{
+       vdev->ioctl_ops = &ivtv_ioctl_ops;
 }
index f8883b487f4a9dbbee6cda1d1edd0c0fb64fd2c6..54d2023b26c4b341ff742a43149eb7063b0a9f84 100644 (file)
@@ -208,16 +208,11 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
                return -ENOMEM;
        }
 
-       s->v4l2dev->type = VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT |
-                   VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER;
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
-               s->v4l2dev->type |= VID_TYPE_MPEG_DECODER;
-       }
        snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s",
                        itv->num, s->name);
 
        s->v4l2dev->minor = minor;
-       s->v4l2dev->dev = &itv->dev->dev;
+       s->v4l2dev->parent = &itv->dev->dev;
        s->v4l2dev->fops = ivtv_stream_info[type].fops;
        s->v4l2dev->release = video_device_release;
        s->v4l2dev->tvnorms = V4L2_STD_ALL;
index 39bf6b114d50ac348bfdb2b77115e8dfbddec377..89a781c6929d77e0993c9eb448c5c6a6211e47e2 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/m52790.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
index 2fb5854cf6f039d58967b9ad07735c0a73e5f9b3..7c8ef6ac6c39cf646a9cfc3d4223d8bea51e48de 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/init.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/delay.h>
@@ -1697,13 +1698,7 @@ static const struct file_operations meye_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device meye_template = {
-       .owner          = THIS_MODULE,
-       .name           = "meye",
-       .type           = VID_TYPE_CAPTURE,
-       .fops           = &meye_fops,
-       .release        = video_device_release,
-       .minor          = -1,
+static const struct v4l2_ioctl_ops meye_ioctl_ops = {
        .vidioc_querycap        = vidioc_querycap,
        .vidioc_enum_input      = vidioc_enum_input,
        .vidioc_g_input         = vidioc_g_input,
@@ -1724,6 +1719,14 @@ static struct video_device meye_template = {
        .vidioc_default         = vidioc_default,
 };
 
+static struct video_device meye_template = {
+       .name           = "meye",
+       .fops           = &meye_fops,
+       .ioctl_ops      = &meye_ioctl_ops,
+       .release        = video_device_release,
+       .minor          = -1,
+};
+
 #ifdef CONFIG_PM
 static int meye_suspend(struct pci_dev *pdev, pm_message_t state)
 {
@@ -1801,7 +1804,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        }
 
        memcpy(meye.video_dev, &meye_template, sizeof(meye_template));
-       meye.video_dev->dev = &meye.mchip_dev->dev;
+       meye.video_dev->parent = &meye.mchip_dev->dev;
 
        if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
                printk(KERN_ERR "meye: unable to power on the camera\n");
index 5691e019d19567d56ba8f9ba1f82a354f55a6ee5..3da74dcee9024abe29bc341c75c09a1da224abb9 100644 (file)
@@ -51,9 +51,9 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/videodev.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/v4l2-i2c-drv-legacy.h>
 #include <media/tvaudio.h>
 #include <media/msp3400.h>
index 1622f70e4dd0b4244f7f16c098182a4df171a10b..846a14a61fd1fc049947a0bd7908392b54977771 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/freezer.h>
-#include <linux/videodev.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/msp3400.h>
index ee43499544c13d9f01cd12d1c973762099475db8..554d2295484e5f1b02f7fec28c34768fa596d0dd 100644 (file)
@@ -120,7 +120,7 @@ static int mt9m001_init(struct soc_camera_device *icd)
        int ret;
 
        /* Disable chip, synchronous option update */
-       dev_dbg(icd->vdev->dev, "%s\n", __func__);
+       dev_dbg(icd->vdev->parent, "%s\n", __func__);
 
        ret = reg_write(icd, MT9M001_RESET, 1);
        if (ret >= 0)
index eafb0c7736e630bff974b002db478702aeee5100..9edaca4371d7cedb5903d324e531eb4f16469a38 100644 (file)
@@ -4666,9 +4666,7 @@ static const struct file_operations ov511_fops = {
 };
 
 static struct video_device vdev_template = {
-       .owner =        THIS_MODULE,
        .name =         "OV511 USB Camera",
-       .type =         VID_TYPE_CAPTURE,
        .fops =         &ov511_fops,
        .release =      video_device_release,
        .minor =        -1,
@@ -5661,43 +5659,43 @@ static int ov_create_sysfs(struct video_device *vdev)
 {
        int rc;
 
-       rc = video_device_create_file(vdev, &dev_attr_custom_id);
+       rc = device_create_file(&vdev->dev, &dev_attr_custom_id);
        if (rc) goto err;
-       rc = video_device_create_file(vdev, &dev_attr_model);
+       rc = device_create_file(&vdev->dev, &dev_attr_model);
        if (rc) goto err_id;
-       rc = video_device_create_file(vdev, &dev_attr_bridge);
+       rc = device_create_file(&vdev->dev, &dev_attr_bridge);
        if (rc) goto err_model;
-       rc = video_device_create_file(vdev, &dev_attr_sensor);
+       rc = device_create_file(&vdev->dev, &dev_attr_sensor);
        if (rc) goto err_bridge;
-       rc = video_device_create_file(vdev, &dev_attr_brightness);
+       rc = device_create_file(&vdev->dev, &dev_attr_brightness);
        if (rc) goto err_sensor;
-       rc = video_device_create_file(vdev, &dev_attr_saturation);
+       rc = device_create_file(&vdev->dev, &dev_attr_saturation);
        if (rc) goto err_bright;
-       rc = video_device_create_file(vdev, &dev_attr_contrast);
+       rc = device_create_file(&vdev->dev, &dev_attr_contrast);
        if (rc) goto err_sat;
-       rc = video_device_create_file(vdev, &dev_attr_hue);
+       rc = device_create_file(&vdev->dev, &dev_attr_hue);
        if (rc) goto err_contrast;
-       rc = video_device_create_file(vdev, &dev_attr_exposure);
+       rc = device_create_file(&vdev->dev, &dev_attr_exposure);
        if (rc) goto err_hue;
 
        return 0;
 
 err_hue:
-       video_device_remove_file(vdev, &dev_attr_hue);
+       device_remove_file(&vdev->dev, &dev_attr_hue);
 err_contrast:
-       video_device_remove_file(vdev, &dev_attr_contrast);
+       device_remove_file(&vdev->dev, &dev_attr_contrast);
 err_sat:
-       video_device_remove_file(vdev, &dev_attr_saturation);
+       device_remove_file(&vdev->dev, &dev_attr_saturation);
 err_bright:
-       video_device_remove_file(vdev, &dev_attr_brightness);
+       device_remove_file(&vdev->dev, &dev_attr_brightness);
 err_sensor:
-       video_device_remove_file(vdev, &dev_attr_sensor);
+       device_remove_file(&vdev->dev, &dev_attr_sensor);
 err_bridge:
-       video_device_remove_file(vdev, &dev_attr_bridge);
+       device_remove_file(&vdev->dev, &dev_attr_bridge);
 err_model:
-       video_device_remove_file(vdev, &dev_attr_model);
+       device_remove_file(&vdev->dev, &dev_attr_model);
 err_id:
-       video_device_remove_file(vdev, &dev_attr_custom_id);
+       device_remove_file(&vdev->dev, &dev_attr_custom_id);
 err:
        return rc;
 }
@@ -5833,7 +5831,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
                goto error;
 
        memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev));
-       ov->vdev->dev = &intf->dev;
+       ov->vdev->parent = &intf->dev;
        video_set_drvdata(ov->vdev, ov);
 
        for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
index 1010e51189b77bd3f6d2970bd69111659e84e51a..baded1262ca9f68b675ca72d3ad18d045d8f2f41 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 
index 36047d4e70f625d1fa693e210c60eebbb9d20fc8..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
-/*
-    planb - PlanB frame grabber driver
-
-    PlanB is used in the 7x00/8x00 series of PowerMacintosh
-    Computers as video input DMA controller.
-
-    Copyright (C) 1998 Michel Lanners (mlan@cpu.lu)
-
-    Based largely on the bttv driver by Ralph Metzler (rjkm@thp.uni-koeln.de)
-
-    Additional debugging and coding by Takashi Oe (toe@unlserve.unl.edu)
-
-    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.
-*/
-
-/* $Id: planb.c,v 1.18 1999/05/02 17:36:34 mlan Exp $ */
-
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <linux/wait.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/dbdma.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/irq.h>
-#include <linux/mutex.h>
-
-#include "planb.h"
-#include "saa7196.h"
-
-/* Would you mind for some ugly debugging? */
-#if 0
-#define DEBUG(x...) printk(KERN_DEBUG ## x) /* Debug driver */
-#else
-#define DEBUG(x...)            /* Don't debug driver */
-#endif
-
-#if 0
-#define IDEBUG(x...) printk(KERN_DEBUG ## x) /* Debug interrupt part */
-#else
-#define IDEBUG(x...)           /* Don't debug interrupt part */
-#endif
-
-/* Ever seen a Mac with more than 1 of these? */
-#define PLANB_MAX 1
-
-static int planb_num;
-static struct planb planbs[PLANB_MAX];
-static volatile struct planb_registers *planb_regs;
-
-static int def_norm = PLANB_DEF_NORM;  /* default norm */
-static int video_nr = -1;
-
-module_param(def_norm, int, 0);
-MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
-module_param(video_nr, int, 0);
-MODULE_LICENSE("GPL");
-
-
-/* ------------------ PlanB Exported Functions ------------------ */
-static long planb_write(struct video_device *, const char *, unsigned long, int);
-static long planb_read(struct video_device *, char *, unsigned long, int);
-static int planb_open(struct video_device *, int);
-static void planb_close(struct video_device *);
-static int planb_ioctl(struct video_device *, unsigned int, void *);
-static int planb_init_done(struct video_device *);
-static int planb_mmap(struct video_device *, const char *, unsigned long);
-static void release_planb(void);
-int init_planbs(struct video_init *);
-
-/* ------------------ PlanB Internal Functions ------------------ */
-static int planb_prepare_open(struct planb *);
-static void planb_prepare_close(struct planb *);
-static void saa_write_reg(unsigned char, unsigned char);
-static unsigned char saa_status(int, struct planb *);
-static void saa_set(unsigned char, unsigned char, struct planb *);
-static void saa_init_regs(struct planb *);
-static int grabbuf_alloc(struct planb *);
-static int vgrab(struct planb *, struct video_mmap *);
-static void add_clip(struct planb *, struct video_clip *);
-static void fill_cmd_buff(struct planb *);
-static void cmd_buff(struct planb *);
-static volatile struct dbdma_cmd *setup_grab_cmd(int, struct planb *);
-static void overlay_start(struct planb *);
-static void overlay_stop(struct planb *);
-static inline void tab_cmd_dbdma(volatile struct dbdma_cmd *, unsigned short,
-       unsigned int);
-static inline void tab_cmd_store(volatile struct dbdma_cmd *, unsigned int,
-       unsigned int);
-static inline void tab_cmd_gen(volatile struct dbdma_cmd *, unsigned short,
-       unsigned short, unsigned int, unsigned int);
-static int init_planb(struct planb *);
-static int find_planb(void);
-static void planb_pre_capture(int, int, struct planb *);
-static volatile struct dbdma_cmd *cmd_geo_setup(volatile struct dbdma_cmd *,
-                                       int, int, int, int, int, struct planb *);
-static inline void planb_dbdma_stop(volatile struct dbdma_regs *);
-static unsigned int saa_geo_setup(int, int, int, int, struct planb *);
-static inline int overlay_is_active(struct planb *);
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-static int grabbuf_alloc(struct planb *pb)
-{
-       int i, npage;
-
-       npage = MAX_GBUFFERS * ((PLANB_MAX_FBUF / PAGE_SIZE + 1)
-#ifndef PLANB_GSCANLINE
-               + MAX_LNUM
-#endif /* PLANB_GSCANLINE */
-               );
-       if ((pb->rawbuf = kmalloc(npage
-                               * sizeof(unsigned long), GFP_KERNEL)) == 0)
-               return -ENOMEM;
-       for (i = 0; i < npage; i++) {
-               pb->rawbuf[i] = (unsigned char *)__get_free_pages(GFP_KERNEL
-                                                               |GFP_DMA, 0);
-               if (!pb->rawbuf[i])
-                       break;
-               SetPageReserved(virt_to_page(pb->rawbuf[i]));
-       }
-       if (i-- < npage) {
-               printk(KERN_DEBUG "PlanB: init_grab: grab buffer not allocated\n");
-               for (; i > 0; i--) {
-                       ClearPageReserved(virt_to_page(pb->rawbuf[i]));
-                       free_pages((unsigned long)pb->rawbuf[i], 0);
-               }
-               kfree(pb->rawbuf);
-               return -ENOBUFS;
-       }
-       pb->rawbuf_size = npage;
-       return 0;
-}
-
-/*****************************/
-/* Hardware access functions */
-/*****************************/
-
-static void saa_write_reg(unsigned char addr, unsigned char val)
-{
-       planb_regs->saa_addr = addr; eieio();
-       planb_regs->saa_regval = val; eieio();
-       return;
-}
-
-/* return  status byte 0 or 1: */
-static unsigned char saa_status(int byte, struct planb *pb)
-{
-       saa_regs[pb->win.norm][SAA7196_STDC] =
-               (saa_regs[pb->win.norm][SAA7196_STDC] & ~2) | ((byte & 1) << 1);
-       saa_write_reg (SAA7196_STDC, saa_regs[pb->win.norm][SAA7196_STDC]);
-
-       /* Let's wait 30msec for this one */
-       msleep_interruptible(30);
-
-       return (unsigned char)in_8 (&planb_regs->saa_status);
-}
-
-static void saa_set(unsigned char addr, unsigned char val, struct planb *pb)
-{
-       if(saa_regs[pb->win.norm][addr] != val) {
-               saa_regs[pb->win.norm][addr] = val;
-               saa_write_reg (addr, val);
-       }
-       return;
-}
-
-static void saa_init_regs(struct planb *pb)
-{
-       int i;
-
-       for (i = 0; i < SAA7196_NUMREGS; i++)
-               saa_write_reg (i, saa_regs[pb->win.norm][i]);
-}
-
-static unsigned int saa_geo_setup(int width, int height, int interlace, int bpp,
-       struct planb *pb)
-{
-       int ht, norm = pb->win.norm;
-
-       switch(bpp) {
-       case 2:
-               /* RGB555+a 1x16-bit + 16-bit transparent */
-               saa_regs[norm][SAA7196_FMTS] &= ~0x3;
-               break;
-       case 1:
-       case 4:
-               /* RGB888 1x24-bit + 8-bit transparent */
-               saa_regs[norm][SAA7196_FMTS] &= ~0x1;
-               saa_regs[norm][SAA7196_FMTS] |= 0x2;
-               break;
-       default:
-               return -EINVAL;
-       }
-       ht = (interlace ? height / 2 : height);
-       saa_regs[norm][SAA7196_OUTPIX] = (unsigned char) (width & 0x00ff);
-       saa_regs[norm][SAA7196_HFILT] = (saa_regs[norm][SAA7196_HFILT] & ~0x3)
-                                               | (width >> 8 & 0x3);
-       saa_regs[norm][SAA7196_OUTLINE] = (unsigned char) (ht & 0xff);
-       saa_regs[norm][SAA7196_VYP] = (saa_regs[norm][SAA7196_VYP] & ~0x3)
-                                               | (ht >> 8 & 0x3);
-       /* feed both fields if interlaced, or else feed only even fields */
-       saa_regs[norm][SAA7196_FMTS] = (interlace) ?
-                                       (saa_regs[norm][SAA7196_FMTS] & ~0x60)
-                                       : (saa_regs[norm][SAA7196_FMTS] | 0x60);
-       /* transparent mode; extended format enabled */
-       saa_regs[norm][SAA7196_DPATH] |= 0x3;
-
-       return 0;
-}
-
-/***************************/
-/* DBDMA support functions */
-/***************************/
-
-static inline void planb_dbdma_restart(volatile struct dbdma_regs *ch)
-{
-       out_le32(&ch->control, PLANB_CLR(RUN));
-       out_le32(&ch->control, PLANB_SET(RUN|WAKE) | PLANB_CLR(PAUSE));
-}
-
-static inline void planb_dbdma_stop(volatile struct dbdma_regs *ch)
-{
-       int i = 0;
-
-       out_le32(&ch->control, PLANB_CLR(RUN) | PLANB_SET(FLUSH));
-       while((in_le32(&ch->status) == (ACTIVE | FLUSH)) && (i < 999)) {
-               IDEBUG("PlanB: waiting for DMA to stop\n");
-               i++;
-       }
-}
-
-static inline void tab_cmd_dbdma(volatile struct dbdma_cmd *ch,
-       unsigned short command, unsigned int cmd_dep)
-{
-       st_le16(&ch->command, command);
-       st_le32(&ch->cmd_dep, cmd_dep);
-}
-
-static inline void tab_cmd_store(volatile struct dbdma_cmd *ch,
-       unsigned int phy_addr, unsigned int cmd_dep)
-{
-       st_le16(&ch->command, STORE_WORD | KEY_SYSTEM);
-       st_le16(&ch->req_count, 4);
-       st_le32(&ch->phy_addr, phy_addr);
-       st_le32(&ch->cmd_dep, cmd_dep);
-}
-
-static inline void tab_cmd_gen(volatile struct dbdma_cmd *ch,
-       unsigned short command, unsigned short req_count,
-       unsigned int phy_addr, unsigned int cmd_dep)
-{
-       st_le16(&ch->command, command);
-       st_le16(&ch->req_count, req_count);
-       st_le32(&ch->phy_addr, phy_addr);
-       st_le32(&ch->cmd_dep, cmd_dep);
-}
-
-static volatile struct dbdma_cmd *cmd_geo_setup(
-       volatile struct dbdma_cmd *c1, int width, int height, int interlace,
-       int bpp, int clip, struct planb *pb)
-{
-       int norm = pb->win.norm;
-
-       if((saa_geo_setup(width, height, interlace, bpp, pb)) != 0)
-               return (volatile struct dbdma_cmd *)NULL;
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
-                                                       SAA7196_FMTS);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
-                                       saa_regs[norm][SAA7196_FMTS]);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
-                                                       SAA7196_DPATH);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
-                                       saa_regs[norm][SAA7196_DPATH]);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->even),
-                                       bpp | ((clip)? PLANB_CLIPMASK: 0));
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->odd),
-                                       bpp | ((clip)? PLANB_CLIPMASK: 0));
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
-                                                       SAA7196_OUTPIX);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
-                                       saa_regs[norm][SAA7196_OUTPIX]);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
-                                                       SAA7196_HFILT);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
-                                       saa_regs[norm][SAA7196_HFILT]);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
-                                                       SAA7196_OUTLINE);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
-                                       saa_regs[norm][SAA7196_OUTLINE]);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
-                                                       SAA7196_VYP);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
-                                       saa_regs[norm][SAA7196_VYP]);
-       return c1;
-}
-
-/******************************/
-/* misc. supporting functions */
-/******************************/
-
-static inline void planb_lock(struct planb *pb)
-{
-       mutex_lock(&pb->lock);
-}
-
-static inline void planb_unlock(struct planb *pb)
-{
-       mutex_unlock(&pb->lock);
-}
-
-/***************/
-/* Driver Core */
-/***************/
-
-static int planb_prepare_open(struct planb *pb)
-{
-       int     i, size;
-
-       /* allocate memory for two plus alpha command buffers (size: max lines,
-          plus 40 commands handling, plus 1 alignment), plus dummy command buf,
-          plus clipmask buffer, plus frame grabbing status */
-       size = (pb->tab_size*(2+MAX_GBUFFERS*TAB_FACTOR)+1+MAX_GBUFFERS
-               * PLANB_DUMMY)*sizeof(struct dbdma_cmd)
-               +(PLANB_MAXLINES*((PLANB_MAXPIXELS+7)& ~7))/8
-               +MAX_GBUFFERS*sizeof(unsigned int);
-       if ((pb->priv_space = kzalloc (size, GFP_KERNEL)) == 0)
-               return -ENOMEM;
-       pb->overlay_last1 = pb->ch1_cmd = (volatile struct dbdma_cmd *)
-                                               DBDMA_ALIGN (pb->priv_space);
-       pb->overlay_last2 = pb->ch2_cmd = pb->ch1_cmd + pb->tab_size;
-       pb->ch1_cmd_phys = virt_to_bus(pb->ch1_cmd);
-       pb->cap_cmd[0] = pb->ch2_cmd + pb->tab_size;
-       pb->pre_cmd[0] = pb->cap_cmd[0] + pb->tab_size * TAB_FACTOR;
-       for (i = 1; i < MAX_GBUFFERS; i++) {
-               pb->cap_cmd[i] = pb->pre_cmd[i-1] + PLANB_DUMMY;
-               pb->pre_cmd[i] = pb->cap_cmd[i] + pb->tab_size * TAB_FACTOR;
-       }
-       pb->frame_stat=(volatile unsigned int *)(pb->pre_cmd[MAX_GBUFFERS-1]
-                                               + PLANB_DUMMY);
-       pb->mask = (unsigned char *)(pb->frame_stat+MAX_GBUFFERS);
-
-       pb->rawbuf = NULL;
-       pb->rawbuf_size = 0;
-       pb->grabbing = 0;
-       for (i = 0; i < MAX_GBUFFERS; i++) {
-               pb->frame_stat[i] = GBUFFER_UNUSED;
-               pb->gwidth[i] = 0;
-               pb->gheight[i] = 0;
-               pb->gfmt[i] = 0;
-               pb->gnorm_switch[i] = 0;
-#ifndef PLANB_GSCANLINE
-               pb->lsize[i] = 0;
-               pb->lnum[i] = 0;
-#endif /* PLANB_GSCANLINE */
-       }
-       pb->gcount = 0;
-       pb->suspend = 0;
-       pb->last_fr = -999;
-       pb->prev_last_fr = -999;
-
-       /* Reset DMA controllers */
-       planb_dbdma_stop(&pb->planb_base->ch2);
-       planb_dbdma_stop(&pb->planb_base->ch1);
-
-       return 0;
-}
-
-static void planb_prepare_close(struct planb *pb)
-{
-       int i;
-
-       /* make sure the dma's are idle */
-       planb_dbdma_stop(&pb->planb_base->ch2);
-       planb_dbdma_stop(&pb->planb_base->ch1);
-       /* free kernel memory of command buffers */
-       if(pb->priv_space != 0) {
-               kfree (pb->priv_space);
-               pb->priv_space = 0;
-               pb->cmd_buff_inited = 0;
-       }
-       if(pb->rawbuf) {
-               for (i = 0; i < pb->rawbuf_size; i++) {
-                       ClearPageReserved(virt_to_page(pb->rawbuf[i]));
-                       free_pages((unsigned long)pb->rawbuf[i], 0);
-               }
-               kfree(pb->rawbuf);
-       }
-       pb->rawbuf = NULL;
-}
-
-/*****************************/
-/* overlay support functions */
-/*****************************/
-
-static inline int overlay_is_active(struct planb *pb)
-{
-       unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);
-       unsigned int caddr = (unsigned)in_le32(&pb->planb_base->ch1.cmdptr);
-
-       return (in_le32(&pb->overlay_last1->cmd_dep) == pb->ch1_cmd_phys)
-                       && (caddr < (pb->ch1_cmd_phys + size))
-                       && (caddr >= (unsigned)pb->ch1_cmd_phys);
-}
-
-static void overlay_start(struct planb *pb)
-{
-
-       DEBUG("PlanB: overlay_start()\n");
-
-       if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {
-
-               DEBUG("PlanB: presumably, grabbing is in progress...\n");
-
-               planb_dbdma_stop(&pb->planb_base->ch2);
-               out_le32 (&pb->planb_base->ch2.cmdptr,
-                                               virt_to_bus(pb->ch2_cmd));
-               planb_dbdma_restart(&pb->planb_base->ch2);
-               st_le16 (&pb->ch1_cmd->command, DBDMA_NOP);
-               tab_cmd_dbdma(pb->last_cmd[pb->last_fr],
-                                       DBDMA_NOP | BR_ALWAYS,
-                                       virt_to_bus(pb->ch1_cmd));
-               eieio();
-               pb->prev_last_fr = pb->last_fr;
-               pb->last_fr = -2;
-               if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {
-                       IDEBUG("PlanB: became inactive "
-                               "in the mean time... reactivating\n");
-                       planb_dbdma_stop(&pb->planb_base->ch1);
-                       out_le32 (&pb->planb_base->ch1.cmdptr,
-                                               virt_to_bus(pb->ch1_cmd));
-                       planb_dbdma_restart(&pb->planb_base->ch1);
-               }
-       } else {
-
-               DEBUG("PlanB: currently idle, so can do whatever\n");
-
-               planb_dbdma_stop(&pb->planb_base->ch2);
-               planb_dbdma_stop(&pb->planb_base->ch1);
-               st_le32 (&pb->planb_base->ch2.cmdptr,
-                                               virt_to_bus(pb->ch2_cmd));
-               st_le32 (&pb->planb_base->ch1.cmdptr,
-                                               virt_to_bus(pb->ch1_cmd));
-               out_le16 (&pb->ch1_cmd->command, DBDMA_NOP);
-               planb_dbdma_restart(&pb->planb_base->ch2);
-               planb_dbdma_restart(&pb->planb_base->ch1);
-               pb->last_fr = -1;
-       }
-       return;
-}
-
-static void overlay_stop(struct planb *pb)
-{
-       DEBUG("PlanB: overlay_stop()\n");
-
-       if(pb->last_fr == -1) {
-
-               DEBUG("PlanB: no grabbing, it seems...\n");
-
-               planb_dbdma_stop(&pb->planb_base->ch2);
-               planb_dbdma_stop(&pb->planb_base->ch1);
-               pb->last_fr = -999;
-       } else if(pb->last_fr == -2) {
-               unsigned int cmd_dep;
-               tab_cmd_dbdma(pb->cap_cmd[pb->prev_last_fr], DBDMA_STOP, 0);
-               eieio();
-               cmd_dep = (unsigned int)in_le32(&pb->overlay_last1->cmd_dep);
-               if(overlay_is_active(pb)) {
-
-                       DEBUG("PlanB: overlay is currently active\n");
-
-                       planb_dbdma_stop(&pb->planb_base->ch2);
-                       planb_dbdma_stop(&pb->planb_base->ch1);
-                       if(cmd_dep != pb->ch1_cmd_phys) {
-                               out_le32(&pb->planb_base->ch1.cmdptr,
-                                               virt_to_bus(pb->overlay_last1));
-                               planb_dbdma_restart(&pb->planb_base->ch1);
-                       }
-               }
-               pb->last_fr = pb->prev_last_fr;
-               pb->prev_last_fr = -999;
-       }
-       return;
-}
-
-static void suspend_overlay(struct planb *pb)
-{
-       int fr = -1;
-       struct dbdma_cmd last;
-
-       DEBUG("PlanB: suspend_overlay: %d\n", pb->suspend);
-
-       if(pb->suspend++)
-               return;
-       if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {
-               if(pb->last_fr == -2) {
-                       fr = pb->prev_last_fr;
-                       memcpy(&last, (void*)pb->last_cmd[fr], sizeof(last));
-                       tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);
-               }
-               if(overlay_is_active(pb)) {
-                       planb_dbdma_stop(&pb->planb_base->ch2);
-                       planb_dbdma_stop(&pb->planb_base->ch1);
-                       pb->suspended.overlay = 1;
-                       pb->suspended.frame = fr;
-                       memcpy(&pb->suspended.cmd, &last, sizeof(last));
-                       return;
-               }
-       }
-       pb->suspended.overlay = 0;
-       pb->suspended.frame = fr;
-       memcpy(&pb->suspended.cmd, &last, sizeof(last));
-       return;
-}
-
-static void resume_overlay(struct planb *pb)
-{
-
-       DEBUG("PlanB: resume_overlay: %d\n", pb->suspend);
-
-       if(pb->suspend > 1)
-               return;
-       if(pb->suspended.frame != -1) {
-               memcpy((void*)pb->last_cmd[pb->suspended.frame],
-                               &pb->suspended.cmd, sizeof(pb->suspended.cmd));
-       }
-       if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {
-               goto finish;
-       }
-       if(pb->suspended.overlay) {
-
-               DEBUG("PlanB: overlay being resumed\n");
-
-               st_le16 (&pb->ch1_cmd->command, DBDMA_NOP);
-               st_le16 (&pb->ch2_cmd->command, DBDMA_NOP);
-               /* Set command buffer addresses */
-               st_le32(&pb->planb_base->ch1.cmdptr,
-                                       virt_to_bus(pb->overlay_last1));
-               out_le32(&pb->planb_base->ch2.cmdptr,
-                                       virt_to_bus(pb->overlay_last2));
-               /* Start the DMA controller */
-               out_le32 (&pb->planb_base->ch2.control,
-                               PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));
-               out_le32 (&pb->planb_base->ch1.control,
-                               PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));
-       } else if(pb->suspended.frame != -1) {
-               out_le32(&pb->planb_base->ch1.cmdptr,
-                               virt_to_bus(pb->last_cmd[pb->suspended.frame]));
-               out_le32 (&pb->planb_base->ch1.control,
-                               PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));
-       }
-
-finish:
-       pb->suspend--;
-       wake_up_interruptible(&pb->suspendq);
-}
-
-static void add_clip(struct planb *pb, struct video_clip *clip)
-{
-       volatile unsigned char  *base;
-       int     xc = clip->x, yc = clip->y;
-       int     wc = clip->width, hc = clip->height;
-       int     ww = pb->win.width, hw = pb->win.height;
-       int     x, y, xtmp1, xtmp2;
-
-       DEBUG("PlanB: clip %dx%d+%d+%d\n", wc, hc, xc, yc);
-
-       if(xc < 0) {
-               wc += xc;
-               xc = 0;
-       }
-       if(yc < 0) {
-               hc += yc;
-               yc = 0;
-       }
-       if(xc + wc > ww)
-               wc = ww - xc;
-       if(wc <= 0) /* Nothing to do */
-               return;
-       if(yc + hc > hw)
-               hc = hw - yc;
-
-       for (y = yc; y < yc+hc; y++) {
-               xtmp1=xc>>3;
-               xtmp2=(xc+wc)>>3;
-               base = pb->mask + y*96;
-               if(xc != 0 || wc >= 8)
-                       *(base + xtmp1) &= (unsigned char)(0x00ff &
-                               (0xff00 >> (xc&7)));
-               for (x = xtmp1 + 1; x < xtmp2; x++) {
-                       *(base + x) = 0;
-               }
-               if(xc < (ww & ~0x7))
-                       *(base + xtmp2) &= (unsigned char)(0x00ff >>
-                               ((xc+wc) & 7));
-       }
-
-       return;
-}
-
-static void fill_cmd_buff(struct planb *pb)
-{
-       int restore = 0;
-       volatile struct dbdma_cmd last;
-
-       DEBUG("PlanB: fill_cmd_buff()\n");
-
-       if(pb->overlay_last1 != pb->ch1_cmd) {
-               restore = 1;
-               last = *(pb->overlay_last1);
-       }
-       memset ((void *) pb->ch1_cmd, 0, 2 * pb->tab_size
-                                       * sizeof(struct dbdma_cmd));
-       cmd_buff (pb);
-       if(restore)
-               *(pb->overlay_last1) = last;
-       if(pb->suspended.overlay) {
-               unsigned long jump_addr = in_le32(&pb->overlay_last1->cmd_dep);
-               if(jump_addr != pb->ch1_cmd_phys) {
-                       int i;
-
-                       DEBUG("PlanB: adjusting ch1's jump address\n");
-
-                       for(i = 0; i < MAX_GBUFFERS; i++) {
-                               if(pb->need_pre_capture[i]) {
-                                   if(jump_addr == virt_to_bus(pb->pre_cmd[i]))
-                                       goto found;
-                               } else {
-                                   if(jump_addr == virt_to_bus(pb->cap_cmd[i]))
-                                       goto found;
-                               }
-                       }
-
-                       DEBUG("PlanB: not found...\n");
-
-                       goto out;
-found:
-                       if(pb->need_pre_capture[i])
-                               out_le32(&pb->pre_cmd[i]->phy_addr,
-                                               virt_to_bus(pb->overlay_last1));
-                       else
-                               out_le32(&pb->cap_cmd[i]->phy_addr,
-                                               virt_to_bus(pb->overlay_last1));
-               }
-       }
-out:
-       pb->cmd_buff_inited = 1;
-
-       return;
-}
-
-static void cmd_buff(struct planb *pb)
-{
-       int             i, bpp, count, nlines, stepsize, interlace;
-       unsigned long   base, jump, addr_com, addr_dep;
-       volatile struct dbdma_cmd *c1 = pb->ch1_cmd;
-       volatile struct dbdma_cmd *c2 = pb->ch2_cmd;
-
-       interlace = pb->win.interlace;
-       bpp = pb->win.bpp;
-       count = (bpp * ((pb->win.x + pb->win.width > pb->win.swidth) ?
-               (pb->win.swidth - pb->win.x) : pb->win.width));
-       nlines = ((pb->win.y + pb->win.height > pb->win.sheight) ?
-               (pb->win.sheight - pb->win.y) : pb->win.height);
-
-       /* Do video in: */
-
-       /* Preamble commands: */
-       addr_com = virt_to_bus(c1);
-       addr_dep = virt_to_bus(&c1->cmd_dep);
-       tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
-       jump = virt_to_bus(c1+16); /* 14 by cmd_geo_setup() and 2 for padding */
-       if((c1 = cmd_geo_setup(c1, pb->win.width, pb->win.height, interlace,
-                                       bpp, 1, pb)) == NULL) {
-               printk(KERN_WARNING "PlanB: encountered serious problems\n");
-               tab_cmd_dbdma(pb->ch1_cmd + 1, DBDMA_STOP, 0);
-               tab_cmd_dbdma(pb->ch2_cmd + 1, DBDMA_STOP, 0);
-               return;
-       }
-       tab_cmd_store(c1++, addr_com, (unsigned)(DBDMA_NOP | BR_ALWAYS) << 16);
-       tab_cmd_store(c1++, addr_dep, jump);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),
-                                                       PLANB_SET(FIELD_SYNC));
-               /* (1) wait for field sync to be set */
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-                                                       PLANB_SET(ODD_FIELD));
-               /* wait for field sync to be cleared */
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
-               /* if not odd field, wait until field sync is set again */
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
-               /* assert ch_sync to ch2 */
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control),
-                                                       PLANB_SET(CH_SYNC));
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-                                                       PLANB_SET(DMA_ABORT));
-
-       base = (pb->frame_buffer_phys + pb->offset + pb->win.y * (pb->win.bpl
-                                       + pb->win.pad) + pb->win.x * bpp);
-
-       if (interlace) {
-               stepsize = 2;
-               jump = virt_to_bus(c1 + (nlines + 1) / 2);
-       } else {
-               stepsize = 1;
-               jump = virt_to_bus(c1 + nlines);
-       }
-
-       /* even field data: */
-       for (i=0; i < nlines; i += stepsize, c1++)
-               tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET,
-                       count, base + i * (pb->win.bpl + pb->win.pad), jump);
-
-       /* For non-interlaced, we use even fields only */
-       if (!interlace)
-               goto cmd_tab_data_end;
-
-       /* Resync to odd field */
-               /* (2) wait for field sync to be set */
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-                                                       PLANB_SET(ODD_FIELD));
-               /* wait for field sync to be cleared */
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
-               /* if not odd field, wait until field sync is set again */
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
-               /* assert ch_sync to ch2 */
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control),
-                                                       PLANB_SET(CH_SYNC));
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-                                                       PLANB_SET(DMA_ABORT));
-
-       /* odd field data: */
-       jump = virt_to_bus(c1 + nlines / 2);
-       for (i=1; i < nlines; i += stepsize, c1++)
-               tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
-                       base + i * (pb->win.bpl + pb->win.pad), jump);
-
-       /* And jump back to the start */
-cmd_tab_data_end:
-       pb->overlay_last1 = c1; /* keep a pointer to the last command */
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->ch1_cmd));
-
-       /* Clipmask command buffer */
-
-       /* Preamble commands: */
-       tab_cmd_dbdma(c2++, DBDMA_NOP, 0);
-       tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel),
-                                                       PLANB_SET(CH_SYNC));
-               /* wait until ch1 asserts ch_sync */
-       tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);
-               /* clear ch_sync asserted by ch1 */
-       tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.control),
-                                                       PLANB_CLR(CH_SYNC));
-       tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel),
-                                                       PLANB_SET(FIELD_SYNC));
-       tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),
-                                                       PLANB_SET(ODD_FIELD));
-
-       /* jump to end of even field if appropriate */
-       /* this points to (interlace)? pos. C: pos. B */
-       jump = (interlace) ? virt_to_bus(c2 + (nlines + 1) / 2 + 2):
-                                               virt_to_bus(c2 + nlines + 2);
-               /* if odd field, skip over to odd field clipmasking */
-       tab_cmd_dbdma(c2++, DBDMA_NOP | BR_IFSET, jump);
-
-       /* even field mask: */
-       tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),
-                                                       PLANB_SET(DMA_ABORT));
-       /* this points to pos. B */
-       jump = (interlace) ? virt_to_bus(c2 + nlines + 1):
-                                               virt_to_bus(c2 + nlines);
-       base = virt_to_bus(pb->mask);
-       for (i=0; i < nlines; i += stepsize, c2++)
-               tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,
-                       base + i * 96, jump);
-
-       /* For non-interlaced, we use only even fields */
-       if(!interlace)
-               goto cmd_tab_mask_end;
-
-       /* odd field mask: */
-/* C */        tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),
-                                                       PLANB_SET(DMA_ABORT));
-       /* this points to pos. B */
-       jump = virt_to_bus(c2 + nlines / 2);
-       base = virt_to_bus(pb->mask);
-       for (i=1; i < nlines; i += 2, c2++)     /* abort if set */
-               tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,
-                       base + i * 96, jump);
-
-       /* Inform channel 1 and jump back to start */
-cmd_tab_mask_end:
-       /* ok, I just realized this is kind of flawed. */
-       /* this part is reached only after odd field clipmasking. */
-       /* wanna clean up? */
-               /* wait for field sync to be set */
-               /* corresponds to fsync (1) of ch1 */
-/* B */        tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);
-               /* restart ch1, meant to clear any dead bit or something */
-       tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch1.control),
-                                                       PLANB_CLR(RUN));
-       tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch1.control),
-                                                       PLANB_SET(RUN));
-       pb->overlay_last2 = c2; /* keep a pointer to the last command */
-               /* start over even field clipmasking */
-       tab_cmd_dbdma(c2, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->ch2_cmd));
-
-       eieio();
-       return;
-}
-
-/*********************************/
-/* grabdisplay support functions */
-/*********************************/
-
-static int palette2fmt[] = {
-       0,
-       PLANB_GRAY,
-       0,
-       0,
-       0,
-       PLANB_COLOUR32,
-       PLANB_COLOUR15,
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,
-};
-
-#define PLANB_PALETTE_MAX 15
-
-static int vgrab(struct planb *pb, struct video_mmap *mp)
-{
-       unsigned int fr = mp->frame;
-       unsigned int format;
-
-       if(pb->rawbuf==NULL) {
-               int err;
-               if((err=grabbuf_alloc(pb)))
-                       return err;
-       }
-
-       IDEBUG("PlanB: grab %d: %dx%d(%u)\n", pb->grabbing,
-                                               mp->width, mp->height, fr);
-
-       if(pb->grabbing >= MAX_GBUFFERS)
-               return -ENOBUFS;
-       if(fr > (MAX_GBUFFERS - 1) || fr < 0)
-               return -EINVAL;
-       if(mp->height <= 0 || mp->width <= 0)
-               return -EINVAL;
-       if(mp->format < 0 || mp->format >= PLANB_PALETTE_MAX)
-               return -EINVAL;
-       if((format = palette2fmt[mp->format]) == 0)
-               return -EINVAL;
-       if (mp->height * mp->width * format > PLANB_MAX_FBUF) /* format = bpp */
-               return -EINVAL;
-
-       planb_lock(pb);
-       if(mp->width != pb->gwidth[fr] || mp->height != pb->gheight[fr] ||
-                       format != pb->gfmt[fr] || (pb->gnorm_switch[fr])) {
-               int i;
-#ifndef PLANB_GSCANLINE
-               unsigned int osize = pb->gwidth[fr] * pb->gheight[fr]
-                                                               * pb->gfmt[fr];
-               unsigned int nsize = mp->width * mp->height * format;
-#endif
-
-               IDEBUG("PlanB: gwidth = %d, gheight = %d, mp->format = %u\n",
-                                       mp->width, mp->height, mp->format);
-
-#ifndef PLANB_GSCANLINE
-               if(pb->gnorm_switch[fr])
-                       nsize = 0;
-               if (nsize < osize) {
-                       for(i = pb->gbuf_idx[fr]; osize > 0; i++) {
-                               memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);
-                               osize -= PAGE_SIZE;
-                       }
-               }
-               for(i = pb->l_fr_addr_idx[fr]; i < pb->l_fr_addr_idx[fr]
-                                                       + pb->lnum[fr]; i++)
-                       memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);
-#else
-/* XXX TODO */
-/*
-               if(pb->gnorm_switch[fr])
-                       memset((void *)pb->gbuffer[fr], 0,
-                                       pb->gbytes_per_line * pb->gheight[fr]);
-               else {
-                       if(mp->
-                       for(i = 0; i < pb->gheight[fr]; i++) {
-                               memset((void *)(pb->gbuffer[fr]
-                                       + pb->gbytes_per_line * i
-                       }
-               }
-*/
-#endif
-               pb->gwidth[fr] = mp->width;
-               pb->gheight[fr] = mp->height;
-               pb->gfmt[fr] = format;
-               pb->last_cmd[fr] = setup_grab_cmd(fr, pb);
-               planb_pre_capture(fr, pb->gfmt[fr], pb); /* gfmt = bpp */
-               pb->need_pre_capture[fr] = 1;
-               pb->gnorm_switch[fr] = 0;
-       } else
-               pb->need_pre_capture[fr] = 0;
-       pb->frame_stat[fr] = GBUFFER_GRABBING;
-       if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {
-
-               IDEBUG("PlanB: ch1 inactive, initiating grabbing\n");
-
-               planb_dbdma_stop(&pb->planb_base->ch1);
-               if(pb->need_pre_capture[fr]) {
-
-                       IDEBUG("PlanB: padding pre-capture sequence\n");
-
-                       out_le32 (&pb->planb_base->ch1.cmdptr,
-                                               virt_to_bus(pb->pre_cmd[fr]));
-               } else {
-                       tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);
-                       tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);
-               /* let's be on the safe side. here is not timing critical. */
-                       tab_cmd_dbdma((pb->cap_cmd[fr] + 1), DBDMA_NOP, 0);
-                       out_le32 (&pb->planb_base->ch1.cmdptr,
-                                               virt_to_bus(pb->cap_cmd[fr]));
-               }
-               planb_dbdma_restart(&pb->planb_base->ch1);
-               pb->last_fr = fr;
-       } else {
-               int i;
-
-               IDEBUG("PlanB: ch1 active, grabbing being queued\n");
-
-               if((pb->last_fr == -1) || ((pb->last_fr == -2) &&
-                                               overlay_is_active(pb))) {
-
-                       IDEBUG("PlanB: overlay is active, grabbing defered\n");
-
-                       tab_cmd_dbdma(pb->last_cmd[fr],
-                                       DBDMA_NOP | BR_ALWAYS,
-                                       virt_to_bus(pb->ch1_cmd));
-                       if(pb->need_pre_capture[fr]) {
-
-                               IDEBUG("PlanB: padding pre-capture sequence\n");
-
-                               tab_cmd_store(pb->pre_cmd[fr],
-                                   virt_to_bus(&pb->overlay_last1->cmd_dep),
-                                               virt_to_bus(pb->ch1_cmd));
-                               eieio();
-                               out_le32 (&pb->overlay_last1->cmd_dep,
-                                               virt_to_bus(pb->pre_cmd[fr]));
-                       } else {
-                               tab_cmd_store(pb->cap_cmd[fr],
-                                   virt_to_bus(&pb->overlay_last1->cmd_dep),
-                                               virt_to_bus(pb->ch1_cmd));
-                               tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
-                                                               DBDMA_NOP, 0);
-                               eieio();
-                               out_le32 (&pb->overlay_last1->cmd_dep,
-                                               virt_to_bus(pb->cap_cmd[fr]));
-                       }
-                       for(i = 0; overlay_is_active(pb) && i < 999; i++)
-                               IDEBUG("PlanB: waiting for overlay done\n");
-                       tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0);
-                       pb->prev_last_fr = fr;
-                       pb->last_fr = -2;
-               } else if(pb->last_fr == -2) {
-
-                       IDEBUG("PlanB: mixed mode detected, grabbing"
-                               " will be done before activating overlay\n");
-
-                       tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0);
-                       if(pb->need_pre_capture[fr]) {
-
-                               IDEBUG("PlanB: padding pre-capture sequence\n");
-
-                               tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr],
-                                               DBDMA_NOP | BR_ALWAYS,
-                                               virt_to_bus(pb->pre_cmd[fr]));
-                               eieio();
-                       } else {
-                               tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);
-                               if(pb->gwidth[pb->prev_last_fr] !=
-                                                               pb->gwidth[fr]
-                                       || pb->gheight[pb->prev_last_fr] !=
-                                                               pb->gheight[fr]
-                                       || pb->gfmt[pb->prev_last_fr] !=
-                                                               pb->gfmt[fr])
-                                       tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
-                                                               DBDMA_NOP, 0);
-                               else
-                                       tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
-                                           DBDMA_NOP | BR_ALWAYS,
-                                           virt_to_bus(pb->cap_cmd[fr] + 16));
-                               tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr],
-                                               DBDMA_NOP | BR_ALWAYS,
-                                               virt_to_bus(pb->cap_cmd[fr]));
-                               eieio();
-                       }
-                       tab_cmd_dbdma(pb->last_cmd[fr],
-                                       DBDMA_NOP | BR_ALWAYS,
-                                       virt_to_bus(pb->ch1_cmd));
-                       eieio();
-                       pb->prev_last_fr = fr;
-                       pb->last_fr = -2;
-               } else {
-
-                       IDEBUG("PlanB: active grabbing session detected\n");
-
-                       if(pb->need_pre_capture[fr]) {
-
-                               IDEBUG("PlanB: padding pre-capture sequence\n");
-
-                               tab_cmd_dbdma(pb->last_cmd[pb->last_fr],
-                                               DBDMA_NOP | BR_ALWAYS,
-                                               virt_to_bus(pb->pre_cmd[fr]));
-                               eieio();
-                       } else {
-                               tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);
-                               tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);
-                               if(pb->gwidth[pb->last_fr] != pb->gwidth[fr]
-                                       || pb->gheight[pb->last_fr] !=
-                                                               pb->gheight[fr]
-                                       || pb->gfmt[pb->last_fr] !=
-                                                               pb->gfmt[fr])
-                                       tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
-                                                               DBDMA_NOP, 0);
-                               else
-                                       tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
-                                           DBDMA_NOP | BR_ALWAYS,
-                                           virt_to_bus(pb->cap_cmd[fr] + 16));
-                               tab_cmd_dbdma(pb->last_cmd[pb->last_fr],
-                                               DBDMA_NOP | BR_ALWAYS,
-                                               virt_to_bus(pb->cap_cmd[fr]));
-                               eieio();
-                       }
-                       pb->last_fr = fr;
-               }
-               if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {
-
-                       IDEBUG("PlanB: became inactive in the mean time..."
-                               "reactivating\n");
-
-                       planb_dbdma_stop(&pb->planb_base->ch1);
-                       out_le32 (&pb->planb_base->ch1.cmdptr,
-                                               virt_to_bus(pb->cap_cmd[fr]));
-                       planb_dbdma_restart(&pb->planb_base->ch1);
-               }
-       }
-       pb->grabbing++;
-       planb_unlock(pb);
-
-       return 0;
-}
-
-static void planb_pre_capture(int fr, int bpp, struct planb *pb)
-{
-       volatile struct dbdma_cmd *c1 = pb->pre_cmd[fr];
-       int interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0;
-
-       tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
-       if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace,
-                                               bpp, 0, pb)) == NULL) {
-               printk(KERN_WARNING "PlanB: encountered some problems\n");
-               tab_cmd_dbdma(pb->pre_cmd[fr] + 1, DBDMA_STOP, 0);
-               return;
-       }
-       /* Sync to even field */
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),
-               PLANB_SET(FIELD_SYNC));
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-               PLANB_SET(ODD_FIELD));
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
-       tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-               PLANB_SET(DMA_ABORT));
-       /* For non-interlaced, we use even fields only */
-       if (pb->gheight[fr] <= pb->maxlines/2)
-               goto cmd_tab_data_end;
-       /* Sync to odd field */
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-               PLANB_SET(ODD_FIELD));
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-               PLANB_SET(DMA_ABORT));
-cmd_tab_data_end:
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->cap_cmd[fr]));
-
-       eieio();
-}
-
-static volatile struct dbdma_cmd *setup_grab_cmd(int fr, struct planb *pb)
-{
-       int             i, bpp, count, nlines, stepsize, interlace;
-#ifdef PLANB_GSCANLINE
-       int             scanline;
-#else
-       int             nlpp, leftover1;
-       unsigned long   base;
-#endif
-       unsigned long   jump;
-       int             pagei;
-       volatile struct dbdma_cmd *c1;
-       volatile struct dbdma_cmd *jump_addr;
-
-       c1 = pb->cap_cmd[fr];
-       interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0;
-       bpp = pb->gfmt[fr];     /* gfmt = bpp */
-       count = bpp * pb->gwidth[fr];
-       nlines = pb->gheight[fr];
-#ifdef PLANB_GSCANLINE
-       scanline = pb->gbytes_per_line;
-#else
-       pb->lsize[fr] = count;
-       pb->lnum[fr] = 0;
-#endif
-
-       /* Do video in: */
-
-       /* Preamble commands: */
-       tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(c1 + 16)); c1++;
-       if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace,
-                                               bpp, 0, pb)) == NULL) {
-               printk(KERN_WARNING "PlanB: encountered serious problems\n");
-               tab_cmd_dbdma(pb->cap_cmd[fr] + 1, DBDMA_STOP, 0);
-               return (pb->cap_cmd[fr] + 2);
-       }
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),
-               PLANB_SET(FIELD_SYNC));
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-               PLANB_SET(ODD_FIELD));
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
-       tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-               PLANB_SET(DMA_ABORT));
-
-       if (interlace) {
-               stepsize = 2;
-               jump_addr = c1 + TAB_FACTOR * (nlines + 1) / 2;
-       } else {
-               stepsize = 1;
-               jump_addr = c1 + TAB_FACTOR * nlines;
-       }
-       jump = virt_to_bus(jump_addr);
-
-       /* even field data: */
-
-       pagei = pb->gbuf_idx[fr];
-#ifdef PLANB_GSCANLINE
-       for (i = 0; i < nlines; i += stepsize) {
-               tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
-                                       virt_to_bus(pb->rawbuf[pagei
-                                       + i * scanline / PAGE_SIZE]), jump);
-       }
-#else
-       i = 0;
-       leftover1 = 0;
-       do {
-           int j;
-
-           base = virt_to_bus(pb->rawbuf[pagei]);
-           nlpp = (PAGE_SIZE - leftover1) / count / stepsize;
-           for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++)
-               tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET,
-                         count, base + count * j * stepsize + leftover1, jump);
-           if(i < nlines) {
-               int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
-
-               if(lov0 == 0)
-                   leftover1 = 0;
-               else {
-                   if(lov0 >= count) {
-                       tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, base
-                               + count * nlpp * stepsize + leftover1, jump);
-                   } else {
-                       pb->l_to_addr[fr][pb->lnum[fr]] = pb->rawbuf[pagei]
-                                       + count * nlpp * stepsize + leftover1;
-                       pb->l_to_next_idx[fr][pb->lnum[fr]] = pagei + 1;
-                       pb->l_to_next_size[fr][pb->lnum[fr]] = count - lov0;
-                       tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
-                               virt_to_bus(pb->rawbuf[pb->l_fr_addr_idx[fr]
-                                               + pb->lnum[fr]]), jump);
-                       if(++pb->lnum[fr] > MAX_LNUM)
-                               pb->lnum[fr]--;
-                   }
-                   leftover1 = count * stepsize - lov0;
-                   i += stepsize;
-               }
-           }
-           pagei++;
-       } while(i < nlines);
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
-       c1 = jump_addr;
-#endif /* PLANB_GSCANLINE */
-
-       /* For non-interlaced, we use even fields only */
-       if (!interlace)
-               goto cmd_tab_data_end;
-
-       /* Sync to odd field */
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-               PLANB_SET(ODD_FIELD));
-       tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
-               PLANB_SET(DMA_ABORT));
-
-       /* odd field data: */
-       jump_addr = c1 + TAB_FACTOR * nlines / 2;
-       jump = virt_to_bus(jump_addr);
-#ifdef PLANB_GSCANLINE
-       for (i = 1; i < nlines; i += stepsize) {
-               tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
-                                       virt_to_bus(pb->rawbuf[pagei
-                                       + i * scanline / PAGE_SIZE]), jump);
-       }
-#else
-       i = 1;
-       leftover1 = 0;
-       pagei = pb->gbuf_idx[fr];
-       if(nlines <= 1)
-           goto skip;
-       do {
-           int j;
-
-           base = virt_to_bus(pb->rawbuf[pagei]);
-           nlpp = (PAGE_SIZE - leftover1) / count / stepsize;
-           if(leftover1 >= count) {
-               tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
-                                               base + leftover1 - count, jump);
-               i += stepsize;
-           }
-           for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++)
-               tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
-                       base + count * (j * stepsize + 1) + leftover1, jump);
-           if(i < nlines) {
-               int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
-
-               if(lov0 == 0)
-                   leftover1 = 0;
-               else {
-                   if(lov0 > count) {
-                       pb->l_to_addr[fr][pb->lnum[fr]] = pb->rawbuf[pagei]
-                               + count * (nlpp * stepsize + 1) + leftover1;
-                       pb->l_to_next_idx[fr][pb->lnum[fr]] = pagei + 1;
-                       pb->l_to_next_size[fr][pb->lnum[fr]] = count * stepsize
-                                                                       - lov0;
-                       tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
-                               virt_to_bus(pb->rawbuf[pb->l_fr_addr_idx[fr]
-                                                       + pb->lnum[fr]]), jump);
-                       if(++pb->lnum[fr] > MAX_LNUM)
-                               pb->lnum[fr]--;
-                       i += stepsize;
-                   }
-                   leftover1 = count * stepsize - lov0;
-               }
-           }
-           pagei++;
-       } while(i < nlines);
-skip:
-       tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
-       c1 = jump_addr;
-#endif /* PLANB_GSCANLINE */
-
-cmd_tab_data_end:
-       tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->intr_stat),
-                       (fr << 9) | PLANB_FRM_IRQ | PLANB_GEN_IRQ);
-       /* stop it */
-       tab_cmd_dbdma(c1, DBDMA_STOP, 0);
-
-       eieio();
-       return c1;
-}
-
-static irqreturn_t planb_irq(int irq, void *dev_id)
-{
-       unsigned int stat, astat;
-       struct planb *pb = (struct planb *)dev_id;
-
-       IDEBUG("PlanB: planb_irq()\n");
-
-       /* get/clear interrupt status bits */
-       eieio();
-       stat = in_le32(&pb->planb_base->intr_stat);
-       astat = stat & pb->intr_mask;
-       out_le32(&pb->planb_base->intr_stat, PLANB_FRM_IRQ
-                                       & ~astat & stat & ~PLANB_GEN_IRQ);
-       IDEBUG("PlanB: stat = %X, astat = %X\n", stat, astat);
-
-       if(astat & PLANB_FRM_IRQ) {
-               unsigned int fr = stat >> 9;
-#ifndef PLANB_GSCANLINE
-               int i;
-#endif
-               IDEBUG("PlanB: PLANB_FRM_IRQ\n");
-
-               pb->gcount++;
-
-               IDEBUG("PlanB: grab %d: fr = %d, gcount = %d\n",
-                               pb->grabbing, fr, pb->gcount);
-#ifndef PLANB_GSCANLINE
-               IDEBUG("PlanB: %d * %d bytes are being copied over\n",
-                               pb->lnum[fr], pb->lsize[fr]);
-               for(i = 0; i < pb->lnum[fr]; i++) {
-                       int first = pb->lsize[fr] - pb->l_to_next_size[fr][i];
-
-                       memcpy(pb->l_to_addr[fr][i],
-                               pb->rawbuf[pb->l_fr_addr_idx[fr] + i],
-                               first);
-                       memcpy(pb->rawbuf[pb->l_to_next_idx[fr][i]],
-                               pb->rawbuf[pb->l_fr_addr_idx[fr] + i] + first,
-                                               pb->l_to_next_size[fr][i]);
-               }
-#endif
-               pb->frame_stat[fr] = GBUFFER_DONE;
-               pb->grabbing--;
-               wake_up_interruptible(&pb->capq);
-               return IRQ_HANDLED;
-       }
-       /* incorrect interrupts? */
-       pb->intr_mask = PLANB_CLR_IRQ;
-       out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
-       printk(KERN_ERR "PlanB: IRQ lockup, cleared intrrupts"
-                                                       " unconditionally\n");
-       return IRQ_HANDLED;
-}
-
-/*******************************
- * Device Operations functions *
- *******************************/
-
-static int planb_open(struct video_device *dev, int mode)
-{
-       struct planb *pb = (struct planb *)dev;
-
-       if (pb->user == 0) {
-               int err;
-               if((err = planb_prepare_open(pb)) != 0)
-                       return err;
-       }
-       pb->user++;
-
-       DEBUG("PlanB: device opened\n");
-       return 0;
-}
-
-static void planb_close(struct video_device *dev)
-{
-       struct planb *pb = (struct planb *)dev;
-
-       if(pb->user < 1) /* ??? */
-               return;
-       planb_lock(pb);
-       if (pb->user == 1) {
-               if (pb->overlay) {
-                       planb_dbdma_stop(&pb->planb_base->ch2);
-                       planb_dbdma_stop(&pb->planb_base->ch1);
-                       pb->overlay = 0;
-               }
-               planb_prepare_close(pb);
-       }
-       pb->user--;
-       planb_unlock(pb);
-
-       DEBUG("PlanB: device closed\n");
-}
-
-static long planb_read(struct video_device *v, char *buf, unsigned long count,
-                               int nonblock)
-{
-       DEBUG("planb: read request\n");
-       return -EINVAL;
-}
-
-static long planb_write(struct video_device *v, const char *buf,
-                               unsigned long count, int nonblock)
-{
-       DEBUG("planb: write request\n");
-       return -EINVAL;
-}
-
-static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
-{
-       struct planb *pb=(struct planb *)dev;
-
-       switch (cmd)
-       {
-               case VIDIOCGCAP:
-               {
-                       struct video_capability b;
-
-                       DEBUG("PlanB: IOCTL VIDIOCGCAP\n");
-
-                       strcpy (b.name, pb->video_dev.name);
-                       b.type = VID_TYPE_OVERLAY | VID_TYPE_CLIPPING |
-                                VID_TYPE_FRAMERAM | VID_TYPE_SCALES |
-                                VID_TYPE_CAPTURE;
-                       b.channels = 2; /* composite & svhs */
-                       b.audios = 0;
-                       b.maxwidth = PLANB_MAXPIXELS;
-                       b.maxheight = PLANB_MAXLINES;
-                       b.minwidth = 32; /* wild guess */
-                       b.minheight = 32;
-                       if (copy_to_user(arg,&b,sizeof(b)))
-                               return -EFAULT;
-                       return 0;
-               }
-               case VIDIOCSFBUF:
-               {
-                       struct video_buffer v;
-                       unsigned short bpp;
-                       unsigned int fmt;
-
-                       DEBUG("PlanB: IOCTL VIDIOCSFBUF\n");
-
-                       if (!capable(CAP_SYS_ADMIN)
-                       || !capable(CAP_SYS_RAWIO))
-                               return -EPERM;
-                       if (copy_from_user(&v, arg,sizeof(v)))
-                               return -EFAULT;
-                       planb_lock(pb);
-                       switch(v.depth) {
-                       case 8:
-                               bpp = 1;
-                               fmt = PLANB_GRAY;
-                               break;
-                       case 15:
-                       case 16:
-                               bpp = 2;
-                               fmt = PLANB_COLOUR15;
-                               break;
-                       case 24:
-                       case 32:
-                               bpp = 4;
-                               fmt = PLANB_COLOUR32;
-                               break;
-                       default:
-                               planb_unlock(pb);
-                               return -EINVAL;
-                       }
-                       if (bpp * v.width > v.bytesperline) {
-                               planb_unlock(pb);
-                               return -EINVAL;
-                       }
-                       pb->win.bpp = bpp;
-                       pb->win.color_fmt = fmt;
-                       pb->frame_buffer_phys = (unsigned long) v.base;
-                       pb->win.sheight = v.height;
-                       pb->win.swidth = v.width;
-                       pb->picture.depth = pb->win.depth = v.depth;
-                       pb->win.bpl = pb->win.bpp * pb->win.swidth;
-                       pb->win.pad = v.bytesperline - pb->win.bpl;
-
-                       DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d,"
-                               " bpl %d (+ %d)\n", v.base, v.width,v.height,
-                               pb->win.bpp, pb->win.bpl, pb->win.pad);
-
-                       pb->cmd_buff_inited = 0;
-                       if(pb->overlay) {
-                               suspend_overlay(pb);
-                               fill_cmd_buff(pb);
-                               resume_overlay(pb);
-                       }
-                       planb_unlock(pb);
-                       return 0;
-               }
-               case VIDIOCGFBUF:
-               {
-                       struct video_buffer v;
-
-                       DEBUG("PlanB: IOCTL VIDIOCGFBUF\n");
-
-                       v.base = (void *)pb->frame_buffer_phys;
-                       v.height = pb->win.sheight;
-                       v.width = pb->win.swidth;
-                       v.depth = pb->win.depth;
-                       v.bytesperline = pb->win.bpl + pb->win.pad;
-                       if (copy_to_user(arg, &v, sizeof(v)))
-                               return -EFAULT;
-                       return 0;
-               }
-               case VIDIOCCAPTURE:
-               {
-                       int i;
-
-                       if(copy_from_user(&i, arg, sizeof(i)))
-                               return -EFAULT;
-                       if(i==0) {
-                               DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");
-
-                               if (!(pb->overlay))
-                                       return 0;
-                               planb_lock(pb);
-                               pb->overlay = 0;
-                               overlay_stop(pb);
-                               planb_unlock(pb);
-                       } else {
-                               DEBUG("PlanB: IOCTL VIDIOCCAPTURE Start\n");
-
-                               if (pb->frame_buffer_phys == 0 ||
-                                         pb->win.width == 0 ||
-                                         pb->win.height == 0)
-                                       return -EINVAL;
-                               if (pb->overlay)
-                                       return 0;
-                               planb_lock(pb);
-                               pb->overlay = 1;
-                               if(!(pb->cmd_buff_inited))
-                                       fill_cmd_buff(pb);
-                               overlay_start(pb);
-                               planb_unlock(pb);
-                       }
-                       return 0;
-               }
-               case VIDIOCGCHAN:
-               {
-                       struct video_channel v;
-
-                       DEBUG("PlanB: IOCTL VIDIOCGCHAN\n");
-
-                       if(copy_from_user(&v, arg,sizeof(v)))
-                               return -EFAULT;
-                       v.flags = 0;
-                       v.tuners = 0;
-                       v.type = VIDEO_TYPE_CAMERA;
-                       v.norm = pb->win.norm;
-                       switch(v.channel)
-                       {
-                       case 0:
-                               strcpy(v.name,"Composite");
-                               break;
-                       case 1:
-                               strcpy(v.name,"SVHS");
-                               break;
-                       default:
-                               return -EINVAL;
-                               break;
-                       }
-                       if(copy_to_user(arg,&v,sizeof(v)))
-                               return -EFAULT;
-
-                       return 0;
-               }
-               case VIDIOCSCHAN:
-               {
-                       struct video_channel v;
-
-                       DEBUG("PlanB: IOCTL VIDIOCSCHAN\n");
-
-                       if(copy_from_user(&v, arg, sizeof(v)))
-                               return -EFAULT;
-
-                       if (v.norm != pb->win.norm) {
-                               int i, maxlines;
-
-                               switch (v.norm)
-                               {
-                               case VIDEO_MODE_PAL:
-                               case VIDEO_MODE_SECAM:
-                                       maxlines = PLANB_MAXLINES;
-                                       break;
-                               case VIDEO_MODE_NTSC:
-                                       maxlines = PLANB_NTSC_MAXLINES;
-                                       break;
-                               default:
-                                       return -EINVAL;
-                                       break;
-                               }
-                               planb_lock(pb);
-                               /* empty the grabbing queue */
-                               wait_event(pb->capq, !pb->grabbing);
-                               pb->maxlines = maxlines;
-                               pb->win.norm = v.norm;
-                               /* Stop overlay if running */
-                               suspend_overlay(pb);
-                               for(i = 0; i < MAX_GBUFFERS; i++)
-                                       pb->gnorm_switch[i] = 1;
-                               /* I know it's an overkill, but.... */
-                               fill_cmd_buff(pb);
-                               /* ok, now init it accordingly */
-                               saa_init_regs (pb);
-                               /* restart overlay if it was running */
-                               resume_overlay(pb);
-                               planb_unlock(pb);
-                       }
-
-                       switch(v.channel)
-                       {
-                       case 0: /* Composite    */
-                               saa_set (SAA7196_IOCC,
-                                       ((saa_regs[pb->win.norm][SAA7196_IOCC] &
-                                         ~7) | 3), pb);
-                               break;
-                       case 1: /* SVHS         */
-                               saa_set (SAA7196_IOCC,
-                                       ((saa_regs[pb->win.norm][SAA7196_IOCC] &
-                                         ~7) | 4), pb);
-                               break;
-                       default:
-                               return -EINVAL;
-                               break;
-                       }
-
-                       return 0;
-               }
-               case VIDIOCGPICT:
-               {
-                       struct video_picture vp = pb->picture;
-
-                       DEBUG("PlanB: IOCTL VIDIOCGPICT\n");
-
-                       switch(pb->win.color_fmt) {
-                       case PLANB_GRAY:
-                               vp.palette = VIDEO_PALETTE_GREY;
-                       case PLANB_COLOUR15:
-                               vp.palette = VIDEO_PALETTE_RGB555;
-                               break;
-                       case PLANB_COLOUR32:
-                               vp.palette = VIDEO_PALETTE_RGB32;
-                               break;
-                       default:
-                               vp.palette = 0;
-                               break;
-                       }
-
-                       if(copy_to_user(arg,&vp,sizeof(vp)))
-                               return -EFAULT;
-                       return 0;
-               }
-               case VIDIOCSPICT:
-               {
-                       struct video_picture vp;
-
-                       DEBUG("PlanB: IOCTL VIDIOCSPICT\n");
-
-                       if(copy_from_user(&vp,arg,sizeof(vp)))
-                               return -EFAULT;
-                       pb->picture = vp;
-                       /* Should we do sanity checks here? */
-                       saa_set (SAA7196_BRIG, (unsigned char)
-                           ((pb->picture.brightness) >> 8), pb);
-                       saa_set (SAA7196_HUEC, (unsigned char)
-                           ((pb->picture.hue) >> 8) ^ 0x80, pb);
-                       saa_set (SAA7196_CSAT, (unsigned char)
-                           ((pb->picture.colour) >> 9), pb);
-                       saa_set (SAA7196_CONT, (unsigned char)
-                           ((pb->picture.contrast) >> 9), pb);
-
-                       return 0;
-               }
-               case VIDIOCSWIN:
-               {
-                       struct video_window     vw;
-                       struct video_clip       clip;
-                       int                     i;
-
-                       DEBUG("PlanB: IOCTL VIDIOCSWIN\n");
-
-                       if(copy_from_user(&vw,arg,sizeof(vw)))
-                               return -EFAULT;
-
-                       planb_lock(pb);
-                       /* Stop overlay if running */
-                       suspend_overlay(pb);
-                       pb->win.interlace = (vw.height > pb->maxlines/2)? 1: 0;
-                       if (pb->win.x != vw.x ||
-                           pb->win.y != vw.y ||
-                           pb->win.width != vw.width ||
-                           pb->win.height != vw.height ||
-                           !pb->cmd_buff_inited) {
-                               pb->win.x = vw.x;
-                               pb->win.y = vw.y;
-                               pb->win.width = vw.width;
-                               pb->win.height = vw.height;
-                               fill_cmd_buff(pb);
-                       }
-                       /* Reset clip mask */
-                       memset ((void *) pb->mask, 0xff, (pb->maxlines
-                                       * ((PLANB_MAXPIXELS + 7) & ~7)) / 8);
-                       /* Add any clip rects */
-                       for (i = 0; i < vw.clipcount; i++) {
-                               if (copy_from_user(&clip, vw.clips + i,
-                                               sizeof(struct video_clip)))
-                                       return -EFAULT;
-                               add_clip(pb, &clip);
-                       }
-                       /* restart overlay if it was running */
-                       resume_overlay(pb);
-                       planb_unlock(pb);
-                       return 0;
-               }
-               case VIDIOCGWIN:
-               {
-                       struct video_window vw;
-
-                       DEBUG("PlanB: IOCTL VIDIOCGWIN\n");
-
-                       vw.x=pb->win.x;
-                       vw.y=pb->win.y;
-                       vw.width=pb->win.width;
-                       vw.height=pb->win.height;
-                       vw.chromakey=0;
-                       vw.flags=0;
-                       if(pb->win.interlace)
-                               vw.flags|=VIDEO_WINDOW_INTERLACE;
-                       if(copy_to_user(arg,&vw,sizeof(vw)))
-                               return -EFAULT;
-                       return 0;
-               }
-               case VIDIOCSYNC: {
-                       int i;
-
-                       IDEBUG("PlanB: IOCTL VIDIOCSYNC\n");
-
-                       if(copy_from_user((void *)&i,arg,sizeof(int)))
-                               return -EFAULT;
-
-                       IDEBUG("PlanB: sync to frame %d\n", i);
-
-                       if(i > (MAX_GBUFFERS - 1) || i < 0)
-                               return -EINVAL;
-chk_grab:
-                       switch (pb->frame_stat[i]) {
-                       case GBUFFER_UNUSED:
-                               return -EINVAL;
-                       case GBUFFER_GRABBING:
-                               IDEBUG("PlanB: waiting for grab"
-                                                       " done (%d)\n", i);
-                               interruptible_sleep_on(&pb->capq);
-                               if(signal_pending(current))
-                                       return -EINTR;
-                               goto chk_grab;
-                       case GBUFFER_DONE:
-                               pb->frame_stat[i] = GBUFFER_UNUSED;
-                               break;
-                       }
-                       return 0;
-               }
-
-               case VIDIOCMCAPTURE:
-               {
-                       struct video_mmap vm;
-                       volatile unsigned int status;
-
-                       IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n");
-
-                       if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm)))
-                               return -EFAULT;
-                       status = pb->frame_stat[vm.frame];
-                       if (status != GBUFFER_UNUSED)
-                               return -EBUSY;
-
-                       return vgrab(pb, &vm);
-               }
-
-               case VIDIOCGMBUF:
-               {
-                       int i;
-                       struct video_mbuf vm;
-
-                       DEBUG("PlanB: IOCTL VIDIOCGMBUF\n");
-
-                       memset(&vm, 0 , sizeof(vm));
-                       vm.size = PLANB_MAX_FBUF * MAX_GBUFFERS;
-                       vm.frames = MAX_GBUFFERS;
-                       for(i = 0; i<MAX_GBUFFERS; i++)
-                               vm.offsets[i] = PLANB_MAX_FBUF * i;
-                       if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
-                               return -EFAULT;
-                       return 0;
-               }
-
-               case PLANBIOCGSAAREGS:
-               {
-                       struct planb_saa_regs preg;
-
-                       DEBUG("PlanB: IOCTL PLANBIOCGSAAREGS\n");
-
-                       if(copy_from_user(&preg, arg, sizeof(preg)))
-                               return -EFAULT;
-                       if(preg.addr >= SAA7196_NUMREGS)
-                               return -EINVAL;
-                       preg.val = saa_regs[pb->win.norm][preg.addr];
-                       if(copy_to_user((void *)arg, (void *)&preg,
-                                                               sizeof(preg)))
-                               return -EFAULT;
-                       return 0;
-               }
-
-               case PLANBIOCSSAAREGS:
-               {
-                       struct planb_saa_regs preg;
-
-                       DEBUG("PlanB: IOCTL PLANBIOCSSAAREGS\n");
-
-                       if(copy_from_user(&preg, arg, sizeof(preg)))
-                               return -EFAULT;
-                       if(preg.addr >= SAA7196_NUMREGS)
-                               return -EINVAL;
-                       saa_set (preg.addr, preg.val, pb);
-                       return 0;
-               }
-
-               case PLANBIOCGSTAT:
-               {
-                       struct planb_stat_regs pstat;
-
-                       DEBUG("PlanB: IOCTL PLANBIOCGSTAT\n");
-
-                       pstat.ch1_stat = in_le32(&pb->planb_base->ch1.status);
-                       pstat.ch2_stat = in_le32(&pb->planb_base->ch2.status);
-                       pstat.saa_stat0 = saa_status(0, pb);
-                       pstat.saa_stat1 = saa_status(1, pb);
-
-                       if(copy_to_user((void *)arg, (void *)&pstat,
-                                                       sizeof(pstat)))
-                               return -EFAULT;
-                       return 0;
-               }
-
-               case PLANBIOCSMODE: {
-                       int v;
-
-                       DEBUG("PlanB: IOCTL PLANBIOCSMODE\n");
-
-                       if(copy_from_user(&v, arg, sizeof(v)))
-                               return -EFAULT;
-
-                       switch(v)
-                       {
-                       case PLANB_TV_MODE:
-                               saa_set (SAA7196_STDC,
-                                       (saa_regs[pb->win.norm][SAA7196_STDC] &
-                                         0x7f), pb);
-                               break;
-                       case PLANB_VTR_MODE:
-                               saa_set (SAA7196_STDC,
-                                       (saa_regs[pb->win.norm][SAA7196_STDC] |
-                                         0x80), pb);
-                               break;
-                       default:
-                               return -EINVAL;
-                               break;
-                       }
-                       pb->win.mode = v;
-                       return 0;
-               }
-               case PLANBIOCGMODE: {
-                       int v=pb->win.mode;
-
-                       DEBUG("PlanB: IOCTL PLANBIOCGMODE\n");
-
-                       if(copy_to_user(arg,&v,sizeof(v)))
-                               return -EFAULT;
-                       return 0;
-               }
-#ifdef PLANB_GSCANLINE
-               case PLANBG_GRAB_BPL: {
-                       int v=pb->gbytes_per_line;
-
-                       DEBUG("PlanB: IOCTL PLANBG_GRAB_BPL\n");
-
-                       if(copy_to_user(arg,&v,sizeof(v)))
-                               return -EFAULT;
-                       return 0;
-               }
-#endif /* PLANB_GSCANLINE */
-               case PLANB_INTR_DEBUG: {
-                       int i;
-
-                       DEBUG("PlanB: IOCTL PLANB_INTR_DEBUG\n");
-
-                       if(copy_from_user(&i, arg, sizeof(i)))
-                               return -EFAULT;
-
-                       /* avoid hang ups all together */
-                       for (i = 0; i < MAX_GBUFFERS; i++) {
-                               if(pb->frame_stat[i] == GBUFFER_GRABBING) {
-                                       pb->frame_stat[i] = GBUFFER_DONE;
-                               }
-                       }
-                       if(pb->grabbing)
-                               pb->grabbing--;
-                       wake_up_interruptible(&pb->capq);
-                       return 0;
-               }
-               case PLANB_INV_REGS: {
-                       int i;
-                       struct planb_any_regs any;
-
-                       DEBUG("PlanB: IOCTL PLANB_INV_REGS\n");
-
-                       if(copy_from_user(&any, arg, sizeof(any)))
-                               return -EFAULT;
-                       if(any.offset < 0 || any.offset + any.bytes > 0x400)
-                               return -EINVAL;
-                       if(any.bytes > 128)
-                               return -EINVAL;
-                       for (i = 0; i < any.bytes; i++) {
-                               any.data[i] =
-                                       in_8((unsigned char *)pb->planb_base
-                                                       + any.offset + i);
-                       }
-                       if(copy_to_user(arg,&any,sizeof(any)))
-                               return -EFAULT;
-                       return 0;
-               }
-               default:
-               {
-                       DEBUG("PlanB: Unimplemented IOCTL\n");
-                       return -ENOIOCTLCMD;
-               }
-       /* Some IOCTLs are currently unsupported on PlanB */
-               case VIDIOCGTUNER: {
-               DEBUG("PlanB: IOCTL VIDIOCGTUNER\n");
-                       goto unimplemented; }
-               case VIDIOCSTUNER: {
-               DEBUG("PlanB: IOCTL VIDIOCSTUNER\n");
-                       goto unimplemented; }
-               case VIDIOCSFREQ: {
-               DEBUG("PlanB: IOCTL VIDIOCSFREQ\n");
-                       goto unimplemented; }
-               case VIDIOCGFREQ: {
-               DEBUG("PlanB: IOCTL VIDIOCGFREQ\n");
-                       goto unimplemented; }
-               case VIDIOCKEY: {
-               DEBUG("PlanB: IOCTL VIDIOCKEY\n");
-                       goto unimplemented; }
-               case VIDIOCSAUDIO: {
-               DEBUG("PlanB: IOCTL VIDIOCSAUDIO\n");
-                       goto unimplemented; }
-               case VIDIOCGAUDIO: {
-               DEBUG("PlanB: IOCTL VIDIOCGAUDIO\n");
-                       goto unimplemented; }
-unimplemented:
-               DEBUG("       Unimplemented\n");
-                       return -ENOIOCTLCMD;
-       }
-       return 0;
-}
-
-static int planb_mmap(struct vm_area_struct *vma, struct video_device *dev, const char *adr, unsigned long size)
-{
-       int i;
-       struct planb *pb = (struct planb *)dev;
-       unsigned long start = (unsigned long)adr;
-
-       if (size > MAX_GBUFFERS * PLANB_MAX_FBUF)
-               return -EINVAL;
-       if (!pb->rawbuf) {
-               int err;
-               if((err=grabbuf_alloc(pb)))
-                       return err;
-       }
-       for (i = 0; i < pb->rawbuf_size; i++) {
-               unsigned long pfn;
-
-               pfn = virt_to_phys((void *)pb->rawbuf[i]) >> PAGE_SHIFT;
-               if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED))
-                       return -EAGAIN;
-               start += PAGE_SIZE;
-               if (size <= PAGE_SIZE)
-                       break;
-               size -= PAGE_SIZE;
-       }
-       return 0;
-}
-
-static struct video_device planb_template=
-{
-       .owner          = THIS_MODULE,
-       .name           = PLANB_DEVICE_NAME,
-       .type           = VID_TYPE_OVERLAY,
-       .open           = planb_open,
-       .close          = planb_close,
-       .read           = planb_read,
-       .write          = planb_write,
-       .ioctl          = planb_ioctl,
-       .mmap           = planb_mmap,   /* mmap? */
-};
-
-static int init_planb(struct planb *pb)
-{
-       unsigned char saa_rev;
-       int i, result;
-
-       memset ((void *) &pb->win, 0, sizeof (struct planb_window));
-       /* Simple sanity check */
-       if(def_norm >= NUM_SUPPORTED_NORM || def_norm < 0) {
-               printk(KERN_ERR "PlanB: Option(s) invalid\n");
-               return -2;
-       }
-       pb->win.norm = def_norm;
-       pb->win.mode = PLANB_TV_MODE;   /* TV mode */
-       pb->win.interlace=1;
-       pb->win.x=0;
-       pb->win.y=0;
-       pb->win.width=768; /* 640 */
-       pb->win.height=576; /* 480 */
-       pb->maxlines=576;
-#if 0
-       btv->win.cropwidth=768; /* 640 */
-       btv->win.cropheight=576; /* 480 */
-       btv->win.cropx=0;
-       btv->win.cropy=0;
-#endif
-       pb->win.pad=0;
-       pb->win.bpp=4;
-       pb->win.depth=32;
-       pb->win.color_fmt=PLANB_COLOUR32;
-       pb->win.bpl=1024*pb->win.bpp;
-       pb->win.swidth=1024;
-       pb->win.sheight=768;
-#ifdef PLANB_GSCANLINE
-       if((pb->gbytes_per_line = PLANB_MAXPIXELS * 4) > PAGE_SIZE
-                               || (pb->gbytes_per_line <= 0))
-               return -3;
-       else {
-               /* page align pb->gbytes_per_line for DMA purpose */
-               for(i = PAGE_SIZE; pb->gbytes_per_line < (i>>1);)
-                       i>>=1;
-               pb->gbytes_per_line = i;
-       }
-#endif
-       pb->tab_size = PLANB_MAXLINES + 40;
-       pb->suspend = 0;
-       mutex_init(&pb->lock);
-       pb->ch1_cmd = 0;
-       pb->ch2_cmd = 0;
-       pb->mask = 0;
-       pb->priv_space = 0;
-       pb->offset = 0;
-       pb->user = 0;
-       pb->overlay = 0;
-       init_waitqueue_head(&pb->suspendq);
-       pb->cmd_buff_inited = 0;
-       pb->frame_buffer_phys = 0;
-
-       /* Reset DMA controllers */
-       planb_dbdma_stop(&pb->planb_base->ch2);
-       planb_dbdma_stop(&pb->planb_base->ch1);
-
-       saa_rev =  (saa_status(0, pb) & 0xf0) >> 4;
-       printk(KERN_INFO "PlanB: SAA7196 video processor rev. %d\n", saa_rev);
-       /* Initialize the SAA registers in memory and on chip */
-       saa_init_regs (pb);
-
-       /* clear interrupt mask */
-       pb->intr_mask = PLANB_CLR_IRQ;
-
-       result = request_irq(pb->irq, planb_irq, 0, "PlanB", pb);
-       if (result < 0) {
-               if (result==-EINVAL)
-                       printk(KERN_ERR "PlanB: Bad irq number (%d) "
-                                               "or handler\n", (int)pb->irq);
-               else if (result==-EBUSY)
-                       printk(KERN_ERR "PlanB: I don't know why, "
-                                       "but IRQ %d is busy\n", (int)pb->irq);
-               return result;
-       }
-       disable_irq(pb->irq);
-
-       /* Now add the template and register the device unit. */
-       memcpy(&pb->video_dev,&planb_template,sizeof(planb_template));
-
-       pb->picture.brightness=0x90<<8;
-       pb->picture.contrast = 0x70 << 8;
-       pb->picture.colour = 0x70<<8;
-       pb->picture.hue = 0x8000;
-       pb->picture.whiteness = 0;
-       pb->picture.depth = pb->win.depth;
-
-       pb->frame_stat=NULL;
-       init_waitqueue_head(&pb->capq);
-       for(i=0; i<MAX_GBUFFERS; i++) {
-               pb->gbuf_idx[i] = PLANB_MAX_FBUF * i / PAGE_SIZE;
-               pb->gwidth[i]=0;
-               pb->gheight[i]=0;
-               pb->gfmt[i]=0;
-               pb->cap_cmd[i]=NULL;
-#ifndef PLANB_GSCANLINE
-               pb->l_fr_addr_idx[i] = MAX_GBUFFERS * (PLANB_MAX_FBUF
-                                               / PAGE_SIZE + 1) + MAX_LNUM * i;
-               pb->lsize[i] = 0;
-               pb->lnum[i] = 0;
-#endif
-       }
-       pb->rawbuf=NULL;
-       pb->grabbing=0;
-
-       /* enable interrupts */
-       out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
-       pb->intr_mask = PLANB_FRM_IRQ;
-       enable_irq(pb->irq);
-
-       if(video_register_device(&pb->video_dev, VFL_TYPE_GRABBER, video_nr)<0)
-               return -1;
-
-       return 0;
-}
-
-/*
- *     Scan for a PlanB controller, request the irq and map the io memory
- */
-
-static int find_planb(void)
-{
-       struct planb            *pb;
-       struct device_node      *planb_devices;
-       unsigned char           dev_fn, confreg, bus;
-       unsigned int            old_base, new_base;
-       unsigned int            irq;
-       struct pci_dev          *pdev;
-       int rc;
-
-       if (!machine_is(powermac))
-               return 0;
-
-       planb_devices = of_find_node_by_name(NULL, "planb");
-       if (planb_devices == 0) {
-               planb_num=0;
-               printk(KERN_WARNING "PlanB: no device found!\n");
-               return planb_num;
-       }
-
-       if (planb_devices->next != NULL)
-               printk(KERN_ERR "Warning: only using first PlanB device!\n");
-       pb = &planbs[0];
-       planb_num = 1;
-
-       if (planb_devices->n_addrs != 1) {
-               printk (KERN_WARNING "PlanB: expecting 1 address for planb "
-                       "(got %d)", planb_devices->n_addrs);
-               of_node_put(planb_devices);
-               return 0;
-       }
-
-       if (planb_devices->n_intrs == 0) {
-               printk(KERN_WARNING "PlanB: no intrs for device %s\n",
-                      planb_devices->full_name);
-               of_node_put(planb_devices);
-               return 0;
-       } else {
-               irq = planb_devices->intrs[0].line;
-       }
-
-       /* Initialize PlanB's PCI registers */
-
-       /* There is a bug with the way OF assigns addresses
-          to the devices behind the chaos bridge.
-          control needs only 0x1000 of space, but decodes only
-          the upper 16 bits. It therefore occupies a full 64K.
-          OF assigns the planb controller memory within this space;
-          so we need to change that here in order to access planb. */
-
-       /* We remap to 0xf1000000 in hope that nobody uses it ! */
-
-       bus = (planb_devices->addrs[0].space >> 16) & 0xff;
-       dev_fn = (planb_devices->addrs[0].space >> 8) & 0xff;
-       confreg = planb_devices->addrs[0].space & 0xff;
-       old_base = planb_devices->addrs[0].address;
-       new_base = 0xf1000000;
-       of_node_put(planb_devices);
-
-       DEBUG("PlanB: Found on bus %d, dev %d, func %d, "
-               "membase 0x%x (base reg. 0x%x)\n",
-               bus, PCI_SLOT(dev_fn), PCI_FUNC(dev_fn), old_base, confreg);
-
-       pdev = pci_get_bus_and_slot(bus, dev_fn);
-       if (!pdev) {
-               printk(KERN_ERR "planb: cannot find slot\n");
-               goto err_out;
-       }
-
-       /* Enable response in memory space, bus mastering,
-          use memory write and invalidate */
-       rc = pci_enable_device(pdev);
-       if (rc) {
-               printk(KERN_ERR "planb: cannot enable PCI device %s\n",
-                      pci_name(pdev));
-               goto err_out;
-       }
-       rc = pci_set_mwi(pdev);
-       if (rc) {
-               printk(KERN_ERR "planb: cannot enable MWI on PCI device %s\n",
-                      pci_name(pdev));
-               goto err_out_disable;
-       }
-       pci_set_master(pdev);
-
-       /* Set the new base address */
-       pci_write_config_dword (pdev, confreg, new_base);
-
-       planb_regs = (volatile struct planb_registers *)
-                                               ioremap (new_base, 0x400);
-       pb->planb_base = planb_regs;
-       pb->planb_base_phys = (struct planb_registers *)new_base;
-       pb->irq = irq;
-       pb->dev = pdev;
-
-       return planb_num;
-
-err_out_disable:
-       pci_disable_device(pdev);
-err_out:
-       /* FIXME handle error */   /* comment moved from pci_find_slot, above */
-       pci_dev_put(pdev);
-       return 0;
-}
-
-static void release_planb(void)
-{
-       int i;
-       struct planb *pb;
-
-       for (i=0;i<planb_num; i++)
-       {
-               pb=&planbs[i];
-
-               /* stop and flash DMAs unconditionally */
-               planb_dbdma_stop(&pb->planb_base->ch2);
-               planb_dbdma_stop(&pb->planb_base->ch1);
-
-               /* clear and free interrupts */
-               pb->intr_mask = PLANB_CLR_IRQ;
-               out_le32 (&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
-               free_irq(pb->irq, pb);
-
-               /* make sure all allocated memory are freed */
-               planb_prepare_close(pb);
-
-               printk(KERN_INFO "PlanB: unregistering with v4l\n");
-               video_unregister_device(&pb->video_dev);
-
-               pci_dev_put(pb->dev);
-
-               /* note that iounmap() does nothing on the PPC right now */
-               iounmap ((void *)pb->planb_base);
-       }
-}
-
-static int __init init_planbs(void)
-{
-       int i;
-
-       if (find_planb()<=0)
-               return -EIO;
-
-       for (i=0; i<planb_num; i++) {
-               if (init_planb(&planbs[i])<0) {
-                       printk(KERN_ERR "PlanB: error registering device %d"
-                                                       " with v4l\n", i);
-                       release_planb();
-                       return -EIO;
-               }
-               printk(KERN_INFO "PlanB: registered device %d with v4l\n", i);
-       }
-       return 0;
-}
-
-static void __exit exit_planbs(void)
-{
-       release_planb();
-}
-
-module_init(init_planbs);
-module_exit(exit_planbs);
index e21b5735c1032c7b122950eb7faf07c2cdafa909..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,232 +0,0 @@
-/*
-    planb - PlanB frame grabber driver
-
-    PlanB is used in the 7x00/8x00 series of PowerMacintosh
-    Computers as video input DMA controller.
-
-    Copyright (C) 1998 Michel Lanners (mlan@cpu.lu)
-
-    Based largely on the bttv driver by Ralph Metzler (rjkm@thp.uni-koeln.de)
-
-    Additional debugging and coding by Takashi Oe (toe@unlserve.unl.edu)
-
-
-    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.
-*/
-
-/* $Id: planb.h,v 1.13 1999/05/03 19:28:56 mlan Exp $ */
-
-#ifndef _PLANB_H_
-#define _PLANB_H_
-
-#ifdef __KERNEL__
-#include <asm/dbdma.h>
-#include "saa7196.h"
-#endif /* __KERNEL__ */
-
-#define PLANB_DEVICE_NAME      "Apple PlanB Video-In"
-#define PLANB_REV              "1.0"
-
-#ifdef __KERNEL__
-//#define PLANB_GSCANLINE      /* use this if apps have the notion of */
-                               /* grab buffer scanline */
-/* This should be safe for both PAL and NTSC */
-#define PLANB_MAXPIXELS 768
-#define PLANB_MAXLINES 576
-#define PLANB_NTSC_MAXLINES 480
-
-/* Uncomment your preferred norm ;-) */
-#define PLANB_DEF_NORM VIDEO_MODE_PAL
-//#define PLANB_DEF_NORM VIDEO_MODE_NTSC
-//#define PLANB_DEF_NORM VIDEO_MODE_SECAM
-
-/* fields settings */
-#define PLANB_GRAY     0x1     /*  8-bit mono? */
-#define PLANB_COLOUR15 0x2     /* 16-bit mode */
-#define PLANB_COLOUR32 0x4     /* 32-bit mode */
-#define PLANB_CLIPMASK 0x8     /* hardware clipmasking */
-
-/* misc. flags for PlanB DMA operation */
-#define        CH_SYNC         0x1     /* synchronize channels (set by ch1;
-                                  cleared by ch2) */
-#define FIELD_SYNC     0x2     /* used for the start of each field
-                                  (0 -> 1 -> 0 for ch1; 0 -> 1 for ch2) */
-#define EVEN_FIELD     0x0     /* even field is detected if unset */
-#define DMA_ABORT      0x2     /* error or just out of sync if set */
-#define ODD_FIELD      0x4     /* odd field is detected if set */
-
-/* for capture operations */
-#define MAX_GBUFFERS   2
-/* note PLANB_MAX_FBUF must be divisible by PAGE_SIZE */
-#ifdef PLANB_GSCANLINE
-#define PLANB_MAX_FBUF 0x240000        /* 576 * 1024 * 4 */
-#define TAB_FACTOR     (1)
-#else
-#define PLANB_MAX_FBUF 0x1b0000        /* 576 * 768 * 4 */
-#define TAB_FACTOR     (2)
-#endif
-#endif /* __KERNEL__ */
-
-struct planb_saa_regs {
-       unsigned char addr;
-       unsigned char val;
-};
-
-struct planb_stat_regs {
-       unsigned int ch1_stat;
-       unsigned int ch2_stat;
-       unsigned char saa_stat0;
-       unsigned char saa_stat1;
-};
-
-struct planb_any_regs {
-       unsigned int offset;
-       unsigned int bytes;
-       unsigned char data[128];
-};
-
-/* planb private ioctls */
-#define PLANBIOCGSAAREGS       _IOWR('v', BASE_VIDIOCPRIVATE, struct planb_saa_regs)   /* Read a saa7196 reg value */
-#define PLANBIOCSSAAREGS       _IOW('v', BASE_VIDIOCPRIVATE + 1, struct planb_saa_regs)        /* Set a saa7196 reg value */
-#define PLANBIOCGSTAT          _IOR('v', BASE_VIDIOCPRIVATE + 2, struct planb_stat_regs)       /* Read planb status */
-#define PLANB_TV_MODE          1
-#define PLANB_VTR_MODE         2
-#define PLANBIOCGMODE          _IOR('v', BASE_VIDIOCPRIVATE + 3, int)  /* Get TV/VTR mode */
-#define PLANBIOCSMODE          _IOW('v', BASE_VIDIOCPRIVATE + 4, int)  /* Set TV/VTR mode */
-
-#ifdef PLANB_GSCANLINE
-#define PLANBG_GRAB_BPL                _IOR('v', BASE_VIDIOCPRIVATE + 5, int)  /* # of bytes per scanline in grab buffer */
-#endif
-
-/* call wake_up_interruptible() with appropriate actions */
-#define PLANB_INTR_DEBUG       _IOW('v', BASE_VIDIOCPRIVATE + 20, int)
-/* investigate which reg does what */
-#define PLANB_INV_REGS         _IOWR('v', BASE_VIDIOCPRIVATE + 21, struct planb_any_regs)
-
-#ifdef __KERNEL__
-
-/* Potentially useful macros */
-#define PLANB_SET(x)   ((x) << 16 | (x))
-#define PLANB_CLR(x)   ((x) << 16)
-
-/* This represents the physical register layout */
-struct planb_registers {
-       volatile struct dbdma_regs      ch1;            /* 0x00: video in */
-       volatile unsigned int           even;           /* 0x40: even field setting */
-       volatile unsigned int           odd;            /* 0x44; odd field setting */
-       unsigned int                    pad1[14];       /* empty? */
-       volatile struct dbdma_regs      ch2;            /* 0x80: clipmask out */
-       unsigned int                    pad2[16];       /* 0xc0: empty? */
-       volatile unsigned int           reg3;           /* 0x100: ???? */
-       volatile unsigned int           intr_stat;      /* 0x104: irq status */
-#define PLANB_CLR_IRQ          0x00            /* clear Plan B interrupt */
-#define PLANB_GEN_IRQ          0x01            /* assert Plan B interrupt */
-#define PLANB_FRM_IRQ          0x0100          /* end of frame */
-       unsigned int                    pad3[1];        /* empty? */
-       volatile unsigned int           reg5;           /* 0x10c: ??? */
-       unsigned int                    pad4[60];       /* empty? */
-       volatile unsigned char          saa_addr;       /* 0x200: SAA subadr */
-       char                            pad5[3];
-       volatile unsigned char          saa_regval;     /* SAA7196 write reg. val */
-       char                            pad6[3];
-       volatile unsigned char          saa_status;     /* SAA7196 status byte */
-       /* There is more unused stuff here */
-};
-
-struct planb_window {
-       int     x, y;
-       ushort  width, height;
-       ushort  bpp, bpl, depth, pad;
-       ushort  swidth, sheight;
-       int     norm;
-       int     interlace;
-       u32     color_fmt;
-       int     chromakey;
-       int     mode;           /* used to switch between TV/VTR modes */
-};
-
-struct planb_suspend {
-       int overlay;
-       int frame;
-       struct dbdma_cmd cmd;
-};
-
-struct planb {
-       struct  video_device video_dev;
-       struct  video_picture picture;          /* Current picture params */
-       struct  video_audio audio_dev;          /* Current audio params */
-
-       volatile struct planb_registers *planb_base;    /* virt base of planb */
-       struct planb_registers *planb_base_phys;        /* phys base of planb */
-       void    *priv_space;                    /* Org. alloc. mem for kfree */
-       int     user;
-       unsigned int tab_size;
-       int     maxlines;
-       struct mutex lock;
-       unsigned int    irq;                    /* interrupt number */
-       volatile unsigned int intr_mask;
-       struct pci_dev *dev;                    /* Our PCI device */
-
-       int     overlay;                        /* overlay running? */
-       struct  planb_window win;
-       unsigned long frame_buffer_phys;        /* We need phys for DMA */
-       int     offset;                         /* offset of pixel 1 */
-       volatile struct dbdma_cmd *ch1_cmd;     /* Video In DMA cmd buffer */
-       volatile struct dbdma_cmd *ch2_cmd;     /* Clip Out DMA cmd buffer */
-       volatile struct dbdma_cmd *overlay_last1;
-       volatile struct dbdma_cmd *overlay_last2;
-       unsigned long ch1_cmd_phys;
-       volatile unsigned char *mask;           /* Clipmask buffer */
-       int suspend;
-       wait_queue_head_t suspendq;
-       struct planb_suspend suspended;
-       int     cmd_buff_inited;                /* cmd buffer inited? */
-
-       int grabbing;
-       unsigned int gcount;
-       wait_queue_head_t capq;
-       int last_fr;
-       int prev_last_fr;
-       unsigned char **rawbuf;
-       int rawbuf_size;
-       int gbuf_idx[MAX_GBUFFERS];
-       volatile struct dbdma_cmd *cap_cmd[MAX_GBUFFERS];
-       volatile struct dbdma_cmd *last_cmd[MAX_GBUFFERS];
-       volatile struct dbdma_cmd *pre_cmd[MAX_GBUFFERS];
-       int need_pre_capture[MAX_GBUFFERS];
-#define PLANB_DUMMY 40 /* # of command buf's allocated for pre-capture seq. */
-       int gwidth[MAX_GBUFFERS], gheight[MAX_GBUFFERS];
-       unsigned int gfmt[MAX_GBUFFERS];
-       int gnorm_switch[MAX_GBUFFERS];
-       volatile unsigned int *frame_stat;
-#define GBUFFER_UNUSED       0x00U
-#define GBUFFER_GRABBING     0x01U
-#define GBUFFER_DONE         0x02U
-#ifdef PLANB_GSCANLINE
-       int gbytes_per_line;
-#else
-#define MAX_LNUM 431   /* change this if PLANB_MAXLINES or */
-                       /* PLANB_MAXPIXELS changes */
-       int l_fr_addr_idx[MAX_GBUFFERS];
-       unsigned char *l_to_addr[MAX_GBUFFERS][MAX_LNUM];
-       int l_to_next_idx[MAX_GBUFFERS][MAX_LNUM];
-       int l_to_next_size[MAX_GBUFFERS][MAX_LNUM];
-       int lsize[MAX_GBUFFERS], lnum[MAX_GBUFFERS];
-#endif
-};
-
-#endif /* __KERNEL__ */
-
-#endif /* _PLANB_H_ */
index 51b1461d8fb62707f48482a59ee34cef55d85a50..00425d7436569e8081e525892fbf8b7f464b1683 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/io.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
@@ -894,9 +895,7 @@ static const struct file_operations pms_fops = {
 
 static struct video_device pms_template=
 {
-       .owner          = THIS_MODULE,
        .name           = "Mediavision PMS",
-       .type           = VID_TYPE_CAPTURE,
        .fops           = &pms_fops,
 };
 
index 4482b2c72cedb3c8a1cbe3a212b7317186615ef3..19eb274c9cd09d2f361154ed764d152472df709f 100644 (file)
@@ -2,8 +2,6 @@ config VIDEO_PVRUSB2
        tristate "Hauppauge WinTV-PVR USB2 support"
        depends on VIDEO_V4L2 && I2C
        depends on VIDEO_MEDIA  # Avoids pvrusb = Y / DVB = M
-       depends on HOTPLUG      # due to FW_LOADER
-       select FW_LOADER
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_CX2341X
index 61801291c2afea954062ca55ce9d18f012b7616f..d657e53bbfa3770448ff8eb0426c6f8bd5be9fc6 100644 (file)
@@ -16,8 +16,8 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
-#ifndef __PVRUSB2_BASE_H
-#define __PVRUSB2_BASE_H
+#ifndef __PVRUSB2_CONTEXT_H
+#define __PVRUSB2_CONTEXT_H
 
 #include <linux/mutex.h>
 #include <linux/usb.h>
index 5d036e7e3f07707eeecd20b089021ef51d4051e2..88e175168438d52ab0ffa113d5b47d561d19d68b 100644 (file)
@@ -97,13 +97,13 @@ static const struct pvr2_device_desc pvr2_device_24xxx = {
                .flag_has_cx25840 = !0,
                .flag_has_wm8775 = !0,
                .flag_has_hauppauge_rom = !0,
-               .flag_has_hauppauge_custom_ir = !0,
                .flag_has_analogtuner = !0,
                .flag_has_fmradio = !0,
                .flag_has_composite = !0,
                .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
                .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+               .ir_scheme = PVR2_IR_SCHEME_24XXX,
 };
 
 
@@ -330,7 +330,7 @@ static const char *pvr2_fw1_names_73xxx[] = {
 };
 
 static const struct pvr2_device_desc pvr2_device_73xxx = {
-               .description = "WinTV PVR USB2 Model Category 73xxx",
+               .description = "WinTV HVR-1900 Model Category 73xxx",
                .shortname = "73xxx",
                .client_modules.lst = pvr2_client_73xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx),
@@ -344,6 +344,7 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
                .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
                .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+               .ir_scheme = PVR2_IR_SCHEME_ZILOG,
 #ifdef CONFIG_VIDEO_PVRUSB2_DVB
                .dvb_props = &pvr2_73xxx_dvb_props,
 #endif
@@ -438,7 +439,7 @@ static const char *pvr2_fw1_names_75xxx[] = {
 };
 
 static const struct pvr2_device_desc pvr2_device_750xx = {
-               .description = "WinTV PVR USB2 Model Category 750xx",
+               .description = "WinTV HVR-1950 Model Category 750xx",
                .shortname = "750xx",
                .client_modules.lst = pvr2_client_75xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
@@ -453,13 +454,14 @@ static const struct pvr2_device_desc pvr2_device_750xx = {
                .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
                .default_std_mask = V4L2_STD_NTSC_M,
                .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+               .ir_scheme = PVR2_IR_SCHEME_ZILOG,
 #ifdef CONFIG_VIDEO_PVRUSB2_DVB
                .dvb_props = &pvr2_750xx_dvb_props,
 #endif
 };
 
 static const struct pvr2_device_desc pvr2_device_751xx = {
-               .description = "WinTV PVR USB2 Model Category 751xx",
+               .description = "WinTV HVR-1950 Model Category 751xx",
                .shortname = "751xx",
                .client_modules.lst = pvr2_client_75xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
@@ -474,6 +476,7 @@ static const struct pvr2_device_desc pvr2_device_751xx = {
                .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
                .default_std_mask = V4L2_STD_NTSC_M,
                .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+               .ir_scheme = PVR2_IR_SCHEME_ZILOG,
 #ifdef CONFIG_VIDEO_PVRUSB2_DVB
                .dvb_props = &pvr2_751xx_dvb_props,
 #endif
index e23ce1d2edd772e9996652e18df182ce70c3744c..cb3a33eb027660a12c3dc355271dbad6c35c69ac 100644 (file)
@@ -48,6 +48,10 @@ struct pvr2_string_table {
 #define PVR2_LED_SCHEME_NONE 0
 #define PVR2_LED_SCHEME_HAUPPAUGE 1
 
+#define PVR2_IR_SCHEME_NONE 0
+#define PVR2_IR_SCHEME_24XXX 1
+#define PVR2_IR_SCHEME_ZILOG 2
+
 /* This describes a particular hardware type (except for the USB device ID
    which must live in a separate structure due to environmental
    constraints).  See the top of pvrusb2-hdw.c for where this is
@@ -126,15 +130,19 @@ struct pvr2_device_desc {
           ensure that it is found. */
        unsigned int flag_has_wm8775:1;
 
-       /* Device has IR hardware that can be faked into looking like a
-          normal Hauppauge i2c IR receiver.  This is currently very
-          specific to the 24xxx device, where Hauppauge had replaced their
-          'standard' I2C IR receiver with a bunch of FPGA logic controlled
-          directly via the FX2.  Turning this on tells the pvrusb2 driver
-          to virtualize the presence of the non-existant IR receiver chip and
-          implement the virtual receiver in terms of appropriate FX2
-          commands. */
-       unsigned int flag_has_hauppauge_custom_ir:1;
+       /* Indicate any specialized IR scheme that might need to be
+          supported by this driver.  If not set, then it is assumed that
+          IR can work without help from the driver (which is frequently
+          the case).  This is otherwise set to one of
+          PVR2_IR_SCHEME_xxxx.  For "xxxx", the value "24XXX" indicates a
+          Hauppauge 24xxx class device which has an FPGA-hosted IR
+          receiver that can only be reached via FX2 command codes.  In
+          that case the pvrusb2 driver will emulate the behavior of the
+          older 29xxx device's IR receiver (a "virtual" I2C chip) in terms
+          of those command codes.  For the value "ZILOG", we're dealing
+          with an IR chip that must be taken out of reset via another FX2
+          command code (which is the case for HVR-1950 devices). */
+       unsigned int ir_scheme:2;
 
        /* These bits define which kinds of sources the device can handle.
           Note: Digital tuner presence is inferred by the
index 6ec4bf81fc7f3e0d65c2f3308e0ae93fdff0aa82..77b3c338506624992f9023eff7adc2a123dd3550 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/kthread.h>
 #include <linux/freezer.h>
+#include <linux/mm.h>
 #include "dvbdev.h"
 #include "pvrusb2-debug.h"
 #include "pvrusb2-hdw-internal.h"
index b58369e7f30bcc800d8207784463ff6bc3e7c4c4..614755ea2ea3a92e9a7713748f6f20cf2c336510 100644 (file)
@@ -24,6 +24,8 @@
 #define FX2CMD_MEM_WRITE_DWORD  0x01u
 #define FX2CMD_MEM_READ_DWORD   0x02u
 
+#define FX2CMD_HCW_ZILOG_RESET  0x10u /* 1=reset 0=release */
+
 #define FX2CMD_MEM_READ_64BYTES 0x28u
 
 #define FX2CMD_REG_WRITE        0x04u
index a5217a2cf4c0fa5b96451237d136ee0d6b7907eb..f051c6aa7f1f223cd36744df1b6cc2af4b26d82a 100644 (file)
@@ -250,6 +250,7 @@ struct pvr2_fx2cmd_descdef {
 static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = {
        {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"},
        {FX2CMD_MEM_READ_DWORD, "read encoder dword"},
+       {FX2CMD_HCW_ZILOG_RESET, "zilog IR reset control"},
        {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"},
        {FX2CMD_REG_WRITE, "write encoder register"},
        {FX2CMD_REG_READ, "read encoder register"},
@@ -1711,6 +1712,14 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
                if (!pvr2_hdw_dev_ok(hdw)) return;
        }
 
+       /* Take the IR chip out of reset, if appropriate */
+       if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_ZILOG) {
+               pvr2_issue_simple_cmd(hdw,
+                                     FX2CMD_HCW_ZILOG_RESET |
+                                     (1 << 8) |
+                                     ((0) << 16));
+       }
+
        // This step MUST happen after the earlier powerup step.
        pvr2_i2c_core_init(hdw);
        if (!pvr2_hdw_dev_ok(hdw)) return;
index 9d3c18b24744f6cb1e3d3db8c29c6050a4b65c21..e600576a6c4b5b7092293052230e54ff3a857cec 100644 (file)
@@ -979,7 +979,9 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
                printk(KERN_INFO "%s: IR disabled\n",hdw->name);
                hdw->i2c_func[0x18] = i2c_black_hole;
        } else if (ir_mode[hdw->unit_number] == 1) {
-               if (hdw->hdw_desc->flag_has_hauppauge_custom_ir) {
+               if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) {
+                       /* This comment is present PURELY to get
+                          checkpatch.pl to STFU.  Lovely, eh? */
                        hdw->i2c_func[0x18] = i2c_24xxx_ir;
                }
        }
index 05a1376405e794d85ddfbcf9d569314519e8c925..b4824782d858c9c8626c791405c822ba363e64af 100644 (file)
@@ -22,6 +22,7 @@
 #include "pvrusb2-debug.h"
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
index 0d72dc470fef871a16b24d35cb339b92badcf313..00306faeac015f1ab9a99c8aaf32b894032bc444 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 struct pvr2_v4l2_dev;
 struct pvr2_v4l2_fh;
@@ -1160,11 +1161,6 @@ static const struct file_operations vdev_fops = {
 
 
 static struct video_device vdev_template = {
-       .owner      = THIS_MODULE,
-       .type       = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
-       .type2      = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
-                      | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
-                      | V4L2_CAP_READWRITE),
        .fops       = &vdev_fops,
 };
 
index 423fa7c2d0c9b465fa54f0a6cb761ea06e1cd420..9aee7cb6f79a9e310e57021ac7d50a1fb73d0dc9 100644 (file)
@@ -165,9 +165,7 @@ static const struct file_operations pwc_fops = {
        .llseek =       no_llseek,
 };
 static struct video_device pwc_template = {
-       .owner =        THIS_MODULE,
        .name =         "Philips Webcam",       /* Filled in later */
-       .type =         VID_TYPE_CAPTURE,
        .release =      video_device_release,
        .fops =         &pwc_fops,
        .minor =        -1,
@@ -1048,19 +1046,20 @@ static int pwc_create_sysfs_files(struct video_device *vdev)
        struct pwc_device *pdev = video_get_drvdata(vdev);
        int rc;
 
-       rc = video_device_create_file(vdev, &dev_attr_button);
+       rc = device_create_file(&vdev->dev, &dev_attr_button);
        if (rc)
                goto err;
        if (pdev->features & FEATURE_MOTOR_PANTILT) {
-               rc = video_device_create_file(vdev, &dev_attr_pan_tilt);
+               rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt);
                if (rc) goto err_button;
        }
 
        return 0;
 
 err_button:
-       video_device_remove_file(vdev, &dev_attr_button);
+       device_remove_file(&vdev->dev, &dev_attr_button);
 err:
+       PWC_ERROR("Could not create sysfs files.\n");
        return rc;
 }
 
@@ -1068,8 +1067,8 @@ static void pwc_remove_sysfs_files(struct video_device *vdev)
 {
        struct pwc_device *pdev = video_get_drvdata(vdev);
        if (pdev->features & FEATURE_MOTOR_PANTILT)
-               video_device_remove_file(vdev, &dev_attr_pan_tilt);
-       video_device_remove_file(vdev, &dev_attr_button);
+               device_remove_file(&vdev->dev, &dev_attr_pan_tilt);
+       device_remove_file(&vdev->dev, &dev_attr_button);
 }
 
 #ifdef CONFIG_USB_PWC_DEBUG
@@ -1767,9 +1766,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                return -ENOMEM;
        }
        memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
-       pdev->vdev->dev = &(udev->dev);
+       pdev->vdev->parent = &(udev->dev);
        strcpy(pdev->vdev->name, name);
-       pdev->vdev->owner = THIS_MODULE;
        video_set_drvdata(pdev->vdev, pdev);
 
        pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
index 8e8e5b27e77ea2f9c77edd549bc696b7b7c1000e..74178754b39b874dc049c3fc630f78d1c97601b1 100644 (file)
 #include <linux/smp_lock.h>
 #include <linux/version.h>
 #include <linux/mutex.h>
+#include <linux/mm.h>
 #include <asm/errno.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include "pwc-uncompress.h"
 #include <media/pwc-ioctl.h>
index 04eb2c3fabd8767ad6e8d282aec7660d426a514e..b1d09d8e2b8572c35c88be39100cf35dbc7e21ba 100644 (file)
 #include <linux/mutex.h>
 #include <linux/videodev2.h>
 #include <linux/version.h>
+#include <linux/mm.h>
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/vmalloc.h>
 #include <linux/usb.h>
 
@@ -184,6 +186,7 @@ struct s2255_dmaqueue {
 #define S2255_FW_LOADED_DSPWAIT        1
 #define S2255_FW_SUCCESS       2
 #define S2255_FW_FAILED                3
+#define S2255_FW_DISCONNECTING  4
 
 struct s2255_fw {
        int                   fw_loaded;
@@ -263,7 +266,6 @@ struct s2255_buffer {
 
 struct s2255_fh {
        struct s2255_dev        *dev;
-       unsigned int            resources;
        const struct s2255_fmt  *fmt;
        unsigned int            width;
        unsigned int            height;
@@ -273,14 +275,9 @@ struct s2255_fh {
        /* mode below is the desired mode.
           mode in s2255_dev is the current mode that was last set */
        struct s2255_mode       mode;
+       int                     resources[MAX_CHANNELS];
 };
 
-/*
- * TODO: fixme S2255_MAX_USERS. Do not limit open driver handles.
- * Limit V4L to one stream at a time.
- */
-#define S2255_MAX_USERS         1
-
 #define CUR_USB_FWVER  774     /* current cypress EEPROM firmware version */
 #define S2255_MAJOR_VERSION    1
 #define S2255_MINOR_VERSION    13
@@ -476,10 +473,9 @@ static void s2255_timer(unsigned long user_data)
        dprintk(100, "s2255 timer\n");
        if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
                printk(KERN_ERR "s2255: can't submit urb\n");
-               if (data->fw) {
-                       release_firmware(data->fw);
-                       data->fw = NULL;
-               }
+               atomic_set(&data->fw_state, S2255_FW_FAILED);
+               /* wake up anything waiting for the firmware */
+               wake_up(&data->wait_fw);
                return;
        }
 }
@@ -509,13 +505,18 @@ static void s2255_fwchunk_complete(struct urb *urb)
        struct usb_device *udev = urb->dev;
        int len;
        dprintk(100, "udev %p urb %p", udev, urb);
-       /* TODO: fixme.  reflect change in status */
        if (urb->status) {
                dev_err(&udev->dev, "URB failed with status %d", urb->status);
+               atomic_set(&data->fw_state, S2255_FW_FAILED);
+               /* wake up anything waiting for the firmware */
+               wake_up(&data->wait_fw);
                return;
        }
        if (data->fw_urb == NULL) {
-               dev_err(&udev->dev, "early disconncect\n");
+               dev_err(&udev->dev, "s2255 disconnected\n");
+               atomic_set(&data->fw_state, S2255_FW_FAILED);
+               /* wake up anything waiting for the firmware */
+               wake_up(&data->wait_fw);
                return;
        }
 #define CHUNK_SIZE 512
@@ -789,7 +790,8 @@ static int res_get(struct s2255_dev *dev, struct s2255_fh *fh)
        }
        /* it's free, grab it */
        dev->resources[fh->channel] = 1;
-       dprintk(1, "res: get\n");
+       fh->resources[fh->channel] = 1;
+       dprintk(1, "s2255: res: get\n");
        mutex_unlock(&dev->lock);
        return 1;
 }
@@ -799,9 +801,18 @@ static int res_locked(struct s2255_dev *dev, struct s2255_fh *fh)
        return dev->resources[fh->channel];
 }
 
+static int res_check(struct s2255_fh *fh)
+{
+       return fh->resources[fh->channel];
+}
+
+
 static void res_free(struct s2255_dev *dev, struct s2255_fh *fh)
 {
+       mutex_lock(&dev->lock);
        dev->resources[fh->channel] = 0;
+       fh->resources[fh->channel] = 0;
+       mutex_unlock(&dev->lock);
        dprintk(1, "res: put\n");
 }
 
@@ -1232,7 +1243,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
        }
 
        if (!res_get(dev, fh)) {
-               dev_err(&dev->udev->dev, "res get busy\n");
+               dev_err(&dev->udev->dev, "s2255: stream busy\n");
                return -EBUSY;
        }
 
@@ -1288,8 +1299,10 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
        }
        s2255_stop_acquire(dev, fh->channel);
        res = videobuf_streamoff(&fh->vb_vidq);
+       if (res < 0)
+               return res;
        res_free(dev, fh);
-       return res;
+       return 0;
 }
 
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
@@ -1462,12 +1475,7 @@ static int s2255_open(struct inode *inode, struct file *file)
        mutex_lock(&dev->open_lock);
 
        dev->users[cur_channel]++;
-       if (dev->users[cur_channel] > S2255_MAX_USERS) {
-               dev->users[cur_channel]--;
-               mutex_unlock(&dev->open_lock);
-               printk(KERN_INFO "s2255drv: too many open handles!\n");
-               return -EBUSY;
-       }
+       dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]);
 
        if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) {
                err("2255 firmware load failed. retrying.\n");
@@ -1478,7 +1486,8 @@ static int s2255_open(struct inode *inode, struct file *file)
                                   msecs_to_jiffies(S2255_LOAD_TIMEOUT));
                if (atomic_read(&dev->fw_data->fw_state)
                    != S2255_FW_SUCCESS) {
-                       printk(KERN_INFO "2255 FW load failed after 2 tries\n");
+                       printk(KERN_INFO "2255 FW load failed.\n");
+                       dev->users[cur_channel]--;
                        mutex_unlock(&dev->open_lock);
                        return -EFAULT;
                }
@@ -1494,6 +1503,7 @@ static int s2255_open(struct inode *inode, struct file *file)
                    != S2255_FW_SUCCESS) {
                        printk(KERN_INFO "2255 firmware not loaded"
                               "try again\n");
+                       dev->users[cur_channel]--;
                        mutex_unlock(&dev->open_lock);
                        return -EBUSY;
                }
@@ -1502,6 +1512,7 @@ static int s2255_open(struct inode *inode, struct file *file)
        /* allocate + initialize per filehandle data */
        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
        if (NULL == fh) {
+               dev->users[cur_channel]--;
                mutex_unlock(&dev->open_lock);
                return -ENOMEM;
        }
@@ -1561,44 +1572,48 @@ static void s2255_destroy(struct kref *kref)
                printk(KERN_ERR "s2255drv: kref problem\n");
                return;
        }
+
+       /*
+        * Wake up any firmware load waiting (only done in .open,
+        * which holds the open_lock mutex)
+        */
+       atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
+       wake_up(&dev->fw_data->wait_fw);
+
        /* prevent s2255_disconnect from racing s2255_open */
        mutex_lock(&dev->open_lock);
        s2255_exit_v4l(dev);
-       /* device unregistered so no longer possible to open. open_mutex
-          can be unlocked */
+       /*
+        * device unregistered so no longer possible to open. open_mutex
+        *  can be unlocked and timers deleted afterwards.
+        */
        mutex_unlock(&dev->open_lock);
 
        /* board shutdown stops the read pipe if it is running */
        s2255_board_shutdown(dev);
 
        /* make sure firmware still not trying to load */
+       del_timer(&dev->timer);  /* only started in .probe and .open */
+
        if (dev->fw_data->fw_urb) {
                dprintk(2, "kill fw_urb\n");
                usb_kill_urb(dev->fw_data->fw_urb);
                usb_free_urb(dev->fw_data->fw_urb);
                dev->fw_data->fw_urb = NULL;
        }
+
        /*
-        * TODO: fixme(above, below): potentially leaving timers alive.
-        *                            do not ignore timeout below if
-        *                            it occurs.
+        * delete the dsp_wait timer, which sets the firmware
+        * state on completion.  This is done before fw_data
+        * is freed below.
         */
 
-       /* make sure we aren't waiting for the DSP */
-       if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_LOADED_DSPWAIT) {
-               /* if we are, wait for the wakeup for fw_success or timeout */
-               wait_event_timeout(dev->fw_data->wait_fw,
-                                  (atomic_read(&dev->fw_data->fw_state)
-                                  == S2255_FW_SUCCESS),
-                                  msecs_to_jiffies(S2255_LOAD_TIMEOUT));
-       }
+       del_timer(&dev->fw_data->dsp_wait); /* only started in .open */
 
-       if (dev->fw_data) {
-               if (dev->fw_data->fw)
-                       release_firmware(dev->fw_data->fw);
-               kfree(dev->fw_data->pfw_data);
-               kfree(dev->fw_data);
-       }
+       if (dev->fw_data->fw)
+               release_firmware(dev->fw_data->fw);
+       kfree(dev->fw_data->pfw_data);
+       kfree(dev->fw_data);
 
        usb_put_dev(dev->udev);
        dprintk(1, "%s", __func__);
@@ -1615,17 +1630,23 @@ static int s2255_close(struct inode *inode, struct file *file)
 
        mutex_lock(&dev->open_lock);
 
-       if (dev->b_acquire[fh->channel])
-               s2255_stop_acquire(dev, fh->channel);
-       res_free(dev, fh);
+       /* turn off stream */
+       if (res_check(fh)) {
+               if (dev->b_acquire[fh->channel])
+                       s2255_stop_acquire(dev, fh->channel);
+               videobuf_streamoff(&fh->vb_vidq);
+               res_free(dev, fh);
+       }
+
        videobuf_mmap_free(&fh->vb_vidq);
-       kfree(fh);
        dev->users[fh->channel]--;
+
        mutex_unlock(&dev->open_lock);
 
        kref_put(&dev->kref, s2255_destroy);
        dprintk(1, "s2255: close called (minor=%d, users=%d)\n",
                minor, dev->users[fh->channel]);
+       kfree(fh);
        return 0;
 }
 
@@ -1658,12 +1679,7 @@ static const struct file_operations s2255_fops_v4l = {
        .llseek = no_llseek,
 };
 
-static struct video_device template = {
-       .name = "s2255v",
-       .type = VID_TYPE_CAPTURE,
-       .fops = &s2255_fops_v4l,
-       .minor = -1,
-       .release = video_device_release,
+static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
        .vidioc_querycap = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
@@ -1685,6 +1701,14 @@ static struct video_device template = {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        .vidiocgmbuf = vidioc_cgmbuf,
 #endif
+};
+
+static struct video_device template = {
+       .name = "s2255v",
+       .fops = &s2255_fops_v4l,
+       .ioctl_ops = &s2255_ioctl_ops,
+       .minor = -1,
+       .release = video_device_release,
        .tvnorms = S2255_NORMS,
        .current_norm = V4L2_STD_NTSC_M,
 };
@@ -1706,7 +1730,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
                /* register 4 video devices */
                dev->vdev[i] = video_device_alloc();
                memcpy(dev->vdev[i], &template, sizeof(struct video_device));
-               dev->vdev[i]->dev = &dev->interface->dev;
+               dev->vdev[i]->parent = &dev->interface->dev;
                if (video_nr == -1)
                        ret = video_register_device(dev->vdev[i],
                                                    VFL_TYPE_GRABBER,
index 03e772130b55f2edeec58f3febce448b1f970a72..6ee63e69b36c4d7106fd0b2bcafb0433df47d64b 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/videotext.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 
 #include "saa5246a.h"
@@ -829,9 +830,7 @@ static const struct file_operations saa_fops = {
 
 static struct video_device saa_template =
 {
-       .owner    = THIS_MODULE,
        .name     = IF_NAME,
-       .type     = VID_TYPE_TELETEXT,
        .fops     = &saa_fops,
        .release  = video_device_release,
        .minor    = -1,
index fde99d9ee71f5716f7acdcefcc3625a3cc05c7e6..0d639738d4e68044f4fa651b97d35573b820da83 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/videotext.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 
 
@@ -710,9 +711,7 @@ static const struct file_operations saa_fops = {
 
 static struct video_device saa_template =
 {
-       .owner          = THIS_MODULE,
        .name           = IF_NAME,
-       .type           = VID_TYPE_TELETEXT,    /*| VID_TYPE_TUNER ?? */
        .fops           = &saa_fops,
 };
 
index 83f076abce35193acf230ec73bcdd9fb87807c6c..7021bbf5897b3ac6988fd5d42d28bc70a4231c9f 100644 (file)
@@ -27,9 +27,7 @@ config VIDEO_SAA7134_ALSA
 config VIDEO_SAA7134_DVB
        tristate "DVB/ATSC Support for saa7134 based TV cards"
        depends on VIDEO_SAA7134 && DVB_CORE
-       depends on HOTPLUG      # due to FW_LOADER
        select VIDEOBUF_DVB
-       select FW_LOADER
        select DVB_PLL if !DVB_FE_CUSTOMISE
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_TDA1004X if !DVB_FE_CUSTOMISE
index 6893f998d292957313facf76d9fdb69ecd4bba0f..98364d171def6ba442c92b28e60125649d6cb7e6 100644 (file)
@@ -5853,9 +5853,6 @@ int saa7134_board_init2(struct saa7134_dev *dev)
        unsigned char buf;
        int board;
 
-       dev->tuner_type = saa7134_boards[dev->board].tuner_type;
-       dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;
-
        switch (dev->board) {
        case SAA7134_BOARD_BMK_MPEX_NOTUNER:
        case SAA7134_BOARD_BMK_MPEX_TUNER:
index cfee84ee7a88a3e5c0a187ddd96532afe700549d..75d618415f4f401e9b9239e8d936ef8d8d0647eb 100644 (file)
@@ -798,7 +798,7 @@ static struct video_device *vdev_init(struct saa7134_dev *dev,
                return NULL;
        *vfd = *template;
        vfd->minor   = -1;
-       vfd->dev     = &dev->pci->dev;
+       vfd->parent  = &dev->pci->dev;
        vfd->release = video_device_release;
        vfd->debug   = video_debug;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
@@ -945,11 +945,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
                dev->board = SAA7134_BOARD_UNKNOWN;
        }
        dev->autodetected = card[dev->nr] != dev->board;
-       dev->tuner_type   = saa7134_boards[dev->board].tuner_type;
+       dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+       dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;
        dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
        if (UNSET != tuner[dev->nr])
                dev->tuner_type = tuner[dev->nr];
-               printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+       printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
                dev->name,pci_dev->subsystem_vendor,
                pci_dev->subsystem_device,saa7134_boards[dev->board].name,
                dev->board, dev->autodetected ?
@@ -1007,11 +1008,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        v4l2_prio_init(&dev->prio);
 
        /* register v4l devices */
-       if (saa7134_no_overlay <= 0) {
-               saa7134_video_template.type |= VID_TYPE_OVERLAY;
-       } else {
-               printk("%s: Overlay support disabled.\n",dev->name);
-       }
+       if (saa7134_no_overlay > 0)
+               printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name);
+
        dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
        err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
                                    video_nr[dev->nr]);
@@ -1024,7 +1023,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
               dev->name,dev->video_dev->minor & 0x1f);
 
        dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
-       dev->vbi_dev->type = VID_TYPE_TUNER | VID_TYPE_TELETEXT;
 
        err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
                                    vbi_nr[dev->nr]);
index 2a5ab957542dfacab6e3e73dfe77da44c2975280..c0c5d7509c25a81c9fb5fda2c79b74cf2314617a 100644 (file)
@@ -89,14 +89,14 @@ static int ts_open(struct inode *inode, struct file *file)
        err = -EBUSY;
        if (!mutex_trylock(&dev->empress_tsq.vb_lock))
                goto done;
-       if (dev->empress_users)
+       if (atomic_read(&dev->empress_users))
                goto done_up;
 
        /* Unmute audio */
        saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
                saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
 
-       dev->empress_users++;
+       atomic_inc(&dev->empress_users);
        file->private_data = dev;
        err = 0;
 
@@ -110,8 +110,6 @@ static int ts_release(struct inode *inode, struct file *file)
 {
        struct saa7134_dev *dev = file->private_data;
 
-       mutex_lock(&dev->empress_tsq.vb_lock);
-
        videobuf_stop(&dev->empress_tsq);
        videobuf_mmap_free(&dev->empress_tsq);
 
@@ -122,9 +120,7 @@ static int ts_release(struct inode *inode, struct file *file)
        saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
                saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
 
-       dev->empress_users--;
-
-       mutex_unlock(&dev->empress_tsq.vb_lock);
+       atomic_dec(&dev->empress_users);
 
        return 0;
 }
@@ -333,6 +329,22 @@ static int empress_g_ext_ctrls(struct file *file, void *priv,
        return saa7134_i2c_call_saa6752(dev, VIDIOC_G_EXT_CTRLS, ctrls);
 }
 
+static int empress_g_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *c)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return saa7134_g_ctrl_internal(dev, NULL, c);
+}
+
+static int empress_s_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *c)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return saa7134_s_ctrl_internal(dev, NULL, c);
+}
+
 static int empress_queryctrl(struct file *file, void *priv,
                                        struct v4l2_queryctrl *c)
 {
@@ -400,16 +412,7 @@ static const struct file_operations ts_fops =
        .llseek   = no_llseek,
 };
 
-/* ----------------------------------------------------------- */
-
-static struct video_device saa7134_empress_template =
-{
-       .name          = "saa7134-empress",
-       .type          = 0 /* FIXME */,
-       .type2         = 0 /* FIXME */,
-       .fops          = &ts_fops,
-       .minor         = -1,
-
+static const struct v4l2_ioctl_ops ts_ioctl_ops = {
        .vidioc_querycap                = empress_querycap,
        .vidioc_enum_fmt_vid_cap        = empress_enum_fmt_vid_cap,
        .vidioc_s_fmt_vid_cap           = empress_s_fmt_vid_cap,
@@ -428,8 +431,17 @@ static struct video_device saa7134_empress_template =
 
        .vidioc_queryctrl               = empress_queryctrl,
        .vidioc_querymenu               = empress_querymenu,
-       .vidioc_g_ctrl                  = saa7134_g_ctrl,
-       .vidioc_s_ctrl                  = saa7134_s_ctrl,
+       .vidioc_g_ctrl                  = empress_g_ctrl,
+       .vidioc_s_ctrl                  = empress_s_ctrl,
+};
+
+/* ----------------------------------------------------------- */
+
+static struct video_device saa7134_empress_template = {
+       .name          = "saa7134-empress",
+       .fops          = &ts_fops,
+       .minor         = -1,
+       .ioctl_ops     = &ts_ioctl_ops,
 
        .tvnorms                        = SAA7134_NORMS,
        .current_norm                   = V4L2_STD_PAL,
@@ -445,7 +457,7 @@ static void empress_signal_update(struct work_struct *work)
                ts_reset_encoder(dev);
        } else {
                dprintk("video signal acquired\n");
-               if (dev->empress_users)
+               if (atomic_read(&dev->empress_users))
                        ts_init_encoder(dev);
        }
 }
@@ -465,7 +477,7 @@ static int empress_init(struct saa7134_dev *dev)
        if (NULL == dev->empress_dev)
                return -ENOMEM;
        *(dev->empress_dev) = saa7134_empress_template;
-       dev->empress_dev->dev     = &dev->pci->dev;
+       dev->empress_dev->parent  = &dev->pci->dev;
        dev->empress_dev->release = video_device_release;
        snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
                 "%s empress (%s)", dev->name,
index 1a5137550e7a8bafe217c91d637fba3fa9ca2b55..68c268981861dee9e8abc93e640a036480eecce8 100644 (file)
@@ -1112,10 +1112,8 @@ static struct videobuf_queue_ops video_qops = {
 
 /* ------------------------------------------------------------------ */
 
-int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
+int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
        const struct v4l2_queryctrl* ctrl;
 
        ctrl = ctrl_by_id(c->id);
@@ -1160,20 +1158,31 @@ int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
        }
        return 0;
 }
-EXPORT_SYMBOL_GPL(saa7134_g_ctrl);
+EXPORT_SYMBOL_GPL(saa7134_g_ctrl_internal);
+
+static int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
+{
+       struct saa7134_fh *fh = priv;
+
+       return saa7134_g_ctrl_internal(fh->dev, fh, c);
+}
 
-int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c)
+int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c)
 {
        const struct v4l2_queryctrl* ctrl;
-       struct saa7134_fh *fh = f;
-       struct saa7134_dev *dev = fh->dev;
        unsigned long flags;
        int restart_overlay = 0;
-       int err = -EINVAL;
+       int err;
 
-       err = v4l2_prio_check(&dev->prio, &fh->prio);
-       if (0 != err)
-               return err;
+       /* When called from the empress code fh == NULL.
+          That needs to be fixed somehow, but for now this is
+          good enough. */
+       if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+       err = -EINVAL;
 
        mutex_lock(&dev->lock);
 
@@ -1274,7 +1283,14 @@ error:
        mutex_unlock(&dev->lock);
        return err;
 }
-EXPORT_SYMBOL_GPL(saa7134_s_ctrl);
+EXPORT_SYMBOL_GPL(saa7134_s_ctrl_internal);
+
+static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c)
+{
+       struct saa7134_fh *fh = f;
+
+       return saa7134_s_ctrl_internal(fh->dev, fh, c);
+}
 
 /* ------------------------------------------------------------------ */
 
@@ -2353,26 +2369,7 @@ static const struct file_operations video_fops =
        .llseek   = no_llseek,
 };
 
-static const struct file_operations radio_fops =
-{
-       .owner    = THIS_MODULE,
-       .open     = video_open,
-       .release  = video_release,
-       .ioctl    = video_ioctl2,
-       .compat_ioctl   = v4l_compat_ioctl32,
-       .llseek   = no_llseek,
-};
-
-/* ----------------------------------------------------------- */
-/* exported stuff                                              */
-
-struct video_device saa7134_video_template =
-{
-       .name                           = "saa7134-video",
-       .type                           = VID_TYPE_CAPTURE|VID_TYPE_TUNER |
-                                       VID_TYPE_CLIPPING|VID_TYPE_SCALES,
-       .fops                           = &video_fops,
-       .minor                          = -1,
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_querycap                = saa7134_querycap,
        .vidioc_enum_fmt_vid_cap        = saa7134_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap           = saa7134_g_fmt_vid_cap,
@@ -2421,16 +2418,18 @@ struct video_device saa7134_video_template =
        .vidioc_g_register              = vidioc_g_register,
        .vidioc_s_register              = vidioc_s_register,
 #endif
-       .tvnorms                        = SAA7134_NORMS,
-       .current_norm                   = V4L2_STD_PAL,
 };
 
-struct video_device saa7134_radio_template =
-{
-       .name                   = "saa7134-radio",
-       .type                   = VID_TYPE_TUNER,
-       .fops                   = &radio_fops,
-       .minor                  = -1,
+static const struct file_operations radio_fops = {
+       .owner    = THIS_MODULE,
+       .open     = video_open,
+       .release  = video_release,
+       .ioctl    = video_ioctl2,
+       .compat_ioctl   = v4l_compat_ioctl32,
+       .llseek   = no_llseek,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
        .vidioc_querycap        = radio_querycap,
        .vidioc_g_tuner         = radio_g_tuner,
        .vidioc_enum_input      = radio_enum_input,
@@ -2447,6 +2446,25 @@ struct video_device saa7134_radio_template =
        .vidioc_s_frequency     = saa7134_s_frequency,
 };
 
+/* ----------------------------------------------------------- */
+/* exported stuff                                              */
+
+struct video_device saa7134_video_template = {
+       .name                           = "saa7134-video",
+       .fops                           = &video_fops,
+       .ioctl_ops                      = &video_ioctl_ops,
+       .minor                          = -1,
+       .tvnorms                        = SAA7134_NORMS,
+       .current_norm                   = V4L2_STD_PAL,
+};
+
+struct video_device saa7134_radio_template = {
+       .name                   = "saa7134-radio",
+       .fops                   = &radio_fops,
+       .ioctl_ops              = &radio_ioctl_ops,
+       .minor                  = -1,
+};
+
 int saa7134_video_init1(struct saa7134_dev *dev)
 {
        /* sanitycheck insmod options */
index 6927cbea86245b6e49cd268af82fc04da600ff76..a0884f639f6504b6826c9e791107f3bbe3f9f06c 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/io.h>
 
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/tuner.h>
 #include <media/ir-common.h>
 #include <media/ir-kbd-i2c.h>
@@ -560,7 +561,7 @@ struct saa7134_dev {
        /* SAA7134_MPEG_EMPRESS only */
        struct video_device        *empress_dev;
        struct videobuf_queue      empress_tsq;
-       unsigned int               empress_users;
+       atomic_t                   empress_users;
        struct work_struct         empress_workqueue;
        int                        empress_started;
 
@@ -662,8 +663,8 @@ extern unsigned int video_debug;
 extern struct video_device saa7134_video_template;
 extern struct video_device saa7134_radio_template;
 
-int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c);
-int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c);
+int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
+int saa7134_g_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
 int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
 
 int saa7134_videoport_init(struct saa7134_dev *dev);
index 2220f9569941e04a767d1692546500294bc0cf7e..af60ede5310d2bcc9acf0f7e12088e759e242d90 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 
-#include <linux/videodev.h>
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 #include <media/v4l2-common.h>
index cd4b6354a7b3c33112ae3aa62f91003eaf5c614d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,117 +0,0 @@
-/*
-    Definitions for the Philips SAA7196 digital video decoder,
-    scaler, and clock generator circuit (DESCpro), as used in
-    the PlanB video input of the Powermac 7x00/8x00 series.
-
-    Copyright (C) 1998 Michel Lanners (mlan@cpu.lu)
-
-    The register defines are shamelessly copied from the meteor
-    driver out of NetBSD (with permission),
-    and are copyrighted (c) 1995 Mark Tinguely and Jim Lowe
-    (Thanks !)
-
-    Additional debugging and coding by Takashi Oe (toe@unlinfo.unl.edu)
-
-    The default values used for PlanB are my mistakes.
-*/
-
-/* $Id: saa7196.h,v 1.5 1999/03/26 23:28:47 mlan Exp $ */
-
-#ifndef _SAA7196_H_
-#define _SAA7196_H_
-
-#define SAA7196_NUMREGS        0x31    /* Number of registers (used)*/
-#define NUM_SUPPORTED_NORM 3   /* Number of supported norms by PlanB */
-
-/* Decoder part: */
-#define SAA7196_IDEL    0x00    /* Increment delay */
-#define SAA7196_HSB5    0x01    /* H-sync begin; 50 hz */
-#define SAA7196_HSS5    0x02    /* H-sync stop; 50 hz */
-#define SAA7196_HCB5    0x03    /* H-clamp begin; 50 hz */
-#define SAA7196_HCS5    0x04    /* H-clamp stop; 50 hz */
-#define SAA7196_HSP5    0x05    /* H-sync after PHI1; 50 hz */
-#define SAA7196_LUMC    0x06    /* Luminance control */
-#define SAA7196_HUEC    0x07    /* Hue control */
-#define SAA7196_CKTQ    0x08    /* Colour Killer Threshold QAM (PAL, NTSC) */
-#define SAA7196_CKTS    0x09    /* Colour Killer Threshold SECAM */
-#define SAA7196_PALS    0x0a    /* PAL switch sensitivity */
-#define SAA7196_SECAMS  0x0b    /* SECAM switch sensitivity */
-#define SAA7196_CGAINC  0x0c    /* Chroma gain control */
-#define SAA7196_STDC    0x0d    /* Standard/Mode control */
-#define SAA7196_IOCC    0x0e    /* I/O and Clock Control */
-#define SAA7196_CTRL1   0x0f    /* Control #1 */
-#define SAA7196_CTRL2   0x10    /* Control #2 */
-#define SAA7196_CGAINR  0x11    /* Chroma Gain Reference */
-#define SAA7196_CSAT    0x12    /* Chroma Saturation */
-#define SAA7196_CONT    0x13    /* Luminance Contrast */
-#define SAA7196_HSB6    0x14    /* H-sync begin; 60 hz */
-#define SAA7196_HSS6    0x15    /* H-sync stop; 60 hz */
-#define SAA7196_HCB6    0x16    /* H-clamp begin; 60 hz */
-#define SAA7196_HCS6    0x17    /* H-clamp stop; 60 hz */
-#define SAA7196_HSP6    0x18    /* H-sync after PHI1; 60 hz */
-#define SAA7196_BRIG    0x19    /* Luminance Brightness */
-
-/* Scaler part: */
-#define SAA7196_FMTS    0x20    /* Formats and sequence */
-#define SAA7196_OUTPIX  0x21    /* Output data pixel/line */
-#define SAA7196_INPIX   0x22    /* Input data pixel/line */
-#define SAA7196_HWS     0x23    /* Horiz. window start */
-#define SAA7196_HFILT   0x24    /* Horiz. filter */
-#define SAA7196_OUTLINE 0x25    /* Output data lines/field */
-#define SAA7196_INLINE  0x26    /* Input data lines/field */
-#define SAA7196_VWS     0x27    /* Vertical window start */
-#define SAA7196_VYP     0x28    /* AFS/vertical Y processing */
-#define SAA7196_VBS     0x29    /* Vertical Bypass start */
-#define SAA7196_VBCNT   0x2a    /* Vertical Bypass count */
-#define SAA7196_VBP     0x2b    /* veritcal Bypass Polarity */
-#define SAA7196_VLOW    0x2c    /* Colour-keying lower V limit */
-#define SAA7196_VHIGH   0x2d    /* Colour-keying upper V limit */
-#define SAA7196_ULOW    0x2e    /* Colour-keying lower U limit */
-#define SAA7196_UHIGH   0x2f    /* Colour-keying upper U limit */
-#define SAA7196_DPATH   0x30    /* Data path setting  */
-
-/* Initialization default values: */
-
-unsigned char saa_regs[NUM_SUPPORTED_NORM][SAA7196_NUMREGS] = {
-
-/* PAL, 768x576 (no scaling), composite video-in */
-/* Decoder: */
-      { 0x50, 0x30, 0x00, 0xe8, 0xb6, 0xe5, 0x63, 0xff,
-       0xfe, 0xf0, 0xfe, 0xe0, 0x20, 0x06, 0x3b, 0x98,
-       0x00, 0x59, 0x41, 0x45, 0x34, 0x0a, 0xf4, 0xd2,
-       0xe9, 0xa2,
-/* Padding */
-                   0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-/* Scaler: */
-       0x72, 0x80, 0x00, 0x03, 0x8d, 0x20, 0x20, 0x12,
-       0xa5, 0x12, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
-       0x87 },
-
-/* NTSC, 640x480? (no scaling), composite video-in */
-/* Decoder: */
-      { 0x50, 0x30, 0x00, 0xe8, 0xb6, 0xe5, 0x50, 0x00,
-       0xf8, 0xf0, 0xfe, 0xe0, 0x00, 0x06, 0x3b, 0x98,
-       0x00, 0x2c, 0x3d, 0x40, 0x34, 0x0a, 0xf4, 0xd2,
-       0xe9, 0x98,
-/* Padding */
-                   0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-/* Scaler: */
-       0x72, 0x80, 0x80, 0x03, 0x89, 0xf0, 0xf0, 0x0d,
-       0xa0, 0x0d, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
-       0x87 },
-
-/* SECAM, 768x576 (no scaling), composite video-in */
-/* Decoder: */
-      { 0x50, 0x30, 0x00, 0xe8, 0xb6, 0xe5, 0x63, 0xff,
-       0xfe, 0xf0, 0xfe, 0xe0, 0x20, 0x07, 0x3b, 0x98,
-       0x00, 0x59, 0x41, 0x45, 0x34, 0x0a, 0xf4, 0xd2,
-       0xe9, 0xa2,
-/* Padding */
-                   0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-/* Scaler: */
-       0x72, 0x80, 0x00, 0x03, 0x8d, 0x20, 0x20, 0x12,
-       0xa5, 0x12, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
-       0x87 }
-       };
-
-#endif /* _SAA7196_H_ */
index 1cd629380f7183c94882fca69c1f4a4e85c67784..f481277892da9be5eedf81d4ffe93043a5a012b1 100644 (file)
@@ -1230,9 +1230,7 @@ static const struct file_operations se401_fops = {
        .llseek =       no_llseek,
 };
 static struct video_device se401_template = {
-       .owner =        THIS_MODULE,
        .name =         "se401 USB camera",
-       .type =         VID_TYPE_CAPTURE,
        .fops =         &se401_fops,
 };
 
index 835ef872e80375af580d676d5616ce0635f9a536..2ce685db5d8b2eaa91021d7668b669cf59f1e74e 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 
 #define se401_DEBUG    /* Turn on debug messages */
index 012005e1a77b60e771e54ed329d315d2a0a8b132..f7ca3cb9340ad3ef0fb750dcd60a229f9d0c2208 100644 (file)
@@ -91,6 +91,7 @@ struct sh_mobile_ceu_dev {
        void __iomem *base;
        unsigned long video_limit;
 
+       /* lock used to protect videobuf */
        spinlock_t lock;
        struct list_head capture;
        struct videobuf_buffer *active;
index 0c8d87d8d18dd0b7e3b60b1b530942f944bfef96..cbfc44433b99fd56a2bbb8aff56712698f96a61e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/usb.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
index 7f9c7bcf3c852428b73052e89b146c33c4569e2b..23408764d0ef6db55e9f8df3eaa57fa57e8007ce 100644 (file)
@@ -1038,8 +1038,7 @@ static ssize_t sn9c102_show_reg(struct device* cd,
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1064,8 +1063,7 @@ sn9c102_store_reg(struct device* cd, struct device_attribute *attr,
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1098,8 +1096,7 @@ static ssize_t sn9c102_show_val(struct device* cd,
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1132,8 +1129,7 @@ sn9c102_store_val(struct device* cd, struct device_attribute *attr,
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1170,8 +1166,7 @@ static ssize_t sn9c102_show_i2c_reg(struct device* cd,
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1198,8 +1193,7 @@ sn9c102_store_i2c_reg(struct device* cd, struct device_attribute *attr,
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1232,8 +1226,7 @@ static ssize_t sn9c102_show_i2c_val(struct device* cd,
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1271,8 +1264,7 @@ sn9c102_store_i2c_val(struct device* cd, struct device_attribute *attr,
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1318,8 +1310,7 @@ sn9c102_store_green(struct device* cd, struct device_attribute *attr,
        if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam) {
                mutex_unlock(&sn9c102_sysfs_lock);
                return -ENODEV;
@@ -1400,8 +1391,7 @@ static ssize_t sn9c102_show_frame_header(struct device* cd,
        struct sn9c102_device* cam;
        ssize_t count;
 
-       cam = video_get_drvdata(container_of(cd, struct video_device,
-                                            class_dev));
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
        if (!cam)
                return -ENODEV;
 
@@ -1428,49 +1418,49 @@ static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
 
 static int sn9c102_create_sysfs(struct sn9c102_device* cam)
 {
-       struct device *classdev = &(cam->v4ldev->class_dev);
+       struct device *dev = &(cam->v4ldev->dev);
        int err = 0;
 
-       if ((err = device_create_file(classdev, &dev_attr_reg)))
+       if ((err = device_create_file(dev, &dev_attr_reg)))
                goto err_out;
-       if ((err = device_create_file(classdev, &dev_attr_val)))
+       if ((err = device_create_file(dev, &dev_attr_val)))
                goto err_reg;
-       if ((err = device_create_file(classdev, &dev_attr_frame_header)))
+       if ((err = device_create_file(dev, &dev_attr_frame_header)))
                goto err_val;
 
        if (cam->sensor.sysfs_ops) {
-               if ((err = device_create_file(classdev, &dev_attr_i2c_reg)))
+               if ((err = device_create_file(dev, &dev_attr_i2c_reg)))
                        goto err_frame_header;
-               if ((err = device_create_file(classdev, &dev_attr_i2c_val)))
+               if ((err = device_create_file(dev, &dev_attr_i2c_val)))
                        goto err_i2c_reg;
        }
 
        if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
-               if ((err = device_create_file(classdev, &dev_attr_green)))
+               if ((err = device_create_file(dev, &dev_attr_green)))
                        goto err_i2c_val;
        } else {
-               if ((err = device_create_file(classdev, &dev_attr_blue)))
+               if ((err = device_create_file(dev, &dev_attr_blue)))
                        goto err_i2c_val;
-               if ((err = device_create_file(classdev, &dev_attr_red)))
+               if ((err = device_create_file(dev, &dev_attr_red)))
                        goto err_blue;
        }
 
        return 0;
 
 err_blue:
-       device_remove_file(classdev, &dev_attr_blue);
+       device_remove_file(dev, &dev_attr_blue);
 err_i2c_val:
        if (cam->sensor.sysfs_ops)
-               device_remove_file(classdev, &dev_attr_i2c_val);
+               device_remove_file(dev, &dev_attr_i2c_val);
 err_i2c_reg:
        if (cam->sensor.sysfs_ops)
-               device_remove_file(classdev, &dev_attr_i2c_reg);
+               device_remove_file(dev, &dev_attr_i2c_reg);
 err_frame_header:
-       device_remove_file(classdev, &dev_attr_frame_header);
+       device_remove_file(dev, &dev_attr_frame_header);
 err_val:
-       device_remove_file(classdev, &dev_attr_val);
+       device_remove_file(dev, &dev_attr_val);
 err_reg:
-       device_remove_file(classdev, &dev_attr_reg);
+       device_remove_file(dev, &dev_attr_reg);
 err_out:
        return err;
 }
@@ -3319,8 +3309,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        }
 
        strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
-       cam->v4ldev->owner = THIS_MODULE;
-       cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
        cam->v4ldev->fops = &sn9c102_fops;
        cam->v4ldev->minor = video_nr[dev_nr];
        cam->v4ldev->release = video_device_release;
index e39b98f1eca4e97edc94ca6008436eef20449fdd..b6be5ee678b6112514b70c3335282919259219f0 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/vmalloc.h>
 
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/v4l2-dev.h>
 #include <media/videobuf-core.h>
 #include <media/soc_camera.h>
@@ -193,7 +194,7 @@ static int soc_camera_open(struct inode *inode, struct file *file)
        mutex_lock(&video_lock);
 
        vdev = video_devdata(file);
-       icd = container_of(vdev->dev, struct soc_camera_device, dev);
+       icd = container_of(vdev->parent, struct soc_camera_device, dev);
        ici = to_soc_camera_host(icd->dev.parent);
 
        if (!try_module_get(icd->ops->owner)) {
@@ -258,7 +259,7 @@ static int soc_camera_close(struct inode *inode, struct file *file)
 
        vfree(icf);
 
-       dev_dbg(vdev->dev, "camera device close\n");
+       dev_dbg(vdev->parent, "camera device close\n");
 
        return 0;
 }
@@ -271,7 +272,7 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf,
        struct video_device *vdev = icd->vdev;
        int err = -EINVAL;
 
-       dev_err(vdev->dev, "camera device read not implemented\n");
+       dev_err(vdev->parent, "camera device read not implemented\n");
 
        return err;
 }
@@ -861,6 +862,35 @@ void soc_camera_device_unregister(struct soc_camera_device *icd)
 }
 EXPORT_SYMBOL(soc_camera_device_unregister);
 
+static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
+       .vidioc_querycap         = soc_camera_querycap,
+       .vidioc_g_fmt_vid_cap    = soc_camera_g_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap    = soc_camera_s_fmt_vid_cap,
+       .vidioc_enum_input       = soc_camera_enum_input,
+       .vidioc_g_input          = soc_camera_g_input,
+       .vidioc_s_input          = soc_camera_s_input,
+       .vidioc_s_std            = soc_camera_s_std,
+       .vidioc_reqbufs          = soc_camera_reqbufs,
+       .vidioc_try_fmt_vid_cap  = soc_camera_try_fmt_vid_cap,
+       .vidioc_querybuf         = soc_camera_querybuf,
+       .vidioc_qbuf             = soc_camera_qbuf,
+       .vidioc_dqbuf            = soc_camera_dqbuf,
+       .vidioc_streamon         = soc_camera_streamon,
+       .vidioc_streamoff        = soc_camera_streamoff,
+       .vidioc_queryctrl        = soc_camera_queryctrl,
+       .vidioc_g_ctrl           = soc_camera_g_ctrl,
+       .vidioc_s_ctrl           = soc_camera_s_ctrl,
+       .vidioc_cropcap          = soc_camera_cropcap,
+       .vidioc_g_crop           = soc_camera_g_crop,
+       .vidioc_s_crop           = soc_camera_s_crop,
+       .vidioc_g_chip_ident     = soc_camera_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register       = soc_camera_g_register,
+       .vidioc_s_register       = soc_camera_s_register,
+#endif
+};
+
 int soc_camera_video_start(struct soc_camera_device *icd)
 {
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
@@ -877,45 +907,19 @@ int soc_camera_video_start(struct soc_camera_device *icd)
 
        strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
        /* Maybe better &ici->dev */
-       vdev->dev               = &icd->dev;
-       vdev->type              = VID_TYPE_CAPTURE;
+       vdev->parent            = &icd->dev;
        vdev->current_norm      = V4L2_STD_UNKNOWN;
        vdev->fops              = &soc_camera_fops;
+       vdev->ioctl_ops         = &soc_camera_ioctl_ops;
        vdev->release           = video_device_release;
        vdev->minor             = -1;
        vdev->tvnorms           = V4L2_STD_UNKNOWN,
-       vdev->vidioc_querycap   = soc_camera_querycap;
-       vdev->vidioc_g_fmt_vid_cap = soc_camera_g_fmt_vid_cap;
-       vdev->vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap;
-       vdev->vidioc_s_fmt_vid_cap = soc_camera_s_fmt_vid_cap;
-       vdev->vidioc_enum_input = soc_camera_enum_input;
-       vdev->vidioc_g_input    = soc_camera_g_input;
-       vdev->vidioc_s_input    = soc_camera_s_input;
-       vdev->vidioc_s_std      = soc_camera_s_std;
-       vdev->vidioc_reqbufs    = soc_camera_reqbufs;
-       vdev->vidioc_try_fmt_vid_cap = soc_camera_try_fmt_vid_cap;
-       vdev->vidioc_querybuf   = soc_camera_querybuf;
-       vdev->vidioc_qbuf       = soc_camera_qbuf;
-       vdev->vidioc_dqbuf      = soc_camera_dqbuf;
-       vdev->vidioc_streamon   = soc_camera_streamon;
-       vdev->vidioc_streamoff  = soc_camera_streamoff;
-       vdev->vidioc_queryctrl  = soc_camera_queryctrl;
-       vdev->vidioc_g_ctrl     = soc_camera_g_ctrl;
-       vdev->vidioc_s_ctrl     = soc_camera_s_ctrl;
-       vdev->vidioc_cropcap    = soc_camera_cropcap;
-       vdev->vidioc_g_crop     = soc_camera_g_crop;
-       vdev->vidioc_s_crop     = soc_camera_s_crop;
-       vdev->vidioc_g_chip_ident = soc_camera_g_chip_ident;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       vdev->vidioc_g_register = soc_camera_g_register;
-       vdev->vidioc_s_register = soc_camera_s_register;
-#endif
 
        icd->current_fmt = &icd->formats[0];
 
        err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
        if (err < 0) {
-               dev_err(vdev->dev, "video_register_device failed\n");
+               dev_err(vdev->parent, "video_register_device failed\n");
                goto evidregd;
        }
        icd->vdev = vdev;
index f308c38d744fb2e7747328baf339492282ca8beb..ad36af30e0992195fa1f72da85428f394d4251a4 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/vmalloc.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include "stk-webcam.h"
 
@@ -340,17 +341,19 @@ static int stk_create_sysfs_files(struct video_device *vdev)
 {
        int ret;
 
-       ret = video_device_create_file(vdev, &dev_attr_brightness);
-       ret += video_device_create_file(vdev, &dev_attr_hflip);
-       ret += video_device_create_file(vdev, &dev_attr_vflip);
+       ret = device_create_file(&vdev->dev, &dev_attr_brightness);
+       ret += device_create_file(&vdev->dev, &dev_attr_hflip);
+       ret += device_create_file(&vdev->dev, &dev_attr_vflip);
+       if (ret)
+               STK_WARNING("Could not create sysfs files\n");
        return ret;
 }
 
 static void stk_remove_sysfs_files(struct video_device *vdev)
 {
-       video_device_remove_file(vdev, &dev_attr_brightness);
-       video_device_remove_file(vdev, &dev_attr_hflip);
-       video_device_remove_file(vdev, &dev_attr_vflip);
+       device_remove_file(&vdev->dev, &dev_attr_brightness);
+       device_remove_file(&vdev->dev, &dev_attr_hflip);
+       device_remove_file(&vdev->dev, &dev_attr_vflip);
 }
 
 #else
@@ -442,18 +445,19 @@ static void stk_isoc_handler(struct urb *urb)
                                fb->v4lbuf.bytesused = 0;
                                fill = fb->buffer;
                        } else if (fb->v4lbuf.bytesused == dev->frame_size) {
-                               list_move_tail(dev->sio_avail.next,
-                                       &dev->sio_full);
-                               wake_up(&dev->wait_frame);
-                               if (list_empty(&dev->sio_avail)) {
-                                       (void) (printk_ratelimit() &&
-                                       STK_ERROR("No buffer available\n"));
-                                       goto resubmit;
+                               if (list_is_singular(&dev->sio_avail)) {
+                                       /* Always reuse the last buffer */
+                                       fb->v4lbuf.bytesused = 0;
+                                       fill = fb->buffer;
+                               } else {
+                                       list_move_tail(dev->sio_avail.next,
+                                               &dev->sio_full);
+                                       wake_up(&dev->wait_frame);
+                                       fb = list_first_entry(&dev->sio_avail,
+                                               struct stk_sio_buffer, list);
+                                       fb->v4lbuf.bytesused = 0;
+                                       fill = fb->buffer;
                                }
-                               fb = list_first_entry(&dev->sio_avail,
-                                       struct stk_sio_buffer, list);
-                               fb->v4lbuf.bytesused = 0;
-                               fill = fb->buffer;
                        }
                } else {
                        framelen -= 4;
@@ -1327,20 +1331,7 @@ static struct file_operations v4l_stk_fops = {
        .llseek = no_llseek
 };
 
-static void stk_v4l_dev_release(struct video_device *vd)
-{
-}
-
-static struct video_device stk_v4l_data = {
-       .name = "stkwebcam",
-       .type = VFL_TYPE_GRABBER,
-       .type2 = VID_TYPE_CAPTURE,
-       .minor = -1,
-       .tvnorms = V4L2_STD_UNKNOWN,
-       .current_norm = V4L2_STD_UNKNOWN,
-       .fops = &v4l_stk_fops,
-       .release = stk_v4l_dev_release,
-
+static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
        .vidioc_querycap = stk_vidioc_querycap,
        .vidioc_enum_fmt_vid_cap = stk_vidioc_enum_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap = stk_vidioc_try_fmt_vid_cap,
@@ -1362,6 +1353,20 @@ static struct video_device stk_v4l_data = {
        .vidioc_g_parm = stk_vidioc_g_parm,
 };
 
+static void stk_v4l_dev_release(struct video_device *vd)
+{
+}
+
+static struct video_device stk_v4l_data = {
+       .name = "stkwebcam",
+       .minor = -1,
+       .tvnorms = V4L2_STD_UNKNOWN,
+       .current_norm = V4L2_STD_UNKNOWN,
+       .fops = &v4l_stk_fops,
+       .ioctl_ops = &v4l_stk_ioctl_ops,
+       .release = stk_v4l_dev_release,
+};
+
 
 static int stk_register_video_device(struct stk_camera *dev)
 {
@@ -1369,7 +1374,7 @@ static int stk_register_video_device(struct stk_camera *dev)
 
        dev->vdev = stk_v4l_data;
        dev->vdev.debug = debug;
-       dev->vdev.dev = &dev->interface->dev;
+       dev->vdev.parent = &dev->interface->dev;
        dev->vdev.priv = dev;
        err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
        if (err)
index c109511f21ea8a92b307d4ce1596748567c0348f..276bded06ab3eb9ac9b7f9414000b1918d81ce24 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/vmalloc.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include "saa7146.h"
 #include "saa7146reg.h"
@@ -1918,7 +1919,6 @@ static const struct file_operations saa_fops = {
 /* template for video_device-structure */
 static struct video_device saa_template = {
        .name = "SAA7146A",
-       .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
        .fops = &saa_fops,
        .minor = -1,
 };
index d7f130bedb5f47a05f6eddff87634e6af54d25c4..56dc3d6b5b29e6e64d1589f2232577b76be0dba5 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/errno.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 
@@ -524,53 +525,54 @@ static int stv680_create_sysfs_files(struct video_device *vdev)
 {
        int rc;
 
-       rc = video_device_create_file(vdev, &dev_attr_model);
+       rc = device_create_file(&vdev->dev, &dev_attr_model);
        if (rc) goto err;
-       rc = video_device_create_file(vdev, &dev_attr_in_use);
+       rc = device_create_file(&vdev->dev, &dev_attr_in_use);
        if (rc) goto err_model;
-       rc = video_device_create_file(vdev, &dev_attr_streaming);
+       rc = device_create_file(&vdev->dev, &dev_attr_streaming);
        if (rc) goto err_inuse;
-       rc = video_device_create_file(vdev, &dev_attr_palette);
+       rc = device_create_file(&vdev->dev, &dev_attr_palette);
        if (rc) goto err_stream;
-       rc = video_device_create_file(vdev, &dev_attr_frames_total);
+       rc = device_create_file(&vdev->dev, &dev_attr_frames_total);
        if (rc) goto err_pal;
-       rc = video_device_create_file(vdev, &dev_attr_frames_read);
+       rc = device_create_file(&vdev->dev, &dev_attr_frames_read);
        if (rc) goto err_framtot;
-       rc = video_device_create_file(vdev, &dev_attr_packets_dropped);
+       rc = device_create_file(&vdev->dev, &dev_attr_packets_dropped);
        if (rc) goto err_framread;
-       rc = video_device_create_file(vdev, &dev_attr_decoding_errors);
+       rc = device_create_file(&vdev->dev, &dev_attr_decoding_errors);
        if (rc) goto err_dropped;
 
        return 0;
 
 err_dropped:
-       video_device_remove_file(vdev, &dev_attr_packets_dropped);
+       device_remove_file(&vdev->dev, &dev_attr_packets_dropped);
 err_framread:
-       video_device_remove_file(vdev, &dev_attr_frames_read);
+       device_remove_file(&vdev->dev, &dev_attr_frames_read);
 err_framtot:
-       video_device_remove_file(vdev, &dev_attr_frames_total);
+       device_remove_file(&vdev->dev, &dev_attr_frames_total);
 err_pal:
-       video_device_remove_file(vdev, &dev_attr_palette);
+       device_remove_file(&vdev->dev, &dev_attr_palette);
 err_stream:
-       video_device_remove_file(vdev, &dev_attr_streaming);
+       device_remove_file(&vdev->dev, &dev_attr_streaming);
 err_inuse:
-       video_device_remove_file(vdev, &dev_attr_in_use);
+       device_remove_file(&vdev->dev, &dev_attr_in_use);
 err_model:
-       video_device_remove_file(vdev, &dev_attr_model);
+       device_remove_file(&vdev->dev, &dev_attr_model);
 err:
+       PDEBUG(0, "STV(e): Could not create sysfs files");
        return rc;
 }
 
 static void stv680_remove_sysfs_files(struct video_device *vdev)
 {
-       video_device_remove_file(vdev, &dev_attr_model);
-       video_device_remove_file(vdev, &dev_attr_in_use);
-       video_device_remove_file(vdev, &dev_attr_streaming);
-       video_device_remove_file(vdev, &dev_attr_palette);
-       video_device_remove_file(vdev, &dev_attr_frames_total);
-       video_device_remove_file(vdev, &dev_attr_frames_read);
-       video_device_remove_file(vdev, &dev_attr_packets_dropped);
-       video_device_remove_file(vdev, &dev_attr_decoding_errors);
+       device_remove_file(&vdev->dev, &dev_attr_model);
+       device_remove_file(&vdev->dev, &dev_attr_in_use);
+       device_remove_file(&vdev->dev, &dev_attr_streaming);
+       device_remove_file(&vdev->dev, &dev_attr_palette);
+       device_remove_file(&vdev->dev, &dev_attr_frames_total);
+       device_remove_file(&vdev->dev, &dev_attr_frames_read);
+       device_remove_file(&vdev->dev, &dev_attr_packets_dropped);
+       device_remove_file(&vdev->dev, &dev_attr_decoding_errors);
 }
 
 /********************************************************************
@@ -1400,9 +1402,7 @@ static const struct file_operations stv680_fops = {
        .llseek =       no_llseek,
 };
 static struct video_device stv680_template = {
-       .owner =        THIS_MODULE,
        .name =         "STV0680 USB camera",
-       .type =         VID_TYPE_CAPTURE,
        .fops =         &stv680_fops,
        .release =      video_device_release,
        .minor =        -1,
@@ -1454,7 +1454,7 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id
                goto error;
        }
        memcpy(stv680->vdev, &stv680_template, sizeof(stv680_template));
-       stv680->vdev->dev = &intf->dev;
+       stv680->vdev->parent = &intf->dev;
        video_set_drvdata(stv680->vdev, stv680);
 
        memcpy (stv680->vdev->name, stv680->camera_name, strlen (stv680->camera_name));
index ae75c187da79baa0623da0667694aa308a67f015..4963d4264880f6fd8a3d2bc34224c8ad1e6aadb1 100644 (file)
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/i2c.h>
 
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/i2c-addr.h>
 
 #ifndef VIDEO_AUDIO_BALANCE
index 7a8ce8fb46dc88b4b13116a0875b98a28484af16..792f0b079909c31513f06a89bc3183972bb908d8 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
index 9220378a5637b6233cd0ec665f3c9b41e27e3e9d..281065b9dd2df877d0c5425949b729b881f6aa17 100644 (file)
@@ -29,7 +29,7 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-i2c-drv-legacy.h>
 
index 93d879dc510f2b5b0d5e0d148696942cb1cfed17..d806a3556eedd9f48b8ba40fc07ef8bf7417bef2 100644 (file)
@@ -19,6 +19,7 @@
 #include <media/tuner.h>
 #include <media/tuner-types.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/v4l2-i2c-drv-legacy.h>
 #include "mt20xx.h"
 #include "tda8290.h"
index 9da0e1807ffb236619fe8f73f56a72fad5b91526..bcc32fa92a81c68840b503d90eb947a8fe1d83e7 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/i2c.h>
 
 #include <media/tuner.h>
 #include <media/tveeprom.h>
 #include <media/v4l2-common.h>
-#include <media/audiochip.h>
+#include <media/v4l2-chip-ident.h>
 
 MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver");
 MODULE_AUTHOR("John Klar");
@@ -261,70 +261,72 @@ hauppauge_tuner[] =
        { TUNER_ABSENT,                 "MaxLinear MXL5005_v2"},
        { TUNER_PHILIPS_TDA8290,        "Philips 18271_8295"},
        /* 150-159 */
-       { TUNER_ABSENT,        "Xceive XC5000"},
+       { TUNER_ABSENT,                 "Xceive XC5000"},
 };
 
+/* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are
+ * internal to a video chip, i.e. not a separate audio chip. */
 static struct HAUPPAUGE_AUDIOIC
 {
-       enum audiochip  id;
+       u32   id;
        char *name;
 }
 audioIC[] =
 {
        /* 0-4 */
-       {AUDIO_CHIP_NONE,     "None"},
-       {AUDIO_CHIP_TEA6300,  "TEA6300"},
-       {AUDIO_CHIP_TEA6300,  "TEA6320"},
-       {AUDIO_CHIP_TDA985X,  "TDA9850"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3400C"},
+       { V4L2_IDENT_NONE,      "None"      },
+       { V4L2_IDENT_UNKNOWN,   "TEA6300"   },
+       { V4L2_IDENT_UNKNOWN,   "TEA6320"   },
+       { V4L2_IDENT_UNKNOWN,   "TDA9850"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP3400C"  },
        /* 5-9 */
-       {AUDIO_CHIP_MSP34XX,  "MSP3410D"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3415"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3430"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3438"},
-       {AUDIO_CHIP_UNKNOWN,  "CS5331"},
+       { V4L2_IDENT_MSPX4XX,   "MSP3410D"  },
+       { V4L2_IDENT_MSPX4XX,   "MSP3415"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP3430"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP3438"   },
+       { V4L2_IDENT_UNKNOWN,   "CS5331"    },
        /* 10-14 */
-       {AUDIO_CHIP_MSP34XX,  "MSP3435"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3440"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3445"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3411"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3416"},
+       { V4L2_IDENT_MSPX4XX,   "MSP3435"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP3440"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP3445"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP3411"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP3416"   },
        /* 15-19 */
-       {AUDIO_CHIP_MSP34XX,  "MSP3425"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3451"},
-       {AUDIO_CHIP_MSP34XX,  "MSP3418"},
-       {AUDIO_CHIP_UNKNOWN,  "Type 0x12"},
-       {AUDIO_CHIP_UNKNOWN,  "OKI7716"},
+       { V4L2_IDENT_MSPX4XX,   "MSP3425"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP3451"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP3418"   },
+       { V4L2_IDENT_UNKNOWN,   "Type 0x12" },
+       { V4L2_IDENT_UNKNOWN,   "OKI7716"   },
        /* 20-24 */
-       {AUDIO_CHIP_MSP34XX,  "MSP4410"},
-       {AUDIO_CHIP_MSP34XX,  "MSP4420"},
-       {AUDIO_CHIP_MSP34XX,  "MSP4440"},
-       {AUDIO_CHIP_MSP34XX,  "MSP4450"},
-       {AUDIO_CHIP_MSP34XX,  "MSP4408"},
+       { V4L2_IDENT_MSPX4XX,   "MSP4410"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP4420"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP4440"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP4450"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP4408"   },
        /* 25-29 */
-       {AUDIO_CHIP_MSP34XX,  "MSP4418"},
-       {AUDIO_CHIP_MSP34XX,  "MSP4428"},
-       {AUDIO_CHIP_MSP34XX,  "MSP4448"},
-       {AUDIO_CHIP_MSP34XX,  "MSP4458"},
-       {AUDIO_CHIP_MSP34XX,  "Type 0x1d"},
+       { V4L2_IDENT_MSPX4XX,   "MSP4418"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP4428"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP4448"   },
+       { V4L2_IDENT_MSPX4XX,   "MSP4458"   },
+       { V4L2_IDENT_MSPX4XX,   "Type 0x1d" },
        /* 30-34 */
-       {AUDIO_CHIP_INTERNAL, "CX880"},
-       {AUDIO_CHIP_INTERNAL, "CX881"},
-       {AUDIO_CHIP_INTERNAL, "CX883"},
-       {AUDIO_CHIP_INTERNAL, "CX882"},
-       {AUDIO_CHIP_INTERNAL, "CX25840"},
+       { V4L2_IDENT_AMBIGUOUS, "CX880"     },
+       { V4L2_IDENT_AMBIGUOUS, "CX881"     },
+       { V4L2_IDENT_AMBIGUOUS, "CX883"     },
+       { V4L2_IDENT_AMBIGUOUS, "CX882"     },
+       { V4L2_IDENT_AMBIGUOUS, "CX25840"   },
        /* 35-39 */
-       {AUDIO_CHIP_INTERNAL, "CX25841"},
-       {AUDIO_CHIP_INTERNAL, "CX25842"},
-       {AUDIO_CHIP_INTERNAL, "CX25843"},
-       {AUDIO_CHIP_INTERNAL, "CX23418"},
-       {AUDIO_CHIP_INTERNAL, "CX23885"},
+       { V4L2_IDENT_AMBIGUOUS, "CX25841"   },
+       { V4L2_IDENT_AMBIGUOUS, "CX25842"   },
+       { V4L2_IDENT_AMBIGUOUS, "CX25843"   },
+       { V4L2_IDENT_AMBIGUOUS, "CX23418"   },
+       { V4L2_IDENT_AMBIGUOUS, "CX23885"   },
        /* 40-44 */
-       {AUDIO_CHIP_INTERNAL, "CX23888"},
-       {AUDIO_CHIP_INTERNAL, "SAA7131"},
-       {AUDIO_CHIP_INTERNAL, "CX23887"},
-       {AUDIO_CHIP_INTERNAL, "SAA7164"},
-       {AUDIO_CHIP_INTERNAL, "AU8522"},
+       { V4L2_IDENT_AMBIGUOUS, "CX23888"   },
+       { V4L2_IDENT_AMBIGUOUS, "SAA7131"   },
+       { V4L2_IDENT_AMBIGUOUS, "CX23887"   },
+       { V4L2_IDENT_AMBIGUOUS, "SAA7164"   },
+       { V4L2_IDENT_AMBIGUOUS, "AU8522"    },
 };
 
 /* This list is supplied by Hauppauge. Thanks! */
@@ -483,7 +485,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                        tvee->has_radio = eeprom_data[i+len-1];
                        /* old style tag, don't know how to detect
                        IR presence, mark as unknown. */
-                       tvee->has_ir = -1;
+                       tvee->has_ir = 0;
                        tvee->model =
                                eeprom_data[i+8] +
                                (eeprom_data[i+9] << 8);
@@ -509,7 +511,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                        if (audioic < ARRAY_SIZE(audioIC))
                                tvee->audio_processor = audioIC[audioic].id;
                        else
-                               tvee->audio_processor = AUDIO_CHIP_UNKNOWN;
+                               tvee->audio_processor = V4L2_IDENT_UNKNOWN;
                        break;
 
                /* case 0x03: tag 'EEInfo' */
@@ -542,7 +544,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                        if (audioic < ARRAY_SIZE(audioIC))
                                tvee->audio_processor = audioIC[audioic].id;
                        else
-                               tvee->audio_processor = AUDIO_CHIP_UNKNOWN;
+                               tvee->audio_processor = V4L2_IDENT_UNKNOWN;
 
                        break;
 
@@ -603,7 +605,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
 
                case 0x0f:
                        /* tag 'IRInfo' */
-                       tvee->has_ir = eeprom_data[i+1];
+                       tvee->has_ir = 1 | (eeprom_data[i+1] << 1);
                        break;
 
                /* case 0x10: tag 'VBIInfo' */
@@ -690,7 +692,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                        t_fmt_name2[6], t_fmt_name2[7], t_format2);
        if (audioic < 0) {
                tveeprom_info("audio processor is unknown (no idx)\n");
-               tvee->audio_processor = AUDIO_CHIP_UNKNOWN;
+               tvee->audio_processor = V4L2_IDENT_UNKNOWN;
        } else {
                if (audioic < ARRAY_SIZE(audioIC))
                        tveeprom_info("audio processor is %s (idx %d)\n",
@@ -703,14 +705,14 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                tveeprom_info("decoder processor is %s (idx %d)\n",
                        STRM(decoderIC, tvee->decoder_processor),
                        tvee->decoder_processor);
-       if (tvee->has_ir == -1)
-               tveeprom_info("has %sradio\n",
-                               tvee->has_radio ? "" : "no ");
-       else
+       if (tvee->has_ir)
                tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n",
                                tvee->has_radio ? "" : "no ",
-                               (tvee->has_ir & 1) ? "" : "no ",
-                               (tvee->has_ir & 2) ? "" : "no ");
+                               (tvee->has_ir & 2) ? "" : "no ",
+                               (tvee->has_ir & 4) ? "" : "no ");
+       else
+               tveeprom_info("has %sradio\n",
+                               tvee->has_radio ? "" : "no ");
 }
 EXPORT_SYMBOL(tveeprom_hauppauge_analog);
 
index 6a3af1005f03e365f654e826890b7c1b8524474e..28af5ce5560d793305ccddb4ea75d3fc0f02840f 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #include <linux/i2c.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/delay.h>
 #include <linux/video_decoder.h>
 #include <media/v4l2-common.h>
index 4128ee20b64e3eee52db9e720b44d2f143a63f2b..bf1bc2f69b02f727a4cad6ff13cf1f9b46b96a55 100644 (file)
@@ -952,8 +952,6 @@ static const struct file_operations usbvideo_fops = {
        .llseek = no_llseek,
 };
 static const struct video_device usbvideo_template = {
-       .owner =      THIS_MODULE,
-       .type =       VID_TYPE_CAPTURE,
        .fops =       &usbvideo_fops,
 };
 
@@ -1040,7 +1038,7 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
                err("%s: uvd->dev == NULL", __func__);
                return -EINVAL;
        }
-       uvd->vdev.dev = &uvd->dev->dev;
+       uvd->vdev.parent = &uvd->dev->dev;
        if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
                err("%s: video_register_device failed", __func__);
                return -EPIPE;
index 051775d4c72611c89a1a6aeda4ba8260d90e81c0..c66985beb8c9dfdfcf364547af4a5c8d0e413d95 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 
index 40d053e0d5bf85254d5a1e13d841ca7878f66282..b7792451a2993f4d2f0329958e5ab0adefc52a5d 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/videodev.h>
 #include <linux/usb.h>
 #include <linux/vmalloc.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/firmware.h>
@@ -791,9 +792,7 @@ static const struct file_operations vicam_fops = {
 };
 
 static struct video_device vicam_template = {
-       .owner          = THIS_MODULE,
        .name           = "ViCam-based USB Camera",
-       .type           = VID_TYPE_CAPTURE,
        .fops           = &vicam_fops,
        .minor          = -1,
 };
index abf685464b7ca1f3335af4ca40f76fdaea8bf2aa..c317ed7a8482fdbcaf47e5f7e635cc634e1cbee9 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/mm.h>
 #include <linux/utsname.h>
 #include <linux/highmem.h>
-#include <linux/videodev.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -43,7 +42,6 @@
 #include <media/saa7115.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
-#include <media/audiochip.h>
 
 #include <linux/workqueue.h>
 
index cd6c41d67899280d9628e3f4e29fd3e57826866d..b977116a0dd99ccfa6475940c01bb860605dea13 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/mm.h>
 #include <linux/utsname.h>
 #include <linux/highmem.h>
-#include <linux/videodev.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -65,8 +64,8 @@
 
 #include <media/saa7115.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/tuner.h>
-#include <media/audiochip.h>
 
 #include <linux/workqueue.h>
 
@@ -184,7 +183,7 @@ MODULE_ALIAS(DRIVER_ALIAS);
 static inline struct usb_usbvision *cd_to_usbvision(struct device *cd)
 {
        struct video_device *vdev =
-               container_of(cd, struct video_device, class_dev);
+               container_of(cd, struct video_device, dev);
        return video_get_drvdata(vdev);
 }
 
@@ -199,7 +198,7 @@ static ssize_t show_model(struct device *cd,
                          struct device_attribute *attr, char *buf)
 {
        struct video_device *vdev =
-               container_of(cd, struct video_device, class_dev);
+               container_of(cd, struct video_device, dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        return sprintf(buf, "%s\n",
                       usbvision_device_data[usbvision->DevModel].ModelString);
@@ -210,7 +209,7 @@ static ssize_t show_hue(struct device *cd,
                        struct device_attribute *attr, char *buf)
 {
        struct video_device *vdev =
-               container_of(cd, struct video_device, class_dev);
+               container_of(cd, struct video_device, dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        struct v4l2_control ctrl;
        ctrl.id = V4L2_CID_HUE;
@@ -225,7 +224,7 @@ static ssize_t show_contrast(struct device *cd,
                             struct device_attribute *attr, char *buf)
 {
        struct video_device *vdev =
-               container_of(cd, struct video_device, class_dev);
+               container_of(cd, struct video_device, dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        struct v4l2_control ctrl;
        ctrl.id = V4L2_CID_CONTRAST;
@@ -240,7 +239,7 @@ static ssize_t show_brightness(struct device *cd,
                               struct device_attribute *attr, char *buf)
 {
        struct video_device *vdev =
-               container_of(cd, struct video_device, class_dev);
+               container_of(cd, struct video_device, dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        struct v4l2_control ctrl;
        ctrl.id = V4L2_CID_BRIGHTNESS;
@@ -255,7 +254,7 @@ static ssize_t show_saturation(struct device *cd,
                               struct device_attribute *attr, char *buf)
 {
        struct video_device *vdev =
-               container_of(cd, struct video_device, class_dev);
+               container_of(cd, struct video_device, dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        struct v4l2_control ctrl;
        ctrl.id = V4L2_CID_SATURATION;
@@ -270,7 +269,7 @@ static ssize_t show_streaming(struct device *cd,
                              struct device_attribute *attr, char *buf)
 {
        struct video_device *vdev =
-               container_of(cd, struct video_device, class_dev);
+               container_of(cd, struct video_device, dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        return sprintf(buf, "%s\n",
                       YES_NO(usbvision->streaming==Stream_On?1:0));
@@ -281,7 +280,7 @@ static ssize_t show_compression(struct device *cd,
                                struct device_attribute *attr, char *buf)
 {
        struct video_device *vdev =
-               container_of(cd, struct video_device, class_dev);
+               container_of(cd, struct video_device, dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        return sprintf(buf, "%s\n",
                       YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS));
@@ -292,7 +291,7 @@ static ssize_t show_device_bridge(struct device *cd,
                                  struct device_attribute *attr, char *buf)
 {
        struct video_device *vdev =
-               container_of(cd, struct video_device, class_dev);
+               container_of(cd, struct video_device, dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        return sprintf(buf, "%d\n", usbvision->bridgeType);
 }
@@ -304,40 +303,31 @@ static void usbvision_create_sysfs(struct video_device *vdev)
        if (!vdev)
                return;
        do {
-               res = device_create_file(&vdev->class_dev,
-                                        &dev_attr_version);
+               res = device_create_file(&vdev->dev, &dev_attr_version);
                if (res<0)
                        break;
-               res = device_create_file(&vdev->class_dev,
-                                        &dev_attr_model);
+               res = device_create_file(&vdev->dev, &dev_attr_model);
                if (res<0)
                        break;
-               res = device_create_file(&vdev->class_dev,
-                                        &dev_attr_hue);
+               res = device_create_file(&vdev->dev, &dev_attr_hue);
                if (res<0)
                        break;
-               res = device_create_file(&vdev->class_dev,
-                                        &dev_attr_contrast);
+               res = device_create_file(&vdev->dev, &dev_attr_contrast);
                if (res<0)
                        break;
-               res = device_create_file(&vdev->class_dev,
-                                        &dev_attr_brightness);
+               res = device_create_file(&vdev->dev, &dev_attr_brightness);
                if (res<0)
                        break;
-               res = device_create_file(&vdev->class_dev,
-                                        &dev_attr_saturation);
+               res = device_create_file(&vdev->dev, &dev_attr_saturation);
                if (res<0)
                        break;
-               res = device_create_file(&vdev->class_dev,
-                                        &dev_attr_streaming);
+               res = device_create_file(&vdev->dev, &dev_attr_streaming);
                if (res<0)
                        break;
-               res = device_create_file(&vdev->class_dev,
-                                        &dev_attr_compression);
+               res = device_create_file(&vdev->dev, &dev_attr_compression);
                if (res<0)
                        break;
-               res = device_create_file(&vdev->class_dev,
-                                        &dev_attr_bridge);
+               res = device_create_file(&vdev->dev, &dev_attr_bridge);
                if (res>=0)
                        return;
        } while (0);
@@ -348,24 +338,15 @@ static void usbvision_create_sysfs(struct video_device *vdev)
 static void usbvision_remove_sysfs(struct video_device *vdev)
 {
        if (vdev) {
-               device_remove_file(&vdev->class_dev,
-                                        &dev_attr_version);
-               device_remove_file(&vdev->class_dev,
-                                        &dev_attr_model);
-               device_remove_file(&vdev->class_dev,
-                                        &dev_attr_hue);
-               device_remove_file(&vdev->class_dev,
-                                        &dev_attr_contrast);
-               device_remove_file(&vdev->class_dev,
-                                        &dev_attr_brightness);
-               device_remove_file(&vdev->class_dev,
-                                        &dev_attr_saturation);
-               device_remove_file(&vdev->class_dev,
-                                        &dev_attr_streaming);
-               device_remove_file(&vdev->class_dev,
-                                        &dev_attr_compression);
-               device_remove_file(&vdev->class_dev,
-                                        &dev_attr_bridge);
+               device_remove_file(&vdev->dev, &dev_attr_version);
+               device_remove_file(&vdev->dev, &dev_attr_model);
+               device_remove_file(&vdev->dev, &dev_attr_hue);
+               device_remove_file(&vdev->dev, &dev_attr_contrast);
+               device_remove_file(&vdev->dev, &dev_attr_brightness);
+               device_remove_file(&vdev->dev, &dev_attr_saturation);
+               device_remove_file(&vdev->dev, &dev_attr_streaming);
+               device_remove_file(&vdev->dev, &dev_attr_compression);
+               device_remove_file(&vdev->dev, &dev_attr_bridge);
        }
 }
 
@@ -1388,13 +1369,8 @@ static const struct file_operations usbvision_fops = {
 /*     .poll          = video_poll, */
        .compat_ioctl  = v4l_compat_ioctl32,
 };
-static struct video_device usbvision_video_template = {
-       .owner             = THIS_MODULE,
-       .type           = VID_TYPE_TUNER | VID_TYPE_CAPTURE,
-       .fops           = &usbvision_fops,
-       .name           = "usbvision-video",
-       .release        = video_device_release,
-       .minor          = -1,
+
+static const struct v4l2_ioctl_ops usbvision_ioctl_ops = {
        .vidioc_querycap      = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
@@ -1426,6 +1402,14 @@ static struct video_device usbvision_video_template = {
        .vidioc_g_register    = vidioc_g_register,
        .vidioc_s_register    = vidioc_s_register,
 #endif
+};
+
+static struct video_device usbvision_video_template = {
+       .fops           = &usbvision_fops,
+       .ioctl_ops      = &usbvision_ioctl_ops,
+       .name           = "usbvision-video",
+       .release        = video_device_release,
+       .minor          = -1,
        .tvnorms              = USBVISION_NORMS,
        .current_norm         = V4L2_STD_PAL
 };
@@ -1441,14 +1425,7 @@ static const struct file_operations usbvision_radio_fops = {
        .compat_ioctl  = v4l_compat_ioctl32,
 };
 
-static struct video_device usbvision_radio_template=
-{
-       .owner             = THIS_MODULE,
-       .type           = VID_TYPE_TUNER,
-       .fops           = &usbvision_radio_fops,
-       .name           = "usbvision-radio",
-       .release        = video_device_release,
-       .minor          = -1,
+static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = {
        .vidioc_querycap      = vidioc_querycap,
        .vidioc_enum_input    = vidioc_enum_input,
        .vidioc_g_input       = vidioc_g_input,
@@ -1462,6 +1439,14 @@ static struct video_device usbvision_radio_template=
        .vidioc_s_tuner       = vidioc_s_tuner,
        .vidioc_g_frequency   = vidioc_g_frequency,
        .vidioc_s_frequency   = vidioc_s_frequency,
+};
+
+static struct video_device usbvision_radio_template = {
+       .fops           = &usbvision_radio_fops,
+       .name           = "usbvision-radio",
+       .release        = video_device_release,
+       .minor          = -1,
+       .ioctl_ops      = &usbvision_radio_ioctl_ops,
 
        .tvnorms              = USBVISION_NORMS,
        .current_norm         = V4L2_STD_PAL
@@ -1479,8 +1464,6 @@ static const struct file_operations usbvision_vbi_fops = {
 
 static struct video_device usbvision_vbi_template=
 {
-       .owner             = THIS_MODULE,
-       .type           = VID_TYPE_TUNER,
        .fops           = &usbvision_vbi_fops,
        .release        = video_device_release,
        .name           = "usbvision-vbi",
@@ -1506,7 +1489,7 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
        }
        *vdev = *vdev_template;
 //     vdev->minor   = -1;
-       vdev->dev     = &usb_dev->dev;
+       vdev->parent  = &usb_dev->dev;
        snprintf(vdev->name, sizeof(vdev->name), "%s", name);
        video_set_drvdata(vdev, usbvision);
        return vdev;
index 3ae95512666f7685b54da8e495845cb44844a5e6..626f4ad7e876e4496ee7a1a882db79ea4ce7e077 100644 (file)
@@ -195,8 +195,8 @@ static struct uvc_menu_info power_line_frequency_controls[] = {
 };
 
 static struct uvc_menu_info exposure_auto_controls[] = {
-       { 1, "Manual Mode" },
        { 2, "Auto Mode" },
+       { 1, "Manual Mode" },
        { 4, "Shutter Priority Mode" },
        { 8, "Aperture Priority Mode" },
 };
@@ -592,6 +592,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
        if (ctrl == NULL)
                return -EINVAL;
 
+       memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
        v4l2_ctrl->id = mapping->id;
        v4l2_ctrl->type = mapping->v4l2_type;
        strncpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
@@ -608,7 +609,8 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
                v4l2_ctrl->default_value = uvc_get_le_value(data, mapping);
        }
 
-       if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
+       switch (mapping->v4l2_type) {
+       case V4L2_CTRL_TYPE_MENU:
                v4l2_ctrl->minimum = 0;
                v4l2_ctrl->maximum = mapping->menu_count - 1;
                v4l2_ctrl->step = 1;
@@ -622,6 +624,15 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
                }
 
                return 0;
+
+       case V4L2_CTRL_TYPE_BOOLEAN:
+               v4l2_ctrl->minimum = 0;
+               v4l2_ctrl->maximum = 1;
+               v4l2_ctrl->step = 1;
+               return 0;
+
+       default:
+               break;
        }
 
        if (ctrl->info->flags & UVC_CONTROL_GET_MIN) {
index f2b2983fe06270eae97d10f6c1f4a4117a159fa1..b3c4d75e84903a0f2e421544387c5c4258185f7e 100644 (file)
@@ -1458,9 +1458,7 @@ static int uvc_register_video(struct uvc_device *dev)
         * unregistered before the reference is released, so we don't need to
         * get another one.
         */
-       vdev->dev = &dev->intf->dev;
-       vdev->type = 0;
-       vdev->type2 = 0;
+       vdev->parent = &dev->intf->dev;
        vdev->minor = -1;
        vdev->fops = &uvc_fops;
        vdev->release = video_device_release;
index 7388d0cee3d4745c2b9aa415c355a47a49b4df2e..5646a6a329393ca9b2573c6de21f29f92805ba44 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/version.h>
+#include <linux/mm.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/usb.h>
index b5a11eb8f9fa9eb6cb4ff06840770da621092928..d7bd71be40a9d8f76afd3a71c12b5025c714867d 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/atomic.h>
 
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include "uvcvideo.h"
 
index a0f6c60279ece8cb97cc69612889e0a646beae63..79937d1031fc81283baf06abc62c5bc45a4c8409 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
index e9dd996fd5df1f6084930345b076e95a12d16941..88ca1310441767ff7314a546a02a8675b69f2cc5 100644 (file)
@@ -64,7 +64,7 @@
 #include <linux/kmod.h>
 #endif
 
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 
 MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr");
 MODULE_DESCRIPTION("misc helper functions for v4l2 device drivers");
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
new file mode 100644 (file)
index 0000000..556615f
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * Video capture interface for Linux version 2
+ *
+ *     A generic video device interface for the LINUX operating system
+ *     using a set of device structures/vectors for low level operations.
+ *
+ *     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.
+ *
+ * Authors:    Alan Cox, <alan@redhat.com> (version 1)
+ *              Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
+ *
+ * Fixes:      20000516  Claudio Matsuoka <claudio@conectiva.com>
+ *             - Added procfs support
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <media/v4l2-common.h>
+
+#define VIDEO_NUM_DEVICES      256
+#define VIDEO_NAME              "video4linux"
+
+/*
+ *     sysfs stuff
+ */
+
+static ssize_t show_index(struct device *cd,
+                        struct device_attribute *attr, char *buf)
+{
+       struct video_device *vfd = container_of(cd, struct video_device, dev);
+       return sprintf(buf, "%i\n", vfd->index);
+}
+
+static ssize_t show_name(struct device *cd,
+                        struct device_attribute *attr, char *buf)
+{
+       struct video_device *vfd = container_of(cd, struct video_device, dev);
+       return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name);
+}
+
+static struct device_attribute video_device_attrs[] = {
+       __ATTR(name, S_IRUGO, show_name, NULL),
+       __ATTR(index, S_IRUGO, show_index, NULL),
+       __ATTR_NULL
+};
+
+struct video_device *video_device_alloc(void)
+{
+       struct video_device *vfd;
+
+       vfd = kzalloc(sizeof(*vfd), GFP_KERNEL);
+       return vfd;
+}
+EXPORT_SYMBOL(video_device_alloc);
+
+void video_device_release(struct video_device *vfd)
+{
+       kfree(vfd);
+}
+EXPORT_SYMBOL(video_device_release);
+
+static void video_release(struct device *cd)
+{
+       struct video_device *vfd = container_of(cd, struct video_device, dev);
+
+#if 1
+       /* needed until all drivers are fixed */
+       if (!vfd->release)
+               return;
+#endif
+       vfd->release(vfd);
+}
+
+static struct class video_class = {
+       .name = VIDEO_NAME,
+       .dev_attrs = video_device_attrs,
+       .dev_release = video_release,
+};
+
+/*
+ *     Active devices
+ */
+
+static struct video_device *video_device[VIDEO_NUM_DEVICES];
+static DEFINE_MUTEX(videodev_lock);
+
+struct video_device *video_devdata(struct file *file)
+{
+       return video_device[iminor(file->f_path.dentry->d_inode)];
+}
+EXPORT_SYMBOL(video_devdata);
+
+/*
+ *     Open a video device - FIXME: Obsoleted
+ */
+static int video_open(struct inode *inode, struct file *file)
+{
+       unsigned int minor = iminor(inode);
+       int err = 0;
+       struct video_device *vfl;
+       const struct file_operations *old_fops;
+
+       if (minor >= VIDEO_NUM_DEVICES)
+               return -ENODEV;
+       lock_kernel();
+       mutex_lock(&videodev_lock);
+       vfl = video_device[minor];
+       if (vfl == NULL) {
+               mutex_unlock(&videodev_lock);
+               request_module("char-major-%d-%d", VIDEO_MAJOR, minor);
+               mutex_lock(&videodev_lock);
+               vfl = video_device[minor];
+               if (vfl == NULL) {
+                       mutex_unlock(&videodev_lock);
+                       unlock_kernel();
+                       return -ENODEV;
+               }
+       }
+       old_fops = file->f_op;
+       file->f_op = fops_get(vfl->fops);
+       if (file->f_op->open)
+               err = file->f_op->open(inode, file);
+       if (err) {
+               fops_put(file->f_op);
+               file->f_op = fops_get(old_fops);
+       }
+       fops_put(old_fops);
+       mutex_unlock(&videodev_lock);
+       unlock_kernel();
+       return err;
+}
+
+/*
+ * open/release helper functions -- handle exclusive opens
+ * Should be removed soon
+ */
+int video_exclusive_open(struct inode *inode, struct file *file)
+{
+       struct video_device *vfl = video_devdata(file);
+       int retval = 0;
+
+       mutex_lock(&vfl->lock);
+       if (vfl->users)
+               retval = -EBUSY;
+       else
+               vfl->users++;
+       mutex_unlock(&vfl->lock);
+       return retval;
+}
+EXPORT_SYMBOL(video_exclusive_open);
+
+int video_exclusive_release(struct inode *inode, struct file *file)
+{
+       struct video_device *vfl = video_devdata(file);
+
+       vfl->users--;
+       return 0;
+}
+EXPORT_SYMBOL(video_exclusive_release);
+
+/**
+ * get_index - assign stream number based on parent device
+ * @vdev: video_device to assign index number to, vdev->dev should be assigned
+ * @num: -1 if auto assign, requested number otherwise
+ *
+ *
+ * returns -ENFILE if num is already in use, a free index number if
+ * successful.
+ */
+static int get_index(struct video_device *vdev, int num)
+{
+       u32 used = 0;
+       const int max_index = sizeof(used) * 8 - 1;
+       int i;
+
+       /* Currently a single v4l driver instance cannot create more than
+          32 devices.
+          Increase to u64 or an array of u32 if more are needed. */
+       if (num > max_index) {
+               printk(KERN_ERR "videodev: %s num is too large\n", __func__);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
+               if (video_device[i] != NULL &&
+                   video_device[i] != vdev &&
+                   video_device[i]->parent == vdev->parent) {
+                       used |= 1 << video_device[i]->index;
+               }
+       }
+
+       if (num >= 0) {
+               if (used & (1 << num))
+                       return -ENFILE;
+               return num;
+       }
+
+       i = ffz(used);
+       return i > max_index ? -ENFILE : i;
+}
+
+static const struct file_operations video_fops;
+
+int video_register_device(struct video_device *vfd, int type, int nr)
+{
+       return video_register_device_index(vfd, type, nr, -1);
+}
+EXPORT_SYMBOL(video_register_device);
+
+/**
+ *     video_register_device - register video4linux devices
+ *     @vfd:  video device structure we want to register
+ *     @type: type of device to register
+ *     @nr:   which device number (0 == /dev/video0, 1 == /dev/video1, ...
+ *             -1 == first free)
+ *
+ *     The registration code assigns minor numbers based on the type
+ *     requested. -ENFILE is returned in all the device slots for this
+ *     category are full. If not then the minor field is set and the
+ *     driver initialize function is called (if non %NULL).
+ *
+ *     Zero is returned on success.
+ *
+ *     Valid types are
+ *
+ *     %VFL_TYPE_GRABBER - A frame grabber
+ *
+ *     %VFL_TYPE_VTX - A teletext device
+ *
+ *     %VFL_TYPE_VBI - Vertical blank data (undecoded)
+ *
+ *     %VFL_TYPE_RADIO - A radio card
+ */
+
+int video_register_device_index(struct video_device *vfd, int type, int nr,
+                                       int index)
+{
+       int i = 0;
+       int base;
+       int end;
+       int ret;
+       char *name_base;
+
+       switch (type) {
+       case VFL_TYPE_GRABBER:
+               base = MINOR_VFL_TYPE_GRABBER_MIN;
+               end = MINOR_VFL_TYPE_GRABBER_MAX+1;
+               name_base = "video";
+               break;
+       case VFL_TYPE_VTX:
+               base = MINOR_VFL_TYPE_VTX_MIN;
+               end = MINOR_VFL_TYPE_VTX_MAX+1;
+               name_base = "vtx";
+               break;
+       case VFL_TYPE_VBI:
+               base = MINOR_VFL_TYPE_VBI_MIN;
+               end = MINOR_VFL_TYPE_VBI_MAX+1;
+               name_base = "vbi";
+               break;
+       case VFL_TYPE_RADIO:
+               base = MINOR_VFL_TYPE_RADIO_MIN;
+               end = MINOR_VFL_TYPE_RADIO_MAX+1;
+               name_base = "radio";
+               break;
+       default:
+               printk(KERN_ERR "%s called with unknown type: %d\n",
+                      __func__, type);
+               return -1;
+       }
+
+       /* pick a minor number */
+       mutex_lock(&videodev_lock);
+       if (nr >= 0  &&  nr < end-base) {
+               /* use the one the driver asked for */
+               i = base + nr;
+               if (NULL != video_device[i]) {
+                       mutex_unlock(&videodev_lock);
+                       return -ENFILE;
+               }
+       } else {
+               /* use first free */
+               for (i = base; i < end; i++)
+                       if (NULL == video_device[i])
+                               break;
+               if (i == end) {
+                       mutex_unlock(&videodev_lock);
+                       return -ENFILE;
+               }
+       }
+       video_device[i] = vfd;
+       vfd->vfl_type = type;
+       vfd->minor = i;
+
+       ret = get_index(vfd, index);
+       vfd->index = ret;
+
+       mutex_unlock(&videodev_lock);
+
+       if (ret < 0) {
+               printk(KERN_ERR "%s: get_index failed\n", __func__);
+               goto fail_minor;
+       }
+
+       mutex_init(&vfd->lock);
+
+       /* sysfs class */
+       memset(&vfd->dev, 0x00, sizeof(vfd->dev));
+       vfd->dev.class = &video_class;
+       vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
+       if (vfd->parent)
+               vfd->dev.parent = vfd->parent;
+       sprintf(vfd->dev.bus_id, "%s%d", name_base, i - base);
+       ret = device_register(&vfd->dev);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: device_register failed\n", __func__);
+               goto fail_minor;
+       }
+
+#if 1
+       /* needed until all drivers are fixed */
+       if (!vfd->release)
+               printk(KERN_WARNING "videodev: \"%s\" has no release callback. "
+                      "Please fix your driver for proper sysfs support, see "
+                      "http://lwn.net/Articles/36850/\n", vfd->name);
+#endif
+       return 0;
+
+fail_minor:
+       mutex_lock(&videodev_lock);
+       video_device[vfd->minor] = NULL;
+       vfd->minor = -1;
+       mutex_unlock(&videodev_lock);
+       return ret;
+}
+EXPORT_SYMBOL(video_register_device_index);
+
+/**
+ *     video_unregister_device - unregister a video4linux device
+ *     @vfd: the device to unregister
+ *
+ *     This unregisters the passed device and deassigns the minor
+ *     number. Future open calls will be met with errors.
+ */
+
+void video_unregister_device(struct video_device *vfd)
+{
+       mutex_lock(&videodev_lock);
+       if (video_device[vfd->minor] != vfd)
+               panic("videodev: bad unregister");
+
+       video_device[vfd->minor] = NULL;
+       device_unregister(&vfd->dev);
+       mutex_unlock(&videodev_lock);
+}
+EXPORT_SYMBOL(video_unregister_device);
+
+/*
+ * Video fs operations
+ */
+static const struct file_operations video_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .open           = video_open,
+};
+
+/*
+ *     Initialise video for linux
+ */
+
+static int __init videodev_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO "Linux video capture interface: v2.00\n");
+       if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) {
+               printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR);
+               return -EIO;
+       }
+
+       ret = class_register(&video_class);
+       if (ret < 0) {
+               unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
+               printk(KERN_WARNING "video_dev: class_register failed\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static void __exit videodev_exit(void)
+{
+       class_unregister(&video_class);
+       unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
+}
+
+module_init(videodev_init)
+module_exit(videodev_exit)
+
+MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2");
+MODULE_LICENSE("GPL");
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
new file mode 100644 (file)
index 0000000..fdfe773
--- /dev/null
@@ -0,0 +1,1875 @@
+/*
+ * Video capture interface for Linux version 2
+ *
+ * A generic framework to process V4L2 ioctl commands.
+ *
+ * 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.
+ *
+ * Authors:    Alan Cox, <alan@redhat.com> (version 1)
+ *              Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#define __OLD_VIDIOC_ /* To allow fixing old calls */
+#include <linux/videodev2.h>
+
+#ifdef CONFIG_VIDEO_V4L1
+#include <linux/videodev.h>
+#endif
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/video_decoder.h>
+
+#define dbgarg(cmd, fmt, arg...) \
+               do {                                                    \
+                   if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {            \
+                       printk(KERN_DEBUG "%s: ",  vfd->name);          \
+                       v4l_printk_ioctl(cmd);                          \
+                       printk(" " fmt,  ## arg);                       \
+                   }                                                   \
+               } while (0)
+
+#define dbgarg2(fmt, arg...) \
+               do {                                                    \
+                   if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)              \
+                       printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\
+               } while (0)
+
+struct std_descr {
+       v4l2_std_id std;
+       const char *descr;
+};
+
+static const struct std_descr standards[] = {
+       { V4L2_STD_NTSC,        "NTSC"      },
+       { V4L2_STD_NTSC_M,      "NTSC-M"    },
+       { V4L2_STD_NTSC_M_JP,   "NTSC-M-JP" },
+       { V4L2_STD_NTSC_M_KR,   "NTSC-M-KR" },
+       { V4L2_STD_NTSC_443,    "NTSC-443"  },
+       { V4L2_STD_PAL,         "PAL"       },
+       { V4L2_STD_PAL_BG,      "PAL-BG"    },
+       { V4L2_STD_PAL_B,       "PAL-B"     },
+       { V4L2_STD_PAL_B1,      "PAL-B1"    },
+       { V4L2_STD_PAL_G,       "PAL-G"     },
+       { V4L2_STD_PAL_H,       "PAL-H"     },
+       { V4L2_STD_PAL_I,       "PAL-I"     },
+       { V4L2_STD_PAL_DK,      "PAL-DK"    },
+       { V4L2_STD_PAL_D,       "PAL-D"     },
+       { V4L2_STD_PAL_D1,      "PAL-D1"    },
+       { V4L2_STD_PAL_K,       "PAL-K"     },
+       { V4L2_STD_PAL_M,       "PAL-M"     },
+       { V4L2_STD_PAL_N,       "PAL-N"     },
+       { V4L2_STD_PAL_Nc,      "PAL-Nc"    },
+       { V4L2_STD_PAL_60,      "PAL-60"    },
+       { V4L2_STD_SECAM,       "SECAM"     },
+       { V4L2_STD_SECAM_B,     "SECAM-B"   },
+       { V4L2_STD_SECAM_G,     "SECAM-G"   },
+       { V4L2_STD_SECAM_H,     "SECAM-H"   },
+       { V4L2_STD_SECAM_DK,    "SECAM-DK"  },
+       { V4L2_STD_SECAM_D,     "SECAM-D"   },
+       { V4L2_STD_SECAM_K,     "SECAM-K"   },
+       { V4L2_STD_SECAM_K1,    "SECAM-K1"  },
+       { V4L2_STD_SECAM_L,     "SECAM-L"   },
+       { V4L2_STD_SECAM_LC,    "SECAM-Lc"  },
+       { 0,                    "Unknown"   }
+};
+
+/* video4linux standard ID conversion to standard name
+ */
+const char *v4l2_norm_to_name(v4l2_std_id id)
+{
+       u32 myid = id;
+       int i;
+
+       /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
+          64 bit comparations. So, on that architecture, with some gcc
+          variants, compilation fails. Currently, the max value is 30bit wide.
+        */
+       BUG_ON(myid != id);
+
+       for (i = 0; standards[i].std; i++)
+               if (myid == standards[i].std)
+                       break;
+       return standards[i].descr;
+}
+EXPORT_SYMBOL(v4l2_norm_to_name);
+
+/* Fill in the fields of a v4l2_standard structure according to the
+   'id' and 'transmission' parameters.  Returns negative on error.  */
+int v4l2_video_std_construct(struct v4l2_standard *vs,
+                            int id, const char *name)
+{
+       u32 index = vs->index;
+
+       memset(vs, 0, sizeof(struct v4l2_standard));
+       vs->index = index;
+       vs->id    = id;
+       if (id & V4L2_STD_525_60) {
+               vs->frameperiod.numerator = 1001;
+               vs->frameperiod.denominator = 30000;
+               vs->framelines = 525;
+       } else {
+               vs->frameperiod.numerator = 1;
+               vs->frameperiod.denominator = 25;
+               vs->framelines = 625;
+       }
+       strlcpy(vs->name, name, sizeof(vs->name));
+       return 0;
+}
+EXPORT_SYMBOL(v4l2_video_std_construct);
+
+/* ----------------------------------------------------------------- */
+/* some arrays for pretty-printing debug messages of enum types      */
+
+const char *v4l2_field_names[] = {
+       [V4L2_FIELD_ANY]        = "any",
+       [V4L2_FIELD_NONE]       = "none",
+       [V4L2_FIELD_TOP]        = "top",
+       [V4L2_FIELD_BOTTOM]     = "bottom",
+       [V4L2_FIELD_INTERLACED] = "interlaced",
+       [V4L2_FIELD_SEQ_TB]     = "seq-tb",
+       [V4L2_FIELD_SEQ_BT]     = "seq-bt",
+       [V4L2_FIELD_ALTERNATE]  = "alternate",
+       [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
+       [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
+};
+EXPORT_SYMBOL(v4l2_field_names);
+
+const char *v4l2_type_names[] = {
+       [V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "vid-cap",
+       [V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "vid-overlay",
+       [V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "vid-out",
+       [V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
+       [V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
+       [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
+       [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "sliced-vbi-out",
+       [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
+};
+EXPORT_SYMBOL(v4l2_type_names);
+
+static const char *v4l2_memory_names[] = {
+       [V4L2_MEMORY_MMAP]    = "mmap",
+       [V4L2_MEMORY_USERPTR] = "userptr",
+       [V4L2_MEMORY_OVERLAY] = "overlay",
+};
+
+#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
+                          arr[a] : "unknown")
+
+/* ------------------------------------------------------------------ */
+/* debug help functions                                               */
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+static const char *v4l1_ioctls[] = {
+       [_IOC_NR(VIDIOCGCAP)]       = "VIDIOCGCAP",
+       [_IOC_NR(VIDIOCGCHAN)]      = "VIDIOCGCHAN",
+       [_IOC_NR(VIDIOCSCHAN)]      = "VIDIOCSCHAN",
+       [_IOC_NR(VIDIOCGTUNER)]     = "VIDIOCGTUNER",
+       [_IOC_NR(VIDIOCSTUNER)]     = "VIDIOCSTUNER",
+       [_IOC_NR(VIDIOCGPICT)]      = "VIDIOCGPICT",
+       [_IOC_NR(VIDIOCSPICT)]      = "VIDIOCSPICT",
+       [_IOC_NR(VIDIOCCAPTURE)]    = "VIDIOCCAPTURE",
+       [_IOC_NR(VIDIOCGWIN)]       = "VIDIOCGWIN",
+       [_IOC_NR(VIDIOCSWIN)]       = "VIDIOCSWIN",
+       [_IOC_NR(VIDIOCGFBUF)]      = "VIDIOCGFBUF",
+       [_IOC_NR(VIDIOCSFBUF)]      = "VIDIOCSFBUF",
+       [_IOC_NR(VIDIOCKEY)]        = "VIDIOCKEY",
+       [_IOC_NR(VIDIOCGFREQ)]      = "VIDIOCGFREQ",
+       [_IOC_NR(VIDIOCSFREQ)]      = "VIDIOCSFREQ",
+       [_IOC_NR(VIDIOCGAUDIO)]     = "VIDIOCGAUDIO",
+       [_IOC_NR(VIDIOCSAUDIO)]     = "VIDIOCSAUDIO",
+       [_IOC_NR(VIDIOCSYNC)]       = "VIDIOCSYNC",
+       [_IOC_NR(VIDIOCMCAPTURE)]   = "VIDIOCMCAPTURE",
+       [_IOC_NR(VIDIOCGMBUF)]      = "VIDIOCGMBUF",
+       [_IOC_NR(VIDIOCGUNIT)]      = "VIDIOCGUNIT",
+       [_IOC_NR(VIDIOCGCAPTURE)]   = "VIDIOCGCAPTURE",
+       [_IOC_NR(VIDIOCSCAPTURE)]   = "VIDIOCSCAPTURE",
+       [_IOC_NR(VIDIOCSPLAYMODE)]  = "VIDIOCSPLAYMODE",
+       [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE",
+       [_IOC_NR(VIDIOCGPLAYINFO)]  = "VIDIOCGPLAYINFO",
+       [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE",
+       [_IOC_NR(VIDIOCGVBIFMT)]    = "VIDIOCGVBIFMT",
+       [_IOC_NR(VIDIOCSVBIFMT)]    = "VIDIOCSVBIFMT"
+};
+#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
+#endif
+
+static const char *v4l2_ioctls[] = {
+       [_IOC_NR(VIDIOC_QUERYCAP)]         = "VIDIOC_QUERYCAP",
+       [_IOC_NR(VIDIOC_RESERVED)]         = "VIDIOC_RESERVED",
+       [_IOC_NR(VIDIOC_ENUM_FMT)]         = "VIDIOC_ENUM_FMT",
+       [_IOC_NR(VIDIOC_G_FMT)]            = "VIDIOC_G_FMT",
+       [_IOC_NR(VIDIOC_S_FMT)]            = "VIDIOC_S_FMT",
+       [_IOC_NR(VIDIOC_REQBUFS)]          = "VIDIOC_REQBUFS",
+       [_IOC_NR(VIDIOC_QUERYBUF)]         = "VIDIOC_QUERYBUF",
+       [_IOC_NR(VIDIOC_G_FBUF)]           = "VIDIOC_G_FBUF",
+       [_IOC_NR(VIDIOC_S_FBUF)]           = "VIDIOC_S_FBUF",
+       [_IOC_NR(VIDIOC_OVERLAY)]          = "VIDIOC_OVERLAY",
+       [_IOC_NR(VIDIOC_QBUF)]             = "VIDIOC_QBUF",
+       [_IOC_NR(VIDIOC_DQBUF)]            = "VIDIOC_DQBUF",
+       [_IOC_NR(VIDIOC_STREAMON)]         = "VIDIOC_STREAMON",
+       [_IOC_NR(VIDIOC_STREAMOFF)]        = "VIDIOC_STREAMOFF",
+       [_IOC_NR(VIDIOC_G_PARM)]           = "VIDIOC_G_PARM",
+       [_IOC_NR(VIDIOC_S_PARM)]           = "VIDIOC_S_PARM",
+       [_IOC_NR(VIDIOC_G_STD)]            = "VIDIOC_G_STD",
+       [_IOC_NR(VIDIOC_S_STD)]            = "VIDIOC_S_STD",
+       [_IOC_NR(VIDIOC_ENUMSTD)]          = "VIDIOC_ENUMSTD",
+       [_IOC_NR(VIDIOC_ENUMINPUT)]        = "VIDIOC_ENUMINPUT",
+       [_IOC_NR(VIDIOC_G_CTRL)]           = "VIDIOC_G_CTRL",
+       [_IOC_NR(VIDIOC_S_CTRL)]           = "VIDIOC_S_CTRL",
+       [_IOC_NR(VIDIOC_G_TUNER)]          = "VIDIOC_G_TUNER",
+       [_IOC_NR(VIDIOC_S_TUNER)]          = "VIDIOC_S_TUNER",
+       [_IOC_NR(VIDIOC_G_AUDIO)]          = "VIDIOC_G_AUDIO",
+       [_IOC_NR(VIDIOC_S_AUDIO)]          = "VIDIOC_S_AUDIO",
+       [_IOC_NR(VIDIOC_QUERYCTRL)]        = "VIDIOC_QUERYCTRL",
+       [_IOC_NR(VIDIOC_QUERYMENU)]        = "VIDIOC_QUERYMENU",
+       [_IOC_NR(VIDIOC_G_INPUT)]          = "VIDIOC_G_INPUT",
+       [_IOC_NR(VIDIOC_S_INPUT)]          = "VIDIOC_S_INPUT",
+       [_IOC_NR(VIDIOC_G_OUTPUT)]         = "VIDIOC_G_OUTPUT",
+       [_IOC_NR(VIDIOC_S_OUTPUT)]         = "VIDIOC_S_OUTPUT",
+       [_IOC_NR(VIDIOC_ENUMOUTPUT)]       = "VIDIOC_ENUMOUTPUT",
+       [_IOC_NR(VIDIOC_G_AUDOUT)]         = "VIDIOC_G_AUDOUT",
+       [_IOC_NR(VIDIOC_S_AUDOUT)]         = "VIDIOC_S_AUDOUT",
+       [_IOC_NR(VIDIOC_G_MODULATOR)]      = "VIDIOC_G_MODULATOR",
+       [_IOC_NR(VIDIOC_S_MODULATOR)]      = "VIDIOC_S_MODULATOR",
+       [_IOC_NR(VIDIOC_G_FREQUENCY)]      = "VIDIOC_G_FREQUENCY",
+       [_IOC_NR(VIDIOC_S_FREQUENCY)]      = "VIDIOC_S_FREQUENCY",
+       [_IOC_NR(VIDIOC_CROPCAP)]          = "VIDIOC_CROPCAP",
+       [_IOC_NR(VIDIOC_G_CROP)]           = "VIDIOC_G_CROP",
+       [_IOC_NR(VIDIOC_S_CROP)]           = "VIDIOC_S_CROP",
+       [_IOC_NR(VIDIOC_G_JPEGCOMP)]       = "VIDIOC_G_JPEGCOMP",
+       [_IOC_NR(VIDIOC_S_JPEGCOMP)]       = "VIDIOC_S_JPEGCOMP",
+       [_IOC_NR(VIDIOC_QUERYSTD)]         = "VIDIOC_QUERYSTD",
+       [_IOC_NR(VIDIOC_TRY_FMT)]          = "VIDIOC_TRY_FMT",
+       [_IOC_NR(VIDIOC_ENUMAUDIO)]        = "VIDIOC_ENUMAUDIO",
+       [_IOC_NR(VIDIOC_ENUMAUDOUT)]       = "VIDIOC_ENUMAUDOUT",
+       [_IOC_NR(VIDIOC_G_PRIORITY)]       = "VIDIOC_G_PRIORITY",
+       [_IOC_NR(VIDIOC_S_PRIORITY)]       = "VIDIOC_S_PRIORITY",
+       [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
+       [_IOC_NR(VIDIOC_LOG_STATUS)]       = "VIDIOC_LOG_STATUS",
+       [_IOC_NR(VIDIOC_G_EXT_CTRLS)]      = "VIDIOC_G_EXT_CTRLS",
+       [_IOC_NR(VIDIOC_S_EXT_CTRLS)]      = "VIDIOC_S_EXT_CTRLS",
+       [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)]    = "VIDIOC_TRY_EXT_CTRLS",
+#if 1
+       [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)]  = "VIDIOC_ENUM_FRAMESIZES",
+       [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
+       [_IOC_NR(VIDIOC_G_ENC_INDEX)]      = "VIDIOC_G_ENC_INDEX",
+       [_IOC_NR(VIDIOC_ENCODER_CMD)]      = "VIDIOC_ENCODER_CMD",
+       [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)]  = "VIDIOC_TRY_ENCODER_CMD",
+
+       [_IOC_NR(VIDIOC_DBG_S_REGISTER)]   = "VIDIOC_DBG_S_REGISTER",
+       [_IOC_NR(VIDIOC_DBG_G_REGISTER)]   = "VIDIOC_DBG_G_REGISTER",
+
+       [_IOC_NR(VIDIOC_G_CHIP_IDENT)]     = "VIDIOC_G_CHIP_IDENT",
+       [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)]   = "VIDIOC_S_HW_FREQ_SEEK",
+#endif
+};
+#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
+
+static const char *v4l2_int_ioctls[] = {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+       [_IOC_NR(DECODER_GET_CAPABILITIES)]    = "DECODER_GET_CAPABILITIES",
+       [_IOC_NR(DECODER_GET_STATUS)]          = "DECODER_GET_STATUS",
+       [_IOC_NR(DECODER_SET_NORM)]            = "DECODER_SET_NORM",
+       [_IOC_NR(DECODER_SET_INPUT)]           = "DECODER_SET_INPUT",
+       [_IOC_NR(DECODER_SET_OUTPUT)]          = "DECODER_SET_OUTPUT",
+       [_IOC_NR(DECODER_ENABLE_OUTPUT)]       = "DECODER_ENABLE_OUTPUT",
+       [_IOC_NR(DECODER_SET_PICTURE)]         = "DECODER_SET_PICTURE",
+       [_IOC_NR(DECODER_SET_GPIO)]            = "DECODER_SET_GPIO",
+       [_IOC_NR(DECODER_INIT)]                = "DECODER_INIT",
+       [_IOC_NR(DECODER_SET_VBI_BYPASS)]      = "DECODER_SET_VBI_BYPASS",
+       [_IOC_NR(DECODER_DUMP)]                = "DECODER_DUMP",
+#endif
+       [_IOC_NR(AUDC_SET_RADIO)]              = "AUDC_SET_RADIO",
+
+       [_IOC_NR(TUNER_SET_TYPE_ADDR)]         = "TUNER_SET_TYPE_ADDR",
+       [_IOC_NR(TUNER_SET_STANDBY)]           = "TUNER_SET_STANDBY",
+       [_IOC_NR(TUNER_SET_CONFIG)]            = "TUNER_SET_CONFIG",
+
+       [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)]     = "VIDIOC_INT_S_TUNER_MODE",
+       [_IOC_NR(VIDIOC_INT_RESET)]            = "VIDIOC_INT_RESET",
+       [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
+       [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)]  = "VIDIOC_INT_DECODE_VBI_LINE",
+       [_IOC_NR(VIDIOC_INT_S_VBI_DATA)]       = "VIDIOC_INT_S_VBI_DATA",
+       [_IOC_NR(VIDIOC_INT_G_VBI_DATA)]       = "VIDIOC_INT_G_VBI_DATA",
+       [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)]   = "VIDIOC_INT_I2S_CLOCK_FREQ",
+       [_IOC_NR(VIDIOC_INT_S_STANDBY)]        = "VIDIOC_INT_S_STANDBY",
+       [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)]  = "VIDIOC_INT_S_AUDIO_ROUTING",
+       [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)]  = "VIDIOC_INT_G_AUDIO_ROUTING",
+       [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)]  = "VIDIOC_INT_S_VIDEO_ROUTING",
+       [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)]  = "VIDIOC_INT_G_VIDEO_ROUTING",
+       [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)]   = "VIDIOC_INT_S_CRYSTAL_FREQ",
+       [_IOC_NR(VIDIOC_INT_INIT)]             = "VIDIOC_INT_INIT",
+       [_IOC_NR(VIDIOC_INT_G_STD_OUTPUT)]     = "VIDIOC_INT_G_STD_OUTPUT",
+       [_IOC_NR(VIDIOC_INT_S_STD_OUTPUT)]     = "VIDIOC_INT_S_STD_OUTPUT",
+};
+#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
+
+/* Common ioctl debug function. This function can be used by
+   external ioctl messages as well as internal V4L ioctl */
+void v4l_printk_ioctl(unsigned int cmd)
+{
+       char *dir, *type;
+
+       switch (_IOC_TYPE(cmd)) {
+       case 'd':
+               if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) {
+                       type = "v4l2_int";
+                       break;
+               }
+               printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]);
+               return;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+       case 'v':
+               if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
+                       type = "v4l1";
+                       break;
+               }
+               printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
+               return;
+#endif
+       case 'V':
+               if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
+                       type = "v4l2";
+                       break;
+               }
+               printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
+               return;
+       default:
+               type = "unknown";
+       }
+
+       switch (_IOC_DIR(cmd)) {
+       case _IOC_NONE:              dir = "--"; break;
+       case _IOC_READ:              dir = "r-"; break;
+       case _IOC_WRITE:             dir = "-w"; break;
+       case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+       default:                     dir = "*ERR*"; break;
+       }
+       printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
+               type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
+}
+EXPORT_SYMBOL(v4l_printk_ioctl);
+
+/*
+ * helper function -- handles userspace copying for ioctl arguments
+ */
+
+#ifdef __OLD_VIDIOC_
+static unsigned int
+video_fix_command(unsigned int cmd)
+{
+       switch (cmd) {
+       case VIDIOC_OVERLAY_OLD:
+               cmd = VIDIOC_OVERLAY;
+               break;
+       case VIDIOC_S_PARM_OLD:
+               cmd = VIDIOC_S_PARM;
+               break;
+       case VIDIOC_S_CTRL_OLD:
+               cmd = VIDIOC_S_CTRL;
+               break;
+       case VIDIOC_G_AUDIO_OLD:
+               cmd = VIDIOC_G_AUDIO;
+               break;
+       case VIDIOC_G_AUDOUT_OLD:
+               cmd = VIDIOC_G_AUDOUT;
+               break;
+       case VIDIOC_CROPCAP_OLD:
+               cmd = VIDIOC_CROPCAP;
+               break;
+       }
+       return cmd;
+}
+#endif
+
+/*
+ * Obsolete usercopy function - Should be removed soon
+ */
+int
+video_usercopy(struct inode *inode, struct file *file,
+              unsigned int cmd, unsigned long arg,
+              int (*func)(struct inode *inode, struct file *file,
+                          unsigned int cmd, void *arg))
+{
+       char    sbuf[128];
+       void    *mbuf = NULL;
+       void    *parg = NULL;
+       int     err  = -EINVAL;
+       int     is_ext_ctrl;
+       size_t  ctrls_size = 0;
+       void __user *user_ptr = NULL;
+
+#ifdef __OLD_VIDIOC_
+       cmd = video_fix_command(cmd);
+#endif
+       is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
+                      cmd == VIDIOC_TRY_EXT_CTRLS);
+
+       /*  Copy arguments into temp kernel buffer  */
+       switch (_IOC_DIR(cmd)) {
+       case _IOC_NONE:
+               parg = NULL;
+               break;
+       case _IOC_READ:
+       case _IOC_WRITE:
+       case (_IOC_WRITE | _IOC_READ):
+               if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+                       parg = sbuf;
+               } else {
+                       /* too big to allocate from stack */
+                       mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
+                       if (NULL == mbuf)
+                               return -ENOMEM;
+                       parg = mbuf;
+               }
+
+               err = -EFAULT;
+               if (_IOC_DIR(cmd) & _IOC_WRITE)
+                       if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
+                               goto out;
+               break;
+       }
+       if (is_ext_ctrl) {
+               struct v4l2_ext_controls *p = parg;
+
+               /* In case of an error, tell the caller that it wasn't
+                  a specific control that caused it. */
+               p->error_idx = p->count;
+               user_ptr = (void __user *)p->controls;
+               if (p->count) {
+                       ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
+                       /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
+                       mbuf = kmalloc(ctrls_size, GFP_KERNEL);
+                       err = -ENOMEM;
+                       if (NULL == mbuf)
+                               goto out_ext_ctrl;
+                       err = -EFAULT;
+                       if (copy_from_user(mbuf, user_ptr, ctrls_size))
+                               goto out_ext_ctrl;
+                       p->controls = mbuf;
+               }
+       }
+
+       /* call driver */
+       err = func(inode, file, cmd, parg);
+       if (err == -ENOIOCTLCMD)
+               err = -EINVAL;
+       if (is_ext_ctrl) {
+               struct v4l2_ext_controls *p = parg;
+
+               p->controls = (void *)user_ptr;
+               if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
+                       err = -EFAULT;
+               goto out_ext_ctrl;
+       }
+       if (err < 0)
+               goto out;
+
+out_ext_ctrl:
+       /*  Copy results into user buffer  */
+       switch (_IOC_DIR(cmd)) {
+       case _IOC_READ:
+       case (_IOC_WRITE | _IOC_READ):
+               if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
+                       err = -EFAULT;
+               break;
+       }
+
+out:
+       kfree(mbuf);
+       return err;
+}
+EXPORT_SYMBOL(video_usercopy);
+
+static void dbgbuf(unsigned int cmd, struct video_device *vfd,
+                                       struct v4l2_buffer *p)
+{
+       struct v4l2_timecode *tc = &p->timecode;
+
+       dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
+               "bytesused=%d, flags=0x%08d, "
+               "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
+                       p->timestamp.tv_sec / 3600,
+                       (int)(p->timestamp.tv_sec / 60) % 60,
+                       (int)(p->timestamp.tv_sec % 60),
+                       p->timestamp.tv_usec,
+                       p->index,
+                       prt_names(p->type, v4l2_type_names),
+                       p->bytesused, p->flags,
+                       p->field, p->sequence,
+                       prt_names(p->memory, v4l2_memory_names),
+                       p->m.userptr, p->length);
+       dbgarg2("timecode=%02d:%02d:%02d type=%d, "
+               "flags=0x%08d, frames=%d, userbits=0x%08x\n",
+                       tc->hours, tc->minutes, tc->seconds,
+                       tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
+}
+
+static inline void dbgrect(struct video_device *vfd, char *s,
+                                                       struct v4l2_rect *r)
+{
+       dbgarg2("%sRect start at %dx%d, size=%dx%d\n", s, r->left, r->top,
+                                               r->width, r->height);
+};
+
+static inline void v4l_print_pix_fmt(struct video_device *vfd,
+                                               struct v4l2_pix_format *fmt)
+{
+       dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
+               "bytesperline=%d sizeimage=%d, colorspace=%d\n",
+               fmt->width, fmt->height,
+               (fmt->pixelformat & 0xff),
+               (fmt->pixelformat >>  8) & 0xff,
+               (fmt->pixelformat >> 16) & 0xff,
+               (fmt->pixelformat >> 24) & 0xff,
+               prt_names(fmt->field, v4l2_field_names),
+               fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
+};
+
+static inline void v4l_print_ext_ctrls(unsigned int cmd,
+       struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
+{
+       __u32 i;
+
+       if (!(vfd->debug & V4L2_DEBUG_IOCTL_ARG))
+               return;
+       dbgarg(cmd, "");
+       printk(KERN_CONT "class=0x%x", c->ctrl_class);
+       for (i = 0; i < c->count; i++) {
+               if (show_vals)
+                       printk(KERN_CONT " id/val=0x%x/0x%x",
+                               c->controls[i].id, c->controls[i].value);
+               else
+                       printk(KERN_CONT " id=0x%x", c->controls[i].id);
+       }
+       printk(KERN_CONT "\n");
+};
+
+static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
+{
+       __u32 i;
+
+       /* zero the reserved fields */
+       c->reserved[0] = c->reserved[1] = 0;
+       for (i = 0; i < c->count; i++) {
+               c->controls[i].reserved2[0] = 0;
+               c->controls[i].reserved2[1] = 0;
+       }
+       /* V4L2_CID_PRIVATE_BASE cannot be used as control class
+          when using extended controls.
+          Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
+          is it allowed for backwards compatibility.
+        */
+       if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
+               return 0;
+       /* Check that all controls are from the same control class. */
+       for (i = 0; i < c->count; i++) {
+               if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
+                       c->error_idx = i;
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
+{
+       if (ops == NULL)
+               return -EINVAL;
+
+       switch (type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               if (ops->vidioc_try_fmt_vid_cap)
+                       return 0;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+               if (ops->vidioc_try_fmt_vid_overlay)
+                       return 0;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               if (ops->vidioc_try_fmt_vid_out)
+                       return 0;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+               if (ops->vidioc_try_fmt_vid_out_overlay)
+                       return 0;
+               break;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               if (ops->vidioc_try_fmt_vbi_cap)
+                       return 0;
+               break;
+       case V4L2_BUF_TYPE_VBI_OUTPUT:
+               if (ops->vidioc_try_fmt_vbi_out)
+                       return 0;
+               break;
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+               if (ops->vidioc_try_fmt_sliced_vbi_cap)
+                       return 0;
+               break;
+       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+               if (ops->vidioc_try_fmt_sliced_vbi_out)
+                       return 0;
+               break;
+       case V4L2_BUF_TYPE_PRIVATE:
+               if (ops->vidioc_try_fmt_type_private)
+                       return 0;
+               break;
+       }
+       return -EINVAL;
+}
+
+static int __video_do_ioctl(struct inode *inode, struct file *file,
+               unsigned int cmd, void *arg)
+{
+       struct video_device *vfd = video_devdata(file);
+       const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
+       void                 *fh = file->private_data;
+       int                  ret = -EINVAL;
+
+       if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
+                               !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
+               v4l_print_ioctl(vfd->name, cmd);
+               printk(KERN_CONT "\n");
+       }
+
+       if (ops == NULL) {
+               printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n",
+                               vfd->name);
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+       /***********************************************************
+        Handles calls to the obsoleted V4L1 API
+        Due to the nature of VIDIOCGMBUF, each driver that supports
+        V4L1 should implement its own handler for this ioctl.
+        ***********************************************************/
+
+       /* --- streaming capture ------------------------------------- */
+       if (cmd == VIDIOCGMBUF) {
+               struct video_mbuf *p = arg;
+
+               memset(p, 0, sizeof(*p));
+
+               if (!ops->vidiocgmbuf)
+                       return ret;
+               ret = ops->vidiocgmbuf(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
+                                               p->size, p->frames,
+                                               (unsigned long)p->offsets);
+               return ret;
+       }
+
+       /********************************************************
+        All other V4L1 calls are handled by v4l1_compat module.
+        Those calls will be translated into V4L2 calls, and
+        __video_do_ioctl will be called again, with one or more
+        V4L2 ioctls.
+        ********************************************************/
+       if (_IOC_TYPE(cmd) == 'v')
+               return v4l_compat_translate_ioctl(inode, file, cmd, arg,
+                                               __video_do_ioctl);
+#endif
+
+       switch (cmd) {
+       /* --- capabilities ------------------------------------------ */
+       case VIDIOC_QUERYCAP:
+       {
+               struct v4l2_capability *cap = (struct v4l2_capability *)arg;
+               memset(cap, 0, sizeof(*cap));
+
+               if (!ops->vidioc_querycap)
+                       break;
+
+               ret = ops->vidioc_querycap(file, fh, cap);
+               if (!ret)
+                       dbgarg(cmd, "driver=%s, card=%s, bus=%s, "
+                                       "version=0x%08x, "
+                                       "capabilities=0x%08x\n",
+                                       cap->driver, cap->card, cap->bus_info,
+                                       cap->version,
+                                       cap->capabilities);
+               break;
+       }
+
+       /* --- priority ------------------------------------------ */
+       case VIDIOC_G_PRIORITY:
+       {
+               enum v4l2_priority *p = arg;
+
+               if (!ops->vidioc_g_priority)
+                       break;
+               ret = ops->vidioc_g_priority(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "priority is %d\n", *p);
+               break;
+       }
+       case VIDIOC_S_PRIORITY:
+       {
+               enum v4l2_priority *p = arg;
+
+               if (!ops->vidioc_s_priority)
+                       break;
+               dbgarg(cmd, "setting priority to %d\n", *p);
+               ret = ops->vidioc_s_priority(file, fh, *p);
+               break;
+       }
+
+       /* --- capture ioctls ---------------------------------------- */
+       case VIDIOC_ENUM_FMT:
+       {
+               struct v4l2_fmtdesc *f = arg;
+               enum v4l2_buf_type type;
+               unsigned int index;
+
+               index = f->index;
+               type  = f->type;
+               memset(f, 0, sizeof(*f));
+               f->index = index;
+               f->type  = type;
+
+               switch (type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       if (ops->vidioc_enum_fmt_vid_cap)
+                               ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (ops->vidioc_enum_fmt_vid_overlay)
+                               ret = ops->vidioc_enum_fmt_vid_overlay(file,
+                                       fh, f);
+                       break;
+#if 1
+               /* V4L2_BUF_TYPE_VBI_CAPTURE should not support VIDIOC_ENUM_FMT
+                * according to the spec. The bttv and saa7134 drivers support
+                * it though, so just warn that this is deprecated and will be
+                * removed in the near future. */
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       if (ops->vidioc_enum_fmt_vbi_cap) {
+                               printk(KERN_WARNING "vidioc_enum_fmt_vbi_cap will be removed in 2.6.28!\n");
+                               ret = ops->vidioc_enum_fmt_vbi_cap(file, fh, f);
+                       }
+                       break;
+#endif
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       if (ops->vidioc_enum_fmt_vid_out)
+                               ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_PRIVATE:
+                       if (ops->vidioc_enum_fmt_type_private)
+                               ret = ops->vidioc_enum_fmt_type_private(file,
+                                                               fh, f);
+                       break;
+               default:
+                       break;
+               }
+               if (!ret)
+                       dbgarg(cmd, "index=%d, type=%d, flags=%d, "
+                               "pixelformat=%c%c%c%c, description='%s'\n",
+                               f->index, f->type, f->flags,
+                               (f->pixelformat & 0xff),
+                               (f->pixelformat >>  8) & 0xff,
+                               (f->pixelformat >> 16) & 0xff,
+                               (f->pixelformat >> 24) & 0xff,
+                               f->description);
+               break;
+       }
+       case VIDIOC_G_FMT:
+       {
+               struct v4l2_format *f = (struct v4l2_format *)arg;
+
+               memset(f->fmt.raw_data, 0, sizeof(f->fmt.raw_data));
+
+               /* FIXME: Should be one dump per type */
+               dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
+
+               switch (f->type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       if (ops->vidioc_g_fmt_vid_cap)
+                               ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
+                       if (!ret)
+                               v4l_print_pix_fmt(vfd, &f->fmt.pix);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (ops->vidioc_g_fmt_vid_overlay)
+                               ret = ops->vidioc_g_fmt_vid_overlay(file,
+                                                                   fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       if (ops->vidioc_g_fmt_vid_out)
+                               ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
+                       if (!ret)
+                               v4l_print_pix_fmt(vfd, &f->fmt.pix);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+                       if (ops->vidioc_g_fmt_vid_out_overlay)
+                               ret = ops->vidioc_g_fmt_vid_out_overlay(file,
+                                      fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       if (ops->vidioc_g_fmt_vbi_cap)
+                               ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_OUTPUT:
+                       if (ops->vidioc_g_fmt_vbi_out)
+                               ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+                       if (ops->vidioc_g_fmt_sliced_vbi_cap)
+                               ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,
+                                                                       fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+                       if (ops->vidioc_g_fmt_sliced_vbi_out)
+                               ret = ops->vidioc_g_fmt_sliced_vbi_out(file,
+                                                                       fh, f);
+                       break;
+               case V4L2_BUF_TYPE_PRIVATE:
+                       if (ops->vidioc_g_fmt_type_private)
+                               ret = ops->vidioc_g_fmt_type_private(file,
+                                                               fh, f);
+                       break;
+               }
+
+               break;
+       }
+       case VIDIOC_S_FMT:
+       {
+               struct v4l2_format *f = (struct v4l2_format *)arg;
+
+               /* FIXME: Should be one dump per type */
+               dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
+
+               switch (f->type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       v4l_print_pix_fmt(vfd, &f->fmt.pix);
+                       if (ops->vidioc_s_fmt_vid_cap)
+                               ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (ops->vidioc_s_fmt_vid_overlay)
+                               ret = ops->vidioc_s_fmt_vid_overlay(file,
+                                                                   fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       v4l_print_pix_fmt(vfd, &f->fmt.pix);
+                       if (ops->vidioc_s_fmt_vid_out)
+                               ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+                       if (ops->vidioc_s_fmt_vid_out_overlay)
+                               ret = ops->vidioc_s_fmt_vid_out_overlay(file,
+                                       fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       if (ops->vidioc_s_fmt_vbi_cap)
+                               ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_OUTPUT:
+                       if (ops->vidioc_s_fmt_vbi_out)
+                               ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+                       if (ops->vidioc_s_fmt_sliced_vbi_cap)
+                               ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
+                                                                       fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+                       if (ops->vidioc_s_fmt_sliced_vbi_out)
+                               ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
+                                                                       fh, f);
+                       break;
+               case V4L2_BUF_TYPE_PRIVATE:
+                       if (ops->vidioc_s_fmt_type_private)
+                               ret = ops->vidioc_s_fmt_type_private(file,
+                                                               fh, f);
+                       break;
+               }
+               break;
+       }
+       case VIDIOC_TRY_FMT:
+       {
+               struct v4l2_format *f = (struct v4l2_format *)arg;
+
+               /* FIXME: Should be one dump per type */
+               dbgarg(cmd, "type=%s\n", prt_names(f->type,
+                                               v4l2_type_names));
+               switch (f->type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       if (ops->vidioc_try_fmt_vid_cap)
+                               ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
+                       if (!ret)
+                               v4l_print_pix_fmt(vfd, &f->fmt.pix);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (ops->vidioc_try_fmt_vid_overlay)
+                               ret = ops->vidioc_try_fmt_vid_overlay(file,
+                                       fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       if (ops->vidioc_try_fmt_vid_out)
+                               ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
+                       if (!ret)
+                               v4l_print_pix_fmt(vfd, &f->fmt.pix);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+                       if (ops->vidioc_try_fmt_vid_out_overlay)
+                               ret = ops->vidioc_try_fmt_vid_out_overlay(file,
+                                      fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       if (ops->vidioc_try_fmt_vbi_cap)
+                               ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_OUTPUT:
+                       if (ops->vidioc_try_fmt_vbi_out)
+                               ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+                       if (ops->vidioc_try_fmt_sliced_vbi_cap)
+                               ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+                       if (ops->vidioc_try_fmt_sliced_vbi_out)
+                               ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_PRIVATE:
+                       if (ops->vidioc_try_fmt_type_private)
+                               ret = ops->vidioc_try_fmt_type_private(file,
+                                                               fh, f);
+                       break;
+               }
+
+               break;
+       }
+       /* FIXME: Those buf reqs could be handled here,
+          with some changes on videobuf to allow its header to be included at
+          videodev2.h or being merged at videodev2.
+        */
+       case VIDIOC_REQBUFS:
+       {
+               struct v4l2_requestbuffers *p = arg;
+
+               if (!ops->vidioc_reqbufs)
+                       break;
+               ret = check_fmt(ops, p->type);
+               if (ret)
+                       break;
+
+               ret = ops->vidioc_reqbufs(file, fh, p);
+               dbgarg(cmd, "count=%d, type=%s, memory=%s\n",
+                               p->count,
+                               prt_names(p->type, v4l2_type_names),
+                               prt_names(p->memory, v4l2_memory_names));
+               break;
+       }
+       case VIDIOC_QUERYBUF:
+       {
+               struct v4l2_buffer *p = arg;
+
+               if (!ops->vidioc_querybuf)
+                       break;
+               ret = check_fmt(ops, p->type);
+               if (ret)
+                       break;
+
+               ret = ops->vidioc_querybuf(file, fh, p);
+               if (!ret)
+                       dbgbuf(cmd, vfd, p);
+               break;
+       }
+       case VIDIOC_QBUF:
+       {
+               struct v4l2_buffer *p = arg;
+
+               if (!ops->vidioc_qbuf)
+                       break;
+               ret = check_fmt(ops, p->type);
+               if (ret)
+                       break;
+
+               ret = ops->vidioc_qbuf(file, fh, p);
+               if (!ret)
+                       dbgbuf(cmd, vfd, p);
+               break;
+       }
+       case VIDIOC_DQBUF:
+       {
+               struct v4l2_buffer *p = arg;
+
+               if (!ops->vidioc_dqbuf)
+                       break;
+               ret = check_fmt(ops, p->type);
+               if (ret)
+                       break;
+
+               ret = ops->vidioc_dqbuf(file, fh, p);
+               if (!ret)
+                       dbgbuf(cmd, vfd, p);
+               break;
+       }
+       case VIDIOC_OVERLAY:
+       {
+               int *i = arg;
+
+               if (!ops->vidioc_overlay)
+                       break;
+               dbgarg(cmd, "value=%d\n", *i);
+               ret = ops->vidioc_overlay(file, fh, *i);
+               break;
+       }
+       case VIDIOC_G_FBUF:
+       {
+               struct v4l2_framebuffer *p = arg;
+
+               if (!ops->vidioc_g_fbuf)
+                       break;
+               ret = ops->vidioc_g_fbuf(file, fh, arg);
+               if (!ret) {
+                       dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
+                                       p->capability, p->flags,
+                                       (unsigned long)p->base);
+                       v4l_print_pix_fmt(vfd, &p->fmt);
+               }
+               break;
+       }
+       case VIDIOC_S_FBUF:
+       {
+               struct v4l2_framebuffer *p = arg;
+
+               if (!ops->vidioc_s_fbuf)
+                       break;
+               dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
+                       p->capability, p->flags, (unsigned long)p->base);
+               v4l_print_pix_fmt(vfd, &p->fmt);
+               ret = ops->vidioc_s_fbuf(file, fh, arg);
+               break;
+       }
+       case VIDIOC_STREAMON:
+       {
+               enum v4l2_buf_type i = *(int *)arg;
+
+               if (!ops->vidioc_streamon)
+                       break;
+               dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
+               ret = ops->vidioc_streamon(file, fh, i);
+               break;
+       }
+       case VIDIOC_STREAMOFF:
+       {
+               enum v4l2_buf_type i = *(int *)arg;
+
+               if (!ops->vidioc_streamoff)
+                       break;
+               dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
+               ret = ops->vidioc_streamoff(file, fh, i);
+               break;
+       }
+       /* ---------- tv norms ---------- */
+       case VIDIOC_ENUMSTD:
+       {
+               struct v4l2_standard *p = arg;
+               v4l2_std_id id = vfd->tvnorms, curr_id = 0;
+               unsigned int index = p->index, i, j = 0;
+               const char *descr = "";
+
+               /* Return norm array in a canonical way */
+               for (i = 0; i <= index && id; i++) {
+                       /* last std value in the standards array is 0, so this
+                          while always ends there since (id & 0) == 0. */
+                       while ((id & standards[j].std) != standards[j].std)
+                               j++;
+                       curr_id = standards[j].std;
+                       descr = standards[j].descr;
+                       j++;
+                       if (curr_id == 0)
+                               break;
+                       if (curr_id != V4L2_STD_PAL &&
+                           curr_id != V4L2_STD_SECAM &&
+                           curr_id != V4L2_STD_NTSC)
+                               id &= ~curr_id;
+               }
+               if (i <= index)
+                       return -EINVAL;
+
+               v4l2_video_std_construct(p, curr_id, descr);
+               p->index = index;
+
+               dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
+                               "framelines=%d\n", p->index,
+                               (unsigned long long)p->id, p->name,
+                               p->frameperiod.numerator,
+                               p->frameperiod.denominator,
+                               p->framelines);
+
+               ret = 0;
+               break;
+       }
+       case VIDIOC_G_STD:
+       {
+               v4l2_std_id *id = arg;
+
+               ret = 0;
+               /* Calls the specific handler */
+               if (ops->vidioc_g_std)
+                       ret = ops->vidioc_g_std(file, fh, id);
+               else
+                       *id = vfd->current_norm;
+
+               if (!ret)
+                       dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
+               break;
+       }
+       case VIDIOC_S_STD:
+       {
+               v4l2_std_id *id = arg, norm;
+
+               dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
+
+               norm = (*id) & vfd->tvnorms;
+               if (vfd->tvnorms && !norm)      /* Check if std is supported */
+                       break;
+
+               /* Calls the specific handler */
+               if (ops->vidioc_s_std)
+                       ret = ops->vidioc_s_std(file, fh, &norm);
+               else
+                       ret = -EINVAL;
+
+               /* Updates standard information */
+               if (ret >= 0)
+                       vfd->current_norm = norm;
+               break;
+       }
+       case VIDIOC_QUERYSTD:
+       {
+               v4l2_std_id *p = arg;
+
+               if (!ops->vidioc_querystd)
+                       break;
+               ret = ops->vidioc_querystd(file, fh, arg);
+               if (!ret)
+                       dbgarg(cmd, "detected std=%08Lx\n",
+                                               (unsigned long long)*p);
+               break;
+       }
+       /* ------ input switching ---------- */
+       /* FIXME: Inputs can be handled inside videodev2 */
+       case VIDIOC_ENUMINPUT:
+       {
+               struct v4l2_input *p = arg;
+               int i = p->index;
+
+               if (!ops->vidioc_enum_input)
+                       break;
+               memset(p, 0, sizeof(*p));
+               p->index = i;
+
+               ret = ops->vidioc_enum_input(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "index=%d, name=%s, type=%d, "
+                               "audioset=%d, "
+                               "tuner=%d, std=%08Lx, status=%d\n",
+                               p->index, p->name, p->type, p->audioset,
+                               p->tuner,
+                               (unsigned long long)p->std,
+                               p->status);
+               break;
+       }
+       case VIDIOC_G_INPUT:
+       {
+               unsigned int *i = arg;
+
+               if (!ops->vidioc_g_input)
+                       break;
+               ret = ops->vidioc_g_input(file, fh, i);
+               if (!ret)
+                       dbgarg(cmd, "value=%d\n", *i);
+               break;
+       }
+       case VIDIOC_S_INPUT:
+       {
+               unsigned int *i = arg;
+
+               if (!ops->vidioc_s_input)
+                       break;
+               dbgarg(cmd, "value=%d\n", *i);
+               ret = ops->vidioc_s_input(file, fh, *i);
+               break;
+       }
+
+       /* ------ output switching ---------- */
+       case VIDIOC_ENUMOUTPUT:
+       {
+               struct v4l2_output *p = arg;
+               int i = p->index;
+
+               if (!ops->vidioc_enum_output)
+                       break;
+               memset(p, 0, sizeof(*p));
+               p->index = i;
+
+               ret = ops->vidioc_enum_output(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "index=%d, name=%s, type=%d, "
+                               "audioset=0x%x, "
+                               "modulator=%d, std=0x%08Lx\n",
+                               p->index, p->name, p->type, p->audioset,
+                               p->modulator, (unsigned long long)p->std);
+               break;
+       }
+       case VIDIOC_G_OUTPUT:
+       {
+               unsigned int *i = arg;
+
+               if (!ops->vidioc_g_output)
+                       break;
+               ret = ops->vidioc_g_output(file, fh, i);
+               if (!ret)
+                       dbgarg(cmd, "value=%d\n", *i);
+               break;
+       }
+       case VIDIOC_S_OUTPUT:
+       {
+               unsigned int *i = arg;
+
+               if (!ops->vidioc_s_output)
+                       break;
+               dbgarg(cmd, "value=%d\n", *i);
+               ret = ops->vidioc_s_output(file, fh, *i);
+               break;
+       }
+
+       /* --- controls ---------------------------------------------- */
+       case VIDIOC_QUERYCTRL:
+       {
+               struct v4l2_queryctrl *p = arg;
+
+               if (!ops->vidioc_queryctrl)
+                       break;
+               ret = ops->vidioc_queryctrl(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, "
+                                       "step=%d, default=%d, flags=0x%08x\n",
+                                       p->id, p->type, p->name,
+                                       p->minimum, p->maximum,
+                                       p->step, p->default_value, p->flags);
+               else
+                       dbgarg(cmd, "id=0x%x\n", p->id);
+               break;
+       }
+       case VIDIOC_G_CTRL:
+       {
+               struct v4l2_control *p = arg;
+
+               if (ops->vidioc_g_ctrl)
+                       ret = ops->vidioc_g_ctrl(file, fh, p);
+               else if (ops->vidioc_g_ext_ctrls) {
+                       struct v4l2_ext_controls ctrls;
+                       struct v4l2_ext_control ctrl;
+
+                       ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
+                       ctrls.count = 1;
+                       ctrls.controls = &ctrl;
+                       ctrl.id = p->id;
+                       ctrl.value = p->value;
+                       if (check_ext_ctrls(&ctrls, 1)) {
+                               ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
+                               if (ret == 0)
+                                       p->value = ctrl.value;
+                       }
+               } else
+                       break;
+               if (!ret)
+                       dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
+               else
+                       dbgarg(cmd, "id=0x%x\n", p->id);
+               break;
+       }
+       case VIDIOC_S_CTRL:
+       {
+               struct v4l2_control *p = arg;
+               struct v4l2_ext_controls ctrls;
+               struct v4l2_ext_control ctrl;
+
+               if (!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
+                       break;
+
+               dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
+
+               if (ops->vidioc_s_ctrl) {
+                       ret = ops->vidioc_s_ctrl(file, fh, p);
+                       break;
+               }
+               if (!ops->vidioc_s_ext_ctrls)
+                       break;
+
+               ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
+               ctrls.count = 1;
+               ctrls.controls = &ctrl;
+               ctrl.id = p->id;
+               ctrl.value = p->value;
+               if (check_ext_ctrls(&ctrls, 1))
+                       ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
+               break;
+       }
+       case VIDIOC_G_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *p = arg;
+
+               p->error_idx = p->count;
+               if (!ops->vidioc_g_ext_ctrls)
+                       break;
+               if (check_ext_ctrls(p, 0))
+                       ret = ops->vidioc_g_ext_ctrls(file, fh, p);
+               v4l_print_ext_ctrls(cmd, vfd, p, !ret);
+               break;
+       }
+       case VIDIOC_S_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *p = arg;
+
+               p->error_idx = p->count;
+               if (!ops->vidioc_s_ext_ctrls)
+                       break;
+               v4l_print_ext_ctrls(cmd, vfd, p, 1);
+               if (check_ext_ctrls(p, 0))
+                       ret = ops->vidioc_s_ext_ctrls(file, fh, p);
+               break;
+       }
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *p = arg;
+
+               p->error_idx = p->count;
+               if (!ops->vidioc_try_ext_ctrls)
+                       break;
+               v4l_print_ext_ctrls(cmd, vfd, p, 1);
+               if (check_ext_ctrls(p, 0))
+                       ret = ops->vidioc_try_ext_ctrls(file, fh, p);
+               break;
+       }
+       case VIDIOC_QUERYMENU:
+       {
+               struct v4l2_querymenu *p = arg;
+
+               if (!ops->vidioc_querymenu)
+                       break;
+               ret = ops->vidioc_querymenu(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",
+                               p->id, p->index, p->name);
+               else
+                       dbgarg(cmd, "id=0x%x, index=%d\n",
+                               p->id, p->index);
+               break;
+       }
+       /* --- audio ---------------------------------------------- */
+       case VIDIOC_ENUMAUDIO:
+       {
+               struct v4l2_audio *p = arg;
+
+               if (!ops->vidioc_enumaudio)
+                       break;
+               ret = ops->vidioc_enumaudio(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
+                                       "mode=0x%x\n", p->index, p->name,
+                                       p->capability, p->mode);
+               else
+                       dbgarg(cmd, "index=%d\n", p->index);
+               break;
+       }
+       case VIDIOC_G_AUDIO:
+       {
+               struct v4l2_audio *p = arg;
+               __u32 index = p->index;
+
+               if (!ops->vidioc_g_audio)
+                       break;
+
+               memset(p, 0, sizeof(*p));
+               p->index = index;
+               ret = ops->vidioc_g_audio(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
+                                       "mode=0x%x\n", p->index,
+                                       p->name, p->capability, p->mode);
+               else
+                       dbgarg(cmd, "index=%d\n", p->index);
+               break;
+       }
+       case VIDIOC_S_AUDIO:
+       {
+               struct v4l2_audio *p = arg;
+
+               if (!ops->vidioc_s_audio)
+                       break;
+               dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
+                                       "mode=0x%x\n", p->index, p->name,
+                                       p->capability, p->mode);
+               ret = ops->vidioc_s_audio(file, fh, p);
+               break;
+       }
+       case VIDIOC_ENUMAUDOUT:
+       {
+               struct v4l2_audioout *p = arg;
+
+               if (!ops->vidioc_enumaudout)
+                       break;
+               dbgarg(cmd, "Enum for index=%d\n", p->index);
+               ret = ops->vidioc_enumaudout(file, fh, p);
+               if (!ret)
+                       dbgarg2("index=%d, name=%s, capability=%d, "
+                                       "mode=%d\n", p->index, p->name,
+                                       p->capability, p->mode);
+               break;
+       }
+       case VIDIOC_G_AUDOUT:
+       {
+               struct v4l2_audioout *p = arg;
+
+               if (!ops->vidioc_g_audout)
+                       break;
+               dbgarg(cmd, "Enum for index=%d\n", p->index);
+               ret = ops->vidioc_g_audout(file, fh, p);
+               if (!ret)
+                       dbgarg2("index=%d, name=%s, capability=%d, "
+                                       "mode=%d\n", p->index, p->name,
+                                       p->capability, p->mode);
+               break;
+       }
+       case VIDIOC_S_AUDOUT:
+       {
+               struct v4l2_audioout *p = arg;
+
+               if (!ops->vidioc_s_audout)
+                       break;
+               dbgarg(cmd, "index=%d, name=%s, capability=%d, "
+                                       "mode=%d\n", p->index, p->name,
+                                       p->capability, p->mode);
+
+               ret = ops->vidioc_s_audout(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_MODULATOR:
+       {
+               struct v4l2_modulator *p = arg;
+
+               if (!ops->vidioc_g_modulator)
+                       break;
+               ret = ops->vidioc_g_modulator(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "index=%d, name=%s, "
+                                       "capability=%d, rangelow=%d,"
+                                       " rangehigh=%d, txsubchans=%d\n",
+                                       p->index, p->name, p->capability,
+                                       p->rangelow, p->rangehigh,
+                                       p->txsubchans);
+               break;
+       }
+       case VIDIOC_S_MODULATOR:
+       {
+               struct v4l2_modulator *p = arg;
+
+               if (!ops->vidioc_s_modulator)
+                       break;
+               dbgarg(cmd, "index=%d, name=%s, capability=%d, "
+                               "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
+                               p->index, p->name, p->capability, p->rangelow,
+                               p->rangehigh, p->txsubchans);
+                       ret = ops->vidioc_s_modulator(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_CROP:
+       {
+               struct v4l2_crop *p = arg;
+
+               if (!ops->vidioc_g_crop)
+                       break;
+               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
+               ret = ops->vidioc_g_crop(file, fh, p);
+               if (!ret)
+                       dbgrect(vfd, "", &p->c);
+               break;
+       }
+       case VIDIOC_S_CROP:
+       {
+               struct v4l2_crop *p = arg;
+
+               if (!ops->vidioc_s_crop)
+                       break;
+               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
+               dbgrect(vfd, "", &p->c);
+               ret = ops->vidioc_s_crop(file, fh, p);
+               break;
+       }
+       case VIDIOC_CROPCAP:
+       {
+               struct v4l2_cropcap *p = arg;
+
+               /*FIXME: Should also show v4l2_fract pixelaspect */
+               if (!ops->vidioc_cropcap)
+                       break;
+               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
+               ret = ops->vidioc_cropcap(file, fh, p);
+               if (!ret) {
+                       dbgrect(vfd, "bounds ", &p->bounds);
+                       dbgrect(vfd, "defrect ", &p->defrect);
+               }
+               break;
+       }
+       case VIDIOC_G_JPEGCOMP:
+       {
+               struct v4l2_jpegcompression *p = arg;
+
+               if (!ops->vidioc_g_jpegcomp)
+                       break;
+               ret = ops->vidioc_g_jpegcomp(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "quality=%d, APPn=%d, "
+                                       "APP_len=%d, COM_len=%d, "
+                                       "jpeg_markers=%d\n",
+                                       p->quality, p->APPn, p->APP_len,
+                                       p->COM_len, p->jpeg_markers);
+               break;
+       }
+       case VIDIOC_S_JPEGCOMP:
+       {
+               struct v4l2_jpegcompression *p = arg;
+
+               if (!ops->vidioc_g_jpegcomp)
+                       break;
+               dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
+                                       "COM_len=%d, jpeg_markers=%d\n",
+                                       p->quality, p->APPn, p->APP_len,
+                                       p->COM_len, p->jpeg_markers);
+                       ret = ops->vidioc_s_jpegcomp(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_ENC_INDEX:
+       {
+               struct v4l2_enc_idx *p = arg;
+
+               if (!ops->vidioc_g_enc_index)
+                       break;
+               ret = ops->vidioc_g_enc_index(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "entries=%d, entries_cap=%d\n",
+                                       p->entries, p->entries_cap);
+               break;
+       }
+       case VIDIOC_ENCODER_CMD:
+       {
+               struct v4l2_encoder_cmd *p = arg;
+
+               if (!ops->vidioc_encoder_cmd)
+                       break;
+               memset(&p->raw, 0, sizeof(p->raw));
+               ret = ops->vidioc_encoder_cmd(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
+               break;
+       }
+       case VIDIOC_TRY_ENCODER_CMD:
+       {
+               struct v4l2_encoder_cmd *p = arg;
+
+               if (!ops->vidioc_try_encoder_cmd)
+                       break;
+               memset(&p->raw, 0, sizeof(p->raw));
+               ret = ops->vidioc_try_encoder_cmd(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
+               break;
+       }
+       case VIDIOC_G_PARM:
+       {
+               struct v4l2_streamparm *p = arg;
+               __u32 type = p->type;
+
+               memset(p, 0, sizeof(*p));
+               p->type = type;
+
+               if (ops->vidioc_g_parm) {
+                       ret = ops->vidioc_g_parm(file, fh, p);
+               } else {
+                       struct v4l2_standard s;
+
+                       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+
+                       v4l2_video_std_construct(&s, vfd->current_norm,
+                                                v4l2_norm_to_name(vfd->current_norm));
+
+                       p->parm.capture.timeperframe = s.frameperiod;
+                       ret = 0;
+               }
+
+               dbgarg(cmd, "type=%d\n", p->type);
+               break;
+       }
+       case VIDIOC_S_PARM:
+       {
+               struct v4l2_streamparm *p = arg;
+
+               if (!ops->vidioc_s_parm)
+                       break;
+               dbgarg(cmd, "type=%d\n", p->type);
+               ret = ops->vidioc_s_parm(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_TUNER:
+       {
+               struct v4l2_tuner *p = arg;
+               __u32 index = p->index;
+
+               if (!ops->vidioc_g_tuner)
+                       break;
+
+               memset(p, 0, sizeof(*p));
+               p->index = index;
+
+               ret = ops->vidioc_g_tuner(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "index=%d, name=%s, type=%d, "
+                                       "capability=0x%x, rangelow=%d, "
+                                       "rangehigh=%d, signal=%d, afc=%d, "
+                                       "rxsubchans=0x%x, audmode=%d\n",
+                                       p->index, p->name, p->type,
+                                       p->capability, p->rangelow,
+                                       p->rangehigh, p->signal, p->afc,
+                                       p->rxsubchans, p->audmode);
+               break;
+       }
+       case VIDIOC_S_TUNER:
+       {
+               struct v4l2_tuner *p = arg;
+
+               if (!ops->vidioc_s_tuner)
+                       break;
+               dbgarg(cmd, "index=%d, name=%s, type=%d, "
+                               "capability=0x%x, rangelow=%d, "
+                               "rangehigh=%d, signal=%d, afc=%d, "
+                               "rxsubchans=0x%x, audmode=%d\n",
+                               p->index, p->name, p->type,
+                               p->capability, p->rangelow,
+                               p->rangehigh, p->signal, p->afc,
+                               p->rxsubchans, p->audmode);
+               ret = ops->vidioc_s_tuner(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_FREQUENCY:
+       {
+               struct v4l2_frequency *p = arg;
+
+               if (!ops->vidioc_g_frequency)
+                       break;
+
+               memset(p->reserved, 0, sizeof(p->reserved));
+
+               ret = ops->vidioc_g_frequency(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
+                                       p->tuner, p->type, p->frequency);
+               break;
+       }
+       case VIDIOC_S_FREQUENCY:
+       {
+               struct v4l2_frequency *p = arg;
+
+               if (!ops->vidioc_s_frequency)
+                       break;
+               dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
+                               p->tuner, p->type, p->frequency);
+               ret = ops->vidioc_s_frequency(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_SLICED_VBI_CAP:
+       {
+               struct v4l2_sliced_vbi_cap *p = arg;
+               __u32 type = p->type;
+
+               if (!ops->vidioc_g_sliced_vbi_cap)
+                       break;
+               memset(p, 0, sizeof(*p));
+               p->type = type;
+               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
+               ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p);
+               if (!ret)
+                       dbgarg2("service_set=%d\n", p->service_set);
+               break;
+       }
+       case VIDIOC_LOG_STATUS:
+       {
+               if (!ops->vidioc_log_status)
+                       break;
+               ret = ops->vidioc_log_status(file, fh);
+               break;
+       }
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       case VIDIOC_DBG_G_REGISTER:
+       {
+               struct v4l2_register *p = arg;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       ret = -EPERM;
+               else if (ops->vidioc_g_register)
+                       ret = ops->vidioc_g_register(file, fh, p);
+               break;
+       }
+       case VIDIOC_DBG_S_REGISTER:
+       {
+               struct v4l2_register *p = arg;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       ret = -EPERM;
+               else if (ops->vidioc_s_register)
+                       ret = ops->vidioc_s_register(file, fh, p);
+               break;
+       }
+#endif
+       case VIDIOC_G_CHIP_IDENT:
+       {
+               struct v4l2_chip_ident *p = arg;
+
+               if (!ops->vidioc_g_chip_ident)
+                       break;
+               ret = ops->vidioc_g_chip_ident(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
+               break;
+       }
+       case VIDIOC_S_HW_FREQ_SEEK:
+       {
+               struct v4l2_hw_freq_seek *p = arg;
+
+               if (!ops->vidioc_s_hw_freq_seek)
+                       break;
+               dbgarg(cmd,
+                       "tuner=%d, type=%d, seek_upward=%d, wrap_around=%d\n",
+                       p->tuner, p->type, p->seek_upward, p->wrap_around);
+               ret = ops->vidioc_s_hw_freq_seek(file, fh, p);
+               break;
+       }
+       default:
+       {
+               if (!ops->vidioc_default)
+                       break;
+               ret = ops->vidioc_default(file, fh, cmd, arg);
+               break;
+       }
+       } /* switch */
+
+       if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
+               if (ret < 0) {
+                       v4l_print_ioctl(vfd->name, cmd);
+                       printk(KERN_CONT " error %d\n", ret);
+               }
+       }
+
+       return ret;
+}
+
+int video_ioctl2(struct inode *inode, struct file *file,
+              unsigned int cmd, unsigned long arg)
+{
+       char    sbuf[128];
+       void    *mbuf = NULL;
+       void    *parg = NULL;
+       int     err  = -EINVAL;
+       int     is_ext_ctrl;
+       size_t  ctrls_size = 0;
+       void __user *user_ptr = NULL;
+
+#ifdef __OLD_VIDIOC_
+       cmd = video_fix_command(cmd);
+#endif
+       is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
+                      cmd == VIDIOC_TRY_EXT_CTRLS);
+
+       /*  Copy arguments into temp kernel buffer  */
+       switch (_IOC_DIR(cmd)) {
+       case _IOC_NONE:
+               parg = NULL;
+               break;
+       case _IOC_READ:
+       case _IOC_WRITE:
+       case (_IOC_WRITE | _IOC_READ):
+               if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+                       parg = sbuf;
+               } else {
+                       /* too big to allocate from stack */
+                       mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
+                       if (NULL == mbuf)
+                               return -ENOMEM;
+                       parg = mbuf;
+               }
+
+               err = -EFAULT;
+               if (_IOC_DIR(cmd) & _IOC_WRITE)
+                       if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
+                               goto out;
+               break;
+       }
+
+       if (is_ext_ctrl) {
+               struct v4l2_ext_controls *p = parg;
+
+               /* In case of an error, tell the caller that it wasn't
+                  a specific control that caused it. */
+               p->error_idx = p->count;
+               user_ptr = (void __user *)p->controls;
+               if (p->count) {
+                       ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
+                       /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
+                       mbuf = kmalloc(ctrls_size, GFP_KERNEL);
+                       err = -ENOMEM;
+                       if (NULL == mbuf)
+                               goto out_ext_ctrl;
+                       err = -EFAULT;
+                       if (copy_from_user(mbuf, user_ptr, ctrls_size))
+                               goto out_ext_ctrl;
+                       p->controls = mbuf;
+               }
+       }
+
+       /* Handles IOCTL */
+       err = __video_do_ioctl(inode, file, cmd, parg);
+       if (err == -ENOIOCTLCMD)
+               err = -EINVAL;
+       if (is_ext_ctrl) {
+               struct v4l2_ext_controls *p = parg;
+
+               p->controls = (void *)user_ptr;
+               if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
+                       err = -EFAULT;
+               goto out_ext_ctrl;
+       }
+       if (err < 0)
+               goto out;
+
+out_ext_ctrl:
+       /*  Copy results into user buffer  */
+       switch (_IOC_DIR(cmd)) {
+       case _IOC_READ:
+       case (_IOC_WRITE | _IOC_READ):
+               if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
+                       err = -EFAULT;
+               break;
+       }
+
+out:
+       kfree(mbuf);
+       return err;
+}
+EXPORT_SYMBOL(video_ioctl2);
index 0a88c44ace00b20199e8606cef813234d39e5c74..b7b05842cf281bda10b27572df02ff9301fb823d 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 
index 03f20acb668cfd193a5ef8fea7a0315fe0083c88..31944b11e6ea409fa454eb1f02a99f7e761f2e4e 100644 (file)
@@ -28,10 +28,10 @@ struct videobuf_dma_contig_memory {
 };
 
 #define MAGIC_DC_MEM 0x0733ac61
-#define MAGIC_CHECK(is, should)                                                \
-       if (unlikely((is) != (should))) {                               \
-               pr_err("magic mismatch: %x expected %x\n", is, should); \
-               BUG();                                                  \
+#define MAGIC_CHECK(is, should)                                                    \
+       if (unlikely((is) != (should))) {                                   \
+               pr_err("magic mismatch: %x expected %x\n", (is), (should)); \
+               BUG();                                                      \
        }
 
 static void
index a868b7ed75ff2cc60f09181c1b1812dd44888c56..be65a2fb39762551d8d30c56634cf273aa909636 100644 (file)
@@ -203,7 +203,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
                        return 0;
 
                /* FIXME: to properly support USERPTR, remap should occur.
-                  The code bellow won't work, since mem->vma = NULL
+                  The code below won't work, since mem->vma = NULL
                 */
                /* Try to remap memory */
                rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
index 6616e6570557b84960d89afc2753e7bf4bf053f0..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
-/*
- * Video capture interface for Linux version 2
- *
- *     A generic video device interface for the LINUX operating system
- *     using a set of device structures/vectors for low level operations.
- *
- *     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.
- *
- * Authors:    Alan Cox, <alan@redhat.com> (version 1)
- *              Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
- *
- * Fixes:      20000516  Claudio Matsuoka <claudio@conectiva.com>
- *             - Added procfs support
- */
-
-#define dbgarg(cmd, fmt, arg...) \
-               do {                                                    \
-                   if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {            \
-                       printk(KERN_DEBUG "%s: ",  vfd->name);          \
-                       v4l_printk_ioctl(cmd);                          \
-                       printk(" " fmt,  ## arg);                       \
-                   }                                                   \
-               } while (0)
-
-#define dbgarg2(fmt, arg...) \
-               do {                                                    \
-                   if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)              \
-                       printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\
-               } while (0)
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kmod.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define __OLD_VIDIOC_ /* To allow fixing old calls*/
-#include <linux/videodev2.h>
-
-#ifdef CONFIG_VIDEO_V4L1
-#include <linux/videodev.h>
-#endif
-#include <media/v4l2-common.h>
-#include <linux/video_decoder.h>
-
-#define VIDEO_NUM_DEVICES      256
-#define VIDEO_NAME              "video4linux"
-
-struct std_descr {
-       v4l2_std_id std;
-       const char *descr;
-};
-
-static const struct std_descr standards[] = {
-       { V4L2_STD_NTSC,        "NTSC"      },
-       { V4L2_STD_NTSC_M,      "NTSC-M"    },
-       { V4L2_STD_NTSC_M_JP,   "NTSC-M-JP" },
-       { V4L2_STD_NTSC_M_KR,   "NTSC-M-KR" },
-       { V4L2_STD_NTSC_443,    "NTSC-443"  },
-       { V4L2_STD_PAL,         "PAL"       },
-       { V4L2_STD_PAL_BG,      "PAL-BG"    },
-       { V4L2_STD_PAL_B,       "PAL-B"     },
-       { V4L2_STD_PAL_B1,      "PAL-B1"    },
-       { V4L2_STD_PAL_G,       "PAL-G"     },
-       { V4L2_STD_PAL_H,       "PAL-H"     },
-       { V4L2_STD_PAL_I,       "PAL-I"     },
-       { V4L2_STD_PAL_DK,      "PAL-DK"    },
-       { V4L2_STD_PAL_D,       "PAL-D"     },
-       { V4L2_STD_PAL_D1,      "PAL-D1"    },
-       { V4L2_STD_PAL_K,       "PAL-K"     },
-       { V4L2_STD_PAL_M,       "PAL-M"     },
-       { V4L2_STD_PAL_N,       "PAL-N"     },
-       { V4L2_STD_PAL_Nc,      "PAL-Nc"    },
-       { V4L2_STD_PAL_60,      "PAL-60"    },
-       { V4L2_STD_SECAM,       "SECAM"     },
-       { V4L2_STD_SECAM_B,     "SECAM-B"   },
-       { V4L2_STD_SECAM_G,     "SECAM-G"   },
-       { V4L2_STD_SECAM_H,     "SECAM-H"   },
-       { V4L2_STD_SECAM_DK,    "SECAM-DK"  },
-       { V4L2_STD_SECAM_D,     "SECAM-D"   },
-       { V4L2_STD_SECAM_K,     "SECAM-K"   },
-       { V4L2_STD_SECAM_K1,    "SECAM-K1"  },
-       { V4L2_STD_SECAM_L,     "SECAM-L"   },
-       { V4L2_STD_SECAM_LC,    "SECAM-Lc"  },
-       { 0,                    "Unknown"   }
-};
-
-/* video4linux standard ID conversion to standard name
- */
-const char *v4l2_norm_to_name(v4l2_std_id id)
-{
-       u32 myid = id;
-       int i;
-
-       /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
-          64 bit comparations. So, on that architecture, with some gcc
-          variants, compilation fails. Currently, the max value is 30bit wide.
-        */
-       BUG_ON(myid != id);
-
-       for (i = 0; standards[i].std; i++)
-               if (myid == standards[i].std)
-                       break;
-       return standards[i].descr;
-}
-EXPORT_SYMBOL(v4l2_norm_to_name);
-
-/* Fill in the fields of a v4l2_standard structure according to the
-   'id' and 'transmission' parameters.  Returns negative on error.  */
-int v4l2_video_std_construct(struct v4l2_standard *vs,
-                            int id, const char *name)
-{
-       u32 index = vs->index;
-
-       memset(vs, 0, sizeof(struct v4l2_standard));
-       vs->index = index;
-       vs->id    = id;
-       if (id & V4L2_STD_525_60) {
-               vs->frameperiod.numerator = 1001;
-               vs->frameperiod.denominator = 30000;
-               vs->framelines = 525;
-       } else {
-               vs->frameperiod.numerator = 1;
-               vs->frameperiod.denominator = 25;
-               vs->framelines = 625;
-       }
-       strlcpy(vs->name, name, sizeof(vs->name));
-       return 0;
-}
-EXPORT_SYMBOL(v4l2_video_std_construct);
-
-/* ----------------------------------------------------------------- */
-/* some arrays for pretty-printing debug messages of enum types      */
-
-const char *v4l2_field_names[] = {
-       [V4L2_FIELD_ANY]        = "any",
-       [V4L2_FIELD_NONE]       = "none",
-       [V4L2_FIELD_TOP]        = "top",
-       [V4L2_FIELD_BOTTOM]     = "bottom",
-       [V4L2_FIELD_INTERLACED] = "interlaced",
-       [V4L2_FIELD_SEQ_TB]     = "seq-tb",
-       [V4L2_FIELD_SEQ_BT]     = "seq-bt",
-       [V4L2_FIELD_ALTERNATE]  = "alternate",
-       [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
-       [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
-};
-EXPORT_SYMBOL(v4l2_field_names);
-
-const char *v4l2_type_names[] = {
-       [V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "vid-cap",
-       [V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "vid-overlay",
-       [V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "vid-out",
-       [V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
-       [V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
-       [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
-       [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "sliced-vbi-out",
-       [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
-};
-EXPORT_SYMBOL(v4l2_type_names);
-
-static const char *v4l2_memory_names[] = {
-       [V4L2_MEMORY_MMAP]    = "mmap",
-       [V4L2_MEMORY_USERPTR] = "userptr",
-       [V4L2_MEMORY_OVERLAY] = "overlay",
-};
-
-#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
-                          arr[a] : "unknown")
-
-/* ------------------------------------------------------------------ */
-/* debug help functions                                               */
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static const char *v4l1_ioctls[] = {
-       [_IOC_NR(VIDIOCGCAP)]       = "VIDIOCGCAP",
-       [_IOC_NR(VIDIOCGCHAN)]      = "VIDIOCGCHAN",
-       [_IOC_NR(VIDIOCSCHAN)]      = "VIDIOCSCHAN",
-       [_IOC_NR(VIDIOCGTUNER)]     = "VIDIOCGTUNER",
-       [_IOC_NR(VIDIOCSTUNER)]     = "VIDIOCSTUNER",
-       [_IOC_NR(VIDIOCGPICT)]      = "VIDIOCGPICT",
-       [_IOC_NR(VIDIOCSPICT)]      = "VIDIOCSPICT",
-       [_IOC_NR(VIDIOCCAPTURE)]    = "VIDIOCCAPTURE",
-       [_IOC_NR(VIDIOCGWIN)]       = "VIDIOCGWIN",
-       [_IOC_NR(VIDIOCSWIN)]       = "VIDIOCSWIN",
-       [_IOC_NR(VIDIOCGFBUF)]      = "VIDIOCGFBUF",
-       [_IOC_NR(VIDIOCSFBUF)]      = "VIDIOCSFBUF",
-       [_IOC_NR(VIDIOCKEY)]        = "VIDIOCKEY",
-       [_IOC_NR(VIDIOCGFREQ)]      = "VIDIOCGFREQ",
-       [_IOC_NR(VIDIOCSFREQ)]      = "VIDIOCSFREQ",
-       [_IOC_NR(VIDIOCGAUDIO)]     = "VIDIOCGAUDIO",
-       [_IOC_NR(VIDIOCSAUDIO)]     = "VIDIOCSAUDIO",
-       [_IOC_NR(VIDIOCSYNC)]       = "VIDIOCSYNC",
-       [_IOC_NR(VIDIOCMCAPTURE)]   = "VIDIOCMCAPTURE",
-       [_IOC_NR(VIDIOCGMBUF)]      = "VIDIOCGMBUF",
-       [_IOC_NR(VIDIOCGUNIT)]      = "VIDIOCGUNIT",
-       [_IOC_NR(VIDIOCGCAPTURE)]   = "VIDIOCGCAPTURE",
-       [_IOC_NR(VIDIOCSCAPTURE)]   = "VIDIOCSCAPTURE",
-       [_IOC_NR(VIDIOCSPLAYMODE)]  = "VIDIOCSPLAYMODE",
-       [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE",
-       [_IOC_NR(VIDIOCGPLAYINFO)]  = "VIDIOCGPLAYINFO",
-       [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE",
-       [_IOC_NR(VIDIOCGVBIFMT)]    = "VIDIOCGVBIFMT",
-       [_IOC_NR(VIDIOCSVBIFMT)]    = "VIDIOCSVBIFMT"
-};
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-#endif
-
-static const char *v4l2_ioctls[] = {
-       [_IOC_NR(VIDIOC_QUERYCAP)]         = "VIDIOC_QUERYCAP",
-       [_IOC_NR(VIDIOC_RESERVED)]         = "VIDIOC_RESERVED",
-       [_IOC_NR(VIDIOC_ENUM_FMT)]         = "VIDIOC_ENUM_FMT",
-       [_IOC_NR(VIDIOC_G_FMT)]            = "VIDIOC_G_FMT",
-       [_IOC_NR(VIDIOC_S_FMT)]            = "VIDIOC_S_FMT",
-       [_IOC_NR(VIDIOC_REQBUFS)]          = "VIDIOC_REQBUFS",
-       [_IOC_NR(VIDIOC_QUERYBUF)]         = "VIDIOC_QUERYBUF",
-       [_IOC_NR(VIDIOC_G_FBUF)]           = "VIDIOC_G_FBUF",
-       [_IOC_NR(VIDIOC_S_FBUF)]           = "VIDIOC_S_FBUF",
-       [_IOC_NR(VIDIOC_OVERLAY)]          = "VIDIOC_OVERLAY",
-       [_IOC_NR(VIDIOC_QBUF)]             = "VIDIOC_QBUF",
-       [_IOC_NR(VIDIOC_DQBUF)]            = "VIDIOC_DQBUF",
-       [_IOC_NR(VIDIOC_STREAMON)]         = "VIDIOC_STREAMON",
-       [_IOC_NR(VIDIOC_STREAMOFF)]        = "VIDIOC_STREAMOFF",
-       [_IOC_NR(VIDIOC_G_PARM)]           = "VIDIOC_G_PARM",
-       [_IOC_NR(VIDIOC_S_PARM)]           = "VIDIOC_S_PARM",
-       [_IOC_NR(VIDIOC_G_STD)]            = "VIDIOC_G_STD",
-       [_IOC_NR(VIDIOC_S_STD)]            = "VIDIOC_S_STD",
-       [_IOC_NR(VIDIOC_ENUMSTD)]          = "VIDIOC_ENUMSTD",
-       [_IOC_NR(VIDIOC_ENUMINPUT)]        = "VIDIOC_ENUMINPUT",
-       [_IOC_NR(VIDIOC_G_CTRL)]           = "VIDIOC_G_CTRL",
-       [_IOC_NR(VIDIOC_S_CTRL)]           = "VIDIOC_S_CTRL",
-       [_IOC_NR(VIDIOC_G_TUNER)]          = "VIDIOC_G_TUNER",
-       [_IOC_NR(VIDIOC_S_TUNER)]          = "VIDIOC_S_TUNER",
-       [_IOC_NR(VIDIOC_G_AUDIO)]          = "VIDIOC_G_AUDIO",
-       [_IOC_NR(VIDIOC_S_AUDIO)]          = "VIDIOC_S_AUDIO",
-       [_IOC_NR(VIDIOC_QUERYCTRL)]        = "VIDIOC_QUERYCTRL",
-       [_IOC_NR(VIDIOC_QUERYMENU)]        = "VIDIOC_QUERYMENU",
-       [_IOC_NR(VIDIOC_G_INPUT)]          = "VIDIOC_G_INPUT",
-       [_IOC_NR(VIDIOC_S_INPUT)]          = "VIDIOC_S_INPUT",
-       [_IOC_NR(VIDIOC_G_OUTPUT)]         = "VIDIOC_G_OUTPUT",
-       [_IOC_NR(VIDIOC_S_OUTPUT)]         = "VIDIOC_S_OUTPUT",
-       [_IOC_NR(VIDIOC_ENUMOUTPUT)]       = "VIDIOC_ENUMOUTPUT",
-       [_IOC_NR(VIDIOC_G_AUDOUT)]         = "VIDIOC_G_AUDOUT",
-       [_IOC_NR(VIDIOC_S_AUDOUT)]         = "VIDIOC_S_AUDOUT",
-       [_IOC_NR(VIDIOC_G_MODULATOR)]      = "VIDIOC_G_MODULATOR",
-       [_IOC_NR(VIDIOC_S_MODULATOR)]      = "VIDIOC_S_MODULATOR",
-       [_IOC_NR(VIDIOC_G_FREQUENCY)]      = "VIDIOC_G_FREQUENCY",
-       [_IOC_NR(VIDIOC_S_FREQUENCY)]      = "VIDIOC_S_FREQUENCY",
-       [_IOC_NR(VIDIOC_CROPCAP)]          = "VIDIOC_CROPCAP",
-       [_IOC_NR(VIDIOC_G_CROP)]           = "VIDIOC_G_CROP",
-       [_IOC_NR(VIDIOC_S_CROP)]           = "VIDIOC_S_CROP",
-       [_IOC_NR(VIDIOC_G_JPEGCOMP)]       = "VIDIOC_G_JPEGCOMP",
-       [_IOC_NR(VIDIOC_S_JPEGCOMP)]       = "VIDIOC_S_JPEGCOMP",
-       [_IOC_NR(VIDIOC_QUERYSTD)]         = "VIDIOC_QUERYSTD",
-       [_IOC_NR(VIDIOC_TRY_FMT)]          = "VIDIOC_TRY_FMT",
-       [_IOC_NR(VIDIOC_ENUMAUDIO)]        = "VIDIOC_ENUMAUDIO",
-       [_IOC_NR(VIDIOC_ENUMAUDOUT)]       = "VIDIOC_ENUMAUDOUT",
-       [_IOC_NR(VIDIOC_G_PRIORITY)]       = "VIDIOC_G_PRIORITY",
-       [_IOC_NR(VIDIOC_S_PRIORITY)]       = "VIDIOC_S_PRIORITY",
-       [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
-       [_IOC_NR(VIDIOC_LOG_STATUS)]       = "VIDIOC_LOG_STATUS",
-       [_IOC_NR(VIDIOC_G_EXT_CTRLS)]      = "VIDIOC_G_EXT_CTRLS",
-       [_IOC_NR(VIDIOC_S_EXT_CTRLS)]      = "VIDIOC_S_EXT_CTRLS",
-       [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)]    = "VIDIOC_TRY_EXT_CTRLS",
-#if 1
-       [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)]  = "VIDIOC_ENUM_FRAMESIZES",
-       [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
-       [_IOC_NR(VIDIOC_G_ENC_INDEX)]      = "VIDIOC_G_ENC_INDEX",
-       [_IOC_NR(VIDIOC_ENCODER_CMD)]      = "VIDIOC_ENCODER_CMD",
-       [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)]  = "VIDIOC_TRY_ENCODER_CMD",
-
-       [_IOC_NR(VIDIOC_DBG_S_REGISTER)]   = "VIDIOC_DBG_S_REGISTER",
-       [_IOC_NR(VIDIOC_DBG_G_REGISTER)]   = "VIDIOC_DBG_G_REGISTER",
-
-       [_IOC_NR(VIDIOC_G_CHIP_IDENT)]     = "VIDIOC_G_CHIP_IDENT",
-       [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)]   = "VIDIOC_S_HW_FREQ_SEEK",
-#endif
-};
-#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-static const char *v4l2_int_ioctls[] = {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-       [_IOC_NR(DECODER_GET_CAPABILITIES)]    = "DECODER_GET_CAPABILITIES",
-       [_IOC_NR(DECODER_GET_STATUS)]          = "DECODER_GET_STATUS",
-       [_IOC_NR(DECODER_SET_NORM)]            = "DECODER_SET_NORM",
-       [_IOC_NR(DECODER_SET_INPUT)]           = "DECODER_SET_INPUT",
-       [_IOC_NR(DECODER_SET_OUTPUT)]          = "DECODER_SET_OUTPUT",
-       [_IOC_NR(DECODER_ENABLE_OUTPUT)]       = "DECODER_ENABLE_OUTPUT",
-       [_IOC_NR(DECODER_SET_PICTURE)]         = "DECODER_SET_PICTURE",
-       [_IOC_NR(DECODER_SET_GPIO)]            = "DECODER_SET_GPIO",
-       [_IOC_NR(DECODER_INIT)]                = "DECODER_INIT",
-       [_IOC_NR(DECODER_SET_VBI_BYPASS)]      = "DECODER_SET_VBI_BYPASS",
-       [_IOC_NR(DECODER_DUMP)]                = "DECODER_DUMP",
-#endif
-       [_IOC_NR(AUDC_SET_RADIO)]              = "AUDC_SET_RADIO",
-
-       [_IOC_NR(TUNER_SET_TYPE_ADDR)]         = "TUNER_SET_TYPE_ADDR",
-       [_IOC_NR(TUNER_SET_STANDBY)]           = "TUNER_SET_STANDBY",
-       [_IOC_NR(TUNER_SET_CONFIG)]            = "TUNER_SET_CONFIG",
-
-       [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)]     = "VIDIOC_INT_S_TUNER_MODE",
-       [_IOC_NR(VIDIOC_INT_RESET)]            = "VIDIOC_INT_RESET",
-       [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
-       [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)]  = "VIDIOC_INT_DECODE_VBI_LINE",
-       [_IOC_NR(VIDIOC_INT_S_VBI_DATA)]       = "VIDIOC_INT_S_VBI_DATA",
-       [_IOC_NR(VIDIOC_INT_G_VBI_DATA)]       = "VIDIOC_INT_G_VBI_DATA",
-       [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)]   = "VIDIOC_INT_I2S_CLOCK_FREQ",
-       [_IOC_NR(VIDIOC_INT_S_STANDBY)]        = "VIDIOC_INT_S_STANDBY",
-       [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)]  = "VIDIOC_INT_S_AUDIO_ROUTING",
-       [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)]  = "VIDIOC_INT_G_AUDIO_ROUTING",
-       [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)]  = "VIDIOC_INT_S_VIDEO_ROUTING",
-       [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)]  = "VIDIOC_INT_G_VIDEO_ROUTING",
-       [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)]   = "VIDIOC_INT_S_CRYSTAL_FREQ",
-       [_IOC_NR(VIDIOC_INT_INIT)]             = "VIDIOC_INT_INIT",
-       [_IOC_NR(VIDIOC_INT_G_STD_OUTPUT)]     = "VIDIOC_INT_G_STD_OUTPUT",
-       [_IOC_NR(VIDIOC_INT_S_STD_OUTPUT)]     = "VIDIOC_INT_S_STD_OUTPUT",
-};
-#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
-
-/* Common ioctl debug function. This function can be used by
-   external ioctl messages as well as internal V4L ioctl */
-void v4l_printk_ioctl(unsigned int cmd)
-{
-       char *dir, *type;
-
-       switch (_IOC_TYPE(cmd)) {
-       case 'd':
-               if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) {
-                       type = "v4l2_int";
-                       break;
-               }
-               printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]);
-               return;
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-       case 'v':
-               if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
-                       type = "v4l1";
-                       break;
-               }
-               printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
-               return;
-#endif
-       case 'V':
-               if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
-                       type = "v4l2";
-                       break;
-               }
-               printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
-               return;
-       default:
-               type = "unknown";
-       }
-
-       switch (_IOC_DIR(cmd)) {
-       case _IOC_NONE:              dir = "--"; break;
-       case _IOC_READ:              dir = "r-"; break;
-       case _IOC_WRITE:             dir = "-w"; break;
-       case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
-       default:                     dir = "*ERR*"; break;
-       }
-       printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
-               type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
-}
-EXPORT_SYMBOL(v4l_printk_ioctl);
-
-/*
- *     sysfs stuff
- */
-
-static ssize_t show_index(struct device *cd,
-                        struct device_attribute *attr, char *buf)
-{
-       struct video_device *vfd = container_of(cd, struct video_device,
-                                               class_dev);
-       return sprintf(buf, "%i\n", vfd->index);
-}
-
-static ssize_t show_name(struct device *cd,
-                        struct device_attribute *attr, char *buf)
-{
-       struct video_device *vfd = container_of(cd, struct video_device,
-                                               class_dev);
-       return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name);
-}
-
-static struct device_attribute video_device_attrs[] = {
-       __ATTR(name, S_IRUGO, show_name, NULL),
-       __ATTR(index, S_IRUGO, show_index, NULL),
-       __ATTR_NULL
-};
-
-struct video_device *video_device_alloc(void)
-{
-       struct video_device *vfd;
-
-       vfd = kzalloc(sizeof(*vfd),GFP_KERNEL);
-       return vfd;
-}
-EXPORT_SYMBOL(video_device_alloc);
-
-void video_device_release(struct video_device *vfd)
-{
-       kfree(vfd);
-}
-EXPORT_SYMBOL(video_device_release);
-
-static void video_release(struct device *cd)
-{
-       struct video_device *vfd = container_of(cd, struct video_device,
-                                                               class_dev);
-
-#if 1
-       /* needed until all drivers are fixed */
-       if (!vfd->release)
-               return;
-#endif
-       vfd->release(vfd);
-}
-
-static struct class video_class = {
-       .name    = VIDEO_NAME,
-       .dev_attrs = video_device_attrs,
-       .dev_release = video_release,
-};
-
-/*
- *     Active devices
- */
-
-static struct video_device *video_device[VIDEO_NUM_DEVICES];
-static DEFINE_MUTEX(videodev_lock);
-
-struct video_device* video_devdata(struct file *file)
-{
-       return video_device[iminor(file->f_path.dentry->d_inode)];
-}
-EXPORT_SYMBOL(video_devdata);
-
-/*
- *     Open a video device - FIXME: Obsoleted
- */
-static int video_open(struct inode *inode, struct file *file)
-{
-       unsigned int minor = iminor(inode);
-       int err = 0;
-       struct video_device *vfl;
-       const struct file_operations *old_fops;
-
-       if(minor>=VIDEO_NUM_DEVICES)
-               return -ENODEV;
-       lock_kernel();
-       mutex_lock(&videodev_lock);
-       vfl=video_device[minor];
-       if(vfl==NULL) {
-               mutex_unlock(&videodev_lock);
-               request_module("char-major-%d-%d", VIDEO_MAJOR, minor);
-               mutex_lock(&videodev_lock);
-               vfl=video_device[minor];
-               if (vfl==NULL) {
-                       mutex_unlock(&videodev_lock);
-                       unlock_kernel();
-                       return -ENODEV;
-               }
-       }
-       old_fops = file->f_op;
-       file->f_op = fops_get(vfl->fops);
-       if(file->f_op->open)
-               err = file->f_op->open(inode,file);
-       if (err) {
-               fops_put(file->f_op);
-               file->f_op = fops_get(old_fops);
-       }
-       fops_put(old_fops);
-       mutex_unlock(&videodev_lock);
-       unlock_kernel();
-       return err;
-}
-
-/*
- * helper function -- handles userspace copying for ioctl arguments
- */
-
-#ifdef __OLD_VIDIOC_
-static unsigned int
-video_fix_command(unsigned int cmd)
-{
-       switch (cmd) {
-       case VIDIOC_OVERLAY_OLD:
-               cmd = VIDIOC_OVERLAY;
-               break;
-       case VIDIOC_S_PARM_OLD:
-               cmd = VIDIOC_S_PARM;
-               break;
-       case VIDIOC_S_CTRL_OLD:
-               cmd = VIDIOC_S_CTRL;
-               break;
-       case VIDIOC_G_AUDIO_OLD:
-               cmd = VIDIOC_G_AUDIO;
-               break;
-       case VIDIOC_G_AUDOUT_OLD:
-               cmd = VIDIOC_G_AUDOUT;
-               break;
-       case VIDIOC_CROPCAP_OLD:
-               cmd = VIDIOC_CROPCAP;
-               break;
-       }
-       return cmd;
-}
-#endif
-
-/*
- * Obsolete usercopy function - Should be removed soon
- */
-int
-video_usercopy(struct inode *inode, struct file *file,
-              unsigned int cmd, unsigned long arg,
-              int (*func)(struct inode *inode, struct file *file,
-                          unsigned int cmd, void *arg))
-{
-       char    sbuf[128];
-       void    *mbuf = NULL;
-       void    *parg = NULL;
-       int     err  = -EINVAL;
-       int     is_ext_ctrl;
-       size_t  ctrls_size = 0;
-       void __user *user_ptr = NULL;
-
-#ifdef __OLD_VIDIOC_
-       cmd = video_fix_command(cmd);
-#endif
-       is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
-                      cmd == VIDIOC_TRY_EXT_CTRLS);
-
-       /*  Copy arguments into temp kernel buffer  */
-       switch (_IOC_DIR(cmd)) {
-       case _IOC_NONE:
-               parg = NULL;
-               break;
-       case _IOC_READ:
-       case _IOC_WRITE:
-       case (_IOC_WRITE | _IOC_READ):
-               if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
-                       parg = sbuf;
-               } else {
-                       /* too big to allocate from stack */
-                       mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
-                       if (NULL == mbuf)
-                               return -ENOMEM;
-                       parg = mbuf;
-               }
-
-               err = -EFAULT;
-               if (_IOC_DIR(cmd) & _IOC_WRITE)
-                       if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
-                               goto out;
-               break;
-       }
-       if (is_ext_ctrl) {
-               struct v4l2_ext_controls *p = parg;
-
-               /* In case of an error, tell the caller that it wasn't
-                  a specific control that caused it. */
-               p->error_idx = p->count;
-               user_ptr = (void __user *)p->controls;
-               if (p->count) {
-                       ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
-                       /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
-                       mbuf = kmalloc(ctrls_size, GFP_KERNEL);
-                       err = -ENOMEM;
-                       if (NULL == mbuf)
-                               goto out_ext_ctrl;
-                       err = -EFAULT;
-                       if (copy_from_user(mbuf, user_ptr, ctrls_size))
-                               goto out_ext_ctrl;
-                       p->controls = mbuf;
-               }
-       }
-
-       /* call driver */
-       err = func(inode, file, cmd, parg);
-       if (err == -ENOIOCTLCMD)
-               err = -EINVAL;
-       if (is_ext_ctrl) {
-               struct v4l2_ext_controls *p = parg;
-
-               p->controls = (void *)user_ptr;
-               if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
-                       err = -EFAULT;
-               goto out_ext_ctrl;
-       }
-       if (err < 0)
-               goto out;
-
-out_ext_ctrl:
-       /*  Copy results into user buffer  */
-       switch (_IOC_DIR(cmd))
-       {
-       case _IOC_READ:
-       case (_IOC_WRITE | _IOC_READ):
-               if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
-                       err = -EFAULT;
-               break;
-       }
-
-out:
-       kfree(mbuf);
-       return err;
-}
-EXPORT_SYMBOL(video_usercopy);
-
-/*
- * open/release helper functions -- handle exclusive opens
- * Should be removed soon
- */
-int video_exclusive_open(struct inode *inode, struct file *file)
-{
-       struct  video_device *vfl = video_devdata(file);
-       int retval = 0;
-
-       mutex_lock(&vfl->lock);
-       if (vfl->users) {
-               retval = -EBUSY;
-       } else {
-               vfl->users++;
-       }
-       mutex_unlock(&vfl->lock);
-       return retval;
-}
-EXPORT_SYMBOL(video_exclusive_open);
-
-int video_exclusive_release(struct inode *inode, struct file *file)
-{
-       struct  video_device *vfl = video_devdata(file);
-
-       vfl->users--;
-       return 0;
-}
-EXPORT_SYMBOL(video_exclusive_release);
-
-static void dbgbuf(unsigned int cmd, struct video_device *vfd,
-                                       struct v4l2_buffer *p)
-{
-       struct v4l2_timecode *tc=&p->timecode;
-
-       dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
-               "bytesused=%d, flags=0x%08d, "
-               "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
-                       (p->timestamp.tv_sec/3600),
-                       (int)(p->timestamp.tv_sec/60)%60,
-                       (int)(p->timestamp.tv_sec%60),
-                       p->timestamp.tv_usec,
-                       p->index,
-                       prt_names(p->type, v4l2_type_names),
-                       p->bytesused, p->flags,
-                       p->field, p->sequence,
-                       prt_names(p->memory, v4l2_memory_names),
-                       p->m.userptr, p->length);
-       dbgarg2("timecode=%02d:%02d:%02d type=%d, "
-               "flags=0x%08d, frames=%d, userbits=0x%08x\n",
-                       tc->hours,tc->minutes,tc->seconds,
-                       tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);
-}
-
-static inline void dbgrect(struct video_device *vfd, char *s,
-                                                       struct v4l2_rect *r)
-{
-       dbgarg2("%sRect start at %dx%d, size=%dx%d\n", s, r->left, r->top,
-                                               r->width, r->height);
-};
-
-static inline void v4l_print_pix_fmt (struct video_device *vfd,
-                                               struct v4l2_pix_format *fmt)
-{
-       dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, "
-               "bytesperline=%d sizeimage=%d, colorspace=%d\n",
-               fmt->width,fmt->height,
-               (fmt->pixelformat & 0xff),
-               (fmt->pixelformat >>  8) & 0xff,
-               (fmt->pixelformat >> 16) & 0xff,
-               (fmt->pixelformat >> 24) & 0xff,
-               prt_names(fmt->field, v4l2_field_names),
-               fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
-};
-
-static inline void v4l_print_ext_ctrls(unsigned int cmd,
-       struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
-{
-       __u32 i;
-
-       if (!(vfd->debug & V4L2_DEBUG_IOCTL_ARG))
-               return;
-       dbgarg(cmd, "");
-       printk(KERN_CONT "class=0x%x", c->ctrl_class);
-       for (i = 0; i < c->count; i++) {
-               if (show_vals)
-                       printk(KERN_CONT " id/val=0x%x/0x%x",
-                               c->controls[i].id, c->controls[i].value);
-               else
-                       printk(KERN_CONT " id=0x%x", c->controls[i].id);
-       }
-       printk(KERN_CONT "\n");
-};
-
-static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
-{
-       __u32 i;
-
-       /* zero the reserved fields */
-       c->reserved[0] = c->reserved[1] = 0;
-       for (i = 0; i < c->count; i++) {
-               c->controls[i].reserved2[0] = 0;
-               c->controls[i].reserved2[1] = 0;
-       }
-       /* V4L2_CID_PRIVATE_BASE cannot be used as control class
-          when using extended controls.
-          Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
-          is it allowed for backwards compatibility.
-        */
-       if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
-               return 0;
-       /* Check that all controls are from the same control class. */
-       for (i = 0; i < c->count; i++) {
-               if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
-                       c->error_idx = i;
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type)
-{
-       switch (type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               if (vfd->vidioc_try_fmt_vid_cap)
-                       return (0);
-               break;
-       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-               if (vfd->vidioc_try_fmt_vid_overlay)
-                       return (0);
-               break;
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-               if (vfd->vidioc_try_fmt_vid_out)
-                       return (0);
-               break;
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-               if (vfd->vidioc_try_fmt_vid_out_overlay)
-                       return (0);
-               break;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               if (vfd->vidioc_try_fmt_vbi_cap)
-                       return (0);
-               break;
-       case V4L2_BUF_TYPE_VBI_OUTPUT:
-               if (vfd->vidioc_try_fmt_vbi_out)
-                       return (0);
-               break;
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-               if (vfd->vidioc_try_fmt_sliced_vbi_cap)
-                       return (0);
-               break;
-       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               if (vfd->vidioc_try_fmt_sliced_vbi_out)
-                       return (0);
-               break;
-       case V4L2_BUF_TYPE_PRIVATE:
-               if (vfd->vidioc_try_fmt_type_private)
-                       return (0);
-               break;
-       }
-       return (-EINVAL);
-}
-
-static int __video_do_ioctl(struct inode *inode, struct file *file,
-               unsigned int cmd, void *arg)
-{
-       struct video_device *vfd = video_devdata(file);
-       void                 *fh = file->private_data;
-       int                  ret = -EINVAL;
-
-       if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
-                               !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
-               v4l_print_ioctl(vfd->name, cmd);
-               printk("\n");
-       }
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-       /***********************************************************
-        Handles calls to the obsoleted V4L1 API
-        Due to the nature of VIDIOCGMBUF, each driver that supports
-        V4L1 should implement its own handler for this ioctl.
-        ***********************************************************/
-
-       /* --- streaming capture ------------------------------------- */
-       if (cmd == VIDIOCGMBUF) {
-               struct video_mbuf *p=arg;
-
-               memset(p, 0, sizeof(*p));
-
-               if (!vfd->vidiocgmbuf)
-                       return ret;
-               ret=vfd->vidiocgmbuf(file, fh, p);
-               if (!ret)
-                       dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
-                                               p->size, p->frames,
-                                               (unsigned long)p->offsets);
-               return ret;
-       }
-
-       /********************************************************
-        All other V4L1 calls are handled by v4l1_compat module.
-        Those calls will be translated into V4L2 calls, and
-        __video_do_ioctl will be called again, with one or more
-        V4L2 ioctls.
-        ********************************************************/
-       if (_IOC_TYPE(cmd)=='v')
-               return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-                                               __video_do_ioctl);
-#endif
-
-       switch(cmd) {
-       /* --- capabilities ------------------------------------------ */
-       case VIDIOC_QUERYCAP:
-       {
-               struct v4l2_capability *cap = (struct v4l2_capability*)arg;
-               memset(cap, 0, sizeof(*cap));
-
-               if (!vfd->vidioc_querycap)
-                       break;
-
-               ret=vfd->vidioc_querycap(file, fh, cap);
-               if (!ret)
-                       dbgarg (cmd, "driver=%s, card=%s, bus=%s, "
-                                       "version=0x%08x, "
-                                       "capabilities=0x%08x\n",
-                                       cap->driver,cap->card,cap->bus_info,
-                                       cap->version,
-                                       cap->capabilities);
-               break;
-       }
-
-       /* --- priority ------------------------------------------ */
-       case VIDIOC_G_PRIORITY:
-       {
-               enum v4l2_priority *p=arg;
-
-               if (!vfd->vidioc_g_priority)
-                       break;
-               ret=vfd->vidioc_g_priority(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "priority is %d\n", *p);
-               break;
-       }
-       case VIDIOC_S_PRIORITY:
-       {
-               enum v4l2_priority *p=arg;
-
-               if (!vfd->vidioc_s_priority)
-                       break;
-               dbgarg(cmd, "setting priority to %d\n", *p);
-               ret=vfd->vidioc_s_priority(file, fh, *p);
-               break;
-       }
-
-       /* --- capture ioctls ---------------------------------------- */
-       case VIDIOC_ENUM_FMT:
-       {
-               struct v4l2_fmtdesc *f = arg;
-               enum v4l2_buf_type type;
-               unsigned int index;
-
-               index = f->index;
-               type  = f->type;
-               memset(f,0,sizeof(*f));
-               f->index = index;
-               f->type  = type;
-
-               switch (type) {
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       if (vfd->vidioc_enum_fmt_vid_cap)
-                               ret = vfd->vidioc_enum_fmt_vid_cap(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-                       if (vfd->vidioc_enum_fmt_vid_overlay)
-                               ret = vfd->vidioc_enum_fmt_vid_overlay(file,
-                                       fh, f);
-                       break;
-#if 1
-               /* V4L2_BUF_TYPE_VBI_CAPTURE should not support VIDIOC_ENUM_FMT
-                * according to the spec. The bttv and saa7134 drivers support
-                * it though, so just warn that this is deprecated and will be
-                * removed in the near future. */
-               case V4L2_BUF_TYPE_VBI_CAPTURE:
-                       if (vfd->vidioc_enum_fmt_vbi_cap) {
-                               printk(KERN_WARNING "vidioc_enum_fmt_vbi_cap will be removed in 2.6.28!\n");
-                               ret = vfd->vidioc_enum_fmt_vbi_cap(file, fh, f);
-                       }
-                       break;
-#endif
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-                       if (vfd->vidioc_enum_fmt_vid_out)
-                               ret = vfd->vidioc_enum_fmt_vid_out(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_PRIVATE:
-                       if (vfd->vidioc_enum_fmt_type_private)
-                               ret = vfd->vidioc_enum_fmt_type_private(file,
-                                                               fh, f);
-                       break;
-               default:
-                       break;
-               }
-               if (!ret)
-                       dbgarg (cmd, "index=%d, type=%d, flags=%d, "
-                                       "pixelformat=%c%c%c%c, description='%s'\n",
-                                       f->index, f->type, f->flags,
-                                       (f->pixelformat & 0xff),
-                                       (f->pixelformat >>  8) & 0xff,
-                                       (f->pixelformat >> 16) & 0xff,
-                                       (f->pixelformat >> 24) & 0xff,
-                                       f->description);
-               break;
-       }
-       case VIDIOC_G_FMT:
-       {
-               struct v4l2_format *f = (struct v4l2_format *)arg;
-
-               memset(f->fmt.raw_data, 0, sizeof(f->fmt.raw_data));
-
-               /* FIXME: Should be one dump per type */
-               dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
-
-               switch (f->type) {
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       if (vfd->vidioc_g_fmt_vid_cap)
-                               ret = vfd->vidioc_g_fmt_vid_cap(file, fh, f);
-                       if (!ret)
-                               v4l_print_pix_fmt(vfd, &f->fmt.pix);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-                       if (vfd->vidioc_g_fmt_vid_overlay)
-                               ret = vfd->vidioc_g_fmt_vid_overlay(file,
-                                                                   fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-                       if (vfd->vidioc_g_fmt_vid_out)
-                               ret = vfd->vidioc_g_fmt_vid_out(file, fh, f);
-                       if (!ret)
-                               v4l_print_pix_fmt(vfd, &f->fmt.pix);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-                       if (vfd->vidioc_g_fmt_vid_out_overlay)
-                               ret = vfd->vidioc_g_fmt_vid_out_overlay(file,
-                                      fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VBI_CAPTURE:
-                       if (vfd->vidioc_g_fmt_vbi_cap)
-                               ret = vfd->vidioc_g_fmt_vbi_cap(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VBI_OUTPUT:
-                       if (vfd->vidioc_g_fmt_vbi_out)
-                               ret = vfd->vidioc_g_fmt_vbi_out(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-                       if (vfd->vidioc_g_fmt_sliced_vbi_cap)
-                               ret = vfd->vidioc_g_fmt_sliced_vbi_cap(file,
-                                                                       fh, f);
-                       break;
-               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-                       if (vfd->vidioc_g_fmt_sliced_vbi_out)
-                               ret = vfd->vidioc_g_fmt_sliced_vbi_out(file,
-                                                                       fh, f);
-                       break;
-               case V4L2_BUF_TYPE_PRIVATE:
-                       if (vfd->vidioc_g_fmt_type_private)
-                               ret = vfd->vidioc_g_fmt_type_private(file,
-                                                               fh, f);
-                       break;
-               }
-
-               break;
-       }
-       case VIDIOC_S_FMT:
-       {
-               struct v4l2_format *f = (struct v4l2_format *)arg;
-
-               /* FIXME: Should be one dump per type */
-               dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
-
-               switch (f->type) {
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       v4l_print_pix_fmt(vfd, &f->fmt.pix);
-                       if (vfd->vidioc_s_fmt_vid_cap)
-                               ret = vfd->vidioc_s_fmt_vid_cap(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-                       if (vfd->vidioc_s_fmt_vid_overlay)
-                               ret = vfd->vidioc_s_fmt_vid_overlay(file,
-                                                                   fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-                       v4l_print_pix_fmt(vfd, &f->fmt.pix);
-                       if (vfd->vidioc_s_fmt_vid_out)
-                               ret = vfd->vidioc_s_fmt_vid_out(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-                       if (vfd->vidioc_s_fmt_vid_out_overlay)
-                               ret = vfd->vidioc_s_fmt_vid_out_overlay(file,
-                                       fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VBI_CAPTURE:
-                       if (vfd->vidioc_s_fmt_vbi_cap)
-                               ret = vfd->vidioc_s_fmt_vbi_cap(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VBI_OUTPUT:
-                       if (vfd->vidioc_s_fmt_vbi_out)
-                               ret = vfd->vidioc_s_fmt_vbi_out(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-                       if (vfd->vidioc_s_fmt_sliced_vbi_cap)
-                               ret = vfd->vidioc_s_fmt_sliced_vbi_cap(file,
-                                                                       fh, f);
-                       break;
-               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-                       if (vfd->vidioc_s_fmt_sliced_vbi_out)
-                               ret = vfd->vidioc_s_fmt_sliced_vbi_out(file,
-                                                                       fh, f);
-                       break;
-               case V4L2_BUF_TYPE_PRIVATE:
-                       if (vfd->vidioc_s_fmt_type_private)
-                               ret = vfd->vidioc_s_fmt_type_private(file,
-                                                               fh, f);
-                       break;
-               }
-               break;
-       }
-       case VIDIOC_TRY_FMT:
-       {
-               struct v4l2_format *f = (struct v4l2_format *)arg;
-
-               /* FIXME: Should be one dump per type */
-               dbgarg (cmd, "type=%s\n", prt_names(f->type,
-                                               v4l2_type_names));
-               switch (f->type) {
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       if (vfd->vidioc_try_fmt_vid_cap)
-                               ret = vfd->vidioc_try_fmt_vid_cap(file, fh, f);
-                       if (!ret)
-                               v4l_print_pix_fmt(vfd, &f->fmt.pix);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-                       if (vfd->vidioc_try_fmt_vid_overlay)
-                               ret = vfd->vidioc_try_fmt_vid_overlay(file,
-                                       fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-                       if (vfd->vidioc_try_fmt_vid_out)
-                               ret = vfd->vidioc_try_fmt_vid_out(file, fh, f);
-                       if (!ret)
-                               v4l_print_pix_fmt(vfd, &f->fmt.pix);
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-                       if (vfd->vidioc_try_fmt_vid_out_overlay)
-                               ret = vfd->vidioc_try_fmt_vid_out_overlay(file,
-                                      fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VBI_CAPTURE:
-                       if (vfd->vidioc_try_fmt_vbi_cap)
-                               ret = vfd->vidioc_try_fmt_vbi_cap(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_VBI_OUTPUT:
-                       if (vfd->vidioc_try_fmt_vbi_out)
-                               ret = vfd->vidioc_try_fmt_vbi_out(file, fh, f);
-                       break;
-               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-                       if (vfd->vidioc_try_fmt_sliced_vbi_cap)
-                               ret = vfd->vidioc_try_fmt_sliced_vbi_cap(file,
-                                                               fh, f);
-                       break;
-               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-                       if (vfd->vidioc_try_fmt_sliced_vbi_out)
-                               ret = vfd->vidioc_try_fmt_sliced_vbi_out(file,
-                                                               fh, f);
-                       break;
-               case V4L2_BUF_TYPE_PRIVATE:
-                       if (vfd->vidioc_try_fmt_type_private)
-                               ret = vfd->vidioc_try_fmt_type_private(file,
-                                                               fh, f);
-                       break;
-               }
-
-               break;
-       }
-       /* FIXME: Those buf reqs could be handled here,
-          with some changes on videobuf to allow its header to be included at
-          videodev2.h or being merged at videodev2.
-        */
-       case VIDIOC_REQBUFS:
-       {
-               struct v4l2_requestbuffers *p=arg;
-
-               if (!vfd->vidioc_reqbufs)
-                       break;
-               ret = check_fmt (vfd, p->type);
-               if (ret)
-                       break;
-
-               ret=vfd->vidioc_reqbufs(file, fh, p);
-               dbgarg (cmd, "count=%d, type=%s, memory=%s\n",
-                               p->count,
-                               prt_names(p->type, v4l2_type_names),
-                               prt_names(p->memory, v4l2_memory_names));
-               break;
-       }
-       case VIDIOC_QUERYBUF:
-       {
-               struct v4l2_buffer *p=arg;
-
-               if (!vfd->vidioc_querybuf)
-                       break;
-               ret = check_fmt (vfd, p->type);
-               if (ret)
-                       break;
-
-               ret=vfd->vidioc_querybuf(file, fh, p);
-               if (!ret)
-                       dbgbuf(cmd,vfd,p);
-               break;
-       }
-       case VIDIOC_QBUF:
-       {
-               struct v4l2_buffer *p=arg;
-
-               if (!vfd->vidioc_qbuf)
-                       break;
-               ret = check_fmt (vfd, p->type);
-               if (ret)
-                       break;
-
-               ret=vfd->vidioc_qbuf(file, fh, p);
-               if (!ret)
-                       dbgbuf(cmd,vfd,p);
-               break;
-       }
-       case VIDIOC_DQBUF:
-       {
-               struct v4l2_buffer *p=arg;
-               if (!vfd->vidioc_dqbuf)
-                       break;
-               ret = check_fmt (vfd, p->type);
-               if (ret)
-                       break;
-
-               ret=vfd->vidioc_dqbuf(file, fh, p);
-               if (!ret)
-                       dbgbuf(cmd,vfd,p);
-               break;
-       }
-       case VIDIOC_OVERLAY:
-       {
-               int *i = arg;
-
-               if (!vfd->vidioc_overlay)
-                       break;
-               dbgarg (cmd, "value=%d\n",*i);
-               ret=vfd->vidioc_overlay(file, fh, *i);
-               break;
-       }
-       case VIDIOC_G_FBUF:
-       {
-               struct v4l2_framebuffer *p = arg;
-
-               if (!vfd->vidioc_g_fbuf)
-                       break;
-               ret = vfd->vidioc_g_fbuf(file, fh, arg);
-               if (!ret) {
-                       dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
-                                       p->capability, p->flags,
-                                       (unsigned long)p->base);
-                       v4l_print_pix_fmt(vfd, &p->fmt);
-               }
-               break;
-       }
-       case VIDIOC_S_FBUF:
-       {
-               struct v4l2_framebuffer *p = arg;
-
-               if (!vfd->vidioc_s_fbuf)
-                       break;
-               dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
-                       p->capability, p->flags, (unsigned long)p->base);
-               v4l_print_pix_fmt(vfd, &p->fmt);
-               ret = vfd->vidioc_s_fbuf(file, fh, arg);
-               break;
-       }
-       case VIDIOC_STREAMON:
-       {
-               enum v4l2_buf_type i = *(int *)arg;
-               if (!vfd->vidioc_streamon)
-                       break;
-               dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
-               ret=vfd->vidioc_streamon(file, fh,i);
-               break;
-       }
-       case VIDIOC_STREAMOFF:
-       {
-               enum v4l2_buf_type i = *(int *)arg;
-
-               if (!vfd->vidioc_streamoff)
-                       break;
-               dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
-               ret=vfd->vidioc_streamoff(file, fh, i);
-               break;
-       }
-       /* ---------- tv norms ---------- */
-       case VIDIOC_ENUMSTD:
-       {
-               struct v4l2_standard *p = arg;
-               v4l2_std_id id = vfd->tvnorms, curr_id = 0;
-               unsigned int index = p->index, i, j = 0;
-               const char *descr = "";
-
-               /* Return norm array in a canonical way */
-               for (i = 0; i <= index && id; i++) {
-                       /* last std value in the standards array is 0, so this
-                          while always ends there since (id & 0) == 0. */
-                       while ((id & standards[j].std) != standards[j].std)
-                               j++;
-                       curr_id = standards[j].std;
-                       descr = standards[j].descr;
-                       j++;
-                       if (curr_id == 0)
-                               break;
-                       if (curr_id != V4L2_STD_PAL &&
-                           curr_id != V4L2_STD_SECAM &&
-                           curr_id != V4L2_STD_NTSC)
-                               id &= ~curr_id;
-               }
-               if (i <= index)
-                       return -EINVAL;
-
-               v4l2_video_std_construct(p, curr_id, descr);
-               p->index = index;
-
-               dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
-                               "framelines=%d\n", p->index,
-                               (unsigned long long)p->id, p->name,
-                               p->frameperiod.numerator,
-                               p->frameperiod.denominator,
-                               p->framelines);
-
-               ret = 0;
-               break;
-       }
-       case VIDIOC_G_STD:
-       {
-               v4l2_std_id *id = arg;
-
-               ret = 0;
-               /* Calls the specific handler */
-               if (vfd->vidioc_g_std)
-                       ret = vfd->vidioc_g_std(file, fh, id);
-               else
-                       *id = vfd->current_norm;
-
-               if (!ret)
-                       dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
-               break;
-       }
-       case VIDIOC_S_STD:
-       {
-               v4l2_std_id *id = arg,norm;
-
-               dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
-
-               norm = (*id) & vfd->tvnorms;
-               if ( vfd->tvnorms && !norm)     /* Check if std is supported */
-                       break;
-
-               /* Calls the specific handler */
-               if (vfd->vidioc_s_std)
-                       ret=vfd->vidioc_s_std(file, fh, &norm);
-               else
-                       ret=-EINVAL;
-
-               /* Updates standard information */
-               if (ret>=0)
-                       vfd->current_norm=norm;
-
-               break;
-       }
-       case VIDIOC_QUERYSTD:
-       {
-               v4l2_std_id *p=arg;
-
-               if (!vfd->vidioc_querystd)
-                       break;
-               ret=vfd->vidioc_querystd(file, fh, arg);
-               if (!ret)
-                       dbgarg (cmd, "detected std=%08Lx\n",
-                                               (unsigned long long)*p);
-               break;
-       }
-       /* ------ input switching ---------- */
-       /* FIXME: Inputs can be handled inside videodev2 */
-       case VIDIOC_ENUMINPUT:
-       {
-               struct v4l2_input *p=arg;
-               int i=p->index;
-
-               if (!vfd->vidioc_enum_input)
-                       break;
-               memset(p, 0, sizeof(*p));
-               p->index=i;
-
-               ret=vfd->vidioc_enum_input(file, fh, p);
-               if (!ret)
-                       dbgarg (cmd, "index=%d, name=%s, type=%d, "
-                                       "audioset=%d, "
-                                       "tuner=%d, std=%08Lx, status=%d\n",
-                                       p->index,p->name,p->type,p->audioset,
-                                       p->tuner,
-                                       (unsigned long long)p->std,
-                                       p->status);
-               break;
-       }
-       case VIDIOC_G_INPUT:
-       {
-               unsigned int *i = arg;
-
-               if (!vfd->vidioc_g_input)
-                       break;
-               ret=vfd->vidioc_g_input(file, fh, i);
-               if (!ret)
-                       dbgarg (cmd, "value=%d\n",*i);
-               break;
-       }
-       case VIDIOC_S_INPUT:
-       {
-               unsigned int *i = arg;
-
-               if (!vfd->vidioc_s_input)
-                       break;
-               dbgarg (cmd, "value=%d\n",*i);
-               ret=vfd->vidioc_s_input(file, fh, *i);
-               break;
-       }
-
-       /* ------ output switching ---------- */
-       case VIDIOC_ENUMOUTPUT:
-       {
-               struct v4l2_output *p = arg;
-               int i = p->index;
-
-               if (!vfd->vidioc_enum_output)
-                       break;
-               memset(p, 0, sizeof(*p));
-               p->index = i;
-
-               ret = vfd->vidioc_enum_output(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "index=%d, name=%s, type=%d, "
-                               "audioset=0x%x, "
-                               "modulator=%d, std=0x%08Lx\n",
-                               p->index, p->name, p->type, p->audioset,
-                               p->modulator, (unsigned long long)p->std);
-               break;
-       }
-       case VIDIOC_G_OUTPUT:
-       {
-               unsigned int *i = arg;
-
-               if (!vfd->vidioc_g_output)
-                       break;
-               ret=vfd->vidioc_g_output(file, fh, i);
-               if (!ret)
-                       dbgarg (cmd, "value=%d\n",*i);
-               break;
-       }
-       case VIDIOC_S_OUTPUT:
-       {
-               unsigned int *i = arg;
-
-               if (!vfd->vidioc_s_output)
-                       break;
-               dbgarg (cmd, "value=%d\n",*i);
-               ret=vfd->vidioc_s_output(file, fh, *i);
-               break;
-       }
-
-       /* --- controls ---------------------------------------------- */
-       case VIDIOC_QUERYCTRL:
-       {
-               struct v4l2_queryctrl *p = arg;
-
-               if (!vfd->vidioc_queryctrl)
-                       break;
-               ret = vfd->vidioc_queryctrl(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, "
-                                       "step=%d, default=%d, flags=0x%08x\n",
-                                       p->id, p->type, p->name,
-                                       p->minimum, p->maximum,
-                                       p->step, p->default_value, p->flags);
-               else
-                       dbgarg(cmd, "id=0x%x\n", p->id);
-               break;
-       }
-       case VIDIOC_G_CTRL:
-       {
-               struct v4l2_control *p = arg;
-
-               if (vfd->vidioc_g_ctrl)
-                       ret = vfd->vidioc_g_ctrl(file, fh, p);
-               else if (vfd->vidioc_g_ext_ctrls) {
-                       struct v4l2_ext_controls ctrls;
-                       struct v4l2_ext_control ctrl;
-
-                       ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
-                       ctrls.count = 1;
-                       ctrls.controls = &ctrl;
-                       ctrl.id = p->id;
-                       ctrl.value = p->value;
-                       if (check_ext_ctrls(&ctrls, 1)) {
-                               ret = vfd->vidioc_g_ext_ctrls(file, fh, &ctrls);
-                               if (ret == 0)
-                                       p->value = ctrl.value;
-                       }
-               } else
-                       break;
-               if (!ret)
-                       dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
-               else
-                       dbgarg(cmd, "id=0x%x\n", p->id);
-               break;
-       }
-       case VIDIOC_S_CTRL:
-       {
-               struct v4l2_control *p = arg;
-               struct v4l2_ext_controls ctrls;
-               struct v4l2_ext_control ctrl;
-
-               if (!vfd->vidioc_s_ctrl && !vfd->vidioc_s_ext_ctrls)
-                       break;
-
-               dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
-
-               if (vfd->vidioc_s_ctrl) {
-                       ret = vfd->vidioc_s_ctrl(file, fh, p);
-                       break;
-               }
-               if (!vfd->vidioc_s_ext_ctrls)
-                       break;
-
-               ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
-               ctrls.count = 1;
-               ctrls.controls = &ctrl;
-               ctrl.id = p->id;
-               ctrl.value = p->value;
-               if (check_ext_ctrls(&ctrls, 1))
-                       ret = vfd->vidioc_s_ext_ctrls(file, fh, &ctrls);
-               break;
-       }
-       case VIDIOC_G_EXT_CTRLS:
-       {
-               struct v4l2_ext_controls *p = arg;
-
-               p->error_idx = p->count;
-               if (!vfd->vidioc_g_ext_ctrls)
-                       break;
-               if (check_ext_ctrls(p, 0))
-                       ret = vfd->vidioc_g_ext_ctrls(file, fh, p);
-               v4l_print_ext_ctrls(cmd, vfd, p, !ret);
-               break;
-       }
-       case VIDIOC_S_EXT_CTRLS:
-       {
-               struct v4l2_ext_controls *p = arg;
-
-               p->error_idx = p->count;
-               if (!vfd->vidioc_s_ext_ctrls)
-                       break;
-               v4l_print_ext_ctrls(cmd, vfd, p, 1);
-               if (check_ext_ctrls(p, 0))
-                       ret = vfd->vidioc_s_ext_ctrls(file, fh, p);
-               break;
-       }
-       case VIDIOC_TRY_EXT_CTRLS:
-       {
-               struct v4l2_ext_controls *p = arg;
-
-               p->error_idx = p->count;
-               if (!vfd->vidioc_try_ext_ctrls)
-                       break;
-               v4l_print_ext_ctrls(cmd, vfd, p, 1);
-               if (check_ext_ctrls(p, 0))
-                       ret = vfd->vidioc_try_ext_ctrls(file, fh, p);
-               break;
-       }
-       case VIDIOC_QUERYMENU:
-       {
-               struct v4l2_querymenu *p = arg;
-
-               if (!vfd->vidioc_querymenu)
-                       break;
-               ret = vfd->vidioc_querymenu(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",
-                               p->id, p->index, p->name);
-               else
-                       dbgarg(cmd, "id=0x%x, index=%d\n",
-                               p->id, p->index);
-               break;
-       }
-       /* --- audio ---------------------------------------------- */
-       case VIDIOC_ENUMAUDIO:
-       {
-               struct v4l2_audio *p = arg;
-
-               if (!vfd->vidioc_enumaudio)
-                       break;
-               ret = vfd->vidioc_enumaudio(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
-                                       "mode=0x%x\n", p->index, p->name,
-                                       p->capability, p->mode);
-               else
-                       dbgarg(cmd, "index=%d\n", p->index);
-               break;
-       }
-       case VIDIOC_G_AUDIO:
-       {
-               struct v4l2_audio *p = arg;
-               __u32 index = p->index;
-
-               if (!vfd->vidioc_g_audio)
-                       break;
-
-               memset(p, 0, sizeof(*p));
-               p->index = index;
-               ret = vfd->vidioc_g_audio(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
-                                       "mode=0x%x\n", p->index,
-                                       p->name, p->capability, p->mode);
-               else
-                       dbgarg(cmd, "index=%d\n", p->index);
-               break;
-       }
-       case VIDIOC_S_AUDIO:
-       {
-               struct v4l2_audio *p = arg;
-
-               if (!vfd->vidioc_s_audio)
-                       break;
-               dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
-                                       "mode=0x%x\n", p->index, p->name,
-                                       p->capability, p->mode);
-               ret = vfd->vidioc_s_audio(file, fh, p);
-               break;
-       }
-       case VIDIOC_ENUMAUDOUT:
-       {
-               struct v4l2_audioout *p=arg;
-
-               if (!vfd->vidioc_enumaudout)
-                       break;
-               dbgarg(cmd, "Enum for index=%d\n", p->index);
-               ret=vfd->vidioc_enumaudout(file, fh, p);
-               if (!ret)
-                       dbgarg2("index=%d, name=%s, capability=%d, "
-                                       "mode=%d\n", p->index, p->name,
-                                       p->capability,p->mode);
-               break;
-       }
-       case VIDIOC_G_AUDOUT:
-       {
-               struct v4l2_audioout *p=arg;
-
-               if (!vfd->vidioc_g_audout)
-                       break;
-               dbgarg(cmd, "Enum for index=%d\n", p->index);
-               ret=vfd->vidioc_g_audout(file, fh, p);
-               if (!ret)
-                       dbgarg2("index=%d, name=%s, capability=%d, "
-                                       "mode=%d\n", p->index, p->name,
-                                       p->capability,p->mode);
-               break;
-       }
-       case VIDIOC_S_AUDOUT:
-       {
-               struct v4l2_audioout *p=arg;
-
-               if (!vfd->vidioc_s_audout)
-                       break;
-               dbgarg(cmd, "index=%d, name=%s, capability=%d, "
-                                       "mode=%d\n", p->index, p->name,
-                                       p->capability,p->mode);
-
-               ret=vfd->vidioc_s_audout(file, fh, p);
-               break;
-       }
-       case VIDIOC_G_MODULATOR:
-       {
-               struct v4l2_modulator *p=arg;
-               if (!vfd->vidioc_g_modulator)
-                       break;
-               ret=vfd->vidioc_g_modulator(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "index=%d, name=%s, "
-                                       "capability=%d, rangelow=%d,"
-                                       " rangehigh=%d, txsubchans=%d\n",
-                                       p->index, p->name,p->capability,
-                                       p->rangelow, p->rangehigh,
-                                       p->txsubchans);
-               break;
-       }
-       case VIDIOC_S_MODULATOR:
-       {
-               struct v4l2_modulator *p=arg;
-               if (!vfd->vidioc_s_modulator)
-                       break;
-               dbgarg(cmd, "index=%d, name=%s, capability=%d, "
-                               "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
-                               p->index, p->name,p->capability,p->rangelow,
-                               p->rangehigh,p->txsubchans);
-                       ret=vfd->vidioc_s_modulator(file, fh, p);
-               break;
-       }
-       case VIDIOC_G_CROP:
-       {
-               struct v4l2_crop *p=arg;
-               if (!vfd->vidioc_g_crop)
-                       break;
-               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
-               ret=vfd->vidioc_g_crop(file, fh, p);
-               if (!ret) {
-                       dbgrect(vfd, "", &p->c);
-               }
-               break;
-       }
-       case VIDIOC_S_CROP:
-       {
-               struct v4l2_crop *p=arg;
-               if (!vfd->vidioc_s_crop)
-                       break;
-               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
-               dbgrect(vfd, "", &p->c);
-               ret=vfd->vidioc_s_crop(file, fh, p);
-               break;
-       }
-       case VIDIOC_CROPCAP:
-       {
-               struct v4l2_cropcap *p = arg;
-
-               /*FIXME: Should also show v4l2_fract pixelaspect */
-               if (!vfd->vidioc_cropcap)
-                       break;
-               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
-               ret = vfd->vidioc_cropcap(file, fh, p);
-               if (!ret) {
-                       dbgrect(vfd, "bounds ", &p->bounds);
-                       dbgrect(vfd, "defrect ", &p->defrect);
-               }
-               break;
-       }
-       case VIDIOC_G_JPEGCOMP:
-       {
-               struct v4l2_jpegcompression *p=arg;
-               if (!vfd->vidioc_g_jpegcomp)
-                       break;
-               ret=vfd->vidioc_g_jpegcomp(file, fh, p);
-               if (!ret)
-                       dbgarg (cmd, "quality=%d, APPn=%d, "
-                                               "APP_len=%d, COM_len=%d, "
-                                               "jpeg_markers=%d\n",
-                                               p->quality,p->APPn,p->APP_len,
-                                               p->COM_len,p->jpeg_markers);
-               break;
-       }
-       case VIDIOC_S_JPEGCOMP:
-       {
-               struct v4l2_jpegcompression *p=arg;
-               if (!vfd->vidioc_g_jpegcomp)
-                       break;
-               dbgarg (cmd, "quality=%d, APPn=%d, APP_len=%d, "
-                                       "COM_len=%d, jpeg_markers=%d\n",
-                                       p->quality,p->APPn,p->APP_len,
-                                       p->COM_len,p->jpeg_markers);
-                       ret=vfd->vidioc_s_jpegcomp(file, fh, p);
-               break;
-       }
-       case VIDIOC_G_ENC_INDEX:
-       {
-               struct v4l2_enc_idx *p=arg;
-
-               if (!vfd->vidioc_g_enc_index)
-                       break;
-               ret=vfd->vidioc_g_enc_index(file, fh, p);
-               if (!ret)
-                       dbgarg (cmd, "entries=%d, entries_cap=%d\n",
-                                       p->entries,p->entries_cap);
-               break;
-       }
-       case VIDIOC_ENCODER_CMD:
-       {
-               struct v4l2_encoder_cmd *p = arg;
-
-               if (!vfd->vidioc_encoder_cmd)
-                       break;
-               memset(&p->raw, 0, sizeof(p->raw));
-               ret = vfd->vidioc_encoder_cmd(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
-               break;
-       }
-       case VIDIOC_TRY_ENCODER_CMD:
-       {
-               struct v4l2_encoder_cmd *p = arg;
-
-               if (!vfd->vidioc_try_encoder_cmd)
-                       break;
-               memset(&p->raw, 0, sizeof(p->raw));
-               ret = vfd->vidioc_try_encoder_cmd(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
-               break;
-       }
-       case VIDIOC_G_PARM:
-       {
-               struct v4l2_streamparm *p=arg;
-               __u32 type=p->type;
-
-               memset(p,0,sizeof(*p));
-               p->type=type;
-
-               if (vfd->vidioc_g_parm) {
-                       ret=vfd->vidioc_g_parm(file, fh, p);
-               } else {
-                       struct v4l2_standard s;
-
-                       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                               return -EINVAL;
-
-                       v4l2_video_std_construct(&s, vfd->current_norm,
-                                                v4l2_norm_to_name(vfd->current_norm));
-
-                       p->parm.capture.timeperframe = s.frameperiod;
-                       ret=0;
-               }
-
-               dbgarg (cmd, "type=%d\n", p->type);
-               break;
-       }
-       case VIDIOC_S_PARM:
-       {
-               struct v4l2_streamparm *p=arg;
-               if (!vfd->vidioc_s_parm)
-                       break;
-               dbgarg (cmd, "type=%d\n", p->type);
-               ret=vfd->vidioc_s_parm(file, fh, p);
-               break;
-       }
-       case VIDIOC_G_TUNER:
-       {
-               struct v4l2_tuner *p = arg;
-               __u32 index = p->index;
-
-               if (!vfd->vidioc_g_tuner)
-                       break;
-
-               memset(p, 0, sizeof(*p));
-               p->index = index;
-
-               ret = vfd->vidioc_g_tuner(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "index=%d, name=%s, type=%d, "
-                                       "capability=0x%x, rangelow=%d, "
-                                       "rangehigh=%d, signal=%d, afc=%d, "
-                                       "rxsubchans=0x%x, audmode=%d\n",
-                                       p->index, p->name, p->type,
-                                       p->capability, p->rangelow,
-                                       p->rangehigh, p->signal, p->afc,
-                                       p->rxsubchans, p->audmode);
-               break;
-       }
-       case VIDIOC_S_TUNER:
-       {
-               struct v4l2_tuner *p = arg;
-
-               if (!vfd->vidioc_s_tuner)
-                       break;
-               dbgarg(cmd, "index=%d, name=%s, type=%d, "
-                               "capability=0x%x, rangelow=%d, "
-                               "rangehigh=%d, signal=%d, afc=%d, "
-                               "rxsubchans=0x%x, audmode=%d\n",
-                               p->index, p->name, p->type,
-                               p->capability, p->rangelow,
-                               p->rangehigh, p->signal, p->afc,
-                               p->rxsubchans, p->audmode);
-               ret = vfd->vidioc_s_tuner(file, fh, p);
-               break;
-       }
-       case VIDIOC_G_FREQUENCY:
-       {
-               struct v4l2_frequency *p = arg;
-
-               if (!vfd->vidioc_g_frequency)
-                       break;
-
-               memset(p->reserved, 0, sizeof(p->reserved));
-
-               ret = vfd->vidioc_g_frequency(file, fh, p);
-               if (!ret)
-                       dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
-                                       p->tuner, p->type, p->frequency);
-               break;
-       }
-       case VIDIOC_S_FREQUENCY:
-       {
-               struct v4l2_frequency *p=arg;
-               if (!vfd->vidioc_s_frequency)
-                       break;
-               dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
-                               p->tuner,p->type,p->frequency);
-               ret=vfd->vidioc_s_frequency(file, fh, p);
-               break;
-       }
-       case VIDIOC_G_SLICED_VBI_CAP:
-       {
-               struct v4l2_sliced_vbi_cap *p = arg;
-               __u32 type = p->type;
-
-               if (!vfd->vidioc_g_sliced_vbi_cap)
-                       break;
-               memset(p, 0, sizeof(*p));
-               p->type = type;
-               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
-               ret = vfd->vidioc_g_sliced_vbi_cap(file, fh, p);
-               if (!ret)
-                       dbgarg2("service_set=%d\n", p->service_set);
-               break;
-       }
-       case VIDIOC_LOG_STATUS:
-       {
-               if (!vfd->vidioc_log_status)
-                       break;
-               ret=vfd->vidioc_log_status(file, fh);
-               break;
-       }
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_DBG_G_REGISTER:
-       {
-               struct v4l2_register *p=arg;
-               if (!capable(CAP_SYS_ADMIN))
-                       ret=-EPERM;
-               else if (vfd->vidioc_g_register)
-                       ret=vfd->vidioc_g_register(file, fh, p);
-               break;
-       }
-       case VIDIOC_DBG_S_REGISTER:
-       {
-               struct v4l2_register *p=arg;
-               if (!capable(CAP_SYS_ADMIN))
-                       ret=-EPERM;
-               else if (vfd->vidioc_s_register)
-                       ret=vfd->vidioc_s_register(file, fh, p);
-               break;
-       }
-#endif
-       case VIDIOC_G_CHIP_IDENT:
-       {
-               struct v4l2_chip_ident *p=arg;
-               if (!vfd->vidioc_g_chip_ident)
-                       break;
-               ret=vfd->vidioc_g_chip_ident(file, fh, p);
-               if (!ret)
-                       dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
-               break;
-       }
-       default:
-       {
-               if (!vfd->vidioc_default)
-                       break;
-               ret = vfd->vidioc_default(file, fh, cmd, arg);
-               break;
-       }
-       case VIDIOC_S_HW_FREQ_SEEK:
-       {
-               struct v4l2_hw_freq_seek *p = arg;
-               if (!vfd->vidioc_s_hw_freq_seek)
-                       break;
-               dbgarg(cmd,
-                       "tuner=%d, type=%d, seek_upward=%d, wrap_around=%d\n",
-                       p->tuner, p->type, p->seek_upward, p->wrap_around);
-               ret = vfd->vidioc_s_hw_freq_seek(file, fh, p);
-               break;
-       }
-       } /* switch */
-
-       if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
-               if (ret < 0) {
-                       v4l_print_ioctl(vfd->name, cmd);
-                       printk(KERN_CONT " error %d\n", ret);
-               }
-       }
-
-       return ret;
-}
-
-int video_ioctl2 (struct inode *inode, struct file *file,
-              unsigned int cmd, unsigned long arg)
-{
-       char    sbuf[128];
-       void    *mbuf = NULL;
-       void    *parg = NULL;
-       int     err  = -EINVAL;
-       int     is_ext_ctrl;
-       size_t  ctrls_size = 0;
-       void __user *user_ptr = NULL;
-
-#ifdef __OLD_VIDIOC_
-       cmd = video_fix_command(cmd);
-#endif
-       is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
-                      cmd == VIDIOC_TRY_EXT_CTRLS);
-
-       /*  Copy arguments into temp kernel buffer  */
-       switch (_IOC_DIR(cmd)) {
-       case _IOC_NONE:
-               parg = NULL;
-               break;
-       case _IOC_READ:
-       case _IOC_WRITE:
-       case (_IOC_WRITE | _IOC_READ):
-               if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
-                       parg = sbuf;
-               } else {
-                       /* too big to allocate from stack */
-                       mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
-                       if (NULL == mbuf)
-                               return -ENOMEM;
-                       parg = mbuf;
-               }
-
-               err = -EFAULT;
-               if (_IOC_DIR(cmd) & _IOC_WRITE)
-                       if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
-                               goto out;
-               break;
-       }
-
-       if (is_ext_ctrl) {
-               struct v4l2_ext_controls *p = parg;
-
-               /* In case of an error, tell the caller that it wasn't
-                  a specific control that caused it. */
-               p->error_idx = p->count;
-               user_ptr = (void __user *)p->controls;
-               if (p->count) {
-                       ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
-                       /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
-                       mbuf = kmalloc(ctrls_size, GFP_KERNEL);
-                       err = -ENOMEM;
-                       if (NULL == mbuf)
-                               goto out_ext_ctrl;
-                       err = -EFAULT;
-                       if (copy_from_user(mbuf, user_ptr, ctrls_size))
-                               goto out_ext_ctrl;
-                       p->controls = mbuf;
-               }
-       }
-
-       /* Handles IOCTL */
-       err = __video_do_ioctl(inode, file, cmd, parg);
-       if (err == -ENOIOCTLCMD)
-               err = -EINVAL;
-       if (is_ext_ctrl) {
-               struct v4l2_ext_controls *p = parg;
-
-               p->controls = (void *)user_ptr;
-               if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
-                       err = -EFAULT;
-               goto out_ext_ctrl;
-       }
-       if (err < 0)
-               goto out;
-
-out_ext_ctrl:
-       /*  Copy results into user buffer  */
-       switch (_IOC_DIR(cmd))
-       {
-       case _IOC_READ:
-       case (_IOC_WRITE | _IOC_READ):
-               if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
-                       err = -EFAULT;
-               break;
-       }
-
-out:
-       kfree(mbuf);
-       return err;
-}
-EXPORT_SYMBOL(video_ioctl2);
-
-/**
- * get_index - assign stream number based on parent device
- * @vdev: video_device to assign index number to, vdev->dev should be assigned
- * @num: -1 if auto assign, requested number otherwise
- *
- *
- * returns -ENFILE if num is already in use, a free index number if
- * successful.
- */
-static int get_index(struct video_device *vdev, int num)
-{
-       u32 used = 0;
-       const int max_index = sizeof(used) * 8 - 1;
-       int i;
-
-       /* Currently a single v4l driver instance cannot create more than
-          32 devices.
-          Increase to u64 or an array of u32 if more are needed. */
-       if (num > max_index) {
-               printk(KERN_ERR "videodev: %s num is too large\n", __func__);
-               return -EINVAL;
-       }
-
-       for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
-               if (video_device[i] != NULL &&
-                   video_device[i] != vdev &&
-                   video_device[i]->dev == vdev->dev) {
-                       used |= 1 << video_device[i]->index;
-               }
-       }
-
-       if (num >= 0) {
-               if (used & (1 << num))
-                       return -ENFILE;
-               return num;
-       }
-
-       i = ffz(used);
-       return i > max_index ? -ENFILE : i;
-}
-
-static const struct file_operations video_fops;
-
-int video_register_device(struct video_device *vfd, int type, int nr)
-{
-       return video_register_device_index(vfd, type, nr, -1);
-}
-EXPORT_SYMBOL(video_register_device);
-
-/**
- *     video_register_device - register video4linux devices
- *     @vfd:  video device structure we want to register
- *     @type: type of device to register
- *     @nr:   which device number (0 == /dev/video0, 1 == /dev/video1, ...
- *             -1 == first free)
- *
- *     The registration code assigns minor numbers based on the type
- *     requested. -ENFILE is returned in all the device slots for this
- *     category are full. If not then the minor field is set and the
- *     driver initialize function is called (if non %NULL).
- *
- *     Zero is returned on success.
- *
- *     Valid types are
- *
- *     %VFL_TYPE_GRABBER - A frame grabber
- *
- *     %VFL_TYPE_VTX - A teletext device
- *
- *     %VFL_TYPE_VBI - Vertical blank data (undecoded)
- *
- *     %VFL_TYPE_RADIO - A radio card
- */
-
-int video_register_device_index(struct video_device *vfd, int type, int nr,
-                                       int index)
-{
-       int i=0;
-       int base;
-       int end;
-       int ret;
-       char *name_base;
-
-       switch(type)
-       {
-               case VFL_TYPE_GRABBER:
-                       base=MINOR_VFL_TYPE_GRABBER_MIN;
-                       end=MINOR_VFL_TYPE_GRABBER_MAX+1;
-                       name_base = "video";
-                       break;
-               case VFL_TYPE_VTX:
-                       base=MINOR_VFL_TYPE_VTX_MIN;
-                       end=MINOR_VFL_TYPE_VTX_MAX+1;
-                       name_base = "vtx";
-                       break;
-               case VFL_TYPE_VBI:
-                       base=MINOR_VFL_TYPE_VBI_MIN;
-                       end=MINOR_VFL_TYPE_VBI_MAX+1;
-                       name_base = "vbi";
-                       break;
-               case VFL_TYPE_RADIO:
-                       base=MINOR_VFL_TYPE_RADIO_MIN;
-                       end=MINOR_VFL_TYPE_RADIO_MAX+1;
-                       name_base = "radio";
-                       break;
-               default:
-                       printk(KERN_ERR "%s called with unknown type: %d\n",
-                              __func__, type);
-                       return -1;
-       }
-
-       /* pick a minor number */
-       mutex_lock(&videodev_lock);
-       if (nr >= 0  &&  nr < end-base) {
-               /* use the one the driver asked for */
-               i = base+nr;
-               if (NULL != video_device[i]) {
-                       mutex_unlock(&videodev_lock);
-                       return -ENFILE;
-               }
-       } else {
-               /* use first free */
-               for(i=base;i<end;i++)
-                       if (NULL == video_device[i])
-                               break;
-               if (i == end) {
-                       mutex_unlock(&videodev_lock);
-                       return -ENFILE;
-               }
-       }
-       video_device[i]=vfd;
-       vfd->minor=i;
-
-       ret = get_index(vfd, index);
-       vfd->index = ret;
-
-       mutex_unlock(&videodev_lock);
-
-       if (ret < 0) {
-               printk(KERN_ERR "%s: get_index failed\n", __func__);
-               goto fail_minor;
-       }
-
-       mutex_init(&vfd->lock);
-
-       /* sysfs class */
-       memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev));
-       vfd->class_dev.class       = &video_class;
-       vfd->class_dev.devt        = MKDEV(VIDEO_MAJOR, vfd->minor);
-       if (vfd->dev)
-               vfd->class_dev.parent = vfd->dev;
-       sprintf(vfd->class_dev.bus_id, "%s%d", name_base, i - base);
-       ret = device_register(&vfd->class_dev);
-       if (ret < 0) {
-               printk(KERN_ERR "%s: device_register failed\n", __func__);
-               goto fail_minor;
-       }
-
-#if 1
-       /* needed until all drivers are fixed */
-       if (!vfd->release)
-               printk(KERN_WARNING "videodev: \"%s\" has no release callback. "
-                      "Please fix your driver for proper sysfs support, see "
-                      "http://lwn.net/Articles/36850/\n", vfd->name);
-#endif
-       return 0;
-
-fail_minor:
-       mutex_lock(&videodev_lock);
-       video_device[vfd->minor] = NULL;
-       vfd->minor = -1;
-       mutex_unlock(&videodev_lock);
-       return ret;
-}
-EXPORT_SYMBOL(video_register_device_index);
-
-/**
- *     video_unregister_device - unregister a video4linux device
- *     @vfd: the device to unregister
- *
- *     This unregisters the passed device and deassigns the minor
- *     number. Future open calls will be met with errors.
- */
-
-void video_unregister_device(struct video_device *vfd)
-{
-       mutex_lock(&videodev_lock);
-       if(video_device[vfd->minor]!=vfd)
-               panic("videodev: bad unregister");
-
-       video_device[vfd->minor]=NULL;
-       device_unregister(&vfd->class_dev);
-       mutex_unlock(&videodev_lock);
-}
-EXPORT_SYMBOL(video_unregister_device);
-
-/*
- * Video fs operations
- */
-static const struct file_operations video_fops=
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .open           = video_open,
-};
-
-/*
- *     Initialise video for linux
- */
-
-static int __init videodev_init(void)
-{
-       int ret;
-
-       printk(KERN_INFO "Linux video capture interface: v2.00\n");
-       if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) {
-               printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR);
-               return -EIO;
-       }
-
-       ret = class_register(&video_class);
-       if (ret < 0) {
-               unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
-               printk(KERN_WARNING "video_dev: class_register failed\n");
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static void __exit videodev_exit(void)
-{
-       class_unregister(&video_class);
-       unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
-}
-
-module_init(videodev_init)
-module_exit(videodev_exit)
-
-MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2");
-MODULE_LICENSE("GPL");
-
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
index 01ea99c9bc1aa5db2d208bff7e23aa54463ab7c6..3989b0eded28c7d8152ec013e3ea270982b45785 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-sgi.h>
 
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <linux/video_decoder.h>
 #include <linux/mutex.h>
@@ -4385,8 +4385,6 @@ static const struct file_operations vino_fops = {
 
 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 */
        .fops           = &vino_fops,
        .minor          = -1,
 };
index 059b01c11dc133e4abb708ace787fa9cc3242843..3518af071a2e2633cc7ec7a62cde3a6ab5cb6c95 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/interrupt.h>
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/kthread.h>
 #include <linux/highmem.h>
 #include <linux/freezer.h>
@@ -1065,13 +1066,7 @@ static const struct file_operations vivi_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device vivi_template = {
-       .name           = "vivi",
-       .type           = VID_TYPE_CAPTURE,
-       .fops           = &vivi_fops,
-       .minor          = -1,
-       .release        = video_device_release,
-
+static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
        .vidioc_querycap      = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
@@ -1093,6 +1088,15 @@ static struct video_device vivi_template = {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        .vidiocgmbuf          = vidiocgmbuf,
 #endif
+};
+
+static struct video_device vivi_template = {
+       .name           = "vivi",
+       .fops           = &vivi_fops,
+       .ioctl_ops      = &vivi_ioctl_ops,
+       .minor          = -1,
+       .release        = video_device_release,
+
        .tvnorms              = V4L2_STD_525_60,
        .current_norm         = V4L2_STD_NTSC_M,
 };
index cbecb3cbbbaa83b9a6e1f5ddfe9283427f9af830..577956c5410bf44b478ff8f8166b3a38edb5026a 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-i2c-drv.h>
index 33f702698a56f06d629bceb96bef454661282855..9402f40095b469f1caced200f9f63e04b74b7c00 100644 (file)
@@ -57,8 +57,9 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/parport.h>
 
 /*#define DEBUG*/                              /* Undef me for production */
@@ -195,9 +196,7 @@ static const struct file_operations w9966_fops = {
        .llseek         = no_llseek,
 };
 static struct video_device w9966_template = {
-       .owner          = THIS_MODULE,
        .name           = W9966_DRIVERNAME,
-       .type           = VID_TYPE_CAPTURE | VID_TYPE_SCALES,
        .fops           = &w9966_fops,
 };
 
index 840522442d07d4a6316a76a7f658481da60de77f..168baabe46591b02b9276e11987aaee44679ac63 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/page.h>
 #include <asm/uaccess.h>
 #include <linux/page-flags.h>
+#include <media/v4l2-ioctl.h>
 
 #include "w9968cf.h"
 #include "w9968cf_decoder.h"
@@ -3549,13 +3550,11 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        }
 
        strcpy(cam->v4ldev->name, symbolic(camlist, mod_id));
-       cam->v4ldev->owner = THIS_MODULE;
-       cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
        cam->v4ldev->fops = &w9968cf_fops;
        cam->v4ldev->minor = video_nr[dev_nr];
        cam->v4ldev->release = video_device_release;
        video_set_drvdata(cam->v4ldev, cam);
-       cam->v4ldev->dev = &cam->dev;
+       cam->v4ldev->parent = &cam->dev;
 
        err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
                                    video_nr[dev_nr]);
index 3c95316bc030cf7dcbcfea1023a4cc5b5426eec7..30032e15e23c2761fc9461462466c0cf82eb381c 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef _W9968CF_H_
 #define _W9968CF_H_
 
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include <linux/device.h>
index 7be47a255853e13c1bedcb1439ba91844697ab9a..95c79ad804872b0f0df78bea3ecb4283174a06bd 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-i2c-drv.h>
index c2ab70a04a740455c3da62ae421a6e6e3ee9db56..48df661d4fc320aa8426b1c7ffc085941730e90b 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-i2c-drv-legacy.h>
index 7bbab541a309d59f6141b7a0b10ff918baf945ce..b1b5cceb4baa3c0172720942693a68b0ad793a74 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/usb.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
index e5c4e9f5193fed56cbd2e504e25dc2fdeb662e5b..550ce7bd5c87d8720402abc0e98f15d7b654b5f9 100644 (file)
@@ -1985,8 +1985,6 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        }
 
        strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera");
-       cam->v4ldev->owner = THIS_MODULE;
-       cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
        cam->v4ldev->fops = &zc0301_fops;
        cam->v4ldev->minor = video_nr[dev_nr];
        cam->v4ldev->release = video_device_release;
index 0929edb2d4f182a3a79ddf051e97692912db2267..d842a7cb99d274ad493fea6eed822a918acd58e5 100644 (file)
@@ -161,7 +161,7 @@ static struct pci_device_id zr36067_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
 
 int zoran_num;                 /* number of Buzs in use */
-struct zoran zoran[BUZ_MAX];
+struct zoran *zoran[BUZ_MAX];
 
 /* videocodec bus functions ZR36060 */
 static u32
@@ -355,9 +355,15 @@ i2cid_to_modulename (u16 i2c_id)
        case I2C_DRIVERID_BT856:
                name = "bt856";
                break;
+       case I2C_DRIVERID_BT866:
+               name = "bt866";
+               break;
        case I2C_DRIVERID_VPX3220:
                name = "vpx3220";
                break;
+       case I2C_DRIVERID_KS0127:
+               name = "ks0127";
+               break;
        }
 
        return name;
@@ -1164,7 +1170,7 @@ static void
 zoran_release (struct zoran *zr)
 {
        if (!zr->initialized)
-               return;
+               goto exit_free;
        /* unregister videocodec bus */
        if (zr->codec) {
                struct videocodec_master *master = zr->codec->master_data;
@@ -1192,6 +1198,8 @@ zoran_release (struct zoran *zr)
        iounmap(zr->zr36057_mem);
        pci_disable_device(zr->pci_dev);
        video_unregister_device(zr->video_dev);
+exit_free:
+       kfree(zr);
 }
 
 void
@@ -1269,8 +1277,14 @@ find_zr36057 (void)
        while (zoran_num < BUZ_MAX &&
               (dev = pci_get_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) {
                card_num = card[zoran_num];
-               zr = &zoran[zoran_num];
-               memset(zr, 0, sizeof(struct zoran));    // Just in case if previous cycle failed
+               zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
+               if (!zr) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: find_zr36057() - kzalloc failed\n",
+                               ZORAN_NAME);
+                       continue;
+               }
                zr->pci_dev = dev;
                //zr->zr36057_mem = NULL;
                zr->id = zoran_num;
@@ -1278,7 +1292,7 @@ find_zr36057 (void)
                spin_lock_init(&zr->spinlock);
                mutex_init(&zr->resource_lock);
                if (pci_enable_device(dev))
-                       continue;
+                       goto zr_free_mem;
                zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0);
                pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION,
                                     &zr->revision);
@@ -1294,7 +1308,7 @@ find_zr36057 (void)
                                        KERN_ERR
                                        "%s: find_zr36057() - no card specified, please use the card=X insmod option\n",
                                        ZR_DEVNAME(zr));
-                               continue;
+                               goto zr_free_mem;
                        }
                } else {
                        int i;
@@ -1333,7 +1347,7 @@ find_zr36057 (void)
                                                KERN_ERR
                                                "%s: find_zr36057() - unknown card\n",
                                                ZR_DEVNAME(zr));
-                                       continue;
+                                       goto zr_free_mem;
                                }
                        }
                }
@@ -1343,7 +1357,7 @@ find_zr36057 (void)
                                KERN_ERR
                                "%s: find_zr36057() - invalid cardnum %d\n",
                                ZR_DEVNAME(zr), card_num);
-                       continue;
+                       goto zr_free_mem;
                }
 
                /* even though we make this a non pointer and thus
@@ -1361,7 +1375,7 @@ find_zr36057 (void)
                                KERN_ERR
                                "%s: find_zr36057() - ioremap failed\n",
                                ZR_DEVNAME(zr));
-                       continue;
+                       goto zr_free_mem;
                }
 
                result = request_irq(zr->pci_dev->irq,
@@ -1530,7 +1544,7 @@ find_zr36057 (void)
                }
                /* Success so keep the pci_dev referenced */
                pci_dev_get(zr->pci_dev);
-               zoran_num++;
+               zoran[zoran_num++] = zr;
                continue;
 
                // Init errors
@@ -1549,6 +1563,8 @@ find_zr36057 (void)
                free_irq(zr->pci_dev->irq, zr);
              zr_unmap:
                iounmap(zr->zr36057_mem);
+             zr_free_mem:
+               kfree(zr);
                continue;
        }
        if (dev)        /* Clean up ref count on early exit */
@@ -1620,7 +1636,7 @@ init_dc10_cards (void)
 
        /* take care of Natoma chipset and a revision 1 zr36057 */
        for (i = 0; i < zoran_num; i++) {
-               struct zoran *zr = &zoran[i];
+               struct zoran *zr = zoran[i];
 
                if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
                        zr->jpg_buffers.need_contiguous = 1;
@@ -1632,7 +1648,7 @@ init_dc10_cards (void)
 
                if (zr36057_init(zr) < 0) {
                        for (i = 0; i < zoran_num; i++)
-                               zoran_release(&zoran[i]);
+                               zoran_release(zoran[i]);
                        return -EIO;
                }
                zoran_proc_init(zr);
@@ -1647,7 +1663,7 @@ unload_dc10_cards (void)
        int i;
 
        for (i = 0; i < zoran_num; i++)
-               zoran_release(&zoran[i]);
+               zoran_release(zoran[i]);
 }
 
 module_init(init_dc10_cards);
index 1b5c4171cf9c37f0b7c3f6f365490ded31b95da2..e4dc9d29b404f6691447b27426d46482cd50ca1f 100644 (file)
@@ -41,7 +41,7 @@ extern int zr36067_debug;
 /* Anybody who uses more than four? */
 #define BUZ_MAX 4
 extern int zoran_num;
-extern struct zoran zoran[BUZ_MAX];
+extern struct zoran *zoran[BUZ_MAX];
 
 extern struct video_device zoran_template;
 
index c0675921fe20465ff80f2d72881264d8a43f07f6..ec6f59674b105c281d25a6a59e8b6696eeff7f7d 100644 (file)
@@ -71,6 +71,7 @@
 
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include "videocodec.h"
 
 #include <asm/byteorder.h>
@@ -1212,8 +1213,8 @@ zoran_open (struct inode *inode,
 
        /* find the device */
        for (i = 0; i < zoran_num; i++) {
-               if (zoran[i].video_dev->minor == minor) {
-                       zr = &zoran[i];
+               if (zoran[i]->video_dev->minor == minor) {
+                       zr = zoran[i];
                        break;
                }
        }
@@ -4643,8 +4644,6 @@ static const struct file_operations zoran_fops = {
 
 struct video_device zoran_template __devinitdata = {
        .name = ZORAN_NAME,
-       .type = ZORAN_VID_TYPE,
-       .type2 = ZORAN_V4L2_VID_FLAGS,
        .fops = &zoran_fops,
        .release = &zoran_vdev_release,
        .minor = -1
index 485df2e3613286292c842769efd8116f87c84b15..18d1c4ba79fbf7c8384ba8497320d180ad226b44 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/proc_fs.h>
 #include <linux/highmem.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 
 /* Version Information */
@@ -761,14 +762,7 @@ static const struct file_operations zr364xx_fops = {
        .llseek = no_llseek,
 };
 
-static struct video_device zr364xx_template = {
-       .owner = THIS_MODULE,
-       .name = DRIVER_DESC,
-       .type = VID_TYPE_CAPTURE,
-       .fops = &zr364xx_fops,
-       .release = video_device_release,
-       .minor = -1,
-
+static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
        .vidioc_querycap        = zr364xx_vidioc_querycap,
        .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
@@ -784,6 +778,14 @@ static struct video_device zr364xx_template = {
        .vidioc_s_ctrl          = zr364xx_vidioc_s_ctrl,
 };
 
+static struct video_device zr364xx_template = {
+       .name = DRIVER_DESC,
+       .fops = &zr364xx_fops,
+       .ioctl_ops = &zr364xx_ioctl_ops,
+       .release = video_device_release,
+       .minor = -1,
+};
+
 
 
 /*******************/
index 61b98c333cb0fafcd9dad77f00e7285f2ca1b17a..a38005008a2019c7beb7f1ae32193d488438bf78 100644 (file)
@@ -249,8 +249,11 @@ EXPORT_SYMBOL(memstick_next_req);
  */
 void memstick_new_req(struct memstick_host *host)
 {
-       host->retries = cmd_retries;
-       host->request(host);
+       if (host->card) {
+               host->retries = cmd_retries;
+               INIT_COMPLETION(host->card->mrq_complete);
+               host->request(host);
+       }
 }
 EXPORT_SYMBOL(memstick_new_req);
 
@@ -415,10 +418,14 @@ err_out:
        return NULL;
 }
 
-static void memstick_power_on(struct memstick_host *host)
+static int memstick_power_on(struct memstick_host *host)
 {
-       host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
-       host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
+       int rc = host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
+
+       if (!rc)
+               rc = host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
+
+       return rc;
 }
 
 static void memstick_check(struct work_struct *work)
@@ -429,8 +436,11 @@ static void memstick_check(struct work_struct *work)
 
        dev_dbg(&host->dev, "memstick_check started\n");
        mutex_lock(&host->lock);
-       if (!host->card)
-               memstick_power_on(host);
+       if (!host->card) {
+               if (memstick_power_on(host))
+                       goto out_power_off;
+       } else
+               host->card->stop(host->card);
 
        card = memstick_alloc_card(host);
 
@@ -448,7 +458,8 @@ static void memstick_check(struct work_struct *work)
                            || !(host->card->check(host->card))) {
                                device_unregister(&host->card->dev);
                                host->card = NULL;
-                       }
+                       } else
+                               host->card->start(host->card);
                }
 
                if (!host->card) {
@@ -461,6 +472,7 @@ static void memstick_check(struct work_struct *work)
                        kfree(card);
        }
 
+out_power_off:
        if (!host->card)
                host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
 
@@ -573,11 +585,15 @@ EXPORT_SYMBOL(memstick_suspend_host);
  */
 void memstick_resume_host(struct memstick_host *host)
 {
+       int rc = 0;
+
        mutex_lock(&host->lock);
        if (host->card)
-               memstick_power_on(host);
+               rc = memstick_power_on(host);
        mutex_unlock(&host->lock);
-       memstick_detect_change(host);
+
+       if (!rc)
+               memstick_detect_change(host);
 }
 EXPORT_SYMBOL(memstick_resume_host);
 
index 477d0fb6e5883dafcaca0d273e79893c10c4173f..44b1817f2f2f02116d2f78a9d16b19c623f93d7c 100644 (file)
@@ -136,9 +136,8 @@ struct mspro_block_data {
        unsigned int          caps;
        struct gendisk        *disk;
        struct request_queue  *queue;
+       struct request        *block_req;
        spinlock_t            q_lock;
-       wait_queue_head_t     q_wait;
-       struct task_struct    *q_thread;
 
        unsigned short        page_size;
        unsigned short        cylinders;
@@ -147,9 +146,10 @@ struct mspro_block_data {
 
        unsigned char         system;
        unsigned char         read_only:1,
-                             active:1,
+                             eject:1,
                              has_request:1,
-                             data_dir:1;
+                             data_dir:1,
+                             active:1;
        unsigned char         transfer_cmd;
 
        int                   (*mrq_handler)(struct memstick_dev *card,
@@ -160,12 +160,14 @@ struct mspro_block_data {
        struct scatterlist    req_sg[MSPRO_BLOCK_MAX_SEGS];
        unsigned int          seg_count;
        unsigned int          current_seg;
-       unsigned short        current_page;
+       unsigned int          current_page;
 };
 
 static DEFINE_IDR(mspro_block_disk_idr);
 static DEFINE_MUTEX(mspro_block_disk_lock);
 
+static int mspro_block_complete_req(struct memstick_dev *card, int error);
+
 /*** Block device ***/
 
 static int mspro_block_bd_open(struct inode *inode, struct file *filp)
@@ -197,8 +199,10 @@ static int mspro_block_disk_release(struct gendisk *disk)
 
        mutex_lock(&mspro_block_disk_lock);
 
-       if (msb->usage_count) {
-               msb->usage_count--;
+       if (msb) {
+               if (msb->usage_count)
+                       msb->usage_count--;
+
                if (!msb->usage_count) {
                        kfree(msb);
                        disk->private_data = NULL;
@@ -523,11 +527,13 @@ static int h_mspro_block_req_init(struct memstick_dev *card,
 static int h_mspro_block_default(struct memstick_dev *card,
                                 struct memstick_request **mrq)
 {
-       complete(&card->mrq_complete);
-       if (!(*mrq)->error)
-               return -EAGAIN;
-       else
-               return (*mrq)->error;
+       return mspro_block_complete_req(card, (*mrq)->error);
+}
+
+static int h_mspro_block_default_bad(struct memstick_dev *card,
+                                    struct memstick_request **mrq)
+{
+       return -ENXIO;
 }
 
 static int h_mspro_block_get_ro(struct memstick_dev *card,
@@ -535,44 +541,30 @@ static int h_mspro_block_get_ro(struct memstick_dev *card,
 {
        struct mspro_block_data *msb = memstick_get_drvdata(card);
 
-       if ((*mrq)->error) {
-               complete(&card->mrq_complete);
-               return (*mrq)->error;
+       if (!(*mrq)->error) {
+               if ((*mrq)->data[offsetof(struct ms_status_register, status0)]
+                   & MEMSTICK_STATUS0_WP)
+                       msb->read_only = 1;
+               else
+                       msb->read_only = 0;
        }
 
-       if ((*mrq)->data[offsetof(struct ms_status_register, status0)]
-           & MEMSTICK_STATUS0_WP)
-               msb->read_only = 1;
-       else
-               msb->read_only = 0;
-
-       complete(&card->mrq_complete);
-       return -EAGAIN;
+       return mspro_block_complete_req(card, (*mrq)->error);
 }
 
 static int h_mspro_block_wait_for_ced(struct memstick_dev *card,
                                      struct memstick_request **mrq)
 {
-       if ((*mrq)->error) {
-               complete(&card->mrq_complete);
-               return (*mrq)->error;
-       }
-
        dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]);
 
-       if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) {
-               card->current_mrq.error = -EFAULT;
-               complete(&card->mrq_complete);
-               return card->current_mrq.error;
+       if (!(*mrq)->error) {
+               if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR))
+                       (*mrq)->error = -EFAULT;
+               else if (!((*mrq)->data[0] & MEMSTICK_INT_CED))
+                       return 0;
        }
 
-       if (!((*mrq)->data[0] & MEMSTICK_INT_CED))
-               return 0;
-       else {
-               card->current_mrq.error = 0;
-               complete(&card->mrq_complete);
-               return -EAGAIN;
-       }
+       return mspro_block_complete_req(card, (*mrq)->error);
 }
 
 static int h_mspro_block_transfer_data(struct memstick_dev *card,
@@ -583,10 +575,8 @@ static int h_mspro_block_transfer_data(struct memstick_dev *card,
        struct scatterlist t_sg = { 0 };
        size_t t_offset;
 
-       if ((*mrq)->error) {
-               complete(&card->mrq_complete);
-               return (*mrq)->error;
-       }
+       if ((*mrq)->error)
+               return mspro_block_complete_req(card, (*mrq)->error);
 
        switch ((*mrq)->tpc) {
        case MS_TPC_WRITE_REG:
@@ -617,8 +607,8 @@ has_int_reg:
 
                        if (msb->current_seg == msb->seg_count) {
                                if (t_val & MEMSTICK_INT_CED) {
-                                       complete(&card->mrq_complete);
-                                       return -EAGAIN;
+                                       return mspro_block_complete_req(card,
+                                                                       0);
                                } else {
                                        card->next_request
                                                = h_mspro_block_wait_for_ced;
@@ -666,140 +656,184 @@ has_int_reg:
 
 /*** Data transfer ***/
 
-static void mspro_block_process_request(struct memstick_dev *card,
-                                       struct request *req)
+static int mspro_block_issue_req(struct memstick_dev *card, int chunk)
 {
        struct mspro_block_data *msb = memstick_get_drvdata(card);
-       struct mspro_param_register param;
-       int rc, chunk, cnt;
-       unsigned short page_count;
        sector_t t_sec;
-       unsigned long flags;
+       unsigned int count;
+       struct mspro_param_register param;
 
-       do {
-               page_count = 0;
+try_again:
+       while (chunk) {
+               msb->current_page = 0;
                msb->current_seg = 0;
-               msb->seg_count = blk_rq_map_sg(req->q, req, msb->req_sg);
+               msb->seg_count = blk_rq_map_sg(msb->block_req->q,
+                                              msb->block_req,
+                                              msb->req_sg);
 
-               if (msb->seg_count) {
-                       msb->current_page = 0;
-                       for (rc = 0; rc < msb->seg_count; rc++)
-                               page_count += msb->req_sg[rc].length
-                                             / msb->page_size;
-
-                       t_sec = req->sector;
-                       sector_div(t_sec, msb->page_size >> 9);
-                       param.system = msb->system;
-                       param.data_count = cpu_to_be16(page_count);
-                       param.data_address = cpu_to_be32((uint32_t)t_sec);
-                       param.tpc_param = 0;
-
-                       msb->data_dir = rq_data_dir(req);
-                       msb->transfer_cmd = msb->data_dir == READ
-                                           ? MSPRO_CMD_READ_DATA
-                                           : MSPRO_CMD_WRITE_DATA;
-
-                       dev_dbg(&card->dev, "data transfer: cmd %x, "
-                               "lba %x, count %x\n", msb->transfer_cmd,
-                               be32_to_cpu(param.data_address),
-                               page_count);
-
-                       card->next_request = h_mspro_block_req_init;
-                       msb->mrq_handler = h_mspro_block_transfer_data;
-                       memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
-                                         &param, sizeof(param));
-                       memstick_new_req(card->host);
-                       wait_for_completion(&card->mrq_complete);
-                       rc = card->current_mrq.error;
+               if (!msb->seg_count) {
+                       chunk = __blk_end_request(msb->block_req, -ENOMEM,
+                                       blk_rq_cur_bytes(msb->block_req));
+                       continue;
+               }
 
-                       if (rc || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
-                               for (cnt = 0; cnt < msb->current_seg; cnt++)
-                                       page_count += msb->req_sg[cnt].length
-                                                     / msb->page_size;
-
-                               if (msb->current_page)
-                                       page_count += msb->current_page - 1;
-
-                               if (page_count && (msb->data_dir == READ))
-                                       rc = msb->page_size * page_count;
-                               else
-                                       rc = -EIO;
-                       } else
-                               rc = msb->page_size * page_count;
-               } else
-                       rc = -EFAULT;
+               t_sec = msb->block_req->sector << 9;
+               sector_div(t_sec, msb->page_size);
 
-               spin_lock_irqsave(&msb->q_lock, flags);
-               if (rc >= 0)
-                       chunk = __blk_end_request(req, 0, rc);
-               else
-                       chunk = __blk_end_request(req, rc, 0);
+               count = msb->block_req->nr_sectors << 9;
+               count /= msb->page_size;
 
-               dev_dbg(&card->dev, "end chunk %d, %d\n", rc, chunk);
-               spin_unlock_irqrestore(&msb->q_lock, flags);
-       } while (chunk);
+               param.system = msb->system;
+               param.data_count = cpu_to_be16(count);
+               param.data_address = cpu_to_be32((uint32_t)t_sec);
+               param.tpc_param = 0;
+
+               msb->data_dir = rq_data_dir(msb->block_req);
+               msb->transfer_cmd = msb->data_dir == READ
+                                   ? MSPRO_CMD_READ_DATA
+                                   : MSPRO_CMD_WRITE_DATA;
+
+               dev_dbg(&card->dev, "data transfer: cmd %x, "
+                       "lba %x, count %x\n", msb->transfer_cmd,
+                       be32_to_cpu(param.data_address), count);
+
+               card->next_request = h_mspro_block_req_init;
+               msb->mrq_handler = h_mspro_block_transfer_data;
+               memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
+                                 &param, sizeof(param));
+               memstick_new_req(card->host);
+               return 0;
+       }
+
+       dev_dbg(&card->dev, "elv_next\n");
+       msb->block_req = elv_next_request(msb->queue);
+       if (!msb->block_req) {
+               dev_dbg(&card->dev, "issue end\n");
+               return -EAGAIN;
+       }
+
+       dev_dbg(&card->dev, "trying again\n");
+       chunk = 1;
+       goto try_again;
 }
 
-static int mspro_block_has_request(struct mspro_block_data *msb)
+static int mspro_block_complete_req(struct memstick_dev *card, int error)
 {
-       int rc = 0;
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       int chunk, cnt;
+       unsigned int t_len = 0;
        unsigned long flags;
 
        spin_lock_irqsave(&msb->q_lock, flags);
-       if (kthread_should_stop() || msb->has_request)
-               rc = 1;
+       dev_dbg(&card->dev, "complete %d, %d\n", msb->has_request ? 1 : 0,
+               error);
+
+       if (msb->has_request) {
+               /* Nothing to do - not really an error */
+               if (error == -EAGAIN)
+                       error = 0;
+
+               if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
+                       if (msb->data_dir == READ) {
+                               for (cnt = 0; cnt < msb->current_seg; cnt++)
+                                       t_len += msb->req_sg[cnt].length
+                                                / msb->page_size;
+
+                                       if (msb->current_page)
+                                               t_len += msb->current_page - 1;
+
+                                       t_len *= msb->page_size;
+                       }
+               } else
+                       t_len = msb->block_req->nr_sectors << 9;
+
+               dev_dbg(&card->dev, "transferred %x (%d)\n", t_len, error);
+
+               if (error && !t_len)
+                       t_len = blk_rq_cur_bytes(msb->block_req);
+
+               chunk = __blk_end_request(msb->block_req, error, t_len);
+
+               error = mspro_block_issue_req(card, chunk);
+
+               if (!error)
+                       goto out;
+               else
+                       msb->has_request = 0;
+       } else {
+               if (!error)
+                       error = -EAGAIN;
+       }
+
+       card->next_request = h_mspro_block_default_bad;
+       complete_all(&card->mrq_complete);
+out:
        spin_unlock_irqrestore(&msb->q_lock, flags);
-       return rc;
+       return error;
 }
 
-static int mspro_block_queue_thread(void *data)
+static void mspro_block_stop(struct memstick_dev *card)
 {
-       struct memstick_dev *card = data;
-       struct memstick_host *host = card->host;
        struct mspro_block_data *msb = memstick_get_drvdata(card);
-       struct request *req;
+       int rc = 0;
        unsigned long flags;
 
        while (1) {
-               wait_event(msb->q_wait, mspro_block_has_request(msb));
-               dev_dbg(&card->dev, "thread iter\n");
-
                spin_lock_irqsave(&msb->q_lock, flags);
-               req = elv_next_request(msb->queue);
-               dev_dbg(&card->dev, "next req %p\n", req);
-               if (!req) {
-                       msb->has_request = 0;
-                       if (kthread_should_stop()) {
-                               spin_unlock_irqrestore(&msb->q_lock, flags);
-                               break;
-                       }
-               } else
-                       msb->has_request = 1;
+               if (!msb->has_request) {
+                       blk_stop_queue(msb->queue);
+                       rc = 1;
+               }
                spin_unlock_irqrestore(&msb->q_lock, flags);
 
-               if (req) {
-                       mutex_lock(&host->lock);
-                       mspro_block_process_request(card, req);
-                       mutex_unlock(&host->lock);
-               }
+               if (rc)
+                       break;
+
+               wait_for_completion(&card->mrq_complete);
        }
-       dev_dbg(&card->dev, "thread finished\n");
-       return 0;
 }
 
-static void mspro_block_request(struct request_queue *q)
+static void mspro_block_start(struct memstick_dev *card)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       unsigned long flags;
+
+       spin_lock_irqsave(&msb->q_lock, flags);
+       blk_start_queue(msb->queue);
+       spin_unlock_irqrestore(&msb->q_lock, flags);
+}
+
+static int mspro_block_prepare_req(struct request_queue *q, struct request *req)
+{
+       if (!blk_fs_request(req) && !blk_pc_request(req)) {
+               blk_dump_rq_flags(req, "MSPro unsupported request");
+               return BLKPREP_KILL;
+       }
+
+       req->cmd_flags |= REQ_DONTPREP;
+
+       return BLKPREP_OK;
+}
+
+static void mspro_block_submit_req(struct request_queue *q)
 {
        struct memstick_dev *card = q->queuedata;
        struct mspro_block_data *msb = memstick_get_drvdata(card);
        struct request *req = NULL;
 
-       if (msb->q_thread) {
-               msb->has_request = 1;
-               wake_up_all(&msb->q_wait);
-       } else {
+       if (msb->has_request)
+               return;
+
+       if (msb->eject) {
                while ((req = elv_next_request(q)) != NULL)
                        end_queued_request(req, -ENODEV);
+
+               return;
        }
+
+       msb->has_request = 1;
+       if (mspro_block_issue_req(card, 0))
+               msb->has_request = 0;
 }
 
 /*** Initialization ***/
@@ -1169,16 +1203,14 @@ static int mspro_block_init_disk(struct memstick_dev *card)
                goto out_release_id;
        }
 
-       spin_lock_init(&msb->q_lock);
-       init_waitqueue_head(&msb->q_wait);
-
-       msb->queue = blk_init_queue(mspro_block_request, &msb->q_lock);
+       msb->queue = blk_init_queue(mspro_block_submit_req, &msb->q_lock);
        if (!msb->queue) {
                rc = -ENOMEM;
                goto out_put_disk;
        }
 
        msb->queue->queuedata = card;
+       blk_queue_prep_rq(msb->queue, mspro_block_prepare_req);
 
        blk_queue_bounce_limit(msb->queue, limit);
        blk_queue_max_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES);
@@ -1204,14 +1236,8 @@ static int mspro_block_init_disk(struct memstick_dev *card)
        capacity *= msb->page_size >> 9;
        set_capacity(msb->disk, capacity);
        dev_dbg(&card->dev, "capacity set %ld\n", capacity);
-       msb->q_thread = kthread_run(mspro_block_queue_thread, card,
-                                   DRIVER_NAME"d");
-       if (IS_ERR(msb->q_thread))
-               goto out_put_disk;
 
-       mutex_unlock(&host->lock);
        add_disk(msb->disk);
-       mutex_lock(&host->lock);
        msb->active = 1;
        return 0;
 
@@ -1259,6 +1285,7 @@ static int mspro_block_probe(struct memstick_dev *card)
                return -ENOMEM;
        memstick_set_drvdata(card, msb);
        msb->card = card;
+       spin_lock_init(&msb->q_lock);
 
        rc = mspro_block_init_card(card);
 
@@ -1272,6 +1299,8 @@ static int mspro_block_probe(struct memstick_dev *card)
        rc = mspro_block_init_disk(card);
        if (!rc) {
                card->check = mspro_block_check_card;
+               card->stop = mspro_block_stop;
+               card->start = mspro_block_start;
                return 0;
        }
 
@@ -1286,26 +1315,17 @@ out_free:
 static void mspro_block_remove(struct memstick_dev *card)
 {
        struct mspro_block_data *msb = memstick_get_drvdata(card);
-       struct task_struct *q_thread = NULL;
        unsigned long flags;
 
        del_gendisk(msb->disk);
        dev_dbg(&card->dev, "mspro block remove\n");
        spin_lock_irqsave(&msb->q_lock, flags);
-       q_thread = msb->q_thread;
-       msb->q_thread = NULL;
-       msb->active = 0;
+       msb->eject = 1;
+       blk_start_queue(msb->queue);
        spin_unlock_irqrestore(&msb->q_lock, flags);
 
-       if (q_thread) {
-               mutex_unlock(&card->host->lock);
-               kthread_stop(q_thread);
-               mutex_lock(&card->host->lock);
-       }
-
-       dev_dbg(&card->dev, "queue thread stopped\n");
-
        blk_cleanup_queue(msb->queue);
+       msb->queue = NULL;
 
        sysfs_remove_group(&card->dev.kobj, &msb->attr_group);
 
@@ -1322,19 +1342,13 @@ static void mspro_block_remove(struct memstick_dev *card)
 static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state)
 {
        struct mspro_block_data *msb = memstick_get_drvdata(card);
-       struct task_struct *q_thread = NULL;
        unsigned long flags;
 
        spin_lock_irqsave(&msb->q_lock, flags);
-       q_thread = msb->q_thread;
-       msb->q_thread = NULL;
-       msb->active = 0;
        blk_stop_queue(msb->queue);
+       msb->active = 0;
        spin_unlock_irqrestore(&msb->q_lock, flags);
 
-       if (q_thread)
-               kthread_stop(q_thread);
-
        return 0;
 }
 
@@ -1373,14 +1387,7 @@ static int mspro_block_resume(struct memstick_dev *card)
                        if (memcmp(s_attr->data, r_attr->data, s_attr->size))
                                break;
 
-                       memstick_set_drvdata(card, msb);
-                       msb->q_thread = kthread_run(mspro_block_queue_thread,
-                                                   card, DRIVER_NAME"d");
-                       if (IS_ERR(msb->q_thread))
-                               msb->q_thread = NULL;
-                       else
-                               msb->active = 1;
-
+                       msb->active = 1;
                        break;
                }
        }
index 4e3bfbcdf155d9cadfc2d1ea06c35911cd3c7c11..3485c63d20b04c0793be29f07d4fffd38f9de457 100644 (file)
@@ -50,6 +50,7 @@ struct jmb38x_ms_host {
        struct jmb38x_ms        *chip;
        void __iomem            *addr;
        spinlock_t              lock;
+       struct tasklet_struct   notify;
        int                     id;
        char                    host_id[32];
        int                     irq;
@@ -590,55 +591,97 @@ static void jmb38x_ms_abort(unsigned long data)
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static void jmb38x_ms_request(struct memstick_host *msh)
+static void jmb38x_ms_req_tasklet(unsigned long data)
 {
+       struct memstick_host *msh = (struct memstick_host *)data;
        struct jmb38x_ms_host *host = memstick_priv(msh);
        unsigned long flags;
        int rc;
 
        spin_lock_irqsave(&host->lock, flags);
-       if (host->req) {
-               spin_unlock_irqrestore(&host->lock, flags);
-               BUG();
-               return;
+       if (!host->req) {
+               do {
+                       rc = memstick_next_req(msh, &host->req);
+                       dev_dbg(&host->chip->pdev->dev, "tasklet req %d\n", rc);
+               } while (!rc && jmb38x_ms_issue_cmd(msh));
        }
-
-       do {
-               rc = memstick_next_req(msh, &host->req);
-       } while (!rc && jmb38x_ms_issue_cmd(msh));
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static void jmb38x_ms_reset(struct jmb38x_ms_host *host)
+static void jmb38x_ms_dummy_submit(struct memstick_host *msh)
 {
-       unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
+       return;
+}
+
+static void jmb38x_ms_submit_req(struct memstick_host *msh)
+{
+       struct jmb38x_ms_host *host = memstick_priv(msh);
+
+       tasklet_schedule(&host->notify);
+}
+
+static int jmb38x_ms_reset(struct jmb38x_ms_host *host)
+{
+       int cnt;
+
+       writel(HOST_CONTROL_RESET_REQ | HOST_CONTROL_CLOCK_EN
+              | readl(host->addr + HOST_CONTROL),
+              host->addr + HOST_CONTROL);
+       mmiowb();
+
+       for (cnt = 0; cnt < 20; ++cnt) {
+               if (!(HOST_CONTROL_RESET_REQ
+                     & readl(host->addr + HOST_CONTROL)))
+                       goto reset_next;
 
-       writel(HOST_CONTROL_RESET_REQ, host->addr + HOST_CONTROL);
+               ndelay(20);
+       }
+       dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n");
+       return -EIO;
+
+reset_next:
+       writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN
+              | readl(host->addr + HOST_CONTROL),
+              host->addr + HOST_CONTROL);
+       mmiowb();
+
+       for (cnt = 0; cnt < 20; ++cnt) {
+               if (!(HOST_CONTROL_RESET
+                     & readl(host->addr + HOST_CONTROL)))
+                       goto reset_ok;
 
-       while (HOST_CONTROL_RESET_REQ
-              & (host_ctl = readl(host->addr + HOST_CONTROL))) {
                ndelay(20);
-               dev_dbg(&host->chip->pdev->dev, "reset %08x\n", host_ctl);
        }
+       dev_dbg(&host->chip->pdev->dev, "reset timeout\n");
+       return -EIO;
 
-       writel(HOST_CONTROL_RESET, host->addr + HOST_CONTROL);
+reset_ok:
        mmiowb();
        writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);
        writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);
+       return 0;
 }
 
-static void jmb38x_ms_set_param(struct memstick_host *msh,
-                               enum memstick_param param,
-                               int value)
+static int jmb38x_ms_set_param(struct memstick_host *msh,
+                              enum memstick_param param,
+                              int value)
 {
        struct jmb38x_ms_host *host = memstick_priv(msh);
        unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
        unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0;
+       int rc = 0;
 
        switch (param) {
        case MEMSTICK_POWER:
                if (value == MEMSTICK_POWER_ON) {
-                       jmb38x_ms_reset(host);
+                       rc = jmb38x_ms_reset(host);
+                       if (rc)
+                               return rc;
+
+                       host_ctl = 7;
+                       host_ctl |= HOST_CONTROL_POWER_EN
+                                | HOST_CONTROL_CLOCK_EN;
+                       writel(host_ctl, host->addr + HOST_CONTROL);
 
                        writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
                                        : PAD_PU_PD_ON_MS_SOCK0,
@@ -647,11 +690,7 @@ static void jmb38x_ms_set_param(struct memstick_host *msh,
                        writel(PAD_OUTPUT_ENABLE_MS,
                               host->addr + PAD_OUTPUT_ENABLE);
 
-                       host_ctl = 7;
-                       host_ctl |= HOST_CONTROL_POWER_EN
-                                | HOST_CONTROL_CLOCK_EN;
-                       writel(host_ctl, host->addr + HOST_CONTROL);
-
+                       msleep(10);
                        dev_dbg(&host->chip->pdev->dev, "power on\n");
                } else if (value == MEMSTICK_POWER_OFF) {
                        host_ctl &= ~(HOST_CONTROL_POWER_EN
@@ -660,7 +699,8 @@ static void jmb38x_ms_set_param(struct memstick_host *msh,
                        writel(0, host->addr + PAD_OUTPUT_ENABLE);
                        writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);
                        dev_dbg(&host->chip->pdev->dev, "power off\n");
-               }
+               } else
+                       return -EINVAL;
                break;
        case MEMSTICK_INTERFACE:
                host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
@@ -686,12 +726,14 @@ static void jmb38x_ms_set_param(struct memstick_host *msh,
                        host_ctl &= ~HOST_CONTROL_REI;
                        clock_ctl = CLOCK_CONTROL_60MHZ;
                        clock_delay = 0;
-               }
+               } else
+                       return -EINVAL;
                writel(host_ctl, host->addr + HOST_CONTROL);
                writel(clock_ctl, host->addr + CLOCK_CONTROL);
                writel(clock_delay, host->addr + CLOCK_DELAY);
                break;
        };
+       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -785,7 +827,9 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
                 host->id);
        host->irq = jm->pdev->irq;
        host->timeout_jiffies = msecs_to_jiffies(1000);
-       msh->request = jmb38x_ms_request;
+
+       tasklet_init(&host->notify, jmb38x_ms_req_tasklet, (unsigned long)msh);
+       msh->request = jmb38x_ms_submit_req;
        msh->set_param = jmb38x_ms_set_param;
 
        msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
@@ -897,6 +941,8 @@ static void jmb38x_ms_remove(struct pci_dev *dev)
 
                host = memstick_priv(jm->hosts[cnt]);
 
+               jm->hosts[cnt]->request = jmb38x_ms_dummy_submit;
+               tasklet_kill(&host->notify);
                writel(0, host->addr + INT_SIGNAL_ENABLE);
                writel(0, host->addr + INT_STATUS_ENABLE);
                mmiowb();
index 8577de4ebb0efa11d9103105c87be938f3ce1160..d32d6ad8f3fc5ab51017a6350c7d68aa4c42736b 100644 (file)
@@ -71,6 +71,7 @@ struct tifm_ms {
        struct tifm_dev         *dev;
        struct timer_list       timer;
        struct memstick_request *req;
+       struct tasklet_struct   notify;
        unsigned int            mode_mask;
        unsigned int            block_pos;
        unsigned long           timeout_jiffies;
@@ -455,49 +456,51 @@ static void tifm_ms_card_event(struct tifm_dev *sock)
        return;
 }
 
-static void tifm_ms_request(struct memstick_host *msh)
+static void tifm_ms_req_tasklet(unsigned long data)
 {
+       struct memstick_host *msh = (struct memstick_host *)data;
        struct tifm_ms *host = memstick_priv(msh);
        struct tifm_dev *sock = host->dev;
        unsigned long flags;
        int rc;
 
        spin_lock_irqsave(&sock->lock, flags);
-       if (host->req) {
-               printk(KERN_ERR "%s : unfinished request detected\n",
-                      sock->dev.bus_id);
-               spin_unlock_irqrestore(&sock->lock, flags);
-               tifm_eject(host->dev);
-               return;
-       }
+       if (!host->req) {
+               if (host->eject) {
+                       do {
+                               rc = memstick_next_req(msh, &host->req);
+                               if (!rc)
+                                       host->req->error = -ETIME;
+                       } while (!rc);
+                       spin_unlock_irqrestore(&sock->lock, flags);
+                       return;
+               }
 
-       if (host->eject) {
                do {
                        rc = memstick_next_req(msh, &host->req);
-                       if (!rc)
-                               host->req->error = -ETIME;
-               } while (!rc);
-               spin_unlock_irqrestore(&sock->lock, flags);
-               return;
+               } while (!rc && tifm_ms_issue_cmd(host));
        }
-
-       do {
-               rc = memstick_next_req(msh, &host->req);
-       } while (!rc && tifm_ms_issue_cmd(host));
-
        spin_unlock_irqrestore(&sock->lock, flags);
+}
+
+static void tifm_ms_dummy_submit(struct memstick_host *msh)
+{
        return;
 }
 
-static void tifm_ms_set_param(struct memstick_host *msh,
-                             enum memstick_param param,
-                             int value)
+static void tifm_ms_submit_req(struct memstick_host *msh)
 {
        struct tifm_ms *host = memstick_priv(msh);
-       struct tifm_dev *sock = host->dev;
-       unsigned long flags;
 
-       spin_lock_irqsave(&sock->lock, flags);
+       tasklet_schedule(&host->notify);
+}
+
+static int tifm_ms_set_param(struct memstick_host *msh,
+                            enum memstick_param param,
+                            int value)
+{
+       struct tifm_ms *host = memstick_priv(msh);
+       struct tifm_dev *sock = host->dev;
 
        switch (param) {
        case MEMSTICK_POWER:
@@ -512,7 +515,8 @@ static void tifm_ms_set_param(struct memstick_host *msh,
                        writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
                               sock->addr + SOCK_MS_SYSTEM);
                        writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
-               }
+               } else
+                       return -EINVAL;
                break;
        case MEMSTICK_INTERFACE:
                if (value == MEMSTICK_SERIAL) {
@@ -525,11 +529,12 @@ static void tifm_ms_set_param(struct memstick_host *msh,
                        writel(TIFM_CTRL_FAST_CLK
                               | readl(sock->addr + SOCK_CONTROL),
                               sock->addr + SOCK_CONTROL);
-               }
+               } else
+                       return -EINVAL;
                break;
        };
 
-       spin_unlock_irqrestore(&sock->lock, flags);
+       return 0;
 }
 
 static void tifm_ms_abort(unsigned long data)
@@ -570,8 +575,9 @@ static int tifm_ms_probe(struct tifm_dev *sock)
        host->timeout_jiffies = msecs_to_jiffies(1000);
 
        setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
+       tasklet_init(&host->notify, tifm_ms_req_tasklet, (unsigned long)msh);
 
-       msh->request = tifm_ms_request;
+       msh->request = tifm_ms_submit_req;
        msh->set_param = tifm_ms_set_param;
        sock->card_event = tifm_ms_card_event;
        sock->data_event = tifm_ms_data_event;
@@ -593,6 +599,8 @@ static void tifm_ms_remove(struct tifm_dev *sock)
        int rc = 0;
        unsigned long flags;
 
+       msh->request = tifm_ms_dummy_submit;
+       tasklet_kill(&host->notify);
        spin_lock_irqsave(&sock->lock, flags);
        host->eject = 1;
        if (host->req) {
index 241592ab13adb6bc8ceddb9e3c9beec78c6c6f18..3f15fcfe4a2ea96e1c4ea4bd8d08beaeb26266a7 100644 (file)
@@ -127,7 +127,7 @@ mpi_ioc.h
  *  08-08-01  01.02.01  Original release for v1.2 work.
  *                      New format for FWVersion and ProductId in
  *                      MSG_IOC_FACTS_REPLY and MPI_FW_HEADER.
- *  08-31-01  01.02.02  Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
+ *  08-31-01  01.02.02  Added event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
  *                      related structure and defines.
  *                      Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED.
  *                      Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE.
@@ -187,7 +187,7 @@ mpi_ioc.h
  *  10-11-06  01.05.12  Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
  *                      Added MaxInitiators field to PortFacts reply.
  *                      Added SAS Device Status Change ReasonCode for
- *                      asynchronous notificaiton.
+ *                      asynchronous notification.
  *                      Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
  *                      data structure.
  *                      Added new ImageType values for FWDownload and FWUpload
@@ -213,7 +213,7 @@ mpi_cnfg.h
  *                      Added _RESPONSE_ID_MASK definition to SCSI_PORT_1
  *                      page and updated the page version.
  *                      Added Information field and _INFO_PARAMS_NEGOTIATED
- *                      definitionto SCSI_DEVICE_0 page.
+ *                      definition to SCSI_DEVICE_0 page.
  *  06-22-00  01.00.03  Removed batch controls from LAN_0 page and updated the
  *                      page version.
  *                      Added BucketsRemaining to LAN_1 page, redefined the
index 34402c47027e3951ac1d7de9387ec81a61227a2d..d6a0074b9dc3b34c239fc8582fc3ef7a45dfc85c 100644 (file)
@@ -273,12 +273,12 @@ mpt_fault_reset_work(struct work_struct *work)
        ioc_raw_state = mpt_GetIocState(ioc, 0);
        if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
                printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
-                   ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
+                      ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
                printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
-                   ioc->name, __FUNCTION__);
+                      ioc->name, __func__);
                rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
                printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
-                   __FUNCTION__, (rc == 0) ? "success" : "failed");
+                      __func__, (rc == 0) ? "success" : "failed");
                ioc_raw_state = mpt_GetIocState(ioc, 0);
                if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
                        printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
@@ -356,7 +356,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
                MptCallbacks[cb_idx] == NULL) {
                printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
-                               __FUNCTION__, ioc->name, cb_idx);
+                               __func__, ioc->name, cb_idx);
                goto out;
        }
 
@@ -420,7 +420,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
                MptCallbacks[cb_idx] == NULL) {
                printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
-                               __FUNCTION__, ioc->name, cb_idx);
+                               __func__, ioc->name, cb_idx);
                freeme = 0;
                goto out;
        }
@@ -2434,7 +2434,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 
        if (ioc->cached_fw != NULL) {
                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
-                   "adapter\n", __FUNCTION__, ioc->name));
+                   "adapter\n", __func__, ioc->name));
                if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
                    ioc->cached_fw, CAN_SLEEP)) < 0) {
                        printk(MYIOC_s_WARN_FMT
@@ -3693,7 +3693,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 
        if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
                drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
-                       "address=%p\n",  ioc->name, __FUNCTION__,
+                       "address=%p\n",  ioc->name, __func__,
                        &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
                CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
                if (sleepFlag == CAN_SLEEP)
@@ -4742,12 +4742,12 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
                break;
        }
 
-       printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
+       printk("%s: persist_opcode=%x\n",__func__, persist_opcode);
 
        /* Get a MF for this command.
         */
        if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
-               printk("%s: no msg frames!\n",__FUNCTION__);
+               printk("%s: no msg frames!\n",__func__);
                return -1;
         }
 
@@ -4771,13 +4771,13 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
            (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
        if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
                printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
-                   __FUNCTION__,
+                   __func__,
                    sasIoUnitCntrReply->IOCStatus,
                    sasIoUnitCntrReply->IOCLogInfo);
                return -1;
        }
 
-       printk("%s: success\n",__FUNCTION__);
+       printk("%s: success\n",__func__);
        return 0;
 }
 
@@ -5784,7 +5784,7 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
 
        if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
-                   ioc->name,__FUNCTION__));
+                   ioc->name,__func__));
                return -1;
        }
 
index a5920423e2b23ac75ac4913ee9d142ebb755527c..f5233f3d9eff03399c13e3e0b7138ad620056797 100644 (file)
@@ -505,7 +505,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
        event = le32_to_cpu(pEvReply->Event) & 0xFF;
 
        dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s() called\n",
-           ioc->name, __FUNCTION__));
+           ioc->name, __func__));
        if(async_queue == NULL)
                return 1;
 
@@ -2482,7 +2482,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
         */
        if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
-                   ioc->name,__FUNCTION__));
+                   ioc->name,__func__));
                goto out;
        }
 
index b36cae9ec6db6c81041f8dccd8b3ce59db466f2e..c3c24fdf9fb621c20acb8249496c6440cad8b8b6 100644 (file)
@@ -231,28 +231,28 @@ static int
 mptfc_abort(struct scsi_cmnd *SCpnt)
 {
        return
-           mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__);
+           mptfc_block_error_handler(SCpnt, mptscsih_abort, __func__);
 }
 
 static int
 mptfc_dev_reset(struct scsi_cmnd *SCpnt)
 {
        return
-           mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__);
+           mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __func__);
 }
 
 static int
 mptfc_bus_reset(struct scsi_cmnd *SCpnt)
 {
        return
-           mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__);
+           mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __func__);
 }
 
 static int
 mptfc_host_reset(struct scsi_cmnd *SCpnt)
 {
        return
-           mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__);
+           mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __func__);
 }
 
 static void
index d709d92b7b30d0714ab2316f731ece1e8487e7fd..a1abf95cf75153d2f2f1abd74549d5ba446ae473 100644 (file)
@@ -610,7 +610,7 @@ mpt_lan_send_turbo(struct net_device *dev, u32 tmsg)
 
        dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
                        IOC_AND_NETDEV_NAMES_s_s(dev),
-                       __FUNCTION__, sent));
+                       __func__, sent));
 
        priv->SendCtl[ctx].skb = NULL;
        pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
@@ -676,7 +676,7 @@ mpt_lan_send_reply(struct net_device *dev, LANSendReply_t *pSendRep)
 
                dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
                                IOC_AND_NETDEV_NAMES_s_s(dev),
-                               __FUNCTION__, sent));
+                               __func__, sent));
 
                priv->SendCtl[ctx].skb = NULL;
                pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
@@ -715,7 +715,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
        u16 cur_naa = 0x1000;
 
        dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n",
-                       __FUNCTION__, skb));
+                       __func__, skb));
 
        spin_lock_irqsave(&priv->txfidx_lock, flags);
        if (priv->mpt_txfidx_tail < 0) {
@@ -723,7 +723,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
                spin_unlock_irqrestore(&priv->txfidx_lock, flags);
 
                printk (KERN_ERR "%s: no tx context available: %u\n",
-                       __FUNCTION__, priv->mpt_txfidx_tail);
+                       __func__, priv->mpt_txfidx_tail);
                return 1;
        }
 
@@ -733,7 +733,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
                spin_unlock_irqrestore(&priv->txfidx_lock, flags);
 
                printk (KERN_ERR "%s: Unable to alloc request frame\n",
-                       __FUNCTION__);
+                       __func__);
                return 1;
        }
 
@@ -1208,7 +1208,7 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
 
        dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n",
                        IOC_AND_NETDEV_NAMES_s_s(dev),
-                       __FUNCTION__, buckets, curr));
+                       __func__, buckets, curr));
 
        max = (mpt_dev->req_sz - MPT_LAN_RECEIVE_POST_REQUEST_SIZE) /
                        (MPT_LAN_TRANSACTION32_SIZE + sizeof(SGESimple64_t));
@@ -1217,9 +1217,9 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
                mf = mpt_get_msg_frame(LanCtx, mpt_dev);
                if (mf == NULL) {
                        printk (KERN_ERR "%s: Unable to alloc request frame\n",
-                               __FUNCTION__);
+                               __func__);
                        dioprintk((KERN_ERR "%s: %u buckets remaining\n",
-                                __FUNCTION__, buckets));
+                                __func__, buckets));
                        goto out;
                }
                pRecvReq = (LANReceivePostRequest_t *) mf;
@@ -1244,7 +1244,7 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
                        spin_lock_irqsave(&priv->rxfidx_lock, flags);
                        if (priv->mpt_rxfidx_tail < 0) {
                                printk (KERN_ERR "%s: Can't alloc context\n",
-                                       __FUNCTION__);
+                                       __func__);
                                spin_unlock_irqrestore(&priv->rxfidx_lock,
                                                       flags);
                                break;
@@ -1267,7 +1267,7 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
                                if (skb == NULL) {
                                        printk (KERN_WARNING
                                                MYNAM "/%s: Can't alloc skb\n",
-                                               __FUNCTION__);
+                                               __func__);
                                        priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
                                        spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
                                        break;
@@ -1305,7 +1305,7 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
 
                if (pSimple == NULL) {
 /**/                   printk (KERN_WARNING MYNAM "/%s: No buckets posted\n",
-/**/                           __FUNCTION__);
+/**/                           __func__);
                        mpt_free_msg_frame(mpt_dev, mf);
                        goto out;
                }
@@ -1329,9 +1329,9 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
 
 out:
        dioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n",
-                 __FUNCTION__, buckets, atomic_read(&priv->buckets_out)));
+                 __func__, buckets, atomic_read(&priv->buckets_out)));
        dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n",
-       __FUNCTION__, priv->total_posted, priv->total_received));
+       __func__, priv->total_posted, priv->total_received));
 
        clear_bit(0, &priv->post_buckets_active);
 }
index b1147aa7afdebf594781c944faafb0414aadc8d8..12b732512e579049fe0152e1a570dd3594b8ad15 100644 (file)
@@ -300,7 +300,7 @@ mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_detai
        phy_info = port_info->phy_info;
 
        dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
-           "bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details,
+           "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
            port_details->num_phys, (unsigned long long)
            port_details->phy_bitmask));
 
@@ -411,7 +411,7 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
                 */
                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                    "%s: [%p]: deleting phy = %d\n",
-                   ioc->name, __FUNCTION__, port_details, i));
+                   ioc->name, __func__, port_details, i));
                port_details->num_phys--;
                port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
                memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
@@ -497,7 +497,7 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
                        continue;
                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                    "%s: [%p]: phy_id=%02d num_phys=%02d "
-                   "bitmask=0x%016llX\n", ioc->name, __FUNCTION__,
+                   "bitmask=0x%016llX\n", ioc->name, __func__,
                    port_details, i, port_details->num_phys,
                    (unsigned long long)port_details->phy_bitmask));
                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
@@ -553,7 +553,7 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
 
        if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
-                   ioc->name,__FUNCTION__, __LINE__));
+                   ioc->name,__func__, __LINE__));
                return 0;
        }
 
@@ -606,7 +606,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,
            GFP_ATOMIC);
        if (!target_reset_list) {
                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
-                   ioc->name,__FUNCTION__, __LINE__));
+                   ioc->name,__func__, __LINE__));
                return;
        }
 
@@ -673,7 +673,7 @@ mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
        ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
        if (!ev) {
                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
-                   ioc->name,__FUNCTION__, __LINE__));
+                   ioc->name,__func__, __LINE__));
                return;
        }
 
@@ -1183,7 +1183,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
        reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
        if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
                printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
-                   ioc->name, __FUNCTION__, reply->IOCStatus, reply->IOCLogInfo);
+                   ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
                error = -ENXIO;
                goto out_unlock;
        }
@@ -1270,14 +1270,14 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
        if (!rsp) {
                printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
-                   ioc->name, __FUNCTION__);
+                   ioc->name, __func__);
                return -EINVAL;
        }
 
        /* do we need to support multiple segments? */
        if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
                printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
-                   ioc->name, __FUNCTION__, req->bio->bi_vcnt, req->data_len,
+                   ioc->name, __func__, req->bio->bi_vcnt, req->data_len,
                    rsp->bio->bi_vcnt, rsp->data_len);
                return -EINVAL;
        }
@@ -1343,7 +1343,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
        if (!timeleft) {
-               printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __FUNCTION__);
+               printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
                /* On timeout reset the board */
                mpt_HardResetHandler(ioc, CAN_SLEEP);
                ret = -ETIMEDOUT;
@@ -1361,7 +1361,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
                rsp->data_len -= smprep->ResponseDataLength;
        } else {
                printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
-                   ioc->name, __FUNCTION__);
+                   ioc->name, __func__);
                ret = -ENXIO;
        }
 unmap:
@@ -2006,7 +2006,7 @@ static int mptsas_probe_one_phy(struct device *dev,
                        if (error) {
                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                        "%s: exit at line=%d\n", ioc->name,
-                                       __FUNCTION__, __LINE__));
+                                       __func__, __LINE__));
                                goto out;
                        }
                        mptsas_set_port(ioc, phy_info, port);
@@ -2076,7 +2076,7 @@ static int mptsas_probe_one_phy(struct device *dev,
                if (!rphy) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        goto out;
                }
 
@@ -2085,7 +2085,7 @@ static int mptsas_probe_one_phy(struct device *dev,
                if (error) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        sas_rphy_free(rphy);
                        goto out;
                }
@@ -2613,7 +2613,7 @@ mptsas_hotplug_work(struct work_struct *work)
                                    (ev->channel << 8) + ev->id)) {
                                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                        "%s: exit at line=%d\n", ioc->name,
-                                               __FUNCTION__, __LINE__));
+                                               __func__, __LINE__));
                                        break;
                                }
                                phy_info = mptsas_find_phyinfo_by_sas_address(
@@ -2633,20 +2633,20 @@ mptsas_hotplug_work(struct work_struct *work)
                if (!phy_info){
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        break;
                }
                if (!phy_info->port_details) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        break;
                }
                rphy = mptsas_get_rphy(phy_info);
                if (!rphy) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        break;
                }
 
@@ -2654,7 +2654,7 @@ mptsas_hotplug_work(struct work_struct *work)
                if (!port) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        break;
                }
 
@@ -2665,7 +2665,7 @@ mptsas_hotplug_work(struct work_struct *work)
                        if (!vtarget) {
                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                        "%s: exit at line=%d\n", ioc->name,
-                                       __FUNCTION__, __LINE__));
+                                       __func__, __LINE__));
                                break;
                        }
 
@@ -2720,7 +2720,7 @@ mptsas_hotplug_work(struct work_struct *work)
                        (ev->channel << 8) + ev->id)) {
                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                        "%s: exit at line=%d\n", ioc->name,
-                                       __FUNCTION__, __LINE__));
+                                       __func__, __LINE__));
                        break;
                }
 
@@ -2732,7 +2732,7 @@ mptsas_hotplug_work(struct work_struct *work)
                if (!phy_info || !phy_info->port_details) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        break;
                }
 
@@ -2744,7 +2744,7 @@ mptsas_hotplug_work(struct work_struct *work)
                        if (!vtarget) {
                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                    "%s: exit at line=%d\n", ioc->name,
-                                   __FUNCTION__, __LINE__));
+                                   __func__, __LINE__));
                                break;
                        }
                        /*
@@ -2767,7 +2767,7 @@ mptsas_hotplug_work(struct work_struct *work)
                if (mptsas_get_rphy(phy_info)) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        if (ev->channel) printk("%d\n", __LINE__);
                        break;
                }
@@ -2776,7 +2776,7 @@ mptsas_hotplug_work(struct work_struct *work)
                if (!port) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        break;
                }
                memcpy(&phy_info->attached, &sas_device,
@@ -2801,7 +2801,7 @@ mptsas_hotplug_work(struct work_struct *work)
                if (!rphy) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        break; /* non-fatal: an rphy can be added later */
                }
 
@@ -2809,7 +2809,7 @@ mptsas_hotplug_work(struct work_struct *work)
                if (sas_rphy_add(rphy)) {
                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
                                "%s: exit at line=%d\n", ioc->name,
-                               __FUNCTION__, __LINE__));
+                               __func__, __LINE__));
                        sas_rphy_free(rphy);
                        break;
                }
index d142b6b4b9766d0591fb1d351ec7e924df2964c3..9f9354fd35160f8a55515437d703973cc5f7323d 100644 (file)
@@ -461,7 +461,7 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
 
        if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
-                   ioc->name,__FUNCTION__));
+                   ioc->name,__func__));
                return;
        }
 
@@ -2187,7 +2187,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
                                (ioc->debug_level & MPT_DEBUG_TM ))
                printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
                        "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
-                       "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
+                       "term_cmnds=%d\n", __func__, ioc->id, pScsiTmReply->Bus,
                         pScsiTmReply->TargetID, pScsiTmReq->TaskType,
                        le16_to_cpu(pScsiTmReply->IOCStatus),
                        le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
index 489d7c5c49656d0c1fce8cdf17ba15a6a0041508..8774c670e668c55a4fe54bff02b014d0fcde89bc 100644 (file)
@@ -243,29 +243,41 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
 
        /* create user entries for this device */
        tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
-       if (tmp && (tmp != i2o_dev))
-               sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
-                                 "user");
+       if (tmp && (tmp != i2o_dev)) {
+               rc = sysfs_create_link(&i2o_dev->device.kobj,
+                                      &tmp->device.kobj, "user");
+               if (rc)
+                       goto unreg_dev;
+       }
 
        /* create user entries refering to this device */
        list_for_each_entry(tmp, &c->devices, list)
            if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
-               && (tmp != i2o_dev))
-               sysfs_create_link(&tmp->device.kobj,
-                                 &i2o_dev->device.kobj, "user");
+               && (tmp != i2o_dev)) {
+               rc = sysfs_create_link(&tmp->device.kobj,
+                                      &i2o_dev->device.kobj, "user");
+               if (rc)
+                       goto rmlink1;
+       }
 
        /* create parent entries for this device */
        tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
-       if (tmp && (tmp != i2o_dev))
-               sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
-                                 "parent");
+       if (tmp && (tmp != i2o_dev)) {
+               rc = sysfs_create_link(&i2o_dev->device.kobj,
+                                      &tmp->device.kobj, "parent");
+               if (rc)
+                       goto rmlink1;
+       }
 
        /* create parent entries refering to this device */
        list_for_each_entry(tmp, &c->devices, list)
            if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
-               && (tmp != i2o_dev))
-               sysfs_create_link(&tmp->device.kobj,
-                                 &i2o_dev->device.kobj, "parent");
+               && (tmp != i2o_dev)) {
+               rc = sysfs_create_link(&tmp->device.kobj,
+                                      &i2o_dev->device.kobj, "parent");
+               if (rc)
+                       goto rmlink2;
+       }
 
        i2o_driver_notify_device_add_all(i2o_dev);
 
@@ -273,6 +285,24 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
 
        return 0;
 
+rmlink2:
+       /* If link creating failed halfway, we loop whole list to cleanup.
+        * And we don't care wrong removing of link, because sysfs_remove_link
+        * will take care of it.
+        */
+       list_for_each_entry(tmp, &c->devices, list) {
+               if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+                       sysfs_remove_link(&tmp->device.kobj, "parent");
+       }
+       sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+rmlink1:
+       list_for_each_entry(tmp, &c->devices, list)
+               if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+                       sysfs_remove_link(&tmp->device.kobj, "user");
+       sysfs_remove_link(&i2o_dev->device.kobj, "user");
+unreg_dev:
+       list_del(&i2o_dev->list);
+       device_unregister(&i2o_dev->device);
 err:
        kfree(i2o_dev);
        return rc;
index 9f93c29fed355074cb443184da54343102c42625..883e7ea31de20af9d32df5cc6a09ff1d7c6041fd 100644 (file)
@@ -19,6 +19,14 @@ config MFD_SM501
          interface. The device may be connected by PCI or local bus with
          varying functions enabled.
 
+config MFD_SM501_GPIO
+       bool "Export GPIO via GPIO layer"
+       depends on MFD_SM501 && HAVE_GPIO_LIB
+        ---help---
+        This option uses the gpio library layer to export the 64 GPIO
+        lines on the SM501. The platform data is used to supply the
+        base number for the first GPIO line to register.
+
 config MFD_ASIC3
        bool "Support for Compaq ASIC3"
        depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM
@@ -28,7 +36,7 @@ config MFD_ASIC3
 
 config HTC_EGPIO
        bool "HTC EGPIO support"
-       depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM
+       depends on GENERIC_HARDIRQS && GPIOLIB && ARM
        help
            This driver supports the CPLD egpio chip present on
            several HTC phones.  It provides basic support for input
@@ -44,7 +52,7 @@ config HTC_PASIC3
 
 config MFD_TC6393XB
        bool "Support Toshiba TC6393XB"
-       depends on HAVE_GPIO_LIB
+       depends on GPIOLIB && ARM
        select MFD_CORE
        help
          Support for Toshiba Mobile IO Controller TC6393XB
index 3b870e7fb3e12c9c932742c3f0a03f1f5605006d..c6408a62d95e3ab791bb3a303ba717ec1563b591 100644 (file)
@@ -256,28 +256,28 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type)
                                      bank + ASIC3_GPIO_TRIGGER_TYPE);
        asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit;
 
-       if (type == IRQT_RISING) {
+       if (type == IRQ_TYPE_EDGE_RISING) {
                trigger |= bit;
                edge |= bit;
-       } else if (type == IRQT_FALLING) {
+       } else if (type == IRQ_TYPE_EDGE_FALLING) {
                trigger |= bit;
                edge &= ~bit;
-       } else if (type == IRQT_BOTHEDGE) {
+       } else if (type == IRQ_TYPE_EDGE_BOTH) {
                trigger |= bit;
                if (asic3_gpio_get(&asic->gpio, irq - asic->irq_base))
                        edge &= ~bit;
                else
                        edge |= bit;
                asic->irq_bothedge[(irq - asic->irq_base) >> 4] |= bit;
-       } else if (type == IRQT_LOW) {
+       } else if (type == IRQ_TYPE_LEVEL_LOW) {
                trigger &= ~bit;
                level &= ~bit;
-       } else if (type == IRQT_HIGH) {
+       } else if (type == IRQ_TYPE_LEVEL_HIGH) {
                trigger &= ~bit;
                level |= bit;
        } else {
                /*
-                * if type == IRQT_NOEDGE, we should mask interrupts, but
+                * if type == IRQ_TYPE_NONE, we should mask interrupts, but
                 * be careful to not unmask them if mask was also called.
                 * Probably need internal state for mask.
                 */
@@ -314,10 +314,12 @@ static int __init asic3_irq_probe(struct platform_device *pdev)
        unsigned long clksel = 0;
        unsigned int irq, irq_base;
        int map_size;
+       int ret;
 
-       asic->irq_nr = platform_get_irq(pdev, 0);
-       if (asic->irq_nr < 0)
-               return asic->irq_nr;
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0)
+               return ret;
+       asic->irq_nr = ret;
 
        /* turn on clock to IRQ controller */
        clksel |= CLOCK_SEL_CX;
@@ -341,7 +343,7 @@ static int __init asic3_irq_probe(struct platform_device *pdev)
                             ASIC3_INTMASK_GINTMASK);
 
        set_irq_chained_handler(asic->irq_nr, asic3_irq_demux);
-       set_irq_type(asic->irq_nr, IRQT_RISING);
+       set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING);
        set_irq_data(asic->irq_nr, asic);
 
        return 0;
index 8872cc0775190c296ab63bb67160b03f99cb3723..6be43172dc656911cd5c9f41f8717426e2be9e54 100644 (file)
@@ -318,6 +318,8 @@ static int __init egpio_probe(struct platform_device *pdev)
                ei->chip[i].dev = &(pdev->dev);
                chip = &(ei->chip[i].chip);
                chip->label           = "htc-egpio";
+               chip->dev             = &pdev->dev;
+               chip->owner           = THIS_MODULE;
                chip->get             = egpio_get;
                chip->set             = egpio_set;
                chip->direction_input = egpio_direction_input;
index 633cbba072f024f013a17f42cc8b3181c63ef8a4..91b294dcc13388ebdec67de1e5b54aaee30eb6e6 100644 (file)
@@ -238,6 +238,8 @@ static int pasic3_remove(struct platform_device *pdev)
        return 0;
 }
 
+MODULE_ALIAS("platform:pasic3");
+
 static struct platform_driver pasic3_driver = {
        .driver         = {
                .name   = "pasic3",
index 1eab7cffceaa10180b79df6cd404f5146f81a189..b5272b5ce3fae295b7edc527463e137d6e5a1a29 100644 (file)
@@ -242,6 +242,8 @@ static int mcp_sa11x0_resume(struct platform_device *dev)
 /*
  * The driver for the SA11x0 MCP port.
  */
+MODULE_ALIAS("platform:sa11x0-mcp");
+
 static struct platform_driver mcp_sa11x0_driver = {
        .probe          = mcp_sa11x0_probe,
        .remove         = mcp_sa11x0_remove,
index d7d88ce053a661fd4aa364c373509953340224e3..9c9c126ed334d406320088ce29e66a8f3958f15d 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/mfd/core.h>
 
-static int mfd_add_device(struct platform_device *parent,
-               const struct mfd_cell *cell,
-               struct resource *mem_base,
-               int irq_base)
+static int mfd_add_device(struct device *parent, int id,
+                         const struct mfd_cell *cell,
+                         struct resource *mem_base,
+                         int irq_base)
 {
        struct resource res[cell->num_resources];
        struct platform_device *pdev;
        int ret = -ENOMEM;
        int r;
 
-       pdev = platform_device_alloc(cell->name, parent->id);
+       pdev = platform_device_alloc(cell->name, id);
        if (!pdev)
                goto fail_alloc;
 
-       pdev->dev.parent = &parent->dev;
+       pdev->dev.parent = parent;
 
        ret = platform_device_add_data(pdev,
-                       cell, sizeof(struct mfd_cell));
+                       cell->platform_data, cell->data_size);
        if (ret)
                goto fail_device;
 
-       memzero(res, sizeof(res));
+       memset(res, 0, sizeof(res));
        for (r = 0; r < cell->num_resources; r++) {
                res[r].name = cell->resources[r].name;
                res[r].flags = cell->resources[r].flags;
@@ -75,17 +75,16 @@ fail_alloc:
        return ret;
 }
 
-int mfd_add_devices(
-               struct platform_device *parent,
-               const struct mfd_cell *cells, int n_devs,
-               struct resource *mem_base,
-               int irq_base)
+int mfd_add_devices(struct device *parent, int id,
+                   const struct mfd_cell *cells, int n_devs,
+                   struct resource *mem_base,
+                   int irq_base)
 {
        int i;
        int ret = 0;
 
        for (i = 0; i < n_devs; i++) {
-               ret = mfd_add_device(parent, cells + i, mem_base, irq_base);
+               ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base);
                if (ret)
                        break;
        }
@@ -99,14 +98,13 @@ EXPORT_SYMBOL(mfd_add_devices);
 
 static int mfd_remove_devices_fn(struct device *dev, void *unused)
 {
-       platform_device_unregister(
-                       container_of(dev, struct platform_device, dev));
+       platform_device_unregister(to_platform_device(dev));
        return 0;
 }
 
-void mfd_remove_devices(struct platform_device *parent)
+void mfd_remove_devices(struct device *parent)
 {
-       device_for_each_child(&parent->dev, NULL, mfd_remove_devices_fn);
+       device_for_each_child(parent, NULL, mfd_remove_devices_fn);
 }
 EXPORT_SYMBOL(mfd_remove_devices);
 
index 2fe64734d8afd2d6e893e40224ee56ff6b935706..7aebad4c06ff939114bdff7f5f58874ee197f96d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/pci.h>
+#include <linux/i2c-gpio.h>
 
 #include <linux/sm501.h>
 #include <linux/sm501-regs.h>
@@ -31,10 +32,37 @@ struct sm501_device {
        struct platform_device          pdev;
 };
 
+struct sm501_gpio;
+
+#ifdef CONFIG_MFD_SM501_GPIO
+#include <linux/gpio.h>
+
+struct sm501_gpio_chip {
+       struct gpio_chip        gpio;
+       struct sm501_gpio       *ourgpio;       /* to get back to parent. */
+       void __iomem            *regbase;
+};
+
+struct sm501_gpio {
+       struct sm501_gpio_chip  low;
+       struct sm501_gpio_chip  high;
+       spinlock_t              lock;
+
+       unsigned int             registered : 1;
+       void __iomem            *regs;
+       struct resource         *regs_res;
+};
+#else
+struct sm501_gpio {
+       /* no gpio support, empty definition for sm501_devdata. */
+};
+#endif
+
 struct sm501_devdata {
        spinlock_t                       reg_lock;
        struct mutex                     clock_lock;
        struct list_head                 devices;
+       struct sm501_gpio                gpio;
 
        struct device                   *dev;
        struct resource                 *io_res;
@@ -42,6 +70,7 @@ struct sm501_devdata {
        struct resource                 *regs_claim;
        struct sm501_platdata           *platdata;
 
+
        unsigned int                     in_suspend;
        unsigned long                    pm_misc;
 
@@ -52,6 +81,7 @@ struct sm501_devdata {
        unsigned int                     rev;
 };
 
+
 #define MHZ (1000 * 1000)
 
 #ifdef DEBUG
@@ -276,58 +306,6 @@ unsigned long sm501_modify_reg(struct device *dev,
 
 EXPORT_SYMBOL_GPL(sm501_modify_reg);
 
-unsigned long sm501_gpio_get(struct device *dev,
-                            unsigned long gpio)
-{
-       struct sm501_devdata *sm = dev_get_drvdata(dev);
-       unsigned long result;
-       unsigned long reg;
-
-       reg = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
-       result = readl(sm->regs + reg);
-
-       result >>= (gpio & 31);
-       return result & 1UL;
-}
-
-EXPORT_SYMBOL_GPL(sm501_gpio_get);
-
-void sm501_gpio_set(struct device *dev,
-                   unsigned long gpio,
-                   unsigned int to,
-                   unsigned int dir)
-{
-       struct sm501_devdata *sm = dev_get_drvdata(dev);
-
-       unsigned long bit = 1 << (gpio & 31);
-       unsigned long base;
-       unsigned long save;
-       unsigned long val;
-
-       base = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
-       base += SM501_GPIO;
-
-       spin_lock_irqsave(&sm->reg_lock, save);
-
-       val = readl(sm->regs + base) & ~bit;
-       if (to)
-               val |= bit;
-       writel(val, sm->regs + base);
-
-       val = readl(sm->regs + SM501_GPIO_DDR_LOW) & ~bit;
-       if (dir)
-               val |= bit;
-
-       writel(val, sm->regs + SM501_GPIO_DDR_LOW);
-       sm501_sync_regs(sm);
-
-       spin_unlock_irqrestore(&sm->reg_lock, save);
-
-}
-
-EXPORT_SYMBOL_GPL(sm501_gpio_set);
-
-
 /* sm501_unit_power
  *
  * alters the power active gate to set specific units on or off
@@ -906,6 +884,313 @@ static int sm501_register_display(struct sm501_devdata *sm,
        return sm501_register_device(sm, pdev);
 }
 
+#ifdef CONFIG_MFD_SM501_GPIO
+
+static inline struct sm501_gpio_chip *to_sm501_gpio(struct gpio_chip *gc)
+{
+       return container_of(gc, struct sm501_gpio_chip, gpio);
+}
+
+static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio)
+{
+       return container_of(gpio, struct sm501_devdata, gpio);
+}
+
+static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
+
+{
+       struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip);
+       unsigned long result;
+
+       result = readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
+       result >>= offset;
+
+       return result & 1UL;
+}
+
+static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+
+{
+       struct sm501_gpio_chip *smchip = to_sm501_gpio(chip);
+       struct sm501_gpio *smgpio = smchip->ourgpio;
+       unsigned long bit = 1 << offset;
+       void __iomem *regs = smchip->regbase;
+       unsigned long save;
+       unsigned long val;
+
+       dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
+               __func__, chip, offset);
+
+       spin_lock_irqsave(&smgpio->lock, save);
+
+       val = readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
+       if (value)
+               val |= bit;
+       writel(val, regs);
+
+       sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+       spin_unlock_irqrestore(&smgpio->lock, save);
+}
+
+static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct sm501_gpio_chip *smchip = to_sm501_gpio(chip);
+       struct sm501_gpio *smgpio = smchip->ourgpio;
+       void __iomem *regs = smchip->regbase;
+       unsigned long bit = 1 << offset;
+       unsigned long save;
+       unsigned long ddr;
+
+       dev_info(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
+                __func__, chip, offset);
+
+       spin_lock_irqsave(&smgpio->lock, save);
+
+       ddr = readl(regs + SM501_GPIO_DDR_LOW);
+       writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
+
+       sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+       spin_unlock_irqrestore(&smgpio->lock, save);
+
+       return 0;
+}
+
+static int sm501_gpio_output(struct gpio_chip *chip,
+                            unsigned offset, int value)
+{
+       struct sm501_gpio_chip *smchip = to_sm501_gpio(chip);
+       struct sm501_gpio *smgpio = smchip->ourgpio;
+       unsigned long bit = 1 << offset;
+       void __iomem *regs = smchip->regbase;
+       unsigned long save;
+       unsigned long val;
+       unsigned long ddr;
+
+       dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d,%d)\n",
+               __func__, chip, offset, value);
+
+       spin_lock_irqsave(&smgpio->lock, save);
+
+       val = readl(regs + SM501_GPIO_DATA_LOW);
+       if (value)
+               val |= bit;
+       else
+               val &= ~bit;
+       writel(val, regs);
+
+       ddr = readl(regs + SM501_GPIO_DDR_LOW);
+       writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
+
+       sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+       writel(val, regs + SM501_GPIO_DATA_LOW);
+
+       sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+       spin_unlock_irqrestore(&smgpio->lock, save);
+
+       return 0;
+}
+
+static struct gpio_chip gpio_chip_template = {
+       .ngpio                  = 32,
+       .direction_input        = sm501_gpio_input,
+       .direction_output       = sm501_gpio_output,
+       .set                    = sm501_gpio_set,
+       .get                    = sm501_gpio_get,
+};
+
+static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
+                                             struct sm501_gpio *gpio,
+                                             struct sm501_gpio_chip *chip)
+{
+       struct sm501_platdata *pdata = sm->platdata;
+       struct gpio_chip *gchip = &chip->gpio;
+       int base = pdata->gpio_base;
+
+       chip->gpio = gpio_chip_template;
+
+       if (chip == &gpio->high) {
+               if (base > 0)
+                       base += 32;
+               chip->regbase = gpio->regs + SM501_GPIO_DATA_HIGH;
+               gchip->label  = "SM501-HIGH";
+       } else {
+               chip->regbase = gpio->regs + SM501_GPIO_DATA_LOW;
+               gchip->label  = "SM501-LOW";
+       }
+
+       gchip->base   = base;
+       chip->ourgpio = gpio;
+
+       return gpiochip_add(gchip);
+}
+
+static int sm501_register_gpio(struct sm501_devdata *sm)
+{
+       struct sm501_gpio *gpio = &sm->gpio;
+       resource_size_t iobase = sm->io_res->start + SM501_GPIO;
+       int ret;
+       int tmp;
+
+       dev_dbg(sm->dev, "registering gpio block %08llx\n",
+               (unsigned long long)iobase);
+
+       spin_lock_init(&gpio->lock);
+
+       gpio->regs_res = request_mem_region(iobase, 0x20, "sm501-gpio");
+       if (gpio->regs_res == NULL) {
+               dev_err(sm->dev, "gpio: failed to request region\n");
+               return -ENXIO;
+       }
+
+       gpio->regs = ioremap(iobase, 0x20);
+       if (gpio->regs == NULL) {
+               dev_err(sm->dev, "gpio: failed to remap registers\n");
+               ret = -ENXIO;
+               goto err_claimed;
+       }
+
+       /* Register both our chips. */
+
+       ret = sm501_gpio_register_chip(sm, gpio, &gpio->low);
+       if (ret) {
+               dev_err(sm->dev, "failed to add low chip\n");
+               goto err_mapped;
+       }
+
+       ret = sm501_gpio_register_chip(sm, gpio, &gpio->high);
+       if (ret) {
+               dev_err(sm->dev, "failed to add high chip\n");
+               goto err_low_chip;
+       }
+
+       gpio->registered = 1;
+
+       return 0;
+
+ err_low_chip:
+       tmp = gpiochip_remove(&gpio->low.gpio);
+       if (tmp) {
+               dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n");
+               return ret;
+       }
+
+ err_mapped:
+       iounmap(gpio->regs);
+
+ err_claimed:
+       release_resource(gpio->regs_res);
+       kfree(gpio->regs_res);
+
+       return ret;
+}
+
+static void sm501_gpio_remove(struct sm501_devdata *sm)
+{
+       struct sm501_gpio *gpio = &sm->gpio;
+       int ret;
+
+       if (!sm->gpio.registered)
+               return;
+
+       ret = gpiochip_remove(&gpio->low.gpio);
+       if (ret)
+               dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n");
+
+       ret = gpiochip_remove(&gpio->high.gpio);
+       if (ret)
+               dev_err(sm->dev, "cannot remove high chip, cannot tidy up\n");
+
+       iounmap(gpio->regs);
+       release_resource(gpio->regs_res);
+       kfree(gpio->regs_res);
+}
+
+static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
+{
+       struct sm501_gpio *gpio = &sm->gpio;
+       int base = (pin < 32) ? gpio->low.gpio.base : gpio->high.gpio.base;
+
+       return (pin % 32) + base;
+}
+
+static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
+{
+       return sm->gpio.registered;
+}
+#else
+static inline int sm501_register_gpio(struct sm501_devdata *sm)
+{
+       return 0;
+}
+
+static inline void sm501_gpio_remove(struct sm501_devdata *sm)
+{
+}
+
+static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
+{
+       return -1;
+}
+
+static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
+{
+       return 0;
+}
+#endif
+
+static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
+                                           struct sm501_platdata_gpio_i2c *iic)
+{
+       struct i2c_gpio_platform_data *icd;
+       struct platform_device *pdev;
+
+       pdev = sm501_create_subdev(sm, "i2c-gpio", 0,
+                                  sizeof(struct i2c_gpio_platform_data));
+       if (!pdev)
+               return -ENOMEM;
+
+       icd = pdev->dev.platform_data;
+
+       /* We keep the pin_sda and pin_scl fields relative in case the
+        * same platform data is passed to >1 SM501.
+        */
+
+       icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda);
+       icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl);
+       icd->timeout = iic->timeout;
+       icd->udelay = iic->udelay;
+
+       /* note, we can't use either of the pin numbers, as the i2c-gpio
+        * driver uses the platform.id field to generate the bus number
+        * to register with the i2c core; The i2c core doesn't have enough
+        * entries to deal with anything we currently use.
+       */
+
+       pdev->id = iic->bus_num;
+
+       dev_info(sm->dev, "registering i2c-%d: sda=%d (%d), scl=%d (%d)\n",
+                iic->bus_num,
+                icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl);
+
+       return sm501_register_device(sm, pdev);
+}
+
+static int sm501_register_gpio_i2c(struct sm501_devdata *sm,
+                                  struct sm501_platdata *pdata)
+{
+       struct sm501_platdata_gpio_i2c *iic = pdata->gpio_i2c;
+       int index;
+       int ret;
+
+       for (index = 0; index < pdata->gpio_i2c_nr; index++, iic++) {
+               ret = sm501_register_gpio_i2c_instance(sm, iic);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
 /* sm501_dbg_regs
  *
  * Debug attribute to attach to parent device to show core registers
@@ -1013,6 +1298,7 @@ static unsigned int sm501_mem_local[] = {
 static int sm501_init_dev(struct sm501_devdata *sm)
 {
        struct sm501_initdata *idata;
+       struct sm501_platdata *pdata;
        resource_size_t mem_avail;
        unsigned long dramctrl;
        unsigned long devid;
@@ -1051,7 +1337,9 @@ static int sm501_init_dev(struct sm501_devdata *sm)
 
        /* check to see if we have some device initialisation */
 
-       idata = sm->platdata ? sm->platdata->init : NULL;
+       pdata = sm->platdata;
+       idata = pdata ? pdata->init : NULL;
+
        if (idata) {
                sm501_init_regs(sm, idata);
 
@@ -1059,6 +1347,15 @@ static int sm501_init_dev(struct sm501_devdata *sm)
                        sm501_register_usbhost(sm, &mem_avail);
                if (idata->devices & (SM501_USE_UART0 | SM501_USE_UART1))
                        sm501_register_uart(sm, idata->devices);
+               if (idata->devices & SM501_USE_GPIO)
+                       sm501_register_gpio(sm);
+       }
+
+       if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+               if (!sm501_gpio_isregistered(sm))
+                       dev_err(sm->dev, "no gpio available for i2c gpio.\n");
+               else
+                       sm501_register_gpio_i2c(sm, pdata);
        }
 
        ret = sm501_check_clocks(sm);
@@ -1138,8 +1435,31 @@ static int sm501_plat_probe(struct platform_device *dev)
 }
 
 #ifdef CONFIG_PM
+
 /* power management support */
 
+static void sm501_set_power(struct sm501_devdata *sm, int on)
+{
+       struct sm501_platdata *pd = sm->platdata;
+
+       if (pd == NULL)
+               return;
+
+       if (pd->get_power) {
+               if (pd->get_power(sm->dev) == on) {
+                       dev_dbg(sm->dev, "is already %d\n", on);
+                       return;
+               }
+       }
+
+       if (pd->set_power) {
+               dev_dbg(sm->dev, "setting power to %d\n", on);
+
+               pd->set_power(sm->dev, on);
+               sm501_mdelay(sm, 10);
+       }
+}
+
 static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct sm501_devdata *sm = platform_get_drvdata(pdev);
@@ -1148,6 +1468,12 @@ static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
        sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
 
        sm501_dump_regs(sm);
+
+       if (sm->platdata) {
+               if (sm->platdata->flags & SM501_FLAG_SUSPEND_OFF)
+                       sm501_set_power(sm, 0);
+       }
+
        return 0;
 }
 
@@ -1155,6 +1481,8 @@ static int sm501_plat_resume(struct platform_device *pdev)
 {
        struct sm501_devdata *sm = platform_get_drvdata(pdev);
 
+       sm501_set_power(sm, 1);
+
        sm501_dump_regs(sm);
        sm501_dump_gate(sm);
        sm501_dump_clk(sm);
@@ -1229,6 +1557,7 @@ static struct sm501_platdata_fb sm501_fb_pdata = {
 static struct sm501_platdata sm501_pci_platdata = {
        .init           = &sm501_pci_initdata,
        .fb             = &sm501_fb_pdata,
+       .gpio_base      = -1,
 };
 
 static int sm501_pci_probe(struct pci_dev *dev,
@@ -1335,6 +1664,8 @@ static void sm501_dev_remove(struct sm501_devdata *sm)
                sm501_remove_sub(sm, smdev);
 
        device_remove_file(sm->dev, &dev_attr_dbg_regs);
+
+       sm501_gpio_remove(sm);
 }
 
 static void sm501_pci_remove(struct pci_dev *dev)
@@ -1378,6 +1709,8 @@ static struct pci_driver sm501_pci_drv = {
        .remove         = sm501_pci_remove,
 };
 
+MODULE_ALIAS("platform:sm501");
+
 static struct platform_driver sm501_plat_drv = {
        .driver         = {
                .name   = "sm501",
index 2d87501b6fd49da6c258314950ab8734a2f6b3e3..f4fd797c15900fffe8a4de120d9da6c684156b45 100644 (file)
@@ -324,7 +324,7 @@ static void tc6393xb_attach_irq(struct platform_device *dev)
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       set_irq_type(tc6393xb->irq, IRQT_FALLING);
+       set_irq_type(tc6393xb->irq, IRQ_TYPE_EDGE_FALLING);
        set_irq_data(tc6393xb->irq, tc6393xb);
        set_irq_chained_handler(tc6393xb->irq, tc6393xb_irq);
 }
@@ -466,8 +466,12 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
                tc6393xb_attach_irq(dev);
 
        tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
+       tc6393xb_cells[TC6393XB_CELL_NAND].platform_data =
+               &tc6393xb_cells[TC6393XB_CELL_NAND];
+       tc6393xb_cells[TC6393XB_CELL_NAND].data_size =
+               sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]);
 
-       retval = mfd_add_devices(dev,
+       retval = mfd_add_devices(&dev->dev, dev->id,
                        tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
                        iomem, tcpd->irq_base);
 
@@ -501,7 +505,7 @@ static int __devexit tc6393xb_remove(struct platform_device *dev)
        struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
        int ret;
 
-       mfd_remove_devices(dev);
+       mfd_remove_devices(&dev->dev);
 
        if (tc6393xb->irq)
                tc6393xb_detach_irq(dev);
index ce67d973d349df0f76ed5a5eccb9836fdc604469..f5ade1904aadafefd641a90c36c63eacaf038dfd 100644 (file)
@@ -77,11 +77,13 @@ config IBM_ASM
          for your IBM server.
 
 config PHANTOM
-       tristate "Sensable PHANToM"
+       tristate "Sensable PHANToM (PCI)"
        depends on PCI
        help
          Say Y here if you want to build a driver for Sensable PHANToM device.
 
+         This driver is only for PCI PHANToMs.
+
          If you choose to build module, its name will be phantom. If unsure,
          say N here.
 
@@ -212,6 +214,18 @@ config TC1100_WMI
          This is a driver for the WMI extensions (wireless and bluetooth power
          control) of the HP Compaq TC1100 tablet.
 
+config HP_WMI
+       tristate "HP WMI extras"
+       depends on ACPI_WMI
+       depends on INPUT
+       depends on RFKILL
+       help
+         Say Y here if you want to support WMI-based hotkeys on HP laptops and
+        to read data from WMI such as docking or ambient light sensor state.
+
+         To compile this driver as a module, choose M here: the module will
+         be called hp-wmi.
+
 config MSI_LAPTOP
         tristate "MSI Laptop Extras"
         depends on X86
@@ -279,6 +293,8 @@ config THINKPAD_ACPI
        select INPUT
        select NEW_LEDS
        select LEDS_CLASS
+       select NET
+       select RFKILL
        ---help---
          This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
          support for Fn-Fx key combinations, Bluetooth control, video
@@ -344,7 +360,7 @@ config THINKPAD_ACPI_VIDEO
          If you are not sure, say Y here.
 
 config THINKPAD_ACPI_HOTKEY_POLL
-       bool "Suport NVRAM polling for hot keys"
+       bool "Support NVRAM polling for hot keys"
        depends on THINKPAD_ACPI
        default y
        ---help---
@@ -422,6 +438,7 @@ config SGI_XP
 
 config HP_ILO
        tristate "Channel interface driver for HP iLO/iLO2 processor"
+       depends on PCI
        default n
        help
          The channel interface driver allows applications to communicate
index 688fe76135e0eca608a8936edc324d37f91e4dea..f5e273420c090859847018861654d046235aa4de 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_ACER_WMI)                += acer-wmi.o
 obj-$(CONFIG_ATMEL_PWM)                += atmel_pwm.o
 obj-$(CONFIG_ATMEL_SSC)                += atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)      += atmel_tclib.o
+obj-$(CONFIG_HP_WMI)           += hp-wmi.o
 obj-$(CONFIG_TC1100_WMI)       += tc1100-wmi.o
 obj-$(CONFIG_LKDTM)            += lkdtm.o
 obj-$(CONFIG_TIFM_CORE)        += tifm_core.o
index e171650766ce73bfc324c6799d4e3521949c72be..bf5e4d065436a2153c76ff13ef6adae2f2604a49 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/atmel-ssc.h>
 
index 5b5a14dab3d38d5e77a26381f849d2e26822934c..6aa5294dfec4fc681305b03a63c1f8e63aecf0ee 100644 (file)
@@ -211,8 +211,7 @@ int pwm_clk_alloc(unsigned prescale, unsigned div)
        if ((mr & 0xffff) == 0) {
                mr |= val;
                ret = PWM_CPR_CLKA;
-       }
-       if ((mr & (0xffff << 16)) == 0) {
+       } else if ((mr & (0xffff << 16)) == 0) {
                mr |= val << 16;
                ret = PWM_CPR_CLKB;
        }
diff --git a/drivers/misc/hp-wmi.c b/drivers/misc/hp-wmi.c
new file mode 100644 (file)
index 0000000..1dbcbcb
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ * HP WMI hotkeys
+ *
+ * Copyright (C) 2008 Red Hat <mjg@redhat.com>
+ *
+ * Portions based on wistron_btns.c:
+ * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
+ * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/rfkill.h>
+#include <linux/string.h>
+
+MODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>");
+MODULE_DESCRIPTION("HP laptop WMI hotkeys driver");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
+MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
+
+#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
+#define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"
+
+#define HPWMI_DISPLAY_QUERY 0x1
+#define HPWMI_HDDTEMP_QUERY 0x2
+#define HPWMI_ALS_QUERY 0x3
+#define HPWMI_DOCK_QUERY 0x4
+#define HPWMI_WIRELESS_QUERY 0x5
+
+static int __init hp_wmi_bios_setup(struct platform_device *device);
+static int __exit hp_wmi_bios_remove(struct platform_device *device);
+
+struct bios_args {
+       u32 signature;
+       u32 command;
+       u32 commandtype;
+       u32 datasize;
+       u32 data;
+};
+
+struct bios_return {
+       u32 sigpass;
+       u32 return_code;
+       u32 value;
+};
+
+struct key_entry {
+       char type;              /* See KE_* below */
+       u8 code;
+       u16 keycode;
+};
+
+enum { KE_KEY, KE_SW, KE_END };
+
+static struct key_entry hp_wmi_keymap[] = {
+       {KE_SW, 0x01, SW_DOCK},
+       {KE_KEY, 0x02, KEY_BRIGHTNESSUP},
+       {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
+       {KE_KEY, 0x04, KEY_HELP},
+       {KE_END, 0}
+};
+
+static struct input_dev *hp_wmi_input_dev;
+static struct platform_device *hp_wmi_platform_dev;
+
+static struct rfkill *wifi_rfkill;
+static struct rfkill *bluetooth_rfkill;
+static struct rfkill *wwan_rfkill;
+
+static struct platform_driver hp_wmi_driver = {
+       .driver = {
+                  .name = "hp-wmi",
+                  .owner = THIS_MODULE,
+       },
+       .probe = hp_wmi_bios_setup,
+       .remove = hp_wmi_bios_remove,
+};
+
+static int hp_wmi_perform_query(int query, int write, int value)
+{
+       struct bios_return bios_return;
+       acpi_status status;
+       union acpi_object *obj;
+       struct bios_args args = {
+               .signature = 0x55434553,
+               .command = write ? 0x2 : 0x1,
+               .commandtype = query,
+               .datasize = write ? 0x4 : 0,
+               .data = value,
+       };
+       struct acpi_buffer input = { sizeof(struct bios_args), &args };
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+
+       status = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);
+
+       obj = output.pointer;
+
+       if (!obj || obj->type != ACPI_TYPE_BUFFER)
+               return -EINVAL;
+
+       bios_return = *((struct bios_return *)obj->buffer.pointer);
+       if (bios_return.return_code > 0)
+               return bios_return.return_code * -1;
+       else
+               return bios_return.value;
+}
+
+static int hp_wmi_display_state(void)
+{
+       return hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, 0);
+}
+
+static int hp_wmi_hddtemp_state(void)
+{
+       return hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, 0);
+}
+
+static int hp_wmi_als_state(void)
+{
+       return hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, 0);
+}
+
+static int hp_wmi_dock_state(void)
+{
+       return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0);
+}
+
+static int hp_wmi_wifi_set(void *data, enum rfkill_state state)
+{
+       if (state)
+               return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x101);
+       else
+               return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x100);
+}
+
+static int hp_wmi_bluetooth_set(void *data, enum rfkill_state state)
+{
+       if (state)
+               return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x202);
+       else
+               return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x200);
+}
+
+static int hp_wmi_wwan_set(void *data, enum rfkill_state state)
+{
+       if (state)
+               return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x404);
+       else
+               return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x400);
+}
+
+static int hp_wmi_wifi_state(void)
+{
+       int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+
+       if (wireless & 0x100)
+               return 1;
+       else
+               return 0;
+}
+
+static int hp_wmi_bluetooth_state(void)
+{
+       int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+
+       if (wireless & 0x10000)
+               return 1;
+       else
+               return 0;
+}
+
+static int hp_wmi_wwan_state(void)
+{
+       int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+
+       if (wireless & 0x1000000)
+               return 1;
+       else
+               return 0;
+}
+
+static ssize_t show_display(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       int value = hp_wmi_display_state();
+       if (value < 0)
+               return -EINVAL;
+       return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t show_hddtemp(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       int value = hp_wmi_hddtemp_state();
+       if (value < 0)
+               return -EINVAL;
+       return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t show_als(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       int value = hp_wmi_als_state();
+       if (value < 0)
+               return -EINVAL;
+       return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t show_dock(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       int value = hp_wmi_dock_state();
+       if (value < 0)
+               return -EINVAL;
+       return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t set_als(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       u32 tmp = simple_strtoul(buf, NULL, 10);
+       hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, tmp);
+       return count;
+}
+
+static DEVICE_ATTR(display, S_IRUGO, show_display, NULL);
+static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL);
+static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
+static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
+
+static struct key_entry *hp_wmi_get_entry_by_scancode(int code)
+{
+       struct key_entry *key;
+
+       for (key = hp_wmi_keymap; key->type != KE_END; key++)
+               if (code == key->code)
+                       return key;
+
+       return NULL;
+}
+
+static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode)
+{
+       struct key_entry *key;
+
+       for (key = hp_wmi_keymap; key->type != KE_END; key++)
+               if (key->type == KE_KEY && keycode == key->keycode)
+                       return key;
+
+       return NULL;
+}
+
+static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+       struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
+
+       if (key && key->type == KE_KEY) {
+               *keycode = key->keycode;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+       struct key_entry *key;
+       int old_keycode;
+
+       if (keycode < 0 || keycode > KEY_MAX)
+               return -EINVAL;
+
+       key = hp_wmi_get_entry_by_scancode(scancode);
+       if (key && key->type == KE_KEY) {
+               old_keycode = key->keycode;
+               key->keycode = keycode;
+               set_bit(keycode, dev->keybit);
+               if (!hp_wmi_get_entry_by_keycode(old_keycode))
+                       clear_bit(old_keycode, dev->keybit);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+void hp_wmi_notify(u32 value, void *context)
+{
+       struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+       static struct key_entry *key;
+       union acpi_object *obj;
+
+       wmi_get_event_data(value, &response);
+
+       obj = (union acpi_object *)response.pointer;
+
+       if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) {
+               int eventcode = *((u8 *) obj->buffer.pointer);
+               key = hp_wmi_get_entry_by_scancode(eventcode);
+               if (key) {
+                       switch (key->type) {
+                       case KE_KEY:
+                               input_report_key(hp_wmi_input_dev,
+                                                key->keycode, 1);
+                               input_sync(hp_wmi_input_dev);
+                               input_report_key(hp_wmi_input_dev,
+                                                key->keycode, 0);
+                               input_sync(hp_wmi_input_dev);
+                               break;
+                       case KE_SW:
+                               input_report_switch(hp_wmi_input_dev,
+                                                   key->keycode,
+                                                   hp_wmi_dock_state());
+                               input_sync(hp_wmi_input_dev);
+                               break;
+                       }
+               } else if (eventcode == 0x5) {
+                       if (wifi_rfkill)
+                               wifi_rfkill->state = hp_wmi_wifi_state();
+                       if (bluetooth_rfkill)
+                               bluetooth_rfkill->state =
+                                   hp_wmi_bluetooth_state();
+                       if (wwan_rfkill)
+                               wwan_rfkill->state = hp_wmi_wwan_state();
+               } else
+                       printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
+                              eventcode);
+       } else
+               printk(KERN_INFO "HP WMI: Unknown response received\n");
+}
+
+static int __init hp_wmi_input_setup(void)
+{
+       struct key_entry *key;
+       int err;
+
+       hp_wmi_input_dev = input_allocate_device();
+
+       hp_wmi_input_dev->name = "HP WMI hotkeys";
+       hp_wmi_input_dev->phys = "wmi/input0";
+       hp_wmi_input_dev->id.bustype = BUS_HOST;
+       hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode;
+       hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode;
+
+       for (key = hp_wmi_keymap; key->type != KE_END; key++) {
+               switch (key->type) {
+               case KE_KEY:
+                       set_bit(EV_KEY, hp_wmi_input_dev->evbit);
+                       set_bit(key->keycode, hp_wmi_input_dev->keybit);
+                       break;
+               case KE_SW:
+                       set_bit(EV_SW, hp_wmi_input_dev->evbit);
+                       set_bit(key->keycode, hp_wmi_input_dev->swbit);
+                       break;
+               }
+       }
+
+       err = input_register_device(hp_wmi_input_dev);
+
+       if (err) {
+               input_free_device(hp_wmi_input_dev);
+               return err;
+       }
+
+       return 0;
+}
+
+static void cleanup_sysfs(struct platform_device *device)
+{
+       device_remove_file(&device->dev, &dev_attr_display);
+       device_remove_file(&device->dev, &dev_attr_hddtemp);
+       device_remove_file(&device->dev, &dev_attr_als);
+       device_remove_file(&device->dev, &dev_attr_dock);
+}
+
+static int __init hp_wmi_bios_setup(struct platform_device *device)
+{
+       int err;
+
+       err = device_create_file(&device->dev, &dev_attr_display);
+       if (err)
+               goto add_sysfs_error;
+       err = device_create_file(&device->dev, &dev_attr_hddtemp);
+       if (err)
+               goto add_sysfs_error;
+       err = device_create_file(&device->dev, &dev_attr_als);
+       if (err)
+               goto add_sysfs_error;
+       err = device_create_file(&device->dev, &dev_attr_dock);
+       if (err)
+               goto add_sysfs_error;
+
+       wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
+       wifi_rfkill->name = "hp-wifi";
+       wifi_rfkill->state = hp_wmi_wifi_state();
+       wifi_rfkill->toggle_radio = hp_wmi_wifi_set;
+       wifi_rfkill->user_claim_unsupported = 1;
+
+       bluetooth_rfkill = rfkill_allocate(&device->dev,
+                                          RFKILL_TYPE_BLUETOOTH);
+       bluetooth_rfkill->name = "hp-bluetooth";
+       bluetooth_rfkill->state = hp_wmi_bluetooth_state();
+       bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
+       bluetooth_rfkill->user_claim_unsupported = 1;
+
+       wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX);
+       wwan_rfkill->name = "hp-wwan";
+       wwan_rfkill->state = hp_wmi_wwan_state();
+       wwan_rfkill->toggle_radio = hp_wmi_wwan_set;
+       wwan_rfkill->user_claim_unsupported = 1;
+
+       rfkill_register(wifi_rfkill);
+       rfkill_register(bluetooth_rfkill);
+       rfkill_register(wwan_rfkill);
+
+       return 0;
+add_sysfs_error:
+       cleanup_sysfs(device);
+       return err;
+}
+
+static int __exit hp_wmi_bios_remove(struct platform_device *device)
+{
+       cleanup_sysfs(device);
+
+       rfkill_unregister(wifi_rfkill);
+       rfkill_unregister(bluetooth_rfkill);
+       rfkill_unregister(wwan_rfkill);
+
+       return 0;
+}
+
+static int __init hp_wmi_init(void)
+{
+       int err;
+
+       if (wmi_has_guid(HPWMI_EVENT_GUID)) {
+               err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
+                                                hp_wmi_notify, NULL);
+               if (!err)
+                       hp_wmi_input_setup();
+       }
+
+       if (wmi_has_guid(HPWMI_BIOS_GUID)) {
+               err = platform_driver_register(&hp_wmi_driver);
+               if (err)
+                       return 0;
+               hp_wmi_platform_dev = platform_device_alloc("hp-wmi", -1);
+               if (!hp_wmi_platform_dev) {
+                       platform_driver_unregister(&hp_wmi_driver);
+                       return 0;
+               }
+               platform_device_add(hp_wmi_platform_dev);
+       }
+
+       return 0;
+}
+
+static void __exit hp_wmi_exit(void)
+{
+       if (wmi_has_guid(HPWMI_EVENT_GUID)) {
+               wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+               input_unregister_device(hp_wmi_input_dev);
+       }
+       if (hp_wmi_platform_dev) {
+               platform_device_del(hp_wmi_platform_dev);
+               platform_driver_unregister(&hp_wmi_driver);
+       }
+}
+
+module_init(hp_wmi_init);
+module_exit(hp_wmi_exit);
index 4ce3bdc2f959b4081a27a30dc7f8486ee9611057..daf585689ce33a0e77a07bd3991e2165f8c04acb 100644 (file)
@@ -563,6 +563,6 @@ module_init(phantom_init);
 module_exit(phantom_exit);
 
 MODULE_AUTHOR("Jiri Slaby <jirislaby@gmail.com>");
-MODULE_DESCRIPTION("Sensable Phantom driver");
+MODULE_DESCRIPTION("Sensable Phantom driver (PCI devices)");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(PHANTOM_VERSION);
index 579b01ff82d4ed73580365334f1790b29e70805d..c3b4227f48a5bbd78e5c6f85d54c87a8d68d403e 100644 (file)
@@ -229,11 +229,10 @@ xpc_hb_checker(void *ignore)
        int last_IRQ_count = 0;
        int new_IRQ_count;
        int force_IRQ = 0;
-       cpumask_of_cpu_ptr(cpumask, XPC_HB_CHECK_CPU);
 
        /* this thread was marked active by xpc_hb_init() */
 
-       set_cpus_allowed_ptr(current, cpumask);
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(XPC_HB_CHECK_CPU));
 
        /* set our heartbeating to other partitions into motion */
        xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
index b5969298f3d32e677726c018bb142f60f6c53148..d3eb7903c346aa9db41abf5897d8be04445f6213 100644 (file)
@@ -21,7 +21,7 @@
  *  02110-1301, USA.
  */
 
-#define TPACPI_VERSION "0.20"
+#define TPACPI_VERSION "0.21"
 #define TPACPI_SYSFS_VERSION 0x020200
 
 /*
@@ -68,6 +68,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/input.h>
 #include <linux/leds.h>
+#include <linux/rfkill.h>
 #include <asm/uaccess.h>
 
 #include <linux/dmi.h>
@@ -144,6 +145,12 @@ enum {
 
 #define TPACPI_MAX_ACPI_ARGS 3
 
+/* rfkill switches */
+enum {
+       TPACPI_RFK_BLUETOOTH_SW_ID = 0,
+       TPACPI_RFK_WWAN_SW_ID,
+};
+
 /* Debugging */
 #define TPACPI_LOG TPACPI_FILE ": "
 #define TPACPI_ERR        KERN_ERR    TPACPI_LOG
@@ -905,6 +912,43 @@ static int __init tpacpi_check_std_acpi_brightness_support(void)
        return 0;
 }
 
+static int __init tpacpi_new_rfkill(const unsigned int id,
+                       struct rfkill **rfk,
+                       const enum rfkill_type rfktype,
+                       const char *name,
+                       int (*toggle_radio)(void *, enum rfkill_state),
+                       int (*get_state)(void *, enum rfkill_state *))
+{
+       int res;
+       enum rfkill_state initial_state;
+
+       *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype);
+       if (!*rfk) {
+               printk(TPACPI_ERR
+                       "failed to allocate memory for rfkill class\n");
+               return -ENOMEM;
+       }
+
+       (*rfk)->name = name;
+       (*rfk)->get_state = get_state;
+       (*rfk)->toggle_radio = toggle_radio;
+
+       if (!get_state(NULL, &initial_state))
+               (*rfk)->state = initial_state;
+
+       res = rfkill_register(*rfk);
+       if (res < 0) {
+               printk(TPACPI_ERR
+                       "failed to register %s rfkill switch: %d\n",
+                       name, res);
+               rfkill_free(*rfk);
+               *rfk = NULL;
+               return res;
+       }
+
+       return 0;
+}
+
 /*************************************************************************
  * thinkpad-acpi driver attributes
  */
@@ -1285,21 +1329,6 @@ static int hotkey_status_set(int status)
        return 0;
 }
 
-static void tpacpi_input_send_radiosw(void)
-{
-       int wlsw;
-
-       if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
-               mutex_lock(&tpacpi_inputdev_send_mutex);
-
-               input_report_switch(tpacpi_inputdev,
-                                   SW_RFKILL_ALL, !!wlsw);
-               input_sync(tpacpi_inputdev);
-
-               mutex_unlock(&tpacpi_inputdev_send_mutex);
-       }
-}
-
 static void tpacpi_input_send_tabletsw(void)
 {
        int state;
@@ -1921,6 +1950,30 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
        &dev_attr_hotkey_wakeup_hotunplug_complete.attr,
 };
 
+static void bluetooth_update_rfk(void);
+static void wan_update_rfk(void);
+static void tpacpi_send_radiosw_update(void)
+{
+       int wlsw;
+
+       /* Sync these BEFORE sending any rfkill events */
+       if (tp_features.bluetooth)
+               bluetooth_update_rfk();
+       if (tp_features.wan)
+               wan_update_rfk();
+
+       if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
+               mutex_lock(&tpacpi_inputdev_send_mutex);
+
+               input_report_switch(tpacpi_inputdev,
+                                   SW_RFKILL_ALL, !!wlsw);
+               input_sync(tpacpi_inputdev);
+
+               mutex_unlock(&tpacpi_inputdev_send_mutex);
+       }
+       hotkey_radio_sw_notify_change();
+}
+
 static void hotkey_exit(void)
 {
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
@@ -2167,9 +2220,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
                printk(TPACPI_INFO
                        "radio switch found; radios are %s\n",
                        enabled(status, 0));
+       }
+       if (tp_features.hotkey_wlsw)
                res = add_to_attr_set(hotkey_dev_attributes,
                                &dev_attr_hotkey_radio_sw.attr);
-       }
 
        /* For X41t, X60t, X61t Tablets... */
        if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
@@ -2287,7 +2341,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
        tpacpi_inputdev->close = &hotkey_inputdev_close;
 
        hotkey_poll_setup_safe(1);
-       tpacpi_input_send_radiosw();
+       tpacpi_send_radiosw_update();
        tpacpi_input_send_tabletsw();
 
        return 0;
@@ -2419,8 +2473,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
                case 7:
                        /* 0x7000-0x7FFF: misc */
                        if (tp_features.hotkey_wlsw && hkey == 0x7000) {
-                               tpacpi_input_send_radiosw();
-                               hotkey_radio_sw_notify_change();
+                               tpacpi_send_radiosw_update();
                                send_acpi_ev = 0;
                                break;
                        }
@@ -2463,8 +2516,7 @@ static void hotkey_resume(void)
                printk(TPACPI_ERR
                       "error while trying to read hot key mask "
                       "from firmware\n");
-       tpacpi_input_send_radiosw();
-       hotkey_radio_sw_notify_change();
+       tpacpi_send_radiosw_update();
        hotkey_tablet_mode_notify_change();
        hotkey_wakeup_reason_notify_change();
        hotkey_wakeup_hotunplug_complete_notify_change();
@@ -2581,8 +2633,66 @@ enum {
        TP_ACPI_BLUETOOTH_UNK           = 0x04, /* unknown function */
 };
 
-static int bluetooth_get_radiosw(void);
-static int bluetooth_set_radiosw(int radio_on);
+static struct rfkill *tpacpi_bluetooth_rfkill;
+
+static int bluetooth_get_radiosw(void)
+{
+       int status;
+
+       if (!tp_features.bluetooth)
+               return -ENODEV;
+
+       /* WLSW overrides bluetooth in firmware/hardware, reflect that */
+       if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
+               return RFKILL_STATE_HARD_BLOCKED;
+
+       if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+               return -EIO;
+
+       return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0) ?
+               RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+}
+
+static void bluetooth_update_rfk(void)
+{
+       int status;
+
+       if (!tpacpi_bluetooth_rfkill)
+               return;
+
+       status = bluetooth_get_radiosw();
+       if (status < 0)
+               return;
+       rfkill_force_state(tpacpi_bluetooth_rfkill, status);
+}
+
+static int bluetooth_set_radiosw(int radio_on, int update_rfk)
+{
+       int status;
+
+       if (!tp_features.bluetooth)
+               return -ENODEV;
+
+       /* WLSW overrides bluetooth in firmware/hardware, but there is no
+        * reason to risk weird behaviour. */
+       if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
+           && radio_on)
+               return -EPERM;
+
+       if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+               return -EIO;
+       if (radio_on)
+               status |= TP_ACPI_BLUETOOTH_RADIOSSW;
+       else
+               status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
+       if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
+               return -EIO;
+
+       if (update_rfk)
+               bluetooth_update_rfk();
+
+       return 0;
+}
 
 /* sysfs bluetooth enable ---------------------------------------------- */
 static ssize_t bluetooth_enable_show(struct device *dev,
@@ -2595,7 +2705,8 @@ static ssize_t bluetooth_enable_show(struct device *dev,
        if (status < 0)
                return status;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0);
 }
 
 static ssize_t bluetooth_enable_store(struct device *dev,
@@ -2608,7 +2719,7 @@ static ssize_t bluetooth_enable_store(struct device *dev,
        if (parse_strtoul(buf, 1, &t))
                return -EINVAL;
 
-       res = bluetooth_set_radiosw(t);
+       res = bluetooth_set_radiosw(t, 1);
 
        return (res) ? res : count;
 }
@@ -2628,6 +2739,31 @@ static const struct attribute_group bluetooth_attr_group = {
        .attrs = bluetooth_attributes,
 };
 
+static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state)
+{
+       int bts = bluetooth_get_radiosw();
+
+       if (bts < 0)
+               return bts;
+
+       *state = bts;
+       return 0;
+}
+
+static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
+{
+       return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
+}
+
+static void bluetooth_exit(void)
+{
+       if (tpacpi_bluetooth_rfkill)
+               rfkill_unregister(tpacpi_bluetooth_rfkill);
+
+       sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+                       &bluetooth_attr_group);
+}
+
 static int __init bluetooth_init(struct ibm_init_struct *iibm)
 {
        int res;
@@ -2646,57 +2782,32 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
                str_supported(tp_features.bluetooth),
                status);
 
-       if (tp_features.bluetooth) {
-               if (!(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
-                       /* no bluetooth hardware present in system */
-                       tp_features.bluetooth = 0;
-                       dbg_printk(TPACPI_DBG_INIT,
-                                  "bluetooth hardware not installed\n");
-               } else {
-                       res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
-                                       &bluetooth_attr_group);
-                       if (res)
-                               return res;
-               }
+       if (tp_features.bluetooth &&
+           !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
+               /* no bluetooth hardware present in system */
+               tp_features.bluetooth = 0;
+               dbg_printk(TPACPI_DBG_INIT,
+                          "bluetooth hardware not installed\n");
        }
 
-       return (tp_features.bluetooth)? 0 : 1;
-}
-
-static void bluetooth_exit(void)
-{
-       sysfs_remove_group(&tpacpi_pdev->dev.kobj,
-                       &bluetooth_attr_group);
-}
-
-static int bluetooth_get_radiosw(void)
-{
-       int status;
-
        if (!tp_features.bluetooth)
-               return -ENODEV;
-
-       if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
-               return -EIO;
-
-       return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0);
-}
-
-static int bluetooth_set_radiosw(int radio_on)
-{
-       int status;
+               return 1;
 
-       if (!tp_features.bluetooth)
-               return -ENODEV;
+       res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+                               &bluetooth_attr_group);
+       if (res)
+               return res;
 
-       if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
-               return -EIO;
-       if (radio_on)
-               status |= TP_ACPI_BLUETOOTH_RADIOSSW;
-       else
-               status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
-       if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
-               return -EIO;
+       res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID,
+                               &tpacpi_bluetooth_rfkill,
+                               RFKILL_TYPE_BLUETOOTH,
+                               "tpacpi_bluetooth_sw",
+                               tpacpi_bluetooth_rfk_set,
+                               tpacpi_bluetooth_rfk_get);
+       if (res) {
+               bluetooth_exit();
+               return res;
+       }
 
        return 0;
 }
@@ -2711,7 +2822,8 @@ static int bluetooth_read(char *p)
                len += sprintf(p + len, "status:\t\tnot supported\n");
        else {
                len += sprintf(p + len, "status:\t\t%s\n",
-                               (status)? "enabled" : "disabled");
+                               (status == RFKILL_STATE_UNBLOCKED) ?
+                                       "enabled" : "disabled");
                len += sprintf(p + len, "commands:\tenable, disable\n");
        }
 
@@ -2727,9 +2839,9 @@ static int bluetooth_write(char *buf)
 
        while ((cmd = next_cmd(&buf))) {
                if (strlencmp(cmd, "enable") == 0) {
-                       bluetooth_set_radiosw(1);
+                       bluetooth_set_radiosw(1, 1);
                } else if (strlencmp(cmd, "disable") == 0) {
-                       bluetooth_set_radiosw(0);
+                       bluetooth_set_radiosw(0, 1);
                } else
                        return -EINVAL;
        }
@@ -2755,8 +2867,66 @@ enum {
        TP_ACPI_WANCARD_UNK             = 0x04, /* unknown function */
 };
 
-static int wan_get_radiosw(void);
-static int wan_set_radiosw(int radio_on);
+static struct rfkill *tpacpi_wan_rfkill;
+
+static int wan_get_radiosw(void)
+{
+       int status;
+
+       if (!tp_features.wan)
+               return -ENODEV;
+
+       /* WLSW overrides WWAN in firmware/hardware, reflect that */
+       if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
+               return RFKILL_STATE_HARD_BLOCKED;
+
+       if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+               return -EIO;
+
+       return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0) ?
+               RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+}
+
+static void wan_update_rfk(void)
+{
+       int status;
+
+       if (!tpacpi_wan_rfkill)
+               return;
+
+       status = wan_get_radiosw();
+       if (status < 0)
+               return;
+       rfkill_force_state(tpacpi_wan_rfkill, status);
+}
+
+static int wan_set_radiosw(int radio_on, int update_rfk)
+{
+       int status;
+
+       if (!tp_features.wan)
+               return -ENODEV;
+
+       /* WLSW overrides bluetooth in firmware/hardware, but there is no
+        * reason to risk weird behaviour. */
+       if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
+           && radio_on)
+               return -EPERM;
+
+       if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+               return -EIO;
+       if (radio_on)
+               status |= TP_ACPI_WANCARD_RADIOSSW;
+       else
+               status &= ~TP_ACPI_WANCARD_RADIOSSW;
+       if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
+               return -EIO;
+
+       if (update_rfk)
+               wan_update_rfk();
+
+       return 0;
+}
 
 /* sysfs wan enable ---------------------------------------------------- */
 static ssize_t wan_enable_show(struct device *dev,
@@ -2769,7 +2939,8 @@ static ssize_t wan_enable_show(struct device *dev,
        if (status < 0)
                return status;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0);
 }
 
 static ssize_t wan_enable_store(struct device *dev,
@@ -2782,7 +2953,7 @@ static ssize_t wan_enable_store(struct device *dev,
        if (parse_strtoul(buf, 1, &t))
                return -EINVAL;
 
-       res = wan_set_radiosw(t);
+       res = wan_set_radiosw(t, 1);
 
        return (res) ? res : count;
 }
@@ -2802,6 +2973,31 @@ static const struct attribute_group wan_attr_group = {
        .attrs = wan_attributes,
 };
 
+static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state)
+{
+       int wans = wan_get_radiosw();
+
+       if (wans < 0)
+               return wans;
+
+       *state = wans;
+       return 0;
+}
+
+static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
+{
+       return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
+}
+
+static void wan_exit(void)
+{
+       if (tpacpi_wan_rfkill)
+               rfkill_unregister(tpacpi_wan_rfkill);
+
+       sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+               &wan_attr_group);
+}
+
 static int __init wan_init(struct ibm_init_struct *iibm)
 {
        int res;
@@ -2818,57 +3014,32 @@ static int __init wan_init(struct ibm_init_struct *iibm)
                str_supported(tp_features.wan),
                status);
 
-       if (tp_features.wan) {
-               if (!(status & TP_ACPI_WANCARD_HWPRESENT)) {
-                       /* no wan hardware present in system */
-                       tp_features.wan = 0;
-                       dbg_printk(TPACPI_DBG_INIT,
-                                  "wan hardware not installed\n");
-               } else {
-                       res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
-                                       &wan_attr_group);
-                       if (res)
-                               return res;
-               }
+       if (tp_features.wan &&
+           !(status & TP_ACPI_WANCARD_HWPRESENT)) {
+               /* no wan hardware present in system */
+               tp_features.wan = 0;
+               dbg_printk(TPACPI_DBG_INIT,
+                          "wan hardware not installed\n");
        }
 
-       return (tp_features.wan)? 0 : 1;
-}
-
-static void wan_exit(void)
-{
-       sysfs_remove_group(&tpacpi_pdev->dev.kobj,
-               &wan_attr_group);
-}
-
-static int wan_get_radiosw(void)
-{
-       int status;
-
        if (!tp_features.wan)
-               return -ENODEV;
-
-       if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
-               return -EIO;
-
-       return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0);
-}
-
-static int wan_set_radiosw(int radio_on)
-{
-       int status;
+               return 1;
 
-       if (!tp_features.wan)
-               return -ENODEV;
+       res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+                               &wan_attr_group);
+       if (res)
+               return res;
 
-       if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
-               return -EIO;
-       if (radio_on)
-               status |= TP_ACPI_WANCARD_RADIOSSW;
-       else
-               status &= ~TP_ACPI_WANCARD_RADIOSSW;
-       if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
-               return -EIO;
+       res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID,
+                               &tpacpi_wan_rfkill,
+                               RFKILL_TYPE_WWAN,
+                               "tpacpi_wwan_sw",
+                               tpacpi_wan_rfk_set,
+                               tpacpi_wan_rfk_get);
+       if (res) {
+               wan_exit();
+               return res;
+       }
 
        return 0;
 }
@@ -2883,7 +3054,8 @@ static int wan_read(char *p)
                len += sprintf(p + len, "status:\t\tnot supported\n");
        else {
                len += sprintf(p + len, "status:\t\t%s\n",
-                               (status)? "enabled" : "disabled");
+                               (status == RFKILL_STATE_UNBLOCKED) ?
+                                       "enabled" : "disabled");
                len += sprintf(p + len, "commands:\tenable, disable\n");
        }
 
@@ -2899,9 +3071,9 @@ static int wan_write(char *buf)
 
        while ((cmd = next_cmd(&buf))) {
                if (strlencmp(cmd, "enable") == 0) {
-                       wan_set_radiosw(1);
+                       wan_set_radiosw(1, 1);
                } else if (strlencmp(cmd, "disable") == 0) {
-                       wan_set_radiosw(0);
+                       wan_set_radiosw(0, 1);
                } else
                        return -EINVAL;
        }
@@ -6168,13 +6340,18 @@ err_out:
 
 /* Probing */
 
-static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
+/* returns 0 - probe ok, or < 0 - probe error.
+ * Probe ok doesn't mean thinkpad found.
+ * On error, kfree() cleanup on tp->* is not performed, caller must do it */
+static int __must_check __init get_thinkpad_model_data(
+                                               struct thinkpad_id_data *tp)
 {
        const struct dmi_device *dev = NULL;
        char ec_fw_string[18];
+       char const *s;
 
        if (!tp)
-               return;
+               return -EINVAL;
 
        memset(tp, 0, sizeof(*tp));
 
@@ -6183,12 +6360,14 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
        else if (dmi_name_in_vendors("LENOVO"))
                tp->vendor = PCI_VENDOR_ID_LENOVO;
        else
-               return;
+               return 0;
 
-       tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION),
-                                       GFP_KERNEL);
+       s = dmi_get_system_info(DMI_BIOS_VERSION);
+       tp->bios_version_str = kstrdup(s, GFP_KERNEL);
+       if (s && !tp->bios_version_str)
+               return -ENOMEM;
        if (!tp->bios_version_str)
-               return;
+               return 0;
        tp->bios_model = tp->bios_version_str[0]
                         | (tp->bios_version_str[1] << 8);
 
@@ -6207,21 +6386,27 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
                        ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
 
                        tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
+                       if (!tp->ec_version_str)
+                               return -ENOMEM;
                        tp->ec_model = ec_fw_string[0]
                                        | (ec_fw_string[1] << 8);
                        break;
                }
        }
 
-       tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION),
-                                       GFP_KERNEL);
-       if (tp->model_str && strnicmp(tp->model_str, "ThinkPad", 8) != 0) {
-               kfree(tp->model_str);
-               tp->model_str = NULL;
+       s = dmi_get_system_info(DMI_PRODUCT_VERSION);
+       if (s && !strnicmp(s, "ThinkPad", 8)) {
+               tp->model_str = kstrdup(s, GFP_KERNEL);
+               if (!tp->model_str)
+                       return -ENOMEM;
        }
 
-       tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME),
-                                       GFP_KERNEL);
+       s = dmi_get_system_info(DMI_PRODUCT_NAME);
+       tp->nummodel_str = kstrdup(s, GFP_KERNEL);
+       if (s && !tp->nummodel_str)
+               return -ENOMEM;
+
+       return 0;
 }
 
 static int __init probe_for_thinkpad(void)
@@ -6484,7 +6669,13 @@ static int __init thinkpad_acpi_module_init(void)
 
        /* Driver-level probe */
 
-       get_thinkpad_model_data(&thinkpad_id);
+       ret = get_thinkpad_model_data(&thinkpad_id);
+       if (ret) {
+               printk(TPACPI_ERR
+                       "unable to get DMI data: %d\n", ret);
+               thinkpad_acpi_module_exit();
+               return ret;
+       }
        ret = probe_for_thinkpad();
        if (ret) {
                thinkpad_acpi_module_exit();
index 19a1a254a0c5f81d8e0a36815caf4b870b6497cc..889e5f898f6f99485c6b031aee41f5a6ff86d0aa 100644 (file)
@@ -12,3 +12,4 @@ mmc_core-y                    := core.o bus.o host.o \
                                   sdio.o sdio_ops.o sdio_bus.o \
                                   sdio_cis.o sdio_io.o sdio_irq.o
 
+mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
index fd95b18e988b3c33496c309f41dcc38356a82c47..0d9b2d6f9ebfba638b2bba41a0a0f6d28c922cc6 100644 (file)
@@ -252,6 +252,10 @@ int mmc_add_card(struct mmc_card *card)
        if (ret)
                return ret;
 
+#ifdef CONFIG_DEBUG_FS
+       mmc_add_card_debugfs(card);
+#endif
+
        mmc_card_set_present(card);
 
        return 0;
@@ -263,6 +267,10 @@ int mmc_add_card(struct mmc_card *card)
  */
 void mmc_remove_card(struct mmc_card *card)
 {
+#ifdef CONFIG_DEBUG_FS
+       mmc_remove_card_debugfs(card);
+#endif
+
        if (mmc_card_present(card)) {
                if (mmc_host_is_spi(card->host)) {
                        printk(KERN_INFO "%s: SPI card removed\n",
index cdb332b7dedc87340ef5ff0aacedc71f8b4fe931..c819effa1032c5ccebf896dff58d78f6e7ca13d5 100644 (file)
@@ -52,5 +52,12 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
 
 extern int use_spi_crc;
 
+/* Debugfs information for hosts and cards */
+void mmc_add_host_debugfs(struct mmc_host *host);
+void mmc_remove_host_debugfs(struct mmc_host *host);
+
+void mmc_add_card_debugfs(struct mmc_card *card);
+void mmc_remove_card_debugfs(struct mmc_card *card);
+
 #endif
 
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
new file mode 100644 (file)
index 0000000..1237bb4
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Debugfs support for hosts and cards
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/stat.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include "core.h"
+#include "mmc_ops.h"
+
+/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
+static int mmc_ios_show(struct seq_file *s, void *data)
+{
+       static const char *vdd_str[] = {
+               [8]     = "2.0",
+               [9]     = "2.1",
+               [10]    = "2.2",
+               [11]    = "2.3",
+               [12]    = "2.4",
+               [13]    = "2.5",
+               [14]    = "2.6",
+               [15]    = "2.7",
+               [16]    = "2.8",
+               [17]    = "2.9",
+               [18]    = "3.0",
+               [19]    = "3.1",
+               [20]    = "3.2",
+               [21]    = "3.3",
+               [22]    = "3.4",
+               [23]    = "3.5",
+               [24]    = "3.6",
+       };
+       struct mmc_host *host = s->private;
+       struct mmc_ios  *ios = &host->ios;
+       const char *str;
+
+       seq_printf(s, "clock:\t\t%u Hz\n", ios->clock);
+       seq_printf(s, "vdd:\t\t%u ", ios->vdd);
+       if ((1 << ios->vdd) & MMC_VDD_165_195)
+               seq_printf(s, "(1.65 - 1.95 V)\n");
+       else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1)
+                       && vdd_str[ios->vdd] && vdd_str[ios->vdd + 1])
+               seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd],
+                               vdd_str[ios->vdd + 1]);
+       else
+               seq_printf(s, "(invalid)\n");
+
+       switch (ios->bus_mode) {
+       case MMC_BUSMODE_OPENDRAIN:
+               str = "open drain";
+               break;
+       case MMC_BUSMODE_PUSHPULL:
+               str = "push-pull";
+               break;
+       default:
+               str = "invalid";
+               break;
+       }
+       seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str);
+
+       switch (ios->chip_select) {
+       case MMC_CS_DONTCARE:
+               str = "don't care";
+               break;
+       case MMC_CS_HIGH:
+               str = "active high";
+               break;
+       case MMC_CS_LOW:
+               str = "active low";
+               break;
+       default:
+               str = "invalid";
+               break;
+       }
+       seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str);
+
+       switch (ios->power_mode) {
+       case MMC_POWER_OFF:
+               str = "off";
+               break;
+       case MMC_POWER_UP:
+               str = "up";
+               break;
+       case MMC_POWER_ON:
+               str = "on";
+               break;
+       default:
+               str = "invalid";
+               break;
+       }
+       seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str);
+       seq_printf(s, "bus width:\t%u (%u bits)\n",
+                       ios->bus_width, 1 << ios->bus_width);
+
+       switch (ios->timing) {
+       case MMC_TIMING_LEGACY:
+               str = "legacy";
+               break;
+       case MMC_TIMING_MMC_HS:
+               str = "mmc high-speed";
+               break;
+       case MMC_TIMING_SD_HS:
+               str = "sd high-speed";
+               break;
+       default:
+               str = "invalid";
+               break;
+       }
+       seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
+
+       return 0;
+}
+
+static int mmc_ios_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mmc_ios_show, inode->i_private);
+}
+
+static const struct file_operations mmc_ios_fops = {
+       .open           = mmc_ios_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+void mmc_add_host_debugfs(struct mmc_host *host)
+{
+       struct dentry *root;
+
+       root = debugfs_create_dir(mmc_hostname(host), NULL);
+       if (IS_ERR(root))
+               /* Don't complain -- debugfs just isn't enabled */
+               return;
+       if (!root)
+               /* Complain -- debugfs is enabled, but it failed to
+                * create the directory. */
+               goto err_root;
+
+       host->debugfs_root = root;
+
+       if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops))
+               goto err_ios;
+
+       return;
+
+err_ios:
+       debugfs_remove_recursive(root);
+       host->debugfs_root = NULL;
+err_root:
+       dev_err(&host->class_dev, "failed to initialize debugfs\n");
+}
+
+void mmc_remove_host_debugfs(struct mmc_host *host)
+{
+       debugfs_remove_recursive(host->debugfs_root);
+}
+
+static int mmc_dbg_card_status_get(void *data, u64 *val)
+{
+       struct mmc_card *card = data;
+       u32             status;
+       int             ret;
+
+       mmc_claim_host(card->host);
+
+       ret = mmc_send_status(data, &status);
+       if (!ret)
+               *val = status;
+
+       mmc_release_host(card->host);
+
+       return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
+               NULL, "%08llx\n");
+
+void mmc_add_card_debugfs(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       struct dentry   *root;
+
+       if (!host->debugfs_root)
+               return;
+
+       root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root);
+       if (IS_ERR(root))
+               /* Don't complain -- debugfs just isn't enabled */
+               return;
+       if (!root)
+               /* Complain -- debugfs is enabled, but it failed to
+                * create the directory. */
+               goto err;
+
+       card->debugfs_root = root;
+
+       if (!debugfs_create_x32("state", S_IRUSR, root, &card->state))
+               goto err;
+
+       if (mmc_card_mmc(card) || mmc_card_sd(card))
+               if (!debugfs_create_file("status", S_IRUSR, root, card,
+                                       &mmc_dbg_card_status_fops))
+                       goto err;
+
+       return;
+
+err:
+       debugfs_remove_recursive(root);
+       card->debugfs_root = NULL;
+       dev_err(&card->dev, "failed to initialize debugfs\n");
+}
+
+void mmc_remove_card_debugfs(struct mmc_card *card)
+{
+       debugfs_remove_recursive(card->debugfs_root);
+}
index 1d795c5379b548f5869b83d7aabf05848a6d27b1..6da80fd4d974669223ac2caf54576f6521c52083 100644 (file)
@@ -127,6 +127,10 @@ int mmc_add_host(struct mmc_host *host)
        if (err)
                return err;
 
+#ifdef CONFIG_DEBUG_FS
+       mmc_add_host_debugfs(host);
+#endif
+
        mmc_start_host(host);
 
        return 0;
@@ -146,6 +150,10 @@ void mmc_remove_host(struct mmc_host *host)
 {
        mmc_stop_host(host);
 
+#ifdef CONFIG_DEBUG_FS
+       mmc_remove_host_debugfs(host);
+#endif
+
        device_del(&host->class_dev);
 
        led_trigger_unregister_simple(host->led);
index a9a5657706c6de2b22b3a92f0086eaa043df8b4b..26bd80e650317397545b4c62d0393f7d429c6e36 100644 (file)
@@ -82,6 +82,8 @@
 # define MCI_OVRE              (  1 <<  30)    /* RX Overrun Error */
 # define MCI_UNRE              (  1 <<  31)    /* TX Underrun Error */
 
+#define MCI_REGS_SIZE          0x100
+
 /* Register access macros */
 #define mci_readl(port,reg)                            \
        __raw_readl((port)->regs + MCI_##reg)
index cce873c5a149528f7d65fb3c5891a71bb5cdb502..992b4beb757c6593f4a790a0a749fcac5af8d165 100644 (file)
@@ -9,13 +9,18 @@
  */
 #include <linux/blkdev.h>
 #include <linux/clk.h>
+#include <linux/debugfs.h>
 #include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
+#include <linux/seq_file.h>
+#include <linux/stat.h>
 
 #include <linux/mmc/host.h>
 
@@ -24,7 +29,6 @@
 #include <asm/unaligned.h>
 
 #include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
 
 #include "atmel-mci-regs.h"
 
@@ -88,6 +92,188 @@ struct atmel_mci {
 #define atmci_clear_pending(host, event)                       \
        clear_bit(event, &host->pending_events)
 
+/*
+ * The debugfs stuff below is mostly optimized away when
+ * CONFIG_DEBUG_FS is not set.
+ */
+static int atmci_req_show(struct seq_file *s, void *v)
+{
+       struct atmel_mci        *host = s->private;
+       struct mmc_request      *mrq = host->mrq;
+       struct mmc_command      *cmd;
+       struct mmc_command      *stop;
+       struct mmc_data         *data;
+
+       /* Make sure we get a consistent snapshot */
+       spin_lock_irq(&host->mmc->lock);
+
+       if (mrq) {
+               cmd = mrq->cmd;
+               data = mrq->data;
+               stop = mrq->stop;
+
+               if (cmd)
+                       seq_printf(s,
+                               "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
+                               cmd->opcode, cmd->arg, cmd->flags,
+                               cmd->resp[0], cmd->resp[1], cmd->resp[2],
+                               cmd->resp[2], cmd->error);
+               if (data)
+                       seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
+                               data->bytes_xfered, data->blocks,
+                               data->blksz, data->flags, data->error);
+               if (stop)
+                       seq_printf(s,
+                               "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
+                               stop->opcode, stop->arg, stop->flags,
+                               stop->resp[0], stop->resp[1], stop->resp[2],
+                               stop->resp[2], stop->error);
+       }
+
+       spin_unlock_irq(&host->mmc->lock);
+
+       return 0;
+}
+
+static int atmci_req_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, atmci_req_show, inode->i_private);
+}
+
+static const struct file_operations atmci_req_fops = {
+       .owner          = THIS_MODULE,
+       .open           = atmci_req_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void atmci_show_status_reg(struct seq_file *s,
+               const char *regname, u32 value)
+{
+       static const char       *sr_bit[] = {
+               [0]     = "CMDRDY",
+               [1]     = "RXRDY",
+               [2]     = "TXRDY",
+               [3]     = "BLKE",
+               [4]     = "DTIP",
+               [5]     = "NOTBUSY",
+               [8]     = "SDIOIRQA",
+               [9]     = "SDIOIRQB",
+               [16]    = "RINDE",
+               [17]    = "RDIRE",
+               [18]    = "RCRCE",
+               [19]    = "RENDE",
+               [20]    = "RTOE",
+               [21]    = "DCRCE",
+               [22]    = "DTOE",
+               [30]    = "OVRE",
+               [31]    = "UNRE",
+       };
+       unsigned int            i;
+
+       seq_printf(s, "%s:\t0x%08x", regname, value);
+       for (i = 0; i < ARRAY_SIZE(sr_bit); i++) {
+               if (value & (1 << i)) {
+                       if (sr_bit[i])
+                               seq_printf(s, " %s", sr_bit[i]);
+                       else
+                               seq_puts(s, " UNKNOWN");
+               }
+       }
+       seq_putc(s, '\n');
+}
+
+static int atmci_regs_show(struct seq_file *s, void *v)
+{
+       struct atmel_mci        *host = s->private;
+       u32                     *buf;
+
+       buf = kmalloc(MCI_REGS_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       /* Grab a more or less consistent snapshot */
+       spin_lock_irq(&host->mmc->lock);
+       memcpy_fromio(buf, host->regs, MCI_REGS_SIZE);
+       spin_unlock_irq(&host->mmc->lock);
+
+       seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n",
+                       buf[MCI_MR / 4],
+                       buf[MCI_MR / 4] & MCI_MR_RDPROOF ? " RDPROOF" : "",
+                       buf[MCI_MR / 4] & MCI_MR_WRPROOF ? " WRPROOF" : "",
+                       buf[MCI_MR / 4] & 0xff);
+       seq_printf(s, "DTOR:\t0x%08x\n", buf[MCI_DTOR / 4]);
+       seq_printf(s, "SDCR:\t0x%08x\n", buf[MCI_SDCR / 4]);
+       seq_printf(s, "ARGR:\t0x%08x\n", buf[MCI_ARGR / 4]);
+       seq_printf(s, "BLKR:\t0x%08x BCNT=%u BLKLEN=%u\n",
+                       buf[MCI_BLKR / 4],
+                       buf[MCI_BLKR / 4] & 0xffff,
+                       (buf[MCI_BLKR / 4] >> 16) & 0xffff);
+
+       /* Don't read RSPR and RDR; it will consume the data there */
+
+       atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]);
+       atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]);
+
+       return 0;
+}
+
+static int atmci_regs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, atmci_regs_show, inode->i_private);
+}
+
+static const struct file_operations atmci_regs_fops = {
+       .owner          = THIS_MODULE,
+       .open           = atmci_regs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void atmci_init_debugfs(struct atmel_mci *host)
+{
+       struct mmc_host *mmc;
+       struct dentry   *root;
+       struct dentry   *node;
+       struct resource *res;
+
+       mmc = host->mmc;
+       root = mmc->debugfs_root;
+       if (!root)
+               return;
+
+       node = debugfs_create_file("regs", S_IRUSR, root, host,
+                       &atmci_regs_fops);
+       if (IS_ERR(node))
+               return;
+       if (!node)
+               goto err;
+
+       res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
+       node->d_inode->i_size = res->end - res->start + 1;
+
+       node = debugfs_create_file("req", S_IRUSR, root, host, &atmci_req_fops);
+       if (!node)
+               goto err;
+
+       node = debugfs_create_x32("pending_events", S_IRUSR, root,
+                                    (u32 *)&host->pending_events);
+       if (!node)
+               goto err;
+
+       node = debugfs_create_x32("completed_events", S_IRUSR, root,
+                                    (u32 *)&host->completed_events);
+       if (!node)
+               goto err;
+
+       return;
+
+err:
+       dev_err(&host->pdev->dev,
+               "failed to initialize debugfs for controller\n");
+}
 
 static void atmci_enable(struct atmel_mci *host)
 {
@@ -388,7 +574,7 @@ static int atmci_get_ro(struct mmc_host *mmc)
        int                     read_only = 0;
        struct atmel_mci        *host = mmc_priv(mmc);
 
-       if (host->wp_pin >= 0) {
+       if (gpio_is_valid(host->wp_pin)) {
                read_only = gpio_get_value(host->wp_pin);
                dev_dbg(&mmc->class_dev, "card is %s\n",
                                read_only ? "read-only" : "read-write");
@@ -450,7 +636,7 @@ static void atmci_detect_change(unsigned long data)
         * been freed.
         */
        smp_rmb();
-       if (host->detect_pin < 0)
+       if (!gpio_is_valid(host->detect_pin))
                return;
 
        enable_irq(gpio_to_irq(host->detect_pin));
@@ -865,7 +1051,7 @@ static int __init atmci_probe(struct platform_device *pdev)
 
        /* Assume card is present if we don't have a detect pin */
        host->present = 1;
-       if (host->detect_pin >= 0) {
+       if (gpio_is_valid(host->detect_pin)) {
                if (gpio_request(host->detect_pin, "mmc_detect")) {
                        dev_dbg(&mmc->class_dev, "no detect pin available\n");
                        host->detect_pin = -1;
@@ -873,7 +1059,7 @@ static int __init atmci_probe(struct platform_device *pdev)
                        host->present = !gpio_get_value(host->detect_pin);
                }
        }
-       if (host->wp_pin >= 0) {
+       if (gpio_is_valid(host->wp_pin)) {
                if (gpio_request(host->wp_pin, "mmc_wp")) {
                        dev_dbg(&mmc->class_dev, "no WP pin available\n");
                        host->wp_pin = -1;
@@ -884,7 +1070,7 @@ static int __init atmci_probe(struct platform_device *pdev)
 
        mmc_add_host(mmc);
 
-       if (host->detect_pin >= 0) {
+       if (gpio_is_valid(host->detect_pin)) {
                setup_timer(&host->detect_timer, atmci_detect_change,
                                (unsigned long)host);
 
@@ -905,6 +1091,8 @@ static int __init atmci_probe(struct platform_device *pdev)
                        "Atmel MCI controller at 0x%08lx irq %d\n",
                        host->mapbase, irq);
 
+       atmci_init_debugfs(host);
+
        return 0;
 
 err_request_irq:
@@ -923,7 +1111,9 @@ static int __exit atmci_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        if (host) {
-               if (host->detect_pin >= 0) {
+               /* Debugfs stuff is cleaned up by mmc core */
+
+               if (gpio_is_valid(host->detect_pin)) {
                        int pin = host->detect_pin;
 
                        /* Make sure the timer doesn't enable the interrupt */
@@ -943,7 +1133,7 @@ static int __exit atmci_remove(struct platform_device *pdev)
                mci_readl(host, SR);
                clk_disable(host->mck);
 
-               if (host->wp_pin >= 0)
+               if (gpio_is_valid(host->wp_pin))
                        gpio_free(host->wp_pin);
 
                free_irq(platform_get_irq(pdev, 0), host->mmc);
index 5e880c0f13495105105efee78d1eadcebdfa4a29..f61406da65d2c953e31896395209ce76428990cc 100644 (file)
  *
  */
 
-#ifdef CONFIG_MMC_DEBUG
-#define DEBUG
-#else
-#undef  DEBUG
-#endif
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -907,31 +901,12 @@ static const struct mmc_host_ops imxmci_ops = {
        .get_ro         = imxmci_get_ro,
 };
 
-static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr)
-{
-       int i;
-
-       for (i = 0; i < dev->num_resources; i++)
-               if (dev->resource[i].flags == mask && nr-- == 0)
-                       return &dev->resource[i];
-       return NULL;
-}
-
-static int platform_device_irq(struct platform_device *dev, int nr)
-{
-       int i;
-
-       for (i = 0; i < dev->num_resources; i++)
-               if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0)
-                       return dev->resource[i].start;
-       return NO_IRQ;
-}
-
 static void imxmci_check_status(unsigned long data)
 {
        struct imxmci_host *host = (struct imxmci_host *)data;
 
-       if( host->pdata->card_present(mmc_dev(host->mmc)) != host->present ) {
+       if (host->pdata && host->pdata->card_present &&
+           host->pdata->card_present(mmc_dev(host->mmc)) != host->present) {
                host->present ^= 1;
                dev_info(mmc_dev(host->mmc), "card %s\n",
                      host->present ? "inserted" : "removed");
@@ -962,13 +937,12 @@ static int imxmci_probe(struct platform_device *pdev)
 
        printk(KERN_INFO "i.MX mmc driver\n");
 
-       r = platform_device_resource(pdev, IORESOURCE_MEM, 0);
-       irq = platform_device_irq(pdev, 0);
-       if (!r || irq == NO_IRQ)
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_get_irq(pdev, 0);
+       if (!r || irq < 0)
                return -ENXIO;
 
-       r = request_mem_region(r->start, 0x100, "IMXMCI");
-       if (!r)
+       if (!request_mem_region(r->start, 0x100, pdev->name))
                return -EBUSY;
 
        mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev);
@@ -995,6 +969,8 @@ static int imxmci_probe(struct platform_device *pdev)
        host->mmc = mmc;
        host->dma_allocated = 0;
        host->pdata = pdev->dev.platform_data;
+       if (!host->pdata)
+               dev_warn(&pdev->dev, "No platform data provided!\n");
 
        spin_lock_init(&host->lock);
        host->res = r;
@@ -1047,7 +1023,11 @@ static int imxmci_probe(struct platform_device *pdev)
        if (ret)
                goto out;
 
-       host->present = host->pdata->card_present(mmc_dev(mmc));
+       if (host->pdata && host->pdata->card_present)
+               host->present = host->pdata->card_present(mmc_dev(mmc));
+       else    /* if there is no way to detect assume that card is present */
+               host->present = 1;
+
        init_timer(&host->timer);
        host->timer.data = (unsigned long)host;
        host->timer.function = imxmci_check_status;
@@ -1073,7 +1053,7 @@ out:
        }
        if (mmc)
                mmc_free_host(mmc);
-       release_resource(r);
+       release_mem_region(r->start, 0x100);
        return ret;
 }
 
@@ -1102,7 +1082,7 @@ static int imxmci_remove(struct platform_device *pdev)
                clk_disable(host->clk);
                clk_put(host->clk);
 
-               release_resource(host->res);
+               release_mem_region(host->res->start, 0x100);
 
                mmc_free_host(mmc);
        }
index 41cc63360e43d357db2d5d42a06cf55b0abd47b3..7503b81374e0783690df20afbc88da0b02a75e85 100644 (file)
@@ -1076,6 +1076,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                 */
                if (canpower && ios->power_mode == MMC_POWER_OFF) {
                        int mres;
+                       u8 nullbyte = 0;
 
                        host->spi->mode &= ~(SPI_CPOL|SPI_CPHA);
                        mres = spi_setup(host->spi);
@@ -1083,7 +1084,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                                dev_dbg(&host->spi->dev,
                                        "switch to SPI mode 0 failed\n");
 
-                       if (spi_w8r8(host->spi, 0x00) < 0)
+                       if (spi_write(host->spi, &nullbyte, 1) < 0)
                                dev_dbg(&host->spi->dev,
                                        "put spi signals to low failed\n");
 
index c3a5db72ddd73b7fd48a29cd467c889ba36978a5..5f95e10229b5f64cf55e79e8930b2c69d4f9181f 100644 (file)
@@ -337,7 +337,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 
        host->align_addr = dma_map_single(mmc_dev(host->mmc),
                host->align_buffer, 128 * 4, direction);
-       if (dma_mapping_error(host->align_addr))
+       if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
                goto fail;
        BUG_ON(host->align_addr & 0x3);
 
@@ -439,7 +439,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 
        host->adma_addr = dma_map_single(mmc_dev(host->mmc),
                host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
-       if (dma_mapping_error(host->align_addr))
+       if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
                goto unmap_entries;
        BUG_ON(host->adma_addr & 0x3);
 
index a06bf8b89343f760ede4d573d8412d6bf0932957..e354faee5df00ad0a0396992e8945ca626fb4e9e 100644 (file)
@@ -9,6 +9,8 @@
  * your option) any later version.
  */
 
+#include <linux/scatterlist.h>
+
 /*
  * Controller registers
  */
index eed06d068fd12f36f64c11a37ea0e3ea7c611d32..14f11f8b9e5fd556fcd71dbe4d6178634c851bcc 100644 (file)
@@ -1,5 +1,3 @@
-# $Id: Kconfig,v 1.11 2005/11/07 11:14:19 gleixner Exp $
-
 menuconfig MTD
        tristate "Memory Technology Device (MTD) support"
        depends on HAS_IOMEM
index 52d51eb91c16f7c1a7a5ec7c3cbbcd5936cb5a39..d072ca5be689a5ee8f1a426e3d1103762fb75283 100644 (file)
@@ -21,8 +21,6 @@
    This is access code for flashes using ARM's flash partitioning
    standards.
 
-   $Id: afs.c,v 1.15 2005/11/07 11:14:19 gleixner Exp $
-
 ======================================================================*/
 
 #include <linux/module.h>
index fcd1aeccdf9393d0780da7ff83c94d8f32e1af62..5f1b472137a024b96fcff3ea3f9bcd654c7389f8 100644 (file)
@@ -4,8 +4,6 @@
  *
  * (C) 2000 Red Hat. GPL'd
  *
- * $Id: cfi_cmdset_0001.c,v 1.186 2005/11/23 22:07:52 nico Exp $
- *
  *
  * 10/10/2000  Nicolas Pitre <nico@cam.org>
  *     - completely revamped method functions so they are aware and
@@ -50,6 +48,8 @@
 #define I82802AC       0x00ac
 #define MANUFACTURER_ST         0x0020
 #define M50LPW080       0x002F
+#define M50FLW080A     0x0080
+#define M50FLW080B     0x0081
 #define AT49BV640D     0x02de
 
 static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
@@ -204,7 +204,7 @@ static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
 {
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
-       struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
+       struct cfi_pri_intelext *extp = cfi->cmdset_priv;
 
        printk(KERN_WARNING "cfi_cmdset_0001: Suspend "
                            "erase on write disabled.\n");
@@ -301,6 +301,8 @@ static struct cfi_fixup jedec_fixup_table[] = {
        { MANUFACTURER_INTEL, I82802AB,   fixup_use_fwh_lock, NULL, },
        { MANUFACTURER_INTEL, I82802AC,   fixup_use_fwh_lock, NULL, },
        { MANUFACTURER_ST,    M50LPW080,  fixup_use_fwh_lock, NULL, },
+       { MANUFACTURER_ST,    M50FLW080A, fixup_use_fwh_lock, NULL, },
+       { MANUFACTURER_ST,    M50FLW080B, fixup_use_fwh_lock, NULL, },
        { 0, 0, NULL, NULL }
 };
 static struct cfi_fixup fixup_table[] = {
@@ -1147,7 +1149,7 @@ static int inval_cache_and_wait_for_operation(
        struct cfi_private *cfi = map->fldrv_priv;
        map_word status, status_OK = CMD(0x80);
        int chip_state = chip->state;
-       unsigned int timeo, sleep_time;
+       unsigned int timeo, sleep_time, reset_timeo;
 
        spin_unlock(chip->mutex);
        if (inval_len)
@@ -1158,6 +1160,7 @@ static int inval_cache_and_wait_for_operation(
        timeo = chip_op_time * 8;
        if (!timeo)
                timeo = 500000;
+       reset_timeo = timeo;
        sleep_time = chip_op_time / 2;
 
        for (;;) {
@@ -1199,6 +1202,12 @@ static int inval_cache_and_wait_for_operation(
                        remove_wait_queue(&chip->wq, &wait);
                        spin_lock(chip->mutex);
                }
+               if (chip->erase_suspended || chip->write_suspended)  {
+                       /* Suspend has occured while sleep: reset timeout */
+                       timeo = reset_timeo;
+                       chip->erase_suspended = 0;
+                       chip->write_suspended = 0;
+               }
        }
 
        /* Done and happy. */
index f7fcc6389533c3221dac34ab72878605d4f94e0b..a972cc6be436367f797a90f5099aca14a7e8a7a9 100644 (file)
@@ -16,9 +16,6 @@
  * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
  *
  * This code is GPL
- *
- * $Id: cfi_cmdset_0002.c,v 1.122 2005/11/07 11:14:22 gleixner Exp $
- *
  */
 
 #include <linux/module.h>
index 1b720cc571f315dfbb1ec2a7faed160835bbb00b..d4714dd9f7ab0d1f6626f87b584899844bc056e0 100644 (file)
@@ -4,8 +4,6 @@
  *
  * (C) 2000 Red Hat. GPL'd
  *
- * $Id: cfi_cmdset_0020.c,v 1.22 2005/11/07 11:14:22 gleixner Exp $
- *
  * 10/10/2000  Nicolas Pitre <nico@cam.org>
  *     - completely revamped method functions so they are aware and
  *       independent of the flash geometry (buswidth, interleave, etc.)
index a4463a91ce31877881beb14427bf8bc6b6f5fd5a..c418e92e1d92b79286f46a173bd1f93ff3591939 100644 (file)
@@ -1,7 +1,6 @@
 /*
    Common Flash Interface probe code.
    (C) 2000 Red Hat. GPL'd.
-   $Id: cfi_probe.c,v 1.86 2005/11/29 14:48:31 gleixner Exp $
 */
 
 #include <linux/module.h>
index 72e0022a47bf50e360686068b66e6d52dbe895a6..0ee457018016083743ca772a38d77325aa6911ae 100644 (file)
@@ -6,9 +6,6 @@
  * Copyright (C) 2003 STMicroelectronics Limited
  *
  * This code is covered by the GPL.
- *
- * $Id: cfi_util.c,v 1.10 2005/11/07 11:14:23 gleixner Exp $
- *
  */
 
 #include <linux/module.h>
index 2174c97549f0e868290799970d71697560bdf4bb..c857609682276468baac7079d2de839c60d7a84d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: chipreg.c,v 1.17 2004/11/16 18:29:00 dwmw2 Exp $
- *
  * Registration for chip drivers
  *
  */
index d338b8c92780255d9d71a62f9484010a0cac7b64..f061885b2812dc5d04bba96f488aa6fa18a9ae49 100644 (file)
@@ -2,7 +2,6 @@
  * Routines common to all CFI-type probes.
  * (C) 2001-2003 Red Hat, Inc.
  * GPL'd
- * $Id: gen_probe.c,v 1.24 2005/11/07 11:14:23 gleixner Exp $
  */
 
 #include <linux/kernel.h>
@@ -71,8 +70,8 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
           interleave and device type, etc. */
        if (!genprobe_new_chip(map, cp, &cfi)) {
                /* The probe didn't like it */
-               printk(KERN_DEBUG "%s: Found no %s device at location zero\n",
-                      cp->name, map->name);
+               pr_debug("%s: Found no %s device at location zero\n",
+                        cp->name, map->name);
                return NULL;
        }
 
index aa07575eb28834adfd09683a95ed87e1a5e6ccc6..dbba5abf0db86d809bc325cbe653f5120ffa183f 100644 (file)
@@ -1,7 +1,6 @@
 /*
    Common Flash Interface probe code.
    (C) 2000 Red Hat. GPL'd.
-   $Id: jedec_probe.c,v 1.66 2005/11/07 11:14:23 gleixner Exp $
    See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)
    for the standard this probe goes back to.
 
@@ -26,6 +25,7 @@
 /* Manufacturers */
 #define MANUFACTURER_AMD       0x0001
 #define MANUFACTURER_ATMEL     0x001f
+#define MANUFACTURER_EON       0x001c
 #define MANUFACTURER_FUJITSU   0x0004
 #define MANUFACTURER_HYUNDAI   0x00AD
 #define MANUFACTURER_INTEL     0x0089
@@ -37,6 +37,7 @@
 #define MANUFACTURER_ST                0x0020
 #define MANUFACTURER_TOSHIBA   0x0098
 #define MANUFACTURER_WINBOND   0x00da
+#define CONTINUATION_CODE      0x007f
 
 
 /* AMD */
@@ -58,6 +59,8 @@
 #define AM29LV040B     0x004F
 #define AM29F032B      0x0041
 #define AM29F002T      0x00B0
+#define AM29SL800DB    0x226B
+#define AM29SL800DT    0x22EA
 
 /* Atmel */
 #define AT49BV512      0x0003
 #define AT49BV32X      0x00C8
 #define AT49BV32XT     0x00C9
 
+/* Eon */
+#define EN29SL800BB    0x226B
+#define EN29SL800BT    0x22EA
+
 /* Fujitsu */
 #define MBM29F040C     0x00A4
 #define MBM29F800BA    0x2258
 #define M50FW080       0x002D
 #define M50FW016       0x002E
 #define M50LPW080       0x002F
+#define M50FLW080A     0x0080
+#define M50FLW080B     0x0081
 
 /* SST */
 #define SST29EE020     0x0010
@@ -191,6 +200,7 @@ enum uaddr {
        MTD_UADDR_0x0555_0x0AAA,
        MTD_UADDR_0x5555_0x2AAA,
        MTD_UADDR_0x0AAA_0x0555,
+       MTD_UADDR_0xAAAA_0x5555,
        MTD_UADDR_DONT_CARE,            /* Requires an arbitrary address */
        MTD_UADDR_UNNECESSARY,          /* Does not require any address */
 };
@@ -238,6 +248,11 @@ static const struct unlock_addr  unlock_addrs[] = {
                .addr2 = 0x0555
        },
 
+       [MTD_UADDR_0xAAAA_0x5555] = {
+               .addr1 = 0xaaaa,
+               .addr2 = 0x5555
+       },
+
        [MTD_UADDR_DONT_CARE] = {
                .addr1 = 0x0000,      /* Doesn't matter which address */
                .addr2 = 0x0000       /* is used - must be last entry */
@@ -521,6 +536,36 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x02000,2),
                        ERASEINFO(0x04000,1),
                }
+       }, {
+               .mfr_id         = MANUFACTURER_AMD,
+               .dev_id         = AM29SL800DT,
+               .name           = "AMD AM29SL800DT",
+               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_0x0AAA_0x0555,
+               .dev_size       = SIZE_1MiB,
+               .cmd_set        = P_ID_AMD_STD,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x10000,15),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x04000,1),
+               }
+       }, {
+               .mfr_id         = MANUFACTURER_AMD,
+               .dev_id         = AM29SL800DB,
+               .name           = "AMD AM29SL800DB",
+               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_0x0AAA_0x0555,
+               .dev_size       = SIZE_1MiB,
+               .cmd_set        = P_ID_AMD_STD,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x04000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x10000,15),
+               }
        }, {
                .mfr_id         = MANUFACTURER_ATMEL,
                .dev_id         = AT49BV512,
@@ -598,6 +643,36 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x10000,63),
                        ERASEINFO(0x02000,8)
                }
+       }, {
+               .mfr_id         = MANUFACTURER_EON,
+               .dev_id         = EN29SL800BT,
+               .name           = "Eon EN29SL800BT",
+               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_0x0AAA_0x0555,
+               .dev_size       = SIZE_1MiB,
+               .cmd_set        = P_ID_AMD_STD,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x10000,15),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x04000,1),
+               }
+       }, {
+               .mfr_id         = MANUFACTURER_EON,
+               .dev_id         = EN29SL800BB,
+               .name           = "Eon EN29SL800BB",
+               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_0x0AAA_0x0555,
+               .dev_size       = SIZE_1MiB,
+               .cmd_set        = P_ID_AMD_STD,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x04000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x10000,15),
+               }
        }, {
                .mfr_id         = MANUFACTURER_FUJITSU,
                .dev_id         = MBM29F040C,
@@ -1392,8 +1467,8 @@ static const struct amd_flash_info jedec_table[] = {
                .mfr_id         = MANUFACTURER_SST,     /* should be CFI */
                .dev_id         = SST39LF160,
                .name           = "SST 39LF160",
-               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
-               .uaddr          = MTD_UADDR_0x5555_0x2AAA,      /* ???? */
+               .devtypes       = CFI_DEVICETYPE_X16,
+               .uaddr          = MTD_UADDR_0xAAAA_0x5555,
                .dev_size       = SIZE_2MiB,
                .cmd_set        = P_ID_AMD_STD,
                .nr_regions     = 2,
@@ -1405,8 +1480,8 @@ static const struct amd_flash_info jedec_table[] = {
                .mfr_id         = MANUFACTURER_SST,     /* should be CFI */
                .dev_id         = SST39VF1601,
                .name           = "SST 39VF1601",
-               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
-               .uaddr          = MTD_UADDR_0x5555_0x2AAA,      /* ???? */
+               .devtypes       = CFI_DEVICETYPE_X16,
+               .uaddr          = MTD_UADDR_0xAAAA_0x5555,
                .dev_size       = SIZE_2MiB,
                .cmd_set        = P_ID_AMD_STD,
                .nr_regions     = 2,
@@ -1590,6 +1665,36 @@ static const struct amd_flash_info jedec_table[] = {
                .nr_regions     = 1,
                .regions        = {
                        ERASEINFO(0x10000,16),
+               },
+       }, {
+               .mfr_id         = MANUFACTURER_ST,
+               .dev_id         = M50FLW080A,
+               .name           = "ST M50FLW080A",
+               .devtypes       = CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_UNNECESSARY,
+               .dev_size       = SIZE_1MiB,
+               .cmd_set        = P_ID_INTEL_EXT,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x1000,16),
+                       ERASEINFO(0x10000,13),
+                       ERASEINFO(0x1000,16),
+                       ERASEINFO(0x1000,16),
+               }
+       }, {
+               .mfr_id         = MANUFACTURER_ST,
+               .dev_id         = M50FLW080B,
+               .name           = "ST M50FLW080B",
+               .devtypes       = CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_UNNECESSARY,
+               .dev_size       = SIZE_1MiB,
+               .cmd_set        = P_ID_INTEL_EXT,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x1000,16),
+                       ERASEINFO(0x1000,16),
+                       ERASEINFO(0x10000,13),
+                       ERASEINFO(0x1000,16),
                }
        }, {
                .mfr_id         = MANUFACTURER_TOSHIBA,
@@ -1696,9 +1801,21 @@ static inline u32 jedec_read_mfr(struct map_info *map, uint32_t base,
 {
        map_word result;
        unsigned long mask;
-       u32 ofs = cfi_build_cmd_addr(0, cfi_interleave(cfi), cfi->device_type);
-       mask = (1 << (cfi->device_type * 8)) -1;
-       result = map_read(map, base + ofs);
+       int bank = 0;
+
+       /* According to JEDEC "Standard Manufacturer's Identification Code"
+        * (http://www.jedec.org/download/search/jep106W.pdf)
+        * several first banks can contain 0x7f instead of actual ID
+        */
+       do {
+               uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8),
+                                                 cfi_interleave(cfi),
+                                                 cfi->device_type);
+               mask = (1 << (cfi->device_type * 8)) - 1;
+               result = map_read(map, base + ofs);
+               bank++;
+       } while ((result.x[0] & mask) == CONTINUATION_CODE);
+
        return result.x[0] & mask;
 }
 
index fc478c0f93f55bdcce74f7f82393a5c36a39b605..494d30d0631a30b255b39c3996d827844aae948e 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * Common code to handle absent "placeholder" devices
  * Copyright 2001 Resilience Corporation <ebrower@resilience.com>
- * $Id: map_absent.c,v 1.6 2005/11/07 11:14:23 gleixner Exp $
  *
  * This map driver is used to allocate "placeholder" MTD
  * devices on systems that have socketed/removable media.
index 5cb6d5263661a63f862d458a6b3a2dfdc31686ae..072dd8abf33a726620bd0f9299c3005632ce4ee4 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * Common code to handle map devices which are simple RAM
  * (C) 2000 Red Hat. GPL'd.
- * $Id: map_ram.c,v 1.22 2005/01/05 18:05:12 dwmw2 Exp $
  */
 
 #include <linux/module.h>
index cb27f855074c279a65ce23a53cc2615ff9417d55..821d0ed6bae3970453a38d2e40bb0bb802930b1d 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * Common code to handle map devices which are simple ROM
  * (C) 2000 Red Hat. GPL'd.
- * $Id: map_rom.c,v 1.23 2005/01/05 18:05:12 dwmw2 Exp $
  */
 
 #include <linux/module.h>
index e472a0e9de9d913228cfa47bc8351b9f360c9e12..71bc07f149b7910f964a5bc9b4c678a149cfbdf9 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: cmdlinepart.c,v 1.19 2005/11/07 11:14:19 gleixner Exp $
- *
  * Read flash partition table from command line
  *
  * Copyright 2002 SYSGO Real-Time Solutions GmbH
@@ -308,7 +306,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
        unsigned long offset;
        int i;
        struct cmdline_mtd_partition *part;
-       char *mtd_id = master->name;
+       const char *mtd_id = master->name;
 
        /* parse command line */
        if (!cmdline_parsed)
index 35ed1103dbb22096c183eb0a903072ec8ef73e1a..9c613f06623cd4d1191eafb7e6d4adfb75736037 100644 (file)
@@ -1,5 +1,4 @@
 # drivers/mtd/maps/Kconfig
-# $Id: Kconfig,v 1.18 2005/11/07 11:14:24 gleixner Exp $
 
 menu "Self-contained MTD device drivers"
        depends on MTD!=n
index 0f788d5c4bf8307b9b609891338bc4469b755534..0993d5cf3923f3a4895a6579aa18759bb76a3c72 100644 (file)
@@ -1,7 +1,6 @@
 #
 # linux/drivers/devices/Makefile
 #
-# $Id: Makefile.common,v 1.7 2004/12/22 17:51:15 joern Exp $
 
 obj-$(CONFIG_MTD_DOC2000)      += doc2000.o
 obj-$(CONFIG_MTD_DOC2001)      += doc2001.o
index 7b72a1b36115f4b1bf4c581c6d67c1e6f6454566..91fbba767635baba3a3bc7755fd8b6c99b230975 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: block2mtd.c,v 1.30 2005/11/29 14:48:32 gleixner Exp $
- *
  * block2mtd.c - create an mtd from a block device
  *
  * Copyright (C) 2001,2002     Simon Evans <spse@secret.org.uk>
@@ -20,9 +18,6 @@
 #include <linux/mutex.h>
 #include <linux/mount.h>
 
-#define VERSION "$Revision: 1.30 $"
-
-
 #define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args)
 #define INFO(fmt, args...) printk(KERN_INFO "block2mtd: " fmt "\n" , ## args)
 
@@ -453,7 +448,6 @@ MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
 static int __init block2mtd_init(void)
 {
        int ret = 0;
-       INFO("version " VERSION);
 
 #ifndef MODULE
        if (strlen(block2mtd_paramline))
index 846989f292e3f01a1992dd73f999583263b9ec7f..50de839c77a9edf410747ba963ae4c3c93d49156 100644 (file)
@@ -3,8 +3,6 @@
  * Linux driver for Disk-On-Chip 2000 and Millennium
  * (c) 1999 Machine Vision Holdings, Inc.
  * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
- *
- * $Id: doc2000.c,v 1.67 2005/11/07 11:14:24 gleixner Exp $
  */
 
 #include <linux/kernel.h>
index 6413efc045e0c98e1e657229fdbdd55e67671b1d..e32c568c11450e1c8041f4e28604ed1b72654d00 100644 (file)
@@ -3,8 +3,6 @@
  * Linux driver for Disk-On-Chip Millennium
  * (c) 1999 Machine Vision Holdings, Inc.
  * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
- *
- * $Id: doc2001.c,v 1.49 2005/11/07 11:14:24 gleixner Exp $
  */
 
 #include <linux/kernel.h>
index 83be3461658f22527a40ab1e57ec0efa503c8252..d853f891b586d65e82254d44716f3cd78de47005 100644 (file)
@@ -6,8 +6,6 @@
  * (c) 1999 Machine Vision Holdings, Inc.
  * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
  *
- * $Id: doc2001plus.c,v 1.14 2005/11/07 11:14:24 gleixner Exp $
- *
  * Released under GPL
  */
 
index fd8a8daba3a82d47915a705b703bfd0b8f21fa75..874e51b110a2d4cfbdadef073e146aab68040bdc 100644 (file)
@@ -7,8 +7,6 @@
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
  * Copyright (C) 2000 Netgem S.A.
  *
- * $Id: docecc.c,v 1.7 2005/11/07 11:14:25 gleixner Exp $
- *
  * 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
index d8cc94ec4e504495421c5a3a558c02cdf8fff024..6e62922942b18efd1a63fc44dfbad3d6ae087612 100644 (file)
@@ -4,9 +4,6 @@
 /* (C) 1999 Machine Vision Holdings, Inc.                      */
 /* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>         */
 
-/* $Id: docprobe.c,v 1.46 2005/11/07 11:14:25 gleixner Exp $   */
-
-
 
 /* DOC_PASSIVE_PROBE:
    In order to ensure that the BIOS checksum is correct at boot time, and
@@ -79,8 +76,6 @@ static unsigned long __initdata doc_locations[] = {
        0xe0000, 0xe2000, 0xe4000, 0xe6000,
        0xe8000, 0xea000, 0xec000, 0xee000,
 #endif /*  CONFIG_MTD_DOCPROBE_HIGH */
-#elif defined(__PPC__)
-       0xe4000000,
 #else
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
 #endif
index 1d324e5c412d547834f05eab936e181f92085c67..f4bda4cee4958869d12291bfa93ad10939eedeb4 100644 (file)
@@ -2,8 +2,6 @@
 /*
  * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART.
  *
- * $Id: lart.c,v 1.9 2005/11/07 11:14:25 gleixner Exp $
- *
  * Author: Abraham vd Merwe <abraham@2d3d.co.za>
  *
  * Copyright (c) 2001, 2d3D, Inc.
index b402269301f6f64e4d22108ffc148f8220108b03..b35c3333e210b61878493d3fd052e1228b38d6db 100644 (file)
@@ -33,6 +33,7 @@
 /* Flash opcodes. */
 #define        OPCODE_WREN             0x06    /* Write enable */
 #define        OPCODE_RDSR             0x05    /* Read status register */
+#define        OPCODE_WRSR             0x01    /* Write status register 1 byte */
 #define        OPCODE_NORM_READ        0x03    /* Read data bytes (low frequency) */
 #define        OPCODE_FAST_READ        0x0b    /* Read data bytes (high frequency) */
 #define        OPCODE_PP               0x02    /* Page program (up to 256 bytes) */
@@ -112,6 +113,17 @@ static int read_sr(struct m25p *flash)
        return val;
 }
 
+/*
+ * Write status register 1 byte
+ * Returns negative if error occurred.
+ */
+static int write_sr(struct m25p *flash, u8 val)
+{
+       flash->command[0] = OPCODE_WRSR;
+       flash->command[1] = val;
+
+       return spi_write(flash->spi, flash->command, 2);
+}
 
 /*
  * Set write enable latch with Write Enable command.
@@ -589,6 +601,16 @@ static int __devinit m25p_probe(struct spi_device *spi)
        mutex_init(&flash->lock);
        dev_set_drvdata(&spi->dev, flash);
 
+       /*
+        * Atmel serial flash tend to power up
+        * with the software protection bits set
+        */
+
+       if (info->jedec_id >> 16 == 0x1f) {
+               write_enable(flash);
+               write_sr(flash, 0);
+       }
+
        if (data && data->name)
                flash->mtd.name = data->name;
        else
index 9cff119a202483cd9cea74438c190b5a4fbb7171..6a9a24a80a6d206a573fea039a8a0274b389db4d 100644 (file)
@@ -5,8 +5,6 @@
  *     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.
- *
- *     $Id: ms02-nv.c,v 1.11 2005/11/14 13:41:47 macro Exp $
  */
 
 #include <linux/init.h>
index 8a6eef7cfee31d7bb0a8dc442b1309041f148468..04deafd3a7714c8ab7b0826eedf7db983d3b9e72 100644 (file)
@@ -9,8 +9,6 @@
  *     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.
- *
- *     $Id: ms02-nv.h,v 1.3 2003/08/19 09:25:36 dwmw2 Exp $
  */
 
 #include <linux/ioport.h>
index b35e4813a3a5e146f6725fb13d6d3be0f588bfe6..54e36bfc2c3b39caed333e3bbd5209ea704ba08c 100644 (file)
@@ -82,7 +82,7 @@
 
 
 struct dataflash {
-       u8                      command[4];
+       uint8_t                 command[4];
        char                    name[24];
 
        unsigned                partitioned:1;
@@ -150,7 +150,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
        struct spi_transfer     x = { .tx_dma = 0, };
        struct spi_message      msg;
        unsigned                blocksize = priv->page_size << 3;
-       u8                      *command;
+       uint8_t                 *command;
 
        DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n",
                        spi->dev.bus_id,
@@ -182,8 +182,8 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
                pageaddr = pageaddr << priv->page_offset;
 
                command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE;
-               command[1] = (u8)(pageaddr >> 16);
-               command[2] = (u8)(pageaddr >> 8);
+               command[1] = (uint8_t)(pageaddr >> 16);
+               command[2] = (uint8_t)(pageaddr >> 8);
                command[3] = 0;
 
                DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n",
@@ -234,7 +234,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct spi_transfer     x[2] = { { .tx_dma = 0, }, };
        struct spi_message      msg;
        unsigned int            addr;
-       u8                      *command;
+       uint8_t                 *command;
        int                     status;
 
        DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
@@ -274,9 +274,9 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
         * fewer "don't care" bytes.  Both buffers stay unchanged.
         */
        command[0] = OP_READ_CONTINUOUS;
-       command[1] = (u8)(addr >> 16);
-       command[2] = (u8)(addr >> 8);
-       command[3] = (u8)(addr >> 0);
+       command[1] = (uint8_t)(addr >> 16);
+       command[2] = (uint8_t)(addr >> 8);
+       command[3] = (uint8_t)(addr >> 0);
        /* plus 4 "don't care" bytes */
 
        status = spi_sync(priv->spi, &msg);
@@ -311,7 +311,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
        size_t                  remaining = len;
        u_char                  *writebuf = (u_char *) buf;
        int                     status = -EINVAL;
-       u8                      *command;
+       uint8_t                 *command;
 
        DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
                spi->dev.bus_id, (unsigned)to, (unsigned)(to + len));
@@ -487,7 +487,9 @@ add_dataflash(struct spi_device *spi, char *name,
        device->write = dataflash_write;
        device->priv = priv;
 
-       dev_info(&spi->dev, "%s (%d KBytes)\n", name, device->size/1024);
+       dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes, "
+               "erasesize %d bytes\n", name, device->size/1024,
+                pagesize, pagesize * 8);       /* 8 pages = 1 block */
        dev_set_drvdata(&spi->dev, priv);
 
        if (mtd_has_partitions()) {
@@ -521,7 +523,7 @@ add_dataflash(struct spi_device *spi, char *name,
  *
  *   Device      Density         ID code          #Pages PageSize  Offset
  *   AT45DB011B  1Mbit   (128K)  xx0011xx (0x0c)    512    264      9
- *   AT45DB021B  2Mbit   (256K)  xx0101xx (0x14)   1025    264      9
+ *   AT45DB021B  2Mbit   (256K)  xx0101xx (0x14)   1024    264      9
  *   AT45DB041B  4Mbit   (512K)  xx0111xx (0x1c)   2048    264      9
  *   AT45DB081B  8Mbit   (1M)    xx1001xx (0x24)   4096    264      9
  *   AT45DB0161B 16Mbit  (2M)    xx1011xx (0x2c)   4096    528     10
@@ -529,9 +531,114 @@ add_dataflash(struct spi_device *spi, char *name,
  *   AT45DB0642  64Mbit  (8M)    xx111xxx (0x3c)   8192   1056     11
  *   AT45DB1282  128Mbit (16M)   xx0100xx (0x10)  16384   1056     11
  */
+
+struct flash_info {
+       char            *name;
+
+       /* JEDEC id zero means "no ID" (most older chips); otherwise it has
+        * a high byte of zero plus three data bytes: the manufacturer id,
+        * then a two byte device id.
+        */
+       uint32_t        jedec_id;
+
+       /* The size listed here is what works with OPCODE_SE, which isn't
+        * necessarily called a "sector" by the vendor.
+        */
+       unsigned        nr_pages;
+       uint16_t        pagesize;
+       uint16_t        pageoffset;
+
+       uint16_t        flags;
+#define        SUP_POW2PS      0x02
+#define        IS_POW2PS       0x01
+};
+
+static struct flash_info __devinitdata dataflash_data [] = {
+
+       { "at45db011d",  0x1f2200, 512, 264, 9, SUP_POW2PS},
+       { "at45db011d",  0x1f2200, 512, 256, 8, SUP_POW2PS | IS_POW2PS},
+
+       { "at45db021d",  0x1f2300, 1024, 264, 9, SUP_POW2PS},
+       { "at45db021d",  0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS},
+
+       { "at45db041d",  0x1f2400, 2048, 264, 9, SUP_POW2PS},
+       { "at45db041d",  0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS},
+
+       { "at45db081d",  0x1f2500, 4096, 264, 9, SUP_POW2PS},
+       { "at45db081d",  0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS},
+
+       { "at45db161d",  0x1f2600, 4096, 528, 10, SUP_POW2PS},
+       { "at45db161d",  0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS},
+
+       { "at45db321c",  0x1f2700, 8192, 528, 10, },
+
+       { "at45db321d",  0x1f2701, 8192, 528, 10, SUP_POW2PS},
+       { "at45db321d",  0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS},
+
+       { "at45db641d",  0x1f2800, 8192, 1056, 11, SUP_POW2PS},
+       { "at45db641d",  0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS},
+};
+
+static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
+{
+       int                     tmp;
+       uint8_t                 code = OP_READ_ID;
+       uint8_t                 id[3];
+       uint32_t                jedec;
+       struct flash_info       *info;
+       int status;
+
+
+       /* JEDEC also defines an optional "extended device information"
+        * string for after vendor-specific data, after the three bytes
+        * we use here.  Supporting some chips might require using it.
+        */
+       tmp = spi_write_then_read(spi, &code, 1, id, 3);
+       if (tmp < 0) {
+               DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
+                       spi->dev.bus_id, tmp);
+               return NULL;
+       }
+       jedec = id[0];
+       jedec = jedec << 8;
+       jedec |= id[1];
+       jedec = jedec << 8;
+       jedec |= id[2];
+
+       for (tmp = 0, info = dataflash_data;
+                       tmp < ARRAY_SIZE(dataflash_data);
+                       tmp++, info++) {
+               if (info->jedec_id == jedec) {
+                       if (info->flags & SUP_POW2PS) {
+                               status = dataflash_status(spi);
+                               if (status & 0x1)
+                                       /* return power of 2 pagesize */
+                                       return ++info;
+                               else
+                                       return info;
+                       }
+               }
+       }
+       return NULL;
+}
+
 static int __devinit dataflash_probe(struct spi_device *spi)
 {
        int status;
+       struct flash_info       *info;
+
+       /*
+        * Try to detect dataflash by JEDEC ID.
+        * If it succeeds we know we have either a C or D part.
+        * D will support power of 2 pagesize option.
+        */
+
+       info = jedec_probe(spi);
+
+       if (info != NULL)
+               return add_dataflash(spi, info->name, info->nr_pages,
+                                info->pagesize, info->pageoffset);
+
 
        status = dataflash_status(spi);
        if (status <= 0 || status == 0xff) {
@@ -551,16 +658,16 @@ static int __devinit dataflash_probe(struct spi_device *spi)
                status = add_dataflash(spi, "AT45DB011B", 512, 264, 9);
                break;
        case 0x14:      /* 0 1 0 1 x x */
-               status = add_dataflash(spi, "AT45DB021B", 1025, 264, 9);
+               status = add_dataflash(spi, "AT45DB021B", 1024, 264, 9);
                break;
        case 0x1c:      /* 0 1 1 1 x x */
-               status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9);
+               status = add_dataflash(spi, "AT45DB041B", 2048, 264, 9);
                break;
        case 0x24:      /* 1 0 0 1 x x */
                status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9);
                break;
        case 0x2c:      /* 1 0 1 1 x x */
-               status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10);
+               status = add_dataflash(spi, "AT45DB161B", 4096, 528, 10);
                break;
        case 0x34:      /* 1 1 0 1 x x */
                status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10);
index 0399be178620ab67be22917e12595118fc3211f0..3aaca88847d39cec5421a072b13609bd25796cda 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * mtdram - a test mtd device
- * $Id: mtdram.c,v 1.37 2005/04/21 03:42:11 joern Exp $
  * Author: Alexander Larsson <alex@cendio.se>
  *
  * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
index c7987b1c5e01db083f237fa26b1c48d963a77a7d..088fbb7595b5adbb5fee1e240ecd605b4a53b51e 100644 (file)
@@ -1,6 +1,4 @@
 /**
- * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $
- *
  * Copyright (c) ????          Jochen Schäuble <psionic@psionic.de>
  * Copyright (c) 2003-2004     Joern Engel <joern@wh.fh-wedel.de>
  *
index bc99817490649572ced4f09e01ec2606c252a854..d38bca64bb1500c93c18641ebb5d29e3749e3c41 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: pmc551.c,v 1.32 2005/11/07 11:14:25 gleixner Exp $
- *
  * PMC551 PCI Mezzanine Ram Device
  *
  * Author:
index cb86db746f28c91f552462696b10d5c99f23c07d..a425d09f35a02fd9f3fbd2f0ff9df68019ba11e3 100644 (file)
@@ -1,7 +1,5 @@
 /*======================================================================
 
-  $Id: slram.c,v 1.36 2005/11/07 11:14:25 gleixner Exp $
-
   This driver provides a method to access memory not used by the kernel
   itself (i.e. if the kernel commandline mem=xxx is used). To actually
   use slram at least mtdblock or mtdchar is required (for block or
index 5c29872184e65b64c3f5938968aaeb29061601f6..f34f20c7891162f6d5fb7c101d3cac9c55da2e82 100644 (file)
@@ -1,5 +1,4 @@
 /* This version ported to the Linux-MTD system by dwmw2@infradead.org
- * $Id: ftl.c,v 1.59 2005/11/29 14:48:31 gleixner Exp $
  *
  * Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups
@@ -1078,8 +1077,6 @@ static struct mtd_blktrans_ops ftl_tr = {
 
 static int init_ftl(void)
 {
-       DEBUG(0, "$Id: ftl.c,v 1.59 2005/11/29 14:48:31 gleixner Exp $\n");
-
        return register_mtd_blktrans(&ftl_tr);
 }
 
index b0e396504e67cf98d2469afc881594706c706bd9..c4f9d3378b24c658f246d8777d47735050cfdffe 100644 (file)
@@ -7,8 +7,6 @@
  * (c) 1999 Machine Vision Holdings, Inc.
  * Author: David Woodhouse <dwmw2@infradead.org>
  *
- * $Id: inftlcore.c,v 1.19 2005/11/07 11:14:20 gleixner Exp $
- *
  * 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
@@ -953,9 +951,6 @@ static struct mtd_blktrans_ops inftl_tr = {
 
 static int __init init_inftl(void)
 {
-       printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, "
-               "inftlmount.c %s\n", inftlmountrev);
-
        return register_mtd_blktrans(&inftl_tr);
 }
 
index c551d2f0779c2e8c141c3a18c3f5bae05686dd84..9113628ed1ef3b54505780efcd7dc729537ea202 100644 (file)
@@ -8,8 +8,6 @@
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
  * Copyright (C) 2000 Netgem S.A.
  *
- * $Id: inftlmount.c,v 1.18 2005/11/07 11:14:20 gleixner Exp $
- *
  * 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
@@ -39,8 +37,6 @@
 #include <linux/mtd/inftl.h>
 #include <linux/mtd/compatmac.h>
 
-char inftlmountrev[]="$Revision: 1.18 $";
-
 /*
  * find_boot_record: Find the INFTL Media Header and its Spare copy which
  *     contains the various device information of the INFTL partition and
index d2fbc29645236d838dd046abb057b0f3a5f0d488..df8e00bba07b2726f71fbf02b6b1d27ff0cf396a 100644 (file)
@@ -1,5 +1,4 @@
 # drivers/mtd/maps/Kconfig
-# $Id: Kconfig,v 1.61 2005/11/07 11:14:26 gleixner Exp $
 
 menu "Mapping drivers for chip access"
        depends on MTD!=n
@@ -510,6 +509,17 @@ config MTD_PCMCIA_ANONYMOUS
 
          If unsure, say N.
 
+config MTD_BFIN_ASYNC
+       tristate "Blackfin BF533-STAMP Flash Chip Support"
+       depends on BFIN533_STAMP && MTD_CFI
+       select MTD_PARTITIONS
+       default y
+       help
+         Map driver which allows for simultaneous utilization of
+         ethernet and CFI parallel flash.
+
+         If compiled as a module, it will be called bfin-async-flash.
+
 config MTD_UCLINUX
        tristate "Generic uClinux RAM/ROM filesystem support"
        depends on MTD_PARTITIONS && !MMU
@@ -539,24 +549,6 @@ config MTD_DMV182
         help
           Map driver for Dy-4 SVME/DMV-182 board.
 
-config MTD_BAST
-       tristate "Map driver for Simtec BAST (EB2410ITX) or Thorcom VR1000"
-       depends on ARCH_BAST || MACH_VR1000
-       select MTD_PARTITIONS
-       select MTD_MAP_BANK_WIDTH_16
-       select MTD_JEDECPROBE
-       help
-         Map driver for NOR flash on the Simtec BAST (EB2410ITX), or the
-         Thorcom VR1000
-
-         Note, this driver *cannot* over-ride the WP link on the
-         board, or currently detect the state of the link.
-
-config MTD_BAST_MAXSIZE
-       int "Maximum size for BAST flash area (MiB)"
-       depends on MTD_BAST
-       default "4"
-
 config MTD_SHARP_SL
        tristate "ROM mapped on Sharp SL Series"
        depends on ARCH_PXA
index c6ce8673dab293e755887c903cd4eb6738f4625a..6cda6df973e5d11c187533e48534ac5ff60c6038 100644 (file)
@@ -1,7 +1,6 @@
 #
 # linux/drivers/maps/Makefile
 #
-# $Id: Makefile.common,v 1.34 2005/11/07 11:14:26 gleixner Exp $
 
 ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y)
 obj-$(CONFIG_MTD)              += map_funcs.o
@@ -10,7 +9,6 @@ endif
 # Chip mappings
 obj-$(CONFIG_MTD_CDB89712)     += cdb89712.o
 obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
-obj-$(CONFIG_MTD_BAST)         += bast-flash.o
 obj-$(CONFIG_MTD_CFI_FLAGADM)  += cfi_flagadm.o
 obj-$(CONFIG_MTD_DC21285)      += dc21285.o
 obj-$(CONFIG_MTD_DILNETPC)     += dilnetpc.o
@@ -66,3 +64,4 @@ obj-$(CONFIG_MTD_SHARP_SL)    += sharpsl-flash.o
 obj-$(CONFIG_MTD_PLATRAM)      += plat-ram.o
 obj-$(CONFIG_MTD_OMAP_NOR)     += omap_nor.o
 obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o
+obj-$(CONFIG_MTD_BFIN_ASYNC)   += bfin-async-flash.o
index 728aed6ad722e276e1642da0a7951b3bd61363f2..948b86f35ef4a2e2068f12878d21f6653f4e9868 100644 (file)
@@ -2,7 +2,6 @@
  * amd76xrom.c
  *
  * Normal mappings of chips in physical memory
- * $Id: amd76xrom.c,v 1.21 2005/11/07 11:14:26 gleixner Exp $
  */
 
 #include <linux/module.h>
index 7ed3424dd959bb2aa3ce42af93a4dc25ad74f25f..cf32267263df815ed07ce6dbb41bd8f96c8e81aa 100644 (file)
@@ -2,8 +2,6 @@
  * NV-RAM memory access on autcpu12
  * (C) 2002 Thomas Gleixner (gleixner@autronix.de)
  *
- * $Id: autcpu12-nvram.c,v 1.9 2005/11/07 11:14:26 gleixner Exp $
- *
  * 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
diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
deleted file mode 100644 (file)
index 1f49206..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-/* linux/drivers/mtd/maps/bast-flash.c
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Simtec Bast (EB2410ITX) NOR MTD Mapping driver
- *
- * Changelog:
- *     20-Sep-2004  BJD  Initial version
- *     17-Jan-2005  BJD  Add whole device if no partitions found
- *
- * $Id: bast-flash.c,v 1.5 2005/11/07 11:14:26 gleixner Exp $
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-#include <asm/mach/flash.h>
-
-#include <asm/arch/map.h>
-#include <asm/arch/bast-map.h>
-#include <asm/arch/bast-cpld.h>
-
-#ifdef CONFIG_MTD_BAST_MAXSIZE
-#define AREA_MAXSIZE (CONFIG_MTD_BAST_MAXSIZE * SZ_1M)
-#else
-#define AREA_MAXSIZE (32 * SZ_1M)
-#endif
-
-#define PFX "bast-flash: "
-
-struct bast_flash_info {
-       struct mtd_info         *mtd;
-       struct map_info          map;
-       struct mtd_partition    *partitions;
-       struct resource         *area;
-};
-
-static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
-
-static void bast_flash_setrw(int to)
-{
-       unsigned int val;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       val = __raw_readb(BAST_VA_CTRL3);
-
-       if (to)
-               val |= BAST_CPLD_CTRL3_ROMWEN;
-       else
-               val &= ~BAST_CPLD_CTRL3_ROMWEN;
-
-       pr_debug("new cpld ctrl3=%02x\n", val);
-
-       __raw_writeb(val, BAST_VA_CTRL3);
-       local_irq_restore(flags);
-}
-
-static int bast_flash_remove(struct platform_device *pdev)
-{
-       struct bast_flash_info *info = platform_get_drvdata(pdev);
-
-       platform_set_drvdata(pdev, NULL);
-
-       if (info == NULL)
-               return 0;
-
-       if (info->map.virt != NULL)
-               iounmap(info->map.virt);
-
-       if (info->mtd) {
-               del_mtd_partitions(info->mtd);
-               map_destroy(info->mtd);
-       }
-
-       kfree(info->partitions);
-
-       if (info->area) {
-               release_resource(info->area);
-               kfree(info->area);
-       }
-
-       kfree(info);
-
-       return 0;
-}
-
-static int bast_flash_probe(struct platform_device *pdev)
-{
-       struct bast_flash_info *info;
-       struct resource *res;
-       int err = 0;
-
-       info = kmalloc(sizeof(*info), GFP_KERNEL);
-       if (info == NULL) {
-               printk(KERN_ERR PFX "no memory for flash info\n");
-               err = -ENOMEM;
-               goto exit_error;
-       }
-
-       memzero(info, sizeof(*info));
-       platform_set_drvdata(pdev, info);
-
-       res = pdev->resource;  /* assume that the flash has one resource */
-
-       info->map.phys = res->start;
-       info->map.size = res->end - res->start + 1;
-       info->map.name = pdev->dev.bus_id;
-       info->map.bankwidth = 2;
-
-       if (info->map.size > AREA_MAXSIZE)
-               info->map.size = AREA_MAXSIZE;
-
-       pr_debug("%s: area %08lx, size %ld\n", __func__,
-                info->map.phys, info->map.size);
-
-       info->area = request_mem_region(res->start, info->map.size,
-                                       pdev->name);
-       if (info->area == NULL) {
-               printk(KERN_ERR PFX "cannot reserve flash memory region\n");
-               err = -ENOENT;
-               goto exit_error;
-       }
-
-       info->map.virt = ioremap(res->start, info->map.size);
-       pr_debug("%s: virt at %08x\n", __func__, (int)info->map.virt);
-
-       if (info->map.virt == 0) {
-               printk(KERN_ERR PFX "failed to ioremap() region\n");
-               err = -EIO;
-               goto exit_error;
-       }
-
-       simple_map_init(&info->map);
-
-       /* enable the write to the flash area */
-
-       bast_flash_setrw(1);
-
-       /* probe for the device(s) */
-
-       info->mtd = do_map_probe("jedec_probe", &info->map);
-       if (info->mtd == NULL)
-               info->mtd = do_map_probe("cfi_probe", &info->map);
-
-       if (info->mtd == NULL) {
-               printk(KERN_ERR PFX "map_probe() failed\n");
-               err = -ENXIO;
-               goto exit_error;
-       }
-
-       /* mark ourselves as the owner */
-       info->mtd->owner = THIS_MODULE;
-
-       err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
-       if (err > 0) {
-               err = add_mtd_partitions(info->mtd, info->partitions, err);
-               if (err)
-                       printk(KERN_ERR PFX "cannot add/parse partitions\n");
-       } else {
-               err = add_mtd_device(info->mtd);
-       }
-
-       if (err == 0)
-               return 0;
-
-       /* fall through to exit error */
-
- exit_error:
-       bast_flash_remove(pdev);
-       return err;
-}
-
-static struct platform_driver bast_flash_driver = {
-       .probe          = bast_flash_probe,
-       .remove         = bast_flash_remove,
-       .driver         = {
-               .name   = "bast-nor",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init bast_flash_init(void)
-{
-       printk("BAST NOR-Flash Driver, (c) 2004 Simtec Electronics\n");
-       return platform_driver_register(&bast_flash_driver);
-}
-
-static void __exit bast_flash_exit(void)
-{
-       platform_driver_unregister(&bast_flash_driver);
-}
-
-module_init(bast_flash_init);
-module_exit(bast_flash_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("BAST MTD Map driver");
-MODULE_ALIAS("platform:bast-nor");
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
new file mode 100644 (file)
index 0000000..6fec86a
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * drivers/mtd/maps/bfin-async-flash.c
+ *
+ * Handle the case where flash memory and ethernet mac/phy are
+ * mapped onto the same async bank.  The BF533-STAMP does this
+ * for example.  All board-specific configuration goes in your
+ * board resources file.
+ *
+ * Copyright 2000 Nicolas Pitre <nico@cam.org>
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include <asm/blackfin.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <asm/unaligned.h>
+
+#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
+
+#define DRIVER_NAME "bfin-async-flash"
+
+struct async_state {
+       struct mtd_info *mtd;
+       struct map_info map;
+       int enet_flash_pin;
+       uint32_t flash_ambctl0, flash_ambctl1;
+       uint32_t save_ambctl0, save_ambctl1;
+       unsigned long irq_flags;
+};
+
+static void switch_to_flash(struct async_state *state)
+{
+       local_irq_save(state->irq_flags);
+
+       gpio_set_value(state->enet_flash_pin, 0);
+
+       state->save_ambctl0 = bfin_read_EBIU_AMBCTL0();
+       state->save_ambctl1 = bfin_read_EBIU_AMBCTL1();
+       bfin_write_EBIU_AMBCTL0(state->flash_ambctl0);
+       bfin_write_EBIU_AMBCTL1(state->flash_ambctl1);
+       SSYNC();
+}
+
+static void switch_back(struct async_state *state)
+{
+       bfin_write_EBIU_AMBCTL0(state->save_ambctl0);
+       bfin_write_EBIU_AMBCTL1(state->save_ambctl1);
+       SSYNC();
+
+       gpio_set_value(state->enet_flash_pin, 1);
+
+       local_irq_restore(state->irq_flags);
+}
+
+static map_word bfin_read(struct map_info *map, unsigned long ofs)
+{
+       struct async_state *state = (struct async_state *)map->map_priv_1;
+       uint16_t word;
+       map_word test;
+
+       switch_to_flash(state);
+
+       word = readw(map->virt + ofs);
+
+       switch_back(state);
+
+       test.x[0] = word;
+       return test;
+}
+
+static void bfin_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
+{
+       struct async_state *state = (struct async_state *)map->map_priv_1;
+
+       switch_to_flash(state);
+
+       memcpy(to, map->virt + from, len);
+
+       switch_back(state);
+}
+
+static void bfin_write(struct map_info *map, map_word d1, unsigned long ofs)
+{
+       struct async_state *state = (struct async_state *)map->map_priv_1;
+       uint16_t d;
+
+       d = d1.x[0];
+
+       switch_to_flash(state);
+
+       writew(d, map->virt + ofs);
+       SSYNC();
+
+       switch_back(state);
+}
+
+static void bfin_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
+{
+       struct async_state *state = (struct async_state *)map->map_priv_1;
+
+       switch_to_flash(state);
+
+       memcpy(map->virt + to, from, len);
+       SSYNC();
+
+       switch_back(state);
+}
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+#endif
+
+static int __devinit bfin_flash_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct physmap_flash_data *pdata = pdev->dev.platform_data;
+       struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       struct resource *flash_ambctl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       struct async_state *state;
+
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return -ENOMEM;
+
+       state->map.name       = DRIVER_NAME;
+       state->map.read       = bfin_read;
+       state->map.copy_from  = bfin_copy_from;
+       state->map.write      = bfin_write;
+       state->map.copy_to    = bfin_copy_to;
+       state->map.bankwidth  = pdata->width;
+       state->map.size       = memory->end - memory->start + 1;
+       state->map.virt       = (void __iomem *)memory->start;
+       state->map.phys       = memory->start;
+       state->map.map_priv_1 = (unsigned long)state;
+       state->enet_flash_pin = platform_get_irq(pdev, 0);
+       state->flash_ambctl0  = flash_ambctl->start;
+       state->flash_ambctl1  = flash_ambctl->end;
+
+       if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) {
+               pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin);
+               return -EBUSY;
+       }
+       gpio_direction_output(state->enet_flash_pin, 1);
+
+       pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
+       state->mtd = do_map_probe(memory->name, &state->map);
+       if (!state->mtd)
+               return -ENXIO;
+
+#ifdef CONFIG_MTD_PARTITIONS
+       ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
+       if (ret > 0) {
+               pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
+               add_mtd_partitions(state->mtd, pdata->parts, ret);
+
+       } else if (pdata->nr_parts) {
+               pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
+               add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts);
+
+       } else
+#endif
+       {
+               pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
+               add_mtd_device(state->mtd);
+       }
+
+       platform_set_drvdata(pdev, state);
+
+       return 0;
+}
+
+static int __devexit bfin_flash_remove(struct platform_device *pdev)
+{
+       struct async_state *state = platform_get_drvdata(pdev);
+       gpio_free(state->enet_flash_pin);
+#ifdef CONFIG_MTD_PARTITIONS
+       del_mtd_partitions(state->mtd);
+#endif
+       map_destroy(state->mtd);
+       kfree(state);
+       return 0;
+}
+
+static struct platform_driver bfin_flash_driver = {
+       .probe          = bfin_flash_probe,
+       .remove         = __devexit_p(bfin_flash_remove),
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init bfin_flash_init(void)
+{
+       return platform_driver_register(&bfin_flash_driver);
+}
+module_init(bfin_flash_init);
+
+static void __exit bfin_flash_exit(void)
+{
+       platform_driver_unregister(&bfin_flash_driver);
+}
+module_exit(bfin_flash_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MTD map driver for Blackfins with flash/ethernet on same async bank");
index 9f17bb6c5a9d388714c8822ea412230d918b6b38..cb507da0a87d74e62dea447b08a2ee64cc1faade 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * Flash on Cirrus CDB89712
  *
- * $Id: cdb89712.c,v 1.11 2005/11/07 11:14:26 gleixner Exp $
  */
 
 #include <linux/module.h>
index 629e6e2641a84c7ca5e2d0ecd53b56566008362b..6464d487eb1ade983c336ab65edbe7312c0de4bc 100644 (file)
@@ -11,7 +11,6 @@
  *
  * (C) 2000 Nicolas Pitre <nico@cam.org>
  *
- * $Id: ceiva.c,v 1.11 2004/09/16 23:27:12 gleixner Exp $
  */
 
 #include <linux/module.h>
index 65e5ee552010be7a4c147a34f806ac3d9a5e46d0..0ecc3f6d735bfb78a2b8ad467dc2d69cb16b50ac 100644 (file)
@@ -1,8 +1,6 @@
 /*
  *  Copyright Â© 2001 Flaga hf. Medical Devices, Kári Davíðsson <kd@flaga.is>
  *
- *  $Id: cfi_flagadm.c,v 1.15 2005/11/07 11:14:26 gleixner Exp $
- *
  *  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
index 92a9c7fac99328adbb0208cc69503685b84882cc..e115667bf1d04083b50d5ea18df34d55f34af7a4 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: dbox2-flash.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $
- *
  * D-Box 2 flash driver
  */
 
index b32bb9347d713045bf9db02cdc08470e70b3165f..3aa018c092f893369ac7d4ff9b4073efa7af861f 100644 (file)
@@ -4,8 +4,6 @@
  * (C) 2000  Nicolas Pitre <nico@cam.org>
  *
  * This code is GPL
- *
- * $Id: dc21285.c,v 1.24 2005/11/07 11:14:26 gleixner Exp $
  */
 #include <linux/module.h>
 #include <linux/types.h>
index 1c3b34ad732511f56c5138a0ac92d9fad2b95263..0713e3a5a22cb4b4bf1baa1db4c5d57d01259e13 100644 (file)
@@ -14,8 +14,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  *
- * $Id: dilnetpc.c,v 1.20 2005/11/07 11:14:26 gleixner Exp $
- *
  * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems
  * featuring the AMD Elan SC410 processor. There are two variants of this
  * board: DNP/1486 and ADNP/1486. The DNP version has 2 megs of flash
index e0558b0b2fe65946ecfd00b3a05f57f79624633d..d171674eb2ed1ec17ee73a0c63a4bdb034e576d7 100644 (file)
@@ -4,8 +4,6 @@
  *
  * Flash map driver for the Dy4 SVME182 board
  *
- * $Id: dmv182.c,v 1.6 2005/11/07 11:14:26 gleixner Exp $
- *
  * Copyright 2003-2004, TimeSys Corporation
  *
  * Based on the SVME181 flash map, by Tom Nelson, Dot4, Inc. for TimeSys Corp.
index 1488bb92f26fab6ad19e46515263332311997279..d92b7c70d3ed58677d5e7971f21c657a875a8b74 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: ebony.c,v 1.16 2005/11/07 11:14:26 gleixner Exp $
- *
  * Mapping for Ebony user flash
  *
  * Matt Porter <mporter@kernel.crashing.org>
index 1c5b97c8968540703130e7e6817f5c4a32e71d1f..9433738c1664178071690e484c4f346886ee4f0e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: edb7312.c,v 1.14 2005/11/07 11:14:27 gleixner Exp $
- *
  * Handle mapping of the NOR flash on Cogent EDB7312 boards
  *
  * Copyright 2002 SYSGO Real-Time Solutions GmbH
index 7c50c271651c768a73307ee04cbc5eb3f11b4460..a8e3fde4cbd557f9feb18f61d8b114b5a267fb56 100644 (file)
@@ -1,6 +1,5 @@
 /* fortunet.c memory map
  *
- * $Id: fortunet.c,v 1.11 2005/11/07 11:14:27 gleixner Exp $
  */
 
 #include <linux/module.h>
index 6dde3182d64a6966d1b6247bc52dd5ee25c8c78b..ef891547446270ade69927c00627d39be3845810 100644 (file)
@@ -2,8 +2,6 @@
  * Flash memory access on Hynix GMS30C7201/HMS30C7202 based
  * evaluation boards
  *
- * $Id: h720x-flash.c,v 1.12 2005/11/07 11:14:27 gleixner Exp $
- *
  * (C) 2002 Jungjun Kim <jungjun.kim@hynix.com>
  *     2003 Thomas Gleixner <tglx@linutronix.de>
  */
index 2c884c49e84a5cd5f0bb1a50e8fc285bb408ceb3..aeb6c916e23f8f6925dda4152055c8417241b78e 100644 (file)
@@ -2,7 +2,6 @@
  * ichxrom.c
  *
  * Normal mappings of chips in physical memory
- * $Id: ichxrom.c,v 1.19 2005/11/07 11:14:27 gleixner Exp $
  */
 
 #include <linux/module.h>
index a0b4dc7155dc66ffc6fd02a5582f860f0381794b..2682ab51a36786732fdd08b83b8cde83f331ad62 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: impa7.c,v 1.14 2005/11/07 11:14:27 gleixner Exp $
- *
  * Handle mapping of the NOR flash on implementa A7 boards
  *
  * Copyright 2002 SYSGO Real-Time Solutions GmbH
index 325c8880c4379393b4266c0849ee0bfc85488344..ee361aaadb1e19a7620de24f2a05aad9fbb48edb 100644 (file)
@@ -22,8 +22,6 @@
    This is access code for flashes using ARM's flash partitioning
    standards.
 
-   $Id: integrator-flash.c,v 1.20 2005/11/07 11:14:27 gleixner Exp $
-
 ======================================================================*/
 
 #include <linux/module.h>
index f27c132794c3efa365e6408b7fa40196ec661ecb..a806119797e0feeb3fd2969199a334daa6aa9c21 100644 (file)
@@ -4,8 +4,6 @@
  * (C) 2000 Nicolas Pitre <nico@cam.org>
  * (C) 2002 Hewlett-Packard Company <jamey.hicks@hp.com>
  * (C) 2003 Christian Pellegrin <chri@ascensit.com>, <chri@infis.univ.ts.it>: concatenation of multiple flashes
- *
- * $Id: ipaq-flash.c,v 1.5 2005/11/07 11:14:27 gleixner Exp $
  */
 
 #include <linux/module.h>
index c8396b8574c4624debf97d0846ab0a88dd07867f..c2264792a20b2b77a2a3ef5a49ea2fcbc8184f2a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: ixp2000.c,v 1.9 2005/11/07 11:14:27 gleixner Exp $
- *
  * drivers/mtd/maps/ixp2000.c
  *
  * Mapping for the Intel XScale IXP2000 based systems
index 01f19a4714b5b7383506d929208b0637a6cc7c0f..9c7a5fbd4e512e93c58de1f08ee2d2b388ca8af7 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: ixp4xx.c,v 1.13 2005/11/16 16:23:21 dvrabel Exp $
- *
  * drivers/mtd/maps/ixp4xx.c
  *
  * MTD Map file for IXP4XX based systems. Please do not make per-board
index 67620adf48114713366d24a8e0175b71e7e65501..9e054503c4cf2920e23c7fded7d2bd39741c4166 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: l440gx.c,v 1.18 2005/11/07 11:14:27 gleixner Exp $
- *
  * BIOS Flash chip on Intel 440GX board.
  *
  * Bugs this currently does not work under linuxBIOS.
index 9105e6ca0aa61de3be27f9063464e1c3372a9a25..3f268370eeca150a7029b7a28c9868d5170f3a3b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: map_funcs.c,v 1.10 2005/06/06 23:04:36 tpoynor Exp $
- *
  * Out-of-line map I/O functions for simple maps when CONFIG_COMPLEX_MAPPINGS
  * is enabled.
  */
index 06b1187278468bb4e0392b8a70edc1b32842c3f3..706f67394b073cb97f8e5894bd88129de4f858cd 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: mbx860.c,v 1.9 2005/11/07 11:14:27 gleixner Exp $
- *
  * Handle mapping of the flash on MBX860 boards
  *
  * Author:     Anton Todorov
index 95dcab2146ad821c90fa29df1784d62076b7d3ee..c0cb319b2b70e26f38f6c9133263098ff245bad0 100644 (file)
@@ -3,8 +3,6 @@
  * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com)
  *     based on sc520cdp.c by Sysgo Real-Time Solutions GmbH
  *
- * $Id: netsc520.c,v 1.14 2005/11/07 11:14:27 gleixner Exp $
- *
  * 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
index 0c9b305a72e0de104e8ad53514f4c36ceebdd2ee..965e6c6d6ab022237d523c224eb47b13830d67c3 100644 (file)
@@ -5,8 +5,6 @@
  *
  *      (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com)
  *      (C) Copyright 2001-2002, SnapGear (www.snapgear.com)
- *
- *     $Id: nettel.c,v 1.12 2005/11/29 14:30:00 gleixner Exp $
  */
 
 /****************************************************************************/
index a6642db3d325e19e6418ce0675fdd0f596e1f522..43e04c1d22a9dd74140f51e3f42092b7b950d0d4 100644 (file)
@@ -1,4 +1,3 @@
-// $Id: octagon-5066.c,v 1.28 2005/11/07 11:14:27 gleixner Exp $
 /* ######################################################################
 
    Octagon 5066 MTD Driver.
index e6e391efbeb6925c30398e5eb8bc2879337aee9b..0a60ebbc217591af7c00511ad3096f8d2fa9656d 100644 (file)
@@ -4,8 +4,6 @@
  * jzhang@ti.com (C) 2003 Texas Instruments.
  *
  *  (C) 2002 MontVista Software, Inc.
- *
- * $Id: omap-toto-flash.c,v 1.5 2005/11/07 11:14:27 gleixner Exp $
  */
 
 #include <linux/module.h>
index d2ab1bae9c346fbf2168ff59199222f226e6f2cb..5c6a25c90380aa70ab2afb4b3f34860adf76d43f 100644 (file)
@@ -7,8 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- *  $Id: pci.c,v 1.14 2005/11/17 08:20:27 dwmw2 Exp $
- *
  * Generic PCI memory map driver.  We support the following boards:
  *  - Intel IQ80310 ATU.
  *  - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001
index 0cc31675aeb909c472479c41a14abc970ec9217e..90924fb00481eda9289716337883155326bd8130 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: pcmciamtd.c,v 1.55 2005/11/07 11:14:28 gleixner Exp $
- *
  * pcmciamtd.c - MTD driver for PCMCIA flash memory cards
  *
  * Author: Simon Evans <spse@secret.org.uk>
@@ -48,7 +46,6 @@ static const int debug = 0;
 
 
 #define DRIVER_DESC    "PCMCIA Flash memory card driver"
-#define DRIVER_VERSION "$Revision: 1.55 $"
 
 /* Size of the PCMCIA address space: 26 bits = 64 MB */
 #define MAX_PCMCIA_ADDR        0x4000000
@@ -785,7 +782,7 @@ static struct pcmcia_driver pcmciamtd_driver = {
 
 static int __init init_pcmciamtd(void)
 {
-       info(DRIVER_DESC " " DRIVER_VERSION);
+       info(DRIVER_DESC);
 
        if(bankwidth && bankwidth != 1 && bankwidth != 2) {
                info("bad bankwidth (%d), using default", bankwidth);
index 183255fcfdcbd288dc38e697b6a6ed8ff3be3321..42d844f8f6bfef79bdfef42ed48b33368ac4ecd0 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: physmap.c,v 1.39 2005/11/29 14:49:36 gleixner Exp $
- *
  * Normal mappings of chips in physical memory
  *
  * Copyright (C) 2003 MontaVista Software Inc.
@@ -203,7 +201,19 @@ static int physmap_flash_suspend(struct platform_device *dev, pm_message_t state
        int i;
 
        for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
-               ret |= info->mtd[i]->suspend(info->mtd[i]);
+               if (info->mtd[i]->suspend) {
+                       ret = info->mtd[i]->suspend(info->mtd[i]);
+                       if (ret)
+                               goto fail;
+               }
+
+       return 0;
+fail:
+       for (--i; i >= 0; --i)
+               if (info->mtd[i]->suspend) {
+                       BUG_ON(!info->mtd[i]->resume);
+                       info->mtd[i]->resume(info->mtd[i]);
+               }
 
        return ret;
 }
@@ -214,7 +224,8 @@ static int physmap_flash_resume(struct platform_device *dev)
        int i;
 
        for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
-               info->mtd[i]->resume(info->mtd[i]);
+               if (info->mtd[i]->resume)
+                       info->mtd[i]->resume(info->mtd[i]);
 
        return 0;
 }
@@ -225,8 +236,9 @@ static void physmap_flash_shutdown(struct platform_device *dev)
        int i;
 
        for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
-               if (info->mtd[i]->suspend(info->mtd[i]) == 0)
-                       info->mtd[i]->resume(info->mtd[i]);
+               if (info->mtd[i]->suspend && info->mtd[i]->resume)
+                       if (info->mtd[i]->suspend(info->mtd[i]) == 0)
+                               info->mtd[i]->resume(info->mtd[i]);
 }
 #else
 #define physmap_flash_suspend NULL
index 3eb2643b232875cea389ed0cfb45a55147eb898b..e7dd9c8a965e2fc86d32b98eaa060657d0819724 100644 (file)
@@ -6,8 +6,6 @@
  *
  * Generic platfrom device based RAM map
  *
- * $Id: plat-ram.c,v 1.7 2005/11/07 11:14:28 gleixner Exp $
- *
  * 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
index 4d858b3d5f826f368872d5317ecc4e9388c91a7c..de002eb1a7fe3a943753b2622a2dd64f7cea909a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: redwood.c,v 1.11 2005/11/07 11:14:28 gleixner Exp $
- *
  * drivers/mtd/maps/redwood.c
  *
  * FLASH map for the IBM Redwood 4/5/6 boards.
index 809a0c8e7aaf7c0fd2a1b5d8d12536f6aadd7eb1..14d90edb443076d3759e98f66464b70ff22ad172 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: rpxlite.c,v 1.22 2004/11/04 13:24:15 gleixner Exp $
- *
  * Handle mapping of the flash on the RPX Lite and CLLF boards
  */
 
index c7d5a52a2d559e997c62ba629bdf38f28f72e2c1..e177a43dfff0e7b07ec74f7752550ce136c4d6d1 100644 (file)
@@ -2,8 +2,6 @@
  * Flash memory access on SA11x0 based devices
  *
  * (C) 2000 Nicolas Pitre <nico@cam.org>
- *
- * $Id: sa1100-flash.c,v 1.51 2005/11/07 11:14:28 gleixner Exp $
  */
 #include <linux/module.h>
 #include <linux/types.h>
index b8c1331b7a04e18d6cafda2fcb86d03ea0925681..6e1e99cd2b59c443715450c03b7f446261ac1776 100644 (file)
@@ -4,9 +4,6 @@
  * Carolyn Smith, Tektronix, Inc.
  *
  * This code is GPLed
- *
- * $Id: sbc8240.c,v 1.5 2005/11/07 11:14:28 gleixner Exp $
- *
  */
 
 /*
index 7cc4041d096d6eaf5fb9e351760a95e1f1d2382c..1b1c0b7e11ef410e64921cdb34db049d86968183 100644 (file)
@@ -17,8 +17,6 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
-   $Id: sbc_gxx.c,v 1.35 2005/11/07 11:14:28 gleixner Exp $
-
 The SBC-MediaGX / SBC-GXx has up to 16 MiB of
 Intel StrataFlash (28F320/28F640) in x8 mode.
 
index 4045e372b90db10b53baaae4d15d045a881e90f9..85c1e56309ec571a326066273be94099a425f7cb 100644 (file)
@@ -16,8 +16,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  *
- * $Id: sc520cdp.c,v 1.23 2005/11/17 08:20:27 dwmw2 Exp $
- *
  *
  * The SC520CDP is an evaluation board for the Elan SC520 processor available
  * from AMD. It has two banks of 32-bit Flash ROM, each 8 Megabytes in size,
index 0fc5584324e3d38488dd62627867787c2201e5d1..21169e6d646c0df26318fdd22176915e515fa244 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * MTD map driver for BIOS Flash on Intel SCB2 boards
- * $Id: scb2_flash.c,v 1.12 2005/03/18 14:04:35 gleixner Exp $
  * Copyright (C) 2002 Sun Microsystems, Inc.
  * Tim Hockin <thockin@sun.com>
  *
index 5e2bce22f37ca6146ee46c7abf3eca84628ff2f0..b5391ebb736e1bac6b4175d7e897670dc38e7ea9 100644 (file)
@@ -2,8 +2,6 @@
 
    Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
 
-   $Id: scx200_docflash.c,v 1.12 2005/11/07 11:14:28 gleixner Exp $
-
    National Semiconductor SCx200 flash mapped with DOCCS
 */
 
index 917dc778f24e12f2c758473c38266804aa517d79..026eab028189a170ebab7c7d013a6da86b4981d3 100644 (file)
@@ -4,8 +4,6 @@
  * Copyright (C) 2001 Lineo Japan, Inc.
  * Copyright (C) 2002  SHARP
  *
- * $Id: sharpsl-flash.c,v 1.7 2005/11/07 11:14:28 gleixner Exp $
- *
  * based on rpxlite.c,v 1.15 2001/10/02 15:05:14 dwmw2 Exp
  *          Handle mapping of the flash on the RPX Lite and CLLF boards
  *
index d76ceef453ce66169c6b02754ed19f26aa05db59..0eb41d9c67867fb90280ba0570408e1536b4760e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: solutionengine.c,v 1.15 2005/11/07 11:14:28 gleixner Exp $
- *
  * Flash and EPROM on Hitachi Solution Engine and similar boards.
  *
  * (C) 2001 Red Hat, Inc.
index 001af7f7dddad5273164cac453f4ea3367386f91..0d7c88396c888a3d367d84f7b3e654b77124429a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sun_uflash.c,v 1.13 2005/11/07 11:14:28 gleixner Exp $
+/*
  *
  * sun_uflash - Driver implementation for user-programmable flash
  * present on many Sun Microsystems SME boardsets.
index 5217340573140f9f7994e88b4ee0d93e74e013fe..a5d3d8531faa1aa22c1fbf8a4d442c4ef7402862 100644 (file)
@@ -2,8 +2,6 @@
  * Handle mapping of the flash memory access routines
  * on TQM8xxL based devices.
  *
- * $Id: tqm8xxl.c,v 1.15 2005/11/07 11:14:28 gleixner Exp $
- *
  * based on rpxlite.c
  *
  * Copyright(C) 2001 Kirk Lee <kirk@hpc.ee.ntu.edu.tw>
index b47270e850bc78754ed876e2704f9355e0d87fec..e2147bf11c88948036c6d4d696b38f7952e62f01 100644 (file)
@@ -22,8 +22,6 @@
  * - Drive A and B use the resident flash disk (RFD) flash translation layer.
  * - If you have created your own jffs file system and the bios overwrites
  *   it during boot, try disabling Drive A: and B: in the boot order.
- *
- * $Id: ts5500_flash.c,v 1.5 2005/11/07 11:14:28 gleixner Exp $
  */
 
 #include <linux/init.h>
index 0f915ac3102e21dba8a8b9fc5c9a5624f20ff183..77a8bfc025770b657ae404b814d7e718ea3da005 100644 (file)
@@ -2,7 +2,6 @@
  * tsunami_flash.c
  *
  * flash chip on alpha ds10...
- * $Id: tsunami_flash.c,v 1.10 2005/11/07 11:14:29 gleixner Exp $
  */
 #include <asm/io.h>
 #include <asm/core_tsunami.h>
index c42f4b83f686dc0235f699b75a2dd457f4f53218..0dc645f8152f21c90031d86443eb604f1af97957 100644 (file)
@@ -4,8 +4,6 @@
  *     uclinux.c -- generic memory mapped MTD driver for uclinux
  *
  *     (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
- *
- *     $Id: uclinux.c,v 1.12 2005/11/07 11:14:29 gleixner Exp $
  */
 
 /****************************************************************************/
@@ -15,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
+#include <linux/mm.h>
 #include <linux/major.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
index b3e48739543551e6f506fcb362739262073e22e3..5a0c9a353b0fa63021834321afa2eab691c6864f 100644 (file)
@@ -1,4 +1,3 @@
-// $Id: vmax301.c,v 1.32 2005/11/07 11:14:29 gleixner Exp $
 /* ######################################################################
 
    Tempustech VMAX SBC301 MTD Driver.
index ca932122fb6409e213c9a0f551bf7f01c0bac497..e243476c8171e114ac0f9b254f7f0b932e6e3e5c 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: walnut.c,v 1.3 2005/11/07 11:14:29 gleixner Exp $
- *
  * Mapping for Walnut flash
  * (used ebony.c as a "framework")
  *
index ac5b8105b6efe69ca210571ffc2b098a7997b762..413b0cf9bbd2f6e3e234f661cd1f16c80e6f9a7e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: wr_sbc82xx_flash.c,v 1.8 2005/11/07 11:14:29 gleixner Exp $
- *
  * Map for flash chips on Wind River PowerQUICC II SBC82xx board.
  *
  * Copyright (C) 2004 Red Hat, Inc.
index 839eed8430a2c77aaf1643937de83ae99501fe6b..9ff007c4962c9f3c58868385729a915ba6b28222 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: mtd_blkdevs.c,v 1.27 2005/11/07 11:14:20 gleixner Exp $
- *
  * (C) 2003 David Woodhouse <dwmw2@infradead.org>
  *
  * Interface to Linux 2.5 block layer for MTD 'translation layers'.
@@ -212,7 +210,7 @@ static struct block_device_operations mtd_blktrans_ops = {
 int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 {
        struct mtd_blktrans_ops *tr = new->tr;
-       struct list_head *this;
+       struct mtd_blktrans_dev *d;
        int last_devnum = -1;
        struct gendisk *gd;
 
@@ -221,8 +219,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
                BUG();
        }
 
-       list_for_each(this, &tr->devs) {
-               struct mtd_blktrans_dev *d = list_entry(this, struct mtd_blktrans_dev, list);
+       list_for_each_entry(d, &tr->devs, list) {
                if (new->devnum == -1) {
                        /* Use first free number */
                        if (d->devnum != last_devnum+1) {
@@ -309,33 +306,24 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
 
 static void blktrans_notify_remove(struct mtd_info *mtd)
 {
-       struct list_head *this, *this2, *next;
-
-       list_for_each(this, &blktrans_majors) {
-               struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
-
-               list_for_each_safe(this2, next, &tr->devs) {
-                       struct mtd_blktrans_dev *dev = list_entry(this2, struct mtd_blktrans_dev, list);
+       struct mtd_blktrans_ops *tr;
+       struct mtd_blktrans_dev *dev, *next;
 
+       list_for_each_entry(tr, &blktrans_majors, list)
+               list_for_each_entry_safe(dev, next, &tr->devs, list)
                        if (dev->mtd == mtd)
                                tr->remove_dev(dev);
-               }
-       }
 }
 
 static void blktrans_notify_add(struct mtd_info *mtd)
 {
-       struct list_head *this;
+       struct mtd_blktrans_ops *tr;
 
        if (mtd->type == MTD_ABSENT)
                return;
 
-       list_for_each(this, &blktrans_majors) {
-               struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
-
+       list_for_each_entry(tr, &blktrans_majors, list)
                tr->add_mtd(tr, mtd);
-       }
-
 }
 
 static struct mtd_notifier blktrans_notifier = {
@@ -406,7 +394,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
 
 int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
 {
-       struct list_head *this, *next;
+       struct mtd_blktrans_dev *dev, *next;
 
        mutex_lock(&mtd_table_mutex);
 
@@ -416,10 +404,8 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
        /* Remove it from the list of active majors */
        list_del(&tr->list);
 
-       list_for_each_safe(this, next, &tr->devs) {
-               struct mtd_blktrans_dev *dev = list_entry(this, struct mtd_blktrans_dev, list);
+       list_for_each_entry_safe(dev, next, &tr->devs, list)
                tr->remove_dev(dev);
-       }
 
        blk_cleanup_queue(tr->blkcore_priv->rq);
        unregister_blkdev(tr->major, tr->name);
index 952da30b17452d829bc97b669b626a38d1836ab5..208c6faa0358afe995608599ea7e39dc4a405e6d 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * Direct MTD block device access
  *
- * $Id: mtdblock.c,v 1.68 2005/11/07 11:14:20 gleixner Exp $
- *
  * (C) 2000-2003 Nicolas Pitre <nico@cam.org>
  * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
  */
index f79dbb49b1a2601ae596283d75ca83564121d0d5..852165f8b1c3510720cfc03ad80c2e68b4cbd728 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: mtdblock_ro.c,v 1.19 2004/11/16 18:28:59 dwmw2 Exp $
- *
  * (C) 2003 David Woodhouse <dwmw2@infradead.org>
  *
  * Simple read-only (writable only for RAM) mtdblock driver
index aef9f4b687c9fdfafc7eb5fddfc6cdb98ea28cc1..d2f331876e4c86a9b8ee74a36541a1baf01b4b9a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: mtdchar.c,v 1.76 2005/11/07 11:14:20 gleixner Exp $
- *
  * Character-device access to raw MTD devices.
  *
  */
@@ -494,6 +492,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
        {
                struct mtd_oob_buf buf;
                struct mtd_oob_ops ops;
+               struct mtd_oob_buf __user *user_buf = argp;
                uint32_t retlen;
 
                if(!(file->f_mode & 2))
@@ -537,8 +536,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                if (ops.oobretlen > 0xFFFFFFFFU)
                        ret = -EOVERFLOW;
                retlen = ops.oobretlen;
-               if (copy_to_user(&((struct mtd_oob_buf *)argp)->length,
-                                &retlen, sizeof(buf.length)))
+               if (copy_to_user(&user_buf->length, &retlen, sizeof(buf.length)))
                        ret = -EFAULT;
 
                kfree(ops.oobbuf);
@@ -592,29 +590,29 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
 
        case MEMLOCK:
        {
-               struct erase_info_user info;
+               struct erase_info_user einfo;
 
-               if (copy_from_user(&info, argp, sizeof(info)))
+               if (copy_from_user(&einfo, argp, sizeof(einfo)))
                        return -EFAULT;
 
                if (!mtd->lock)
                        ret = -EOPNOTSUPP;
                else
-                       ret = mtd->lock(mtd, info.start, info.length);
+                       ret = mtd->lock(mtd, einfo.start, einfo.length);
                break;
        }
 
        case MEMUNLOCK:
        {
-               struct erase_info_user info;
+               struct erase_info_user einfo;
 
-               if (copy_from_user(&info, argp, sizeof(info)))
+               if (copy_from_user(&einfo, argp, sizeof(einfo)))
                        return -EFAULT;
 
                if (!mtd->unlock)
                        ret = -EOPNOTSUPP;
                else
-                       ret = mtd->unlock(mtd, info.start, info.length);
+                       ret = mtd->unlock(mtd, einfo.start, einfo.length);
                break;
        }
 
@@ -714,15 +712,15 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
 
        case OTPLOCK:
        {
-               struct otp_info info;
+               struct otp_info oinfo;
 
                if (mfi->mode != MTD_MODE_OTP_USER)
                        return -EINVAL;
-               if (copy_from_user(&info, argp, sizeof(info)))
+               if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
                        return -EFAULT;
                if (!mtd->lock_user_prot_reg)
                        return -EOPNOTSUPP;
-               ret = mtd->lock_user_prot_reg(mtd, info.start, info.length);
+               ret = mtd->lock_user_prot_reg(mtd, oinfo.start, oinfo.length);
                break;
        }
 #endif
index d563dcd4b2644e2330398909e02f8e8146dbca9a..2972a5edb73d507e60b9b633b5e85e14a9070074 100644 (file)
@@ -6,8 +6,6 @@
  * NAND support by Christian Gan <cgan@iders.ca>
  *
  * This code is GPL
- *
- * $Id: mtdconcat.c,v 1.11 2005/11/07 11:14:20 gleixner Exp $
  */
 
 #include <linux/kernel.h>
index f7e7890e5bc6889f1ce0aa9fdc18c7be6cf42e6a..a9d246949820a9b0b61aef86061ddf341be21f92 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: mtdcore.c,v 1.47 2005/11/07 11:14:20 gleixner Exp $
- *
  * Core registration and callback routines for MTD
  * drivers and users.
  *
@@ -53,7 +51,7 @@ int add_mtd_device(struct mtd_info *mtd)
 
        for (i=0; i < MAX_MTD_DEVICES; i++)
                if (!mtd_table[i]) {
-                       struct list_head *this;
+                       struct mtd_notifier *not;
 
                        mtd_table[i] = mtd;
                        mtd->index = i;
@@ -72,10 +70,8 @@ int add_mtd_device(struct mtd_info *mtd)
                        DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name);
                        /* No need to get a refcount on the module containing
                           the notifier, since we hold the mtd_table_mutex */
-                       list_for_each(this, &mtd_notifiers) {
-                               struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
+                       list_for_each_entry(not, &mtd_notifiers, list)
                                not->add(mtd);
-                       }
 
                        mutex_unlock(&mtd_table_mutex);
                        /* We _know_ we aren't being removed, because
@@ -113,14 +109,12 @@ int del_mtd_device (struct mtd_info *mtd)
                       mtd->index, mtd->name, mtd->usecount);
                ret = -EBUSY;
        } else {
-               struct list_head *this;
+               struct mtd_notifier *not;
 
                /* No need to get a refcount on the module containing
                   the notifier, since we hold the mtd_table_mutex */
-               list_for_each(this, &mtd_notifiers) {
-                       struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
+               list_for_each_entry(not, &mtd_notifiers, list)
                        not->remove(mtd);
-               }
 
                mtd_table[mtd->index] = NULL;
 
index 07c701169344266e907ce92ee2068c2a8ad6881d..edb90b58a9b16980bd42066f6026bbd1ca7c0667 100644 (file)
@@ -5,8 +5,6 @@
  *
  * This code is GPL
  *
- * $Id: mtdpart.c,v 1.55 2005/11/07 11:14:20 gleixner Exp $
- *
  *     02-21-2002      Thomas Gleixner <gleixner@autronix.de>
  *                     added support for read_oob, write_oob
  */
@@ -46,8 +44,8 @@ struct mtd_part {
  * to the _real_ device.
  */
 
-static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
-                       size_t *retlen, u_char *buf)
+static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
+               size_t *retlen, u_char *buf)
 {
        struct mtd_part *part = PART(mtd);
        int res;
@@ -56,7 +54,7 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
                len = 0;
        else if (from + len > mtd->size)
                len = mtd->size - from;
-       res = part->master->read (part->master, from + part->offset,
+       res = part->master->read(part->master, from + part->offset,
                                   len, retlen, buf);
        if (unlikely(res)) {
                if (res == -EUCLEAN)
@@ -67,8 +65,8 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
        return res;
 }
 
-static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
-                       size_t *retlen, void **virt, resource_size_t *phys)
+static int part_point(struct mtd_info *mtd, loff_t from, size_t len,
+               size_t *retlen, void **virt, resource_size_t *phys)
 {
        struct mtd_part *part = PART(mtd);
        if (from >= mtd->size)
@@ -87,7 +85,7 @@ static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 }
 
 static int part_read_oob(struct mtd_info *mtd, loff_t from,
-                        struct mtd_oob_ops *ops)
+               struct mtd_oob_ops *ops)
 {
        struct mtd_part *part = PART(mtd);
        int res;
@@ -107,38 +105,38 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
        return res;
 }
 
-static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
-                       size_t *retlen, u_char *buf)
+static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
+               size_t len, size_t *retlen, u_char *buf)
 {
        struct mtd_part *part = PART(mtd);
-       return part->master->read_user_prot_reg (part->master, from,
+       return part->master->read_user_prot_reg(part->master, from,
                                        len, retlen, buf);
 }
 
-static int part_get_user_prot_info (struct mtd_info *mtd,
-                                   struct otp_info *buf, size_t len)
+static int part_get_user_prot_info(struct mtd_info *mtd,
+               struct otp_info *buf, size_t len)
 {
        struct mtd_part *part = PART(mtd);
-       return part->master->get_user_prot_info (part->master, buf, len);
+       return part->master->get_user_prot_info(part->master, buf, len);
 }
 
-static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
-                       size_t *retlen, u_char *buf)
+static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
+               size_t len, size_t *retlen, u_char *buf)
 {
        struct mtd_part *part = PART(mtd);
-       return part->master->read_fact_prot_reg (part->master, from,
+       return part->master->read_fact_prot_reg(part->master, from,
                                        len, retlen, buf);
 }
 
-static int part_get_fact_prot_info (struct mtd_info *mtd,
-                                   struct otp_info *buf, size_t len)
+static int part_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf,
+               size_t len)
 {
        struct mtd_part *part = PART(mtd);
-       return part->master->get_fact_prot_info (part->master, buf, len);
+       return part->master->get_fact_prot_info(part->master, buf, len);
 }
 
-static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
-                       size_t *retlen, const u_char *buf)
+static int part_write(struct mtd_info *mtd, loff_t to, size_t len,
+               size_t *retlen, const u_char *buf)
 {
        struct mtd_part *part = PART(mtd);
        if (!(mtd->flags & MTD_WRITEABLE))
@@ -147,12 +145,12 @@ static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
                len = 0;
        else if (to + len > mtd->size)
                len = mtd->size - to;
-       return part->master->write (part->master, to + part->offset,
+       return part->master->write(part->master, to + part->offset,
                                    len, retlen, buf);
 }
 
-static int part_panic_write (struct mtd_info *mtd, loff_t to, size_t len,
-                       size_t *retlen, const u_char *buf)
+static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
+               size_t *retlen, const u_char *buf)
 {
        struct mtd_part *part = PART(mtd);
        if (!(mtd->flags & MTD_WRITEABLE))
@@ -161,12 +159,12 @@ static int part_panic_write (struct mtd_info *mtd, loff_t to, size_t len,
                len = 0;
        else if (to + len > mtd->size)
                len = mtd->size - to;
-       return part->master->panic_write (part->master, to + part->offset,
+       return part->master->panic_write(part->master, to + part->offset,
                                    len, retlen, buf);
 }
 
 static int part_write_oob(struct mtd_info *mtd, loff_t to,
-                        struct mtd_oob_ops *ops)
+               struct mtd_oob_ops *ops)
 {
        struct mtd_part *part = PART(mtd);
 
@@ -180,31 +178,32 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to,
        return part->master->write_oob(part->master, to + part->offset, ops);
 }
 
-static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
-                       size_t *retlen, u_char *buf)
+static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
+               size_t len, size_t *retlen, u_char *buf)
 {
        struct mtd_part *part = PART(mtd);
-       return part->master->write_user_prot_reg (part->master, from,
+       return part->master->write_user_prot_reg(part->master, from,
                                        len, retlen, buf);
 }
 
-static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len)
+static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
+               size_t len)
 {
        struct mtd_part *part = PART(mtd);
-       return part->master->lock_user_prot_reg (part->master, from, len);
+       return part->master->lock_user_prot_reg(part->master, from, len);
 }
 
-static int part_writev (struct mtd_info *mtd,  const struct kvec *vecs,
-                        unsigned long count, loff_t to, size_t *retlen)
+static int part_writev(struct mtd_info *mtd, const struct kvec *vecs,
+               unsigned long count, loff_t to, size_t *retlen)
 {
        struct mtd_part *part = PART(mtd);
        if (!(mtd->flags & MTD_WRITEABLE))
                return -EROFS;
-       return part->master->writev (part->master, vecs, count,
+       return part->master->writev(part->master, vecs, count,
                                        to + part->offset, retlen);
 }
 
-static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
+static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
        struct mtd_part *part = PART(mtd);
        int ret;
@@ -236,7 +235,7 @@ void mtd_erase_callback(struct erase_info *instr)
 }
 EXPORT_SYMBOL_GPL(mtd_erase_callback);
 
-static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
+static int part_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
 {
        struct mtd_part *part = PART(mtd);
        if ((len + ofs) > mtd->size)
@@ -244,7 +243,7 @@ static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
        return part->master->lock(part->master, ofs + part->offset, len);
 }
 
-static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len)
+static int part_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
 {
        struct mtd_part *part = PART(mtd);
        if ((len + ofs) > mtd->size)
@@ -270,7 +269,7 @@ static void part_resume(struct mtd_info *mtd)
        part->master->resume(part->master);
 }
 
-static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
+static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
        struct mtd_part *part = PART(mtd);
        if (ofs >= mtd->size)
@@ -279,7 +278,7 @@ static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
        return part->master->block_isbad(part->master, ofs);
 }
 
-static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
+static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
        struct mtd_part *part = PART(mtd);
        int res;
@@ -302,229 +301,237 @@ static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
 
 int del_mtd_partitions(struct mtd_info *master)
 {
-       struct list_head *node;
-       struct mtd_part *slave;
+       struct mtd_part *slave, *next;
 
-       for (node = mtd_partitions.next;
-            node != &mtd_partitions;
-            node = node->next) {
-               slave = list_entry(node, struct mtd_part, list);
+       list_for_each_entry_safe(slave, next, &mtd_partitions, list)
                if (slave->master == master) {
-                       struct list_head *prev = node->prev;
-                       __list_del(prev, node->next);
-                       if(slave->registered)
+                       list_del(&slave->list);
+                       if (slave->registered)
                                del_mtd_device(&slave->mtd);
                        kfree(slave);
-                       node = prev;
                }
-       }
 
        return 0;
 }
+EXPORT_SYMBOL(del_mtd_partitions);
 
-/*
- * This function, given a master MTD object and a partition table, creates
- * and registers slave MTD objects which are bound to the master according to
- * the partition definitions.
- * (Q: should we register the master MTD object as well?)
- */
-
-int add_mtd_partitions(struct mtd_info *master,
-                      const struct mtd_partition *parts,
-                      int nbparts)
+static struct mtd_part *add_one_partition(struct mtd_info *master,
+               const struct mtd_partition *part, int partno,
+               u_int32_t cur_offset)
 {
        struct mtd_part *slave;
-       u_int32_t cur_offset = 0;
-       int i;
-
-       printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
-
-       for (i = 0; i < nbparts; i++) {
 
-               /* allocate the partition structure */
-               slave = kzalloc (sizeof(*slave), GFP_KERNEL);
-               if (!slave) {
-                       printk ("memory allocation error while creating partitions for \"%s\"\n",
-                               master->name);
-                       del_mtd_partitions(master);
-                       return -ENOMEM;
-               }
-               list_add(&slave->list, &mtd_partitions);
+       /* allocate the partition structure */
+       slave = kzalloc(sizeof(*slave), GFP_KERNEL);
+       if (!slave) {
+               printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
+                       master->name);
+               del_mtd_partitions(master);
+               return NULL;
+       }
+       list_add(&slave->list, &mtd_partitions);
 
-               /* set up the MTD object for this partition */
-               slave->mtd.type = master->type;
-               slave->mtd.flags = master->flags & ~parts[i].mask_flags;
-               slave->mtd.size = parts[i].size;
-               slave->mtd.writesize = master->writesize;
-               slave->mtd.oobsize = master->oobsize;
-               slave->mtd.oobavail = master->oobavail;
-               slave->mtd.subpage_sft = master->subpage_sft;
+       /* set up the MTD object for this partition */
+       slave->mtd.type = master->type;
+       slave->mtd.flags = master->flags & ~part->mask_flags;
+       slave->mtd.size = part->size;
+       slave->mtd.writesize = master->writesize;
+       slave->mtd.oobsize = master->oobsize;
+       slave->mtd.oobavail = master->oobavail;
+       slave->mtd.subpage_sft = master->subpage_sft;
 
-               slave->mtd.name = parts[i].name;
-               slave->mtd.owner = master->owner;
+       slave->mtd.name = part->name;
+       slave->mtd.owner = master->owner;
 
-               slave->mtd.read = part_read;
-               slave->mtd.write = part_write;
+       slave->mtd.read = part_read;
+       slave->mtd.write = part_write;
 
-               if (master->panic_write)
-                       slave->mtd.panic_write = part_panic_write;
+       if (master->panic_write)
+               slave->mtd.panic_write = part_panic_write;
 
-               if(master->point && master->unpoint){
-                       slave->mtd.point = part_point;
-                       slave->mtd.unpoint = part_unpoint;
-               }
+       if (master->point && master->unpoint) {
+               slave->mtd.point = part_point;
+               slave->mtd.unpoint = part_unpoint;
+       }
 
-               if (master->read_oob)
-                       slave->mtd.read_oob = part_read_oob;
-               if (master->write_oob)
-                       slave->mtd.write_oob = part_write_oob;
-               if(master->read_user_prot_reg)
-                       slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
-               if(master->read_fact_prot_reg)
-                       slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
-               if(master->write_user_prot_reg)
-                       slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
-               if(master->lock_user_prot_reg)
-                       slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
-               if(master->get_user_prot_info)
-                       slave->mtd.get_user_prot_info = part_get_user_prot_info;
-               if(master->get_fact_prot_info)
-                       slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
-               if (master->sync)
-                       slave->mtd.sync = part_sync;
-               if (!i && master->suspend && master->resume) {
-                               slave->mtd.suspend = part_suspend;
-                               slave->mtd.resume = part_resume;
+       if (master->read_oob)
+               slave->mtd.read_oob = part_read_oob;
+       if (master->write_oob)
+               slave->mtd.write_oob = part_write_oob;
+       if (master->read_user_prot_reg)
+               slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
+       if (master->read_fact_prot_reg)
+               slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
+       if (master->write_user_prot_reg)
+               slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
+       if (master->lock_user_prot_reg)
+               slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
+       if (master->get_user_prot_info)
+               slave->mtd.get_user_prot_info = part_get_user_prot_info;
+       if (master->get_fact_prot_info)
+               slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
+       if (master->sync)
+               slave->mtd.sync = part_sync;
+       if (!partno && master->suspend && master->resume) {
+                       slave->mtd.suspend = part_suspend;
+                       slave->mtd.resume = part_resume;
+       }
+       if (master->writev)
+               slave->mtd.writev = part_writev;
+       if (master->lock)
+               slave->mtd.lock = part_lock;
+       if (master->unlock)
+               slave->mtd.unlock = part_unlock;
+       if (master->block_isbad)
+               slave->mtd.block_isbad = part_block_isbad;
+       if (master->block_markbad)
+               slave->mtd.block_markbad = part_block_markbad;
+       slave->mtd.erase = part_erase;
+       slave->master = master;
+       slave->offset = part->offset;
+       slave->index = partno;
+
+       if (slave->offset == MTDPART_OFS_APPEND)
+               slave->offset = cur_offset;
+       if (slave->offset == MTDPART_OFS_NXTBLK) {
+               slave->offset = cur_offset;
+               if ((cur_offset % master->erasesize) != 0) {
+                       /* Round up to next erasesize */
+                       slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
+                       printk(KERN_NOTICE "Moving partition %d: "
+                              "0x%08x -> 0x%08x\n", partno,
+                              cur_offset, slave->offset);
                }
-               if (master->writev)
-                       slave->mtd.writev = part_writev;
-               if (master->lock)
-                       slave->mtd.lock = part_lock;
-               if (master->unlock)
-                       slave->mtd.unlock = part_unlock;
-               if (master->block_isbad)
-                       slave->mtd.block_isbad = part_block_isbad;
-               if (master->block_markbad)
-                       slave->mtd.block_markbad = part_block_markbad;
-               slave->mtd.erase = part_erase;
-               slave->master = master;
-               slave->offset = parts[i].offset;
-               slave->index = i;
-
-               if (slave->offset == MTDPART_OFS_APPEND)
-                       slave->offset = cur_offset;
-               if (slave->offset == MTDPART_OFS_NXTBLK) {
-                       slave->offset = cur_offset;
-                       if ((cur_offset % master->erasesize) != 0) {
-                               /* Round up to next erasesize */
-                               slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
-                               printk(KERN_NOTICE "Moving partition %d: "
-                                      "0x%08x -> 0x%08x\n", i,
-                                      cur_offset, slave->offset);
+       }
+       if (slave->mtd.size == MTDPART_SIZ_FULL)
+               slave->mtd.size = master->size - slave->offset;
+
+       printk(KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
+               slave->offset + slave->mtd.size, slave->mtd.name);
+
+       /* let's do some sanity checks */
+       if (slave->offset >= master->size) {
+               /* let's register it anyway to preserve ordering */
+               slave->offset = 0;
+               slave->mtd.size = 0;
+               printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n",
+                       part->name);
+               goto out_register;
+       }
+       if (slave->offset + slave->mtd.size > master->size) {
+               slave->mtd.size = master->size - slave->offset;
+               printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
+                       part->name, master->name, slave->mtd.size);
+       }
+       if (master->numeraseregions > 1) {
+               /* Deal with variable erase size stuff */
+               int i, max = master->numeraseregions;
+               u32 end = slave->offset + slave->mtd.size;
+               struct mtd_erase_region_info *regions = master->eraseregions;
+
+               /* Find the first erase regions which is part of this
+                * partition. */
+               for (i = 0; i < max && regions[i].offset <= slave->offset; i++)
+                       ;
+               /* The loop searched for the region _behind_ the first one */
+               i--;
+
+               /* Pick biggest erasesize */
+               for (; i < max && regions[i].offset < end; i++) {
+                       if (slave->mtd.erasesize < regions[i].erasesize) {
+                               slave->mtd.erasesize = regions[i].erasesize;
                        }
                }
-               if (slave->mtd.size == MTDPART_SIZ_FULL)
-                       slave->mtd.size = master->size - slave->offset;
-               cur_offset = slave->offset + slave->mtd.size;
+               BUG_ON(slave->mtd.erasesize == 0);
+       } else {
+               /* Single erase size */
+               slave->mtd.erasesize = master->erasesize;
+       }
 
-               printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
-                       slave->offset + slave->mtd.size, slave->mtd.name);
+       if ((slave->mtd.flags & MTD_WRITEABLE) &&
+           (slave->offset % slave->mtd.erasesize)) {
+               /* Doesn't start on a boundary of major erase size */
+               /* FIXME: Let it be writable if it is on a boundary of
+                * _minor_ erase size though */
+               slave->mtd.flags &= ~MTD_WRITEABLE;
+               printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
+                       part->name);
+       }
+       if ((slave->mtd.flags & MTD_WRITEABLE) &&
+           (slave->mtd.size % slave->mtd.erasesize)) {
+               slave->mtd.flags &= ~MTD_WRITEABLE;
+               printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
+                       part->name);
+       }
 
-               /* let's do some sanity checks */
-               if (slave->offset >= master->size) {
-                               /* let's register it anyway to preserve ordering */
-                       slave->offset = 0;
-                       slave->mtd.size = 0;
-                       printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
-                               parts[i].name);
-               }
-               if (slave->offset + slave->mtd.size > master->size) {
-                       slave->mtd.size = master->size - slave->offset;
-                       printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
-                               parts[i].name, master->name, slave->mtd.size);
-               }
-               if (master->numeraseregions>1) {
-                       /* Deal with variable erase size stuff */
-                       int i;
-                       struct mtd_erase_region_info *regions = master->eraseregions;
-
-                       /* Find the first erase regions which is part of this partition. */
-                       for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
-                               ;
-
-                       for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
-                               if (slave->mtd.erasesize < regions[i].erasesize) {
-                                       slave->mtd.erasesize = regions[i].erasesize;
-                               }
-                       }
-               } else {
-                       /* Single erase size */
-                       slave->mtd.erasesize = master->erasesize;
-               }
+       slave->mtd.ecclayout = master->ecclayout;
+       if (master->block_isbad) {
+               uint32_t offs = 0;
 
-               if ((slave->mtd.flags & MTD_WRITEABLE) &&
-                   (slave->offset % slave->mtd.erasesize)) {
-                       /* Doesn't start on a boundary of major erase size */
-                       /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
-                       slave->mtd.flags &= ~MTD_WRITEABLE;
-                       printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
-                               parts[i].name);
-               }
-               if ((slave->mtd.flags & MTD_WRITEABLE) &&
-                   (slave->mtd.size % slave->mtd.erasesize)) {
-                       slave->mtd.flags &= ~MTD_WRITEABLE;
-                       printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
-                               parts[i].name);
+               while (offs < slave->mtd.size) {
+                       if (master->block_isbad(master,
+                                               offs + slave->offset))
+                               slave->mtd.ecc_stats.badblocks++;
+                       offs += slave->mtd.erasesize;
                }
+       }
 
-               slave->mtd.ecclayout = master->ecclayout;
-               if (master->block_isbad) {
-                       uint32_t offs = 0;
+out_register:
+       if (part->mtdp) {
+               /* store the object pointer (caller may or may not register it*/
+               *part->mtdp = &slave->mtd;
+               slave->registered = 0;
+       } else {
+               /* register our partition */
+               add_mtd_device(&slave->mtd);
+               slave->registered = 1;
+       }
+       return slave;
+}
 
-                       while(offs < slave->mtd.size) {
-                               if (master->block_isbad(master,
-                                                       offs + slave->offset))
-                                       slave->mtd.ecc_stats.badblocks++;
-                               offs += slave->mtd.erasesize;
-                       }
-               }
+/*
+ * This function, given a master MTD object and a partition table, creates
+ * and registers slave MTD objects which are bound to the master according to
+ * the partition definitions.
+ * (Q: should we register the master MTD object as well?)
+ */
 
-               if(parts[i].mtdp)
-               {       /* store the object pointer (caller may or may not register it */
-                       *parts[i].mtdp = &slave->mtd;
-                       slave->registered = 0;
-               }
-               else
-               {
-                       /* register our partition */
-                       add_mtd_device(&slave->mtd);
-                       slave->registered = 1;
-               }
+int add_mtd_partitions(struct mtd_info *master,
+                      const struct mtd_partition *parts,
+                      int nbparts)
+{
+       struct mtd_part *slave;
+       u_int32_t cur_offset = 0;
+       int i;
+
+       printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
+
+       for (i = 0; i < nbparts; i++) {
+               slave = add_one_partition(master, parts + i, i, cur_offset);
+               if (!slave)
+                       return -ENOMEM;
+               cur_offset = slave->offset + slave->mtd.size;
        }
 
        return 0;
 }
-
 EXPORT_SYMBOL(add_mtd_partitions);
-EXPORT_SYMBOL(del_mtd_partitions);
 
 static DEFINE_SPINLOCK(part_parser_lock);
 static LIST_HEAD(part_parsers);
 
 static struct mtd_part_parser *get_partition_parser(const char *name)
 {
-       struct list_head *this;
-       void *ret = NULL;
-       spin_lock(&part_parser_lock);
+       struct mtd_part_parser *p, *ret = NULL;
 
-       list_for_each(this, &part_parsers) {
-               struct mtd_part_parser *p = list_entry(this, struct mtd_part_parser, list);
+       spin_lock(&part_parser_lock);
 
+       list_for_each_entry(p, &part_parsers, list)
                if (!strcmp(p->name, name) && try_module_get(p->owner)) {
                        ret = p;
                        break;
                }
-       }
+
        spin_unlock(&part_parser_lock);
 
        return ret;
@@ -538,6 +545,7 @@ int register_mtd_parser(struct mtd_part_parser *p)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(register_mtd_parser);
 
 int deregister_mtd_parser(struct mtd_part_parser *p)
 {
@@ -546,6 +554,7 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
        spin_unlock(&part_parser_lock);
        return 0;
 }
+EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
                         struct mtd_partition **pparts, unsigned long origin)
@@ -573,7 +582,4 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
        }
        return ret;
 }
-
 EXPORT_SYMBOL_GPL(parse_mtd_partitions);
-EXPORT_SYMBOL_GPL(register_mtd_parser);
-EXPORT_SYMBOL_GPL(deregister_mtd_parser);
index 5076faf9ca66c54ae300d960f5befccbfc01fb55..71406e517857c456384ddd95ef51633119fe562a 100644 (file)
@@ -1,5 +1,4 @@
 # drivers/mtd/nand/Kconfig
-# $Id: Kconfig,v 1.35 2005/11/07 11:14:30 gleixner Exp $
 
 menuconfig MTD_NAND
        tristate "NAND Device Support"
@@ -272,22 +271,23 @@ config MTD_NAND_CS553X
 
          If you say "m", the module will be called "cs553x_nand.ko".
 
-config MTD_NAND_AT91
-       bool "Support for NAND Flash / SmartMedia on AT91"
-       depends on ARCH_AT91
+config MTD_NAND_ATMEL
+       tristate "Support for NAND Flash / SmartMedia on AT91 and AVR32"
+       depends on ARCH_AT91 || AVR32
        help
          Enables support for NAND Flash / Smart Media Card interface
-         on Atmel AT91 processors.
+         on Atmel AT91 and AVR32 processors.
 choice
-       prompt "ECC management for NAND Flash / SmartMedia on AT91"
-       depends on MTD_NAND_AT91
+       prompt "ECC management for NAND Flash / SmartMedia on AT91 / AVR32"
+       depends on MTD_NAND_ATMEL
 
-config MTD_NAND_AT91_ECC_HW
+config MTD_NAND_ATMEL_ECC_HW
        bool "Hardware ECC"
-       depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260
+       depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 || AVR32
        help
-         Uses hardware ECC provided by the at91sam9260/at91sam9263 chip
-         instead of software ECC.
+         Use hardware ECC instead of software ECC when the chip
+         supports it.
+
          The hardware ECC controller is capable of single bit error
          correction and 2-bit random detection per page.
 
@@ -297,16 +297,16 @@ config MTD_NAND_AT91_ECC_HW
 
          If unsure, say Y
 
-config MTD_NAND_AT91_ECC_SOFT
+config MTD_NAND_ATMEL_ECC_SOFT
        bool "Software ECC"
        help
-         Uses software ECC.
+         Use software ECC.
 
          NB : hardware and software ECC schemes are incompatible.
          If you switch from one to another, you'll have to erase your
          mtd partition.
 
-config MTD_NAND_AT91_ECC_NONE
+config MTD_NAND_ATMEL_ECC_NONE
        bool "No ECC (testing only, DANGEROUS)"
        depends on DEBUG_KERNEL
        help
index a6e74a46992a7bde250a5ca7a5d9b20eef96ea00..d772581de573cf4281e64cf11598e234ca2dd6e7 100644 (file)
@@ -1,7 +1,6 @@
 #
 # linux/drivers/nand/Makefile
 #
-# $Id: Makefile.common,v 1.15 2004/11/26 12:28:22 dedekind Exp $
 
 obj-$(CONFIG_MTD_NAND)                 += nand.o nand_ecc.o
 obj-$(CONFIG_MTD_NAND_IDS)             += nand_ids.o
@@ -24,7 +23,7 @@ obj-$(CONFIG_MTD_NAND_TS7250)         += ts7250.o
 obj-$(CONFIG_MTD_NAND_NANDSIM)         += nandsim.o
 obj-$(CONFIG_MTD_NAND_CS553X)          += cs553x_nand.o
 obj-$(CONFIG_MTD_NAND_NDFC)            += ndfc.o
-obj-$(CONFIG_MTD_NAND_AT91)            += at91_nand.o
+obj-$(CONFIG_MTD_NAND_ATMEL)           += atmel_nand.o
 obj-$(CONFIG_MTD_NAND_CM_X270)         += cmx270_nand.o
 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)   += excite_nandflash.o
 obj-$(CONFIG_MTD_NAND_PXA3xx)          += pxa3xx_nand.o
similarity index 62%
rename from drivers/mtd/nand/at91_nand.c
rename to drivers/mtd/nand/atmel_nand.c
index 0adb287027a249409062c5ba6a46cadc717f50a8..99aec46e21450565e3e323adccfcb1f077597511 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/mtd/nand/at91_nand.c
- *
  *  Copyright (C) 2003 Rick Bronson
  *
  *  Derived from drivers/mtd/nand/autcpu12.c
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 
-#include <asm/io.h>
-#include <asm/sizes.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
+#include <asm/arch/cpu.h>
 
-#ifdef CONFIG_MTD_NAND_AT91_ECC_HW
+#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
 #define hard_ecc       1
 #else
 #define hard_ecc       0
 #endif
 
-#ifdef CONFIG_MTD_NAND_AT91_ECC_NONE
+#ifdef CONFIG_MTD_NAND_ATMEL_ECC_NONE
 #define no_ecc         1
 #else
 #define no_ecc         0
 
 /* Register access macros */
 #define ecc_readl(add, reg)                            \
-       __raw_readl(add + AT91_ECC_##reg)
+       __raw_readl(add + ATMEL_ECC_##reg)
 #define ecc_writel(add, reg, value)                    \
-       __raw_writel((value), add + AT91_ECC_##reg)
+       __raw_writel((value), add + ATMEL_ECC_##reg)
 
-#include <asm/arch/at91_ecc.h> /* AT91SAM9260/3 ECC registers */
+#include "atmel_nand_ecc.h"    /* Hardware ECC registers */
 
 /* oob layout for large page size
  * bad block info is on bytes 0 and 1
  * the bytes have to be consecutives to avoid
  * several NAND_CMD_RNDOUT during read
  */
-static struct nand_ecclayout at91_oobinfo_large = {
+static struct nand_ecclayout atmel_oobinfo_large = {
        .eccbytes = 4,
        .eccpos = {60, 61, 62, 63},
        .oobfree = {
@@ -76,7 +73,7 @@ static struct nand_ecclayout at91_oobinfo_large = {
  * the bytes have to be consecutives to avoid
  * several NAND_CMD_RNDOUT during read
  */
-static struct nand_ecclayout at91_oobinfo_small = {
+static struct nand_ecclayout atmel_oobinfo_small = {
        .eccbytes = 4,
        .eccpos = {0, 1, 2, 3},
        .oobfree = {
@@ -84,11 +81,11 @@ static struct nand_ecclayout at91_oobinfo_small = {
        },
 };
 
-struct at91_nand_host {
+struct atmel_nand_host {
        struct nand_chip        nand_chip;
        struct mtd_info         mtd;
        void __iomem            *io_base;
-       struct at91_nand_data   *board;
+       struct atmel_nand_data  *board;
        struct device           *dev;
        void __iomem            *ecc;
 };
@@ -96,34 +93,34 @@ struct at91_nand_host {
 /*
  * Enable NAND.
  */
-static void at91_nand_enable(struct at91_nand_host *host)
+static void atmel_nand_enable(struct atmel_nand_host *host)
 {
        if (host->board->enable_pin)
-               at91_set_gpio_value(host->board->enable_pin, 0);
+               gpio_set_value(host->board->enable_pin, 0);
 }
 
 /*
  * Disable NAND.
  */
-static void at91_nand_disable(struct at91_nand_host *host)
+static void atmel_nand_disable(struct atmel_nand_host *host)
 {
        if (host->board->enable_pin)
-               at91_set_gpio_value(host->board->enable_pin, 1);
+               gpio_set_value(host->board->enable_pin, 1);
 }
 
 /*
  * Hardware specific access to control-lines
  */
-static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
        struct nand_chip *nand_chip = mtd->priv;
-       struct at91_nand_host *host = nand_chip->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
 
        if (ctrl & NAND_CTRL_CHANGE) {
                if (ctrl & NAND_NCE)
-                       at91_nand_enable(host);
+                       atmel_nand_enable(host);
                else
-                       at91_nand_disable(host);
+                       atmel_nand_disable(host);
        }
        if (cmd == NAND_CMD_NONE)
                return;
@@ -137,18 +134,49 @@ static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 /*
  * Read the Device Ready pin.
  */
-static int at91_nand_device_ready(struct mtd_info *mtd)
+static int atmel_nand_device_ready(struct mtd_info *mtd)
 {
        struct nand_chip *nand_chip = mtd->priv;
-       struct at91_nand_host *host = nand_chip->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
 
-       return at91_get_gpio_value(host->board->rdy_pin);
+       return gpio_get_value(host->board->rdy_pin);
+}
+
+/*
+ * Minimal-overhead PIO for data access.
+ */
+static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+       struct nand_chip        *nand_chip = mtd->priv;
+
+       __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
+}
+
+static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
+{
+       struct nand_chip        *nand_chip = mtd->priv;
+
+       __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
+}
+
+static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+       struct nand_chip        *nand_chip = mtd->priv;
+
+       __raw_writesb(nand_chip->IO_ADDR_W, buf, len);
+}
+
+static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
+{
+       struct nand_chip        *nand_chip = mtd->priv;
+
+       __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
 }
 
 /*
  * write oob for small pages
  */
-static int at91_nand_write_oob_512(struct mtd_info *mtd,
+static int atmel_nand_write_oob_512(struct mtd_info *mtd,
                struct nand_chip *chip, int page)
 {
        int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -176,7 +204,7 @@ static int at91_nand_write_oob_512(struct mtd_info *mtd,
 /*
  * read oob for small pages
  */
-static int at91_nand_read_oob_512(struct mtd_info *mtd,
+static int atmel_nand_read_oob_512(struct mtd_info *mtd,
                struct nand_chip *chip, int page, int sndcmd)
 {
        if (sndcmd) {
@@ -196,11 +224,11 @@ static int at91_nand_read_oob_512(struct mtd_info *mtd,
  * dat:        raw data (unused)
  * ecc_code:   buffer for ECC
  */
-static int at91_nand_calculate(struct mtd_info *mtd,
+static int atmel_nand_calculate(struct mtd_info *mtd,
                const u_char *dat, unsigned char *ecc_code)
 {
        struct nand_chip *nand_chip = mtd->priv;
-       struct at91_nand_host *host = nand_chip->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
        uint32_t *eccpos = nand_chip->ecc.layout->eccpos;
        unsigned int ecc_value;
 
@@ -211,7 +239,7 @@ static int at91_nand_calculate(struct mtd_info *mtd,
        ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;
 
        /* get the last 2 ECC bytes */
-       ecc_value = ecc_readl(host->ecc, NPR) & AT91_ECC_NPARITY;
+       ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY;
 
        ecc_code[eccpos[2]] = ecc_value & 0xFF;
        ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;
@@ -226,7 +254,7 @@ static int at91_nand_calculate(struct mtd_info *mtd,
  * chip:       nand chip info structure
  * buf:        buffer to store read data
  */
-static int at91_nand_read_page(struct mtd_info *mtd,
+static int atmel_nand_read_page(struct mtd_info *mtd,
                struct nand_chip *chip, uint8_t *buf)
 {
        int eccsize = chip->ecc.size;
@@ -237,6 +265,19 @@ static int at91_nand_read_page(struct mtd_info *mtd,
        uint8_t *ecc_pos;
        int stat;
 
+       /*
+        * Errata: ALE is incorrectly wired up to the ECC controller
+        * on the AP7000, so it will include the address cycles in the
+        * ECC calculation.
+        *
+        * Workaround: Reset the parity registers before reading the
+        * actual data.
+        */
+       if (cpu_is_at32ap7000()) {
+               struct atmel_nand_host *host = chip->priv;
+               ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
+       }
+
        /* read the page */
        chip->read_buf(mtd, p, eccsize);
 
@@ -285,11 +326,11 @@ static int at91_nand_read_page(struct mtd_info *mtd,
  *
  * Detect and correct a 1 bit error for a page
  */
-static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
+static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
                u_char *read_ecc, u_char *isnull)
 {
        struct nand_chip *nand_chip = mtd->priv;
-       struct at91_nand_host *host = nand_chip->priv;
+       struct atmel_nand_host *host = nand_chip->priv;
        unsigned int ecc_status;
        unsigned int ecc_word, ecc_bit;
 
@@ -297,43 +338,43 @@ static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
        ecc_status = ecc_readl(host->ecc, SR);
 
        /* if there's no error */
-       if (likely(!(ecc_status & AT91_ECC_RECERR)))
+       if (likely(!(ecc_status & ATMEL_ECC_RECERR)))
                return 0;
 
        /* get error bit offset (4 bits) */
-       ecc_bit = ecc_readl(host->ecc, PR) & AT91_ECC_BITADDR;
+       ecc_bit = ecc_readl(host->ecc, PR) & ATMEL_ECC_BITADDR;
        /* get word address (12 bits) */
-       ecc_word = ecc_readl(host->ecc, PR) & AT91_ECC_WORDADDR;
+       ecc_word = ecc_readl(host->ecc, PR) & ATMEL_ECC_WORDADDR;
        ecc_word >>= 4;
 
        /* if there are multiple errors */
-       if (ecc_status & AT91_ECC_MULERR) {
+       if (ecc_status & ATMEL_ECC_MULERR) {
                /* check if it is a freshly erased block
                 * (filled with 0xff) */
-               if ((ecc_bit == AT91_ECC_BITADDR)
-                               && (ecc_word == (AT91_ECC_WORDADDR >> 4))) {
+               if ((ecc_bit == ATMEL_ECC_BITADDR)
+                               && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) {
                        /* the block has just been erased, return OK */
                        return 0;
                }
                /* it doesn't seems to be a freshly
                 * erased block.
                 * We can't correct so many errors */
-               dev_dbg(host->dev, "at91_nand : multiple errors detected."
+               dev_dbg(host->dev, "atmel_nand : multiple errors detected."
                                " Unable to correct.\n");
                return -EIO;
        }
 
        /* if there's a single bit error : we can correct it */
-       if (ecc_status & AT91_ECC_ECCERR) {
+       if (ecc_status & ATMEL_ECC_ECCERR) {
                /* there's nothing much to do here.
                 * the bit error is on the ECC itself.
                 */
-               dev_dbg(host->dev, "at91_nand : one bit error on ECC code."
+               dev_dbg(host->dev, "atmel_nand : one bit error on ECC code."
                                " Nothing to correct\n");
                return 0;
        }
 
-       dev_dbg(host->dev, "at91_nand : one bit error on data."
+       dev_dbg(host->dev, "atmel_nand : one bit error on data."
                        " (word offset in the page :"
                        " 0x%x bit offset : 0x%x)\n",
                        ecc_word, ecc_bit);
@@ -345,14 +386,21 @@ static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
                /* 8 bits words */
                dat[ecc_word] ^= (1 << ecc_bit);
        }
-       dev_dbg(host->dev, "at91_nand : error corrected\n");
+       dev_dbg(host->dev, "atmel_nand : error corrected\n");
        return 1;
 }
 
 /*
- * Enable HW ECC : unsused
+ * Enable HW ECC : unused on most chips
  */
-static void at91_nand_hwctl(struct mtd_info *mtd, int mode) { ; }
+static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
+{
+       if (cpu_is_at32ap7000()) {
+               struct nand_chip *nand_chip = mtd->priv;
+               struct atmel_nand_host *host = nand_chip->priv;
+               ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
+       }
+}
 
 #ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL };
@@ -361,9 +409,9 @@ static const char *part_probes[] = { "cmdlinepart", NULL };
 /*
  * Probe for the NAND device.
  */
-static int __init at91_nand_probe(struct platform_device *pdev)
+static int __init atmel_nand_probe(struct platform_device *pdev)
 {
-       struct at91_nand_host *host;
+       struct atmel_nand_host *host;
        struct mtd_info *mtd;
        struct nand_chip *nand_chip;
        struct resource *regs;
@@ -375,24 +423,24 @@ static int __init at91_nand_probe(struct platform_device *pdev)
        int num_partitions = 0;
 #endif
 
-       /* Allocate memory for the device structure (and zero it) */
-       host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL);
-       if (!host) {
-               printk(KERN_ERR "at91_nand: failed to allocate device structure.\n");
-               return -ENOMEM;
-       }
-
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
-               printk(KERN_ERR "at91_nand: can't get I/O resource mem\n");
+               printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n");
                return -ENXIO;
        }
 
+       /* Allocate memory for the device structure (and zero it) */
+       host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL);
+       if (!host) {
+               printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n");
+               return -ENOMEM;
+       }
+
        host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
        if (host->io_base == NULL) {
-               printk(KERN_ERR "at91_nand: ioremap failed\n");
-               kfree(host);
-               return -EIO;
+               printk(KERN_ERR "atmel_nand: ioremap failed\n");
+               res = -EIO;
+               goto err_nand_ioremap;
        }
 
        mtd = &host->mtd;
@@ -407,14 +455,14 @@ static int __init at91_nand_probe(struct platform_device *pdev)
        /* Set address of NAND IO lines */
        nand_chip->IO_ADDR_R = host->io_base;
        nand_chip->IO_ADDR_W = host->io_base;
-       nand_chip->cmd_ctrl = at91_nand_cmd_ctrl;
+       nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
 
        if (host->board->rdy_pin)
-               nand_chip->dev_ready = at91_nand_device_ready;
+               nand_chip->dev_ready = atmel_nand_device_ready;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        if (!regs && hard_ecc) {
-               printk(KERN_ERR "at91_nand: can't get I/O resource "
+               printk(KERN_ERR "atmel_nand: can't get I/O resource "
                                "regs\nFalling back on software ECC\n");
        }
 
@@ -424,15 +472,15 @@ static int __init at91_nand_probe(struct platform_device *pdev)
        if (hard_ecc && regs) {
                host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
                if (host->ecc == NULL) {
-                       printk(KERN_ERR "at91_nand: ioremap failed\n");
+                       printk(KERN_ERR "atmel_nand: ioremap failed\n");
                        res = -EIO;
                        goto err_ecc_ioremap;
                }
                nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME;
-               nand_chip->ecc.calculate = at91_nand_calculate;
-               nand_chip->ecc.correct = at91_nand_correct;
-               nand_chip->ecc.hwctl = at91_nand_hwctl;
-               nand_chip->ecc.read_page = at91_nand_read_page;
+               nand_chip->ecc.calculate = atmel_nand_calculate;
+               nand_chip->ecc.correct = atmel_nand_correct;
+               nand_chip->ecc.hwctl = atmel_nand_hwctl;
+               nand_chip->ecc.read_page = atmel_nand_read_page;
                nand_chip->ecc.bytes = 4;
                nand_chip->ecc.prepad = 0;
                nand_chip->ecc.postpad = 0;
@@ -440,24 +488,30 @@ static int __init at91_nand_probe(struct platform_device *pdev)
 
        nand_chip->chip_delay = 20;             /* 20us command delay time */
 
-       if (host->board->bus_width_16)          /* 16-bit bus width */
+       if (host->board->bus_width_16) {        /* 16-bit bus width */
                nand_chip->options |= NAND_BUSWIDTH_16;
+               nand_chip->read_buf = atmel_read_buf16;
+               nand_chip->write_buf = atmel_write_buf16;
+       } else {
+               nand_chip->read_buf = atmel_read_buf;
+               nand_chip->write_buf = atmel_write_buf;
+       }
 
        platform_set_drvdata(pdev, host);
-       at91_nand_enable(host);
+       atmel_nand_enable(host);
 
        if (host->board->det_pin) {
-               if (at91_get_gpio_value(host->board->det_pin)) {
-                       printk ("No SmartMedia card inserted.\n");
+               if (gpio_get_value(host->board->det_pin)) {
+                       printk("No SmartMedia card inserted.\n");
                        res = ENXIO;
-                       goto out;
+                       goto err_no_card;
                }
        }
 
        /* first scan to find the device and get the page size */
        if (nand_scan_ident(mtd, 1)) {
                res = -ENXIO;
-               goto out;
+               goto err_scan_ident;
        }
 
        if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
@@ -467,22 +521,22 @@ static int __init at91_nand_probe(struct platform_device *pdev)
                /* set ECC page size and oob layout */
                switch (mtd->writesize) {
                case 512:
-                       nand_chip->ecc.layout = &at91_oobinfo_small;
-                       nand_chip->ecc.read_oob = at91_nand_read_oob_512;
-                       nand_chip->ecc.write_oob = at91_nand_write_oob_512;
-                       ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_528);
+                       nand_chip->ecc.layout = &atmel_oobinfo_small;
+                       nand_chip->ecc.read_oob = atmel_nand_read_oob_512;
+                       nand_chip->ecc.write_oob = atmel_nand_write_oob_512;
+                       ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
                        break;
                case 1024:
-                       nand_chip->ecc.layout = &at91_oobinfo_large;
-                       ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_1056);
+                       nand_chip->ecc.layout = &atmel_oobinfo_large;
+                       ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
                        break;
                case 2048:
-                       nand_chip->ecc.layout = &at91_oobinfo_large;
-                       ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_2112);
+                       nand_chip->ecc.layout = &atmel_oobinfo_large;
+                       ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
                        break;
                case 4096:
-                       nand_chip->ecc.layout = &at91_oobinfo_large;
-                       ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_4224);
+                       nand_chip->ecc.layout = &atmel_oobinfo_large;
+                       ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
                        break;
                default:
                        /* page size not handled by HW ECC */
@@ -502,12 +556,12 @@ static int __init at91_nand_probe(struct platform_device *pdev)
        /* second phase scan */
        if (nand_scan_tail(mtd)) {
                res = -ENXIO;
-               goto out;
+               goto err_scan_tail;
        }
 
 #ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_CMDLINE_PARTS
-       mtd->name = "at91_nand";
+       mtd->name = "atmel_nand";
        num_partitions = parse_mtd_partitions(mtd, part_probes,
                                              &partitions, 0);
 #endif
@@ -516,9 +570,9 @@ static int __init at91_nand_probe(struct platform_device *pdev)
                                                         &num_partitions);
 
        if ((!partitions) || (num_partitions == 0)) {
-               printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
+               printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n");
                res = ENXIO;
-               goto release;
+               goto err_no_partitions;
        }
 
        res = add_mtd_partitions(mtd, partitions, num_partitions);
@@ -530,17 +584,19 @@ static int __init at91_nand_probe(struct platform_device *pdev)
                return res;
 
 #ifdef CONFIG_MTD_PARTITIONS
-release:
+err_no_partitions:
 #endif
        nand_release(mtd);
-
-out:
-       iounmap(host->ecc);
-
-err_ecc_ioremap:
-       at91_nand_disable(host);
+err_scan_tail:
+err_scan_ident:
+err_no_card:
+       atmel_nand_disable(host);
        platform_set_drvdata(pdev, NULL);
+       if (host->ecc)
+               iounmap(host->ecc);
+err_ecc_ioremap:
        iounmap(host->io_base);
+err_nand_ioremap:
        kfree(host);
        return res;
 }
@@ -548,47 +604,47 @@ err_ecc_ioremap:
 /*
  * Remove a NAND device.
  */
-static int __devexit at91_nand_remove(struct platform_device *pdev)
+static int __exit atmel_nand_remove(struct platform_device *pdev)
 {
-       struct at91_nand_host *host = platform_get_drvdata(pdev);
+       struct atmel_nand_host *host = platform_get_drvdata(pdev);
        struct mtd_info *mtd = &host->mtd;
 
        nand_release(mtd);
 
-       at91_nand_disable(host);
+       atmel_nand_disable(host);
 
+       if (host->ecc)
+               iounmap(host->ecc);
        iounmap(host->io_base);
-       iounmap(host->ecc);
        kfree(host);
 
        return 0;
 }
 
-static struct platform_driver at91_nand_driver = {
-       .probe          = at91_nand_probe,
-       .remove         = at91_nand_remove,
+static struct platform_driver atmel_nand_driver = {
+       .remove         = __exit_p(atmel_nand_remove),
        .driver         = {
-               .name   = "at91_nand",
+               .name   = "atmel_nand",
                .owner  = THIS_MODULE,
        },
 };
 
-static int __init at91_nand_init(void)
+static int __init atmel_nand_init(void)
 {
-       return platform_driver_register(&at91_nand_driver);
+       return platform_driver_probe(&atmel_nand_driver, atmel_nand_probe);
 }
 
 
-static void __exit at91_nand_exit(void)
+static void __exit atmel_nand_exit(void)
 {
-       platform_driver_unregister(&at91_nand_driver);
+       platform_driver_unregister(&atmel_nand_driver);
 }
 
 
-module_init(at91_nand_init);
-module_exit(at91_nand_exit);
+module_init(atmel_nand_init);
+module_exit(atmel_nand_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Rick Bronson");
-MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200 / AT91SAM9");
-MODULE_ALIAS("platform:at91_nand");
+MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91 / AVR32");
+MODULE_ALIAS("platform:atmel_nand");
diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
new file mode 100644 (file)
index 0000000..1ee7f99
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Error Corrected Code Controller (ECC) - System peripherals regsters.
+ * Based on AT91SAM9260 datasheet revision B.
+ *
+ * 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 ATMEL_NAND_ECC_H
+#define ATMEL_NAND_ECC_H
+
+#define ATMEL_ECC_CR           0x00                    /* Control register */
+#define                ATMEL_ECC_RST           (1 << 0)                /* Reset parity */
+
+#define ATMEL_ECC_MR           0x04                    /* Mode register */
+#define                ATMEL_ECC_PAGESIZE      (3 << 0)                /* Page Size */
+#define                        ATMEL_ECC_PAGESIZE_528          (0)
+#define                        ATMEL_ECC_PAGESIZE_1056         (1)
+#define                        ATMEL_ECC_PAGESIZE_2112         (2)
+#define                        ATMEL_ECC_PAGESIZE_4224         (3)
+
+#define ATMEL_ECC_SR           0x08                    /* Status register */
+#define                ATMEL_ECC_RECERR                (1 << 0)                /* Recoverable Error */
+#define                ATMEL_ECC_ECCERR                (1 << 1)                /* ECC Single Bit Error */
+#define                ATMEL_ECC_MULERR                (1 << 2)                /* Multiple Errors */
+
+#define ATMEL_ECC_PR           0x0c                    /* Parity register */
+#define                ATMEL_ECC_BITADDR       (0xf << 0)              /* Bit Error Address */
+#define                ATMEL_ECC_WORDADDR      (0xfff << 4)            /* Word Error Address */
+
+#define ATMEL_ECC_NPR          0x10                    /* NParity register */
+#define                ATMEL_ECC_NPARITY       (0xffff << 0)           /* NParity */
+
+#endif
index 09e421a968934828a95100aebb4a6df8c6e9de54..761946ea45b132da9dde13b1d3ea9b7935f53a8a 100644 (file)
@@ -3,8 +3,6 @@
  *
  *  Copyright (C) 2004 Embedded Edge, LLC
  *
- * $Id: au1550nd.c,v 1.13 2005/11/07 11:14:30 gleixner Exp $
- *
  * 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.
@@ -604,8 +602,6 @@ module_init(au1xxx_nand_init);
  */
 static void __exit au1550_cleanup(void)
 {
-       struct nand_chip *this = (struct nand_chip *)&au1550_mtd[1];
-
        /* Release resources, unregister device */
        nand_release(au1550_mtd);
 
index dd38011ee0b7326096973b694a3339467bc984f5..553dd7e9b41c983711898a3a0020d4647731efc5 100644 (file)
@@ -6,8 +6,6 @@
  *  Derived from drivers/mtd/spia.c
  *      Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
  *
- * $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $
- *
  * 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.
index da6ceaa80ba137c1c4114a199d59efb09bcf08ed..95345d05157922fdfedf21b6a7d9527215f40be3 100644 (file)
@@ -626,10 +626,12 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 {
        struct mtd_info *mtd;
        struct cafe_priv *cafe;
-       struct mtd_partition *parts;
        uint32_t ctrl;
-       int nr_parts;
        int err = 0;
+#ifdef CONFIG_MTD_PARTITIONS
+       struct mtd_partition *parts;
+       int nr_parts;
+#endif
 
        /* Very old versions shared the same PCI ident for all three
           functions on the chip. Verify the class too... */
index 0e72153b329736000e4c43abfc76038b725d5959..765d4f0f7c865c1682e94d11ba48fa6986c3d02c 100644 (file)
@@ -15,8 +15,6 @@
  * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de>
  *
  * Interface to generic NAND code for M-Systems DiskOnChip devices
- *
- * $Id: diskonchip.c,v 1.55 2005/11/07 11:14:30 gleixner Exp $
  */
 
 #include <linux/kernel.h>
@@ -54,8 +52,6 @@ static unsigned long __initdata doc_locations[] = {
        0xe0000, 0xe2000, 0xe4000, 0xe6000,
        0xe8000, 0xea000, 0xec000, 0xee000,
 #endif /*  CONFIG_MTD_DOCPROBE_HIGH */
-#elif defined(__PPC__)
-       0xe4000000,
 #else
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
 #endif
index ba67bbec20d3a4fbab3ac9733d05ee7cc3f61229..387e4352903e80af7807c155129ab131e9dfbacf 100644 (file)
@@ -6,8 +6,6 @@
  *  Derived from drivers/mtd/nand/autcpu12.c
  *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
  *
- * $Id: edb7312.c,v 1.12 2005/11/07 11:14:30 gleixner Exp $
- *
  * 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.
index bed87290deccd3b07e120278d77f47c347e57517..ced14b5294d51dac99826cee87899e464abf5fe5 100644 (file)
@@ -209,7 +209,7 @@ static int __init excite_nand_probe(struct device *dev)
        if (likely(!scan_res)) {
                DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id);
                add_mtd_partitions(&drvdata->board_mtd, partition_info,
-                                  sizeof partition_info / sizeof partition_info[0]);
+                                  ARRAY_SIZE(partition_info));
        } else {
                iounmap(drvdata->regs);
                kfree(drvdata);
index 4b69aacdf5ca45410207dca1f8908413f166e1c1..9dff51351f4fba32559541ce50c175d48ef52828 100644 (file)
@@ -89,7 +89,6 @@ static struct nand_ecclayout fsl_elbc_oob_sp_eccm0 = {
        .eccbytes = 3,
        .eccpos = {6, 7, 8},
        .oobfree = { {0, 5}, {9, 7} },
-       .oobavail = 12,
 };
 
 /* Small Page FLASH with FMR[ECCM] = 1 */
@@ -97,7 +96,6 @@ static struct nand_ecclayout fsl_elbc_oob_sp_eccm1 = {
        .eccbytes = 3,
        .eccpos = {8, 9, 10},
        .oobfree = { {0, 5}, {6, 2}, {11, 5} },
-       .oobavail = 12,
 };
 
 /* Large Page FLASH with FMR[ECCM] = 0 */
@@ -105,7 +103,6 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm0 = {
        .eccbytes = 12,
        .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56},
        .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} },
-       .oobavail = 48,
 };
 
 /* Large Page FLASH with FMR[ECCM] = 1 */
@@ -113,7 +110,48 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = {
        .eccbytes = 12,
        .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
        .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} },
-       .oobavail = 48,
+};
+
+/*
+ * fsl_elbc_oob_lp_eccm* specify that LP NAND's OOB free area starts at offset
+ * 1, so we have to adjust bad block pattern. This pattern should be used for
+ * x8 chips only. So far hardware does not support x16 chips anyway.
+ */
+static u8 scan_ff_pattern[] = { 0xff, };
+
+static struct nand_bbt_descr largepage_memorybased = {
+       .options = 0,
+       .offs = 0,
+       .len = 1,
+       .pattern = scan_ff_pattern,
+};
+
+/*
+ * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt,
+ * interfere with ECC positions, that's why we implement our own descriptors.
+ * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0.
+ */
+static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+                  NAND_BBT_2BIT | NAND_BBT_VERSION,
+       .offs = 11,
+       .len = 4,
+       .veroffs = 15,
+       .maxblocks = 4,
+       .pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+                  NAND_BBT_2BIT | NAND_BBT_VERSION,
+       .offs = 11,
+       .len = 4,
+       .veroffs = 15,
+       .maxblocks = 4,
+       .pattern = mirror_pattern,
 };
 
 /*=================================*/
@@ -687,8 +725,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
                        chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
                                           &fsl_elbc_oob_lp_eccm1 :
                                           &fsl_elbc_oob_lp_eccm0;
-                       mtd->ecclayout = chip->ecc.layout;
-                       mtd->oobavail = chip->ecc.layout->oobavail;
+                       chip->badblock_pattern = &largepage_memorybased;
                }
        } else {
                dev_err(ctrl->dev,
@@ -752,8 +789,12 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
        chip->cmdfunc = fsl_elbc_cmdfunc;
        chip->waitfunc = fsl_elbc_wait;
 
+       chip->bbt_td = &bbt_main_descr;
+       chip->bbt_md = &bbt_mirror_descr;
+
        /* set up nand options */
-       chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR;
+       chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
+                       NAND_USE_FLASH_BBT;
 
        chip->controller = &ctrl->controller;
        chip->priv = priv;
@@ -795,8 +836,8 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
        return 0;
 }
 
-static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
-                               struct device_node *node)
+static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
+                                        struct device_node *node)
 {
        struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
        struct fsl_elbc_mtd *priv;
@@ -917,7 +958,7 @@ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
        return 0;
 }
 
-static int __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev)
+static int fsl_elbc_ctrl_remove(struct of_device *ofdev)
 {
        struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
        int i;
@@ -1041,7 +1082,7 @@ static struct of_platform_driver fsl_elbc_ctrl_driver = {
        },
        .match_table = fsl_elbc_match,
        .probe = fsl_elbc_ctrl_probe,
-       .remove = __devexit_p(fsl_elbc_ctrl_remove),
+       .remove = fsl_elbc_ctrl_remove,
 };
 
 static int __init fsl_elbc_init(void)
index 2d585d2d090c97e58efc831ec988159ee1a3fb22..9e59de501c2e95beab5a18881b38ed2c312794a0 100644 (file)
@@ -7,8 +7,6 @@
  *       Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
  *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
  *
- * $Id: h1910.c,v 1.6 2005/11/07 11:14:30 gleixner Exp $
- *
  * 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.
index ba1bdf787323190377c20aa239317ee278769b5b..d1129bae6c27d20731ef0ead6b86a863e590e7f4 100644 (file)
@@ -797,6 +797,87 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
        return 0;
 }
 
+/**
+ * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @dataofs    offset of requested data within the page
+ * @readlen    data length
+ * @buf:       buffer to store read data
+ */
+static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
+{
+       int start_step, end_step, num_steps;
+       uint32_t *eccpos = chip->ecc.layout->eccpos;
+       uint8_t *p;
+       int data_col_addr, i, gaps = 0;
+       int datafrag_len, eccfrag_len, aligned_len, aligned_pos;
+       int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
+
+       /* Column address wihin the page aligned to ECC size (256bytes). */
+       start_step = data_offs / chip->ecc.size;
+       end_step = (data_offs + readlen - 1) / chip->ecc.size;
+       num_steps = end_step - start_step + 1;
+
+       /* Data size aligned to ECC ecc.size*/
+       datafrag_len = num_steps * chip->ecc.size;
+       eccfrag_len = num_steps * chip->ecc.bytes;
+
+       data_col_addr = start_step * chip->ecc.size;
+       /* If we read not a page aligned data */
+       if (data_col_addr != 0)
+               chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
+
+       p = bufpoi + data_col_addr;
+       chip->read_buf(mtd, p, datafrag_len);
+
+       /* Calculate  ECC */
+       for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
+               chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
+
+       /* The performance is faster if to position offsets
+          according to ecc.pos. Let make sure here that
+          there are no gaps in ecc positions */
+       for (i = 0; i < eccfrag_len - 1; i++) {
+               if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
+                       eccpos[i + start_step * chip->ecc.bytes + 1]) {
+                       gaps = 1;
+                       break;
+               }
+       }
+       if (gaps) {
+               chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
+               chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+       } else {
+               /* send the command to read the particular ecc bytes */
+               /* take care about buswidth alignment in read_buf */
+               aligned_pos = eccpos[start_step * chip->ecc.bytes] & ~(busw - 1);
+               aligned_len = eccfrag_len;
+               if (eccpos[start_step * chip->ecc.bytes] & (busw - 1))
+                       aligned_len++;
+               if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1))
+                       aligned_len++;
+
+               chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1);
+               chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
+       }
+
+       for (i = 0; i < eccfrag_len; i++)
+               chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + start_step * chip->ecc.bytes]];
+
+       p = bufpoi + data_col_addr;
+       for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) {
+               int stat;
+
+               stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
+               if (stat == -1)
+                       mtd->ecc_stats.failed++;
+               else
+                       mtd->ecc_stats.corrected += stat;
+       }
+       return 0;
+}
+
 /**
  * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
  * @mtd:       mtd info structure
@@ -994,6 +1075,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                        /* Now read the page into the buffer */
                        if (unlikely(ops->mode == MTD_OOB_RAW))
                                ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
+                       else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
+                               ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);
                        else
                                ret = chip->ecc.read_page(mtd, chip, bufpoi);
                        if (ret < 0)
@@ -1001,7 +1084,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 
                        /* Transfer not aligned data */
                        if (!aligned) {
-                               chip->pagebuf = realpage;
+                               if (!NAND_SUBPAGE_READ(chip) && !oob)
+                                       chip->pagebuf = realpage;
                                memcpy(buf, chip->buffers->databuf + col, bytes);
                        }
 
@@ -2521,6 +2605,7 @@ int nand_scan_tail(struct mtd_info *mtd)
                chip->ecc.calculate = nand_calculate_ecc;
                chip->ecc.correct = nand_correct_data;
                chip->ecc.read_page = nand_read_page_swecc;
+               chip->ecc.read_subpage = nand_read_subpage;
                chip->ecc.write_page = nand_write_page_swecc;
                chip->ecc.read_oob = nand_read_oob_std;
                chip->ecc.write_oob = nand_write_oob_std;
index 5e121ceaa59899ea94d964aab94df39845c18520..0b1c48595f1255547aea9eae6e41ba03e47dc05f 100644 (file)
@@ -6,8 +6,6 @@
  *
  *  Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
  *
- * $Id: nand_bbt.c,v 1.36 2005/11/07 11:14:30 gleixner Exp $
- *
  * 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.
index 9003a135e0502089f6a8e44f77f26b129a849375..918a806a8471f7aaa1b68b29e5e401a15737d4a4 100644 (file)
@@ -9,8 +9,6 @@
  *
  * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
  *
- * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $
- *
  * This file 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
index a3e3ab0185d52b6e076f7380279ca6a8caf29cd2..69ee2c90eb0b3499e30c9ce00bdf787c2fb9dd53 100644 (file)
@@ -3,8 +3,6 @@
  *
  *  Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
  *
- * $Id: nand_ids.c,v 1.16 2005/11/07 11:14:31 gleixner Exp $
- *
  * 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.
index bb885d1fcab5e9bbb87a085f0af76a76ea5e88bb..ecd70e2504f6c07eef8f87b824ba1a2d71d02ba6 100644 (file)
@@ -21,8 +21,6 @@
  * 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
- *
- * $Id: nandsim.c,v 1.8 2005/03/19 15:33:56 dedekind Exp $
  */
 
 #include <linux/init.h>
@@ -39,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/random.h>
+#include <asm/div64.h>
 
 /* Default simulator parameters values */
 #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE)  || \
@@ -298,11 +297,11 @@ struct nandsim {
 
        /* NAND flash "geometry" */
        struct nandsin_geometry {
-               uint32_t totsz;     /* total flash size, bytes */
+               uint64_t totsz;     /* total flash size, bytes */
                uint32_t secsz;     /* flash sector (erase block) size, bytes */
                uint pgsz;          /* NAND flash page size, bytes */
                uint oobsz;         /* page OOB area size, bytes */
-               uint32_t totszoob;  /* total flash size including OOB, bytes */
+               uint64_t totszoob;  /* total flash size including OOB, bytes */
                uint pgszoob;       /* page size including OOB , bytes*/
                uint secszoob;      /* sector size including OOB, bytes */
                uint pgnum;         /* total number of pages */
@@ -459,6 +458,12 @@ static char *get_partition_name(int i)
        return kstrdup(buf, GFP_KERNEL);
 }
 
+static u_int64_t divide(u_int64_t n, u_int32_t d)
+{
+       do_div(n, d);
+       return n;
+}
+
 /*
  * Initialize the nandsim structure.
  *
@@ -469,8 +474,8 @@ static int init_nandsim(struct mtd_info *mtd)
        struct nand_chip *chip = (struct nand_chip *)mtd->priv;
        struct nandsim   *ns   = (struct nandsim *)(chip->priv);
        int i, ret = 0;
-       u_int32_t remains;
-       u_int32_t next_offset;
+       u_int64_t remains;
+       u_int64_t next_offset;
 
        if (NS_IS_INITIALIZED(ns)) {
                NS_ERR("init_nandsim: nandsim is already initialized\n");
@@ -487,8 +492,8 @@ static int init_nandsim(struct mtd_info *mtd)
        ns->geom.oobsz    = mtd->oobsize;
        ns->geom.secsz    = mtd->erasesize;
        ns->geom.pgszoob  = ns->geom.pgsz + ns->geom.oobsz;
-       ns->geom.pgnum    = ns->geom.totsz / ns->geom.pgsz;
-       ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz;
+       ns->geom.pgnum    = divide(ns->geom.totsz, ns->geom.pgsz);
+       ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz;
        ns->geom.secshift = ffs(ns->geom.secsz) - 1;
        ns->geom.pgshift  = chip->page_shift;
        ns->geom.oobshift = ffs(ns->geom.oobsz) - 1;
@@ -511,7 +516,7 @@ static int init_nandsim(struct mtd_info *mtd)
        }
 
        if (ns->options & OPT_SMALLPAGE) {
-               if (ns->geom.totsz < (32 << 20)) {
+               if (ns->geom.totsz <= (32 << 20)) {
                        ns->geom.pgaddrbytes  = 3;
                        ns->geom.secaddrbytes = 2;
                } else {
@@ -537,15 +542,16 @@ static int init_nandsim(struct mtd_info *mtd)
        remains = ns->geom.totsz;
        next_offset = 0;
        for (i = 0; i < parts_num; ++i) {
-               unsigned long part = parts[i];
-               if (!part || part > remains / ns->geom.secsz) {
+               u_int64_t part_sz = (u_int64_t)parts[i] * ns->geom.secsz;
+
+               if (!part_sz || part_sz > remains) {
                        NS_ERR("bad partition size.\n");
                        ret = -EINVAL;
                        goto error;
                }
                ns->partitions[i].name   = get_partition_name(i);
                ns->partitions[i].offset = next_offset;
-               ns->partitions[i].size   = part * ns->geom.secsz;
+               ns->partitions[i].size   = part_sz;
                next_offset += ns->partitions[i].size;
                remains -= ns->partitions[i].size;
        }
@@ -573,7 +579,7 @@ static int init_nandsim(struct mtd_info *mtd)
        if (ns->busw == 16)
                NS_WARN("16-bit flashes support wasn't tested\n");
 
-       printk("flash size: %u MiB\n",          ns->geom.totsz >> 20);
+       printk("flash size: %llu MiB\n",        ns->geom.totsz >> 20);
        printk("page size: %u bytes\n",         ns->geom.pgsz);
        printk("OOB area size: %u bytes\n",     ns->geom.oobsz);
        printk("sector size: %u KiB\n",         ns->geom.secsz >> 10);
@@ -583,7 +589,7 @@ static int init_nandsim(struct mtd_info *mtd)
        printk("bits in sector size: %u\n",     ns->geom.secshift);
        printk("bits in page size: %u\n",       ns->geom.pgshift);
        printk("bits in OOB size: %u\n",        ns->geom.oobshift);
-       printk("flash size with OOB: %u KiB\n", ns->geom.totszoob >> 10);
+       printk("flash size with OOB: %llu KiB\n", ns->geom.totszoob >> 10);
        printk("page address bytes: %u\n",      ns->geom.pgaddrbytes);
        printk("sector address bytes: %u\n",    ns->geom.secaddrbytes);
        printk("options: %#x\n",                ns->options);
@@ -825,7 +831,7 @@ static int setup_wear_reporting(struct mtd_info *mtd)
 
        if (!rptwear)
                return 0;
-       wear_eb_count = mtd->size / mtd->erasesize;
+       wear_eb_count = divide(mtd->size, mtd->erasesize);
        mem = wear_eb_count * sizeof(unsigned long);
        if (mem / sizeof(unsigned long) != wear_eb_count) {
                NS_ERR("Too many erase blocks for wear reporting\n");
@@ -2013,7 +2019,7 @@ static int __init ns_init_module(void)
        }
 
        if (overridesize) {
-               u_int32_t new_size = nsmtd->erasesize << overridesize;
+               u_int64_t new_size = (u_int64_t)nsmtd->erasesize << overridesize;
                if (new_size >> overridesize != nsmtd->erasesize) {
                        NS_ERR("overridesize is too big\n");
                        goto err_exit;
@@ -2021,7 +2027,8 @@ static int __init ns_init_module(void)
                /* N.B. This relies on nand_scan not doing anything with the size before we change it */
                nsmtd->size = new_size;
                chip->chipsize = new_size;
-               chip->chip_shift = ffs(new_size) - 1;
+               chip->chip_shift = ffs(nsmtd->erasesize) + overridesize - 1;
+               chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
        }
 
        if ((retval = setup_wear_reporting(nsmtd)) != 0)
index 082073acf20fc51b6a252623bca2d7cc59ba456b..cc86584318512acc1b00547d3d87404bf95a98a0 100644 (file)
@@ -6,8 +6,6 @@
  *  Derived from drivers/mtd/nand/edb7312.c
  *
  *
- * $Id: ppchameleonevb.c,v 1.7 2005/11/07 11:14:31 gleixner Exp $
- *
  * 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.
index 26f88215bc47d48c12ff9768da72829366d4ac76..a033c4cd8e16e8b7a6d0b8225eedc78c8df0e690 100644 (file)
@@ -6,8 +6,6 @@
  *  Derived from drivers/mtd/nand/spia.c
  *       Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
  *
- * $Id: rtc_from4.c,v 1.10 2005/11/07 11:14:31 gleixner Exp $
- *
  * 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.
index b34a460ab67915afe3812d6ced1410cfff6c16b7..556139ed1fdf8b50919dfa078fe74a98626008d6 100644 (file)
@@ -1,26 +1,10 @@
 /* linux/drivers/mtd/nand/s3c2410.c
  *
- * Copyright (c) 2004,2005 Simtec Electronics
- *     http://www.simtec.co.uk/products/SWLINUX/
+ * Copyright Â© 2004-2008 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
  *     Ben Dooks <ben@simtec.co.uk>
  *
- * Samsung S3C2410/S3C240 NAND driver
- *
- * Changelog:
- *     21-Sep-2004  BJD  Initial version
- *     23-Sep-2004  BJD  Multiple device support
- *     28-Sep-2004  BJD  Fixed ECC placement for Hardware mode
- *     12-Oct-2004  BJD  Fixed errors in use of platform data
- *     18-Feb-2005  BJD  Fix sparse errors
- *     14-Mar-2005  BJD  Applied tglx's code reduction patch
- *     02-May-2005  BJD  Fixed s3c2440 support
- *     02-May-2005  BJD  Reduced hwcontrol decode
- *     20-Jun-2005  BJD  Updated s3c2440 support, fixed timing bug
- *     08-Jul-2005  BJD  Fix OOPS when no platform data supplied
- *     20-Oct-2005  BJD  Fix timing calculation bug
- *     14-Jan-2006  BJD  Allow clock to be stopped when idle
- *
- * $Id: s3c2410.c,v 1.23 2006/04/01 18:06:29 bjd Exp $
+ * Samsung S3C2410/S3C2440/S3C2412 NAND driver
  *
  * 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
@@ -52,6 +36,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/cpufreq.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -120,8 +105,13 @@ struct s3c2410_nand_info {
        int                             sel_bit;
        int                             mtd_count;
        unsigned long                   save_sel;
+       unsigned long                   clk_rate;
 
        enum s3c_cpu_type               cpu_type;
+
+#ifdef CONFIG_CPU_FREQ
+       struct notifier_block   freq_transition;
+#endif
 };
 
 /* conversion functions */
@@ -179,17 +169,18 @@ static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
 
 /* controller setup */
 
-static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
-                              struct platform_device *pdev)
+static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
 {
-       struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
-       unsigned long clkrate = clk_get_rate(info->clk);
+       struct s3c2410_platform_nand *plat = info->platform;
        int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
        int tacls, twrph0, twrph1;
-       unsigned long cfg = 0;
+       unsigned long clkrate = clk_get_rate(info->clk);
+       unsigned long set, cfg, mask;
+       unsigned long flags;
 
        /* calculate the timing information for the controller */
 
+       info->clk_rate = clkrate;
        clkrate /= 1000;        /* turn clock into kHz for ease of use */
 
        if (plat != NULL) {
@@ -211,28 +202,69 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
        dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
               tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
 
+       switch (info->cpu_type) {
+       case TYPE_S3C2410:
+               mask = (S3C2410_NFCONF_TACLS(3) |
+                       S3C2410_NFCONF_TWRPH0(7) |
+                       S3C2410_NFCONF_TWRPH1(7));
+               set = S3C2410_NFCONF_EN;
+               set |= S3C2410_NFCONF_TACLS(tacls - 1);
+               set |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
+               set |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
+               break;
+
+       case TYPE_S3C2440:
+       case TYPE_S3C2412:
+               mask = (S3C2410_NFCONF_TACLS(tacls_max - 1) |
+                       S3C2410_NFCONF_TWRPH0(7) |
+                       S3C2410_NFCONF_TWRPH1(7));
+
+               set = S3C2440_NFCONF_TACLS(tacls - 1);
+               set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
+               set |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
+               break;
+
+       default:
+               /* keep compiler happy */
+               mask = 0;
+               set = 0;
+               BUG();
+       }
+
+       dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
+
+       local_irq_save(flags);
+
+       cfg = readl(info->regs + S3C2410_NFCONF);
+       cfg &= ~mask;
+       cfg |= set;
+       writel(cfg, info->regs + S3C2410_NFCONF);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
+{
+       int ret;
+
+       ret = s3c2410_nand_setrate(info);
+       if (ret < 0)
+               return ret;
+
        switch (info->cpu_type) {
        case TYPE_S3C2410:
-               cfg = S3C2410_NFCONF_EN;
-               cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
-               cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
-               cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
+       default:
                break;
 
        case TYPE_S3C2440:
        case TYPE_S3C2412:
-               cfg = S3C2440_NFCONF_TACLS(tacls - 1);
-               cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
-               cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
-
                /* enable the controller and de-assert nFCE */
 
                writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
        }
 
-       dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
-
-       writel(cfg, info->regs + S3C2410_NFCONF);
        return 0;
 }
 
@@ -513,6 +545,52 @@ static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int
        writesl(info->regs + S3C2440_NFDATA, buf, len / 4);
 }
 
+/* cpufreq driver support */
+
+#ifdef CONFIG_CPU_FREQ
+
+static int s3c2410_nand_cpufreq_transition(struct notifier_block *nb,
+                                         unsigned long val, void *data)
+{
+       struct s3c2410_nand_info *info;
+       unsigned long newclk;
+
+       info = container_of(nb, struct s3c2410_nand_info, freq_transition);
+       newclk = clk_get_rate(info->clk);
+
+       if ((val == CPUFREQ_POSTCHANGE && newclk < info->clk_rate) ||
+           (val == CPUFREQ_PRECHANGE && newclk > info->clk_rate)) {
+               s3c2410_nand_setrate(info);
+       }
+
+       return 0;
+}
+
+static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
+{
+       info->freq_transition.notifier_call = s3c2410_nand_cpufreq_transition;
+
+       return cpufreq_register_notifier(&info->freq_transition,
+                                        CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
+{
+       cpufreq_unregister_notifier(&info->freq_transition,
+                                   CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
+{
+       return 0;
+}
+
+static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
+{
+}
+#endif
+
 /* device management functions */
 
 static int s3c2410_nand_remove(struct platform_device *pdev)
@@ -524,9 +602,10 @@ static int s3c2410_nand_remove(struct platform_device *pdev)
        if (info == NULL)
                return 0;
 
-       /* first thing we need to do is release all our mtds
-        * and their partitions, then go through freeing the
-        * resources used
+       s3c2410_nand_cpufreq_deregister(info);
+
+       /* Release all our mtds  and their partitions, then go through
+        * freeing the resources used
         */
 
        if (info->mtds != NULL) {
@@ -691,7 +770,8 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
 {
        struct nand_chip *chip = &nmtd->chip;
 
-       printk("%s: chip %p: %d\n", __func__, chip, chip->page_shift);
+       dev_dbg(info->device, "chip %p => page shift %d\n",
+               chip, chip->page_shift);
 
        if (hardware_ecc) {
                /* change the behaviour depending on wether we are using
@@ -784,7 +864,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
 
        /* initialise the hardware */
 
-       err = s3c2410_nand_inithw(info, pdev);
+       err = s3c2410_nand_inithw(info);
        if (err != 0)
                goto exit_error;
 
@@ -827,6 +907,12 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
                        sets++;
        }
 
+       err = s3c2410_nand_cpufreq_register(info);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to init cpufreq support\n");
+               goto exit_error;
+       }
+
        if (allow_clk_stop(info)) {
                dev_info(&pdev->dev, "clock idle support enabled\n");
                clk_disable(info->clk);
@@ -874,7 +960,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
 
        if (info) {
                clk_enable(info->clk);
-               s3c2410_nand_inithw(info, dev);
+               s3c2410_nand_inithw(info);
 
                /* Restore the state of the nFCE line. */
 
index 033f8800b1e69224d81c15dd670bc24e95190a7f..6dba2fb66ae5e32536b11757f0289af9002f47a1 100644 (file)
@@ -3,8 +3,6 @@
  *
  *  Copyright (C) 2004 Richard Purdie
  *
- *  $Id: sharpsl.c,v 1.7 2005/11/07 11:14:31 gleixner Exp $
- *
  *  Based on Sharp's NAND driver sharp_sl.c
  *
  * This program is free software; you can redistribute it and/or modify
index 1f6d429b158319c6db75f710e8daad63bbe48588..0cc6d0acb8febdcde011545e5022bb950e3ccf0e 100644 (file)
@@ -8,8 +8,6 @@
  *                     to controllines (due to change in nand.c)
  *                     page_cache added
  *
- * $Id: spia.c,v 1.25 2005/11/07 11:14:31 gleixner Exp $
- *
  * 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.
index f9e2d4a0ab8c661bba8dec6e46f1e194433eecfd..bbf492e6830dafde45f20b2fe70032ccc3da4f20 100644 (file)
@@ -14,8 +14,6 @@
  *  Overview:
  *   This is a device driver for the NAND flash device found on the
  *   TI fido board. It supports 32MiB and 64MiB cards
- *
- * $Id: toto.c,v 1.5 2005/11/07 11:14:31 gleixner Exp $
  */
 
 #include <linux/slab.h>
index f40081069ab2c6fa0f2a5705eaad7c9e698c28af..807a72752eeb035885b1f633d77d7f4e08e4ee6e 100644 (file)
@@ -9,8 +9,6 @@
  * Derived from drivers/mtd/nand/autcpu12.c
  *   Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
  *
- * $Id: ts7250.c,v 1.4 2004/12/30 22:02:07 joff Exp $
- *
  * 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.
index 0c9ce19ea27a3476f44384749476822b3c311cfa..320b929abe795ea00eb5bf4c130f6db966d32893 100644 (file)
@@ -1,7 +1,6 @@
 /* Linux driver for NAND Flash Translation Layer      */
 /* (c) 1999 Machine Vision Holdings, Inc.             */
 /* Author: David Woodhouse <dwmw2@infradead.org>      */
-/* $Id: nftlcore.c,v 1.98 2005/11/07 11:14:21 gleixner Exp $ */
 
 /*
   The contents of this file are distributed under the GNU General
@@ -803,12 +802,8 @@ static struct mtd_blktrans_ops nftl_tr = {
        .owner          = THIS_MODULE,
 };
 
-extern char nftlmountrev[];
-
 static int __init init_nftl(void)
 {
-       printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.98 $, nftlmount.c %s\n", nftlmountrev);
-
        return register_mtd_blktrans(&nftl_tr);
 }
 
index 345e6eff89ce5929c3548d1874b6363b102ae554..ccc4f209fbb5c17985ba5e264b0a6ddde9824fa3 100644 (file)
@@ -4,8 +4,6 @@
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
  * Copyright (C) 2000 Netgem S.A.
  *
- * $Id: nftlmount.c,v 1.41 2005/11/07 11:14:21 gleixner Exp $
- *
  * 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
@@ -31,8 +29,6 @@
 
 #define SECTORSIZE 512
 
-char nftlmountrev[]="$Revision: 1.41 $";
-
 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
  *     various device information of the NFTL partition and Bad Unit Table. Update
  *     the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
index 5d7965f7e9ce6a3f8232a53cb2c0e2a243f13379..926cf3a4135d1ca84094c40d018803709d059334 100644 (file)
@@ -325,28 +325,11 @@ static int onenand_wait(struct mtd_info *mtd, int state)
 
        ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
 
-       if (ctrl & ONENAND_CTRL_ERROR) {
-               printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl);
-               if (ctrl & ONENAND_CTRL_LOCK)
-                       printk(KERN_ERR "onenand_wait: it's locked error.\n");
-               if (state == FL_READING) {
-                       /*
-                        * A power loss while writing can result in a page
-                        * becoming unreadable.  When the device is mounted
-                        * again, reading that page gives controller errors.
-                        * Upper level software like JFFS2 treat -EIO as fatal,
-                        * refusing to mount at all.  That means it is necessary
-                        * to treat the error as an ECC error to allow recovery.
-                        * Note that typically in this case, the eraseblock can
-                        * still be erased and rewritten i.e. it has not become
-                        * a bad block.
-                        */
-                       mtd->ecc_stats.failed++;
-                       return -EBADMSG;
-               }
-               return -EIO;
-       }
-
+       /*
+        * In the Spec. it checks the controller status first
+        * However if you get the correct information in case of
+        * power off recovery (POR) test, it should read ECC status first
+        */
        if (interrupt & ONENAND_INT_READ) {
                int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
                if (ecc) {
@@ -364,6 +347,15 @@ static int onenand_wait(struct mtd_info *mtd, int state)
                return -EIO;
        }
 
+       /* If there's controller error, it's a real error */
+       if (ctrl & ONENAND_CTRL_ERROR) {
+               printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n",
+                       ctrl);
+               if (ctrl & ONENAND_CTRL_LOCK)
+                       printk(KERN_ERR "onenand_wait: it's locked error.\n");
+               return -EIO;
+       }
+
        return 0;
 }
 
@@ -1135,22 +1127,26 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state)
        interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
        ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
 
-       /* Initial bad block case: 0x2400 or 0x0400 */
-       if (ctrl & ONENAND_CTRL_ERROR) {
-               printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl);
-               return ONENAND_BBT_READ_ERROR;
-       }
-
        if (interrupt & ONENAND_INT_READ) {
                int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
-               if (ecc & ONENAND_ECC_2BIT_ALL)
+               if (ecc & ONENAND_ECC_2BIT_ALL) {
+                       printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x"
+                               ", controller error 0x%04x\n", ecc, ctrl);
                        return ONENAND_BBT_READ_ERROR;
+               }
        } else {
                printk(KERN_ERR "onenand_bbt_wait: read timeout!"
                        "ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
                return ONENAND_BBT_READ_FATAL_ERROR;
        }
 
+       /* Initial bad block case: 0x2400 or 0x0400 */
+       if (ctrl & ONENAND_CTRL_ERROR) {
+               printk(KERN_DEBUG "onenand_bbt_wait: "
+                       "controller error = 0x%04x\n", ctrl);
+               return ONENAND_BBT_READ_ERROR;
+       }
+
        return 0;
 }
 
index c5030f94f04e180adeea6eda0af5f0b8994e83cb..2d600a1bf2aa76e804679e2df284d8b7f9be2742 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: redboot.c,v 1.21 2006/03/30 18:34:37 bjd Exp $
- *
  * Parse RedBoot-style Flash Image System (FIS) tables and
  * produce a Linux partition array to match.
  */
index c84e45465499dba5ad0117c1fc213b4104705171..e538c0a72abb0d531ddd992a559671d7020a7f5f 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright (C) 2005  Sean Young <sean@mess.org>
  *
- * $Id: rfd_ftl.c,v 1.8 2006/01/15 12:51:44 sean Exp $
- *
  * This type of flash translation layer (FTL) is used by the Embedded BIOS
  * by General Software. It is known as the Resident Flash Disk (RFD), see:
  *
index 961416ac06167350bf689c631a85b0ece7f067ec..c7630a2283109a39d8289cf114f748bd9770cd8f 100644 (file)
  * @name: MTD device name or number string
  * @vid_hdr_offs: VID header offset
  */
-struct mtd_dev_param
-{
+struct mtd_dev_param {
        char name[MTD_PARAM_LEN_MAX];
        int vid_hdr_offs;
 };
 
 /* Numbers of elements set in the @mtd_dev_param array */
-static int mtd_devs = 0;
+static int mtd_devs;
 
 /* MTD devices specification parameters */
 static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];
@@ -160,8 +159,7 @@ void ubi_put_device(struct ubi_device *ubi)
 }
 
 /**
- * ubi_get_by_major - get UBI device description object by character device
- *                    major number.
+ * ubi_get_by_major - get UBI device by character device major number.
  * @major: major number
  *
  * This function is similar to 'ubi_get_device()', but it searches the device
@@ -354,16 +352,35 @@ static void kill_volumes(struct ubi_device *ubi)
                        ubi_free_volume(ubi, ubi->volumes[i]);
 }
 
+/**
+ * free_user_volumes - free all user volumes.
+ * @ubi: UBI device description object
+ *
+ * Normally the volumes are freed at the release function of the volume device
+ * objects. However, on error paths the volumes have to be freed before the
+ * device objects have been initialized.
+ */
+static void free_user_volumes(struct ubi_device *ubi)
+{
+       int i;
+
+       for (i = 0; i < ubi->vtbl_slots; i++)
+               if (ubi->volumes[i]) {
+                       kfree(ubi->volumes[i]->eba_tbl);
+                       kfree(ubi->volumes[i]);
+               }
+}
+
 /**
  * uif_init - initialize user interfaces for an UBI device.
  * @ubi: UBI device description object
  *
  * This function returns zero in case of success and a negative error code in
- * case of failure.
+ * case of failure. Note, this function destroys all volumes if it failes.
  */
 static int uif_init(struct ubi_device *ubi)
 {
-       int i, err;
+       int i, err, do_free = 0;
        dev_t dev;
 
        sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
@@ -384,7 +401,7 @@ static int uif_init(struct ubi_device *ubi)
 
        ubi_assert(MINOR(dev) == 0);
        cdev_init(&ubi->cdev, &ubi_cdev_operations);
-       dbg_msg("%s major is %u", ubi->ubi_name, MAJOR(dev));
+       dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev));
        ubi->cdev.owner = THIS_MODULE;
 
        err = cdev_add(&ubi->cdev, dev, 1);
@@ -410,10 +427,13 @@ static int uif_init(struct ubi_device *ubi)
 
 out_volumes:
        kill_volumes(ubi);
+       do_free = 0;
 out_sysfs:
        ubi_sysfs_close(ubi);
        cdev_del(&ubi->cdev);
 out_unreg:
+       if (do_free)
+               free_user_volumes(ubi);
        unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
        ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err);
        return err;
@@ -422,6 +442,10 @@ out_unreg:
 /**
  * uif_close - close user interfaces for an UBI device.
  * @ubi: UBI device description object
+ *
+ * Note, since this function un-registers UBI volume device objects (@vol->dev),
+ * the memory allocated voe the volumes is freed as well (in the release
+ * function).
  */
 static void uif_close(struct ubi_device *ubi)
 {
@@ -431,6 +455,21 @@ static void uif_close(struct ubi_device *ubi)
        unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
 }
 
+/**
+ * free_internal_volumes - free internal volumes.
+ * @ubi: UBI device description object
+ */
+static void free_internal_volumes(struct ubi_device *ubi)
+{
+       int i;
+
+       for (i = ubi->vtbl_slots;
+            i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
+               kfree(ubi->volumes[i]->eba_tbl);
+               kfree(ubi->volumes[i]);
+       }
+}
+
 /**
  * attach_by_scanning - attach an MTD device using scanning method.
  * @ubi: UBI device descriptor
@@ -475,6 +514,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
 out_wl:
        ubi_wl_close(ubi);
 out_vtbl:
+       free_internal_volumes(ubi);
        vfree(ubi->vtbl);
 out_si:
        ubi_scan_destroy_si(si);
@@ -482,7 +522,7 @@ out_si:
 }
 
 /**
- * io_init - initialize I/O unit for a given UBI device.
+ * io_init - initialize I/O sub-system for a given UBI device.
  * @ubi: UBI device description object
  *
  * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are
@@ -530,7 +570,11 @@ static int io_init(struct ubi_device *ubi)
        ubi->min_io_size = ubi->mtd->writesize;
        ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
 
-       /* Make sure minimal I/O unit is power of 2 */
+       /*
+        * Make sure minimal I/O unit is power of 2. Note, there is no
+        * fundamental reason for this assumption. It is just an optimization
+        * which allows us to avoid costly division operations.
+        */
        if (!is_power_of_2(ubi->min_io_size)) {
                ubi_err("min. I/O unit (%d) is not power of 2",
                        ubi->min_io_size);
@@ -581,7 +625,7 @@ static int io_init(struct ubi_device *ubi)
        if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE ||
            ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||
            ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||
-           ubi->leb_start % ubi->min_io_size) {
+           ubi->leb_start & (ubi->min_io_size - 1)) {
                ubi_err("bad VID header (%d) or data offsets (%d)",
                        ubi->vid_hdr_offset, ubi->leb_start);
                return -EINVAL;
@@ -646,7 +690,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
 
        /*
         * Clear the auto-resize flag in the volume in-memory copy of the
-        * volume table, and 'ubi_resize_volume()' will propogate this change
+        * volume table, and 'ubi_resize_volume()' will propagate this change
         * to the flash.
         */
        ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG;
@@ -655,7 +699,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
                struct ubi_vtbl_record vtbl_rec;
 
                /*
-                * No avalilable PEBs to re-size the volume, clear the flag on
+                * No available PEBs to re-size the volume, clear the flag on
                 * flash and exit.
                 */
                memcpy(&vtbl_rec, &ubi->vtbl[vol_id],
@@ -682,13 +726,13 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
 
 /**
  * ubi_attach_mtd_dev - attach an MTD device.
- * @mtd_dev: MTD device description object
+ * @mtd: MTD device description object
  * @ubi_num: number to assign to the new UBI device
  * @vid_hdr_offset: VID header offset
  *
  * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number
  * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
- * which case this function finds a vacant device nubert and assings it
+ * which case this function finds a vacant device number and assigns it
  * automatically. Returns the new UBI device number in case of success and a
  * negative error code in case of failure.
  *
@@ -698,7 +742,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
 int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 {
        struct ubi_device *ubi;
-       int i, err;
+       int i, err, do_free = 1;
 
        /*
         * Check if we already have the same MTD device attached.
@@ -735,7 +779,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
                        if (!ubi_devices[ubi_num])
                                break;
                if (ubi_num == UBI_MAX_DEVICES) {
-                       dbg_err("only %d UBI devices may be created", UBI_MAX_DEVICES);
+                       dbg_err("only %d UBI devices may be created",
+                               UBI_MAX_DEVICES);
                        return -ENFILE;
                }
        } else {
@@ -760,6 +805,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 
        mutex_init(&ubi->buf_mutex);
        mutex_init(&ubi->ckvol_mutex);
+       mutex_init(&ubi->mult_mutex);
        mutex_init(&ubi->volumes_mutex);
        spin_lock_init(&ubi->volumes_lock);
 
@@ -798,7 +844,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 
        err = uif_init(ubi);
        if (err)
-               goto out_detach;
+               goto out_nofree;
 
        ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
        if (IS_ERR(ubi->bgt_thread)) {
@@ -824,20 +870,22 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
                ubi->beb_rsvd_pebs);
        ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
 
-       /* Enable the background thread */
-       if (!DBG_DISABLE_BGT) {
+       if (!DBG_DISABLE_BGT)
                ubi->thread_enabled = 1;
-               wake_up_process(ubi->bgt_thread);
-       }
+       wake_up_process(ubi->bgt_thread);
 
        ubi_devices[ubi_num] = ubi;
        return ubi_num;
 
 out_uif:
        uif_close(ubi);
+out_nofree:
+       do_free = 0;
 out_detach:
-       ubi_eba_close(ubi);
        ubi_wl_close(ubi);
+       if (do_free)
+               free_user_volumes(ubi);
+       free_internal_volumes(ubi);
        vfree(ubi->vtbl);
 out_free:
        vfree(ubi->peb_buf1);
@@ -899,8 +947,8 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
                kthread_stop(ubi->bgt_thread);
 
        uif_close(ubi);
-       ubi_eba_close(ubi);
        ubi_wl_close(ubi);
+       free_internal_volumes(ubi);
        vfree(ubi->vtbl);
        put_mtd_device(ubi->mtd);
        vfree(ubi->peb_buf1);
@@ -1044,8 +1092,7 @@ static void __exit ubi_exit(void)
 module_exit(ubi_exit);
 
 /**
- * bytes_str_to_int - convert a string representing number of bytes to an
- * integer.
+ * bytes_str_to_int - convert a number of bytes string into an integer.
  * @str: the string to convert
  *
  * This function returns positive resulting integer in case of success and a
index 89193ba9451e78e771740724fbb98ff04135aeb7..03c759b4eeb5e852b192794f242020bc45792c22 100644 (file)
@@ -39,9 +39,9 @@
 #include <linux/stat.h>
 #include <linux/ioctl.h>
 #include <linux/capability.h>
+#include <linux/uaccess.h>
 #include <linux/smp_lock.h>
 #include <mtd/ubi-user.h>
-#include <asm/uaccess.h>
 #include <asm/div64.h>
 #include "ubi.h"
 
@@ -116,7 +116,7 @@ static int vol_cdev_open(struct inode *inode, struct file *file)
        else
                mode = UBI_READONLY;
 
-       dbg_msg("open volume %d, mode %d", vol_id, mode);
+       dbg_gen("open volume %d, mode %d", vol_id, mode);
 
        desc = ubi_open_volume(ubi_num, vol_id, mode);
        unlock_kernel();
@@ -132,7 +132,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
        struct ubi_volume_desc *desc = file->private_data;
        struct ubi_volume *vol = desc->vol;
 
-       dbg_msg("release volume %d, mode %d", vol->vol_id, desc->mode);
+       dbg_gen("release volume %d, mode %d", vol->vol_id, desc->mode);
 
        if (vol->updating) {
                ubi_warn("update of volume %d not finished, volume is damaged",
@@ -141,7 +141,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
                vol->updating = 0;
                vfree(vol->upd_buf);
        } else if (vol->changing_leb) {
-               dbg_msg("only %lld of %lld bytes received for atomic LEB change"
+               dbg_gen("only %lld of %lld bytes received for atomic LEB change"
                        " for volume %d:%d, cancel", vol->upd_received,
                        vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id);
                vol->changing_leb = 0;
@@ -183,7 +183,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
                return -EINVAL;
        }
 
-       dbg_msg("seek volume %d, offset %lld, origin %d, new offset %lld",
+       dbg_gen("seek volume %d, offset %lld, origin %d, new offset %lld",
                vol->vol_id, offset, origin, new_offset);
 
        file->f_pos = new_offset;
@@ -201,7 +201,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
        void *tbuf;
        uint64_t tmp;
 
-       dbg_msg("read %zd bytes from offset %lld of volume %d",
+       dbg_gen("read %zd bytes from offset %lld of volume %d",
                count, *offp, vol->vol_id);
 
        if (vol->updating) {
@@ -216,7 +216,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
                return 0;
 
        if (vol->corrupted)
-               dbg_msg("read from corrupted volume %d", vol->vol_id);
+               dbg_gen("read from corrupted volume %d", vol->vol_id);
 
        if (*offp + count > vol->used_bytes)
                count_save = count = vol->used_bytes - *offp;
@@ -285,7 +285,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
        char *tbuf;
        uint64_t tmp;
 
-       dbg_msg("requested: write %zd bytes to offset %lld of volume %u",
+       dbg_gen("requested: write %zd bytes to offset %lld of volume %u",
                count, *offp, vol->vol_id);
 
        if (vol->vol_type == UBI_STATIC_VOLUME)
@@ -295,7 +295,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
        off = do_div(tmp, vol->usable_leb_size);
        lnum = tmp;
 
-       if (off % ubi->min_io_size) {
+       if (off & (ubi->min_io_size - 1)) {
                dbg_err("unaligned position");
                return -EINVAL;
        }
@@ -304,7 +304,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
                count_save = count = vol->used_bytes - *offp;
 
        /* We can write only in fractions of the minimum I/O unit */
-       if (count % ubi->min_io_size) {
+       if (count & (ubi->min_io_size - 1)) {
                dbg_err("unaligned write length");
                return -EINVAL;
        }
@@ -352,7 +352,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
 }
 
 #else
-#define vol_cdev_direct_write(file, buf, count, offp) -EPERM
+#define vol_cdev_direct_write(file, buf, count, offp) (-EPERM)
 #endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */
 
 static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
@@ -437,7 +437,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
                        break;
                }
 
-               rsvd_bytes = vol->reserved_pebs * (ubi->leb_size-vol->data_pad);
+               rsvd_bytes = (long long)vol->reserved_pebs *
+                                       ubi->leb_size-vol->data_pad;
                if (bytes < 0 || bytes > rsvd_bytes) {
                        err = -EINVAL;
                        break;
@@ -513,7 +514,7 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
                        break;
                }
 
-               dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
+               dbg_gen("erase LEB %d:%d", vol->vol_id, lnum);
                err = ubi_eba_unmap_leb(ubi, vol, lnum);
                if (err)
                        break;
@@ -564,7 +565,7 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
        if (req->alignment > ubi->leb_size)
                goto bad;
 
-       n = req->alignment % ubi->min_io_size;
+       n = req->alignment & (ubi->min_io_size - 1);
        if (req->alignment != 1 && n)
                goto bad;
 
@@ -573,6 +574,10 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
                goto bad;
        }
 
+       n = strnlen(req->name, req->name_len + 1);
+       if (n != req->name_len)
+               goto bad;
+
        return 0;
 
 bad:
@@ -600,6 +605,166 @@ static int verify_rsvol_req(const struct ubi_device *ubi,
        return 0;
 }
 
+/**
+ * rename_volumes - rename UBI volumes.
+ * @ubi: UBI device description object
+ * @req: volumes re-name request
+ *
+ * This is a helper function for the volume re-name IOCTL which validates the
+ * the request, opens the volume and calls corresponding volumes management
+ * function. Returns zero in case of success and a negative error code in case
+ * of failure.
+ */
+static int rename_volumes(struct ubi_device *ubi,
+                         struct ubi_rnvol_req *req)
+{
+       int i, n, err;
+       struct list_head rename_list;
+       struct ubi_rename_entry *re, *re1;
+
+       if (req->count < 0 || req->count > UBI_MAX_RNVOL)
+               return -EINVAL;
+
+       if (req->count == 0)
+               return 0;
+
+       /* Validate volume IDs and names in the request */
+       for (i = 0; i < req->count; i++) {
+               if (req->ents[i].vol_id < 0 ||
+                   req->ents[i].vol_id >= ubi->vtbl_slots)
+                       return -EINVAL;
+               if (req->ents[i].name_len < 0)
+                       return -EINVAL;
+               if (req->ents[i].name_len > UBI_VOL_NAME_MAX)
+                       return -ENAMETOOLONG;
+               req->ents[i].name[req->ents[i].name_len] = '\0';
+               n = strlen(req->ents[i].name);
+               if (n != req->ents[i].name_len)
+                       err = -EINVAL;
+       }
+
+       /* Make sure volume IDs and names are unique */
+       for (i = 0; i < req->count - 1; i++) {
+               for (n = i + 1; n < req->count; n++) {
+                       if (req->ents[i].vol_id == req->ents[n].vol_id) {
+                               dbg_err("duplicated volume id %d",
+                                       req->ents[i].vol_id);
+                               return -EINVAL;
+                       }
+                       if (!strcmp(req->ents[i].name, req->ents[n].name)) {
+                               dbg_err("duplicated volume name \"%s\"",
+                                       req->ents[i].name);
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       /* Create the re-name list */
+       INIT_LIST_HEAD(&rename_list);
+       for (i = 0; i < req->count; i++) {
+               int vol_id = req->ents[i].vol_id;
+               int name_len = req->ents[i].name_len;
+               const char *name = req->ents[i].name;
+
+               re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL);
+               if (!re) {
+                       err = -ENOMEM;
+                       goto out_free;
+               }
+
+               re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE);
+               if (IS_ERR(re->desc)) {
+                       err = PTR_ERR(re->desc);
+                       dbg_err("cannot open volume %d, error %d", vol_id, err);
+                       kfree(re);
+                       goto out_free;
+               }
+
+               /* Skip this re-naming if the name does not really change */
+               if (re->desc->vol->name_len == name_len &&
+                   !memcmp(re->desc->vol->name, name, name_len)) {
+                       ubi_close_volume(re->desc);
+                       kfree(re);
+                       continue;
+               }
+
+               re->new_name_len = name_len;
+               memcpy(re->new_name, name, name_len);
+               list_add_tail(&re->list, &rename_list);
+               dbg_msg("will rename volume %d from \"%s\" to \"%s\"",
+                       vol_id, re->desc->vol->name, name);
+       }
+
+       if (list_empty(&rename_list))
+               return 0;
+
+       /* Find out the volumes which have to be removed */
+       list_for_each_entry(re, &rename_list, list) {
+               struct ubi_volume_desc *desc;
+               int no_remove_needed = 0;
+
+               /*
+                * Volume @re->vol_id is going to be re-named to
+                * @re->new_name, while its current name is @name. If a volume
+                * with name @re->new_name currently exists, it has to be
+                * removed, unless it is also re-named in the request (@req).
+                */
+               list_for_each_entry(re1, &rename_list, list) {
+                       if (re->new_name_len == re1->desc->vol->name_len &&
+                           !memcmp(re->new_name, re1->desc->vol->name,
+                                   re1->desc->vol->name_len)) {
+                               no_remove_needed = 1;
+                               break;
+                       }
+               }
+
+               if (no_remove_needed)
+                       continue;
+
+               /*
+                * It seems we need to remove volume with name @re->new_name,
+                * if it exists.
+                */
+               desc = ubi_open_volume_nm(ubi->ubi_num, re->new_name, UBI_EXCLUSIVE);
+               if (IS_ERR(desc)) {
+                       err = PTR_ERR(desc);
+                       if (err == -ENODEV)
+                               /* Re-naming into a non-existing volume name */
+                               continue;
+
+                       /* The volume exists but busy, or an error occurred */
+                       dbg_err("cannot open volume \"%s\", error %d",
+                               re->new_name, err);
+                       goto out_free;
+               }
+
+               re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL);
+               if (!re) {
+                       err = -ENOMEM;
+                       ubi_close_volume(desc);
+                       goto out_free;
+               }
+
+               re->remove = 1;
+               re->desc = desc;
+               list_add(&re->list, &rename_list);
+               dbg_msg("will remove volume %d, name \"%s\"",
+                       re->desc->vol->vol_id, re->desc->vol->name);
+       }
+
+       mutex_lock(&ubi->volumes_mutex);
+       err = ubi_rename_volumes(ubi, &rename_list);
+       mutex_unlock(&ubi->volumes_mutex);
+
+out_free:
+       list_for_each_entry_safe(re, re1, &rename_list, list) {
+               ubi_close_volume(re->desc);
+               list_del(&re->list);
+               kfree(re);
+       }
+       return err;
+}
+
 static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
                          unsigned int cmd, unsigned long arg)
 {
@@ -621,19 +786,18 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
        {
                struct ubi_mkvol_req req;
 
-               dbg_msg("create volume");
+               dbg_gen("create volume");
                err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req));
                if (err) {
                        err = -EFAULT;
                        break;
                }
 
+               req.name[req.name_len] = '\0';
                err = verify_mkvol_req(ubi, &req);
                if (err)
                        break;
 
-               req.name[req.name_len] = '\0';
-
                mutex_lock(&ubi->volumes_mutex);
                err = ubi_create_volume(ubi, &req);
                mutex_unlock(&ubi->volumes_mutex);
@@ -652,7 +816,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
        {
                int vol_id;
 
-               dbg_msg("remove volume");
+               dbg_gen("remove volume");
                err = get_user(vol_id, (__user int32_t *)argp);
                if (err) {
                        err = -EFAULT;
@@ -666,7 +830,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
                }
 
                mutex_lock(&ubi->volumes_mutex);
-               err = ubi_remove_volume(desc);
+               err = ubi_remove_volume(desc, 0);
                mutex_unlock(&ubi->volumes_mutex);
 
                /*
@@ -685,7 +849,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
                uint64_t tmp;
                struct ubi_rsvol_req req;
 
-               dbg_msg("re-size volume");
+               dbg_gen("re-size volume");
                err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req));
                if (err) {
                        err = -EFAULT;
@@ -713,6 +877,32 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
+       /* Re-name volumes command */
+       case UBI_IOCRNVOL:
+       {
+               struct ubi_rnvol_req *req;
+
+               dbg_msg("re-name volumes");
+               req = kmalloc(sizeof(struct ubi_rnvol_req), GFP_KERNEL);
+               if (!req) {
+                       err = -ENOMEM;
+                       break;
+               };
+
+               err = copy_from_user(req, argp, sizeof(struct ubi_rnvol_req));
+               if (err) {
+                       err = -EFAULT;
+                       kfree(req);
+                       break;
+               }
+
+               mutex_lock(&ubi->mult_mutex);
+               err = rename_volumes(ubi, req);
+               mutex_unlock(&ubi->mult_mutex);
+               kfree(req);
+               break;
+       }
+
        default:
                err = -ENOTTY;
                break;
@@ -738,7 +928,7 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file,
                struct ubi_attach_req req;
                struct mtd_info *mtd;
 
-               dbg_msg("attach MTD device");
+               dbg_gen("attach MTD device");
                err = copy_from_user(&req, argp, sizeof(struct ubi_attach_req));
                if (err) {
                        err = -EFAULT;
@@ -778,7 +968,7 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file,
        {
                int ubi_num;
 
-               dbg_msg("dettach MTD device");
+               dbg_gen("dettach MTD device");
                err = get_user(ubi_num, (__user int32_t *)argp);
                if (err) {
                        err = -EFAULT;
index 56956ec2845ff70bf4139f08ba56184487005816..c0ed60e8ade978ca74091aed6a8e5b14f1a47e63 100644 (file)
@@ -24,7 +24,7 @@
  * changes.
  */
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 #include "ubi.h"
 
  */
 void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
 {
-       dbg_msg("erase counter header dump:");
-       dbg_msg("magic          %#08x", be32_to_cpu(ec_hdr->magic));
-       dbg_msg("version        %d",    (int)ec_hdr->version);
-       dbg_msg("ec             %llu",  (long long)be64_to_cpu(ec_hdr->ec));
-       dbg_msg("vid_hdr_offset %d",    be32_to_cpu(ec_hdr->vid_hdr_offset));
-       dbg_msg("data_offset    %d",    be32_to_cpu(ec_hdr->data_offset));
-       dbg_msg("hdr_crc        %#08x", be32_to_cpu(ec_hdr->hdr_crc));
-       dbg_msg("erase counter header hexdump:");
+       printk(KERN_DEBUG "Erase counter header dump:\n");
+       printk(KERN_DEBUG "\tmagic          %#08x\n",
+              be32_to_cpu(ec_hdr->magic));
+       printk(KERN_DEBUG "\tversion        %d\n", (int)ec_hdr->version);
+       printk(KERN_DEBUG "\tec             %llu\n",
+              (long long)be64_to_cpu(ec_hdr->ec));
+       printk(KERN_DEBUG "\tvid_hdr_offset %d\n",
+              be32_to_cpu(ec_hdr->vid_hdr_offset));
+       printk(KERN_DEBUG "\tdata_offset    %d\n",
+              be32_to_cpu(ec_hdr->data_offset));
+       printk(KERN_DEBUG "\thdr_crc        %#08x\n",
+              be32_to_cpu(ec_hdr->hdr_crc));
+       printk(KERN_DEBUG "erase counter header hexdump:\n");
        print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
                       ec_hdr, UBI_EC_HDR_SIZE, 1);
 }
@@ -52,22 +57,23 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
  */
 void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
 {
-       dbg_msg("volume identifier header dump:");
-       dbg_msg("magic     %08x", be32_to_cpu(vid_hdr->magic));
-       dbg_msg("version   %d",   (int)vid_hdr->version);
-       dbg_msg("vol_type  %d",   (int)vid_hdr->vol_type);
-       dbg_msg("copy_flag %d",   (int)vid_hdr->copy_flag);
-       dbg_msg("compat    %d",   (int)vid_hdr->compat);
-       dbg_msg("vol_id    %d",   be32_to_cpu(vid_hdr->vol_id));
-       dbg_msg("lnum      %d",   be32_to_cpu(vid_hdr->lnum));
-       dbg_msg("leb_ver   %u",   be32_to_cpu(vid_hdr->leb_ver));
-       dbg_msg("data_size %d",   be32_to_cpu(vid_hdr->data_size));
-       dbg_msg("used_ebs  %d",   be32_to_cpu(vid_hdr->used_ebs));
-       dbg_msg("data_pad  %d",   be32_to_cpu(vid_hdr->data_pad));
-       dbg_msg("sqnum     %llu",
+       printk(KERN_DEBUG "Volume identifier header dump:\n");
+       printk(KERN_DEBUG "\tmagic     %08x\n", be32_to_cpu(vid_hdr->magic));
+       printk(KERN_DEBUG "\tversion   %d\n",   (int)vid_hdr->version);
+       printk(KERN_DEBUG "\tvol_type  %d\n",   (int)vid_hdr->vol_type);
+       printk(KERN_DEBUG "\tcopy_flag %d\n",   (int)vid_hdr->copy_flag);
+       printk(KERN_DEBUG "\tcompat    %d\n",   (int)vid_hdr->compat);
+       printk(KERN_DEBUG "\tvol_id    %d\n",   be32_to_cpu(vid_hdr->vol_id));
+       printk(KERN_DEBUG "\tlnum      %d\n",   be32_to_cpu(vid_hdr->lnum));
+       printk(KERN_DEBUG "\tdata_size %d\n",   be32_to_cpu(vid_hdr->data_size));
+       printk(KERN_DEBUG "\tused_ebs  %d\n",   be32_to_cpu(vid_hdr->used_ebs));
+       printk(KERN_DEBUG "\tdata_pad  %d\n",   be32_to_cpu(vid_hdr->data_pad));
+       printk(KERN_DEBUG "\tsqnum     %llu\n",
                (unsigned long long)be64_to_cpu(vid_hdr->sqnum));
-       dbg_msg("hdr_crc   %08x", be32_to_cpu(vid_hdr->hdr_crc));
-       dbg_msg("volume identifier header hexdump:");
+       printk(KERN_DEBUG "\thdr_crc   %08x\n", be32_to_cpu(vid_hdr->hdr_crc));
+       printk(KERN_DEBUG "Volume identifier header hexdump:\n");
+       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+                      vid_hdr, UBI_VID_HDR_SIZE, 1);
 }
 
 /**
@@ -76,27 +82,27 @@ void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
  */
 void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
 {
-       dbg_msg("volume information dump:");
-       dbg_msg("vol_id          %d", vol->vol_id);
-       dbg_msg("reserved_pebs   %d", vol->reserved_pebs);
-       dbg_msg("alignment       %d", vol->alignment);
-       dbg_msg("data_pad        %d", vol->data_pad);
-       dbg_msg("vol_type        %d", vol->vol_type);
-       dbg_msg("name_len        %d", vol->name_len);
-       dbg_msg("usable_leb_size %d", vol->usable_leb_size);
-       dbg_msg("used_ebs        %d", vol->used_ebs);
-       dbg_msg("used_bytes      %lld", vol->used_bytes);
-       dbg_msg("last_eb_bytes   %d", vol->last_eb_bytes);
-       dbg_msg("corrupted       %d", vol->corrupted);
-       dbg_msg("upd_marker      %d", vol->upd_marker);
+       printk(KERN_DEBUG "Volume information dump:\n");
+       printk(KERN_DEBUG "\tvol_id          %d\n", vol->vol_id);
+       printk(KERN_DEBUG "\treserved_pebs   %d\n", vol->reserved_pebs);
+       printk(KERN_DEBUG "\talignment       %d\n", vol->alignment);
+       printk(KERN_DEBUG "\tdata_pad        %d\n", vol->data_pad);
+       printk(KERN_DEBUG "\tvol_type        %d\n", vol->vol_type);
+       printk(KERN_DEBUG "\tname_len        %d\n", vol->name_len);
+       printk(KERN_DEBUG "\tusable_leb_size %d\n", vol->usable_leb_size);
+       printk(KERN_DEBUG "\tused_ebs        %d\n", vol->used_ebs);
+       printk(KERN_DEBUG "\tused_bytes      %lld\n", vol->used_bytes);
+       printk(KERN_DEBUG "\tlast_eb_bytes   %d\n", vol->last_eb_bytes);
+       printk(KERN_DEBUG "\tcorrupted       %d\n", vol->corrupted);
+       printk(KERN_DEBUG "\tupd_marker      %d\n", vol->upd_marker);
 
        if (vol->name_len <= UBI_VOL_NAME_MAX &&
            strnlen(vol->name, vol->name_len + 1) == vol->name_len) {
-               dbg_msg("name            %s", vol->name);
+               printk(KERN_DEBUG "\tname            %s\n", vol->name);
        } else {
-               dbg_msg("the 1st 5 characters of the name: %c%c%c%c%c",
-                       vol->name[0], vol->name[1], vol->name[2],
-                       vol->name[3], vol->name[4]);
+               printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n",
+                      vol->name[0], vol->name[1], vol->name[2],
+                      vol->name[3], vol->name[4]);
        }
 }
 
@@ -109,28 +115,29 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
 {
        int name_len = be16_to_cpu(r->name_len);
 
-       dbg_msg("volume table record %d dump:", idx);
-       dbg_msg("reserved_pebs   %d", be32_to_cpu(r->reserved_pebs));
-       dbg_msg("alignment       %d", be32_to_cpu(r->alignment));
-       dbg_msg("data_pad        %d", be32_to_cpu(r->data_pad));
-       dbg_msg("vol_type        %d", (int)r->vol_type);
-       dbg_msg("upd_marker      %d", (int)r->upd_marker);
-       dbg_msg("name_len        %d", name_len);
+       printk(KERN_DEBUG "Volume table record %d dump:\n", idx);
+       printk(KERN_DEBUG "\treserved_pebs   %d\n",
+              be32_to_cpu(r->reserved_pebs));
+       printk(KERN_DEBUG "\talignment       %d\n", be32_to_cpu(r->alignment));
+       printk(KERN_DEBUG "\tdata_pad        %d\n", be32_to_cpu(r->data_pad));
+       printk(KERN_DEBUG "\tvol_type        %d\n", (int)r->vol_type);
+       printk(KERN_DEBUG "\tupd_marker      %d\n", (int)r->upd_marker);
+       printk(KERN_DEBUG "\tname_len        %d\n", name_len);
 
        if (r->name[0] == '\0') {
-               dbg_msg("name            NULL");
+               printk(KERN_DEBUG "\tname            NULL\n");
                return;
        }
 
        if (name_len <= UBI_VOL_NAME_MAX &&
            strnlen(&r->name[0], name_len + 1) == name_len) {
-               dbg_msg("name            %s", &r->name[0]);
+               printk(KERN_DEBUG "\tname            %s\n", &r->name[0]);
        } else {
-               dbg_msg("1st 5 characters of the name: %c%c%c%c%c",
+               printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n",
                        r->name[0], r->name[1], r->name[2], r->name[3],
                        r->name[4]);
        }
-       dbg_msg("crc             %#08x", be32_to_cpu(r->crc));
+       printk(KERN_DEBUG "\tcrc             %#08x\n", be32_to_cpu(r->crc));
 }
 
 /**
@@ -139,15 +146,15 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
  */
 void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv)
 {
-       dbg_msg("volume scanning information dump:");
-       dbg_msg("vol_id         %d", sv->vol_id);
-       dbg_msg("highest_lnum   %d", sv->highest_lnum);
-       dbg_msg("leb_count      %d", sv->leb_count);
-       dbg_msg("compat         %d", sv->compat);
-       dbg_msg("vol_type       %d", sv->vol_type);
-       dbg_msg("used_ebs       %d", sv->used_ebs);
-       dbg_msg("last_data_size %d", sv->last_data_size);
-       dbg_msg("data_pad       %d", sv->data_pad);
+       printk(KERN_DEBUG "Volume scanning information dump:\n");
+       printk(KERN_DEBUG "\tvol_id         %d\n", sv->vol_id);
+       printk(KERN_DEBUG "\thighest_lnum   %d\n", sv->highest_lnum);
+       printk(KERN_DEBUG "\tleb_count      %d\n", sv->leb_count);
+       printk(KERN_DEBUG "\tcompat         %d\n", sv->compat);
+       printk(KERN_DEBUG "\tvol_type       %d\n", sv->vol_type);
+       printk(KERN_DEBUG "\tused_ebs       %d\n", sv->used_ebs);
+       printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size);
+       printk(KERN_DEBUG "\tdata_pad       %d\n", sv->data_pad);
 }
 
 /**
@@ -157,14 +164,13 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv)
  */
 void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type)
 {
-       dbg_msg("eraseblock scanning information dump:");
-       dbg_msg("ec       %d", seb->ec);
-       dbg_msg("pnum     %d", seb->pnum);
+       printk(KERN_DEBUG "eraseblock scanning information dump:\n");
+       printk(KERN_DEBUG "\tec       %d\n", seb->ec);
+       printk(KERN_DEBUG "\tpnum     %d\n", seb->pnum);
        if (type == 0) {
-               dbg_msg("lnum     %d", seb->lnum);
-               dbg_msg("scrub    %d", seb->scrub);
-               dbg_msg("sqnum    %llu", seb->sqnum);
-               dbg_msg("leb_ver  %u", seb->leb_ver);
+               printk(KERN_DEBUG "\tlnum     %d\n", seb->lnum);
+               printk(KERN_DEBUG "\tscrub    %d\n", seb->scrub);
+               printk(KERN_DEBUG "\tsqnum    %llu\n", seb->sqnum);
        }
 }
 
@@ -176,16 +182,16 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req)
 {
        char nm[17];
 
-       dbg_msg("volume creation request dump:");
-       dbg_msg("vol_id    %d",   req->vol_id);
-       dbg_msg("alignment %d",   req->alignment);
-       dbg_msg("bytes     %lld", (long long)req->bytes);
-       dbg_msg("vol_type  %d",   req->vol_type);
-       dbg_msg("name_len  %d",   req->name_len);
+       printk(KERN_DEBUG "Volume creation request dump:\n");
+       printk(KERN_DEBUG "\tvol_id    %d\n",   req->vol_id);
+       printk(KERN_DEBUG "\talignment %d\n",   req->alignment);
+       printk(KERN_DEBUG "\tbytes     %lld\n", (long long)req->bytes);
+       printk(KERN_DEBUG "\tvol_type  %d\n",   req->vol_type);
+       printk(KERN_DEBUG "\tname_len  %d\n",   req->name_len);
 
        memcpy(nm, req->name, 16);
        nm[16] = 0;
-       dbg_msg("the 1st 16 characters of the name: %s", nm);
+       printk(KERN_DEBUG "\t1st 16 characters of name: %s\n", nm);
 }
 
-#endif /* CONFIG_MTD_UBI_DEBUG_MSG */
+#endif /* CONFIG_MTD_UBI_DEBUG */
index 8ea99d8c9e1f0459862b77bbd54918e3b68bf88a..78e914d23ece835d597e0c10c753965fed3d5e31 100644 (file)
 #ifdef CONFIG_MTD_UBI_DEBUG
 #include <linux/random.h>
 
-#define ubi_assert(expr)  BUG_ON(!(expr))
 #define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__)
-#else
-#define ubi_assert(expr)  ({})
-#define dbg_err(fmt, ...) ({})
-#endif
 
-#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
-#define DBG_DISABLE_BGT 1
-#else
-#define DBG_DISABLE_BGT 0
-#endif
+#define ubi_assert(expr)  do {                                               \
+        if (unlikely(!(expr))) {                                             \
+                printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
+                       __func__, __LINE__, current->pid);                    \
+                ubi_dbg_dump_stack();                                        \
+        }                                                                    \
+} while (0)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG
-/* Generic debugging message */
 #define dbg_msg(fmt, ...)                                    \
        printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
               current->pid, __func__, ##__VA_ARGS__)
@@ -61,36 +56,29 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv);
 void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
 void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 
+#ifdef CONFIG_MTD_UBI_DEBUG_MSG
+/* General debugging messages */
+#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
 #else
-
-#define dbg_msg(fmt, ...)    ({})
-#define ubi_dbg_dump_stack() ({})
-#define ubi_dbg_dump_ec_hdr(ec_hdr)      ({})
-#define ubi_dbg_dump_vid_hdr(vid_hdr)    ({})
-#define ubi_dbg_dump_vol_info(vol)       ({})
-#define ubi_dbg_dump_vtbl_record(r, idx) ({})
-#define ubi_dbg_dump_sv(sv)              ({})
-#define ubi_dbg_dump_seb(seb, type)      ({})
-#define ubi_dbg_dump_mkvol_req(req)      ({})
-
-#endif /* CONFIG_MTD_UBI_DEBUG_MSG */
+#define dbg_gen(fmt, ...) ({})
+#endif
 
 #ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA
-/* Messages from the eraseblock association unit */
+/* Messages from the eraseblock association sub-system */
 #define dbg_eba(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
 #else
 #define dbg_eba(fmt, ...) ({})
 #endif
 
 #ifdef CONFIG_MTD_UBI_DEBUG_MSG_WL
-/* Messages from the wear-leveling unit */
+/* Messages from the wear-leveling sub-system */
 #define dbg_wl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
 #else
 #define dbg_wl(fmt, ...) ({})
 #endif
 
 #ifdef CONFIG_MTD_UBI_DEBUG_MSG_IO
-/* Messages from the input/output unit */
+/* Messages from the input/output sub-system */
 #define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
 #else
 #define dbg_io(fmt, ...) ({})
@@ -105,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 #define UBI_IO_DEBUG 0
 #endif
 
+#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
+#define DBG_DISABLE_BGT 1
+#else
+#define DBG_DISABLE_BGT 0
+#endif
+
 #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS
 /**
  * ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
@@ -149,4 +143,30 @@ static inline int ubi_dbg_is_erase_failure(void)
 #define ubi_dbg_is_erase_failure() 0
 #endif
 
+#else
+
+#define ubi_assert(expr)                 ({})
+#define dbg_err(fmt, ...)                ({})
+#define dbg_msg(fmt, ...)                ({})
+#define dbg_gen(fmt, ...)                ({})
+#define dbg_eba(fmt, ...)                ({})
+#define dbg_wl(fmt, ...)                 ({})
+#define dbg_io(fmt, ...)                 ({})
+#define dbg_bld(fmt, ...)                ({})
+#define ubi_dbg_dump_stack()             ({})
+#define ubi_dbg_dump_ec_hdr(ec_hdr)      ({})
+#define ubi_dbg_dump_vid_hdr(vid_hdr)    ({})
+#define ubi_dbg_dump_vol_info(vol)       ({})
+#define ubi_dbg_dump_vtbl_record(r, idx) ({})
+#define ubi_dbg_dump_sv(sv)              ({})
+#define ubi_dbg_dump_seb(seb, type)      ({})
+#define ubi_dbg_dump_mkvol_req(req)      ({})
+
+#define UBI_IO_DEBUG               0
+#define DBG_DISABLE_BGT            0
+#define ubi_dbg_is_bitflip()       0
+#define ubi_dbg_is_write_failure() 0
+#define ubi_dbg_is_erase_failure() 0
+
+#endif /* !CONFIG_MTD_UBI_DEBUG */
 #endif /* !__UBI_DEBUG_H__ */
index 7ce91ca742b136c7b60ac6db25ffb3d3771d2d6b..e04bcf1dff87c1b2dfdd75ef2428a0bb76781ef7 100644 (file)
  */
 
 /*
- * The UBI Eraseblock Association (EBA) unit.
+ * The UBI Eraseblock Association (EBA) sub-system.
  *
- * This unit is responsible for I/O to/from logical eraseblock.
+ * This sub-system is responsible for I/O to/from logical eraseblock.
  *
  * Although in this implementation the EBA table is fully kept and managed in
  * RAM, which assumes poor scalability, it might be (partially) maintained on
  * flash in future implementations.
  *
- * The EBA unit implements per-logical eraseblock locking. Before accessing a
- * logical eraseblock it is locked for reading or writing. The per-logical
- * eraseblock locking is implemented by means of the lock tree. The lock tree
- * is an RB-tree which refers all the currently locked logical eraseblocks. The
- * lock tree elements are &struct ubi_ltree_entry objects. They are indexed by
- * (@vol_id, @lnum) pairs.
+ * The EBA sub-system implements per-logical eraseblock locking. Before
+ * accessing a logical eraseblock it is locked for reading or writing. The
+ * per-logical eraseblock locking is implemented by means of the lock tree. The
+ * lock tree is an RB-tree which refers all the currently locked logical
+ * eraseblocks. The lock tree elements are &struct ubi_ltree_entry objects.
+ * They are indexed by (@vol_id, @lnum) pairs.
  *
  * EBA also maintains the global sequence counter which is incremented each
  * time a logical eraseblock is mapped to a physical eraseblock and it is
@@ -189,9 +189,7 @@ static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi,
        le->users += 1;
        spin_unlock(&ubi->ltree_lock);
 
-       if (le_free)
-               kfree(le_free);
-
+       kfree(le_free);
        return le;
 }
 
@@ -223,22 +221,18 @@ static int leb_read_lock(struct ubi_device *ubi, int vol_id, int lnum)
  */
 static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum)
 {
-       int free = 0;
        struct ubi_ltree_entry *le;
 
        spin_lock(&ubi->ltree_lock);
        le = ltree_lookup(ubi, vol_id, lnum);
        le->users -= 1;
        ubi_assert(le->users >= 0);
+       up_read(&le->mutex);
        if (le->users == 0) {
                rb_erase(&le->rb, &ubi->ltree);
-               free = 1;
+               kfree(le);
        }
        spin_unlock(&ubi->ltree_lock);
-
-       up_read(&le->mutex);
-       if (free)
-               kfree(le);
 }
 
 /**
@@ -274,7 +268,6 @@ static int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum)
  */
 static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum)
 {
-       int free;
        struct ubi_ltree_entry *le;
 
        le = ltree_add_entry(ubi, vol_id, lnum);
@@ -289,12 +282,9 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum)
        ubi_assert(le->users >= 0);
        if (le->users == 0) {
                rb_erase(&le->rb, &ubi->ltree);
-               free = 1;
-       } else
-               free = 0;
-       spin_unlock(&ubi->ltree_lock);
-       if (free)
                kfree(le);
+       }
+       spin_unlock(&ubi->ltree_lock);
 
        return 1;
 }
@@ -307,23 +297,18 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum)
  */
 static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum)
 {
-       int free;
        struct ubi_ltree_entry *le;
 
        spin_lock(&ubi->ltree_lock);
        le = ltree_lookup(ubi, vol_id, lnum);
        le->users -= 1;
        ubi_assert(le->users >= 0);
+       up_write(&le->mutex);
        if (le->users == 0) {
                rb_erase(&le->rb, &ubi->ltree);
-               free = 1;
-       } else
-               free = 0;
-       spin_unlock(&ubi->ltree_lock);
-
-       up_write(&le->mutex);
-       if (free)
                kfree(le);
+       }
+       spin_unlock(&ubi->ltree_lock);
 }
 
 /**
@@ -516,9 +501,8 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
        struct ubi_vid_hdr *vid_hdr;
 
        vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
-       if (!vid_hdr) {
+       if (!vid_hdr)
                return -ENOMEM;
-       }
 
        mutex_lock(&ubi->buf_mutex);
 
@@ -752,7 +736,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
                /* If this is the last LEB @len may be unaligned */
                len = ALIGN(data_size, ubi->min_io_size);
        else
-               ubi_assert(len % ubi->min_io_size == 0);
+               ubi_assert(!(len & (ubi->min_io_size - 1)));
 
        vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
        if (!vid_hdr)
@@ -919,7 +903,7 @@ retry:
        }
 
        if (vol->eba_tbl[lnum] >= 0) {
-               err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1);
+               err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0);
                if (err)
                        goto out_leb_unlock;
        }
@@ -1141,7 +1125,7 @@ out_unlock_leb:
 }
 
 /**
- * ubi_eba_init_scan - initialize the EBA unit using scanning information.
+ * ubi_eba_init_scan - initialize the EBA sub-system using scanning information.
  * @ubi: UBI device description object
  * @si: scanning information
  *
@@ -1156,7 +1140,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
        struct ubi_scan_leb *seb;
        struct rb_node *rb;
 
-       dbg_eba("initialize EBA unit");
+       dbg_eba("initialize EBA sub-system");
 
        spin_lock_init(&ubi->ltree_lock);
        mutex_init(&ubi->alc_mutex);
@@ -1222,7 +1206,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
                ubi->rsvd_pebs  += ubi->beb_rsvd_pebs;
        }
 
-       dbg_eba("EBA unit is initialized");
+       dbg_eba("EBA sub-system is initialized");
        return 0;
 
 out_free:
@@ -1233,20 +1217,3 @@ out_free:
        }
        return err;
 }
-
-/**
- * ubi_eba_close - close EBA unit.
- * @ubi: UBI device description object
- */
-void ubi_eba_close(const struct ubi_device *ubi)
-{
-       int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
-
-       dbg_eba("close EBA unit");
-
-       for (i = 0; i < num_volumes; i++) {
-               if (!ubi->volumes[i])
-                       continue;
-               kfree(ubi->volumes[i]->eba_tbl);
-       }
-}
index e909b390069a263e63d5d80a9a8bdf239644fb9f..605812bb0b1a3d1f5dcefa40929842c00bdbf2f1 100644 (file)
@@ -111,7 +111,7 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct ubi_device *ubi;
        uint64_t tmp = from;
 
-       dbg_msg("read %zd bytes from offset %lld", len, from);
+       dbg_gen("read %zd bytes from offset %lld", len, from);
 
        if (len < 0 || from < 0 || from + len > mtd->size)
                return -EINVAL;
@@ -162,7 +162,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
        struct ubi_device *ubi;
        uint64_t tmp = to;
 
-       dbg_msg("write %zd bytes to offset %lld", len, to);
+       dbg_gen("write %zd bytes to offset %lld", len, to);
 
        if (len < 0 || to < 0 || len + to > mtd->size)
                return -EINVAL;
@@ -215,7 +215,7 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr)
        struct ubi_volume *vol;
        struct ubi_device *ubi;
 
-       dbg_msg("erase %u bytes at offset %u", instr->len, instr->addr);
+       dbg_gen("erase %u bytes at offset %u", instr->len, instr->addr);
 
        if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize)
                return -EINVAL;
@@ -249,8 +249,8 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr)
        if (err)
                goto out_err;
 
-        instr->state = MTD_ERASE_DONE;
-        mtd_erase_callback(instr);
+       instr->state = MTD_ERASE_DONE;
+       mtd_erase_callback(instr);
        return 0;
 
 out_err:
@@ -299,12 +299,12 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
                mtd->size = vol->used_bytes;
 
        if (add_mtd_device(mtd)) {
-               ubi_err("cannot not add MTD device\n");
+               ubi_err("cannot not add MTD device");
                kfree(mtd->name);
                return -ENFILE;
        }
 
-       dbg_msg("added mtd%d (\"%s\"), size %u, EB size %u",
+       dbg_gen("added mtd%d (\"%s\"), size %u, EB size %u",
                mtd->index, mtd->name, mtd->size, mtd->erasesize);
        return 0;
 }
@@ -322,7 +322,7 @@ int ubi_destroy_gluebi(struct ubi_volume *vol)
        int err;
        struct mtd_info *mtd = &vol->gluebi_mtd;
 
-       dbg_msg("remove mtd%d", mtd->index);
+       dbg_gen("remove mtd%d", mtd->index);
        err = del_mtd_device(mtd);
        if (err)
                return err;
index 4ac11df7b048d3a24684744c4f399f13b81653ea..2fb64be44f1bab1efde6fd48988b8b22dabd5f39 100644 (file)
  */
 
 /*
- * UBI input/output unit.
+ * UBI input/output sub-system.
  *
- * This unit provides a uniform way to work with all kinds of the underlying
- * MTD devices. It also implements handy functions for reading and writing UBI
- * headers.
+ * This sub-system provides a uniform way to work with all kinds of the
+ * underlying MTD devices. It also implements handy functions for reading and
+ * writing UBI headers.
  *
  * We are trying to have a paranoid mindset and not to trust to what we read
- * from the flash media in order to be more secure and robust. So this unit
- * validates every single header it reads from the flash media.
+ * from the flash media in order to be more secure and robust. So this
+ * sub-system validates every single header it reads from the flash media.
  *
  * Some words about how the eraseblock headers are stored.
  *
  * 512-byte chunks, we have to allocate one more buffer and copy our VID header
  * to offset 448 of this buffer.
  *
- * The I/O unit does the following trick in order to avoid this extra copy.
- * It always allocates a @ubi->vid_hdr_alsize bytes buffer for the VID header
- * and returns a pointer to offset @ubi->vid_hdr_shift of this buffer. When the
- * VID header is being written out, it shifts the VID header pointer back and
- * writes the whole sub-page.
+ * The I/O sub-system does the following trick in order to avoid this extra
+ * copy. It always allocates a @ubi->vid_hdr_alsize bytes buffer for the VID
+ * header and returns a pointer to offset @ubi->vid_hdr_shift of this buffer.
+ * When the VID header is being written out, it shifts the VID header pointer
+ * back and writes the whole sub-page.
  */
 
 #include <linux/crc32.h>
@@ -156,15 +156,19 @@ retry:
                        /*
                         * -EUCLEAN is reported if there was a bit-flip which
                         * was corrected, so this is harmless.
+                        *
+                        * We do not report about it here unless debugging is
+                        * enabled. A corresponding message will be printed
+                        * later, when it is has been scrubbed.
                         */
-                       ubi_msg("fixable bit-flip detected at PEB %d", pnum);
+                       dbg_msg("fixable bit-flip detected at PEB %d", pnum);
                        ubi_assert(len == read);
                        return UBI_IO_BITFLIPS;
                }
 
                if (read != len && retries++ < UBI_IO_RETRIES) {
-                       dbg_io("error %d while reading %d bytes from PEB %d:%d, "
-                              "read only %zd bytes, retry",
+                       dbg_io("error %d while reading %d bytes from PEB %d:%d,"
+                              " read only %zd bytes, retry",
                               err, len, pnum, offset, read);
                        yield();
                        goto retry;
@@ -187,7 +191,7 @@ retry:
                ubi_assert(len == read);
 
                if (ubi_dbg_is_bitflip()) {
-                       dbg_msg("bit-flip (emulated)");
+                       dbg_gen("bit-flip (emulated)");
                        err = UBI_IO_BITFLIPS;
                }
        }
@@ -391,6 +395,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
 {
        int err, i, patt_count;
 
+       ubi_msg("run torture test for PEB %d", pnum);
        patt_count = ARRAY_SIZE(patterns);
        ubi_assert(patt_count > 0);
 
@@ -434,6 +439,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
        }
 
        err = patt_count;
+       ubi_msg("PEB %d passed torture test, do not mark it a bad", pnum);
 
 out:
        mutex_unlock(&ubi->buf_mutex);
@@ -699,8 +705,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 
        if (hdr_crc != crc) {
                if (verbose) {
-                       ubi_warn("bad EC header CRC at PEB %d, calculated %#08x,"
-                                " read %#08x", pnum, crc, hdr_crc);
+                       ubi_warn("bad EC header CRC at PEB %d, calculated "
+                                "%#08x, read %#08x", pnum, crc, hdr_crc);
                        ubi_dbg_dump_ec_hdr(ec_hdr);
                }
                return UBI_IO_BAD_EC_HDR;
@@ -1095,8 +1101,7 @@ fail:
 }
 
 /**
- * paranoid_check_peb_ec_hdr - check that the erase counter header of a
- * physical eraseblock is in-place and is all right.
+ * paranoid_check_peb_ec_hdr - check erase counter header.
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock number to check
  *
@@ -1174,8 +1179,7 @@ fail:
 }
 
 /**
- * paranoid_check_peb_vid_hdr - check that the volume identifier header of a
- * physical eraseblock is in-place and is all right.
+ * paranoid_check_peb_vid_hdr - check volume identifier header.
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock number to check
  *
@@ -1256,7 +1260,7 @@ static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
 
 fail:
        ubi_err("paranoid check failed for PEB %d", pnum);
-       dbg_msg("hex dump of the %d-%d region", offset, offset + len);
+       ubi_msg("hex dump of the %d-%d region", offset, offset + len);
        print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
                       ubi->dbg_peb_buf, len, 1);
        err = 1;
index a70d58823f8d116804c4c05bfaf807cead9015e5..5d9bcf109c13be5e584b17bf345b6ddd016cc876 100644 (file)
@@ -106,7 +106,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
        struct ubi_device *ubi;
        struct ubi_volume *vol;
 
-       dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode);
+       dbg_gen("open device %d volume %d, mode %d", ubi_num, vol_id, mode);
 
        if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
                return ERR_PTR(-EINVAL);
@@ -215,7 +215,7 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
        struct ubi_device *ubi;
        struct ubi_volume_desc *ret;
 
-       dbg_msg("open volume %s, mode %d", name, mode);
+       dbg_gen("open volume %s, mode %d", name, mode);
 
        if (!name)
                return ERR_PTR(-EINVAL);
@@ -266,7 +266,7 @@ void ubi_close_volume(struct ubi_volume_desc *desc)
        struct ubi_volume *vol = desc->vol;
        struct ubi_device *ubi = vol->ubi;
 
-       dbg_msg("close volume %d, mode %d", vol->vol_id, desc->mode);
+       dbg_gen("close volume %d, mode %d", vol->vol_id, desc->mode);
 
        spin_lock(&ubi->volumes_lock);
        switch (desc->mode) {
@@ -323,7 +323,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
        struct ubi_device *ubi = vol->ubi;
        int err, vol_id = vol->vol_id;
 
-       dbg_msg("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
+       dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
 
        if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
            lnum >= vol->used_ebs || offset < 0 || len < 0 ||
@@ -388,7 +388,7 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
        struct ubi_device *ubi = vol->ubi;
        int vol_id = vol->vol_id;
 
-       dbg_msg("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset);
+       dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset);
 
        if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
                return -EINVAL;
@@ -397,8 +397,8 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
                return -EROFS;
 
        if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 ||
-           offset + len > vol->usable_leb_size || offset % ubi->min_io_size ||
-           len % ubi->min_io_size)
+           offset + len > vol->usable_leb_size ||
+           offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
                return -EINVAL;
 
        if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
@@ -438,7 +438,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
        struct ubi_device *ubi = vol->ubi;
        int vol_id = vol->vol_id;
 
-       dbg_msg("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum);
+       dbg_gen("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum);
 
        if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
                return -EINVAL;
@@ -447,7 +447,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
                return -EROFS;
 
        if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 ||
-           len > vol->usable_leb_size || len % ubi->min_io_size)
+           len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
                return -EINVAL;
 
        if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
@@ -482,7 +482,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
        struct ubi_device *ubi = vol->ubi;
        int err;
 
-       dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
+       dbg_gen("erase LEB %d:%d", vol->vol_id, lnum);
 
        if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
                return -EROFS;
@@ -542,7 +542,7 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum)
        struct ubi_volume *vol = desc->vol;
        struct ubi_device *ubi = vol->ubi;
 
-       dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum);
+       dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);
 
        if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
                return -EROFS;
@@ -579,7 +579,7 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
        struct ubi_volume *vol = desc->vol;
        struct ubi_device *ubi = vol->ubi;
 
-       dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum);
+       dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);
 
        if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
                return -EROFS;
@@ -621,7 +621,7 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum)
 {
        struct ubi_volume *vol = desc->vol;
 
-       dbg_msg("test LEB %d:%d", vol->vol_id, lnum);
+       dbg_gen("test LEB %d:%d", vol->vol_id, lnum);
 
        if (lnum < 0 || lnum >= vol->reserved_pebs)
                return -EINVAL;
@@ -632,3 +632,27 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum)
        return vol->eba_tbl[lnum] >= 0;
 }
 EXPORT_SYMBOL_GPL(ubi_is_mapped);
+
+/**
+ * ubi_sync - synchronize UBI device buffers.
+ * @ubi_num: UBI device to synchronize
+ *
+ * The underlying MTD device may cache data in hardware or in software. This
+ * function ensures the caches are flushed. Returns zero in case of success and
+ * a negative error code in case of failure.
+ */
+int ubi_sync(int ubi_num)
+{
+       struct ubi_device *ubi;
+
+       ubi = ubi_get_device(ubi_num);
+       if (!ubi)
+               return -ENODEV;
+
+       if (ubi->mtd->sync)
+               ubi->mtd->sync(ubi->mtd);
+
+       ubi_put_device(ubi);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ubi_sync);
index 93e05281201292c4641d95593eb03158797d29a9..22ad314029452935dfffff32165d49047da2603d 100644 (file)
@@ -37,7 +37,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
 {
        int i;
 
-       ubi_assert(length % ubi->min_io_size == 0);
+       ubi_assert(!(length & (ubi->min_io_size - 1)));
 
        for (i = length - 1; i >= 0; i--)
                if (((const uint8_t *)buf)[i] != 0xFF)
index 96d410e106ab1cb72cf9f6bda211e756eaa8c98d..967bb4406df9e01c48aa5e5e0ff71a514558412d 100644 (file)
@@ -19,9 +19,9 @@
  */
 
 /*
- * UBI scanning unit.
+ * UBI scanning sub-system.
  *
- * This unit is responsible for scanning the flash media, checking UBI
+ * This sub-system is responsible for scanning the flash media, checking UBI
  * headers and providing complete information about the UBI flash image.
  *
  * The scanning information is represented by a &struct ubi_scan_info' object.
@@ -93,8 +93,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
 }
 
 /**
- * validate_vid_hdr - check that volume identifier header is correct and
- * consistent.
+ * validate_vid_hdr - check volume identifier header.
  * @vid_hdr: the volume identifier header to check
  * @sv: information about the volume this logical eraseblock belongs to
  * @pnum: physical eraseblock number the VID header came from
@@ -103,7 +102,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
  * non-zero if an inconsistency was found and zero if not.
  *
  * Note, UBI does sanity check of everything it reads from the flash media.
- * Most of the checks are done in the I/O unit. Here we check that the
+ * Most of the checks are done in the I/O sub-system. Here we check that the
  * information in the VID header is consistent to the information in other VID
  * headers of the same volume.
  */
@@ -247,45 +246,21 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
        struct ubi_vid_hdr *vh = NULL;
        unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
 
-       if (seb->sqnum == 0 && sqnum2 == 0) {
-               long long abs, v1 = seb->leb_ver, v2 = be32_to_cpu(vid_hdr->leb_ver);
-
+       if (sqnum2 == seb->sqnum) {
                /*
-                * UBI constantly increases the logical eraseblock version
-                * number and it can overflow. Thus, we have to bear in mind
-                * that versions that are close to %0xFFFFFFFF are less then
-                * versions that are close to %0.
-                *
-                * The UBI WL unit guarantees that the number of pending tasks
-                * is not greater then %0x7FFFFFFF. So, if the difference
-                * between any two versions is greater or equivalent to
-                * %0x7FFFFFFF, there was an overflow and the logical
-                * eraseblock with lower version is actually newer then the one
-                * with higher version.
-                *
-                * FIXME: but this is anyway obsolete and will be removed at
-                * some point.
+                * This must be a really ancient UBI image which has been
+                * created before sequence numbers support has been added. At
+                * that times we used 32-bit LEB versions stored in logical
+                * eraseblocks. That was before UBI got into mainline. We do not
+                * support these images anymore. Well, those images will work
+                * still work, but only if no unclean reboots happened.
                 */
-               dbg_bld("using old crappy leb_ver stuff");
-
-               if (v1 == v2) {
-                       ubi_err("PEB %d and PEB %d have the same version %lld",
-                               seb->pnum, pnum, v1);
-                       return -EINVAL;
-               }
-
-               abs = v1 - v2;
-               if (abs < 0)
-                       abs = -abs;
+               ubi_err("unsupported on-flash UBI format\n");
+               return -EINVAL;
+       }
 
-               if (abs < 0x7FFFFFFF)
-                       /* Non-overflow situation */
-                       second_is_newer = (v2 > v1);
-               else
-                       second_is_newer = (v2 < v1);
-       } else
-               /* Obviously the LEB with lower sequence counter is older */
-               second_is_newer = sqnum2 > seb->sqnum;
+       /* Obviously the LEB with lower sequence counter is older */
+       second_is_newer = !!(sqnum2 > seb->sqnum);
 
        /*
         * Now we know which copy is newer. If the copy flag of the PEB with
@@ -293,7 +268,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
         * check data CRC. For the second PEB we already have the VID header,
         * for the first one - we'll need to re-read it from flash.
         *
-        * FIXME: this may be optimized so that we wouldn't read twice.
+        * Note: this may be optimized so that we wouldn't read twice.
         */
 
        if (second_is_newer) {
@@ -379,8 +354,7 @@ out_free_vidh:
 }
 
 /**
- * ubi_scan_add_used - add information about a physical eraseblock to the
- * scanning information.
+ * ubi_scan_add_used - add physical eraseblock to the scanning information.
  * @ubi: UBI device description object
  * @si: scanning information
  * @pnum: the physical eraseblock number
@@ -400,7 +374,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
                      int bitflips)
 {
        int err, vol_id, lnum;
-       uint32_t leb_ver;
        unsigned long long sqnum;
        struct ubi_scan_volume *sv;
        struct ubi_scan_leb *seb;
@@ -409,10 +382,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
        vol_id = be32_to_cpu(vid_hdr->vol_id);
        lnum = be32_to_cpu(vid_hdr->lnum);
        sqnum = be64_to_cpu(vid_hdr->sqnum);
-       leb_ver = be32_to_cpu(vid_hdr->leb_ver);
 
-       dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, ver %u, bitflips %d",
-               pnum, vol_id, lnum, ec, sqnum, leb_ver, bitflips);
+       dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d",
+               pnum, vol_id, lnum, ec, sqnum, bitflips);
 
        sv = add_volume(si, vol_id, pnum, vid_hdr);
        if (IS_ERR(sv) < 0)
@@ -445,25 +417,20 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
                 */
 
                dbg_bld("this LEB already exists: PEB %d, sqnum %llu, "
-                       "LEB ver %u, EC %d", seb->pnum, seb->sqnum,
-                       seb->leb_ver, seb->ec);
-
-               /*
-                * Make sure that the logical eraseblocks have different
-                * versions. Otherwise the image is bad.
-                */
-               if (seb->leb_ver == leb_ver && leb_ver != 0) {
-                       ubi_err("two LEBs with same version %u", leb_ver);
-                       ubi_dbg_dump_seb(seb, 0);
-                       ubi_dbg_dump_vid_hdr(vid_hdr);
-                       return -EINVAL;
-               }
+                       "EC %d", seb->pnum, seb->sqnum, seb->ec);
 
                /*
                 * Make sure that the logical eraseblocks have different
                 * sequence numbers. Otherwise the image is bad.
                 *
-                * FIXME: remove 'sqnum != 0' check when leb_ver is removed.
+                * However, if the sequence number is zero, we assume it must
+                * be an ancient UBI image from the era when UBI did not have
+                * sequence numbers. We still can attach these images, unless
+                * there is a need to distinguish between old and new
+                * eraseblocks, in which case we'll refuse the image in
+                * 'compare_lebs()'. In other words, we attach old clean
+                * images, but refuse attaching old images with duplicated
+                * logical eraseblocks because there was an unclean reboot.
                 */
                if (seb->sqnum == sqnum && sqnum != 0) {
                        ubi_err("two LEBs with same sequence number %llu",
@@ -503,7 +470,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
                        seb->pnum = pnum;
                        seb->scrub = ((cmp_res & 2) || bitflips);
                        seb->sqnum = sqnum;
-                       seb->leb_ver = leb_ver;
 
                        if (sv->highest_lnum == lnum)
                                sv->last_data_size =
@@ -540,7 +506,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
        seb->lnum = lnum;
        seb->sqnum = sqnum;
        seb->scrub = bitflips;
-       seb->leb_ver = leb_ver;
 
        if (sv->highest_lnum <= lnum) {
                sv->highest_lnum = lnum;
@@ -554,8 +519,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
 }
 
 /**
- * ubi_scan_find_sv - find information about a particular volume in the
- * scanning information.
+ * ubi_scan_find_sv - find volume in the scanning information.
  * @si: scanning information
  * @vol_id: the requested volume ID
  *
@@ -584,8 +548,7 @@ struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
 }
 
 /**
- * ubi_scan_find_seb - find information about a particular logical
- * eraseblock in the volume scanning information.
+ * ubi_scan_find_seb - find LEB in the volume scanning information.
  * @sv: a pointer to the volume scanning information
  * @lnum: the requested logical eraseblock
  *
@@ -645,9 +608,9 @@ void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
  *
  * This function erases physical eraseblock 'pnum', and writes the erase
  * counter header to it. This function should only be used on UBI device
- * initialization stages, when the EBA unit had not been yet initialized. This
- * function returns zero in case of success and a negative error code in case
- * of failure.
+ * initialization stages, when the EBA sub-system had not been yet initialized.
+ * This function returns zero in case of success and a negative error code in
+ * case of failure.
  */
 int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
                       int pnum, int ec)
@@ -687,9 +650,10 @@ out_free:
  * @si: scanning information
  *
  * This function returns a free physical eraseblock. It is supposed to be
- * called on the UBI initialization stages when the wear-leveling unit is not
- * initialized yet. This function picks a physical eraseblocks from one of the
- * lists, writes the EC header if it is needed, and removes it from the list.
+ * called on the UBI initialization stages when the wear-leveling sub-system is
+ * not initialized yet. This function picks a physical eraseblocks from one of
+ * the lists, writes the EC header if it is needed, and removes it from the
+ * list.
  *
  * This function returns scanning physical eraseblock information in case of
  * success and an error code in case of failure.
@@ -742,8 +706,7 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
 }
 
 /**
- * process_eb - read UBI headers, check them and add corresponding data
- * to the scanning information.
+ * process_eb - read, check UBI headers, and add them to scanning information.
  * @ubi: UBI device description object
  * @si: scanning information
  * @pnum: the physical eraseblock number
@@ -751,7 +714,8 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
  * This function returns a zero if the physical eraseblock was successfully
  * handled and a negative error code in case of failure.
  */
-static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum)
+static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
+                     int pnum)
 {
        long long uninitialized_var(ec);
        int err, bitflips = 0, vol_id, ec_corr = 0;
@@ -764,8 +728,9 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
                return err;
        else if (err) {
                /*
-                * FIXME: this is actually duty of the I/O unit to initialize
-                * this, but MTD does not provide enough information.
+                * FIXME: this is actually duty of the I/O sub-system to
+                * initialize this, but MTD does not provide enough
+                * information.
                 */
                si->bad_peb_count += 1;
                return 0;
@@ -930,7 +895,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
        for (pnum = 0; pnum < ubi->peb_count; pnum++) {
                cond_resched();
 
-               dbg_msg("process PEB %d", pnum);
+               dbg_gen("process PEB %d", pnum);
                err = process_eb(ubi, si, pnum);
                if (err < 0)
                        goto out_vidh;
@@ -1079,8 +1044,7 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 
 /**
- * paranoid_check_si - check if the scanning information is correct and
- * consistent.
+ * paranoid_check_si - check the scanning information.
  * @ubi: UBI device description object
  * @si: scanning information
  *
@@ -1265,11 +1229,6 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
                                ubi_err("bad data_pad %d", sv->data_pad);
                                goto bad_vid_hdr;
                        }
-
-                       if (seb->leb_ver != be32_to_cpu(vidh->leb_ver)) {
-                               ubi_err("bad leb_ver %u", seb->leb_ver);
-                               goto bad_vid_hdr;
-                       }
                }
 
                if (!last_seb)
@@ -1299,8 +1258,7 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
                if (err < 0) {
                        kfree(buf);
                        return err;
-               }
-               else if (err)
+               } else if (err)
                        buf[pnum] = 1;
        }
 
index 966b9b682a423819921f69ca02e626ad0c89772b..61df208e2f2077de860db28494e8639349368111 100644 (file)
@@ -34,7 +34,6 @@
  * @u: unions RB-tree or @list links
  * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
  * @u.list: link in one of the eraseblock lists
- * @leb_ver: logical eraseblock version (obsolete)
  *
  * One object of this type is allocated for each physical eraseblock during
  * scanning.
@@ -49,7 +48,6 @@ struct ubi_scan_leb {
                struct rb_node rb;
                struct list_head list;
        } u;
-       uint32_t leb_ver;
 };
 
 /**
@@ -59,16 +57,16 @@ struct ubi_scan_leb {
  * @leb_count: number of logical eraseblocks in this volume
  * @vol_type: volume type
  * @used_ebs: number of used logical eraseblocks in this volume (only for
- * static volumes)
+ *            static volumes)
  * @last_data_size: amount of data in the last logical eraseblock of this
- * volume (always equivalent to the usable logical eraseblock size in case of
- * dynamic volumes)
+ *                  volume (always equivalent to the usable logical eraseblock
+ *                  size in case of dynamic volumes)
  * @data_pad: how many bytes at the end of logical eraseblocks of this volume
- * are not used (due to volume alignment)
+ *            are not used (due to volume alignment)
  * @compat: compatibility flags of this volume
  * @rb: link in the volume RB-tree
  * @root: root of the RB-tree containing all the eraseblock belonging to this
- * volume (&struct ubi_scan_leb objects)
+ *        volume (&struct ubi_scan_leb objects)
  *
  * One object of this type is allocated for each volume during scanning.
  */
@@ -92,8 +90,8 @@ struct ubi_scan_volume {
  * @free: list of free physical eraseblocks
  * @erase: list of physical eraseblocks which have to be erased
  * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
+ *         those belonging to "preserve"-compatible internal volumes)
  * @bad_peb_count: count of bad physical eraseblocks
- * those belonging to "preserve"-compatible internal volumes)
  * @vols_found: number of volumes found during scanning
  * @highest_vol_id: highest volume ID
  * @alien_peb_count: count of physical eraseblocks in the @alien list
@@ -106,8 +104,8 @@ struct ubi_scan_volume {
  * @ec_count: a temporary variable used when calculating @mean_ec
  *
  * This data structure contains the result of scanning and may be used by other
- * UBI units to build final UBI data structures, further error-recovery and so
- * on.
+ * UBI sub-systems to build final UBI data structures, further error-recovery
+ * and so on.
  */
 struct ubi_scan_info {
        struct rb_root volumes;
@@ -132,8 +130,7 @@ struct ubi_device;
 struct ubi_vid_hdr;
 
 /*
- * ubi_scan_move_to_list - move a physical eraseblock from the volume tree to a
- * list.
+ * ubi_scan_move_to_list - move a PEB from the volume tree to a list.
  *
  * @sv: volume scanning information
  * @seb: scanning eraseblock infprmation
index c3185d9fd048836dfd09c52e266e1875e9571337..2ad94040905322528d9d36ec4edadeae15e086a8 100644 (file)
@@ -98,10 +98,11 @@ enum {
  * Compatibility constants used by internal volumes.
  *
  * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
- * to the flash
+ *                     to the flash
  * @UBI_COMPAT_RO: attach this device in read-only mode
  * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
- * physical eraseblocks, don't allow the wear-leveling unit to move them
+ *                       physical eraseblocks, don't allow the wear-leveling
+ *                       sub-system to move them
  * @UBI_COMPAT_REJECT: reject this UBI image
  */
 enum {
@@ -123,7 +124,7 @@ enum {
  * struct ubi_ec_hdr - UBI erase counter header.
  * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
  * @version: version of UBI implementation which is supposed to accept this
- * UBI image
+ *           UBI image
  * @padding1: reserved for future, zeroes
  * @ec: the erase counter
  * @vid_hdr_offset: where the VID header starts
@@ -159,24 +160,23 @@ struct ubi_ec_hdr {
  * struct ubi_vid_hdr - on-flash UBI volume identifier header.
  * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
  * @version: UBI implementation version which is supposed to accept this UBI
- * image (%UBI_VERSION)
+ *           image (%UBI_VERSION)
  * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
  * @copy_flag: if this logical eraseblock was copied from another physical
- * eraseblock (for wear-leveling reasons)
+ *             eraseblock (for wear-leveling reasons)
  * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
- * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+ *          %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
  * @vol_id: ID of this volume
  * @lnum: logical eraseblock number
- * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
- * removed, kept only for not breaking older UBI users)
+ * @padding1: reserved for future, zeroes
  * @data_size: how many bytes of data this logical eraseblock contains
  * @used_ebs: total number of used logical eraseblocks in this volume
  * @data_pad: how many bytes at the end of this physical eraseblock are not
- * used
+ *            used
  * @data_crc: CRC checksum of the data stored in this logical eraseblock
- * @padding1: reserved for future, zeroes
- * @sqnum: sequence number
  * @padding2: reserved for future, zeroes
+ * @sqnum: sequence number
+ * @padding3: reserved for future, zeroes
  * @hdr_crc: volume identifier header CRC checksum
  *
  * The @sqnum is the value of the global sequence counter at the time when this
@@ -224,10 +224,6 @@ struct ubi_ec_hdr {
  * checksum is correct, this physical eraseblock is selected (P1). Otherwise
  * the older one (P) is selected.
  *
- * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
- * in the past. But it is not used anymore and we keep it in order to be able
- * to deal with old UBI images. It will be removed at some point.
- *
  * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
  * Internal volumes are not seen from outside and are used for various internal
  * UBI purposes. In this implementation there is only one internal volume - the
@@ -248,9 +244,9 @@ struct ubi_ec_hdr {
  * The @data_crc field contains the CRC checksum of the contents of the logical
  * eraseblock if this is a static volume. In case of dynamic volumes, it does
  * not contain the CRC checksum as a rule. The only exception is when the
- * data of the physical eraseblock was moved by the wear-leveling unit, then
- * the wear-leveling unit calculates the data CRC and stores it in the
- * @data_crc field. And of course, the @copy_flag is %in this case.
+ * data of the physical eraseblock was moved by the wear-leveling sub-system,
+ * then the wear-leveling sub-system calculates the data CRC and stores it in
+ * the @data_crc field. And of course, the @copy_flag is %in this case.
  *
  * The @data_size field is used only for static volumes because UBI has to know
  * how many bytes of data are stored in this eraseblock. For dynamic volumes,
@@ -277,14 +273,14 @@ struct ubi_vid_hdr {
        __u8    compat;
        __be32  vol_id;
        __be32  lnum;
-       __be32  leb_ver; /* obsolete, to be removed, don't use */
+       __u8    padding1[4];
        __be32  data_size;
        __be32  used_ebs;
        __be32  data_pad;
        __be32  data_crc;
-       __u8    padding1[4];
+       __u8    padding2[4];
        __be64  sqnum;
-       __u8    padding2[12];
+       __u8    padding3[12];
        __be32  hdr_crc;
 } __attribute__ ((packed));
 
index 67dcbd11c15c27c10cfd4349ede90c96ec11ea59..1c3fa18c26a7f9fdbf1b0b6a0d2443d82a65745e 100644 (file)
 #define UBI_IO_RETRIES 3
 
 /*
- * Error codes returned by the I/O unit.
+ * Error codes returned by the I/O sub-system.
  *
  * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only
- * 0xFF bytes
+ *                   %0xFF bytes
  * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a
- * valid erase counter header, and the rest are %0xFF bytes
+ *                  valid erase counter header, and the rest are %0xFF bytes
  * UBI_IO_BAD_EC_HDR: the erase counter header is corrupted (bad magic or CRC)
  * UBI_IO_BAD_VID_HDR: the volume identifier header is corrupted (bad magic or
- * CRC)
+ *                     CRC)
  * UBI_IO_BITFLIPS: bit-flips were detected and corrected
  */
 enum {
@@ -99,9 +99,9 @@ enum {
  * @ec: erase counter
  * @pnum: physical eraseblock number
  *
- * This data structure is used in the WL unit. Each physical eraseblock has a
- * corresponding &struct wl_entry object which may be kept in different
- * RB-trees. See WL unit for details.
+ * This data structure is used in the WL sub-system. Each physical eraseblock
+ * has a corresponding &struct wl_entry object which may be kept in different
+ * RB-trees. See WL sub-system for details.
  */
 struct ubi_wl_entry {
        struct rb_node rb;
@@ -118,10 +118,10 @@ struct ubi_wl_entry {
  * @mutex: read/write mutex to implement read/write access serialization to
  *         the (@vol_id, @lnum) logical eraseblock
  *
- * This data structure is used in the EBA unit to implement per-LEB locking.
- * When a logical eraseblock is being locked - corresponding
+ * This data structure is used in the EBA sub-system to implement per-LEB
+ * locking. When a logical eraseblock is being locked - corresponding
  * &struct ubi_ltree_entry object is inserted to the lock tree (@ubi->ltree).
- * See EBA unit for details.
+ * See EBA sub-system for details.
  */
 struct ubi_ltree_entry {
        struct rb_node rb;
@@ -131,6 +131,27 @@ struct ubi_ltree_entry {
        struct rw_semaphore mutex;
 };
 
+/**
+ * struct ubi_rename_entry - volume re-name description data structure.
+ * @new_name_len: new volume name length
+ * @new_name: new volume name
+ * @remove: if not zero, this volume should be removed, not re-named
+ * @desc: descriptor of the volume
+ * @list: links re-name entries into a list
+ *
+ * This data structure is utilized in the multiple volume re-name code. Namely,
+ * UBI first creates a list of &struct ubi_rename_entry objects from the
+ * &struct ubi_rnvol_req request object, and then utilizes this list to do all
+ * the job.
+ */
+struct ubi_rename_entry {
+       int new_name_len;
+       char new_name[UBI_VOL_NAME_MAX + 1];
+       int remove;
+       struct ubi_volume_desc *desc;
+       struct list_head list;
+};
+
 struct ubi_volume_desc;
 
 /**
@@ -206,7 +227,7 @@ struct ubi_volume {
        int alignment;
        int data_pad;
        int name_len;
-       char name[UBI_VOL_NAME_MAX+1];
+       char name[UBI_VOL_NAME_MAX + 1];
 
        int upd_ebs;
        int ch_lnum;
@@ -225,7 +246,7 @@ struct ubi_volume {
 #ifdef CONFIG_MTD_UBI_GLUEBI
        /*
         * Gluebi-related stuff may be compiled out.
-        * TODO: this should not be built into UBI but should be a separate
+        * Note: this should not be built into UBI but should be a separate
         * ubimtd driver which works on top of UBI and emulates MTD devices.
         */
        struct ubi_volume_desc *gluebi_desc;
@@ -235,8 +256,7 @@ struct ubi_volume {
 };
 
 /**
- * struct ubi_volume_desc - descriptor of the UBI volume returned when it is
- * opened.
+ * struct ubi_volume_desc - UBI volume descriptor returned when it is opened.
  * @vol: reference to the corresponding volume description object
  * @mode: open mode (%UBI_READONLY, %UBI_READWRITE, or %UBI_EXCLUSIVE)
  */
@@ -273,7 +293,7 @@ struct ubi_wl_entry;
  * @vtbl_size: size of the volume table in bytes
  * @vtbl: in-RAM volume table copy
  * @volumes_mutex: protects on-flash volume table and serializes volume
- *                 changes, like creation, deletion, update, resize
+ *                 changes, like creation, deletion, update, re-size and re-name
  *
  * @max_ec: current highest erase counter value
  * @mean_ec: current mean erase counter value
@@ -293,6 +313,7 @@ struct ubi_wl_entry;
  *           @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works
  *           fields
  * @move_mutex: serializes eraseblock moves
+ * @work_sem: sycnhronizes the WL worker with use tasks
  * @wl_scheduled: non-zero if the wear-leveling was scheduled
  * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any
  *             physical eraseblock
@@ -316,11 +337,11 @@ struct ubi_wl_entry;
  * @ro_mode: if the UBI device is in read-only mode
  * @leb_size: logical eraseblock size
  * @leb_start: starting offset of logical eraseblocks within physical
- * eraseblocks
+ *             eraseblocks
  * @ec_hdr_alsize: size of the EC header aligned to @hdrs_min_io_size
  * @vid_hdr_alsize: size of the VID header aligned to @hdrs_min_io_size
  * @vid_hdr_offset: starting offset of the volume identifier header (might be
- * unaligned)
+ *                  unaligned)
  * @vid_hdr_aloffset: starting offset of the VID header aligned to
  * @hdrs_min_io_size
  * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset
@@ -331,6 +352,8 @@ struct ubi_wl_entry;
  * @peb_buf1: a buffer of PEB size used for different purposes
  * @peb_buf2: another buffer of PEB size used for different purposes
  * @buf_mutex: proptects @peb_buf1 and @peb_buf2
+ * @ckvol_mutex: serializes static volume checking when opening
+ * @mult_mutex: serializes operations on multiple volumes, like re-nameing
  * @dbg_peb_buf: buffer of PEB size used for debugging
  * @dbg_buf_mutex: proptects @dbg_peb_buf
  */
@@ -356,16 +379,16 @@ struct ubi_device {
        struct mutex volumes_mutex;
 
        int max_ec;
-       /* TODO: mean_ec is not updated run-time, fix */
+       /* Note, mean_ec is not updated run-time - should be fixed */
        int mean_ec;
 
-       /* EBA unit's stuff */
+       /* EBA sub-system's stuff */
        unsigned long long global_sqnum;
        spinlock_t ltree_lock;
        struct rb_root ltree;
        struct mutex alc_mutex;
 
-       /* Wear-leveling unit's stuff */
+       /* Wear-leveling sub-system's stuff */
        struct rb_root used;
        struct rb_root free;
        struct rb_root scrub;
@@ -388,7 +411,7 @@ struct ubi_device {
        int thread_enabled;
        char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2];
 
-       /* I/O unit's stuff */
+       /* I/O sub-system's stuff */
        long long flash_size;
        int peb_count;
        int peb_size;
@@ -411,6 +434,7 @@ struct ubi_device {
        void *peb_buf2;
        struct mutex buf_mutex;
        struct mutex ckvol_mutex;
+       struct mutex mult_mutex;
 #ifdef CONFIG_MTD_UBI_DEBUG
        void *dbg_peb_buf;
        struct mutex dbg_buf_mutex;
@@ -427,12 +451,15 @@ extern struct mutex ubi_devices_mutex;
 /* vtbl.c */
 int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
                           struct ubi_vtbl_record *vtbl_rec);
+int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
+                           struct list_head *rename_list);
 int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si);
 
 /* vmt.c */
 int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req);
-int ubi_remove_volume(struct ubi_volume_desc *desc);
+int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl);
 int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs);
+int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list);
 int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol);
 void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol);
 
@@ -447,7 +474,8 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
                             const void __user *buf, int count);
 
 /* misc.c */
-int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length);
+int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
+                     int length);
 int ubi_check_volume(struct ubi_device *ubi, int vol_id);
 void ubi_calculate_reserved(struct ubi_device *ubi);
 
@@ -477,7 +505,6 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
 int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                     struct ubi_vid_hdr *vid_hdr);
 int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
-void ubi_eba_close(const struct ubi_device *ubi);
 
 /* wl.c */
 int ubi_wl_get_peb(struct ubi_device *ubi, int dtype);
index ddaa1a56cc692d278f16e1f92cc9a799fcd72b90..8b89cc18ff0b69753326dbe48b87015726cf3cc1 100644 (file)
@@ -39,7 +39,7 @@
  */
 
 #include <linux/err.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/div64.h>
 #include "ubi.h"
 
@@ -56,11 +56,11 @@ static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol)
        int err;
        struct ubi_vtbl_record vtbl_rec;
 
-       dbg_msg("set update marker for volume %d", vol->vol_id);
+       dbg_gen("set update marker for volume %d", vol->vol_id);
 
        if (vol->upd_marker) {
                ubi_assert(ubi->vtbl[vol->vol_id].upd_marker);
-               dbg_msg("already set");
+               dbg_gen("already set");
                return 0;
        }
 
@@ -92,7 +92,7 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
        uint64_t tmp;
        struct ubi_vtbl_record vtbl_rec;
 
-       dbg_msg("clear update marker for volume %d", vol->vol_id);
+       dbg_gen("clear update marker for volume %d", vol->vol_id);
 
        memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id],
               sizeof(struct ubi_vtbl_record));
@@ -133,7 +133,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
        int i, err;
        uint64_t tmp;
 
-       dbg_msg("start update of volume %d, %llu bytes", vol->vol_id, bytes);
+       dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes);
        ubi_assert(!vol->updating && !vol->changing_leb);
        vol->updating = 1;
 
@@ -183,7 +183,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
 {
        ubi_assert(!vol->updating && !vol->changing_leb);
 
-       dbg_msg("start changing LEB %d:%d, %u bytes",
+       dbg_gen("start changing LEB %d:%d, %u bytes",
                vol->vol_id, req->lnum, req->bytes);
        if (req->bytes == 0)
                return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0,
@@ -237,16 +237,17 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
        int err;
 
        if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
-               len = ALIGN(len, ubi->min_io_size);
-               memset(buf + len, 0xFF, len - len);
+               int l = ALIGN(len, ubi->min_io_size);
 
-               len = ubi_calc_data_len(ubi, buf, len);
+               memset(buf + len, 0xFF, l - len);
+               len = ubi_calc_data_len(ubi, buf, l);
                if (len == 0) {
-                       dbg_msg("all %d bytes contain 0xFF - skip", len);
+                       dbg_gen("all %d bytes contain 0xFF - skip", len);
                        return 0;
                }
 
-               err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, UBI_UNKNOWN);
+               err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len,
+                                       UBI_UNKNOWN);
        } else {
                /*
                 * When writing static volume, and this is the last logical
@@ -267,6 +268,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
 
 /**
  * ubi_more_update_data - write more update data.
+ * @ubi: UBI device description object
  * @vol: volume description object
  * @buf: write data (user-space memory buffer)
  * @count: how much bytes to write
@@ -283,7 +285,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
        uint64_t tmp;
        int lnum, offs, err = 0, len, to_write = count;
 
-       dbg_msg("write %d of %lld bytes, %lld already passed",
+       dbg_gen("write %d of %lld bytes, %lld already passed",
                count, vol->upd_bytes, vol->upd_received);
 
        if (ubi->ro_mode)
@@ -384,6 +386,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
 
 /**
  * ubi_more_leb_change_data - accept more data for atomic LEB change.
+ * @ubi: UBI device description object
  * @vol: volume description object
  * @buf: write data (user-space memory buffer)
  * @count: how much bytes to write
@@ -400,7 +403,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
 {
        int err;
 
-       dbg_msg("write %d of %lld bytes, %lld already passed",
+       dbg_gen("write %d of %lld bytes, %lld already passed",
                count, vol->upd_bytes, vol->upd_received);
 
        if (ubi->ro_mode)
@@ -418,7 +421,8 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
        if (vol->upd_received == vol->upd_bytes) {
                int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);
 
-               memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes);
+               memset(vol->upd_buf + vol->upd_bytes, 0xFF,
+                      len - vol->upd_bytes);
                len = ubi_calc_data_len(ubi, vol->upd_buf, len);
                err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
                                                vol->upd_buf, len, UBI_UNKNOWN);
index 5be58d85c6393c53c2be0f4693ff8a9bd13e40b3..3531ca9a1e24e9ec4721b21eea4a7c77244d7db8 100644 (file)
@@ -28,9 +28,9 @@
 #include "ubi.h"
 
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-static void paranoid_check_volumes(struct ubi_device *ubi);
+static int paranoid_check_volumes(struct ubi_device *ubi);
 #else
-#define paranoid_check_volumes(ubi)
+#define paranoid_check_volumes(ubi) 0
 #endif
 
 static ssize_t vol_attribute_show(struct device *dev,
@@ -127,6 +127,7 @@ static void vol_release(struct device *dev)
 {
        struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
 
+       kfree(vol->eba_tbl);
        kfree(vol);
 }
 
@@ -201,7 +202,7 @@ static void volume_sysfs_close(struct ubi_volume *vol)
  */
 int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 {
-       int i, err, vol_id = req->vol_id, dont_free = 0;
+       int i, err, vol_id = req->vol_id, do_free = 1;
        struct ubi_volume *vol;
        struct ubi_vtbl_record vtbl_rec;
        uint64_t bytes;
@@ -217,7 +218,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        spin_lock(&ubi->volumes_lock);
        if (vol_id == UBI_VOL_NUM_AUTO) {
                /* Find unused volume ID */
-               dbg_msg("search for vacant volume ID");
+               dbg_gen("search for vacant volume ID");
                for (i = 0; i < ubi->vtbl_slots; i++)
                        if (!ubi->volumes[i]) {
                                vol_id = i;
@@ -232,7 +233,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
                req->vol_id = vol_id;
        }
 
-       dbg_msg("volume ID %d, %llu bytes, type %d, name %s",
+       dbg_gen("volume ID %d, %llu bytes, type %d, name %s",
                vol_id, (unsigned long long)req->bytes,
                (int)req->vol_type, req->name);
 
@@ -252,7 +253,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
                        goto out_unlock;
                }
 
-        /* Calculate how many eraseblocks are requested */
+       /* Calculate how many eraseblocks are requested */
        vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment;
        bytes = req->bytes;
        if (do_div(bytes, vol->usable_leb_size))
@@ -274,7 +275,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        vol->data_pad  = ubi->leb_size % vol->alignment;
        vol->vol_type  = req->vol_type;
        vol->name_len  = req->name_len;
-       memcpy(vol->name, req->name, vol->name_len + 1);
+       memcpy(vol->name, req->name, vol->name_len);
        vol->ubi = ubi;
 
        /*
@@ -349,7 +350,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
                vtbl_rec.vol_type = UBI_VID_DYNAMIC;
        else
                vtbl_rec.vol_type = UBI_VID_STATIC;
-       memcpy(vtbl_rec.name, vol->name, vol->name_len + 1);
+       memcpy(vtbl_rec.name, vol->name, vol->name_len);
 
        err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
        if (err)
@@ -360,19 +361,19 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        ubi->vol_count += 1;
        spin_unlock(&ubi->volumes_lock);
 
-       paranoid_check_volumes(ubi);
-       return 0;
+       err = paranoid_check_volumes(ubi);
+       return err;
 
 out_sysfs:
        /*
-        * We have registered our device, we should not free the volume*
+        * We have registered our device, we should not free the volume
         * description object in this function in case of an error - it is
         * freed by the release function.
         *
         * Get device reference to prevent the release function from being
         * called just after sysfs has been closed.
         */
-       dont_free = 1;
+       do_free = 0;
        get_device(&vol->dev);
        volume_sysfs_close(vol);
 out_gluebi:
@@ -382,17 +383,18 @@ out_gluebi:
 out_cdev:
        cdev_del(&vol->cdev);
 out_mapping:
-       kfree(vol->eba_tbl);
+       if (do_free)
+               kfree(vol->eba_tbl);
 out_acc:
        spin_lock(&ubi->volumes_lock);
        ubi->rsvd_pebs -= vol->reserved_pebs;
        ubi->avail_pebs += vol->reserved_pebs;
 out_unlock:
        spin_unlock(&ubi->volumes_lock);
-       if (dont_free)
-               put_device(&vol->dev);
-       else
+       if (do_free)
                kfree(vol);
+       else
+               put_device(&vol->dev);
        ubi_err("cannot create volume %d, error %d", vol_id, err);
        return err;
 }
@@ -400,19 +402,20 @@ out_unlock:
 /**
  * ubi_remove_volume - remove volume.
  * @desc: volume descriptor
+ * @no_vtbl: do not change volume table if not zero
  *
  * This function removes volume described by @desc. The volume has to be opened
  * in "exclusive" mode. Returns zero in case of success and a negative error
  * code in case of failure. The caller has to have the @ubi->volumes_mutex
  * locked.
  */
-int ubi_remove_volume(struct ubi_volume_desc *desc)
+int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
 {
        struct ubi_volume *vol = desc->vol;
        struct ubi_device *ubi = vol->ubi;
        int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs;
 
-       dbg_msg("remove UBI volume %d", vol_id);
+       dbg_gen("remove UBI volume %d", vol_id);
        ubi_assert(desc->mode == UBI_EXCLUSIVE);
        ubi_assert(vol == ubi->volumes[vol_id]);
 
@@ -435,9 +438,11 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
        if (err)
                goto out_err;
 
-       err = ubi_change_vtbl_record(ubi, vol_id, NULL);
-       if (err)
-               goto out_err;
+       if (!no_vtbl) {
+               err = ubi_change_vtbl_record(ubi, vol_id, NULL);
+               if (err)
+                       goto out_err;
+       }
 
        for (i = 0; i < vol->reserved_pebs; i++) {
                err = ubi_eba_unmap_leb(ubi, vol, i);
@@ -445,8 +450,6 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
                        goto out_err;
        }
 
-       kfree(vol->eba_tbl);
-       vol->eba_tbl = NULL;
        cdev_del(&vol->cdev);
        volume_sysfs_close(vol);
 
@@ -465,8 +468,9 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
        ubi->vol_count -= 1;
        spin_unlock(&ubi->volumes_lock);
 
-       paranoid_check_volumes(ubi);
-       return 0;
+       if (!no_vtbl)
+               err = paranoid_check_volumes(ubi);
+       return err;
 
 out_err:
        ubi_err("cannot remove volume %d, error %d", vol_id, err);
@@ -497,7 +501,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
        if (ubi->ro_mode)
                return -EROFS;
 
-       dbg_msg("re-size volume %d to from %d to %d PEBs",
+       dbg_gen("re-size volume %d to from %d to %d PEBs",
                vol_id, vol->reserved_pebs, reserved_pebs);
 
        if (vol->vol_type == UBI_STATIC_VOLUME &&
@@ -586,8 +590,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
                        (long long)vol->used_ebs * vol->usable_leb_size;
        }
 
-       paranoid_check_volumes(ubi);
-       return 0;
+       err = paranoid_check_volumes(ubi);
+       return err;
 
 out_acc:
        if (pebs > 0) {
@@ -601,6 +605,44 @@ out_free:
        return err;
 }
 
+/**
+ * ubi_rename_volumes - re-name UBI volumes.
+ * @ubi: UBI device description object
+ * @rename_list: list of &struct ubi_rename_entry objects
+ *
+ * This function re-names or removes volumes specified in the re-name list.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list)
+{
+       int err;
+       struct ubi_rename_entry *re;
+
+       err = ubi_vtbl_rename_volumes(ubi, rename_list);
+       if (err)
+               return err;
+
+       list_for_each_entry(re, rename_list, list) {
+               if (re->remove) {
+                       err = ubi_remove_volume(re->desc, 1);
+                       if (err)
+                               break;
+               } else {
+                       struct ubi_volume *vol = re->desc->vol;
+
+                       spin_lock(&ubi->volumes_lock);
+                       vol->name_len = re->new_name_len;
+                       memcpy(vol->name, re->new_name, re->new_name_len + 1);
+                       spin_unlock(&ubi->volumes_lock);
+               }
+       }
+
+       if (!err)
+               err = paranoid_check_volumes(ubi);
+       return err;
+}
+
 /**
  * ubi_add_volume - add volume.
  * @ubi: UBI device description object
@@ -615,8 +657,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
        int err, vol_id = vol->vol_id;
        dev_t dev;
 
-       dbg_msg("add volume %d", vol_id);
-       ubi_dbg_dump_vol_info(vol);
+       dbg_gen("add volume %d", vol_id);
 
        /* Register character device for the volume */
        cdev_init(&vol->cdev, &ubi_vol_cdev_operations);
@@ -650,8 +691,8 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
                return err;
        }
 
-       paranoid_check_volumes(ubi);
-       return 0;
+       err = paranoid_check_volumes(ubi);
+       return err;
 
 out_gluebi:
        err = ubi_destroy_gluebi(vol);
@@ -672,7 +713,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
 {
        int err;
 
-       dbg_msg("free volume %d", vol->vol_id);
+       dbg_gen("free volume %d", vol->vol_id);
 
        ubi->volumes[vol->vol_id] = NULL;
        err = ubi_destroy_gluebi(vol);
@@ -686,8 +727,10 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
  * paranoid_check_volume - check volume information.
  * @ubi: UBI device description object
  * @vol_id: volume ID
+ *
+ * Returns zero if volume is all right and a a negative error code if not.
  */
-static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
+static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
 {
        int idx = vol_id2idx(ubi, vol_id);
        int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker;
@@ -705,16 +748,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
                        goto fail;
                }
                spin_unlock(&ubi->volumes_lock);
-               return;
-       }
-
-       if (vol->exclusive) {
-               /*
-                * The volume may be being created at the moment, do not check
-                * it (e.g., it may be in the middle of ubi_create_volume().
-                */
-               spin_unlock(&ubi->volumes_lock);
-               return;
+               return 0;
        }
 
        if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 ||
@@ -727,7 +761,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
                goto fail;
        }
 
-       n = vol->alignment % ubi->min_io_size;
+       n = vol->alignment & (ubi->min_io_size - 1);
        if (vol->alignment != 1 && n) {
                ubi_err("alignment is not multiple of min I/O unit");
                goto fail;
@@ -824,31 +858,39 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
 
        if (alignment != vol->alignment || data_pad != vol->data_pad ||
            upd_marker != vol->upd_marker || vol_type != vol->vol_type ||
-           name_len!= vol->name_len || strncmp(name, vol->name, name_len)) {
+           name_len != vol->name_len || strncmp(name, vol->name, name_len)) {
                ubi_err("volume info is different");
                goto fail;
        }
 
        spin_unlock(&ubi->volumes_lock);
-       return;
+       return 0;
 
 fail:
        ubi_err("paranoid check failed for volume %d", vol_id);
-       ubi_dbg_dump_vol_info(vol);
+       if (vol)
+               ubi_dbg_dump_vol_info(vol);
        ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
        spin_unlock(&ubi->volumes_lock);
-       BUG();
+       return -EINVAL;
 }
 
 /**
  * paranoid_check_volumes - check information about all volumes.
  * @ubi: UBI device description object
+ *
+ * Returns zero if volumes are all right and a a negative error code if not.
  */
-static void paranoid_check_volumes(struct ubi_device *ubi)
+static int paranoid_check_volumes(struct ubi_device *ubi)
 {
-       int i;
+       int i, err = 0;
 
-       for (i = 0; i < ubi->vtbl_slots; i++)
-               paranoid_check_volume(ubi, i);
+       for (i = 0; i < ubi->vtbl_slots; i++) {
+               err = paranoid_check_volume(ubi, i);
+               if (err)
+                       break;
+       }
+
+       return err;
 }
 #endif
index af36b12be27871ddefd1c34a0d17f95483042343..217d0e111b2a4652212f563cb9baf5255f2bbdca 100644 (file)
@@ -115,8 +115,58 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
 }
 
 /**
- * vtbl_check - check if volume table is not corrupted and contains sensible
- *              data.
+ * ubi_vtbl_rename_volumes - rename UBI volumes in the volume table.
+ * @ubi: UBI device description object
+ * @rename_list: list of &struct ubi_rename_entry objects
+ *
+ * This function re-names multiple volumes specified in @req in the volume
+ * table. Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
+                           struct list_head *rename_list)
+{
+       int i, err;
+       struct ubi_rename_entry *re;
+       struct ubi_volume *layout_vol;
+
+       list_for_each_entry(re, rename_list, list) {
+               uint32_t crc;
+               struct ubi_volume *vol = re->desc->vol;
+               struct ubi_vtbl_record *vtbl_rec = &ubi->vtbl[vol->vol_id];
+
+               if (re->remove) {
+                       memcpy(vtbl_rec, &empty_vtbl_record,
+                              sizeof(struct ubi_vtbl_record));
+                       continue;
+               }
+
+               vtbl_rec->name_len = cpu_to_be16(re->new_name_len);
+               memcpy(vtbl_rec->name, re->new_name, re->new_name_len);
+               memset(vtbl_rec->name + re->new_name_len, 0,
+                      UBI_VOL_NAME_MAX + 1 - re->new_name_len);
+               crc = crc32(UBI_CRC32_INIT, vtbl_rec,
+                           UBI_VTBL_RECORD_SIZE_CRC);
+               vtbl_rec->crc = cpu_to_be32(crc);
+       }
+
+       layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)];
+       for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
+               err = ubi_eba_unmap_leb(ubi, layout_vol, i);
+               if (err)
+                       return err;
+
+               err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
+                                       ubi->vtbl_size, UBI_LONGTERM);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+/**
+ * vtbl_check - check if volume table is not corrupted and sensible.
  * @ubi: UBI device description object
  * @vtbl: volume table
  *
@@ -127,7 +177,7 @@ static int vtbl_check(const struct ubi_device *ubi,
                      const struct ubi_vtbl_record *vtbl)
 {
        int i, n, reserved_pebs, alignment, data_pad, vol_type, name_len;
-       int upd_marker;
+       int upd_marker, err;
        uint32_t crc;
        const char *name;
 
@@ -153,7 +203,7 @@ static int vtbl_check(const struct ubi_device *ubi,
                if (reserved_pebs == 0) {
                        if (memcmp(&vtbl[i], &empty_vtbl_record,
                                                UBI_VTBL_RECORD_SIZE)) {
-                               dbg_err("bad empty record");
+                               err = 2;
                                goto bad;
                        }
                        continue;
@@ -161,56 +211,57 @@ static int vtbl_check(const struct ubi_device *ubi,
 
                if (reserved_pebs < 0 || alignment < 0 || data_pad < 0 ||
                    name_len < 0) {
-                       dbg_err("negative values");
+                       err = 3;
                        goto bad;
                }
 
                if (alignment > ubi->leb_size || alignment == 0) {
-                       dbg_err("bad alignment");
+                       err = 4;
                        goto bad;
                }
 
-               n = alignment % ubi->min_io_size;
+               n = alignment & (ubi->min_io_size - 1);
                if (alignment != 1 && n) {
-                       dbg_err("alignment is not multiple of min I/O unit");
+                       err = 5;
                        goto bad;
                }
 
                n = ubi->leb_size % alignment;
                if (data_pad != n) {
                        dbg_err("bad data_pad, has to be %d", n);
+                       err = 6;
                        goto bad;
                }
 
                if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) {
-                       dbg_err("bad vol_type");
+                       err = 7;
                        goto bad;
                }
 
                if (upd_marker != 0 && upd_marker != 1) {
-                       dbg_err("bad upd_marker");
+                       err = 8;
                        goto bad;
                }
 
                if (reserved_pebs > ubi->good_peb_count) {
                        dbg_err("too large reserved_pebs, good PEBs %d",
                                ubi->good_peb_count);
+                       err = 9;
                        goto bad;
                }
 
                if (name_len > UBI_VOL_NAME_MAX) {
-                       dbg_err("too long volume name, max %d",
-                               UBI_VOL_NAME_MAX);
+                       err = 10;
                        goto bad;
                }
 
                if (name[0] == '\0') {
-                       dbg_err("NULL volume name");
+                       err = 11;
                        goto bad;
                }
 
                if (name_len != strnlen(name, name_len + 1)) {
-                       dbg_err("bad name_len");
+                       err = 12;
                        goto bad;
                }
        }
@@ -235,7 +286,7 @@ static int vtbl_check(const struct ubi_device *ubi,
        return 0;
 
 bad:
-       ubi_err("volume table check failed, record %d", i);
+       ubi_err("volume table check failed: record %d, error %d", i, err);
        ubi_dbg_dump_vtbl_record(&vtbl[i], i);
        return -EINVAL;
 }
@@ -287,7 +338,6 @@ retry:
                             vid_hdr->data_pad = cpu_to_be32(0);
        vid_hdr->lnum = cpu_to_be32(copy);
        vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum);
-       vid_hdr->leb_ver = cpu_to_be32(old_seb ? old_seb->leb_ver + 1: 0);
 
        /* The EC header is already there, write the VID header */
        err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr);
@@ -370,7 +420,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
         *    to LEB 0.
         */
 
-       dbg_msg("check layout volume");
+       dbg_gen("check layout volume");
 
        /* Read both LEB 0 and LEB 1 into memory */
        ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
@@ -384,7 +434,16 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
                err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
                                       ubi->vtbl_size);
                if (err == UBI_IO_BITFLIPS || err == -EBADMSG)
-                       /* Scrub the PEB later */
+                       /*
+                        * Scrub the PEB later. Note, -EBADMSG indicates an
+                        * uncorrectable ECC error, but we have our own CRC and
+                        * the data will be checked later. If the data is OK,
+                        * the PEB will be scrubbed (because we set
+                        * seb->scrub). If the data is not OK, the contents of
+                        * the PEB will be recovered from the second copy, and
+                        * seb->scrub will be cleared in
+                        * 'ubi_scan_add_used()'.
+                        */
                        seb->scrub = 1;
                else if (err)
                        goto out_free;
@@ -400,7 +459,8 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
        if (!leb_corrupted[0]) {
                /* LEB 0 is OK */
                if (leb[1])
-                       leb_corrupted[1] = memcmp(leb[0], leb[1], ubi->vtbl_size);
+                       leb_corrupted[1] = memcmp(leb[0], leb[1],
+                                                 ubi->vtbl_size);
                if (leb_corrupted[1]) {
                        ubi_warn("volume table copy #2 is corrupted");
                        err = create_vtbl(ubi, si, 1, leb[0]);
@@ -620,30 +680,32 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
 static int check_sv(const struct ubi_volume *vol,
                    const struct ubi_scan_volume *sv)
 {
+       int err;
+
        if (sv->highest_lnum >= vol->reserved_pebs) {
-               dbg_err("bad highest_lnum");
+               err = 1;
                goto bad;
        }
        if (sv->leb_count > vol->reserved_pebs) {
-               dbg_err("bad leb_count");
+               err = 2;
                goto bad;
        }
        if (sv->vol_type != vol->vol_type) {
-               dbg_err("bad vol_type");
+               err = 3;
                goto bad;
        }
        if (sv->used_ebs > vol->reserved_pebs) {
-               dbg_err("bad used_ebs");
+               err = 4;
                goto bad;
        }
        if (sv->data_pad != vol->data_pad) {
-               dbg_err("bad data_pad");
+               err = 5;
                goto bad;
        }
        return 0;
 
 bad:
-       ubi_err("bad scanning information");
+       ubi_err("bad scanning information, error %d", err);
        ubi_dbg_dump_sv(sv);
        ubi_dbg_dump_vol_info(vol);
        return -EINVAL;
@@ -672,14 +734,13 @@ static int check_scanning_info(const struct ubi_device *ubi,
                return -EINVAL;
        }
 
-       if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT&&
+       if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
            si->highest_vol_id < UBI_INTERNAL_VOL_START) {
                ubi_err("too large volume ID %d found by scanning",
                        si->highest_vol_id);
                return -EINVAL;
        }
 
-
        for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
                cond_resched();
 
@@ -717,8 +778,7 @@ static int check_scanning_info(const struct ubi_device *ubi,
 }
 
 /**
- * ubi_read_volume_table - read volume table.
- * information.
+ * ubi_read_volume_table - read the volume table.
  * @ubi: UBI device description object
  * @si: scanning information
  *
@@ -797,11 +857,10 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
 
 out_free:
        vfree(ubi->vtbl);
-       for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++)
-               if (ubi->volumes[i]) {
-                       kfree(ubi->volumes[i]);
-                       ubi->volumes[i] = NULL;
-               }
+       for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
+               kfree(ubi->volumes[i]);
+               ubi->volumes[i] = NULL;
+       }
        return err;
 }
 
index a471a491f0ab0c2840543594966640487e7bacd4..05d70937b54322d8ecd878d05cc69e084ef4a5ed 100644 (file)
  */
 
 /*
- * UBI wear-leveling unit.
+ * UBI wear-leveling sub-system.
  *
- * This unit is responsible for wear-leveling. It works in terms of physical
- * eraseblocks and erase counters and knows nothing about logical eraseblocks,
- * volumes, etc. From this unit's perspective all physical eraseblocks are of
- * two types - used and free. Used physical eraseblocks are those that were
- * "get" by the 'ubi_wl_get_peb()' function, and free physical eraseblocks are
- * those that were put by the 'ubi_wl_put_peb()' function.
+ * This sub-system is responsible for wear-leveling. It works in terms of
+ * physical* eraseblocks and erase counters and knows nothing about logical
+ * eraseblocks, volumes, etc. From this sub-system's perspective all physical
+ * eraseblocks are of two types - used and free. Used physical eraseblocks are
+ * those that were "get" by the 'ubi_wl_get_peb()' function, and free physical
+ * eraseblocks are those that were put by the 'ubi_wl_put_peb()' function.
  *
  * Physical eraseblocks returned by 'ubi_wl_get_peb()' have only erase counter
- * header. The rest of the physical eraseblock contains only 0xFF bytes.
+ * header. The rest of the physical eraseblock contains only %0xFF bytes.
  *
- * When physical eraseblocks are returned to the WL unit by means of the
+ * When physical eraseblocks are returned to the WL sub-system by means of the
  * 'ubi_wl_put_peb()' function, they are scheduled for erasure. The erasure is
  * done asynchronously in context of the per-UBI device background thread,
- * which is also managed by the WL unit.
+ * which is also managed by the WL sub-system.
  *
  * The wear-leveling is ensured by means of moving the contents of used
  * physical eraseblocks with low erase counter to free physical eraseblocks
  * The 'ubi_wl_get_peb()' function accepts data type hints which help to pick
  * an "optimal" physical eraseblock. For example, when it is known that the
  * physical eraseblock will be "put" soon because it contains short-term data,
- * the WL unit may pick a free physical eraseblock with low erase counter, and
- * so forth.
+ * the WL sub-system may pick a free physical eraseblock with low erase
+ * counter, and so forth.
  *
- * If the WL unit fails to erase a physical eraseblock, it marks it as bad.
+ * If the WL sub-system fails to erase a physical eraseblock, it marks it as
+ * bad.
  *
- * This unit is also responsible for scrubbing. If a bit-flip is detected in a
- * physical eraseblock, it has to be moved. Technically this is the same as
- * moving it for wear-leveling reasons.
+ * This sub-system is also responsible for scrubbing. If a bit-flip is detected
+ * in a physical eraseblock, it has to be moved. Technically this is the same
+ * as moving it for wear-leveling reasons.
  *
- * As it was said, for the UBI unit all physical eraseblocks are either "free"
- * or "used". Free eraseblock are kept in the @wl->free RB-tree, while used
- * eraseblocks are kept in a set of different RB-trees: @wl->used,
+ * As it was said, for the UBI sub-system all physical eraseblocks are either
+ * "free" or "used". Free eraseblock are kept in the @wl->free RB-tree, while
+ * used eraseblocks are kept in a set of different RB-trees: @wl->used,
  * @wl->prot.pnum, @wl->prot.aec, and @wl->scrub.
  *
  * Note, in this implementation, we keep a small in-RAM object for each physical
  * eraseblock. This is surely not a scalable solution. But it appears to be good
  * enough for moderately large flashes and it is simple. In future, one may
- * re-work this unit and make it more scalable.
+ * re-work this sub-system and make it more scalable.
  *
- * At the moment this unit does not utilize the sequence number, which was
- * introduced relatively recently. But it would be wise to do this because the
- * sequence number of a logical eraseblock characterizes how old is it. For
+ * At the moment this sub-system does not utilize the sequence number, which
+ * was introduced relatively recently. But it would be wise to do this because
+ * the sequence number of a logical eraseblock characterizes how old is it. For
  * example, when we move a PEB with low erase counter, and we need to pick the
  * target PEB, we pick a PEB with the highest EC if our PEB is "old" and we
  * pick target PEB with an average EC if our PEB is not very "old". This is a
- * room for future re-works of the WL unit.
+ * room for future re-works of the WL sub-system.
  *
- * FIXME: looks too complex, should be simplified (later).
+ * Note: the stuff with protection trees looks too complex and is difficult to
+ * understand. Should be fixed.
  */
 
 #include <linux/slab.h>
 
 /*
  * Maximum difference between two erase counters. If this threshold is
- * exceeded, the WL unit starts moving data from used physical eraseblocks with
- * low erase counter to free physical eraseblocks with high erase counter.
+ * exceeded, the WL sub-system starts moving data from used physical
+ * eraseblocks with low erase counter to free physical eraseblocks with high
+ * erase counter.
  */
 #define UBI_WL_THRESHOLD CONFIG_MTD_UBI_WL_THRESHOLD
 
 /*
- * When a physical eraseblock is moved, the WL unit has to pick the target
+ * When a physical eraseblock is moved, the WL sub-system has to pick the target
  * physical eraseblock to move to. The simplest way would be just to pick the
  * one with the highest erase counter. But in certain workloads this could lead
  * to an unlimited wear of one or few physical eraseblock. Indeed, imagine a
  * situation when the picked physical eraseblock is constantly erased after the
  * data is written to it. So, we have a constant which limits the highest erase
- * counter of the free physical eraseblock to pick. Namely, the WL unit does
- * not pick eraseblocks with erase counter greater then the lowest erase
+ * counter of the free physical eraseblock to pick. Namely, the WL sub-system
+ * does not pick eraseblocks with erase counter greater then the lowest erase
  * counter plus %WL_FREE_MAX_DIFF.
  */
 #define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD)
  * @abs_ec: the absolute erase counter value when the protection ends
  * @e: the wear-leveling entry of the physical eraseblock under protection
  *
- * When the WL unit returns a physical eraseblock, the physical eraseblock is
- * protected from being moved for some "time". For this reason, the physical
- * eraseblock is not directly moved from the @wl->free tree to the @wl->used
- * tree. There is one more tree in between where this physical eraseblock is
- * temporarily stored (@wl->prot).
+ * When the WL sub-system returns a physical eraseblock, the physical
+ * eraseblock is protected from being moved for some "time". For this reason,
+ * the physical eraseblock is not directly moved from the @wl->free tree to the
+ * @wl->used tree. There is one more tree in between where this physical
+ * eraseblock is temporarily stored (@wl->prot).
  *
  * All this protection stuff is needed because:
  *  o we don't want to move physical eraseblocks just after we have given them
@@ -175,7 +178,6 @@ struct ubi_wl_prot_entry {
  * @list: a link in the list of pending works
  * @func: worker function
  * @priv: private data of the worker function
- *
  * @e: physical eraseblock to erase
  * @torture: if the physical eraseblock has to be tortured
  *
@@ -473,52 +475,47 @@ retry:
        }
 
        switch (dtype) {
-               case UBI_LONGTERM:
-                       /*
-                        * For long term data we pick a physical eraseblock
-                        * with high erase counter. But the highest erase
-                        * counter we can pick is bounded by the the lowest
-                        * erase counter plus %WL_FREE_MAX_DIFF.
-                        */
-                       e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
-                       protect = LT_PROTECTION;
-                       break;
-               case UBI_UNKNOWN:
-                       /*
-                        * For unknown data we pick a physical eraseblock with
-                        * medium erase counter. But we by no means can pick a
-                        * physical eraseblock with erase counter greater or
-                        * equivalent than the lowest erase counter plus
-                        * %WL_FREE_MAX_DIFF.
-                        */
-                       first = rb_entry(rb_first(&ubi->free),
-                                        struct ubi_wl_entry, rb);
-                       last = rb_entry(rb_last(&ubi->free),
-                                       struct ubi_wl_entry, rb);
+       case UBI_LONGTERM:
+               /*
+                * For long term data we pick a physical eraseblock with high
+                * erase counter. But the highest erase counter we can pick is
+                * bounded by the the lowest erase counter plus
+                * %WL_FREE_MAX_DIFF.
+                */
+               e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
+               protect = LT_PROTECTION;
+               break;
+       case UBI_UNKNOWN:
+               /*
+                * For unknown data we pick a physical eraseblock with medium
+                * erase counter. But we by no means can pick a physical
+                * eraseblock with erase counter greater or equivalent than the
+                * lowest erase counter plus %WL_FREE_MAX_DIFF.
+                */
+               first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb);
+               last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, rb);
 
-                       if (last->ec - first->ec < WL_FREE_MAX_DIFF)
-                               e = rb_entry(ubi->free.rb_node,
-                                               struct ubi_wl_entry, rb);
-                       else {
-                               medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
-                               e = find_wl_entry(&ubi->free, medium_ec);
-                       }
-                       protect = U_PROTECTION;
-                       break;
-               case UBI_SHORTTERM:
-                       /*
-                        * For short term data we pick a physical eraseblock
-                        * with the lowest erase counter as we expect it will
-                        * be erased soon.
-                        */
-                       e = rb_entry(rb_first(&ubi->free),
-                                    struct ubi_wl_entry, rb);
-                       protect = ST_PROTECTION;
-                       break;
-               default:
-                       protect = 0;
-                       e = NULL;
-                       BUG();
+               if (last->ec - first->ec < WL_FREE_MAX_DIFF)
+                       e = rb_entry(ubi->free.rb_node,
+                                       struct ubi_wl_entry, rb);
+               else {
+                       medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
+                       e = find_wl_entry(&ubi->free, medium_ec);
+               }
+               protect = U_PROTECTION;
+               break;
+       case UBI_SHORTTERM:
+               /*
+                * For short term data we pick a physical eraseblock with the
+                * lowest erase counter as we expect it will be erased soon.
+                */
+               e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb);
+               protect = ST_PROTECTION;
+               break;
+       default:
+               protect = 0;
+               e = NULL;
+               BUG();
        }
 
        /*
@@ -582,7 +579,8 @@ found:
  * This function returns zero in case of success and a negative error code in
  * case of failure.
  */
-static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int torture)
+static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
+                     int torture)
 {
        int err;
        struct ubi_ec_hdr *ec_hdr;
@@ -634,8 +632,7 @@ out_free:
 }
 
 /**
- * check_protection_over - check if it is time to stop protecting some
- * physical eraseblocks.
+ * check_protection_over - check if it is time to stop protecting some PEBs.
  * @ubi: UBI device description object
  *
  * This function is called after each erase operation, when the absolute erase
@@ -871,6 +868,10 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
        }
 
        ubi_free_vid_hdr(ubi, vid_hdr);
+       if (scrubbing && !protect)
+               ubi_msg("scrubbed PEB %d, data moved to PEB %d",
+                       e1->pnum, e2->pnum);
+
        spin_lock(&ubi->wl_lock);
        if (protect)
                prot_tree_add(ubi, e1, pe, protect);
@@ -1054,8 +1055,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
                spin_unlock(&ubi->wl_lock);
 
                /*
-                * One more erase operation has happened, take care about protected
-                * physical eraseblocks.
+                * One more erase operation has happened, take care about
+                * protected physical eraseblocks.
                 */
                check_protection_over(ubi);
 
@@ -1136,7 +1137,7 @@ out_ro:
 }
 
 /**
- * ubi_wl_put_peb - return a physical eraseblock to the wear-leveling unit.
+ * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system.
  * @ubi: UBI device description object
  * @pnum: physical eraseblock to return
  * @torture: if this physical eraseblock has to be tortured
@@ -1175,11 +1176,11 @@ retry:
                /*
                 * User is putting the physical eraseblock which was selected
                 * as the target the data is moved to. It may happen if the EBA
-                * unit already re-mapped the LEB in 'ubi_eba_copy_leb()' but
-                * the WL unit has not put the PEB to the "used" tree yet, but
-                * it is about to do this. So we just set a flag which will
-                * tell the WL worker that the PEB is not needed anymore and
-                * should be scheduled for erasure.
+                * sub-system already re-mapped the LEB in 'ubi_eba_copy_leb()'
+                * but the WL sub-system has not put the PEB to the "used" tree
+                * yet, but it is about to do this. So we just set a flag which
+                * will tell the WL worker that the PEB is not needed anymore
+                * and should be scheduled for erasure.
                 */
                dbg_wl("PEB %d is the target of data moving", pnum);
                ubi_assert(!ubi->move_to_put);
@@ -1229,7 +1230,7 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum)
 {
        struct ubi_wl_entry *e;
 
-       ubi_msg("schedule PEB %d for scrubbing", pnum);
+       dbg_msg("schedule PEB %d for scrubbing", pnum);
 
 retry:
        spin_lock(&ubi->wl_lock);
@@ -1368,7 +1369,7 @@ int ubi_thread(void *u)
                int err;
 
                if (kthread_should_stop())
-                       goto out;
+                       break;
 
                if (try_to_freeze())
                        continue;
@@ -1403,7 +1404,6 @@ int ubi_thread(void *u)
                cond_resched();
        }
 
-out:
        dbg_wl("background thread \"%s\" is killed", ubi->bgt_name);
        return 0;
 }
@@ -1426,8 +1426,7 @@ static void cancel_pending(struct ubi_device *ubi)
 }
 
 /**
- * ubi_wl_init_scan - initialize the wear-leveling unit using scanning
- * information.
+ * ubi_wl_init_scan - initialize the WL sub-system using scanning information.
  * @ubi: UBI device description object
  * @si: scanning information
  *
@@ -1584,13 +1583,12 @@ static void protection_trees_destroy(struct ubi_device *ubi)
 }
 
 /**
- * ubi_wl_close - close the wear-leveling unit.
+ * ubi_wl_close - close the wear-leveling sub-system.
  * @ubi: UBI device description object
  */
 void ubi_wl_close(struct ubi_device *ubi)
 {
-       dbg_wl("close the UBI wear-leveling unit");
-
+       dbg_wl("close the WL sub-system");
        cancel_pending(ubi);
        protection_trees_destroy(ubi);
        tree_destroy(&ubi->used);
@@ -1602,8 +1600,7 @@ void ubi_wl_close(struct ubi_device *ubi)
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 
 /**
- * paranoid_check_ec - make sure that the erase counter of a physical eraseblock
- * is correct.
+ * paranoid_check_ec - make sure that the erase counter of a PEB is correct.
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock number to check
  * @ec: the erase counter to check
@@ -1644,13 +1641,12 @@ out_free:
 }
 
 /**
- * paranoid_check_in_wl_tree - make sure that a wear-leveling entry is present
- * in a WL RB-tree.
+ * paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
  * @e: the wear-leveling entry to check
  * @root: the root of the tree
  *
- * This function returns zero if @e is in the @root RB-tree and %1 if it
- * is not.
+ * This function returns zero if @e is in the @root RB-tree and %1 if it is
+ * not.
  */
 static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
                                     struct rb_root *root)
index 7a14980f3472d133da546174cef0f6365ffb4772..18d3eeb7eab26188501967dcf4fc9b95d773210c 100644 (file)
@@ -482,7 +482,7 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep)
                        goto err;
 
                d = dma_map_single(NULL, page, PAGE_SIZE, DMA_FROM_DEVICE);
-               if (dma_mapping_error(d)) {
+               if (dma_mapping_error(NULL, d)) {
                        free_page((unsigned long)page);
                        goto err;
                }
@@ -505,7 +505,7 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep)
                        goto err;
 
                d = dma_map_single(NULL, page, PAGE_SIZE, DMA_TO_DEVICE);
-               if (dma_mapping_error(d)) {
+               if (dma_mapping_error(NULL, d)) {
                        free_page((unsigned long)page);
                        goto err;
                }
index 0263bef9cc6ddfb2cfa428ebe1ad6a104d27b49c..af251a5df844929097ef67adb394936871bbec3b 100644 (file)
@@ -814,7 +814,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        }
 
        /* release skb */
-       BUG_TRAP(skb);
+       WARN_ON(!skb);
        dev_kfree_skb(skb);
        tx_buf->first_bd = 0;
        tx_buf->skb = NULL;
@@ -837,9 +837,9 @@ static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
        used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS;
 
 #ifdef BNX2X_STOP_ON_ERROR
-       BUG_TRAP(used >= 0);
-       BUG_TRAP(used <= fp->bp->tx_ring_size);
-       BUG_TRAP((fp->bp->tx_ring_size - used) <= MAX_TX_AVAIL);
+       WARN_ON(used < 0);
+       WARN_ON(used > fp->bp->tx_ring_size);
+       WARN_ON((fp->bp->tx_ring_size - used) > MAX_TX_AVAIL);
 #endif
 
        return (s16)(fp->bp->tx_ring_size) - used;
@@ -1020,7 +1020,7 @@ static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp,
 
        mapping = pci_map_page(bp->pdev, page, 0, BCM_PAGE_SIZE*PAGES_PER_SGE,
                               PCI_DMA_FROMDEVICE);
-       if (unlikely(dma_mapping_error(mapping))) {
+       if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
                __free_pages(page, PAGES_PER_SGE_SHIFT);
                return -ENOMEM;
        }
@@ -1048,7 +1048,7 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
 
        mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
                                 PCI_DMA_FROMDEVICE);
-       if (unlikely(dma_mapping_error(mapping))) {
+       if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
                dev_kfree_skb(skb);
                return -ENOMEM;
        }
@@ -4374,7 +4374,7 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
                        }
                        ring_prod = NEXT_RX_IDX(ring_prod);
                        cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod);
-                       BUG_TRAP(ring_prod > i);
+                       WARN_ON(ring_prod <= i);
                }
 
                fp->rx_bd_prod = ring_prod;
index 83768df27806be9394fb087acac83ee6f87f08a0..f1936d51b458e387e3ba0ffef867f1e388bb8a90 100644 (file)
@@ -576,6 +576,18 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags)
        list_for_each_safe(elem, tmp, &list) {
                cas_page_t *page = list_entry(elem, cas_page_t, list);
 
+               /*
+                * With the lockless pagecache, cassini buffering scheme gets
+                * slightly less accurate: we might find that a page has an
+                * elevated reference count here, due to a speculative ref,
+                * and skip it as in-use. Ideally we would be able to reclaim
+                * it. However this would be such a rare case, it doesn't
+                * matter too much as we should pick it up the next time round.
+                *
+                * Importantly, if we find that the page has a refcount of 1
+                * here (our refcount), then we know it is definitely not inuse
+                * so we can reuse it.
+                */
                if (page_count(page->buffer) > 1)
                        continue;
 
index a96331c875e69cf0d07a9398cf4f74692c06faae..1b0861d73ab7d00ef103ab2d58de7975b134ab20 100644 (file)
@@ -386,7 +386,7 @@ static inline int add_one_rx_buf(void *va, unsigned int len,
        dma_addr_t mapping;
 
        mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE);
-       if (unlikely(pci_dma_mapping_error(mapping)))
+       if (unlikely(pci_dma_mapping_error(pdev, mapping)))
                return -ENOMEM;
 
        pci_unmap_addr_set(sd, dma_addr, mapping);
index 1037b1332312998aa36274b279381263419f0371..19d32a227be14c3202f1773da8dda65898503bc0 100644 (file)
@@ -1790,7 +1790,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
        rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
                RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
 
-       if (pci_dma_mapping_error(rx->dma_addr)) {
+       if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) {
                dev_kfree_skb_any(rx->skb);
                rx->skb = NULL;
                rx->dma_addr = 0;
index a14561f40db0fddd497b4894c6b67db1d8996dc2..9350564065e7713f900dcbc77acae0fc463728b7 100644 (file)
@@ -1090,7 +1090,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
                tx_ring->buffer_info[i].dma =
                        pci_map_single(pdev, skb->data, skb->len,
                                       PCI_DMA_TODEVICE);
-               if (pci_dma_mapping_error(tx_ring->buffer_info[i].dma)) {
+               if (pci_dma_mapping_error(pdev, tx_ring->buffer_info[i].dma)) {
                        ret_val = 4;
                        goto err_nomem;
                }
@@ -1153,7 +1153,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
                rx_ring->buffer_info[i].dma =
                        pci_map_single(pdev, skb->data, 2048,
                                       PCI_DMA_FROMDEVICE);
-               if (pci_dma_mapping_error(rx_ring->buffer_info[i].dma)) {
+               if (pci_dma_mapping_error(pdev, rx_ring->buffer_info[i].dma)) {
                        ret_val = 8;
                        goto err_nomem;
                }
index 869544b8c05c2b184ccf3703398419af2cc550f0..d1367789976740f829083d63ed787b788e854e01 100644 (file)
@@ -195,7 +195,7 @@ map_skb:
                buffer_info->dma = pci_map_single(pdev, skb->data,
                                                  adapter->rx_buffer_len,
                                                  PCI_DMA_FROMDEVICE);
-               if (pci_dma_mapping_error(buffer_info->dma)) {
+               if (pci_dma_mapping_error(pdev, buffer_info->dma)) {
                        dev_err(&pdev->dev, "RX DMA map failed\n");
                        adapter->rx_dma_failed++;
                        break;
@@ -265,7 +265,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
                                                   ps_page->page,
                                                   0, PAGE_SIZE,
                                                   PCI_DMA_FROMDEVICE);
-                               if (pci_dma_mapping_error(ps_page->dma)) {
+                               if (pci_dma_mapping_error(pdev, ps_page->dma)) {
                                        dev_err(&adapter->pdev->dev,
                                          "RX DMA page map failed\n");
                                        adapter->rx_dma_failed++;
@@ -300,7 +300,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
                buffer_info->dma = pci_map_single(pdev, skb->data,
                                                  adapter->rx_ps_bsize0,
                                                  PCI_DMA_FROMDEVICE);
-               if (pci_dma_mapping_error(buffer_info->dma)) {
+               if (pci_dma_mapping_error(pdev, buffer_info->dma)) {
                        dev_err(&pdev->dev, "RX DMA map failed\n");
                        adapter->rx_dma_failed++;
                        /* cleanup skb */
@@ -3344,7 +3344,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
                                skb->data + offset,
                                size,
                                PCI_DMA_TODEVICE);
-               if (pci_dma_mapping_error(buffer_info->dma)) {
+               if (pci_dma_mapping_error(adapter->pdev, buffer_info->dma)) {
                        dev_err(&adapter->pdev->dev, "TX DMA map failed\n");
                        adapter->tx_dma_failed++;
                        return -1;
@@ -3382,7 +3382,8 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
                                        offset,
                                        size,
                                        PCI_DMA_TODEVICE);
-                       if (pci_dma_mapping_error(buffer_info->dma)) {
+                       if (pci_dma_mapping_error(adapter->pdev,
+                                                 buffer_info->dma)) {
                                dev_err(&adapter->pdev->dev,
                                        "TX DMA page map failed\n");
                                adapter->tx_dma_failed++;
@@ -4067,8 +4068,6 @@ static void e1000_netpoll(struct net_device *netdev)
        disable_irq(adapter->pdev->irq);
        e1000_intr(adapter->pdev->irq, netdev);
 
-       e1000_clean_tx_irq(adapter);
-
        enable_irq(adapter->pdev->irq);
 }
 #endif
index 32a4f17d35fc5f1387ca232bc7100761cc7bcafe..ecd5c71a7a8a5f6470f7362a051434f61529e5b3 100644 (file)
@@ -2,12 +2,6 @@
  * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
  * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
  *
- * This version of the driver is specific to the FADS implementation,
- * since the board contains control registers external to the processor
- * for the control of the LevelOne LXT970 transceiver.  The MPC860T manual
- * describes connections using the internal parallel port I/O, which
- * is basically all of Port D.
- *
  * Right now, I am very wasteful with the buffers.  I allocate memory
  * pages and then divide them into 2K frame buffers.  This way I know I
  * have buffers large enough to hold one frame within one buffer descriptor.
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
-    defined(CONFIG_M5272) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x)
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include "fec.h"
-#else
-#include <asm/8xx_immap.h>
-#include <asm/mpc8xx.h>
-#include "commproc.h"
-#endif
 
 #if defined(CONFIG_FEC2)
 #define        FEC_MAX_PORTS   2
@@ -67,7 +53,7 @@
 #define        FEC_MAX_PORTS   1
 #endif
 
-#if defined(CONFIG_FADS) || defined(CONFIG_RPXCLASSIC) || defined(CONFIG_M5272)
+#if defined(CONFIG_M5272)
 #define HAVE_mii_link_interrupt
 #endif
 
@@ -1235,14 +1221,9 @@ static phy_info_t const * const phy_info[] = {
 
 /* ------------------------------------------------------------------------- */
 #ifdef HAVE_mii_link_interrupt
-#ifdef CONFIG_RPXCLASSIC
-static void
-mii_link_interrupt(void *dev_id);
-#else
 static irqreturn_t
 mii_link_interrupt(int irq, void * dev_id);
 #endif
-#endif
 
 #if defined(CONFIG_M5272)
 /*
@@ -1795,24 +1776,6 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
 
        if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0)
                panic("Could not allocate FEC IRQ!");
-
-#ifdef CONFIG_RPXCLASSIC
-       /* Make Port C, bit 15 an input that causes interrupts.
-       */
-       immap->im_ioport.iop_pcpar &= ~0x0001;
-       immap->im_ioport.iop_pcdir &= ~0x0001;
-       immap->im_ioport.iop_pcso &= ~0x0001;
-       immap->im_ioport.iop_pcint |= 0x0001;
-       cpm_install_handler(CPMVEC_PIO_PC15, mii_link_interrupt, dev);
-
-       /* Make LEDS reflect Link status.
-       */
-       *((uint *) RPX_CSR_ADDR) &= ~BCSR2_FETHLEDMODE;
-#endif
-#ifdef CONFIG_FADS
-       if (request_8xxirq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0)
-               panic("Could not allocate MII IRQ!");
-#endif
 }
 
 static void __inline__ fec_get_mac(struct net_device *dev)
@@ -1821,16 +1784,6 @@ static void __inline__ fec_get_mac(struct net_device *dev)
 
        bd = (bd_t *)__res;
        memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
-
-#ifdef CONFIG_RPXCLASSIC
-       /* The Embedded Planet boards have only one MAC address in
-        * the EEPROM, but can have two Ethernet ports.  For the
-        * FEC port, we create another address by setting one of
-        * the address bits above something that would have (up to
-        * now) been allocated.
-        */
-       dev->dev_adrd[3] |= 0x80;
-#endif
 }
 
 static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
@@ -2109,13 +2062,8 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
 /* This interrupt occurs when the PHY detects a link change.
 */
 #ifdef HAVE_mii_link_interrupt
-#ifdef CONFIG_RPXCLASSIC
-static void
-mii_link_interrupt(void *dev_id)
-#else
 static irqreturn_t
 mii_link_interrupt(int irq, void * dev_id)
-#endif
 {
        struct  net_device *dev = dev_id;
        struct fec_enet_private *fep = netdev_priv(dev);
index 00527805e4f170a8a1bdb6888aa2a30829210d6b..a03fe1fb61ca4caf7b6f1faca1ee9da359c25ca6 100644 (file)
@@ -33,6 +33,7 @@
 */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
@@ -52,7 +53,9 @@
 #include <asm/hvcall.h>
 #include <asm/atomic.h>
 #include <asm/vio.h>
+#include <asm/iommu.h>
 #include <asm/uaccess.h>
+#include <asm/firmware.h>
 #include <linux/seq_file.h>
 
 #include "ibmveth.h"
@@ -94,8 +97,10 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
 static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance);
 static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
+static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev);
 static struct kobj_type ktype_veth_pool;
 
+
 #ifdef CONFIG_PROC_FS
 #define IBMVETH_PROC_DIR "ibmveth"
 static struct proc_dir_entry *ibmveth_proc_dir;
@@ -226,16 +231,16 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
        u32 i;
        u32 count = pool->size - atomic_read(&pool->available);
        u32 buffers_added = 0;
+       struct sk_buff *skb;
+       unsigned int free_index, index;
+       u64 correlator;
+       unsigned long lpar_rc;
+       dma_addr_t dma_addr;
 
        mb();
 
        for(i = 0; i < count; ++i) {
-               struct sk_buff *skb;
-               unsigned int free_index, index;
-               u64 correlator;
                union ibmveth_buf_desc desc;
-               unsigned long lpar_rc;
-               dma_addr_t dma_addr;
 
                skb = alloc_skb(pool->buff_size, GFP_ATOMIC);
 
@@ -255,6 +260,9 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
                dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
                                pool->buff_size, DMA_FROM_DEVICE);
 
+               if (dma_mapping_error(&adapter->vdev->dev, dma_addr))
+                       goto failure;
+
                pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
                pool->dma_addr[index] = dma_addr;
                pool->skbuff[index] = skb;
@@ -267,25 +275,32 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
 
                lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
 
-               if(lpar_rc != H_SUCCESS) {
-                       pool->free_map[free_index] = index;
-                       pool->skbuff[index] = NULL;
-                       if (pool->consumer_index == 0)
-                               pool->consumer_index = pool->size - 1;
-                       else
-                               pool->consumer_index--;
-                       dma_unmap_single(&adapter->vdev->dev,
-                                       pool->dma_addr[index], pool->buff_size,
-                                       DMA_FROM_DEVICE);
-                       dev_kfree_skb_any(skb);
-                       adapter->replenish_add_buff_failure++;
-                       break;
-               } else {
+               if (lpar_rc != H_SUCCESS)
+                       goto failure;
+               else {
                        buffers_added++;
                        adapter->replenish_add_buff_success++;
                }
        }
 
+       mb();
+       atomic_add(buffers_added, &(pool->available));
+       return;
+
+failure:
+       pool->free_map[free_index] = index;
+       pool->skbuff[index] = NULL;
+       if (pool->consumer_index == 0)
+               pool->consumer_index = pool->size - 1;
+       else
+               pool->consumer_index--;
+       if (!dma_mapping_error(&adapter->vdev->dev, dma_addr))
+               dma_unmap_single(&adapter->vdev->dev,
+                                pool->dma_addr[index], pool->buff_size,
+                                DMA_FROM_DEVICE);
+       dev_kfree_skb_any(skb);
+       adapter->replenish_add_buff_failure++;
+
        mb();
        atomic_add(buffers_added, &(pool->available));
 }
@@ -297,7 +312,7 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
 
        adapter->replenish_task_cycles++;
 
-       for(i = 0; i < IbmVethNumBufferPools; i++)
+       for (i = (IbmVethNumBufferPools - 1); i >= 0; i--)
                if(adapter->rx_buff_pool[i].active)
                        ibmveth_replenish_buffer_pool(adapter,
                                                     &adapter->rx_buff_pool[i]);
@@ -433,11 +448,11 @@ static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter)
 static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
 {
        int i;
+       struct device *dev = &adapter->vdev->dev;
 
        if(adapter->buffer_list_addr != NULL) {
-               if(!dma_mapping_error(adapter->buffer_list_dma)) {
-                       dma_unmap_single(&adapter->vdev->dev,
-                                       adapter->buffer_list_dma, 4096,
+               if (!dma_mapping_error(dev, adapter->buffer_list_dma)) {
+                       dma_unmap_single(dev, adapter->buffer_list_dma, 4096,
                                        DMA_BIDIRECTIONAL);
                        adapter->buffer_list_dma = DMA_ERROR_CODE;
                }
@@ -446,9 +461,8 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
        }
 
        if(adapter->filter_list_addr != NULL) {
-               if(!dma_mapping_error(adapter->filter_list_dma)) {
-                       dma_unmap_single(&adapter->vdev->dev,
-                                       adapter->filter_list_dma, 4096,
+               if (!dma_mapping_error(dev, adapter->filter_list_dma)) {
+                       dma_unmap_single(dev, adapter->filter_list_dma, 4096,
                                        DMA_BIDIRECTIONAL);
                        adapter->filter_list_dma = DMA_ERROR_CODE;
                }
@@ -457,8 +471,8 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
        }
 
        if(adapter->rx_queue.queue_addr != NULL) {
-               if(!dma_mapping_error(adapter->rx_queue.queue_dma)) {
-                       dma_unmap_single(&adapter->vdev->dev,
+               if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) {
+                       dma_unmap_single(dev,
                                        adapter->rx_queue.queue_dma,
                                        adapter->rx_queue.queue_len,
                                        DMA_BIDIRECTIONAL);
@@ -472,6 +486,18 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
                if (adapter->rx_buff_pool[i].active)
                        ibmveth_free_buffer_pool(adapter,
                                                 &adapter->rx_buff_pool[i]);
+
+       if (adapter->bounce_buffer != NULL) {
+               if (!dma_mapping_error(dev, adapter->bounce_buffer_dma)) {
+                       dma_unmap_single(&adapter->vdev->dev,
+                                       adapter->bounce_buffer_dma,
+                                       adapter->netdev->mtu + IBMVETH_BUFF_OH,
+                                       DMA_BIDIRECTIONAL);
+                       adapter->bounce_buffer_dma = DMA_ERROR_CODE;
+               }
+               kfree(adapter->bounce_buffer);
+               adapter->bounce_buffer = NULL;
+       }
 }
 
 static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
@@ -508,6 +534,7 @@ static int ibmveth_open(struct net_device *netdev)
        int rc;
        union ibmveth_buf_desc rxq_desc;
        int i;
+       struct device *dev;
 
        ibmveth_debug_printk("open starting\n");
 
@@ -536,17 +563,19 @@ static int ibmveth_open(struct net_device *netdev)
                return -ENOMEM;
        }
 
-       adapter->buffer_list_dma = dma_map_single(&adapter->vdev->dev,
+       dev = &adapter->vdev->dev;
+
+       adapter->buffer_list_dma = dma_map_single(dev,
                        adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL);
-       adapter->filter_list_dma = dma_map_single(&adapter->vdev->dev,
+       adapter->filter_list_dma = dma_map_single(dev,
                        adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL);
-       adapter->rx_queue.queue_dma = dma_map_single(&adapter->vdev->dev,
+       adapter->rx_queue.queue_dma = dma_map_single(dev,
                        adapter->rx_queue.queue_addr,
                        adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL);
 
-       if((dma_mapping_error(adapter->buffer_list_dma) ) ||
-          (dma_mapping_error(adapter->filter_list_dma)) ||
-          (dma_mapping_error(adapter->rx_queue.queue_dma))) {
+       if ((dma_mapping_error(dev, adapter->buffer_list_dma)) ||
+           (dma_mapping_error(dev, adapter->filter_list_dma)) ||
+           (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) {
                ibmveth_error_printk("unable to map filter or buffer list pages\n");
                ibmveth_cleanup(adapter);
                napi_disable(&adapter->napi);
@@ -607,6 +636,24 @@ static int ibmveth_open(struct net_device *netdev)
                return rc;
        }
 
+       adapter->bounce_buffer =
+           kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL);
+       if (!adapter->bounce_buffer) {
+               ibmveth_error_printk("unable to allocate bounce buffer\n");
+               ibmveth_cleanup(adapter);
+               napi_disable(&adapter->napi);
+               return -ENOMEM;
+       }
+       adapter->bounce_buffer_dma =
+           dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer,
+                          netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(dev, adapter->bounce_buffer_dma)) {
+               ibmveth_error_printk("unable to map bounce buffer\n");
+               ibmveth_cleanup(adapter);
+               napi_disable(&adapter->napi);
+               return -ENOMEM;
+       }
+
        ibmveth_debug_printk("initial replenish cycle\n");
        ibmveth_interrupt(netdev->irq, netdev);
 
@@ -853,10 +900,12 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
        unsigned int tx_packets = 0;
        unsigned int tx_send_failed = 0;
        unsigned int tx_map_failed = 0;
+       int used_bounce = 0;
+       unsigned long data_dma_addr;
 
        desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len;
-       desc.fields.address = dma_map_single(&adapter->vdev->dev, skb->data,
-                                            skb->len, DMA_TO_DEVICE);
+       data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
+                                      skb->len, DMA_TO_DEVICE);
 
        if (skb->ip_summed == CHECKSUM_PARTIAL &&
            ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
@@ -875,12 +924,16 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                buf[1] = 0;
        }
 
-       if (dma_mapping_error(desc.fields.address)) {
-               ibmveth_error_printk("tx: unable to map xmit buffer\n");
+       if (dma_mapping_error(&adapter->vdev->dev, data_dma_addr)) {
+               if (!firmware_has_feature(FW_FEATURE_CMO))
+                       ibmveth_error_printk("tx: unable to map xmit buffer\n");
+               skb_copy_from_linear_data(skb, adapter->bounce_buffer,
+                                         skb->len);
+               desc.fields.address = adapter->bounce_buffer_dma;
                tx_map_failed++;
-               tx_dropped++;
-               goto out;
-       }
+               used_bounce = 1;
+       } else
+               desc.fields.address = data_dma_addr;
 
        /* send the frame. Arbitrarily set retrycount to 1024 */
        correlator = 0;
@@ -904,8 +957,9 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                netdev->trans_start = jiffies;
        }
 
-       dma_unmap_single(&adapter->vdev->dev, desc.fields.address,
-                        skb->len, DMA_TO_DEVICE);
+       if (!used_bounce)
+               dma_unmap_single(&adapter->vdev->dev, data_dma_addr,
+                                skb->len, DMA_TO_DEVICE);
 
 out:   spin_lock_irqsave(&adapter->stats_lock, flags);
        netdev->stats.tx_dropped += tx_dropped;
@@ -1053,9 +1107,9 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
 static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct ibmveth_adapter *adapter = dev->priv;
+       struct vio_dev *viodev = adapter->vdev;
        int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
-       int reinit = 0;
-       int i, rc;
+       int i;
 
        if (new_mtu < IBMVETH_MAX_MTU)
                return -EINVAL;
@@ -1067,23 +1121,34 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
        if (i == IbmVethNumBufferPools)
                return -EINVAL;
 
+       /* Deactivate all the buffer pools so that the next loop can activate
+          only the buffer pools necessary to hold the new MTU */
+       for (i = 0; i < IbmVethNumBufferPools; i++)
+               if (adapter->rx_buff_pool[i].active) {
+                       ibmveth_free_buffer_pool(adapter,
+                                                &adapter->rx_buff_pool[i]);
+                       adapter->rx_buff_pool[i].active = 0;
+               }
+
        /* Look for an active buffer pool that can hold the new MTU */
        for(i = 0; i<IbmVethNumBufferPools; i++) {
-               if (!adapter->rx_buff_pool[i].active) {
-                       adapter->rx_buff_pool[i].active = 1;
-                       reinit = 1;
-               }
+               adapter->rx_buff_pool[i].active = 1;
 
                if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
-                       if (reinit && netif_running(adapter->netdev)) {
+                       if (netif_running(adapter->netdev)) {
                                adapter->pool_config = 1;
                                ibmveth_close(adapter->netdev);
                                adapter->pool_config = 0;
                                dev->mtu = new_mtu;
-                               if ((rc = ibmveth_open(adapter->netdev)))
-                                       return rc;
-                       } else
-                               dev->mtu = new_mtu;
+                               vio_cmo_set_dev_desired(viodev,
+                                               ibmveth_get_desired_dma
+                                               (viodev));
+                               return ibmveth_open(adapter->netdev);
+                       }
+                       dev->mtu = new_mtu;
+                       vio_cmo_set_dev_desired(viodev,
+                                               ibmveth_get_desired_dma
+                                               (viodev));
                        return 0;
                }
        }
@@ -1098,6 +1163,46 @@ static void ibmveth_poll_controller(struct net_device *dev)
 }
 #endif
 
+/**
+ * ibmveth_get_desired_dma - Calculate IO memory desired by the driver
+ *
+ * @vdev: struct vio_dev for the device whose desired IO mem is to be returned
+ *
+ * Return value:
+ *     Number of bytes of IO data the driver will need to perform well.
+ */
+static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev)
+{
+       struct net_device *netdev = dev_get_drvdata(&vdev->dev);
+       struct ibmveth_adapter *adapter;
+       unsigned long ret;
+       int i;
+       int rxqentries = 1;
+
+       /* netdev inits at probe time along with the structures we need below*/
+       if (netdev == NULL)
+               return IOMMU_PAGE_ALIGN(IBMVETH_IO_ENTITLEMENT_DEFAULT);
+
+       adapter = netdev_priv(netdev);
+
+       ret = IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE;
+       ret += IOMMU_PAGE_ALIGN(netdev->mtu);
+
+       for (i = 0; i < IbmVethNumBufferPools; i++) {
+               /* add the size of the active receive buffers */
+               if (adapter->rx_buff_pool[i].active)
+                       ret +=
+                           adapter->rx_buff_pool[i].size *
+                           IOMMU_PAGE_ALIGN(adapter->rx_buff_pool[i].
+                                   buff_size);
+               rxqentries += adapter->rx_buff_pool[i].size;
+       }
+       /* add the size of the receive queue entries */
+       ret += IOMMU_PAGE_ALIGN(rxqentries * sizeof(struct ibmveth_rx_q_entry));
+
+       return ret;
+}
+
 static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 {
        int rc, i;
@@ -1242,6 +1347,8 @@ static int __devexit ibmveth_remove(struct vio_dev *dev)
        ibmveth_proc_unregister_adapter(adapter);
 
        free_netdev(netdev);
+       dev_set_drvdata(&dev->dev, NULL);
+
        return 0;
 }
 
@@ -1402,14 +1509,15 @@ const char * buf, size_t count)
                                return -EPERM;
                        }
 
-                       pool->active = 0;
                        if (netif_running(netdev)) {
                                adapter->pool_config = 1;
                                ibmveth_close(netdev);
+                               pool->active = 0;
                                adapter->pool_config = 0;
                                if ((rc = ibmveth_open(netdev)))
                                        return rc;
                        }
+                       pool->active = 0;
                }
        } else if (attr == &veth_num_attr) {
                if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
@@ -1485,6 +1593,7 @@ static struct vio_driver ibmveth_driver = {
        .id_table       = ibmveth_device_table,
        .probe          = ibmveth_probe,
        .remove         = ibmveth_remove,
+       .get_desired_dma = ibmveth_get_desired_dma,
        .driver         = {
                .name   = ibmveth_driver_name,
                .owner  = THIS_MODULE,
index 41f61cd18852b26cd7f6bfc36808588fc2b230e6..d281869487526371e28b1eb2254a5ff0d91f2a2b 100644 (file)
@@ -93,9 +93,12 @@ static inline long h_illan_attributes(unsigned long unit_address,
   plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
 
 #define IbmVethNumBufferPools 5
+#define IBMVETH_IO_ENTITLEMENT_DEFAULT 4243456 /* MTU of 1500 needs 4.2Mb */
 #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
 #define IBMVETH_MAX_MTU 68
 #define IBMVETH_MAX_POOL_COUNT 4096
+#define IBMVETH_BUFF_LIST_SIZE 4096
+#define IBMVETH_FILT_LIST_SIZE 4096
 #define IBMVETH_MAX_BUF_SIZE (1024 * 128)
 
 static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
@@ -143,6 +146,8 @@ struct ibmveth_adapter {
     struct ibmveth_rx_q rx_queue;
     int pool_config;
     int rx_csum;
+    void *bounce_buffer;
+    dma_addr_t bounce_buffer_dma;
 
     /* adapter specific stats */
     u64 replenish_task_cycles;
index b8d0639c1cdfa655c2b3ab5f499de6310668cc02..c46864d626b28e44b7e25669ea319d1f74a2dd53 100644 (file)
@@ -1128,7 +1128,7 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
        msg->data.addr[0] = dma_map_single(port->dev, skb->data,
                                skb->len, DMA_TO_DEVICE);
 
-       if (dma_mapping_error(msg->data.addr[0]))
+       if (dma_mapping_error(port->dev, msg->data.addr[0]))
                goto recycle_and_drop;
 
        msg->dev = port->dev;
@@ -1226,7 +1226,7 @@ static void veth_recycle_msg(struct veth_lpar_connection *cnx,
                dma_address = msg->data.addr[0];
                dma_length = msg->data.len[0];
 
-               if (!dma_mapping_error(dma_address))
+               if (!dma_mapping_error(msg->dev, dma_address))
                        dma_unmap_single(msg->dev, dma_address, dma_length,
                                        DMA_TO_DEVICE);
 
index f9d6b4dca180e49f6d16fc4ebfe594831cc0cf29..096bca54bcf77c33300d43b7e46a7734434378c0 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index aa95287790442e83e623e8a5f4895db5f5c1dcf5..f094ee00c416a240cd564089d10ba5d0bba067b1 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 70dff94a8bc616f11e984559a91fbf6db1598294..2845a0560b84e18fcd28c64e9caa145b59c9a034 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -67,6 +67,8 @@ enum {
        CMD_STAT_BAD_INDEX      = 0x0a,
        /* FW image corrupted: */
        CMD_STAT_BAD_NVMEM      = 0x0b,
+       /* Error in ICM mapping (e.g. not enough auxiliary ICM pages to execute command): */
+       CMD_STAT_ICM_ERROR      = 0x0c,
        /* Attempt to modify a QP/EE which is not in the presumed state: */
        CMD_STAT_BAD_QP_STATE   = 0x10,
        /* Bad segment parameters (Address/Size): */
@@ -119,6 +121,7 @@ static int mlx4_status_to_errno(u8 status)
                [CMD_STAT_BAD_RES_STATE]  = -EBADF,
                [CMD_STAT_BAD_INDEX]      = -EBADF,
                [CMD_STAT_BAD_NVMEM]      = -EFAULT,
+               [CMD_STAT_ICM_ERROR]      = -ENFILE,
                [CMD_STAT_BAD_QP_STATE]   = -EINVAL,
                [CMD_STAT_BAD_SEG_PARAM]  = -EFAULT,
                [CMD_STAT_REG_BOUND]      = -EBUSY,
index 95e87a2f8896f97ca5110613fdcd2a6527ccfc5f..9bb50e3f8974386ff329d0d2d97671d27bf8a5f6 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index e141a1513f079427e6e7e881b587c3cf317ab500..8a8b56135a58bda015fac0a4b184b4e344072072 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -33,6 +33,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/mm.h>
 #include <linux/dma-mapping.h>
 
 #include <linux/mlx4/cmd.h>
@@ -525,7 +526,7 @@ int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt)
                return -ENOMEM;
        priv->eq_table.icm_dma  = pci_map_page(dev->pdev, priv->eq_table.icm_page, 0,
                                               PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-       if (pci_dma_mapping_error(priv->eq_table.icm_dma)) {
+       if (pci_dma_mapping_error(dev->pdev, priv->eq_table.icm_dma)) {
                __free_page(priv->eq_table.icm_page);
                return -ENOMEM;
        }
index 2b5006b9be67964239fa0e2b0ebc87df7050ffdf..7e32955da9829afcc9b80c16f2a06bae1402af96 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -46,6 +46,10 @@ enum {
 extern void __buggy_use_of_MLX4_GET(void);
 extern void __buggy_use_of_MLX4_PUT(void);
 
+static int enable_qos;
+module_param(enable_qos, bool, 0444);
+MODULE_PARM_DESC(enable_qos, "Enable Quality of Service support in the HCA (default: off)");
+
 #define MLX4_GET(dest, source, offset)                               \
        do {                                                          \
                void *__p = (char *) (source) + (offset);             \
@@ -198,7 +202,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET    0x8e
 #define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET      0x90
 #define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET    0x92
-#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET                0x97
+#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET                0x94
 #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET         0x98
 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET                0xa0
 
@@ -373,12 +377,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
                }
        }
 
-       if (dev_cap->bmme_flags & 1)
-               mlx4_dbg(dev, "Base MM extensions: yes "
-                        "(flags %d, rsvd L_Key %08x)\n",
-                        dev_cap->bmme_flags, dev_cap->reserved_lkey);
-       else
-               mlx4_dbg(dev, "Base MM extensions: no\n");
+       mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n",
+                dev_cap->bmme_flags, dev_cap->reserved_lkey);
 
        /*
         * Each UAR has 4 EQ doorbells; so if a UAR is reserved, then
@@ -737,6 +737,10 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
        if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
                *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3);
 
+       /* Enable QoS support if module parameter set */
+       if (enable_qos)
+               *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2);
+
        /* QPC/EEC/CQC/EQC/RDMARC attributes */
 
        MLX4_PUT(inbox, param->qpc_base,      INIT_HCA_QPC_BASE_OFFSET);
index a0e046c149b78c18c359826389145ab93e63f556..decbb5c2ad41b7379ddbe5b5ce8df81abc4243ca 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2006, 2007 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -98,7 +98,7 @@ struct mlx4_dev_cap {
        int cmpt_entry_sz;
        int mtt_entry_sz;
        int resize_srq;
-       u bmme_flags;
+       u32 bmme_flags;
        u32 reserved_lkey;
        u64 max_icm_sz;
        int max_gso_sz;
index 2a5bef6388fec9fb28995edb44e350474f60a1d7..baf4bf66062ca6a91652eb6bd5e5224b3ffb9440 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 6c44edf35847e07c1de518f2bc78d4dbe70947b7..ab56a2f89b651eb3c33cba5da21e1686a21bb98e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 4a6c4d526f1b51e72dad933fed05558faf8f57e5..0e7eb1038f9f443e8b0af3525a5fd9b871c608d7 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index d3736013fe9b7ca9b46847ebd2d5cae462c9524d..1252a919de2eb9bd43e8e3c92aa5792b47e81932 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -158,6 +158,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
        dev->caps.max_msg_sz         = dev_cap->max_msg_sz;
        dev->caps.page_size_cap      = ~(u32) (dev_cap->min_page_sz - 1);
        dev->caps.flags              = dev_cap->flags;
+       dev->caps.bmme_flags         = dev_cap->bmme_flags;
+       dev->caps.reserved_lkey      = dev_cap->reserved_lkey;
        dev->caps.stat_rate_support  = dev_cap->stat_rate_support;
        dev->caps.max_gso_sz         = dev_cap->max_gso_sz;
 
index b4b57870ddfdbefc7ecb26ff0167eed4d398e3c5..c83f88ce073663697e7cff88b6a6428e59b1b547 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index a4023c2dd05092762ba3f8be32ef9fac5b1a7652..5337e3ac3e78c152143e31bc2283f2dc2c7b1752 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  * Copyright (c) 2005, 2006, 2007 Cisco Systems.  All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -118,6 +118,7 @@ struct mlx4_bitmap {
 
 struct mlx4_buddy {
        unsigned long         **bits;
+       unsigned int           *num_free;
        int                     max_order;
        spinlock_t              lock;
 };
index 03a9abcce5240bbe53be4783e25584b010dcd68b..62071d9c4a557c61a38da5167cf2d017590b5ac7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -47,7 +47,7 @@ struct mlx4_mpt_entry {
        __be32 flags;
        __be32 qpn;
        __be32 key;
-       __be32 pd;
+       __be32 pd_flags;
        __be64 start;
        __be64 length;
        __be32 lkey;
@@ -61,11 +61,15 @@ struct mlx4_mpt_entry {
 } __attribute__((packed));
 
 #define MLX4_MPT_FLAG_SW_OWNS      (0xfUL << 28)
+#define MLX4_MPT_FLAG_FREE         (0x3UL << 28)
 #define MLX4_MPT_FLAG_MIO          (1 << 17)
 #define MLX4_MPT_FLAG_BIND_ENABLE   (1 << 15)
 #define MLX4_MPT_FLAG_PHYSICAL     (1 <<  9)
 #define MLX4_MPT_FLAG_REGION       (1 <<  8)
 
+#define MLX4_MPT_PD_FLAG_FAST_REG   (1 << 26)
+#define MLX4_MPT_PD_FLAG_EN_INV            (3 << 24)
+
 #define MLX4_MTT_FLAG_PRESENT          1
 
 #define MLX4_MPT_STATUS_SW             0xF0
@@ -79,23 +83,26 @@ static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order)
 
        spin_lock(&buddy->lock);
 
-       for (o = order; o <= buddy->max_order; ++o) {
-               m = 1 << (buddy->max_order - o);
-               seg = find_first_bit(buddy->bits[o], m);
-               if (seg < m)
-                       goto found;
-       }
+       for (o = order; o <= buddy->max_order; ++o)
+               if (buddy->num_free[o]) {
+                       m = 1 << (buddy->max_order - o);
+                       seg = find_first_bit(buddy->bits[o], m);
+                       if (seg < m)
+                               goto found;
+               }
 
        spin_unlock(&buddy->lock);
        return -1;
 
  found:
        clear_bit(seg, buddy->bits[o]);
+       --buddy->num_free[o];
 
        while (o > order) {
                --o;
                seg <<= 1;
                set_bit(seg ^ 1, buddy->bits[o]);
+               ++buddy->num_free[o];
        }
 
        spin_unlock(&buddy->lock);
@@ -113,11 +120,13 @@ static void mlx4_buddy_free(struct mlx4_buddy *buddy, u32 seg, int order)
 
        while (test_bit(seg ^ 1, buddy->bits[order])) {
                clear_bit(seg ^ 1, buddy->bits[order]);
+               --buddy->num_free[order];
                seg >>= 1;
                ++order;
        }
 
        set_bit(seg, buddy->bits[order]);
+       ++buddy->num_free[order];
 
        spin_unlock(&buddy->lock);
 }
@@ -131,7 +140,9 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
 
        buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
                              GFP_KERNEL);
-       if (!buddy->bits)
+       buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+                                 GFP_KERNEL);
+       if (!buddy->bits || !buddy->num_free)
                goto err_out;
 
        for (i = 0; i <= buddy->max_order; ++i) {
@@ -143,6 +154,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
        }
 
        set_bit(0, buddy->bits[buddy->max_order]);
+       buddy->num_free[buddy->max_order] = 1;
 
        return 0;
 
@@ -150,9 +162,10 @@ err_out_free:
        for (i = 0; i <= buddy->max_order; ++i)
                kfree(buddy->bits[i]);
 
+err_out:
        kfree(buddy->bits);
+       kfree(buddy->num_free);
 
-err_out:
        return -ENOMEM;
 }
 
@@ -164,6 +177,7 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
                kfree(buddy->bits[i]);
 
        kfree(buddy->bits);
+       kfree(buddy->num_free);
 }
 
 static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
@@ -314,21 +328,30 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
 
        memset(mpt_entry, 0, sizeof *mpt_entry);
 
-       mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS     |
-                                      MLX4_MPT_FLAG_MIO         |
+       mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_MIO         |
                                       MLX4_MPT_FLAG_REGION      |
                                       mr->access);
 
        mpt_entry->key         = cpu_to_be32(key_to_hw_index(mr->key));
-       mpt_entry->pd          = cpu_to_be32(mr->pd);
+       mpt_entry->pd_flags    = cpu_to_be32(mr->pd | MLX4_MPT_PD_FLAG_EN_INV);
        mpt_entry->start       = cpu_to_be64(mr->iova);
        mpt_entry->length      = cpu_to_be64(mr->size);
        mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift);
+
        if (mr->mtt.order < 0) {
                mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
                mpt_entry->mtt_seg = 0;
-       } else
+       } else {
                mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt));
+       }
+
+       if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) {
+               /* fast register MR in free state */
+               mpt_entry->flags    |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
+               mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG);
+       } else {
+               mpt_entry->flags    |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS);
+       }
 
        err = mlx4_SW2HW_MPT(dev, mailbox,
                             key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1));
index 3a93c5f0f7ab8cc0ef33b8559d598b6e0fa82f5c..aa616892d09cbac5c2169e334a5893515ca9fb99 100644 (file)
@@ -91,6 +91,13 @@ EXPORT_SYMBOL_GPL(mlx4_uar_free);
 
 int mlx4_init_uar_table(struct mlx4_dev *dev)
 {
+       if (dev->caps.num_uars <= 128) {
+               mlx4_err(dev, "Only %d UAR pages (need more than 128)\n",
+                        dev->caps.num_uars);
+               mlx4_err(dev, "Increase firmware log2_uar_bar_megabytes?\n");
+               return -ENODEV;
+       }
+
        return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap,
                                dev->caps.num_uars, dev->caps.num_uars - 1,
                                max(128, dev->caps.reserved_uars));
index ee5484c44a1833781887dbbdc42775f5d661bc60..c49a86044bf7bec2c53d77264164e0c5e223e005 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
index e199715fabd0947d6014a9b068bd583aa3745eb6..3951b884c0fba94abebab3e254de14cdf99c63d2 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index d23f46d692ef5daf02ad7076842b4859c558bd82..533eb6db24b37d589996baa8ea882c3e764116b8 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 993d87c9296f92361763e1662eae7ce545cb7aaf..edc0fd588985f51da906e325398ae36bac2f715c 100644 (file)
@@ -650,7 +650,7 @@ static void pasemi_mac_replenish_rx_ring(const struct net_device *dev,
                                     mac->bufsz - LOCAL_SKB_ALIGN,
                                     PCI_DMA_FROMDEVICE);
 
-               if (unlikely(dma_mapping_error(dma))) {
+               if (unlikely(pci_dma_mapping_error(mac->dma_pdev, dma))) {
                        dev_kfree_skb_irq(info->skb);
                        break;
                }
@@ -1519,7 +1519,7 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
        map[0] = pci_map_single(mac->dma_pdev, skb->data, skb_headlen(skb),
                                PCI_DMA_TODEVICE);
        map_size[0] = skb_headlen(skb);
-       if (dma_mapping_error(map[0]))
+       if (pci_dma_mapping_error(mac->dma_pdev, map[0]))
                goto out_err_nolock;
 
        for (i = 0; i < nfrags; i++) {
@@ -1529,7 +1529,7 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
                                        frag->page_offset, frag->size,
                                        PCI_DMA_TODEVICE);
                map_size[i+1] = frag->size;
-               if (dma_mapping_error(map[i+1])) {
+               if (pci_dma_mapping_error(mac->dma_pdev, map[i+1])) {
                        nfrags = i;
                        goto out_err_nolock;
                }
index 739b3ab7bccc2d9ea719c6080eb3137bf2ba2dbc..ddccc074a76a88da15574be350b408e0e9605817 100644 (file)
@@ -581,12 +581,12 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        if (file == ppp->owner)
                                ppp_shutdown_interface(ppp);
                }
-               if (atomic_read(&file->f_count) <= 2) {
+               if (atomic_long_read(&file->f_count) <= 2) {
                        ppp_release(NULL, file);
                        err = 0;
                } else
-                       printk(KERN_DEBUG "PPPIOCDETACH file->f_count=%d\n",
-                              atomic_read(&file->f_count));
+                       printk(KERN_DEBUG "PPPIOCDETACH file->f_count=%ld\n",
+                              atomic_long_read(&file->f_count));
                unlock_kernel();
                return err;
        }
index e7d48a352beb0dabe4f3a70e5f4512949eae1f6a..e82b37bbd6c3534c244ef41d7d848c04d1d19caa 100644 (file)
@@ -328,7 +328,7 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
                                             qdev->lrg_buffer_len -
                                             QL_HEADER_SPACE,
                                             PCI_DMA_FROMDEVICE);
-                       err = pci_dma_mapping_error(map);
+                       err = pci_dma_mapping_error(qdev->pdev, map);
                        if(err) {
                                printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
                                       qdev->ndev->name, err);
@@ -1919,7 +1919,7 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
                                                     QL_HEADER_SPACE,
                                                     PCI_DMA_FROMDEVICE);
 
-                               err = pci_dma_mapping_error(map);
+                               err = pci_dma_mapping_error(qdev->pdev, map);
                                if(err) {
                                        printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
                                               qdev->ndev->name, err);
@@ -2454,7 +2454,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
         */
        map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE);
 
-       err = pci_dma_mapping_error(map);
+       err = pci_dma_mapping_error(qdev->pdev, map);
        if(err) {
                printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
                       qdev->ndev->name, err);
@@ -2487,7 +2487,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
                                                     sizeof(struct oal),
                                                     PCI_DMA_TODEVICE);
 
-                               err = pci_dma_mapping_error(map);
+                               err = pci_dma_mapping_error(qdev->pdev, map);
                                if(err) {
 
                                        printk(KERN_ERR "%s: PCI mapping outbound address list with error: %d\n",
@@ -2514,7 +2514,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
                                         frag->page_offset, frag->size,
                                         PCI_DMA_TODEVICE);
 
-                       err = pci_dma_mapping_error(map);
+                       err = pci_dma_mapping_error(qdev->pdev, map);
                        if(err) {
                                printk(KERN_ERR "%s: PCI mapping frags failed with error: %d\n",
                                       qdev->ndev->name, err);
@@ -2916,7 +2916,7 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
                                             QL_HEADER_SPACE,
                                             PCI_DMA_FROMDEVICE);
 
-                       err = pci_dma_mapping_error(map);
+                       err = pci_dma_mapping_error(qdev->pdev, map);
                        if(err) {
                                printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
                                       qdev->ndev->name, err);
index 9dae40ccf0482cdce2a9df3bb25ee0e7730a35ae..86d77d05190aca1a89f038b5a1e90dae584d5345 100644 (file)
@@ -2512,8 +2512,8 @@ static void stop_nic(struct s2io_nic *nic)
  *   Return Value:
  *  SUCCESS on success or an appropriate -ve value on failure.
  */
-
-static int fill_rx_buffers(struct ring_info *ring, int from_card_up)
+static int fill_rx_buffers(struct s2io_nic *nic, struct ring_info *ring,
+                               int from_card_up)
 {
        struct sk_buff *skb;
        struct RxD_t *rxdp;
@@ -2602,7 +2602,8 @@ static int fill_rx_buffers(struct ring_info *ring, int from_card_up)
                        rxdp1->Buffer0_ptr = pci_map_single
                            (ring->pdev, skb->data, size - NET_IP_ALIGN,
                                PCI_DMA_FROMDEVICE);
-                       if(pci_dma_mapping_error(rxdp1->Buffer0_ptr))
+                       if (pci_dma_mapping_error(nic->pdev,
+                                               rxdp1->Buffer0_ptr))
                                goto pci_map_failed;
 
                        rxdp->Control_2 =
@@ -2636,7 +2637,8 @@ static int fill_rx_buffers(struct ring_info *ring, int from_card_up)
                                rxdp3->Buffer0_ptr =
                                   pci_map_single(ring->pdev, ba->ba_0,
                                        BUF0_LEN, PCI_DMA_FROMDEVICE);
-                               if (pci_dma_mapping_error(rxdp3->Buffer0_ptr))
+                       if (pci_dma_mapping_error(nic->pdev,
+                                               rxdp3->Buffer0_ptr))
                                        goto pci_map_failed;
                        } else
                                pci_dma_sync_single_for_device(ring->pdev,
@@ -2655,7 +2657,8 @@ static int fill_rx_buffers(struct ring_info *ring, int from_card_up)
                                (ring->pdev, skb->data, ring->mtu + 4,
                                                PCI_DMA_FROMDEVICE);
 
-                               if (pci_dma_mapping_error(rxdp3->Buffer2_ptr))
+                               if (pci_dma_mapping_error(nic->pdev,
+                                                       rxdp3->Buffer2_ptr))
                                        goto pci_map_failed;
 
                                if (from_card_up) {
@@ -2664,8 +2667,8 @@ static int fill_rx_buffers(struct ring_info *ring, int from_card_up)
                                                ba->ba_1, BUF1_LEN,
                                                PCI_DMA_FROMDEVICE);
 
-                                       if (pci_dma_mapping_error
-                                               (rxdp3->Buffer1_ptr)) {
+                                       if (pci_dma_mapping_error(nic->pdev,
+                                               rxdp3->Buffer1_ptr)) {
                                                pci_unmap_single
                                                        (ring->pdev,
                                                    (dma_addr_t)(unsigned long)
@@ -2806,9 +2809,9 @@ static void free_rx_buffers(struct s2io_nic *sp)
        }
 }
 
-static int s2io_chk_rx_buffers(struct ring_info *ring)
+static int s2io_chk_rx_buffers(struct s2io_nic *nic, struct ring_info *ring)
 {
-       if (fill_rx_buffers(ring, 0) == -ENOMEM) {
+       if (fill_rx_buffers(nic, ring, 0) == -ENOMEM) {
                DBG_PRINT(INFO_DBG, "%s:Out of memory", ring->dev->name);
                DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
        }
@@ -2848,7 +2851,7 @@ static int s2io_poll_msix(struct napi_struct *napi, int budget)
                return 0;
 
        pkts_processed = rx_intr_handler(ring, budget);
-       s2io_chk_rx_buffers(ring);
+       s2io_chk_rx_buffers(nic, ring);
 
        if (pkts_processed < budget_org) {
                netif_rx_complete(dev, napi);
@@ -2882,7 +2885,7 @@ static int s2io_poll_inta(struct napi_struct *napi, int budget)
        for (i = 0; i < config->rx_ring_num; i++) {
                ring = &mac_control->rings[i];
                ring_pkts_processed = rx_intr_handler(ring, budget);
-               s2io_chk_rx_buffers(ring);
+               s2io_chk_rx_buffers(nic, ring);
                pkts_processed += ring_pkts_processed;
                budget -= ring_pkts_processed;
                if (budget <= 0)
@@ -2939,7 +2942,8 @@ static void s2io_netpoll(struct net_device *dev)
                rx_intr_handler(&mac_control->rings[i], 0);
 
        for (i = 0; i < config->rx_ring_num; i++) {
-               if (fill_rx_buffers(&mac_control->rings[i], 0) == -ENOMEM) {
+               if (fill_rx_buffers(nic, &mac_control->rings[i], 0) ==
+                               -ENOMEM) {
                        DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
                        DBG_PRINT(INFO_DBG, " in Rx Netpoll!!\n");
                        break;
@@ -4235,14 +4239,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                txdp->Buffer_Pointer = pci_map_single(sp->pdev,
                                        fifo->ufo_in_band_v,
                                        sizeof(u64), PCI_DMA_TODEVICE);
-               if (pci_dma_mapping_error(txdp->Buffer_Pointer))
+               if (pci_dma_mapping_error(sp->pdev, txdp->Buffer_Pointer))
                        goto pci_map_failed;
                txdp++;
        }
 
        txdp->Buffer_Pointer = pci_map_single
            (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
-       if (pci_dma_mapping_error(txdp->Buffer_Pointer))
+       if (pci_dma_mapping_error(sp->pdev, txdp->Buffer_Pointer))
                goto pci_map_failed;
 
        txdp->Host_Control = (unsigned long) skb;
@@ -4345,7 +4349,7 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id)
                netif_rx_schedule(dev, &ring->napi);
        } else {
                rx_intr_handler(ring, 0);
-               s2io_chk_rx_buffers(ring);
+               s2io_chk_rx_buffers(sp, ring);
        }
 
        return IRQ_HANDLED;
@@ -4826,7 +4830,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
                 */
                if (!config->napi) {
                        for (i = 0; i < config->rx_ring_num; i++)
-                               s2io_chk_rx_buffers(&mac_control->rings[i]);
+                               s2io_chk_rx_buffers(sp, &mac_control->rings[i]);
                }
                writeq(sp->general_int_mask, &bar0->general_int_mask);
                readl(&bar0->general_int_status);
@@ -6859,7 +6863,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
                                pci_map_single( sp->pdev, (*skb)->data,
                                        size - NET_IP_ALIGN,
                                        PCI_DMA_FROMDEVICE);
-                       if (pci_dma_mapping_error(rxdp1->Buffer0_ptr))
+                       if (pci_dma_mapping_error(sp->pdev, rxdp1->Buffer0_ptr))
                                goto memalloc_failed;
                        rxdp->Host_Control = (unsigned long) (*skb);
                }
@@ -6886,12 +6890,13 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
                                pci_map_single(sp->pdev, (*skb)->data,
                                               dev->mtu + 4,
                                               PCI_DMA_FROMDEVICE);
-                       if (pci_dma_mapping_error(rxdp3->Buffer2_ptr))
+                       if (pci_dma_mapping_error(sp->pdev, rxdp3->Buffer2_ptr))
                                goto memalloc_failed;
                        rxdp3->Buffer0_ptr = *temp0 =
                                pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN,
                                                PCI_DMA_FROMDEVICE);
-                       if (pci_dma_mapping_error(rxdp3->Buffer0_ptr)) {
+                       if (pci_dma_mapping_error(sp->pdev,
+                                               rxdp3->Buffer0_ptr)) {
                                pci_unmap_single (sp->pdev,
                                        (dma_addr_t)rxdp3->Buffer2_ptr,
                                        dev->mtu + 4, PCI_DMA_FROMDEVICE);
@@ -6903,7 +6908,8 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
                        rxdp3->Buffer1_ptr = *temp1 =
                                pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN,
                                                PCI_DMA_FROMDEVICE);
-                       if (pci_dma_mapping_error(rxdp3->Buffer1_ptr)) {
+                       if (pci_dma_mapping_error(sp->pdev,
+                                               rxdp3->Buffer1_ptr)) {
                                pci_unmap_single (sp->pdev,
                                        (dma_addr_t)rxdp3->Buffer0_ptr,
                                        BUF0_LEN, PCI_DMA_FROMDEVICE);
@@ -7187,7 +7193,7 @@ static int s2io_card_up(struct s2io_nic * sp)
 
        for (i = 0; i < config->rx_ring_num; i++) {
                mac_control->rings[i].mtu = dev->mtu;
-               ret = fill_rx_buffers(&mac_control->rings[i], 1);
+               ret = fill_rx_buffers(sp, &mac_control->rings[i], 1);
                if (ret) {
                        DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n",
                                  dev->name);
index 601b001437c01b8bf13966448641e197e4eb749d..0d27dd39bc0938c95585137156365fa910e161d0 100644 (file)
@@ -233,7 +233,7 @@ static inline int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue,
                                          rx_buf->data, rx_buf->len,
                                          PCI_DMA_FROMDEVICE);
 
-       if (unlikely(pci_dma_mapping_error(rx_buf->dma_addr))) {
+       if (unlikely(pci_dma_mapping_error(efx->pci_dev, rx_buf->dma_addr))) {
                dev_kfree_skb_any(rx_buf->skb);
                rx_buf->skb = NULL;
                return -EIO;
@@ -275,7 +275,7 @@ static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
                                        0, efx_rx_buf_size(efx),
                                        PCI_DMA_FROMDEVICE);
 
-               if (unlikely(pci_dma_mapping_error(dma_addr))) {
+               if (unlikely(pci_dma_mapping_error(efx->pci_dev, dma_addr))) {
                        __free_pages(rx_buf->page, efx->rx_buffer_order);
                        rx_buf->page = NULL;
                        return -EIO;
index 5cdd082ab8f6aba562838dada2af5bd9ec214067..5e8374ab28eea5a9fc5198c0f955d8fdc614a622 100644 (file)
@@ -172,7 +172,7 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
 
        /* Process all fragments */
        while (1) {
-               if (unlikely(pci_dma_mapping_error(dma_addr)))
+               if (unlikely(pci_dma_mapping_error(pci_dev, dma_addr)))
                        goto pci_err;
 
                /* Store fields for marking in the per-fragment final
@@ -661,7 +661,8 @@ efx_tsoh_heap_alloc(struct efx_tx_queue *tx_queue, size_t header_len)
        tsoh->dma_addr = pci_map_single(tx_queue->efx->pci_dev,
                                        TSOH_BUFFER(tsoh), header_len,
                                        PCI_DMA_TODEVICE);
-       if (unlikely(pci_dma_mapping_error(tsoh->dma_addr))) {
+       if (unlikely(pci_dma_mapping_error(tx_queue->efx->pci_dev,
+                                          tsoh->dma_addr))) {
                kfree(tsoh);
                return NULL;
        }
@@ -863,7 +864,7 @@ static inline int tso_get_fragment(struct tso_state *st, struct efx_nic *efx,
 
        st->ifc.unmap_addr = pci_map_page(efx->pci_dev, page, page_off,
                                          len, PCI_DMA_TODEVICE);
-       if (likely(!pci_dma_mapping_error(st->ifc.unmap_addr))) {
+       if (likely(!pci_dma_mapping_error(efx->pci_dev, st->ifc.unmap_addr))) {
                st->ifc.unmap_len = len;
                st->ifc.len = len;
                st->ifc.dma_addr = st->ifc.unmap_addr;
index 711e4a8948e06edcb420f08183525cb7f60d54b4..5257cf464f1a8923ad77dd60219b5f8eafb79490 100644 (file)
@@ -1829,9 +1829,6 @@ static int sky2_down(struct net_device *dev)
        if (netif_msg_ifdown(sky2))
                printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
-       /* Stop more packets from being queued */
-       netif_stop_queue(dev);
-
        /* Disable port IRQ */
        imask = sky2_read32(hw, B0_IMSK);
        imask &= ~portirq_msk[port];
@@ -1887,8 +1884,6 @@ static int sky2_down(struct net_device *dev)
 
        sky2_phy_power_down(hw, port);
 
-       netif_carrier_off(dev);
-
        /* turn off LED's */
        sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
 
index 00aa0b108cb9691982991bd819c53b1ac9b3252f..b6435d0d71f9a067f887f7102159ae0d9a651ed5 100644 (file)
@@ -452,7 +452,7 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
        /* iommu-map the skb */
        buf = pci_map_single(card->pdev, descr->skb->data,
                        SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
-       if (pci_dma_mapping_error(buf)) {
+       if (pci_dma_mapping_error(card->pdev, buf)) {
                dev_kfree_skb_any(descr->skb);
                descr->skb = NULL;
                if (netif_msg_rx_err(card) && net_ratelimit())
@@ -691,7 +691,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
        unsigned long flags;
 
        buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
-       if (pci_dma_mapping_error(buf)) {
+       if (pci_dma_mapping_error(card->pdev, buf)) {
                if (netif_msg_tx_err(card) && net_ratelimit())
                        dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). "
                                  "Dropping packet\n", skb->data, skb->len);
index a645e5028c14bcd12053d77b31f4f0cfd7003c9b..8487ace9d2e3a8d73a8fedbe32a2447ec9575222 100644 (file)
@@ -506,7 +506,7 @@ static void *alloc_rxbuf_page(struct pci_dev *hwdev, dma_addr_t *dma_handle)
                return NULL;
        *dma_handle = pci_map_single(hwdev, buf, PAGE_SIZE,
                                     PCI_DMA_FROMDEVICE);
-       if (pci_dma_mapping_error(*dma_handle)) {
+       if (pci_dma_mapping_error(hwdev, *dma_handle)) {
                free_page((unsigned long)buf);
                return NULL;
        }
@@ -536,7 +536,7 @@ static struct sk_buff *alloc_rxbuf_skb(struct net_device *dev,
                return NULL;
        *dma_handle = pci_map_single(hwdev, skb->data, RX_BUF_SIZE,
                                     PCI_DMA_FROMDEVICE);
-       if (pci_dma_mapping_error(*dma_handle)) {
+       if (pci_dma_mapping_error(hwdev, *dma_handle)) {
                dev_kfree_skb_any(skb);
                return NULL;
        }
index c28d7cb2035b1dbcb5425aaeff55294d3f4eb786..0196a0df90210995ec6a5abe228eb23bb22d494c 100644 (file)
@@ -19,6 +19,7 @@
 //#define DEBUG
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/ethtool.h>
 #include <linux/module.h>
 #include <linux/virtio.h>
 #include <linux/virtio_net.h>
@@ -54,9 +55,15 @@ struct virtnet_info
        struct tasklet_struct tasklet;
        bool free_in_tasklet;
 
+       /* I like... big packets and I cannot lie! */
+       bool big_packets;
+
        /* Receive & send queues. */
        struct sk_buff_head recv;
        struct sk_buff_head send;
+
+       /* Chain pages by the private ptr. */
+       struct page *pages;
 };
 
 static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb)
@@ -69,6 +76,23 @@ static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
        sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
 }
 
+static void give_a_page(struct virtnet_info *vi, struct page *page)
+{
+       page->private = (unsigned long)vi->pages;
+       vi->pages = page;
+}
+
+static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
+{
+       struct page *p = vi->pages;
+
+       if (p)
+               vi->pages = (struct page *)p->private;
+       else
+               p = alloc_page(gfp_mask);
+       return p;
+}
+
 static void skb_xmit_done(struct virtqueue *svq)
 {
        struct virtnet_info *vi = svq->vdev->priv;
@@ -88,6 +112,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
                        unsigned len)
 {
        struct virtio_net_hdr *hdr = skb_vnet_hdr(skb);
+       int err;
 
        if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
                pr_debug("%s: short packet %i\n", dev->name, len);
@@ -95,10 +120,23 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
                goto drop;
        }
        len -= sizeof(struct virtio_net_hdr);
-       BUG_ON(len > MAX_PACKET_LEN);
 
-       skb_trim(skb, len);
+       if (len <= MAX_PACKET_LEN) {
+               unsigned int i;
 
+               for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+                       give_a_page(dev->priv, skb_shinfo(skb)->frags[i].page);
+               skb->data_len = 0;
+               skb_shinfo(skb)->nr_frags = 0;
+       }
+
+       err = pskb_trim(skb, len);
+       if (err) {
+               pr_debug("%s: pskb_trim failed %i %d\n", dev->name, len, err);
+               dev->stats.rx_dropped++;
+               goto drop;
+       }
+       skb->truesize += skb->data_len;
        dev->stats.rx_bytes += skb->len;
        dev->stats.rx_packets++;
 
@@ -160,7 +198,7 @@ static void try_fill_recv(struct virtnet_info *vi)
 {
        struct sk_buff *skb;
        struct scatterlist sg[2+MAX_SKB_FRAGS];
-       int num, err;
+       int num, err, i;
 
        sg_init_table(sg, 2+MAX_SKB_FRAGS);
        for (;;) {
@@ -170,6 +208,24 @@ static void try_fill_recv(struct virtnet_info *vi)
 
                skb_put(skb, MAX_PACKET_LEN);
                vnet_hdr_to_sg(sg, skb);
+
+               if (vi->big_packets) {
+                       for (i = 0; i < MAX_SKB_FRAGS; i++) {
+                               skb_frag_t *f = &skb_shinfo(skb)->frags[i];
+                               f->page = get_a_page(vi, GFP_ATOMIC);
+                               if (!f->page)
+                                       break;
+
+                               f->page_offset = 0;
+                               f->size = PAGE_SIZE;
+
+                               skb->data_len += PAGE_SIZE;
+                               skb->len += PAGE_SIZE;
+
+                               skb_shinfo(skb)->nr_frags++;
+                       }
+               }
+
                num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
                skb_queue_head(&vi->recv, skb);
 
@@ -335,16 +391,11 @@ again:
        free_old_xmit_skbs(vi);
 
        /* If we has a buffer left over from last time, send it now. */
-       if (unlikely(vi->last_xmit_skb)) {
-               if (xmit_skb(vi, vi->last_xmit_skb) != 0) {
-                       /* Drop this skb: we only queue one. */
-                       vi->dev->stats.tx_dropped++;
-                       kfree_skb(skb);
-                       skb = NULL;
-                       goto stop_queue;
-               }
-               vi->last_xmit_skb = NULL;
-       }
+       if (unlikely(vi->last_xmit_skb) &&
+           xmit_skb(vi, vi->last_xmit_skb) != 0)
+               goto stop_queue;
+
+       vi->last_xmit_skb = NULL;
 
        /* Put new one in send queue and do transmit */
        if (likely(skb)) {
@@ -370,6 +421,11 @@ stop_queue:
                netif_start_queue(dev);
                goto again;
        }
+       if (skb) {
+               /* Drop this skb: we only queue one. */
+               vi->dev->stats.tx_dropped++;
+               kfree_skb(skb);
+       }
        goto done;
 }
 
@@ -408,6 +464,22 @@ static int virtnet_close(struct net_device *dev)
        return 0;
 }
 
+static int virtnet_set_tx_csum(struct net_device *dev, u32 data)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
+       struct virtio_device *vdev = vi->vdev;
+
+       if (data && !virtio_has_feature(vdev, VIRTIO_NET_F_CSUM))
+               return -ENOSYS;
+
+       return ethtool_op_set_tx_hw_csum(dev, data);
+}
+
+static struct ethtool_ops virtnet_ethtool_ops = {
+       .set_tx_csum = virtnet_set_tx_csum,
+       .set_sg = ethtool_op_set_sg,
+};
+
 static int virtnet_probe(struct virtio_device *vdev)
 {
        int err;
@@ -427,6 +499,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = virtnet_netpoll;
 #endif
+       SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
        SET_NETDEV_DEV(dev, &vdev->dev);
 
        /* Do we support "hardware" checksums? */
@@ -462,11 +535,18 @@ static int virtnet_probe(struct virtio_device *vdev)
        vi->dev = dev;
        vi->vdev = vdev;
        vdev->priv = vi;
+       vi->pages = NULL;
 
        /* If they give us a callback when all buffers are done, we don't need
         * the timer. */
        vi->free_in_tasklet = virtio_has_feature(vdev,VIRTIO_F_NOTIFY_ON_EMPTY);
 
+       /* If we can receive ANY GSO packets, we must allocate large ones. */
+       if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4)
+           || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6)
+           || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
+               vi->big_packets = true;
+
        /* We expect two virtqueues, receive then send. */
        vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done);
        if (IS_ERR(vi->rvq)) {
@@ -541,6 +621,10 @@ static void virtnet_remove(struct virtio_device *vdev)
        vdev->config->del_vq(vi->svq);
        vdev->config->del_vq(vi->rvq);
        unregister_netdev(vi->dev);
+
+       while (vi->pages)
+               __free_pages(get_a_page(vi, GFP_KERNEL), 0);
+
        free_netdev(vi->dev);
 }
 
@@ -553,7 +637,9 @@ static unsigned int features[] = {
        VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM,
        VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
        VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
-       VIRTIO_NET_F_HOST_ECN, VIRTIO_F_NOTIFY_ON_EMPTY,
+       VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
+       VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
+       VIRTIO_F_NOTIFY_ON_EMPTY,
 };
 
 static struct virtio_driver virtio_net = {
index 217d506527a96d2f72e887f75b9cab2425554e0f..d9769c527346874f6f876babf37f67a11ebcd32e 100644 (file)
@@ -1166,7 +1166,7 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
                bf->skb = skb;
                bf->skbaddr = pci_map_single(sc->pdev,
                        skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
-               if (unlikely(pci_dma_mapping_error(bf->skbaddr))) {
+               if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) {
                        ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
                        dev_kfree_skb(skb);
                        bf->skb = NULL;
@@ -1918,7 +1918,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
        ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
                        "skbaddr %llx\n", skb, skb->data, skb->len,
                        (unsigned long long)bf->skbaddr);
-       if (pci_dma_mapping_error(bf->skbaddr)) {
+       if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) {
                ATH5K_ERR(sc, "beacon DMA mapping failed\n");
                return -EIO;
        }
index 3a7a11a75fb464017ce284d34a41388f2875dd15..f821dbc952a42bb2e53a49c110decc859eff3d55 100644 (file)
@@ -4,7 +4,7 @@ config OF_DEVICE
 
 config OF_GPIO
        def_bool y
-       depends on OF && PPC_OF && HAVE_GPIO_LIB
+       depends on OF && PPC_OF && GPIOLIB
        help
          OpenFirmware GPIO accessors
 
@@ -13,3 +13,9 @@ config OF_I2C
        depends on PPC_OF && I2C
        help
          OpenFirmware I2C accessors
+
+config OF_SPI
+       def_tristate SPI
+       depends on OF && PPC_OF && SPI
+       help
+         OpenFirmware SPI accessors
index 548772e871fd8e52a1ed66156fc0c129e84660af..4c3c6f8e36f51577281f881f6edf464834847111 100644 (file)
@@ -2,3 +2,4 @@ obj-y = base.o
 obj-$(CONFIG_OF_DEVICE) += device.o platform.o
 obj-$(CONFIG_OF_GPIO)   += gpio.o
 obj-$(CONFIG_OF_I2C)   += of_i2c.o
+obj-$(CONFIG_OF_SPI)   += of_spi.o
index 23ffb7c0caf24148277ddd19c7430b5c90fb6fcb..ad8ac1a8af28689acc7198b22fe95a888d62e6a6 100644 (file)
@@ -385,3 +385,91 @@ struct device_node *of_find_matching_node(struct device_node *from,
        return np;
 }
 EXPORT_SYMBOL(of_find_matching_node);
+
+/**
+ * of_modalias_table: Table of explicit compatible ==> modalias mappings
+ *
+ * This table allows particulare compatible property values to be mapped
+ * to modalias strings.  This is useful for busses which do not directly
+ * understand the OF device tree but are populated based on data contained
+ * within the device tree.  SPI and I2C are the two current users of this
+ * table.
+ *
+ * In most cases, devices do not need to be listed in this table because
+ * the modalias value can be derived directly from the compatible table.
+ * However, if for any reason a value cannot be derived, then this table
+ * provides a method to override the implicit derivation.
+ *
+ * At the moment, a single table is used for all bus types because it is
+ * assumed that the data size is small and that the compatible values
+ * should already be distinct enough to differentiate between SPI, I2C
+ * and other devices.
+ */
+struct of_modalias_table {
+       char *of_device;
+       char *modalias;
+};
+static struct of_modalias_table of_modalias_table[] = {
+       /* Empty for now; add entries as needed */
+};
+
+/**
+ * of_modalias_node - Lookup appropriate modalias for a device node
+ * @node:      pointer to a device tree node
+ * @modalias:  Pointer to buffer that modalias value will be copied into
+ * @len:       Length of modalias value
+ *
+ * Based on the value of the compatible property, this routine will determine
+ * an appropriate modalias value for a particular device tree node.  Three
+ * separate methods are used to derive a modalias value.
+ *
+ * First method is to lookup the compatible value in of_modalias_table.
+ * Second is to look for a "linux,<modalias>" entry in the compatible list
+ * and used that for modalias.  Third is to strip off the manufacturer
+ * prefix from the first compatible entry and use the remainder as modalias
+ *
+ * This routine returns 0 on success
+ */
+int of_modalias_node(struct device_node *node, char *modalias, int len)
+{
+       int i, cplen;
+       const char *compatible;
+       const char *p;
+
+       /* 1. search for exception list entry */
+       for (i = 0; i < ARRAY_SIZE(of_modalias_table); i++) {
+               compatible = of_modalias_table[i].of_device;
+               if (!of_device_is_compatible(node, compatible))
+                       continue;
+               strlcpy(modalias, of_modalias_table[i].modalias, len);
+               return 0;
+       }
+
+       compatible = of_get_property(node, "compatible", &cplen);
+       if (!compatible)
+               return -ENODEV;
+
+       /* 2. search for linux,<modalias> entry */
+       p = compatible;
+       while (cplen > 0) {
+               if (!strncmp(p, "linux,", 6)) {
+                       p += 6;
+                       strlcpy(modalias, p, len);
+                       return 0;
+               }
+
+               i = strlen(p) + 1;
+               p += i;
+               cplen -= i;
+       }
+
+       /* 3. take first compatible entry and strip manufacturer */
+       p = strchr(compatible, ',');
+       if (!p)
+               return -ENODEV;
+       p++;
+       strlcpy(modalias, p, len);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_modalias_node);
+
index 5c015d310d4a9a92b493cbd7d34691c85dd6b992..6a98dc8aa30b1af9a1e8ce9a2a8264073a631eee 100644 (file)
 #include <linux/of_i2c.h>
 #include <linux/module.h>
 
-struct i2c_driver_device {
-       char    *of_device;
-       char    *i2c_type;
-};
-
-static struct i2c_driver_device i2c_devices[] = {
-};
-
-static int of_find_i2c_driver(struct device_node *node,
-                             struct i2c_board_info *info)
-{
-       int i, cplen;
-       const char *compatible;
-       const char *p;
-
-       /* 1. search for exception list entry */
-       for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
-               if (!of_device_is_compatible(node, i2c_devices[i].of_device))
-                       continue;
-               if (strlcpy(info->type, i2c_devices[i].i2c_type,
-                           I2C_NAME_SIZE) >= I2C_NAME_SIZE)
-                       return -ENOMEM;
-
-               return 0;
-       }
-
-       compatible = of_get_property(node, "compatible", &cplen);
-       if (!compatible)
-               return -ENODEV;
-
-       /* 2. search for linux,<i2c-type> entry */
-       p = compatible;
-       while (cplen > 0) {
-               if (!strncmp(p, "linux,", 6)) {
-                       p += 6;
-                       if (strlcpy(info->type, p,
-                                   I2C_NAME_SIZE) >= I2C_NAME_SIZE)
-                               return -ENOMEM;
-                       return 0;
-               }
-
-               i = strlen(p) + 1;
-               p += i;
-               cplen -= i;
-       }
-
-       /* 3. take fist compatible entry and strip manufacturer */
-       p = strchr(compatible, ',');
-       if (!p)
-               return -ENODEV;
-       p++;
-       if (strlcpy(info->type, p, I2C_NAME_SIZE) >= I2C_NAME_SIZE)
-               return -ENOMEM;
-       return 0;
-}
-
 void of_register_i2c_devices(struct i2c_adapter *adap,
                             struct device_node *adap_node)
 {
@@ -83,6 +27,9 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
                const u32 *addr;
                int len;
 
+               if (of_modalias_node(node, info.type, sizeof(info.type)) < 0)
+                       continue;
+
                addr = of_get_property(node, "reg", &len);
                if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
                        printk(KERN_ERR
@@ -91,13 +38,6 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
                }
 
                info.irq = irq_of_parse_and_map(node, 0);
-               if (info.irq == NO_IRQ)
-                       info.irq = -1;
-
-               if (of_find_i2c_driver(node, &info) < 0) {
-                       irq_dispose_mapping(info.irq);
-                       continue;
-               }
 
                info.addr = *addr;
 
diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c
new file mode 100644 (file)
index 0000000..b01eec0
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * SPI OF support routines
+ * Copyright (C) 2008 Secret Lab Technologies Ltd.
+ *
+ * Support routines for deriving SPI device attachments from the device
+ * tree.
+ */
+
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/of_spi.h>
+
+/**
+ * of_register_spi_devices - Register child devices onto the SPI bus
+ * @master:    Pointer to spi_master device
+ * @np:                parent node of SPI device nodes
+ *
+ * Registers an spi_device for each child node of 'np' which has a 'reg'
+ * property.
+ */
+void of_register_spi_devices(struct spi_master *master, struct device_node *np)
+{
+       struct spi_device *spi;
+       struct device_node *nc;
+       const u32 *prop;
+       int rc;
+       int len;
+
+       for_each_child_of_node(np, nc) {
+               /* Alloc an spi_device */
+               spi = spi_alloc_device(master);
+               if (!spi) {
+                       dev_err(&master->dev, "spi_device alloc error for %s\n",
+                               nc->full_name);
+                       spi_dev_put(spi);
+                       continue;
+               }
+
+               /* Select device driver */
+               if (of_modalias_node(nc, spi->modalias,
+                                    sizeof(spi->modalias)) < 0) {
+                       dev_err(&master->dev, "cannot find modalias for %s\n",
+                               nc->full_name);
+                       spi_dev_put(spi);
+                       continue;
+               }
+
+               /* Device address */
+               prop = of_get_property(nc, "reg", &len);
+               if (!prop || len < sizeof(*prop)) {
+                       dev_err(&master->dev, "%s has no 'reg' property\n",
+                               nc->full_name);
+                       spi_dev_put(spi);
+                       continue;
+               }
+               spi->chip_select = *prop;
+
+               /* Mode (clock phase/polarity/etc.) */
+               if (of_find_property(nc, "spi-cpha", NULL))
+                       spi->mode |= SPI_CPHA;
+               if (of_find_property(nc, "spi-cpol", NULL))
+                       spi->mode |= SPI_CPOL;
+
+               /* Device speed */
+               prop = of_get_property(nc, "spi-max-frequency", &len);
+               if (!prop || len < sizeof(*prop)) {
+                       dev_err(&master->dev, "%s has no 'spi-max-frequency' property\n",
+                               nc->full_name);
+                       spi_dev_put(spi);
+                       continue;
+               }
+               spi->max_speed_hz = *prop;
+
+               /* IRQ */
+               spi->irq = irq_of_parse_and_map(nc, 0);
+
+               /* Store a pointer to the node in the device structure */
+               of_node_get(nc);
+               spi->dev.archdata.of_node = nc;
+
+               /* Register the new device */
+               request_module(spi->modalias);
+               rc = spi_add_device(spi);
+               if (rc) {
+                       dev_err(&master->dev, "spi_device register error %s\n",
+                               nc->full_name);
+                       spi_dev_put(spi);
+               }
+
+       }
+}
+EXPORT_SYMBOL(of_register_spi_devices);
index 0338b09126742300efd226e4fce332a0e2c0bbad..e97059415ab423387eb0dfd0f4c210cd38766c68 100644 (file)
@@ -199,8 +199,6 @@ int parport_wait_peripheral(struct parport *port,
        /* 40ms of slow polling. */
        deadline = jiffies + msecs_to_jiffies(40);
        while (time_before (jiffies, deadline)) {
-               int ret;
-
                if (signal_pending (current))
                        return -EINTR;
 
index 4ec220b2eae7dba0bf61481931209fbc08f8d2fc..6938d2e9f18f8171d41adcaa0e33e1e487334305 100644 (file)
@@ -406,6 +406,8 @@ static int parport_ax88796_resume(struct platform_device *dev)
 #define parport_ax88796_resume  NULL
 #endif
 
+MODULE_ALIAS("platform:ax88796-pp");
+
 static struct platform_driver axdrv = {
        .driver         = {
                .name   = "ax88796-pp",
index 802a81d4736778192166ff41e7d8635b3cb5a406..00e1d9620f7cbca16e94f12bd932bba8f2b1b1e0 100644 (file)
@@ -235,7 +235,7 @@ failed:
     
 ======================================================================*/
 
-void parport_cs_release(struct pcmcia_device *link)
+static void parport_cs_release(struct pcmcia_device *link)
 {
        parport_info_t *info = link->priv;
 
index e0c2a4584ec61f22cf3be8d2cae19d6259dd0ef5..8a846adf1dcf2cd2ac792693c3cb3b124b36ceb4 100644 (file)
@@ -2867,7 +2867,7 @@ static struct parport_pc_pci {
         * and 840 locks up if you write 1 to bit 2! */
        /* oxsemi_952 */                { 1, { { 0, 1 }, } },
        /* oxsemi_954 */                { 1, { { 0, -1 }, } },
-       /* oxsemi_840 */                { 1, { { 0, -1 }, } },
+       /* oxsemi_840 */                { 1, { { 0, 1 }, } },
        /* aks_0100 */                  { 1, { { 0, -1 }, } },
        /* mobility_pp */               { 1, { { 0, 1 }, } },
        /* netmos_9705 */               { 1, { { 0, -1 }, } }, /* untested */
index d950fc34320a61e21a32f9a8b4dc928f9fcc365a..554e11f9e1cea9705ab4b54fa43ea9c60f33d558 100644 (file)
@@ -429,9 +429,6 @@ struct parport_default_sysctl_table
        ctl_table dev_dir[2];
 };
 
-extern unsigned long parport_default_timeslice;
-extern int parport_default_spintime;
-
 static struct parport_default_sysctl_table
 parport_default_sysctl_table = {
        .sysctl_header  = NULL,
index f941f609dbf399edfd389b4ace85a07816a5e633..8bf86ae2333fc963207d2b14d2702c96a9532bc6 100644 (file)
@@ -317,10 +317,8 @@ int __init dmar_table_init(void)
                return -ENODEV;
        }
 
-       if (list_empty(&dmar_rmrr_units)) {
+       if (list_empty(&dmar_rmrr_units))
                printk(KERN_INFO PREFIX "No RMRR found\n");
-               return -ENODEV;
-       }
 
        return 0;
 }
index 1323a43285d71efb7635e1114d939fef34618219..ad27e9e225a6f37b2ee7bb46dc601a0e73ad11db 100644 (file)
@@ -1103,7 +1103,7 @@ static inline void dbg_ctrl(struct controller *ctrl)
        dbg("  Power Indicator      : %3s\n", PWR_LED(ctrl)    ? "yes" : "no");
        dbg("  Hot-Plug Surprise    : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
        dbg("  EMI Present          : %3s\n", EMI(ctrl)        ? "yes" : "no");
-       dbg("  Comamnd Completed    : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes");
+       dbg("  Command Completed    : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes");
        pciehp_readw(ctrl, SLOTSTATUS, &reg16);
        dbg("Slot Status            : 0x%04x\n", reg16);
        pciehp_readw(ctrl, SLOTCTRL, &reg16);
index 15af618d36e20a0f64c704b67cc14e2c1dc2daf2..18354817173ccaaeaf9110e0c5c9be4aeb50a2b1 100644 (file)
@@ -126,7 +126,16 @@ static void msix_flush_writes(unsigned int irq)
        }
 }
 
-static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
+/*
+ * PCI 2.3 does not specify mask bits for each MSI interrupt.  Attempting to
+ * mask all MSI interrupts by clearing the MSI enable bit does not work
+ * reliably as devices without an INTx disable bit will then generate a
+ * level IRQ which will never be cleared.
+ *
+ * Returns 1 if it succeeded in masking the interrupt and 0 if the device
+ * doesn't support MSI masking.
+ */
+static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
 {
        struct msi_desc *entry;
 
@@ -144,8 +153,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
                        mask_bits |= flag & mask;
                        pci_write_config_dword(entry->dev, pos, mask_bits);
                } else {
-                       __msi_set_enable(entry->dev, entry->msi_attrib.pos,
-                                        !flag);
+                       return 0;
                }
                break;
        case PCI_CAP_ID_MSIX:
@@ -161,6 +169,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
                break;
        }
        entry->msi_attrib.masked = !!flag;
+       return 1;
 }
 
 void read_msi_msg(unsigned int irq, struct msi_msg *msg)
index 7764768b6a0e7dfc225c76693b3be997df4b926f..89a2f0fa10f91d79b216bc78da9d19eb0fbd3941 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/module.h>
+#include <linux/pci-aspm.h>
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acresrc.h>
@@ -372,6 +373,12 @@ static int __init acpi_pci_init(void)
                printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n");
                pci_no_msi();
        }
+
+       if (acpi_gbl_FADT.boot_flags & BAF_PCIE_ASPM_CONTROL) {
+               printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
+               pcie_no_aspm();
+       }
+
        ret = register_acpi_bus_type(&acpi_pci_bus);
        if (ret)
                return 0;
index d00f0e0d84537168c3464d476db3485753924450..0a3d856833fcaf669482eb19cf7cbe73a91f45d9 100644 (file)
@@ -572,6 +572,10 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
                if (!ret)
                        pci_update_current_state(dev);
        }
+       /* This device is quirked not to be put into D3, so
+          don't put it in D3 */
+       if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
+               return 0;
 
        error = pci_raw_set_power_state(dev, state);
 
@@ -1040,7 +1044,7 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
  * @dev: PCI device to handle.
  * @state: PCI state from which device will issue PME#.
  */
-static bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
+bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
 {
        if (!dev->pm_cap)
                return false;
@@ -1123,17 +1127,16 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
 }
 
 /**
- * pci_prepare_to_sleep - prepare PCI device for system-wide transition into a sleep state
- * @dev: Device to handle.
+ * pci_target_state - find an appropriate low power state for a given PCI dev
+ * @dev: PCI device
  *
- * Choose the power state appropriate for the device depending on whether
- * it can wake up the system and/or is power manageable by the platform
- * (PCI_D3hot is the default) and put the device into that state.
+ * Use underlying platform code to find a supported low power state for @dev.
+ * If the platform can't manage @dev, return the deepest state from which it
+ * can generate wake events, based on any available PME info.
  */
-int pci_prepare_to_sleep(struct pci_dev *dev)
+pci_power_t pci_target_state(struct pci_dev *dev)
 {
        pci_power_t target_state = PCI_D3hot;
-       int error;
 
        if (platform_pci_power_manageable(dev)) {
                /*
@@ -1160,7 +1163,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
                 * to generate PME#.
                 */
                if (!dev->pm_cap)
-                       return -EIO;
+                       return PCI_POWER_ERROR;
 
                if (dev->pme_support) {
                        while (target_state
@@ -1169,6 +1172,25 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
                }
        }
 
+       return target_state;
+}
+
+/**
+ * pci_prepare_to_sleep - prepare PCI device for system-wide transition into a sleep state
+ * @dev: Device to handle.
+ *
+ * Choose the power state appropriate for the device depending on whether
+ * it can wake up the system and/or is power manageable by the platform
+ * (PCI_D3hot is the default) and put the device into that state.
+ */
+int pci_prepare_to_sleep(struct pci_dev *dev)
+{
+       pci_power_t target_state = pci_target_state(dev);
+       int error;
+
+       if (target_state == PCI_POWER_ERROR)
+               return -EIO;
+
        pci_enable_wake(dev, target_state, true);
 
        error = pci_set_power_state(dev, target_state);
@@ -1918,7 +1940,9 @@ EXPORT_SYMBOL(pci_select_bars);
 EXPORT_SYMBOL(pci_set_power_state);
 EXPORT_SYMBOL(pci_save_state);
 EXPORT_SYMBOL(pci_restore_state);
+EXPORT_SYMBOL(pci_pme_capable);
 EXPORT_SYMBOL(pci_enable_wake);
+EXPORT_SYMBOL(pci_target_state);
 EXPORT_SYMBOL(pci_prepare_to_sleep);
 EXPORT_SYMBOL(pci_back_from_sleep);
 EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
index f82495583e63c123a89a41e23af1b658ac509a62..9a7c9e1408a41823aef2198f6e3a8e0e220d609a 100644 (file)
@@ -55,7 +55,7 @@ struct pcie_link_state {
        struct endpoint_state endpoints[8];
 };
 
-static int aspm_disabled;
+static int aspm_disabled, aspm_force;
 static DEFINE_MUTEX(aspm_lock);
 static LIST_HEAD(link_list);
 
@@ -510,6 +510,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
 {
        struct pci_dev *child_dev;
        int child_pos;
+       u32 reg32;
 
        /*
         * Some functions in a slot might not all be PCIE functions, very
@@ -519,6 +520,19 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
                child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
                if (!child_pos)
                        return -EINVAL;
+
+               /*
+                * Disable ASPM for pre-1.1 PCIe device, we follow MS to use
+                * RBER bit to determine if a function is 1.1 version device
+                */
+               pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP,
+                       &reg32);
+               if (!(reg32 & PCI_EXP_DEVCAP_RBER && !aspm_force)) {
+                       printk("Pre-1.1 PCIe device detected, "
+                               "disable ASPM for %s. It can be enabled forcedly"
+                               " with 'pcie_aspm=force'\n", pci_name(pdev));
+                       return -EINVAL;
+               }
        }
        return 0;
 }
@@ -802,11 +816,23 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
 
 static int __init pcie_aspm_disable(char *str)
 {
-       aspm_disabled = 1;
+       if (!strcmp(str, "off")) {
+               aspm_disabled = 1;
+               printk(KERN_INFO "PCIe ASPM is disabled\n");
+       } else if (!strcmp(str, "force")) {
+               aspm_force = 1;
+               printk(KERN_INFO "PCIe ASPM is forcedly enabled\n");
+       }
        return 1;
 }
 
-__setup("pcie_noaspm", pcie_aspm_disable);
+__setup("pcie_aspm=", pcie_aspm_disable);
+
+void pcie_no_aspm(void)
+{
+       if (!aspm_force)
+               aspm_disabled = 1;
+}
 
 #ifdef CONFIG_ACPI
 #include <acpi/acpi_bus.h>
index b1724cf31b669ef459d3250aa8fae48b38e4c7fa..7098dfb07449ebfa665144f3fc3537c1b27ebad3 100644 (file)
@@ -163,12 +163,9 @@ static inline unsigned int pci_calc_resource_flags(unsigned int flags)
        return IORESOURCE_MEM;
 }
 
-/*
- * Find the extent of a PCI decode..
- */
-static u32 pci_size(u32 base, u32 maxbase, u32 mask)
+static u64 pci_size(u64 base, u64 maxbase, u64 mask)
 {
-       u32 size = mask & maxbase;      /* Find the significant bits */
+       u64 size = mask & maxbase;      /* Find the significant bits */
        if (!size)
                return 0;
 
@@ -184,135 +181,142 @@ static u32 pci_size(u32 base, u32 maxbase, u32 mask)
        return size;
 }
 
-static u64 pci_size64(u64 base, u64 maxbase, u64 mask)
-{
-       u64 size = mask & maxbase;      /* Find the significant bits */
-       if (!size)
-               return 0;
+enum pci_bar_type {
+       pci_bar_unknown,        /* Standard PCI BAR probe */
+       pci_bar_io,             /* An io port BAR */
+       pci_bar_mem32,          /* A 32-bit memory BAR */
+       pci_bar_mem64,          /* A 64-bit memory BAR */
+};
 
-       /* Get the lowest of them to find the decode size, and
-          from that the extent.  */
-       size = (size & ~(size-1)) - 1;
+static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
+{
+       if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
+               res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK;
+               return pci_bar_io;
+       }
 
-       /* base == maxbase can be valid only if the BAR has
-          already been programmed with all 1s.  */
-       if (base == maxbase && ((base | size) & mask) != mask)
-               return 0;
+       res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
 
-       return size;
+       if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64)
+               return pci_bar_mem64;
+       return pci_bar_mem32;
 }
 
-static inline int is_64bit_memory(u32 mask)
+/*
+ * If the type is not unknown, we assume that the lowest bit is 'enable'.
+ * Returns 1 if the BAR was 64-bit and 0 if it was 32-bit.
+ */
+static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
+                       struct resource *res, unsigned int pos)
 {
-       if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
-           (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64))
-               return 1;
-       return 0;
-}
+       u32 l, sz, mask;
 
-static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
-{
-       unsigned int pos, reg, next;
-       u32 l, sz;
-       struct resource *res;
+       mask = type ? ~PCI_ROM_ADDRESS_ENABLE : ~0;
 
-       for(pos=0; pos<howmany; pos = next) {
-               u64 l64;
-               u64 sz64;
-               u32 raw_sz;
+       res->name = pci_name(dev);
 
-               next = pos+1;
-               res = &dev->resource[pos];
-               res->name = pci_name(dev);
-               reg = PCI_BASE_ADDRESS_0 + (pos << 2);
-               pci_read_config_dword(dev, reg, &l);
-               pci_write_config_dword(dev, reg, ~0);
-               pci_read_config_dword(dev, reg, &sz);
-               pci_write_config_dword(dev, reg, l);
-               if (!sz || sz == 0xffffffff)
-                       continue;
-               if (l == 0xffffffff)
-                       l = 0;
-               raw_sz = sz;
-               if ((l & PCI_BASE_ADDRESS_SPACE) ==
-                               PCI_BASE_ADDRESS_SPACE_MEMORY) {
-                       sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK);
-                       /*
-                        * For 64bit prefetchable memory sz could be 0, if the
-                        * real size is bigger than 4G, so we need to check
-                        * szhi for that.
-                        */
-                       if (!is_64bit_memory(l) && !sz)
-                               continue;
-                       res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
-                       res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK;
+       pci_read_config_dword(dev, pos, &l);
+       pci_write_config_dword(dev, pos, mask);
+       pci_read_config_dword(dev, pos, &sz);
+       pci_write_config_dword(dev, pos, l);
+
+       /*
+        * All bits set in sz means the device isn't working properly.
+        * If the BAR isn't implemented, all bits must be 0.  If it's a
+        * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit
+        * 1 must be clear.
+        */
+       if (!sz || sz == 0xffffffff)
+               goto fail;
+
+       /*
+        * I don't know how l can have all bits set.  Copied from old code.
+        * Maybe it fixes a bug on some ancient platform.
+        */
+       if (l == 0xffffffff)
+               l = 0;
+
+       if (type == pci_bar_unknown) {
+               type = decode_bar(res, l);
+               res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
+               if (type == pci_bar_io) {
+                       l &= PCI_BASE_ADDRESS_IO_MASK;
+                       mask = PCI_BASE_ADDRESS_IO_MASK & 0xffff;
                } else {
-                       sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff);
-                       if (!sz)
-                               continue;
-                       res->start = l & PCI_BASE_ADDRESS_IO_MASK;
-                       res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
+                       l &= PCI_BASE_ADDRESS_MEM_MASK;
+                       mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
                }
-               res->end = res->start + (unsigned long) sz;
-               res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
-               if (is_64bit_memory(l)) {
-                       u32 szhi, lhi;
-
-                       pci_read_config_dword(dev, reg+4, &lhi);
-                       pci_write_config_dword(dev, reg+4, ~0);
-                       pci_read_config_dword(dev, reg+4, &szhi);
-                       pci_write_config_dword(dev, reg+4, lhi);
-                       sz64 = ((u64)szhi << 32) | raw_sz;
-                       l64 = ((u64)lhi << 32) | l;
-                       sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK);
-                       next++;
-#if BITS_PER_LONG == 64
-                       if (!sz64) {
-                               res->start = 0;
-                               res->end = 0;
-                               res->flags = 0;
-                               continue;
-                       }
-                       res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK;
-                       res->end = res->start + sz64;
-#else
-                       if (sz64 > 0x100000000ULL) {
-                               dev_err(&dev->dev, "BAR %d: can't handle 64-bit"
-                                       " BAR\n", pos);
-                               res->start = 0;
-                               res->flags = 0;
-                       } else if (lhi) {
-                               /* 64-bit wide address, treat as disabled */
-                               pci_write_config_dword(dev, reg,
-                                       l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK);
-                               pci_write_config_dword(dev, reg+4, 0);
-                               res->start = 0;
-                               res->end = sz;
-                       }
-#endif
+       } else {
+               res->flags |= (l & IORESOURCE_ROM_ENABLE);
+               l &= PCI_ROM_ADDRESS_MASK;
+               mask = (u32)PCI_ROM_ADDRESS_MASK;
+       }
+
+       if (type == pci_bar_mem64) {
+               u64 l64 = l;
+               u64 sz64 = sz;
+               u64 mask64 = mask | (u64)~0 << 32;
+
+               pci_read_config_dword(dev, pos + 4, &l);
+               pci_write_config_dword(dev, pos + 4, ~0);
+               pci_read_config_dword(dev, pos + 4, &sz);
+               pci_write_config_dword(dev, pos + 4, l);
+
+               l64 |= ((u64)l << 32);
+               sz64 |= ((u64)sz << 32);
+
+               sz64 = pci_size(l64, sz64, mask64);
+
+               if (!sz64)
+                       goto fail;
+
+               if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
+                       dev_err(&dev->dev, "can't handle 64-bit BAR\n");
+                       goto fail;
+               } else if ((sizeof(resource_size_t) < 8) && l) {
+                       /* Address above 32-bit boundary; disable the BAR */
+                       pci_write_config_dword(dev, pos, 0);
+                       pci_write_config_dword(dev, pos + 4, 0);
+                       res->start = 0;
+                       res->end = sz64;
+               } else {
+                       res->start = l64;
+                       res->end = l64 + sz64;
                }
+       } else {
+               sz = pci_size(l, sz, mask);
+
+               if (!sz)
+                       goto fail;
+
+               res->start = l;
+               res->end = l + sz;
        }
+
+ out:
+       return (type == pci_bar_mem64) ? 1 : 0;
+ fail:
+       res->flags = 0;
+       goto out;
+}
+
+static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
+{
+       unsigned int pos, reg;
+
+       for (pos = 0; pos < howmany; pos++) {
+               struct resource *res = &dev->resource[pos];
+               reg = PCI_BASE_ADDRESS_0 + (pos << 2);
+               pos += __pci_read_base(dev, pci_bar_unknown, res, reg);
+       }
+
        if (rom) {
+               struct resource *res = &dev->resource[PCI_ROM_RESOURCE];
                dev->rom_base_reg = rom;
-               res = &dev->resource[PCI_ROM_RESOURCE];
-               res->name = pci_name(dev);
-               pci_read_config_dword(dev, rom, &l);
-               pci_write_config_dword(dev, rom, ~PCI_ROM_ADDRESS_ENABLE);
-               pci_read_config_dword(dev, rom, &sz);
-               pci_write_config_dword(dev, rom, l);
-               if (l == 0xffffffff)
-                       l = 0;
-               if (sz && sz != 0xffffffff) {
-                       sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK);
-                       if (sz) {
-                               res->flags = (l & IORESOURCE_ROM_ENABLE) |
-                                 IORESOURCE_MEM | IORESOURCE_PREFETCH |
-                                 IORESOURCE_READONLY | IORESOURCE_CACHEABLE |
-                                 IORESOURCE_SIZEALIGN;
-                               res->start = l & PCI_ROM_ADDRESS_MASK;
-                               res->end = res->start + (unsigned long) sz;
-                       }
-               }
+               res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH |
+                               IORESOURCE_READONLY | IORESOURCE_CACHEABLE |
+                               IORESOURCE_SIZEALIGN;
+               __pci_read_base(dev, pci_bar_mem32, res, rom);
        }
 }
 
@@ -1053,7 +1057,8 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
                }
        }
 
-       if (bus->self)
+       /* only one slot has pcie device */
+       if (bus->self && nr)
                pcie_aspm_init_link_state(bus->self);
 
        return nr;
index 4400dffbd93a853310855cd441cf7f5293e8c091..e1098c302c4565d56cdb59e97e276293dd1bbbb5 100644 (file)
@@ -88,7 +88,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
        if ((pos & 3) && cnt > 2) {
                unsigned short val;
                pci_user_read_config_word(dev, pos, &val);
-               __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
+               __put_user(cpu_to_le16(val), (__le16 __user *) buf);
                buf += 2;
                pos += 2;
                cnt -= 2;
@@ -97,7 +97,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
        while (cnt >= 4) {
                unsigned int val;
                pci_user_read_config_dword(dev, pos, &val);
-               __put_user(cpu_to_le32(val), (unsigned int __user *) buf);
+               __put_user(cpu_to_le32(val), (__le32 __user *) buf);
                buf += 4;
                pos += 4;
                cnt -= 4;
@@ -106,7 +106,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
        if (cnt >= 2) {
                unsigned short val;
                pci_user_read_config_word(dev, pos, &val);
-               __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
+               __put_user(cpu_to_le16(val), (__le16 __user *) buf);
                buf += 2;
                pos += 2;
                cnt -= 2;
@@ -156,8 +156,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        }
 
        if ((pos & 3) && cnt > 2) {
-               unsigned short val;
-               __get_user(val, (unsigned short __user *) buf);
+               __le16 val;
+               __get_user(val, (__le16 __user *) buf);
                pci_user_write_config_word(dev, pos, le16_to_cpu(val));
                buf += 2;
                pos += 2;
@@ -165,8 +165,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        }
 
        while (cnt >= 4) {
-               unsigned int val;
-               __get_user(val, (unsigned int __user *) buf);
+               __le32 val;
+               __get_user(val, (__le32 __user *) buf);
                pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
                buf += 4;
                pos += 4;
@@ -174,8 +174,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        }
 
        if (cnt >= 2) {
-               unsigned short val;
-               __get_user(val, (unsigned short __user *) buf);
+               __le16 val;
+               __get_user(val, (__le16 __user *) buf);
                pci_user_write_config_word(dev, pos, le16_to_cpu(val));
                buf += 2;
                pos += 2;
index 12d489395fad0496d7953a78a30d6237ae9018ac..0fb365074288f20d40a2bf954cb9b42a848c479d 100644 (file)
@@ -923,6 +923,19 @@ static void __init quirk_ide_samemode(struct pci_dev *pdev)
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode);
 
+/*
+ * Some ATA devices break if put into D3
+ */
+
+static void __devinit quirk_no_ata_d3(struct pci_dev *pdev)
+{
+       /* Quirk the legacy ATA devices only. The AHCI ones are ok */
+       if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
+               pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3);
+
 /* This was originally an Alpha specific thing, but it really fits here.
  * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
  */
index c21f9a9c3e3f45d04b034d0e291652039c032918..a34284b1482a52ab5f2282fe3c7263049f6e3a4c 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/of_platform.h>
 
index 420a77540f412758979e72b300d7aeac1801b145..8c21446996f2190632d59d55b2c173dad6e0273e 100644 (file)
@@ -149,10 +149,10 @@ soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *stat
                 */
                if (skt->irq_state != 1 && state->io_irq) {
                        skt->irq_state = 1;
-                       set_irq_type(skt->irq, IRQT_FALLING);
+                       set_irq_type(skt->irq, IRQ_TYPE_EDGE_FALLING);
                } else if (skt->irq_state == 1 && state->io_irq == 0) {
                        skt->irq_state = 0;
-                       set_irq_type(skt->irq, IRQT_NOEDGE);
+                       set_irq_type(skt->irq, IRQ_TYPE_NONE);
                }
 
                skt->cs_state = *state;
@@ -527,7 +527,7 @@ int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt,
                                  IRQF_DISABLED, irqs[i].str, skt);
                if (res)
                        break;
-               set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+               set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
        }
 
        if (res) {
@@ -560,7 +560,7 @@ void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt,
 
        for (i = 0; i < nr; i++)
                if (irqs[i].sock == skt->nr)
-                       set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+                       set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
 }
 EXPORT_SYMBOL(soc_pcmcia_disable_irqs);
 
@@ -571,8 +571,8 @@ void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt,
 
        for (i = 0; i < nr; i++)
                if (irqs[i].sock == skt->nr) {
-                       set_irq_type(irqs[i].irq, IRQT_RISING);
-                       set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
+                       set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_RISING);
+                       set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_BOTH);
                }
 }
 EXPORT_SYMBOL(soc_pcmcia_enable_irqs);
index e3fa9a2d9a3d3a2a9124bd334c54632aeb760f94..9fd7bb9b7dce2579d1955a055ad5bf362f0e14b2 100644 (file)
@@ -19,7 +19,6 @@ struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
 int pnp_interface_attach_device(struct pnp_dev *dev);
 
 int pnp_add_card(struct pnp_card *card);
-struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id);
 void pnp_remove_card(struct pnp_card *card);
 int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
 void pnp_remove_card_device(struct pnp_dev *dev);
index a762a4176736fcc5aa3e5d3ce4016ca921bcabbd..e75b060daa955231af4d52a79816fa4824a17d5b 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/ctype.h>
 #include <linux/slab.h>
 #include <linux/pnp.h>
+#include <linux/dma-mapping.h>
 #include "base.h"
 
 LIST_HEAD(pnp_cards);
@@ -101,7 +102,7 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv)
  * @id: pointer to a pnp_id structure
  * @card: pointer to the desired card
  */
-struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id)
+static struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id)
 {
        struct pnp_id *dev_id, *ptr;
 
@@ -167,6 +168,9 @@ struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnp
        sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
                card->number);
 
+       card->dev.coherent_dma_mask = DMA_24BIT_MASK;
+       card->dev.dma_mask = &card->dev.coherent_dma_mask;
+
        dev_id = pnp_add_card_id(card, pnpid);
        if (!dev_id) {
                kfree(card);
index 55f55ed72dc7a69019d9c948c35c827d918955bd..0bdf9b8a5e58593d308ecc95f25fb7d2209e2998 100644 (file)
@@ -245,15 +245,17 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
         */
        for_each_pci_dev(pdev) {
                for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-                       if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM) ||
-                           pci_resource_len(pdev, i) == 0)
+                       unsigned int type;
+
+                       type = pci_resource_flags(pdev, i) &
+                                       (IORESOURCE_IO | IORESOURCE_MEM);
+                       if (!type || pci_resource_len(pdev, i) == 0)
                                continue;
 
                        pci_start = pci_resource_start(pdev, i);
                        pci_end = pci_resource_end(pdev, i);
                        for (j = 0;
-                            (res = pnp_get_resource(dev, IORESOURCE_MEM, j));
-                            j++) {
+                            (res = pnp_get_resource(dev, type, j)); j++) {
                                if (res->start == 0 && res->end == 0)
                                        continue;
 
@@ -283,9 +285,10 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
                                 * the PCI region, and that might prevent a PCI
                                 * driver from requesting its resources.
                                 */
-                               dev_warn(&dev->dev, "mem resource "
+                               dev_warn(&dev->dev, "%s resource "
                                        "(0x%llx-0x%llx) overlaps %s BAR %d "
                                        "(0x%llx-0x%llx), disabling\n",
+                                       pnp_resource_type_name(res),
                                        (unsigned long long) pnp_start,
                                        (unsigned long long) pnp_end,
                                        pci_name(pdev), i,
index 71be36f18709e80771719103941e40c9f653f922..308ddb201b660da9d84e21279eef011eb87907af 100644 (file)
@@ -433,6 +433,8 @@ static int ds2760_battery_resume(struct platform_device *pdev)
 
 #endif /* CONFIG_PM */
 
+MODULE_ALIAS("platform:ds2760-battery");
+
 static struct platform_driver ds2760_battery_driver = {
        .driver = {
                .name = "ds2760-battery",
index 82810b7bff9ccbf7b2dd183f7e49e4036239ff66..0471ec743ab9561425d723482c986b809fbf1d9c 100644 (file)
@@ -362,6 +362,8 @@ static int pda_power_resume(struct platform_device *pdev)
 #define pda_power_resume NULL
 #endif /* CONFIG_PM */
 
+MODULE_ALIAS("platform:pda-power");
+
 static struct platform_driver pda_power_pdrv = {
        .driver = {
                .name = "pda-power",
index fc85bf2e4a9752887566eb20f5a8eacbb897fb68..90ab73825401a0b5f4c0b7de15c5ff755a4edb7d 100644 (file)
@@ -273,6 +273,25 @@ comment "SPI RTC drivers"
 
 if SPI_MASTER
 
+config RTC_DRV_M41T94
+       tristate "ST M41T94"
+       help
+         If you say yes here you will get support for the
+         ST M41T94 SPI RTC chip.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-m41t94.
+
+config RTC_DRV_DS1305
+       tristate "Dallas/Maxim DS1305/DS1306"
+       help
+         Select this driver to get support for the Dallas/Maxim DS1305
+         and DS1306 real time clock chips.  These support a trickle
+         charger, alarms, and NVRAM in addition to the clock.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-ds1305.
+
 config RTC_DRV_MAX6902
        tristate "Maxim MAX6902"
        help
index b5d9d67df887f7be847d23e0ef7f7b6e4c0eb233..18622ef84cab0c4f48e15aa437edccff357136e4 100644 (file)
@@ -24,6 +24,7 @@ obj-$(CONFIG_RTC_DRV_BFIN)    += rtc-bfin.o
 obj-$(CONFIG_RTC_DRV_CMOS)     += rtc-cmos.o
 obj-$(CONFIG_RTC_DRV_DS1216)   += rtc-ds1216.o
 obj-$(CONFIG_RTC_DRV_DS1302)   += rtc-ds1302.o
+obj-$(CONFIG_RTC_DRV_DS1305)   += rtc-ds1305.o
 obj-$(CONFIG_RTC_DRV_DS1307)   += rtc-ds1307.o
 obj-$(CONFIG_RTC_DRV_DS1374)   += rtc-ds1374.o
 obj-$(CONFIG_RTC_DRV_DS1511)   += rtc-ds1511.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX)  += rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)   += rtc-fm3130.o
 obj-$(CONFIG_RTC_DRV_ISL1208)  += rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_M41T80)   += rtc-m41t80.o
+obj-$(CONFIG_RTC_DRV_M41T94)   += rtc-m41t94.o
 obj-$(CONFIG_RTC_DRV_M48T59)   += rtc-m48t59.o
 obj-$(CONFIG_RTC_DRV_M48T86)   += rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_MAX6900)  += rtc-max6900.o
index 9c3db934cc247b6d68859b3869980feeefd92936..cd32d05db773bcc2f16081a75daecbaf9f073a74 100644 (file)
@@ -171,8 +171,10 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
                | BIN2BCD(tm.tm_mday) << 24
                | AT91_RTC_DATEEN | AT91_RTC_MTHEN);
 
-       if (alrm->enabled)
+       if (alrm->enabled) {
+               at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
                at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+       }
 
        pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
                at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
@@ -191,28 +193,22 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
 
        pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg);
 
+       /* important:  scrub old status before enabling IRQs */
        switch (cmd) {
        case RTC_AIE_OFF:       /* alarm off */
                at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
                break;
        case RTC_AIE_ON:        /* alarm on */
+               at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
                at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
                break;
        case RTC_UIE_OFF:       /* update off */
-       case RTC_PIE_OFF:       /* periodic off */
                at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
                break;
        case RTC_UIE_ON:        /* update on */
-       case RTC_PIE_ON:        /* periodic on */
+               at91_sys_write(AT91_RTC_SCCR, AT91_RTC_SECEV);
                at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
                break;
-       case RTC_IRQP_READ:     /* read periodic alarm frequency */
-               ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
-               break;
-       case RTC_IRQP_SET:      /* set periodic alarm frequency */
-               if (arg != AT91_RTC_FREQ)
-                       ret = -EINVAL;
-               break;
        default:
                ret = -ENOIOCTLCMD;
                break;
index d7bb9bac71df9494a6b18b90b52c0c23b986a272..6ea349aba3ba1fa81f159bcbb18235073cf80164 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/mod_devicetable.h>
 
-#ifdef CONFIG_HPET_EMULATE_RTC
-#include <asm/hpet.h>
-#endif
-
 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
 #include <asm-generic/rtc.h>
 
-#ifndef CONFIG_HPET_EMULATE_RTC
-#define is_hpet_enabled()                      0
-#define hpet_set_alarm_time(hrs, min, sec)     do { } while (0)
-#define hpet_set_periodic_freq(arg)            0
-#define hpet_mask_rtc_irq_bit(arg)             do { } while (0)
-#define hpet_set_rtc_irq_bit(arg)              do { } while (0)
-#define hpet_rtc_timer_init()                  do { } while (0)
-#define hpet_register_irq_handler(h)           0
-#define hpet_unregister_irq_handler(h)         do { } while (0)
-extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
-#endif
-
 struct cmos_rtc {
        struct rtc_device       *rtc;
        struct device           *dev;
@@ -93,6 +77,72 @@ static inline int is_intr(u8 rtc_intr)
 
 /*----------------------------------------------------------------*/
 
+/* Much modern x86 hardware has HPETs (10+ MHz timers) which, because
+ * many BIOS programmers don't set up "sane mode" IRQ routing, are mostly
+ * used in a broken "legacy replacement" mode.  The breakage includes
+ * HPET #1 hijacking the IRQ for this RTC, and being unavailable for
+ * other (better) use.
+ *
+ * When that broken mode is in use, platform glue provides a partial
+ * emulation of hardware RTC IRQ facilities using HPET #1.  We don't
+ * want to use HPET for anything except those IRQs though...
+ */
+#ifdef CONFIG_HPET_EMULATE_RTC
+#include <asm/hpet.h>
+#else
+
+static inline int is_hpet_enabled(void)
+{
+       return 0;
+}
+
+static inline int hpet_mask_rtc_irq_bit(unsigned long mask)
+{
+       return 0;
+}
+
+static inline int hpet_set_rtc_irq_bit(unsigned long mask)
+{
+       return 0;
+}
+
+static inline int
+hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
+{
+       return 0;
+}
+
+static inline int hpet_set_periodic_freq(unsigned long freq)
+{
+       return 0;
+}
+
+static inline int hpet_rtc_dropped_irq(void)
+{
+       return 0;
+}
+
+static inline int hpet_rtc_timer_init(void)
+{
+       return 0;
+}
+
+extern irq_handler_t hpet_rtc_interrupt;
+
+static inline int hpet_register_irq_handler(irq_handler_t handler)
+{
+       return 0;
+}
+
+static inline int hpet_unregister_irq_handler(irq_handler_t handler)
+{
+       return 0;
+}
+
+#endif
+
+/*----------------------------------------------------------------*/
+
 static int cmos_read_time(struct device *dev, struct rtc_time *t)
 {
        /* REVISIT:  if the clock has a "century" register, use
@@ -185,11 +235,56 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        return 0;
 }
 
+static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control)
+{
+       unsigned char   rtc_intr;
+
+       /* NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
+        * allegedly some older rtcs need that to handle irqs properly
+        */
+       rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
+
+       if (is_hpet_enabled())
+               return;
+
+       rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+       if (is_intr(rtc_intr))
+               rtc_update_irq(cmos->rtc, 1, rtc_intr);
+}
+
+static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask)
+{
+       unsigned char   rtc_control;
+
+       /* flush any pending IRQ status, notably for update irqs,
+        * before we enable new IRQs
+        */
+       rtc_control = CMOS_READ(RTC_CONTROL);
+       cmos_checkintr(cmos, rtc_control);
+
+       rtc_control |= mask;
+       CMOS_WRITE(rtc_control, RTC_CONTROL);
+       hpet_set_rtc_irq_bit(mask);
+
+       cmos_checkintr(cmos, rtc_control);
+}
+
+static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
+{
+       unsigned char   rtc_control;
+
+       rtc_control = CMOS_READ(RTC_CONTROL);
+       rtc_control &= ~mask;
+       CMOS_WRITE(rtc_control, RTC_CONTROL);
+       hpet_mask_rtc_irq_bit(mask);
+
+       cmos_checkintr(cmos, rtc_control);
+}
+
 static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
        unsigned char   mon, mday, hrs, min, sec;
-       unsigned char   rtc_control, rtc_intr;
 
        if (!is_valid_irq(cmos->irq))
                return -EIO;
@@ -213,17 +308,10 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        sec = t->time.tm_sec;
        sec = (sec < 60) ? BIN2BCD(sec) : 0xff;
 
-       hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
        spin_lock_irq(&rtc_lock);
 
        /* next rtc irq must not be from previous alarm setting */
-       rtc_control = CMOS_READ(RTC_CONTROL);
-       rtc_control &= ~RTC_AIE;
-       CMOS_WRITE(rtc_control, RTC_CONTROL);
-       rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
-       rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
-       if (is_intr(rtc_intr))
-               rtc_update_irq(cmos->rtc, 1, rtc_intr);
+       cmos_irq_disable(cmos, RTC_AIE);
 
        /* update alarm */
        CMOS_WRITE(hrs, RTC_HOURS_ALARM);
@@ -237,14 +325,13 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
                        CMOS_WRITE(mon, cmos->mon_alrm);
        }
 
-       if (t->enabled) {
-               rtc_control |= RTC_AIE;
-               CMOS_WRITE(rtc_control, RTC_CONTROL);
-               rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
-               rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
-               if (is_intr(rtc_intr))
-                       rtc_update_irq(cmos->rtc, 1, rtc_intr);
-       }
+       /* FIXME the HPET alarm glue currently ignores day_alrm
+        * and mon_alrm ...
+        */
+       hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
+
+       if (t->enabled)
+               cmos_irq_enable(cmos, RTC_AIE);
 
        spin_unlock_irq(&rtc_lock);
 
@@ -267,8 +354,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
        f = 16 - f;
 
        spin_lock_irqsave(&rtc_lock, flags);
-       if (!hpet_set_periodic_freq(freq))
-               CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
+       hpet_set_periodic_freq(freq);
+       CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
        return 0;
@@ -277,26 +364,17 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
 static int cmos_irq_set_state(struct device *dev, int enabled)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
-       unsigned char   rtc_control, rtc_intr;
        unsigned long   flags;
 
        if (!is_valid_irq(cmos->irq))
                return -ENXIO;
 
        spin_lock_irqsave(&rtc_lock, flags);
-       rtc_control = CMOS_READ(RTC_CONTROL);
 
        if (enabled)
-               rtc_control |= RTC_PIE;
+               cmos_irq_enable(cmos, RTC_PIE);
        else
-               rtc_control &= ~RTC_PIE;
-
-       CMOS_WRITE(rtc_control, RTC_CONTROL);
-
-       rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
-       rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
-       if (is_intr(rtc_intr))
-               rtc_update_irq(cmos->rtc, 1, rtc_intr);
+               cmos_irq_disable(cmos, RTC_PIE);
 
        spin_unlock_irqrestore(&rtc_lock, flags);
        return 0;
@@ -308,7 +386,6 @@ static int
 cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
-       unsigned char   rtc_control, rtc_intr;
        unsigned long   flags;
 
        switch (cmd) {
@@ -316,51 +393,29 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
        case RTC_AIE_ON:
        case RTC_UIE_OFF:
        case RTC_UIE_ON:
-       case RTC_PIE_OFF:
-       case RTC_PIE_ON:
                if (!is_valid_irq(cmos->irq))
                        return -EINVAL;
                break;
+       /* PIE ON/OFF is handled by cmos_irq_set_state() */
        default:
                return -ENOIOCTLCMD;
        }
 
        spin_lock_irqsave(&rtc_lock, flags);
-       rtc_control = CMOS_READ(RTC_CONTROL);
        switch (cmd) {
        case RTC_AIE_OFF:       /* alarm off */
-               rtc_control &= ~RTC_AIE;
-               hpet_mask_rtc_irq_bit(RTC_AIE);
+               cmos_irq_disable(cmos, RTC_AIE);
                break;
        case RTC_AIE_ON:        /* alarm on */
-               rtc_control |= RTC_AIE;
-               hpet_set_rtc_irq_bit(RTC_AIE);
+               cmos_irq_enable(cmos, RTC_AIE);
                break;
        case RTC_UIE_OFF:       /* update off */
-               rtc_control &= ~RTC_UIE;
-               hpet_mask_rtc_irq_bit(RTC_UIE);
+               cmos_irq_disable(cmos, RTC_UIE);
                break;
        case RTC_UIE_ON:        /* update on */
-               rtc_control |= RTC_UIE;
-               hpet_set_rtc_irq_bit(RTC_UIE);
-               break;
-       case RTC_PIE_OFF:       /* periodic off */
-               rtc_control &= ~RTC_PIE;
-               hpet_mask_rtc_irq_bit(RTC_PIE);
-               break;
-       case RTC_PIE_ON:        /* periodic on */
-               rtc_control |= RTC_PIE;
-               hpet_set_rtc_irq_bit(RTC_PIE);
+               cmos_irq_enable(cmos, RTC_UIE);
                break;
        }
-       if (!is_hpet_enabled())
-               CMOS_WRITE(rtc_control, RTC_CONTROL);
-
-       rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
-       rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
-       if (is_intr(rtc_intr))
-               rtc_update_irq(cmos->rtc, 1, rtc_intr);
-
        spin_unlock_irqrestore(&rtc_lock, flags);
        return 0;
 }
@@ -502,27 +557,29 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
        u8              rtc_control;
 
        spin_lock(&rtc_lock);
-       /*
-        * In this case it is HPET RTC interrupt handler
-        * calling us, with the interrupt information
-        * passed as arg1, instead of irq.
+
+       /* When the HPET interrupt handler calls us, the interrupt
+        * status is passed as arg1 instead of the irq number.  But
+        * always clear irq status, even when HPET is in the way.
+        *
+        * Note that HPET and RTC are almost certainly out of phase,
+        * giving different IRQ status ...
         */
+       irqstat = CMOS_READ(RTC_INTR_FLAGS);
+       rtc_control = CMOS_READ(RTC_CONTROL);
        if (is_hpet_enabled())
                irqstat = (unsigned long)irq & 0xF0;
-       else {
-               irqstat = CMOS_READ(RTC_INTR_FLAGS);
-               rtc_control = CMOS_READ(RTC_CONTROL);
-               irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
-       }
+       irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
 
        /* All Linux RTC alarms should be treated as if they were oneshot.
         * Similar code may be needed in system wakeup paths, in case the
         * alarm woke the system.
         */
        if (irqstat & RTC_AIE) {
-               rtc_control = CMOS_READ(RTC_CONTROL);
                rtc_control &= ~RTC_AIE;
                CMOS_WRITE(rtc_control, RTC_CONTROL);
+               hpet_mask_rtc_irq_bit(RTC_AIE);
+
                CMOS_READ(RTC_INTR_FLAGS);
        }
        spin_unlock(&rtc_lock);
@@ -629,18 +686,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
         * do something about other clock frequencies.
         */
        cmos_rtc.rtc->irq_freq = 1024;
-       if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq))
-               CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
+       hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
+       CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
+
+       /* disable irqs */
+       cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE);
 
-       /* disable irqs.
-        *
-        * NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
-        * allegedly some older rtcs need that to handle irqs properly
-        */
        rtc_control = CMOS_READ(RTC_CONTROL);
-       rtc_control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
-       CMOS_WRITE(rtc_control, RTC_CONTROL);
-       CMOS_READ(RTC_INTR_FLAGS);
 
        spin_unlock_irq(&rtc_lock);
 
@@ -687,7 +739,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
                goto cleanup2;
        }
 
-       pr_info("%s: alarms up to one %s%s\n",
+       pr_info("%s: alarms up to one %s%s%s\n",
                        cmos_rtc.rtc->dev.bus_id,
                        is_valid_irq(rtc_irq)
                                ?  (cmos_rtc.mon_alrm
@@ -695,8 +747,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
                                        : (cmos_rtc.day_alrm
                                                ? "month" : "day"))
                                : "no",
-                       cmos_rtc.century ? ", y3k" : ""
-                       );
+                       cmos_rtc.century ? ", y3k" : "",
+                       is_hpet_enabled() ? ", hpet irqs" : "");
 
        return 0;
 
@@ -713,13 +765,8 @@ cleanup0:
 
 static void cmos_do_shutdown(void)
 {
-       unsigned char   rtc_control;
-
        spin_lock_irq(&rtc_lock);
-       rtc_control = CMOS_READ(RTC_CONTROL);
-       rtc_control &= ~(RTC_PIE|RTC_AIE|RTC_UIE);
-       CMOS_WRITE(rtc_control, RTC_CONTROL);
-       CMOS_READ(RTC_INTR_FLAGS);
+       cmos_irq_disable(&cmos_rtc, RTC_IRQMASK);
        spin_unlock_irq(&rtc_lock);
 }
 
@@ -760,17 +807,17 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
        spin_lock_irq(&rtc_lock);
        cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL);
        if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
-               unsigned char   irqstat;
+               unsigned char   mask;
 
                if (do_wake)
-                       tmp &= ~(RTC_PIE|RTC_UIE);
+                       mask = RTC_IRQMASK & ~RTC_AIE;
                else
-                       tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE);
+                       mask = RTC_IRQMASK;
+               tmp &= ~mask;
                CMOS_WRITE(tmp, RTC_CONTROL);
-               irqstat = CMOS_READ(RTC_INTR_FLAGS);
-               irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF;
-               if (is_intr(irqstat))
-                       rtc_update_irq(cmos->rtc, 1, irqstat);
+               hpet_mask_rtc_irq_bit(mask);
+
+               cmos_checkintr(cmos, tmp);
        }
        spin_unlock_irq(&rtc_lock);
 
@@ -796,7 +843,8 @@ static int cmos_resume(struct device *dev)
        unsigned char   tmp = cmos->suspend_ctrl;
 
        /* re-enable any irqs previously active */
-       if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
+       if (tmp & RTC_IRQMASK) {
+               unsigned char   mask;
 
                if (cmos->enabled_wake) {
                        if (cmos->wake_off)
@@ -807,18 +855,28 @@ static int cmos_resume(struct device *dev)
                }
 
                spin_lock_irq(&rtc_lock);
-               CMOS_WRITE(tmp, RTC_CONTROL);
-               tmp = CMOS_READ(RTC_INTR_FLAGS);
-               tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF;
-               if (is_intr(tmp))
-                       rtc_update_irq(cmos->rtc, 1, tmp);
+               do {
+                       CMOS_WRITE(tmp, RTC_CONTROL);
+                       hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK);
+
+                       mask = CMOS_READ(RTC_INTR_FLAGS);
+                       mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
+                       if (!is_hpet_enabled() || !is_intr(mask))
+                               break;
+
+                       /* force one-shot behavior if HPET blocked
+                        * the wake alarm's irq
+                        */
+                       rtc_update_irq(cmos->rtc, 1, mask);
+                       tmp &= ~RTC_AIE;
+                       hpet_mask_rtc_irq_bit(RTC_AIE);
+               } while (mask & RTC_AIE);
                spin_unlock_irq(&rtc_lock);
        }
 
        pr_debug("%s: resume, ctrl %02x\n",
                        cmos_rtc.rtc->dev.bus_id,
-                       cmos->suspend_ctrl);
-
+                       tmp);
 
        return 0;
 }
index 0114a78b7cbbe6687892cca1fad58dc76d8883f9..0a870b7e5c323f5a5411f6c494545d33c023465c 100644 (file)
@@ -209,7 +209,7 @@ static unsigned int rtc_dev_poll(struct file *file, poll_table *wait)
        return (data != 0) ? (POLLIN | POLLRDNORM) : 0;
 }
 
-static int rtc_dev_ioctl(struct inode *inode, struct file *file,
+static long rtc_dev_ioctl(struct file *file,
                unsigned int cmd, unsigned long arg)
 {
        int err = 0;
@@ -219,6 +219,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
        struct rtc_wkalrm alarm;
        void __user *uarg = (void __user *) arg;
 
+       err = mutex_lock_interruptible(&rtc->ops_lock);
+       if (err)
+               return -EBUSY;
+
        /* check that the calling task has appropriate permissions
         * for certain ioctls. doing this check here is useful
         * to avoid duplicate code in each driver.
@@ -227,26 +231,31 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
        case RTC_EPOCH_SET:
        case RTC_SET_TIME:
                if (!capable(CAP_SYS_TIME))
-                       return -EACCES;
+                       err = -EACCES;
                break;
 
        case RTC_IRQP_SET:
                if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE))
-                       return -EACCES;
+                       err = -EACCES;
                break;
 
        case RTC_PIE_ON:
                if (rtc->irq_freq > rtc->max_user_freq &&
                                !capable(CAP_SYS_RESOURCE))
-                       return -EACCES;
+                       err = -EACCES;
                break;
        }
 
+       if (err)
+               goto done;
+
        /* try the driver's ioctl interface */
        if (ops->ioctl) {
                err = ops->ioctl(rtc->dev.parent, cmd, arg);
-               if (err != -ENOIOCTLCMD)
+               if (err != -ENOIOCTLCMD) {
+                       mutex_unlock(&rtc->ops_lock);
                        return err;
+               }
        }
 
        /* if the driver does not provide the ioctl interface
@@ -265,15 +274,19 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
 
        switch (cmd) {
        case RTC_ALM_READ:
+               mutex_unlock(&rtc->ops_lock);
+
                err = rtc_read_alarm(rtc, &alarm);
                if (err < 0)
                        return err;
 
                if (copy_to_user(uarg, &alarm.time, sizeof(tm)))
-                       return -EFAULT;
-               break;
+                       err = -EFAULT;
+               return err;
 
        case RTC_ALM_SET:
+               mutex_unlock(&rtc->ops_lock);
+
                if (copy_from_user(&alarm.time, uarg, sizeof(tm)))
                        return -EFAULT;
 
@@ -321,24 +334,26 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
                        }
                }
 
-               err = rtc_set_alarm(rtc, &alarm);
-               break;
+               return rtc_set_alarm(rtc, &alarm);
 
        case RTC_RD_TIME:
+               mutex_unlock(&rtc->ops_lock);
+
                err = rtc_read_time(rtc, &tm);
                if (err < 0)
                        return err;
 
                if (copy_to_user(uarg, &tm, sizeof(tm)))
-                       return -EFAULT;
-               break;
+                       err = -EFAULT;
+               return err;
 
        case RTC_SET_TIME:
+               mutex_unlock(&rtc->ops_lock);
+
                if (copy_from_user(&tm, uarg, sizeof(tm)))
                        return -EFAULT;
 
-               err = rtc_set_time(rtc, &tm);
-               break;
+               return rtc_set_time(rtc, &tm);
 
        case RTC_PIE_ON:
                err = rtc_irq_set_state(rtc, NULL, 1);
@@ -376,34 +391,37 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
                break;
 #endif
        case RTC_WKALM_SET:
+               mutex_unlock(&rtc->ops_lock);
                if (copy_from_user(&alarm, uarg, sizeof(alarm)))
                        return -EFAULT;
 
-               err = rtc_set_alarm(rtc, &alarm);
-               break;
+               return rtc_set_alarm(rtc, &alarm);
 
        case RTC_WKALM_RD:
+               mutex_unlock(&rtc->ops_lock);
                err = rtc_read_alarm(rtc, &alarm);
                if (err < 0)
                        return err;
 
                if (copy_to_user(uarg, &alarm, sizeof(alarm)))
-                       return -EFAULT;
-               break;
+                       err = -EFAULT;
+               return err;
 
 #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
        case RTC_UIE_OFF:
                clear_uie(rtc);
-               return 0;
+               break;
 
        case RTC_UIE_ON:
-               return set_uie(rtc);
+               err = set_uie(rtc);
 #endif
        default:
                err = -ENOTTY;
                break;
        }
 
+done:
+       mutex_unlock(&rtc->ops_lock);
        return err;
 }
 
@@ -432,7 +450,7 @@ static const struct file_operations rtc_dev_fops = {
        .llseek         = no_llseek,
        .read           = rtc_dev_read,
        .poll           = rtc_dev_poll,
-       .ioctl          = rtc_dev_ioctl,
+       .unlocked_ioctl = rtc_dev_ioctl,
        .open           = rtc_dev_open,
        .release        = rtc_dev_release,
        .fasync         = rtc_dev_fasync,
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
new file mode 100644 (file)
index 0000000..b91d02a
--- /dev/null
@@ -0,0 +1,847 @@
+/*
+ * rtc-ds1305.c -- driver for DS1305 and DS1306 SPI RTC chips
+ *
+ * Copyright (C) 2008 David Brownell
+ *
+ * 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/bcd.h>
+#include <linux/rtc.h>
+#include <linux/workqueue.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ds1305.h>
+
+
+/*
+ * Registers ... mask DS1305_WRITE into register address to write,
+ * otherwise you're reading it.  All non-bitmask values are BCD.
+ */
+#define DS1305_WRITE           0x80
+
+
+/* RTC date/time ... the main special cases are that we:
+ *  - Need fancy "hours" encoding in 12hour mode
+ *  - Don't rely on the "day-of-week" field (or tm_wday)
+ *  - Are a 21st-century clock (2000 <= year < 2100)
+ */
+#define DS1305_RTC_LEN         7               /* bytes for RTC regs */
+
+#define DS1305_SEC             0x00            /* register addresses */
+#define DS1305_MIN             0x01
+#define DS1305_HOUR            0x02
+#      define DS1305_HR_12             0x40    /* set == 12 hr mode */
+#      define DS1305_HR_PM             0x20    /* set == PM (12hr mode) */
+#define DS1305_WDAY            0x03
+#define DS1305_MDAY            0x04
+#define DS1305_MON             0x05
+#define DS1305_YEAR            0x06
+
+
+/* The two alarms have only sec/min/hour/wday fields (ALM_LEN).
+ * DS1305_ALM_DISABLE disables a match field (some combos are bad).
+ *
+ * NOTE that since we don't use WDAY, we limit ourselves to alarms
+ * only one day into the future (vs potentially up to a week).
+ *
+ * NOTE ALSO that while we could generate once-a-second IRQs (UIE), we
+ * don't currently support them.  We'd either need to do it only when
+ * no alarm is pending (not the standard model), or to use the second
+ * alarm (implying that this is a DS1305 not DS1306, *and* that either
+ * it's wired up a second IRQ we know, or that INTCN is set)
+ */
+#define DS1305_ALM_LEN         4               /* bytes for ALM regs */
+#define DS1305_ALM_DISABLE     0x80
+
+#define DS1305_ALM0(r)         (0x07 + (r))    /* register addresses */
+#define DS1305_ALM1(r)         (0x0b + (r))
+
+
+/* three control registers */
+#define DS1305_CONTROL_LEN     3               /* bytes of control regs */
+
+#define DS1305_CONTROL         0x0f            /* register addresses */
+#      define DS1305_nEOSC             0x80    /* low enables oscillator */
+#      define DS1305_WP                0x40    /* write protect */
+#      define DS1305_INTCN             0x04    /* clear == only int0 used */
+#      define DS1306_1HZ               0x04    /* enable 1Hz output */
+#      define DS1305_AEI1              0x02    /* enable ALM1 IRQ */
+#      define DS1305_AEI0              0x01    /* enable ALM0 IRQ */
+#define DS1305_STATUS          0x10
+/* status has just AEIx bits, mirrored as IRQFx */
+#define DS1305_TRICKLE         0x11
+/* trickle bits are defined in <linux/spi/ds1305.h> */
+
+/* a bunch of NVRAM */
+#define DS1305_NVRAM_LEN       96              /* bytes of NVRAM */
+
+#define DS1305_NVRAM           0x20            /* register addresses */
+
+
+struct ds1305 {
+       struct spi_device       *spi;
+       struct rtc_device       *rtc;
+
+       struct work_struct      work;
+
+       unsigned long           flags;
+#define FLAG_EXITING   0
+
+       bool                    hr12;
+       u8                      ctrl[DS1305_CONTROL_LEN];
+};
+
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Utilities ...  tolerate 12-hour AM/PM notation in case of non-Linux
+ * software (like a bootloader) which may require it.
+ */
+
+static unsigned bcd2hour(u8 bcd)
+{
+       if (bcd & DS1305_HR_12) {
+               unsigned        hour = 0;
+
+               bcd &= ~DS1305_HR_12;
+               if (bcd & DS1305_HR_PM) {
+                       hour = 12;
+                       bcd &= ~DS1305_HR_PM;
+               }
+               hour += BCD2BIN(bcd);
+               return hour - 1;
+       }
+       return BCD2BIN(bcd);
+}
+
+static u8 hour2bcd(bool hr12, int hour)
+{
+       if (hr12) {
+               hour++;
+               if (hour <= 12)
+                       return DS1305_HR_12 | BIN2BCD(hour);
+               hour -= 12;
+               return DS1305_HR_12 | DS1305_HR_PM | BIN2BCD(hour);
+       }
+       return BIN2BCD(hour);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Interface to RTC framework
+ */
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+/*
+ * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl)
+ */
+static int ds1305_ioctl(struct device *dev, unsigned cmd, unsigned long arg)
+{
+       struct ds1305   *ds1305 = dev_get_drvdata(dev);
+       u8              buf[2];
+       int             status = -ENOIOCTLCMD;
+
+       buf[0] = DS1305_WRITE | DS1305_CONTROL;
+       buf[1] = ds1305->ctrl[0];
+
+       switch (cmd) {
+       case RTC_AIE_OFF:
+               status = 0;
+               if (!(buf[1] & DS1305_AEI0))
+                       goto done;
+               buf[1] &= ~DS1305_AEI0;
+               break;
+
+       case RTC_AIE_ON:
+               status = 0;
+               if (ds1305->ctrl[0] & DS1305_AEI0)
+                       goto done;
+               buf[1] |= DS1305_AEI0;
+               break;
+       }
+       if (status == 0) {
+               status = spi_write_then_read(ds1305->spi, buf, sizeof buf,
+                               NULL, 0);
+               if (status >= 0)
+                       ds1305->ctrl[0] = buf[1];
+       }
+
+done:
+       return status;
+}
+
+#else
+#define ds1305_ioctl   NULL
+#endif
+
+/*
+ * Get/set of date and time is pretty normal.
+ */
+
+static int ds1305_get_time(struct device *dev, struct rtc_time *time)
+{
+       struct ds1305   *ds1305 = dev_get_drvdata(dev);
+       u8              addr = DS1305_SEC;
+       u8              buf[DS1305_RTC_LEN];
+       int             status;
+
+       /* Use write-then-read to get all the date/time registers
+        * since dma from stack is nonportable
+        */
+       status = spi_write_then_read(ds1305->spi, &addr, sizeof addr,
+                       buf, sizeof buf);
+       if (status < 0)
+               return status;
+
+       dev_vdbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n",
+               "read", buf[0], buf[1], buf[2], buf[3],
+               buf[4], buf[5], buf[6]);
+
+       /* Decode the registers */
+       time->tm_sec = BCD2BIN(buf[DS1305_SEC]);
+       time->tm_min = BCD2BIN(buf[DS1305_MIN]);
+       time->tm_hour = bcd2hour(buf[DS1305_HOUR]);
+       time->tm_wday = buf[DS1305_WDAY] - 1;
+       time->tm_mday = BCD2BIN(buf[DS1305_MDAY]);
+       time->tm_mon = BCD2BIN(buf[DS1305_MON]) - 1;
+       time->tm_year = BCD2BIN(buf[DS1305_YEAR]) + 100;
+
+       dev_vdbg(dev, "%s secs=%d, mins=%d, "
+               "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+               "read", time->tm_sec, time->tm_min,
+               time->tm_hour, time->tm_mday,
+               time->tm_mon, time->tm_year, time->tm_wday);
+
+       /* Time may not be set */
+       return rtc_valid_tm(time);
+}
+
+static int ds1305_set_time(struct device *dev, struct rtc_time *time)
+{
+       struct ds1305   *ds1305 = dev_get_drvdata(dev);
+       u8              buf[1 + DS1305_RTC_LEN];
+       u8              *bp = buf;
+
+       dev_vdbg(dev, "%s secs=%d, mins=%d, "
+               "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+               "write", time->tm_sec, time->tm_min,
+               time->tm_hour, time->tm_mday,
+               time->tm_mon, time->tm_year, time->tm_wday);
+
+       /* Write registers starting at the first time/date address. */
+       *bp++ = DS1305_WRITE | DS1305_SEC;
+
+       *bp++ = BIN2BCD(time->tm_sec);
+       *bp++ = BIN2BCD(time->tm_min);
+       *bp++ = hour2bcd(ds1305->hr12, time->tm_hour);
+       *bp++ = (time->tm_wday < 7) ? (time->tm_wday + 1) : 1;
+       *bp++ = BIN2BCD(time->tm_mday);
+       *bp++ = BIN2BCD(time->tm_mon + 1);
+       *bp++ = BIN2BCD(time->tm_year - 100);
+
+       dev_dbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n",
+               "write", buf[1], buf[2], buf[3],
+               buf[4], buf[5], buf[6], buf[7]);
+
+       /* use write-then-read since dma from stack is nonportable */
+       return spi_write_then_read(ds1305->spi, buf, sizeof buf,
+                       NULL, 0);
+}
+
+/*
+ * Get/set of alarm is a bit funky:
+ *
+ * - First there's the inherent raciness of getting the (partitioned)
+ *   status of an alarm that could trigger while we're reading parts
+ *   of that status.
+ *
+ * - Second there's its limited range (we could increase it a bit by
+ *   relying on WDAY), which means it will easily roll over.
+ *
+ * - Third there's the choice of two alarms and alarm signals.
+ *   Here we use ALM0 and expect that nINT0 (open drain) is used;
+ *   that's the only real option for DS1306 runtime alarms, and is
+ *   natural on DS1305.
+ *
+ * - Fourth, there's also ALM1, and a second interrupt signal:
+ *     + On DS1305 ALM1 uses nINT1 (when INTCN=1) else nINT0;
+ *     + On DS1306 ALM1 only uses INT1 (an active high pulse)
+ *       and it won't work when VCC1 is active.
+ *
+ *   So to be most general, we should probably set both alarms to the
+ *   same value, letting ALM1 be the wakeup event source on DS1306
+ *   and handling several wiring options on DS1305.
+ *
+ * - Fifth, we support the polled mode (as well as possible; why not?)
+ *   even when no interrupt line is wired to an IRQ.
+ */
+
+/*
+ * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl)
+ */
+static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct ds1305   *ds1305 = dev_get_drvdata(dev);
+       struct spi_device *spi = ds1305->spi;
+       u8              addr;
+       int             status;
+       u8              buf[DS1305_ALM_LEN];
+
+       /* Refresh control register cache BEFORE reading ALM0 registers,
+        * since reading alarm registers acks any pending IRQ.  That
+        * makes returning "pending" status a bit of a lie, but that bit
+        * of EFI status is at best fragile anyway (given IRQ handlers).
+        */
+       addr = DS1305_CONTROL;
+       status = spi_write_then_read(spi, &addr, sizeof addr,
+                       ds1305->ctrl, sizeof ds1305->ctrl);
+       if (status < 0)
+               return status;
+
+       alm->enabled = !!(ds1305->ctrl[0] & DS1305_AEI0);
+       alm->pending = !!(ds1305->ctrl[1] & DS1305_AEI0);
+
+       /* get and check ALM0 registers */
+       addr = DS1305_ALM0(DS1305_SEC);
+       status = spi_write_then_read(spi, &addr, sizeof addr,
+                       buf, sizeof buf);
+       if (status < 0)
+               return status;
+
+       dev_vdbg(dev, "%s: %02x %02x %02x %02x\n",
+               "alm0 read", buf[DS1305_SEC], buf[DS1305_MIN],
+               buf[DS1305_HOUR], buf[DS1305_WDAY]);
+
+       if ((DS1305_ALM_DISABLE & buf[DS1305_SEC])
+                       || (DS1305_ALM_DISABLE & buf[DS1305_MIN])
+                       || (DS1305_ALM_DISABLE & buf[DS1305_HOUR]))
+               return -EIO;
+
+       /* Stuff these values into alm->time and let RTC framework code
+        * fill in the rest ... and also handle rollover to tomorrow when
+        * that's needed.
+        */
+       alm->time.tm_sec = BCD2BIN(buf[DS1305_SEC]);
+       alm->time.tm_min = BCD2BIN(buf[DS1305_MIN]);
+       alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]);
+       alm->time.tm_mday = -1;
+       alm->time.tm_mon = -1;
+       alm->time.tm_year = -1;
+       /* next three fields are unused by Linux */
+       alm->time.tm_wday = -1;
+       alm->time.tm_mday = -1;
+       alm->time.tm_isdst = -1;
+
+       return 0;
+}
+
+/*
+ * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl)
+ */
+static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct ds1305   *ds1305 = dev_get_drvdata(dev);
+       struct spi_device *spi = ds1305->spi;
+       unsigned long   now, later;
+       struct rtc_time tm;
+       int             status;
+       u8              buf[1 + DS1305_ALM_LEN];
+
+       /* convert desired alarm to time_t */
+       status = rtc_tm_to_time(&alm->time, &later);
+       if (status < 0)
+               return status;
+
+       /* Read current time as time_t */
+       status = ds1305_get_time(dev, &tm);
+       if (status < 0)
+               return status;
+       status = rtc_tm_to_time(&tm, &now);
+       if (status < 0)
+               return status;
+
+       /* make sure alarm fires within the next 24 hours */
+       if (later <= now)
+               return -EINVAL;
+       if ((later - now) > 24 * 60 * 60)
+               return -EDOM;
+
+       /* disable alarm if needed */
+       if (ds1305->ctrl[0] & DS1305_AEI0) {
+               ds1305->ctrl[0] &= ~DS1305_AEI0;
+
+               buf[0] = DS1305_WRITE | DS1305_CONTROL;
+               buf[1] = ds1305->ctrl[0];
+               status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0);
+               if (status < 0)
+                       return status;
+       }
+
+       /* write alarm */
+       buf[0] = DS1305_WRITE | DS1305_ALM0(DS1305_SEC);
+       buf[1 + DS1305_SEC] = BIN2BCD(alm->time.tm_sec);
+       buf[1 + DS1305_MIN] = BIN2BCD(alm->time.tm_min);
+       buf[1 + DS1305_HOUR] = hour2bcd(ds1305->hr12, alm->time.tm_hour);
+       buf[1 + DS1305_WDAY] = DS1305_ALM_DISABLE;
+
+       dev_dbg(dev, "%s: %02x %02x %02x %02x\n",
+               "alm0 write", buf[1 + DS1305_SEC], buf[1 + DS1305_MIN],
+               buf[1 + DS1305_HOUR], buf[1 + DS1305_WDAY]);
+
+       status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0);
+       if (status < 0)
+               return status;
+
+       /* enable alarm if requested */
+       if (alm->enabled) {
+               ds1305->ctrl[0] |= DS1305_AEI0;
+
+               buf[0] = DS1305_WRITE | DS1305_CONTROL;
+               buf[1] = ds1305->ctrl[0];
+               status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0);
+       }
+
+       return status;
+}
+
+#ifdef CONFIG_PROC_FS
+
+static int ds1305_proc(struct device *dev, struct seq_file *seq)
+{
+       struct ds1305   *ds1305 = dev_get_drvdata(dev);
+       char            *diodes = "no";
+       char            *resistors = "";
+
+       /* ctrl[2] is treated as read-only; no locking needed */
+       if ((ds1305->ctrl[2] & 0xf0) == DS1305_TRICKLE_MAGIC) {
+               switch (ds1305->ctrl[2] & 0x0c) {
+               case DS1305_TRICKLE_DS2:
+                       diodes = "2 diodes, ";
+                       break;
+               case DS1305_TRICKLE_DS1:
+                       diodes = "1 diode, ";
+                       break;
+               default:
+                       goto done;
+               }
+               switch (ds1305->ctrl[2] & 0x03) {
+               case DS1305_TRICKLE_2K:
+                       resistors = "2k Ohm";
+                       break;
+               case DS1305_TRICKLE_4K:
+                       resistors = "4k Ohm";
+                       break;
+               case DS1305_TRICKLE_8K:
+                       resistors = "8k Ohm";
+                       break;
+               default:
+                       diodes = "no";
+                       break;
+               }
+       }
+
+done:
+       return seq_printf(seq,
+                       "trickle_charge\t: %s%s\n",
+                       diodes, resistors);
+}
+
+#else
+#define ds1305_proc    NULL
+#endif
+
+static const struct rtc_class_ops ds1305_ops = {
+       .ioctl          = ds1305_ioctl,
+       .read_time      = ds1305_get_time,
+       .set_time       = ds1305_set_time,
+       .read_alarm     = ds1305_get_alarm,
+       .set_alarm      = ds1305_set_alarm,
+       .proc           = ds1305_proc,
+};
+
+static void ds1305_work(struct work_struct *work)
+{
+       struct ds1305   *ds1305 = container_of(work, struct ds1305, work);
+       struct mutex    *lock = &ds1305->rtc->ops_lock;
+       struct spi_device *spi = ds1305->spi;
+       u8              buf[3];
+       int             status;
+
+       /* lock to protect ds1305->ctrl */
+       mutex_lock(lock);
+
+       /* Disable the IRQ, and clear its status ... for now, we "know"
+        * that if more than one alarm is active, they're in sync.
+        * Note that reading ALM data registers also clears IRQ status.
+        */
+       ds1305->ctrl[0] &= ~(DS1305_AEI1 | DS1305_AEI0);
+       ds1305->ctrl[1] = 0;
+
+       buf[0] = DS1305_WRITE | DS1305_CONTROL;
+       buf[1] = ds1305->ctrl[0];
+       buf[2] = 0;
+
+       status = spi_write_then_read(spi, buf, sizeof buf,
+                       NULL, 0);
+       if (status < 0)
+               dev_dbg(&spi->dev, "clear irq --> %d\n", status);
+
+       mutex_unlock(lock);
+
+       if (!test_bit(FLAG_EXITING, &ds1305->flags))
+               enable_irq(spi->irq);
+
+       /* rtc_update_irq() requires an IRQ-disabled context */
+       local_irq_disable();
+       rtc_update_irq(ds1305->rtc, 1, RTC_AF | RTC_IRQF);
+       local_irq_enable();
+}
+
+/*
+ * This "real" IRQ handler hands off to a workqueue mostly to allow
+ * mutex locking for ds1305->ctrl ... unlike I2C, we could issue async
+ * I/O requests in IRQ context (to clear the IRQ status).
+ */
+static irqreturn_t ds1305_irq(int irq, void *p)
+{
+       struct ds1305           *ds1305 = p;
+
+       disable_irq(irq);
+       schedule_work(&ds1305->work);
+       return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Interface for NVRAM
+ */
+
+static void msg_init(struct spi_message *m, struct spi_transfer *x,
+               u8 *addr, size_t count, char *tx, char *rx)
+{
+       spi_message_init(m);
+       memset(x, 0, 2 * sizeof(*x));
+
+       x->tx_buf = addr;
+       x->len = 1;
+       spi_message_add_tail(x, m);
+
+       x++;
+
+       x->tx_buf = tx;
+       x->rx_buf = rx;
+       x->len = count;
+       spi_message_add_tail(x, m);
+}
+
+static ssize_t
+ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
+               char *buf, loff_t off, size_t count)
+{
+       struct spi_device       *spi;
+       u8                      addr;
+       struct spi_message      m;
+       struct spi_transfer     x[2];
+       int                     status;
+
+       spi = container_of(kobj, struct spi_device, dev.kobj);
+
+       if (unlikely(off >= DS1305_NVRAM_LEN))
+               return 0;
+       if (count >= DS1305_NVRAM_LEN)
+               count = DS1305_NVRAM_LEN;
+       if ((off + count) > DS1305_NVRAM_LEN)
+               count = DS1305_NVRAM_LEN - off;
+       if (unlikely(!count))
+               return count;
+
+       addr = DS1305_NVRAM + off;
+       msg_init(&m, x, &addr, count, NULL, buf);
+
+       status = spi_sync(spi, &m);
+       if (status < 0)
+               dev_err(&spi->dev, "nvram %s error %d\n", "read", status);
+       return (status < 0) ? status : count;
+}
+
+static ssize_t
+ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
+               char *buf, loff_t off, size_t count)
+{
+       struct spi_device       *spi;
+       u8                      addr;
+       struct spi_message      m;
+       struct spi_transfer     x[2];
+       int                     status;
+
+       spi = container_of(kobj, struct spi_device, dev.kobj);
+
+       if (unlikely(off >= DS1305_NVRAM_LEN))
+               return -EFBIG;
+       if (count >= DS1305_NVRAM_LEN)
+               count = DS1305_NVRAM_LEN;
+       if ((off + count) > DS1305_NVRAM_LEN)
+               count = DS1305_NVRAM_LEN - off;
+       if (unlikely(!count))
+               return count;
+
+       addr = (DS1305_WRITE | DS1305_NVRAM) + off;
+       msg_init(&m, x, &addr, count, buf, NULL);
+
+       status = spi_sync(spi, &m);
+       if (status < 0)
+               dev_err(&spi->dev, "nvram %s error %d\n", "write", status);
+       return (status < 0) ? status : count;
+}
+
+static struct bin_attribute nvram = {
+       .attr.name      = "nvram",
+       .attr.mode      = S_IRUGO | S_IWUSR,
+       .attr.owner     = THIS_MODULE,
+       .read           = ds1305_nvram_read,
+       .write          = ds1305_nvram_write,
+       .size           = DS1305_NVRAM_LEN,
+};
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Interface to SPI stack
+ */
+
+static int __devinit ds1305_probe(struct spi_device *spi)
+{
+       struct ds1305                   *ds1305;
+       struct rtc_device               *rtc;
+       int                             status;
+       u8                              addr, value;
+       struct ds1305_platform_data     *pdata = spi->dev.platform_data;
+       bool                            write_ctrl = false;
+
+       /* Sanity check board setup data.  This may be hooked up
+        * in 3wire mode, but we don't care.  Note that unless
+        * there's an inverter in place, this needs SPI_CS_HIGH!
+        */
+       if ((spi->bits_per_word && spi->bits_per_word != 8)
+                       || (spi->max_speed_hz > 2000000)
+                       || !(spi->mode & SPI_CPHA))
+               return -EINVAL;
+
+       /* set up driver data */
+       ds1305 = kzalloc(sizeof *ds1305, GFP_KERNEL);
+       if (!ds1305)
+               return -ENOMEM;
+       ds1305->spi = spi;
+       spi_set_drvdata(spi, ds1305);
+
+       /* read and cache control registers */
+       addr = DS1305_CONTROL;
+       status = spi_write_then_read(spi, &addr, sizeof addr,
+                       ds1305->ctrl, sizeof ds1305->ctrl);
+       if (status < 0) {
+               dev_dbg(&spi->dev, "can't %s, %d\n",
+                               "read", status);
+               goto fail0;
+       }
+
+       dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n",
+                       "read", ds1305->ctrl[0],
+                       ds1305->ctrl[1], ds1305->ctrl[2]);
+
+       /* Sanity check register values ... partially compensating for the
+        * fact that SPI has no device handshake.  A pullup on MISO would
+        * make these tests fail; but not all systems will have one.  If
+        * some register is neither 0x00 nor 0xff, a chip is likely there.
+        */
+       if ((ds1305->ctrl[0] & 0x38) != 0 || (ds1305->ctrl[1] & 0xfc) != 0) {
+               dev_dbg(&spi->dev, "RTC chip is not present\n");
+               status = -ENODEV;
+               goto fail0;
+       }
+       if (ds1305->ctrl[2] == 0)
+               dev_dbg(&spi->dev, "chip may not be present\n");
+
+       /* enable writes if needed ... if we were paranoid it would
+        * make sense to enable them only when absolutely necessary.
+        */
+       if (ds1305->ctrl[0] & DS1305_WP) {
+               u8              buf[2];
+
+               ds1305->ctrl[0] &= ~DS1305_WP;
+
+               buf[0] = DS1305_WRITE | DS1305_CONTROL;
+               buf[1] = ds1305->ctrl[0];
+               status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0);
+
+               dev_dbg(&spi->dev, "clear WP --> %d\n", status);
+               if (status < 0)
+                       goto fail0;
+       }
+
+       /* on DS1305, maybe start oscillator; like most low power
+        * oscillators, it may take a second to stabilize
+        */
+       if (ds1305->ctrl[0] & DS1305_nEOSC) {
+               ds1305->ctrl[0] &= ~DS1305_nEOSC;
+               write_ctrl = true;
+               dev_warn(&spi->dev, "SET TIME!\n");
+       }
+
+       /* ack any pending IRQs */
+       if (ds1305->ctrl[1]) {
+               ds1305->ctrl[1] = 0;
+               write_ctrl = true;
+       }
+
+       /* this may need one-time (re)init */
+       if (pdata) {
+               /* maybe enable trickle charge */
+               if (((ds1305->ctrl[2] & 0xf0) != DS1305_TRICKLE_MAGIC)) {
+                       ds1305->ctrl[2] = DS1305_TRICKLE_MAGIC
+                                               | pdata->trickle;
+                       write_ctrl = true;
+               }
+
+               /* on DS1306, configure 1 Hz signal */
+               if (pdata->is_ds1306) {
+                       if (pdata->en_1hz) {
+                               if (!(ds1305->ctrl[0] & DS1306_1HZ)) {
+                                       ds1305->ctrl[0] |= DS1306_1HZ;
+                                       write_ctrl = true;
+                               }
+                       } else {
+                               if (ds1305->ctrl[0] & DS1306_1HZ) {
+                                       ds1305->ctrl[0] &= ~DS1306_1HZ;
+                                       write_ctrl = true;
+                               }
+                       }
+               }
+       }
+
+       if (write_ctrl) {
+               u8              buf[4];
+
+               buf[0] = DS1305_WRITE | DS1305_CONTROL;
+               buf[1] = ds1305->ctrl[0];
+               buf[2] = ds1305->ctrl[1];
+               buf[3] = ds1305->ctrl[2];
+               status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0);
+               if (status < 0) {
+                       dev_dbg(&spi->dev, "can't %s, %d\n",
+                                       "write", status);
+                       goto fail0;
+               }
+
+               dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n",
+                               "write", ds1305->ctrl[0],
+                               ds1305->ctrl[1], ds1305->ctrl[2]);
+       }
+
+       /* see if non-Linux software set up AM/PM mode */
+       addr = DS1305_HOUR;
+       status = spi_write_then_read(spi, &addr, sizeof addr,
+                               &value, sizeof value);
+       if (status < 0) {
+               dev_dbg(&spi->dev, "read HOUR --> %d\n", status);
+               goto fail0;
+       }
+
+       ds1305->hr12 = (DS1305_HR_12 & value) != 0;
+       if (ds1305->hr12)
+               dev_dbg(&spi->dev, "AM/PM\n");
+
+       /* register RTC ... from here on, ds1305->ctrl needs locking */
+       rtc = rtc_device_register("ds1305", &spi->dev,
+                       &ds1305_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               status = PTR_ERR(rtc);
+               dev_dbg(&spi->dev, "register rtc --> %d\n", status);
+               goto fail0;
+       }
+       ds1305->rtc = rtc;
+
+       /* Maybe set up alarm IRQ; be ready to handle it triggering right
+        * away.  NOTE that we don't share this.  The signal is active low,
+        * and we can't ack it before a SPI message delay.  We temporarily
+        * disable the IRQ until it's acked, which lets us work with more
+        * IRQ trigger modes (not all IRQ controllers can do falling edge).
+        */
+       if (spi->irq) {
+               INIT_WORK(&ds1305->work, ds1305_work);
+               status = request_irq(spi->irq, ds1305_irq,
+                               0, dev_name(&rtc->dev), ds1305);
+               if (status < 0) {
+                       dev_dbg(&spi->dev, "request_irq %d --> %d\n",
+                                       spi->irq, status);
+                       goto fail1;
+               }
+       }
+
+       /* export NVRAM */
+       status = sysfs_create_bin_file(&spi->dev.kobj, &nvram);
+       if (status < 0) {
+               dev_dbg(&spi->dev, "register nvram --> %d\n", status);
+               goto fail2;
+       }
+
+       return 0;
+
+fail2:
+       free_irq(spi->irq, ds1305);
+fail1:
+       rtc_device_unregister(rtc);
+fail0:
+       kfree(ds1305);
+       return status;
+}
+
+static int __devexit ds1305_remove(struct spi_device *spi)
+{
+       struct ds1305   *ds1305 = spi_get_drvdata(spi);
+
+       sysfs_remove_bin_file(&spi->dev.kobj, &nvram);
+
+       /* carefully shut down irq and workqueue, if present */
+       if (spi->irq) {
+               set_bit(FLAG_EXITING, &ds1305->flags);
+               free_irq(spi->irq, ds1305);
+               flush_scheduled_work();
+       }
+
+       rtc_device_unregister(ds1305->rtc);
+       spi_set_drvdata(spi, NULL);
+       kfree(ds1305);
+       return 0;
+}
+
+static struct spi_driver ds1305_driver = {
+       .driver.name    = "rtc-ds1305",
+       .driver.owner   = THIS_MODULE,
+       .probe          = ds1305_probe,
+       .remove         = __devexit_p(ds1305_remove),
+       /* REVISIT add suspend/resume */
+};
+
+static int __init ds1305_init(void)
+{
+       return spi_register_driver(&ds1305_driver);
+}
+module_init(ds1305_init);
+
+static void __exit ds1305_exit(void)
+{
+       spi_unregister_driver(&ds1305_driver);
+}
+module_exit(ds1305_exit);
+
+MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips");
+MODULE_LICENSE("GPL");
index 0a19c06019be6c32ea71ccc3849cd7d108040385..24bc1689fc74c095d88641cb7c78755e5ee0b9f8 100644 (file)
  *
  */
 
-#include <linux/module.h>
+#include <linux/bcd.h>
+#include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/string.h>
-#include <linux/i2c.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
 #ifdef CONFIG_RTC_DRV_M41T80_WDT
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/reboot.h>
+#include <linux/watchdog.h>
 #endif
 
 #define M41T80_REG_SSEC        0
@@ -631,14 +631,12 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                if (rv & WDIOS_DISABLECARD) {
-                       printk(KERN_INFO
-                              "rtc-m41t80: disable watchdog\n");
+                       pr_info("rtc-m41t80: disable watchdog\n");
                        wdt_disable();
                }
 
                if (rv & WDIOS_ENABLECARD) {
-                       printk(KERN_INFO
-                              "rtc-m41t80: enable watchdog\n");
+                       pr_info("rtc-m41t80: enable watchdog\n");
                        wdt_ping();
                }
 
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c
new file mode 100644 (file)
index 0000000..9b19499
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Driver for ST M41T94 SPI RTC
+ *
+ * Copyright (C) 2008 Kim B. Heino
+ *
+ * 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/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+
+#define M41T94_REG_SECONDS     0x01
+#define M41T94_REG_MINUTES     0x02
+#define M41T94_REG_HOURS       0x03
+#define M41T94_REG_WDAY                0x04
+#define M41T94_REG_DAY         0x05
+#define M41T94_REG_MONTH       0x06
+#define M41T94_REG_YEAR                0x07
+#define M41T94_REG_HT          0x0c
+
+#define M41T94_BIT_HALT                0x40
+#define M41T94_BIT_STOP                0x80
+#define M41T94_BIT_CB          0x40
+#define M41T94_BIT_CEB         0x80
+
+static int m41t94_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       u8 buf[8]; /* write cmd + 7 registers */
+
+       dev_dbg(dev, "%s secs=%d, mins=%d, "
+               "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+               "write", tm->tm_sec, tm->tm_min,
+               tm->tm_hour, tm->tm_mday,
+               tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+       buf[0] = 0x80 | M41T94_REG_SECONDS; /* write time + date */
+       buf[M41T94_REG_SECONDS] = BIN2BCD(tm->tm_sec);
+       buf[M41T94_REG_MINUTES] = BIN2BCD(tm->tm_min);
+       buf[M41T94_REG_HOURS]   = BIN2BCD(tm->tm_hour);
+       buf[M41T94_REG_WDAY]    = BIN2BCD(tm->tm_wday + 1);
+       buf[M41T94_REG_DAY]     = BIN2BCD(tm->tm_mday);
+       buf[M41T94_REG_MONTH]   = BIN2BCD(tm->tm_mon + 1);
+
+       buf[M41T94_REG_HOURS] |= M41T94_BIT_CEB;
+       if (tm->tm_year >= 100)
+               buf[M41T94_REG_HOURS] |= M41T94_BIT_CB;
+       buf[M41T94_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+
+       return spi_write(spi, buf, 8);
+}
+
+static int m41t94_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       u8 buf[2];
+       int ret, hour;
+
+       /* clear halt update bit */
+       ret = spi_w8r8(spi, M41T94_REG_HT);
+       if (ret < 0)
+               return ret;
+       if (ret & M41T94_BIT_HALT) {
+               buf[0] = 0x80 | M41T94_REG_HT;
+               buf[1] = ret & ~M41T94_BIT_HALT;
+               spi_write(spi, buf, 2);
+       }
+
+       /* clear stop bit */
+       ret = spi_w8r8(spi, M41T94_REG_SECONDS);
+       if (ret < 0)
+               return ret;
+       if (ret & M41T94_BIT_STOP) {
+               buf[0] = 0x80 | M41T94_REG_SECONDS;
+               buf[1] = ret & ~M41T94_BIT_STOP;
+               spi_write(spi, buf, 2);
+       }
+
+       tm->tm_sec  = BCD2BIN(spi_w8r8(spi, M41T94_REG_SECONDS));
+       tm->tm_min  = BCD2BIN(spi_w8r8(spi, M41T94_REG_MINUTES));
+       hour = spi_w8r8(spi, M41T94_REG_HOURS);
+       tm->tm_hour = BCD2BIN(hour & 0x3f);
+       tm->tm_wday = BCD2BIN(spi_w8r8(spi, M41T94_REG_WDAY)) - 1;
+       tm->tm_mday = BCD2BIN(spi_w8r8(spi, M41T94_REG_DAY));
+       tm->tm_mon  = BCD2BIN(spi_w8r8(spi, M41T94_REG_MONTH)) - 1;
+       tm->tm_year = BCD2BIN(spi_w8r8(spi, M41T94_REG_YEAR));
+       if ((hour & M41T94_BIT_CB) || !(hour & M41T94_BIT_CEB))
+               tm->tm_year += 100;
+
+       dev_dbg(dev, "%s secs=%d, mins=%d, "
+               "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+               "read", tm->tm_sec, tm->tm_min,
+               tm->tm_hour, tm->tm_mday,
+               tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+       /* initial clock setting can be undefined */
+       return rtc_valid_tm(tm);
+}
+
+static const struct rtc_class_ops m41t94_rtc_ops = {
+       .read_time      = m41t94_read_time,
+       .set_time       = m41t94_set_time,
+};
+
+static struct spi_driver m41t94_driver;
+
+static int __devinit m41t94_probe(struct spi_device *spi)
+{
+       struct rtc_device *rtc;
+       int res;
+
+       spi->bits_per_word = 8;
+       spi_setup(spi);
+
+       res = spi_w8r8(spi, M41T94_REG_SECONDS);
+       if (res < 0) {
+               dev_err(&spi->dev, "not found.\n");
+               return res;
+       }
+
+       rtc = rtc_device_register(m41t94_driver.driver.name,
+               &spi->dev, &m41t94_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
+
+       dev_set_drvdata(&spi->dev, rtc);
+
+       return 0;
+}
+
+static int __devexit m41t94_remove(struct spi_device *spi)
+{
+       struct rtc_device *rtc = platform_get_drvdata(spi);
+
+       if (rtc)
+               rtc_device_unregister(rtc);
+
+       return 0;
+}
+
+static struct spi_driver m41t94_driver = {
+       .driver = {
+               .name   = "rtc-m41t94",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = m41t94_probe,
+       .remove = __devexit_p(m41t94_remove),
+};
+
+static __init int m41t94_init(void)
+{
+       return spi_register_driver(&m41t94_driver);
+}
+
+module_init(m41t94_init);
+
+static __exit void m41t94_exit(void)
+{
+       spi_unregister_driver(&m41t94_driver);
+}
+
+module_exit(m41t94_exit);
+
+MODULE_AUTHOR("Kim B. Heino <Kim.Heino@bluegiga.com>");
+MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC");
+MODULE_LICENSE("GPL");
index eb23d8423f42dc15f6e1d226766bff6c40989c5b..8876605d4d4bbc746a56da23169e4c190cbb4e6c 100644 (file)
 #define rtc_write(val, addr)   omap_writeb(val, OMAP_RTC_BASE + (addr))
 
 
-/* platform_bus isn't hotpluggable, so for static linkage it'd be safe
- * to get rid of probe() and remove() code ... too bad the driver struct
- * remembers probe(), that's about 25% of the runtime footprint!!
- */
-#ifndef        MODULE
-#undef __devexit
-#undef __devexit_p
-#define        __devexit       __exit
-#define        __devexit_p     __exit_p
-#endif
-
-
 /* we rely on the rtc framework to handle locking (rtc->ops_lock),
  * so the only other requirement is that register accesses which
  * require BUSY to be clear are made with IRQs locally disabled
@@ -324,7 +312,7 @@ static struct rtc_class_ops omap_rtc_ops = {
 static int omap_rtc_alarm;
 static int omap_rtc_timer;
 
-static int __devinit omap_rtc_probe(struct platform_device *pdev)
+static int __init omap_rtc_probe(struct platform_device *pdev)
 {
        struct resource         *res, *mem;
        struct rtc_device       *rtc;
@@ -440,7 +428,7 @@ fail:
        return -EIO;
 }
 
-static int __devexit omap_rtc_remove(struct platform_device *pdev)
+static int __exit omap_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device       *rtc = platform_get_drvdata(pdev);;
 
@@ -498,8 +486,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
 
 MODULE_ALIAS("platform:omap_rtc");
 static struct platform_driver omap_rtc_driver = {
-       .probe          = omap_rtc_probe,
-       .remove         = __devexit_p(omap_rtc_remove),
+       .remove         = __exit_p(omap_rtc_remove),
        .suspend        = omap_rtc_suspend,
        .resume         = omap_rtc_resume,
        .shutdown       = omap_rtc_shutdown,
@@ -511,7 +498,7 @@ static struct platform_driver omap_rtc_driver = {
 
 static int __init rtc_init(void)
 {
-       return platform_driver_register(&omap_rtc_driver);
+       return platform_driver_probe(&omap_rtc_driver, omap_rtc_probe);
 }
 module_init(rtc_init);
 
index 3d09d8f0b1f0244220bcd1562d109664fa87f266..d388c662bf4b6b630909187a9fbc5370e3c97c7f 100644 (file)
@@ -2,6 +2,7 @@
  *  drivers/rtc/rtc-pcf8583.c
  *
  *  Copyright (C) 2000 Russell King
+ *  Copyright (C) 2008 Wolfram Sang & Juergen Beisert, Pengutronix
  *
  * 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
@@ -14,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
-#include <linux/string.h>
 #include <linux/rtc.h>
 #include <linux/init.h>
 #include <linux/errno.h>
@@ -27,7 +27,6 @@ struct rtc_mem {
 };
 
 struct pcf8583 {
-       struct i2c_client client;
        struct rtc_device *rtc;
        unsigned char ctrl;
 };
@@ -40,10 +39,6 @@ struct pcf8583 {
 #define CTRL_ALARM     0x02
 #define CTRL_TIMER     0x01
 
-static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END };
-
-/* Module parameters */
-I2C_CLIENT_INSMOD;
 
 static struct i2c_driver pcf8583_driver;
 
@@ -269,106 +264,60 @@ static const struct rtc_class_ops pcf8583_rtc_ops = {
        .set_time       = pcf8583_rtc_set_time,
 };
 
-static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind);
-
-static int pcf8583_attach(struct i2c_adapter *adap)
-{
-       return i2c_probe(adap, &addr_data, pcf8583_probe);
-}
-
-static int pcf8583_detach(struct i2c_client *client)
-{
-       int err;
-       struct pcf8583 *pcf = i2c_get_clientdata(client);
-       struct rtc_device *rtc = pcf->rtc;
-
-       if (rtc)
-               rtc_device_unregister(rtc);
-
-       if ((err = i2c_detach_client(client)))
-               return err;
-
-       kfree(pcf);
-       return 0;
-}
-
-static struct i2c_driver pcf8583_driver = {
-       .driver = {
-               .name   = "pcf8583",
-       },
-       .id             = I2C_DRIVERID_PCF8583,
-       .attach_adapter = pcf8583_attach,
-       .detach_client  = pcf8583_detach,
-};
-
-static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind)
+static int pcf8583_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
 {
-       struct pcf8583 *pcf;
-       struct i2c_client *client;
-       struct rtc_device *rtc;
-       unsigned char buf[1], ad[1] = { 0 };
+       struct pcf8583 *pcf8583;
        int err;
-       struct i2c_msg msgs[2] = {
-               {
-                       .addr = addr,
-                       .flags = 0,
-                       .len = 1,
-                       .buf = ad,
-               }, {
-                       .addr = addr,
-                       .flags = I2C_M_RD,
-                       .len = 1,
-                       .buf = buf,
-               }
-       };
 
-       if (!i2c_check_functionality(adap, I2C_FUNC_I2C))
-               return 0;
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -ENODEV;
 
-       pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
-       if (!pcf)
+       pcf8583 = kzalloc(sizeof(struct pcf8583), GFP_KERNEL);
+       if (!pcf8583)
                return -ENOMEM;
 
-       client = &pcf->client;
+       pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name,
+                       &client->dev, &pcf8583_rtc_ops, THIS_MODULE);
 
-       client->addr            = addr;
-       client->adapter = adap;
-       client->driver  = &pcf8583_driver;
-
-       strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE);
-
-       if (i2c_transfer(client->adapter, msgs, 2) != 2) {
-               err = -EIO;
+       if (IS_ERR(pcf8583->rtc)) {
+               err = PTR_ERR(pcf8583->rtc);
                goto exit_kfree;
        }
 
-       err = i2c_attach_client(client);
-
-       if (err)
-               goto exit_kfree;
-
-       rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev,
-                                 &pcf8583_rtc_ops, THIS_MODULE);
+       i2c_set_clientdata(client, pcf8583);
+       return 0;
 
-       if (IS_ERR(rtc)) {
-               err = PTR_ERR(rtc);
-               goto exit_detach;
-       }
+exit_kfree:
+       kfree(pcf8583);
+       return err;
+}
 
-       pcf->rtc = rtc;
-       i2c_set_clientdata(client, pcf);
-       set_ctrl(client, buf[0]);
+static int __devexit pcf8583_remove(struct i2c_client *client)
+{
+       struct pcf8583 *pcf8583 = i2c_get_clientdata(client);
 
+       if (pcf8583->rtc)
+               rtc_device_unregister(pcf8583->rtc);
+       kfree(pcf8583);
        return 0;
+}
 
-exit_detach:
-       i2c_detach_client(client);
-
-exit_kfree:
-       kfree(pcf);
+static const struct i2c_device_id pcf8583_id[] = {
+       { "pcf8583", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf8583_id);
 
-       return err;
-}
+static struct i2c_driver pcf8583_driver = {
+       .driver = {
+               .name   = "pcf8583",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = pcf8583_probe,
+       .remove         = __devexit_p(pcf8583_remove),
+       .id_table       = pcf8583_id,
+};
 
 static __init int pcf8583_init(void)
 {
index fed86e507fdfb87aa17e610d1758317731fc1990..54b1ebb0150249e926fe637894a775c2bca3485e 100644 (file)
@@ -36,10 +36,8 @@ static struct resource *s3c_rtc_mem;
 static void __iomem *s3c_rtc_base;
 static int s3c_rtc_alarmno = NO_IRQ;
 static int s3c_rtc_tickno  = NO_IRQ;
-static int s3c_rtc_freq    = 1;
 
 static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
-static unsigned int tick_count;
 
 /* IRQ Handlers */
 
@@ -55,7 +53,7 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
 {
        struct rtc_device *rdev = id;
 
-       rtc_update_irq(rdev, tick_count++, RTC_PF | RTC_IRQF);
+       rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
        return IRQ_HANDLED;
 }
 
@@ -74,35 +72,37 @@ static void s3c_rtc_setaie(int to)
        writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
 }
 
-static void s3c_rtc_setpie(int to)
+static int s3c_rtc_setpie(struct device *dev, int enabled)
 {
        unsigned int tmp;
 
-       pr_debug("%s: pie=%d\n", __func__, to);
+       pr_debug("%s: pie=%d\n", __func__, enabled);
 
        spin_lock_irq(&s3c_rtc_pie_lock);
        tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
 
-       if (to)
+       if (enabled)
                tmp |= S3C2410_TICNT_ENABLE;
 
        writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
        spin_unlock_irq(&s3c_rtc_pie_lock);
+
+       return 0;
 }
 
-static void s3c_rtc_setfreq(int freq)
+static int s3c_rtc_setfreq(struct device *dev, int freq)
 {
        unsigned int tmp;
 
        spin_lock_irq(&s3c_rtc_pie_lock);
-       tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
-
-       s3c_rtc_freq = freq;
 
+       tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
        tmp |= (128 / freq)-1;
 
        writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
        spin_unlock_irq(&s3c_rtc_pie_lock);
+
+       return 0;
 }
 
 /* Time read/write */
@@ -267,12 +267,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        writeb(alrm_en, base + S3C2410_RTCALM);
 
-       if (0) {
-               alrm_en = readb(base + S3C2410_RTCALM);
-               alrm_en &= ~S3C2410_RTCALM_ALMEN;
-               writeb(alrm_en, base + S3C2410_RTCALM);
-               disable_irq_wake(s3c_rtc_alarmno);
-       }
+       s3c_rtc_setaie(alrm->enabled);
 
        if (alrm->enabled)
                enable_irq_wake(s3c_rtc_alarmno);
@@ -282,59 +277,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
        return 0;
 }
 
-static int s3c_rtc_ioctl(struct device *dev,
-                        unsigned int cmd, unsigned long arg)
-{
-       unsigned int ret = -ENOIOCTLCMD;
-
-       switch (cmd) {
-       case RTC_AIE_OFF:
-       case RTC_AIE_ON:
-               s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0);
-               ret = 0;
-               break;
-
-       case RTC_PIE_OFF:
-       case RTC_PIE_ON:
-               tick_count = 0;
-               s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0);
-               ret = 0;
-               break;
-
-       case RTC_IRQP_READ:
-               ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg);
-               break;
-
-       case RTC_IRQP_SET:
-               if (!is_power_of_2(arg)) {
-                       ret = -EINVAL;
-                       goto exit;
-               }
-
-               pr_debug("s3c2410_rtc: setting frequency %ld\n", arg);
-
-               s3c_rtc_setfreq(arg);
-               ret = 0;
-               break;
-
-       case RTC_UIE_ON:
-       case RTC_UIE_OFF:
-               ret = -EINVAL;
-       }
-
- exit:
-       return ret;
-}
-
 static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
 {
        unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
 
        seq_printf(seq, "periodic_IRQ\t: %s\n",
                     (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
-
-       seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq);
-
        return 0;
 }
 
@@ -374,7 +322,7 @@ static void s3c_rtc_release(struct device *dev)
 
        /* do not clear AIE here, it may be needed for wake */
 
-       s3c_rtc_setpie(0);
+       s3c_rtc_setpie(dev, 0);
        free_irq(s3c_rtc_alarmno, rtc_dev);
        free_irq(s3c_rtc_tickno, rtc_dev);
 }
@@ -382,11 +330,12 @@ static void s3c_rtc_release(struct device *dev)
 static const struct rtc_class_ops s3c_rtcops = {
        .open           = s3c_rtc_open,
        .release        = s3c_rtc_release,
-       .ioctl          = s3c_rtc_ioctl,
        .read_time      = s3c_rtc_gettime,
        .set_time       = s3c_rtc_settime,
        .read_alarm     = s3c_rtc_getalarm,
        .set_alarm      = s3c_rtc_setalarm,
+       .irq_set_freq   = s3c_rtc_setfreq,
+       .irq_set_state  = s3c_rtc_setpie,
        .proc           = s3c_rtc_proc,
 };
 
@@ -430,14 +379,14 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
        }
 }
 
-static int s3c_rtc_remove(struct platform_device *dev)
+static int __devexit s3c_rtc_remove(struct platform_device *dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(dev);
 
        platform_set_drvdata(dev, NULL);
        rtc_device_unregister(rtc);
 
-       s3c_rtc_setpie(0);
+       s3c_rtc_setpie(&dev->dev, 0);
        s3c_rtc_setaie(0);
 
        iounmap(s3c_rtc_base);
@@ -447,7 +396,7 @@ static int s3c_rtc_remove(struct platform_device *dev)
        return 0;
 }
 
-static int s3c_rtc_probe(struct platform_device *pdev)
+static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        struct resource *res;
@@ -504,7 +453,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)
        pr_debug("s3c2410_rtc: RTCCON=%02x\n",
                 readb(s3c_rtc_base + S3C2410_RTCCON));
 
-       s3c_rtc_setfreq(s3c_rtc_freq);
+       s3c_rtc_setfreq(&pdev->dev, 1);
 
        /* register RTC and exit */
 
@@ -560,7 +509,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
 
 static struct platform_driver s3c2410_rtcdrv = {
        .probe          = s3c_rtc_probe,
-       .remove         = s3c_rtc_remove,
+       .remove         = __devexit_p(s3c_rtc_remove),
        .suspend        = s3c_rtc_suspend,
        .resume         = s3c_rtc_resume,
        .driver         = {
index be9c70d0b193d2210ff3611728e1cafae133a961..884b635f028b792ee9b9afef8954345b4375e24a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for NEC VR4100 series Real Time Clock unit.
  *
- *  Copyright (C) 2003-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  *
  *  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
@@ -34,7 +34,7 @@
 
 MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
 MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 
 /* RTC 1 registers */
 #define ETIMELREG              0x00
@@ -82,7 +82,6 @@ static unsigned long epoch = 1970;    /* Jan 1 1970 00:00:00 */
 
 static DEFINE_SPINLOCK(rtc_lock);
 static char rtc_name[] = "RTC";
-static unsigned long periodic_frequency;
 static unsigned long periodic_count;
 static unsigned int alarm_enabled;
 static int aie_irq = -1;
@@ -207,10 +206,37 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
        return 0;
 }
 
-static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq)
 {
        unsigned long count;
 
+       count = RTC_FREQUENCY;
+       do_div(count, freq);
+
+       periodic_count = count;
+
+       spin_lock_irq(&rtc_lock);
+
+       rtc1_write(RTCL1LREG, count);
+       rtc1_write(RTCL1HREG, count >> 16);
+
+       spin_unlock_irq(&rtc_lock);
+
+       return 0;
+}
+
+static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled)
+{
+       if (enabled)
+               enable_irq(pie_irq);
+       else
+               disable_irq(pie_irq);
+
+       return 0;
+}
+
+static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
        switch (cmd) {
        case RTC_AIE_ON:
                spin_lock_irq(&rtc_lock);
@@ -230,33 +256,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
                        alarm_enabled = 0;
                }
 
-               spin_unlock_irq(&rtc_lock);
-               break;
-       case RTC_PIE_ON:
-               enable_irq(pie_irq);
-               break;
-       case RTC_PIE_OFF:
-               disable_irq(pie_irq);
-               break;
-       case RTC_IRQP_READ:
-               return put_user(periodic_frequency, (unsigned long __user *)arg);
-               break;
-       case RTC_IRQP_SET:
-               if (arg > MAX_PERIODIC_RATE)
-                       return -EINVAL;
-
-               periodic_frequency = arg;
-
-               count = RTC_FREQUENCY;
-               do_div(count, arg);
-
-               periodic_count = count;
-
-               spin_lock_irq(&rtc_lock);
-
-               rtc1_write(RTCL1LREG, count);
-               rtc1_write(RTCL1HREG, count >> 16);
-
                spin_unlock_irq(&rtc_lock);
                break;
        case RTC_EPOCH_READ:
@@ -309,6 +308,8 @@ static const struct rtc_class_ops vr41xx_rtc_ops = {
        .set_time       = vr41xx_rtc_set_time,
        .read_alarm     = vr41xx_rtc_read_alarm,
        .set_alarm      = vr41xx_rtc_set_alarm,
+       .irq_set_freq   = vr41xx_rtc_irq_set_freq,
+       .irq_set_state  = vr41xx_rtc_irq_set_state,
 };
 
 static int __devinit rtc_probe(struct platform_device *pdev)
@@ -346,6 +347,8 @@ static int __devinit rtc_probe(struct platform_device *pdev)
                goto err_iounmap_all;
        }
 
+       rtc->max_user_freq = MAX_PERIODIC_RATE;
+
        spin_lock_irq(&rtc_lock);
 
        rtc1_write(ECMPLREG, 0);
index 4a5ec39f9ca60a4dc0beb227703c0fedc3777535..0815690ac1e03cd8b7fb003e7c9fabb38804647c 100644 (file)
@@ -6,4 +6,4 @@
 # it under the terms of the GNU General Public License (version 2 only)
 # as published by the Free Software Foundation.
 
-obj-$(CONFIG_VIRTIO) += kvm_virtio.o
+obj-$(CONFIG_S390_GUEST) += kvm_virtio.o
index 5ab34340919be3a417caf1ad5bfd50ff91f1054d..79954bd6bfa5a02b963e6c2868c9c5ad22bed5af 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/virtio.h>
 #include <linux/virtio_config.h>
+#include <linux/virtio_console.h>
 #include <linux/interrupt.h>
 #include <linux/virtio_ring.h>
 #include <linux/pfn.h>
@@ -87,16 +88,20 @@ static u32 kvm_get_features(struct virtio_device *vdev)
        return features;
 }
 
-static void kvm_set_features(struct virtio_device *vdev, u32 features)
+static void kvm_finalize_features(struct virtio_device *vdev)
 {
-       unsigned int i;
+       unsigned int i, bits;
        struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
        /* Second half of bitmap is features we accept. */
        u8 *out_features = kvm_vq_features(desc) + desc->feature_len;
 
+       /* Give virtio_ring a chance to accept features. */
+       vring_transport_features(vdev);
+
        memset(out_features, 0, desc->feature_len);
-       for (i = 0; i < min(desc->feature_len * 8, 32); i++) {
-               if (features & (1 << i))
+       bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8;
+       for (i = 0; i < bits; i++) {
+               if (test_bit(i, vdev->features))
                        out_features[i / 8] |= (1 << (i % 8));
        }
 }
@@ -222,7 +227,7 @@ static void kvm_del_vq(struct virtqueue *vq)
  */
 static struct virtio_config_ops kvm_vq_configspace_ops = {
        .get_features = kvm_get_features,
-       .set_features = kvm_set_features,
+       .finalize_features = kvm_finalize_features,
        .get = kvm_get,
        .set = kvm_set,
        .get_status = kvm_get_status,
@@ -333,6 +338,25 @@ static int __init kvm_devices_init(void)
        return 0;
 }
 
+/* code for early console output with virtio_console */
+static __init int early_put_chars(u32 vtermno, const char *buf, int count)
+{
+       char scratch[17];
+       unsigned int len = count;
+
+       if (len > sizeof(scratch) - 1)
+               len = sizeof(scratch) - 1;
+       scratch[len] = '\0';
+       memcpy(scratch, buf, len);
+       kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, __pa(scratch));
+       return len;
+}
+
+void s390_virtio_console_init(void)
+{
+       virtio_cons_early_init(early_put_chars);
+}
+
 /*
  * We do this after core stuff, but before the drivers.
  */
index c3ad89e302bd1ae6695e0e377faf21b4a3fa4008..cebb25e36e8238c8217d7db0204a6e8ccd221ca5 100644 (file)
@@ -3321,7 +3321,7 @@ int qeth_change_mtu(struct net_device *dev, int new_mtu)
        struct qeth_card *card;
        char dbf_text[15];
 
-       card = netdev_priv(dev);
+       card = dev->ml_priv;
 
        QETH_DBF_TEXT(TRACE, 4, "chgmtu");
        sprintf(dbf_text, "%8x", new_mtu);
@@ -3343,7 +3343,7 @@ struct net_device_stats *qeth_get_stats(struct net_device *dev)
 {
        struct qeth_card *card;
 
-       card = netdev_priv(dev);
+       card = dev->ml_priv;
 
        QETH_DBF_TEXT(TRACE, 5, "getstat");
 
@@ -3395,7 +3395,7 @@ void qeth_tx_timeout(struct net_device *dev)
 {
        struct qeth_card *card;
 
-       card = netdev_priv(dev);
+       card = dev->ml_priv;
        card->stats.tx_errors++;
        qeth_schedule_recovery(card);
 }
@@ -3403,7 +3403,7 @@ EXPORT_SYMBOL_GPL(qeth_tx_timeout);
 
 int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        int rc = 0;
 
        switch (regnum) {
@@ -4253,7 +4253,7 @@ EXPORT_SYMBOL_GPL(qeth_core_get_stats_count);
 void qeth_core_get_ethtool_stats(struct net_device *dev,
                struct ethtool_stats *stats, u64 *data)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        data[0] = card->stats.rx_packets -
                                card->perf_stats.initial_rx_packets;
        data[1] = card->perf_stats.bufs_rec;
@@ -4313,7 +4313,7 @@ EXPORT_SYMBOL_GPL(qeth_core_get_strings);
 void qeth_core_get_drvinfo(struct net_device *dev,
                struct ethtool_drvinfo *info)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        if (card->options.layer2)
                strcpy(info->driver, "qeth_l2");
        else
@@ -4331,7 +4331,7 @@ EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
 int qeth_core_ethtool_get_settings(struct net_device *netdev,
                                        struct ethtool_cmd *ecmd)
 {
-       struct qeth_card *card = netdev_priv(netdev);
+       struct qeth_card *card = netdev->ml_priv;
        enum qeth_link_types link_type;
 
        if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
index 3fbc3bdec0c5cfada6edccd973072f81ee2b97f7..a8b069cd9a4c63efb2197e24ba469790692bcdce 100644 (file)
@@ -35,7 +35,7 @@ static int qeth_l2_recover(void *);
 
 static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        struct mii_ioctl_data *mii_data;
        int rc = 0;
 
@@ -317,7 +317,7 @@ static void qeth_l2_process_vlans(struct qeth_card *card, int clear)
 
 static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        struct qeth_vlan_vid *id;
 
        QETH_DBF_TEXT_(TRACE, 4, "aid:%d", vid);
@@ -334,7 +334,7 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 static void qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
        struct qeth_vlan_vid *id, *tmpid = NULL;
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
 
        QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid);
        spin_lock_bh(&card->vlanlock);
@@ -566,7 +566,7 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
 static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
 {
        struct sockaddr *addr = p;
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        int rc = 0;
 
        QETH_DBF_TEXT(TRACE, 3, "setmac");
@@ -590,7 +590,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
 
 static void qeth_l2_set_multicast_list(struct net_device *dev)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        struct dev_mc_list *dm;
 
        if (card->info.type == QETH_CARD_TYPE_OSN)
@@ -612,7 +612,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        int rc;
        struct qeth_hdr *hdr = NULL;
        int elements = 0;
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        struct sk_buff *new_skb = skb;
        int ipv = qeth_get_ip_version(skb);
        int cast_type = qeth_get_cast_type(card, skb);
@@ -767,7 +767,7 @@ static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
 
 static int qeth_l2_open(struct net_device *dev)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
 
        QETH_DBF_TEXT(TRACE, 4, "qethopen");
        if (card->state != CARD_STATE_SOFTSETUP)
@@ -791,7 +791,7 @@ static int qeth_l2_open(struct net_device *dev)
 
 static int qeth_l2_stop(struct net_device *dev)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
 
        QETH_DBF_TEXT(TRACE, 4, "qethstop");
        netif_tx_disable(dev);
@@ -838,7 +838,7 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
 
 static int qeth_l2_ethtool_set_tso(struct net_device *dev, u32 data)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
 
        if (data) {
                if (card->options.large_send == QETH_LARGE_SEND_NO) {
@@ -894,7 +894,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
        if (!card->dev)
                return -ENODEV;
 
-       card->dev->priv = card;
+       card->dev->ml_priv = card;
        card->dev->tx_timeout = &qeth_tx_timeout;
        card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
        card->dev->open = qeth_l2_open;
@@ -1178,7 +1178,7 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
        QETH_DBF_TEXT(TRACE, 2, "osnsdmc");
        if (!dev)
                return -ENODEV;
-       card = netdev_priv(dev);
+       card = dev->ml_priv;
        if (!card)
                return -ENODEV;
        if ((card->state != CARD_STATE_UP) &&
@@ -1201,7 +1201,7 @@ int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
        *dev = qeth_l2_netdev_by_devno(read_dev_no);
        if (*dev == NULL)
                return -ENODEV;
-       card = netdev_priv(*dev);
+       card = (*dev)->ml_priv;
        if (!card)
                return -ENODEV;
        if ((assist_cb == NULL) || (data_cb == NULL))
@@ -1219,7 +1219,7 @@ void qeth_osn_deregister(struct net_device *dev)
        QETH_DBF_TEXT(TRACE, 2, "osndereg");
        if (!dev)
                return;
-       card = netdev_priv(dev);
+       card = dev->ml_priv;
        if (!card)
                return;
        card->osn_info.assist_cb = NULL;
index 38de31b557082cbe006f227bb3f6e88603ed3dc4..3e1d13857350959519524ec655f5659d3f633444 100644 (file)
@@ -1813,7 +1813,7 @@ static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
 static void qeth_l3_vlan_rx_register(struct net_device *dev,
                        struct vlan_group *grp)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        unsigned long flags;
 
        QETH_DBF_TEXT(TRACE, 4, "vlanreg");
@@ -1825,7 +1825,7 @@ static void qeth_l3_vlan_rx_register(struct net_device *dev,
 static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
        struct net_device *vlandev;
-       struct qeth_card *card = (struct qeth_card *) dev->priv;
+       struct qeth_card *card = dev->ml_priv;
        struct in_device *in_dev;
 
        if (card->info.type == QETH_CARD_TYPE_IQD)
@@ -1851,7 +1851,7 @@ static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 
 static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        unsigned long flags;
 
        QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid);
@@ -2013,7 +2013,7 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev,
                }
        }
 
-       if (rc && !(netdev_priv(vlan_dev_real_dev(dev)) == (void *)card))
+       if (rc && !(vlan_dev_real_dev(dev)->ml_priv == (void *)card))
                return 0;
 
        return rc;
@@ -2047,9 +2047,9 @@ static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
 
        rc = qeth_l3_verify_dev(dev);
        if (rc == QETH_REAL_CARD)
-               card = netdev_priv(dev);
+               card = dev->ml_priv;
        else if (rc == QETH_VLAN_CARD)
-               card = netdev_priv(vlan_dev_real_dev(dev));
+               card = vlan_dev_real_dev(dev)->ml_priv;
        if (card && card->options.layer2)
                card = NULL;
        QETH_DBF_TEXT_(TRACE, 4, "%d", rc);
@@ -2110,7 +2110,7 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
 
 static void qeth_l3_set_multicast_list(struct net_device *dev)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
 
        QETH_DBF_TEXT(TRACE, 3, "setmulti");
        qeth_l3_delete_mc_addresses(card);
@@ -2438,7 +2438,7 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card)
 
 static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        struct qeth_arp_cache_entry arp_entry;
        struct mii_ioctl_data *mii_data;
        int rc = 0;
@@ -2595,7 +2595,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        u16 *tag;
        struct qeth_hdr *hdr = NULL;
        int elements_needed = 0;
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        struct sk_buff *new_skb = NULL;
        int ipv = qeth_get_ip_version(skb);
        int cast_type = qeth_get_cast_type(card, skb);
@@ -2763,7 +2763,7 @@ tx_drop:
 
 static int qeth_l3_open(struct net_device *dev)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
 
        QETH_DBF_TEXT(TRACE, 4, "qethopen");
        if (card->state != CARD_STATE_SOFTSETUP)
@@ -2780,7 +2780,7 @@ static int qeth_l3_open(struct net_device *dev)
 
 static int qeth_l3_stop(struct net_device *dev)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
 
        QETH_DBF_TEXT(TRACE, 4, "qethstop");
        netif_tx_disable(dev);
@@ -2792,14 +2792,14 @@ static int qeth_l3_stop(struct net_device *dev)
 
 static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
 
        return (card->options.checksum_type == HW_CHECKSUMMING);
 }
 
 static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
        enum qeth_card_states old_state;
        enum qeth_checksum_types csum_type;
 
@@ -2825,7 +2825,7 @@ static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 
 static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data)
 {
-       struct qeth_card *card = netdev_priv(dev);
+       struct qeth_card *card = dev->ml_priv;
 
        if (data) {
                if (card->options.large_send == QETH_LARGE_SEND_NO) {
@@ -2915,7 +2915,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
                return -ENODEV;
 
        card->dev->hard_start_xmit = qeth_l3_hard_start_xmit;
-       card->dev->priv = card;
+       card->dev->ml_priv = card;
        card->dev->tx_timeout = &qeth_tx_timeout;
        card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
        card->dev->open = qeth_l3_open;
index 7045511f9ad2be543f9c4d5940b67d9a28bb0a09..b92c19bb6876971bf042c9f0e8e372e6bd5e91ef 100644 (file)
@@ -4,7 +4,7 @@
    Written By: Adam Radford <linuxraid@amcc.com>
    Modifications By: Tom Couch <linuxraid@amcc.com>
 
-   Copyright (C) 2004-2007 Applied Micro Circuits Corporation.
+   Copyright (C) 2004-2008 Applied Micro Circuits 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
                  Add support for 9650SE controllers.
    2.26.02.009 - Fix dma mask setting to fallback to 32-bit if 64-bit fails.
    2.26.02.010 - Add support for 9690SA controllers.
+   2.26.02.011 - Increase max AENs drained to 256.
+                 Add MSI support and "use_msi" module parameter.
+                 Fix bug in twa_get_param() on 4GB+.
+                 Use pci_resource_len() for ioremap().
 */
 
 #include <linux/module.h>
@@ -95,7 +99,7 @@
 #include "3w-9xxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "2.26.02.010"
+#define TW_DRIVER_VERSION "2.26.02.011"
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -107,6 +111,10 @@ MODULE_DESCRIPTION ("3ware 9000 Storage Controller Linux Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(TW_DRIVER_VERSION);
 
+static int use_msi = 0;
+module_param(use_msi, int, S_IRUGO);
+MODULE_PARM_DESC(use_msi, "Use Message Signaled Interrupts.  Default: 0");
+
 /* Function prototypes */
 static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header);
 static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id);
@@ -1038,7 +1046,6 @@ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl
        TW_Command_Full *full_command_packet;
        TW_Command *command_packet;
        TW_Param_Apache *param;
-       unsigned long param_value;
        void *retval = NULL;
 
        /* Setup the command packet */
@@ -1057,9 +1064,8 @@ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl
        param->table_id = cpu_to_le16(table_id | 0x8000);
        param->parameter_id = cpu_to_le16(parameter_id);
        param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes);
-       param_value = tw_dev->generic_buffer_phys[request_id];
 
-       command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(param_value);
+       command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
        command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
 
        /* Post the command packet to the board */
@@ -2000,7 +2006,7 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
 {
        struct Scsi_Host *host = NULL;
        TW_Device_Extension *tw_dev;
-       u32 mem_addr;
+       unsigned long mem_addr, mem_len;
        int retval = -ENODEV;
 
        retval = pci_enable_device(pdev);
@@ -2045,13 +2051,16 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
                goto out_free_device_extension;
        }
 
-       if (pdev->device == PCI_DEVICE_ID_3WARE_9000)
+       if (pdev->device == PCI_DEVICE_ID_3WARE_9000) {
                mem_addr = pci_resource_start(pdev, 1);
-       else
+               mem_len = pci_resource_len(pdev, 1);
+       } else {
                mem_addr = pci_resource_start(pdev, 2);
+               mem_len = pci_resource_len(pdev, 2);
+       }
 
        /* Save base address */
-       tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE);
+       tw_dev->base_addr = ioremap(mem_addr, mem_len);
        if (!tw_dev->base_addr) {
                TW_PRINTK(tw_dev->host, TW_DRIVER, 0x35, "Failed to ioremap");
                goto out_release_mem_region;
@@ -2086,7 +2095,7 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
 
        pci_set_drvdata(pdev, host);
 
-       printk(KERN_WARNING "3w-9xxx: scsi%d: Found a 3ware 9000 Storage Controller at 0x%x, IRQ: %d.\n",
+       printk(KERN_WARNING "3w-9xxx: scsi%d: Found a 3ware 9000 Storage Controller at 0x%lx, IRQ: %d.\n",
               host->host_no, mem_addr, pdev->irq);
        printk(KERN_WARNING "3w-9xxx: scsi%d: Firmware %s, BIOS %s, Ports: %d.\n",
               host->host_no,
@@ -2097,6 +2106,11 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
               le32_to_cpu(*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
                                     TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)));
 
+       /* Try to enable MSI */
+       if (use_msi && (pdev->device != PCI_DEVICE_ID_3WARE_9000) &&
+           !pci_enable_msi(pdev))
+               set_bit(TW_USING_MSI, &tw_dev->flags);
+
        /* Now setup the interrupt handler */
        retval = request_irq(pdev->irq, twa_interrupt, IRQF_SHARED, "3w-9xxx", tw_dev);
        if (retval) {
@@ -2120,6 +2134,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
        return 0;
 
 out_remove_host:
+       if (test_bit(TW_USING_MSI, &tw_dev->flags))
+               pci_disable_msi(pdev);
        scsi_remove_host(host);
 out_iounmap:
        iounmap(tw_dev->base_addr);
@@ -2151,6 +2167,10 @@ static void twa_remove(struct pci_dev *pdev)
        /* Shutdown the card */
        __twa_shutdown(tw_dev);
 
+       /* Disable MSI if enabled */
+       if (test_bit(TW_USING_MSI, &tw_dev->flags))
+               pci_disable_msi(pdev);
+
        /* Free IO remapping */
        iounmap(tw_dev->base_addr);
 
index d14a9479e3895edf2dea95800128073b8a686954..1729a8785fea197c0e1ae16f962952372dc0b5cf 100644 (file)
@@ -4,7 +4,7 @@
    Written By: Adam Radford <linuxraid@amcc.com>
    Modifications By: Tom Couch <linuxraid@amcc.com>
 
-   Copyright (C) 2004-2007 Applied Micro Circuits Corporation.
+   Copyright (C) 2004-2008 Applied Micro Circuits 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
@@ -319,8 +319,8 @@ static twa_message_type twa_error_table[] = {
 
 /* Compatibility defines */
 #define TW_9000_ARCH_ID 0x5
-#define TW_CURRENT_DRIVER_SRL 30
-#define TW_CURRENT_DRIVER_BUILD 80
+#define TW_CURRENT_DRIVER_SRL 35
+#define TW_CURRENT_DRIVER_BUILD 0
 #define TW_CURRENT_DRIVER_BRANCH 0
 
 /* Phase defines */
@@ -352,8 +352,9 @@ static twa_message_type twa_error_table[] = {
 #define TW_MAX_RESET_TRIES                   2
 #define TW_MAX_CMDS_PER_LUN                  254
 #define TW_MAX_RESPONSE_DRAIN                256
-#define TW_MAX_AEN_DRAIN                     40
+#define TW_MAX_AEN_DRAIN                     255
 #define TW_IN_RESET                           2
+#define TW_USING_MSI                         3
 #define TW_IN_ATTENTION_LOOP                 4
 #define TW_MAX_SECTORS                        256
 #define TW_AEN_WAIT_TIME                      1000
index 26be540d1dd373ec79872fed9d97d71b3d8f16a1..c7f06298bd3c09242abd800cebb1b2b7dfb3f104 100644 (file)
@@ -63,6 +63,7 @@ comment "SCSI support type (disk, tape, CD-ROM)"
 config BLK_DEV_SD
        tristate "SCSI disk support"
        depends on SCSI
+       select CRC_T10DIF
        ---help---
          If you want to use SCSI hard disks, Fibre Channel disks,
          Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
index a8149677de23613076b65e7f8a318a027de4c39c..72fd5043cfa1c14cef585db3077317ce8c6699a0 100644 (file)
@@ -151,6 +151,8 @@ scsi_mod-$(CONFIG_SCSI_PROC_FS)     += scsi_proc.o
 scsi_tgt-y                     += scsi_tgt_lib.o scsi_tgt_if.o
 
 sd_mod-objs    := sd.o
+sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o
+
 sr_mod-objs    := sr.o sr_ioctl.o sr_vendor.o
 ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
                := -DCONFIG_NCR53C8XX_PREFETCH -DSCSI_NCR_BIG_ENDIAN \
index 8591585e5cc55c27669a004c48c048521a3dc9e4..218777bfc143db8bc54b1967b4c07f0a29232492 100644 (file)
@@ -2278,7 +2278,7 @@ do { \
 #define ASC_DBG(lvl, format, arg...) {                                 \
        if (asc_dbglvl >= (lvl))                                        \
                printk(KERN_DEBUG "%s: %s: " format, DRV_NAME,          \
-                       __FUNCTION__ , ## arg);                         \
+                       __func__ , ## arg);                             \
 }
 
 #define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
index 0899cb61e3ddc08dd9db34a541decdb00f76a242..b5a868d85eb49760ac1f512195b29cb88c43578b 100644 (file)
@@ -288,20 +288,20 @@ static LIST_HEAD(aha152x_host_list);
 #define DO_LOCK(flags) \
        do { \
                if(spin_is_locked(&QLOCK)) { \
-                       DPRINTK(debug_intr, DEBUG_LEAD "(%s:%d) already locked at %s:%d\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \
+                       DPRINTK(debug_intr, DEBUG_LEAD "(%s:%d) already locked at %s:%d\n", CMDINFO(CURRENT_SC), __func__, __LINE__, QLOCKER, QLOCKERL); \
                } \
-               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \
+               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __func__, __LINE__); \
                spin_lock_irqsave(&QLOCK,flags); \
-               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \
-               QLOCKER=__FUNCTION__; \
+               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locked\n", CMDINFO(CURRENT_SC), __func__, __LINE__); \
+               QLOCKER=__func__; \
                QLOCKERL=__LINE__; \
        } while(0)
 
 #define DO_UNLOCK(flags)       \
        do { \
-               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocking (locked at %s:%d)\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \
+               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocking (locked at %s:%d)\n", CMDINFO(CURRENT_SC), __func__, __LINE__, QLOCKER, QLOCKERL); \
                spin_unlock_irqrestore(&QLOCK,flags); \
-               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \
+               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocked\n", CMDINFO(CURRENT_SC), __func__, __LINE__); \
                QLOCKER="(not locked)"; \
                QLOCKERL=0; \
        } while(0)
index 2ef459e9cda1a190213ae59fc2b64126f50c8923..2863a9d22851511f1fb9f8de2b9982903c8671bf 100644 (file)
@@ -39,9 +39,9 @@
 
 #ifdef ASD_ENTER_EXIT
 #define ENTER  printk(KERN_NOTICE "%s: ENTER %s\n", ASD_DRIVER_NAME, \
-               __FUNCTION__)
+               __func__)
 #define EXIT   printk(KERN_NOTICE "%s: --EXIT %s\n", ASD_DRIVER_NAME, \
-               __FUNCTION__)
+               __func__)
 #else
 #define ENTER
 #define EXIT
index 83a78222896dfa171136dbb0bd6e04fc836a4f87..eb9dc3195fdfdbe7918b7d3ce0a3547e53e55ce4 100644 (file)
@@ -1359,7 +1359,7 @@ int asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask)
        struct asd_ascb *ascb_list;
 
        if (!phy_mask) {
-               asd_printk("%s called with phy_mask of 0!?\n", __FUNCTION__);
+               asd_printk("%s called with phy_mask of 0!?\n", __func__);
                return 0;
        }
 
index 46643319c5201d1a1fbdc0b060982c4198085347..ca55013b6ae588cd699dde7739faf1f8dcbc3025 100644 (file)
@@ -211,7 +211,7 @@ static void asd_form_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
                phy->asd_port = port;
        }
        ASD_DPRINTK("%s: updating phy_mask 0x%x for phy%d\n",
-                   __FUNCTION__, phy->asd_port->phy_mask, sas_phy->id);
+                   __func__, phy->asd_port->phy_mask, sas_phy->id);
        asd_update_port_links(asd_ha, phy);
        spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
 }
@@ -294,7 +294,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
                struct asd_ascb *cp = asd_ascb_alloc_list(ascb->ha, &num,
                                                          GFP_ATOMIC);
                if (!cp) {
-                       asd_printk("%s: out of memory\n", __FUNCTION__);
+                       asd_printk("%s: out of memory\n", __func__);
                        goto out;
                }
                ASD_DPRINTK("phy%d: retries:0 performing link reset seq\n",
@@ -446,7 +446,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
                struct domain_device *failed_dev = NULL;
 
                ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
-                           __FUNCTION__, dl->status_block[3]);
+                           __func__, dl->status_block[3]);
 
                /*
                 * Find the task that caused the abort and abort it first.
@@ -474,7 +474,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
 
                if (!failed_dev) {
                        ASD_DPRINTK("%s: Can't find task (tc=%d) to abort!\n",
-                                   __FUNCTION__, tc_abort);
+                                   __func__, tc_abort);
                        goto out;
                }
 
@@ -502,7 +502,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
                conn_handle = *((u16*)(&dl->status_block[1]));
                conn_handle = le16_to_cpu(conn_handle);
 
-               ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__,
+               ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __func__,
                            dl->status_block[3]);
 
                /* Find the last pending task for the device... */
@@ -522,7 +522,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
 
                if (!last_dev_task) {
                        ASD_DPRINTK("%s: Device reset for idle device %d?\n",
-                                   __FUNCTION__, conn_handle);
+                                   __func__, conn_handle);
                        goto out;
                }
 
@@ -549,10 +549,10 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
                goto out;
        }
        case SIGNAL_NCQ_ERROR:
-               ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __FUNCTION__);
+               ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __func__);
                goto out;
        case CLEAR_NCQ_ERROR:
-               ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __FUNCTION__);
+               ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __func__);
                goto out;
        }
 
@@ -560,26 +560,26 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
 
        switch (sb_opcode) {
        case BYTES_DMAED:
-               ASD_DPRINTK("%s: phy%d: BYTES_DMAED\n", __FUNCTION__, phy_id);
+               ASD_DPRINTK("%s: phy%d: BYTES_DMAED\n", __func__, phy_id);
                asd_bytes_dmaed_tasklet(ascb, dl, edb, phy_id);
                break;
        case PRIMITIVE_RECVD:
-               ASD_DPRINTK("%s: phy%d: PRIMITIVE_RECVD\n", __FUNCTION__,
+               ASD_DPRINTK("%s: phy%d: PRIMITIVE_RECVD\n", __func__,
                            phy_id);
                asd_primitive_rcvd_tasklet(ascb, dl, phy_id);
                break;
        case PHY_EVENT:
-               ASD_DPRINTK("%s: phy%d: PHY_EVENT\n", __FUNCTION__, phy_id);
+               ASD_DPRINTK("%s: phy%d: PHY_EVENT\n", __func__, phy_id);
                asd_phy_event_tasklet(ascb, dl);
                break;
        case LINK_RESET_ERROR:
-               ASD_DPRINTK("%s: phy%d: LINK_RESET_ERROR\n", __FUNCTION__,
+               ASD_DPRINTK("%s: phy%d: LINK_RESET_ERROR\n", __func__,
                            phy_id);
                asd_link_reset_err_tasklet(ascb, dl, phy_id);
                break;
        case TIMER_EVENT:
                ASD_DPRINTK("%s: phy%d: TIMER_EVENT, lost dw sync\n",
-                           __FUNCTION__, phy_id);
+                           __func__, phy_id);
                asd_turn_led(asd_ha, phy_id, 0);
                /* the device is gone */
                sas_phy_disconnected(sas_phy);
@@ -587,7 +587,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
                sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT);
                break;
        default:
-               ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __FUNCTION__,
+               ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __func__,
                            phy_id, sb_opcode);
                ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n",
                            edb, dl->opcode);
@@ -654,7 +654,7 @@ static void control_phy_tasklet_complete(struct asd_ascb *ascb,
 
        if (status != 0) {
                ASD_DPRINTK("%s: phy%d status block opcode:0x%x\n",
-                           __FUNCTION__, phy_id, status);
+                           __func__, phy_id, status);
                goto out;
        }
 
@@ -663,7 +663,7 @@ static void control_phy_tasklet_complete(struct asd_ascb *ascb,
                asd_ha->hw_prof.enabled_phys &= ~(1 << phy_id);
                asd_turn_led(asd_ha, phy_id, 0);
                asd_control_led(asd_ha, phy_id, 0);
-               ASD_DPRINTK("%s: disable phy%d\n", __FUNCTION__, phy_id);
+               ASD_DPRINTK("%s: disable phy%d\n", __func__, phy_id);
                break;
 
        case ENABLE_PHY:
@@ -673,40 +673,40 @@ static void control_phy_tasklet_complete(struct asd_ascb *ascb,
                        get_lrate_mode(phy, oob_mode);
                        asd_turn_led(asd_ha, phy_id, 1);
                        ASD_DPRINTK("%s: phy%d, lrate:0x%x, proto:0x%x\n",
-                                   __FUNCTION__, phy_id,phy->sas_phy.linkrate,
+                                   __func__, phy_id,phy->sas_phy.linkrate,
                                    phy->sas_phy.iproto);
                } else if (oob_status & CURRENT_SPINUP_HOLD) {
                        asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
                        asd_turn_led(asd_ha, phy_id, 1);
-                       ASD_DPRINTK("%s: phy%d, spinup hold\n", __FUNCTION__,
+                       ASD_DPRINTK("%s: phy%d, spinup hold\n", __func__,
                                    phy_id);
                } else if (oob_status & CURRENT_ERR_MASK) {
                        asd_turn_led(asd_ha, phy_id, 0);
                        ASD_DPRINTK("%s: phy%d: error: oob status:0x%02x\n",
-                                   __FUNCTION__, phy_id, oob_status);
+                                   __func__, phy_id, oob_status);
                } else if (oob_status & (CURRENT_HOT_PLUG_CNCT
                                         | CURRENT_DEVICE_PRESENT))  {
                        asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
                        asd_turn_led(asd_ha, phy_id, 1);
                        ASD_DPRINTK("%s: phy%d: hot plug or device present\n",
-                                   __FUNCTION__, phy_id);
+                                   __func__, phy_id);
                } else {
                        asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
                        asd_turn_led(asd_ha, phy_id, 0);
                        ASD_DPRINTK("%s: phy%d: no device present: "
                                    "oob_status:0x%x\n",
-                                   __FUNCTION__, phy_id, oob_status);
+                                   __func__, phy_id, oob_status);
                }
                break;
        case RELEASE_SPINUP_HOLD:
        case PHY_NO_OP:
        case EXECUTE_HARD_RESET:
-               ASD_DPRINTK("%s: phy%d: sub_func:0x%x\n", __FUNCTION__,
+               ASD_DPRINTK("%s: phy%d: sub_func:0x%x\n", __func__,
                            phy_id, control_phy->sub_func);
                /* XXX finish */
                break;
        default:
-               ASD_DPRINTK("%s: phy%d: sub_func:0x%x?\n", __FUNCTION__,
+               ASD_DPRINTK("%s: phy%d: sub_func:0x%x?\n", __func__,
                            phy_id, control_phy->sub_func);
                break;
        }
index 326765c9caf869a00e7fd000dc075075eb03cfce..75d20f72501feaaf7c631a6cf791da9284ea93f5 100644 (file)
@@ -320,7 +320,7 @@ Again:
        case TC_RESUME:
        case TC_PARTIAL_SG_LIST:
        default:
-               ASD_DPRINTK("%s: dl opcode: 0x%x?\n", __FUNCTION__, opcode);
+               ASD_DPRINTK("%s: dl opcode: 0x%x?\n", __func__, opcode);
                break;
        }
 
index 633ff40c736a69f0b9ebc8ad2abd97adb14b981f..d4640ef6d44fcc00e56b95d88ad9906e8934bb4b 100644 (file)
@@ -75,12 +75,12 @@ static void asd_clear_nexus_tasklet_complete(struct asd_ascb *ascb,
                                             struct done_list_struct *dl)
 {
        struct tasklet_completion_status *tcs = ascb->uldd_task;
-       ASD_DPRINTK("%s: here\n", __FUNCTION__);
+       ASD_DPRINTK("%s: here\n", __func__);
        if (!del_timer(&ascb->timer)) {
-               ASD_DPRINTK("%s: couldn't delete timer\n", __FUNCTION__);
+               ASD_DPRINTK("%s: couldn't delete timer\n", __func__);
                return;
        }
-       ASD_DPRINTK("%s: opcode: 0x%x\n", __FUNCTION__, dl->opcode);
+       ASD_DPRINTK("%s: opcode: 0x%x\n", __func__, dl->opcode);
        tcs->dl_opcode = dl->opcode;
        complete(ascb->completion);
        asd_ascb_free(ascb);
@@ -91,7 +91,7 @@ static void asd_clear_nexus_timedout(unsigned long data)
        struct asd_ascb *ascb = (void *)data;
        struct tasklet_completion_status *tcs = ascb->uldd_task;
 
-       ASD_DPRINTK("%s: here\n", __FUNCTION__);
+       ASD_DPRINTK("%s: here\n", __func__);
        tcs->dl_opcode = TMF_RESP_FUNC_FAILED;
        complete(ascb->completion);
 }
@@ -103,7 +103,7 @@ static void asd_clear_nexus_timedout(unsigned long data)
        DECLARE_COMPLETION_ONSTACK(completion); \
        DECLARE_TCS(tcs); \
                \
-       ASD_DPRINTK("%s: PRE\n", __FUNCTION__); \
+       ASD_DPRINTK("%s: PRE\n", __func__); \
         res = 1;                \
        ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); \
        if (!ascb)              \
@@ -115,12 +115,12 @@ static void asd_clear_nexus_timedout(unsigned long data)
        scb->header.opcode = CLEAR_NEXUS
 
 #define CLEAR_NEXUS_POST        \
-       ASD_DPRINTK("%s: POST\n", __FUNCTION__); \
+       ASD_DPRINTK("%s: POST\n", __func__); \
        res = asd_enqueue_internal(ascb, asd_clear_nexus_tasklet_complete, \
                                   asd_clear_nexus_timedout);              \
        if (res)                \
                goto out_err;   \
-       ASD_DPRINTK("%s: clear nexus posted, waiting...\n", __FUNCTION__); \
+       ASD_DPRINTK("%s: clear nexus posted, waiting...\n", __func__); \
        wait_for_completion(&completion); \
        res = tcs.dl_opcode; \
        if (res == TC_NO_ERROR) \
@@ -417,7 +417,7 @@ int asd_abort_task(struct sas_task *task)
        if (task->task_state_flags & SAS_TASK_STATE_DONE) {
                spin_unlock_irqrestore(&task->task_state_lock, flags);
                res = TMF_RESP_FUNC_COMPLETE;
-               ASD_DPRINTK("%s: task 0x%p done\n", __FUNCTION__, task);
+               ASD_DPRINTK("%s: task 0x%p done\n", __func__, task);
                goto out_done;
        }
        spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -481,7 +481,7 @@ int asd_abort_task(struct sas_task *task)
        if (task->task_state_flags & SAS_TASK_STATE_DONE) {
                spin_unlock_irqrestore(&task->task_state_lock, flags);
                res = TMF_RESP_FUNC_COMPLETE;
-               ASD_DPRINTK("%s: task 0x%p done\n", __FUNCTION__, task);
+               ASD_DPRINTK("%s: task 0x%p done\n", __func__, task);
                goto out_done;
        }
        spin_unlock_irqrestore(&task->task_state_lock, flags);
index a715632e19d472ec61956f87c12a1c61f8fbc4a5..477542602284661dbcb7d0d65d65223d612d3ec4 100644 (file)
@@ -240,7 +240,7 @@ static void __fas216_checkmagic(FAS216_Info *info, const char *func)
                panic("scsi memory space corrupted in %s", func);
        }
 }
-#define fas216_checkmagic(info) __fas216_checkmagic((info), __FUNCTION__)
+#define fas216_checkmagic(info) __fas216_checkmagic((info), __func__)
 #else
 #define fas216_checkmagic(info)
 #endif
@@ -2658,7 +2658,7 @@ int fas216_eh_host_reset(struct scsi_cmnd *SCpnt)
        fas216_checkmagic(info);
 
        printk("scsi%d.%c: %s: resetting host\n",
-               info->host->host_no, '0' + SCpnt->device->id, __FUNCTION__);
+               info->host->host_no, '0' + SCpnt->device->id, __func__);
 
        /*
         * Reset the SCSI chip.
index aa2011b6468387609993e2ab7643b8e40740c403..3c257fe0893e51c9740f226b752a559321cb95a4 100644 (file)
@@ -930,6 +930,7 @@ static int ch_probe(struct device *dev)
        if (init)
                ch_init_elem(ch);
 
+       dev_set_drvdata(dev, ch);
        sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name);
 
        return 0;
index 2adc0f666b682fbd8e738299a4b385a8505761bc..67070257919fcbca074c23b177e97ba6484e6217 100644 (file)
@@ -30,3 +30,11 @@ config SCSI_DH_EMC
        depends on SCSI_DH
        help
        If you have a EMC CLARiiON select y. Otherwise, say N.
+
+config SCSI_DH_ALUA
+       tristate "SPC-3 ALUA Device Handler (EXPERIMENTAL)"
+       depends on SCSI_DH && EXPERIMENTAL
+       help
+         SCSI Device handler for generic SPC-3 Asymmetric Logical Unit
+         Access (ALUA).
+
index 35272e93b1c82578c624a8213c692f221eaa9426..e1d2ea083e159d0585d783a8c8757acb93ad0300 100644 (file)
@@ -5,3 +5,4 @@ obj-$(CONFIG_SCSI_DH)           += scsi_dh.o
 obj-$(CONFIG_SCSI_DH_RDAC)     += scsi_dh_rdac.o
 obj-$(CONFIG_SCSI_DH_HP_SW)    += scsi_dh_hp_sw.o
 obj-$(CONFIG_SCSI_DH_EMC)      += scsi_dh_emc.o
+obj-$(CONFIG_SCSI_DH_ALUA)     += scsi_dh_alua.o
index ab6c21cd9689c6c3ff27987fc53cacd138861dbd..a518f2eff19af1a7dcf86383f287940487ce80f3 100644 (file)
 #include <scsi/scsi_dh.h>
 #include "../scsi_priv.h"
 
+struct scsi_dh_devinfo_list {
+       struct list_head node;
+       char vendor[9];
+       char model[17];
+       struct scsi_device_handler *handler;
+};
+
 static DEFINE_SPINLOCK(list_lock);
 static LIST_HEAD(scsi_dh_list);
+static LIST_HEAD(scsi_dh_dev_list);
 
 static struct scsi_device_handler *get_device_handler(const char *name)
 {
@@ -33,7 +41,7 @@ static struct scsi_device_handler *get_device_handler(const char *name)
 
        spin_lock(&list_lock);
        list_for_each_entry(tmp, &scsi_dh_list, list) {
-               if (!strcmp(tmp->name, name)) {
+               if (!strncmp(tmp->name, name, strlen(tmp->name))) {
                        found = tmp;
                        break;
                }
@@ -42,11 +50,307 @@ static struct scsi_device_handler *get_device_handler(const char *name)
        return found;
 }
 
+
+static struct scsi_device_handler *
+scsi_dh_cache_lookup(struct scsi_device *sdev)
+{
+       struct scsi_dh_devinfo_list *tmp;
+       struct scsi_device_handler *found_dh = NULL;
+
+       spin_lock(&list_lock);
+       list_for_each_entry(tmp, &scsi_dh_dev_list, node) {
+               if (!strncmp(sdev->vendor, tmp->vendor, strlen(tmp->vendor)) &&
+                   !strncmp(sdev->model, tmp->model, strlen(tmp->model))) {
+                       found_dh = tmp->handler;
+                       break;
+               }
+       }
+       spin_unlock(&list_lock);
+
+       return found_dh;
+}
+
+static int scsi_dh_handler_lookup(struct scsi_device_handler *scsi_dh,
+                                 struct scsi_device *sdev)
+{
+       int i, found = 0;
+
+       for(i = 0; scsi_dh->devlist[i].vendor; i++) {
+               if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor,
+                            strlen(scsi_dh->devlist[i].vendor)) &&
+                   !strncmp(sdev->model, scsi_dh->devlist[i].model,
+                            strlen(scsi_dh->devlist[i].model))) {
+                       found = 1;
+                       break;
+               }
+       }
+       return found;
+}
+
+/*
+ * device_handler_match - Attach a device handler to a device
+ * @scsi_dh - The device handler to match against or NULL
+ * @sdev - SCSI device to be tested against @scsi_dh
+ *
+ * Tests @sdev against the device handler @scsi_dh or against
+ * all registered device_handler if @scsi_dh == NULL.
+ * Returns the found device handler or NULL if not found.
+ */
+static struct scsi_device_handler *
+device_handler_match(struct scsi_device_handler *scsi_dh,
+                    struct scsi_device *sdev)
+{
+       struct scsi_device_handler *found_dh = NULL;
+       struct scsi_dh_devinfo_list *tmp;
+
+       found_dh = scsi_dh_cache_lookup(sdev);
+       if (found_dh)
+               return found_dh;
+
+       if (scsi_dh) {
+               if (scsi_dh_handler_lookup(scsi_dh, sdev))
+                       found_dh = scsi_dh;
+       } else {
+               struct scsi_device_handler *tmp_dh;
+
+               spin_lock(&list_lock);
+               list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
+                       if (scsi_dh_handler_lookup(tmp_dh, sdev))
+                               found_dh = tmp_dh;
+               }
+               spin_unlock(&list_lock);
+       }
+
+       if (found_dh) { /* If device is found, add it to the cache */
+               tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+               if (tmp) {
+                       strncpy(tmp->vendor, sdev->vendor, 8);
+                       strncpy(tmp->model, sdev->model, 16);
+                       tmp->vendor[8] = '\0';
+                       tmp->model[16] = '\0';
+                       tmp->handler = found_dh;
+                       spin_lock(&list_lock);
+                       list_add(&tmp->node, &scsi_dh_dev_list);
+                       spin_unlock(&list_lock);
+               } else {
+                       found_dh = NULL;
+               }
+       }
+
+       return found_dh;
+}
+
+/*
+ * scsi_dh_handler_attach - Attach a device handler to a device
+ * @sdev - SCSI device the device handler should attach to
+ * @scsi_dh - The device handler to attach
+ */
+static int scsi_dh_handler_attach(struct scsi_device *sdev,
+                                 struct scsi_device_handler *scsi_dh)
+{
+       int err = 0;
+
+       if (sdev->scsi_dh_data) {
+               if (sdev->scsi_dh_data->scsi_dh != scsi_dh)
+                       err = -EBUSY;
+       } else if (scsi_dh->attach)
+               err = scsi_dh->attach(sdev);
+
+       return err;
+}
+
+/*
+ * scsi_dh_handler_detach - Detach a device handler from a device
+ * @sdev - SCSI device the device handler should be detached from
+ * @scsi_dh - Device handler to be detached
+ *
+ * Detach from a device handler. If a device handler is specified,
+ * only detach if the currently attached handler matches @scsi_dh.
+ */
+static void scsi_dh_handler_detach(struct scsi_device *sdev,
+                                  struct scsi_device_handler *scsi_dh)
+{
+       if (!sdev->scsi_dh_data)
+               return;
+
+       if (scsi_dh && scsi_dh != sdev->scsi_dh_data->scsi_dh)
+               return;
+
+       if (!scsi_dh)
+               scsi_dh = sdev->scsi_dh_data->scsi_dh;
+
+       if (scsi_dh && scsi_dh->detach)
+               scsi_dh->detach(sdev);
+}
+
+/*
+ * Functions for sysfs attribute 'dh_state'
+ */
+static ssize_t
+store_dh_state(struct device *dev, struct device_attribute *attr,
+              const char *buf, size_t count)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct scsi_device_handler *scsi_dh;
+       int err = -EINVAL;
+
+       if (!sdev->scsi_dh_data) {
+               /*
+                * Attach to a device handler
+                */
+               if (!(scsi_dh = get_device_handler(buf)))
+                       return err;
+               err = scsi_dh_handler_attach(sdev, scsi_dh);
+       } else {
+               scsi_dh = sdev->scsi_dh_data->scsi_dh;
+               if (!strncmp(buf, "detach", 6)) {
+                       /*
+                        * Detach from a device handler
+                        */
+                       scsi_dh_handler_detach(sdev, scsi_dh);
+                       err = 0;
+               } else if (!strncmp(buf, "activate", 8)) {
+                       /*
+                        * Activate a device handler
+                        */
+                       if (scsi_dh->activate)
+                               err = scsi_dh->activate(sdev);
+                       else
+                               err = 0;
+               }
+       }
+
+       return err<0?err:count;
+}
+
+static ssize_t
+show_dh_state(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+
+       if (!sdev->scsi_dh_data)
+               return snprintf(buf, 20, "detached\n");
+
+       return snprintf(buf, 20, "%s\n", sdev->scsi_dh_data->scsi_dh->name);
+}
+
+static struct device_attribute scsi_dh_state_attr =
+       __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state,
+              store_dh_state);
+
+/*
+ * scsi_dh_sysfs_attr_add - Callback for scsi_init_dh
+ */
+static int scsi_dh_sysfs_attr_add(struct device *dev, void *data)
+{
+       struct scsi_device *sdev;
+       int err;
+
+       if (!scsi_is_sdev_device(dev))
+               return 0;
+
+       sdev = to_scsi_device(dev);
+
+       err = device_create_file(&sdev->sdev_gendev,
+                                &scsi_dh_state_attr);
+
+       return 0;
+}
+
+/*
+ * scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh
+ */
+static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data)
+{
+       struct scsi_device *sdev;
+
+       if (!scsi_is_sdev_device(dev))
+               return 0;
+
+       sdev = to_scsi_device(dev);
+
+       device_remove_file(&sdev->sdev_gendev,
+                          &scsi_dh_state_attr);
+
+       return 0;
+}
+
+/*
+ * scsi_dh_notifier - notifier chain callback
+ */
+static int scsi_dh_notifier(struct notifier_block *nb,
+                           unsigned long action, void *data)
+{
+       struct device *dev = data;
+       struct scsi_device *sdev;
+       int err = 0;
+       struct scsi_device_handler *devinfo = NULL;
+
+       if (!scsi_is_sdev_device(dev))
+               return 0;
+
+       sdev = to_scsi_device(dev);
+
+       if (action == BUS_NOTIFY_ADD_DEVICE) {
+               devinfo = device_handler_match(NULL, sdev);
+               if (!devinfo)
+                       goto out;
+
+               err = scsi_dh_handler_attach(sdev, devinfo);
+               if (!err)
+                       err = device_create_file(dev, &scsi_dh_state_attr);
+       } else if (action == BUS_NOTIFY_DEL_DEVICE) {
+               device_remove_file(dev, &scsi_dh_state_attr);
+               scsi_dh_handler_detach(sdev, NULL);
+       }
+out:
+       return err;
+}
+
+/*
+ * scsi_dh_notifier_add - Callback for scsi_register_device_handler
+ */
 static int scsi_dh_notifier_add(struct device *dev, void *data)
 {
        struct scsi_device_handler *scsi_dh = data;
+       struct scsi_device *sdev;
+
+       if (!scsi_is_sdev_device(dev))
+               return 0;
+
+       if (!get_device(dev))
+               return 0;
+
+       sdev = to_scsi_device(dev);
+
+       if (device_handler_match(scsi_dh, sdev))
+               scsi_dh_handler_attach(sdev, scsi_dh);
+
+       put_device(dev);
+
+       return 0;
+}
+
+/*
+ * scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler
+ */
+static int scsi_dh_notifier_remove(struct device *dev, void *data)
+{
+       struct scsi_device_handler *scsi_dh = data;
+       struct scsi_device *sdev;
+
+       if (!scsi_is_sdev_device(dev))
+               return 0;
+
+       if (!get_device(dev))
+               return 0;
+
+       sdev = to_scsi_device(dev);
+
+       scsi_dh_handler_detach(sdev, scsi_dh);
+
+       put_device(dev);
 
-       scsi_dh->nb.notifier_call(&scsi_dh->nb, BUS_NOTIFY_ADD_DEVICE, dev);
        return 0;
 }
 
@@ -59,33 +363,19 @@ static int scsi_dh_notifier_add(struct device *dev, void *data)
  */
 int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
 {
-       int ret = -EBUSY;
-       struct scsi_device_handler *tmp;
+       if (get_device_handler(scsi_dh->name))
+               return -EBUSY;
 
-       tmp = get_device_handler(scsi_dh->name);
-       if (tmp)
-               goto done;
-
-       ret = bus_register_notifier(&scsi_bus_type, &scsi_dh->nb);
-
-       bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
        spin_lock(&list_lock);
        list_add(&scsi_dh->list, &scsi_dh_list);
        spin_unlock(&list_lock);
+       bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
+       printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
 
-done:
-       return ret;
+       return SCSI_DH_OK;
 }
 EXPORT_SYMBOL_GPL(scsi_register_device_handler);
 
-static int scsi_dh_notifier_remove(struct device *dev, void *data)
-{
-       struct scsi_device_handler *scsi_dh = data;
-
-       scsi_dh->nb.notifier_call(&scsi_dh->nb, BUS_NOTIFY_DEL_DEVICE, dev);
-       return 0;
-}
-
 /*
  * scsi_unregister_device_handler - register a device handler personality
  *      module.
@@ -95,23 +385,26 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data)
  */
 int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
 {
-       int ret = -ENODEV;
-       struct scsi_device_handler *tmp;
-
-       tmp = get_device_handler(scsi_dh->name);
-       if (!tmp)
-               goto done;
+       struct scsi_dh_devinfo_list *tmp, *pos;
 
-       ret = bus_unregister_notifier(&scsi_bus_type, &scsi_dh->nb);
+       if (!get_device_handler(scsi_dh->name))
+               return -ENODEV;
 
        bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
-                                       scsi_dh_notifier_remove);
+                        scsi_dh_notifier_remove);
+
        spin_lock(&list_lock);
        list_del(&scsi_dh->list);
+       list_for_each_entry_safe(pos, tmp, &scsi_dh_dev_list, node) {
+               if (pos->handler == scsi_dh) {
+                       list_del(&pos->node);
+                       kfree(pos);
+               }
+       }
        spin_unlock(&list_lock);
+       printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
 
-done:
-       return ret;
+       return SCSI_DH_OK;
 }
 EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
 
@@ -157,6 +450,97 @@ int scsi_dh_handler_exist(const char *name)
 }
 EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
 
+/*
+ * scsi_dh_handler_attach - Attach device handler
+ * @sdev - sdev the handler should be attached to
+ * @name - name of the handler to attach
+ */
+int scsi_dh_attach(struct request_queue *q, const char *name)
+{
+       unsigned long flags;
+       struct scsi_device *sdev;
+       struct scsi_device_handler *scsi_dh;
+       int err = 0;
+
+       scsi_dh = get_device_handler(name);
+       if (!scsi_dh)
+               return -EINVAL;
+
+       spin_lock_irqsave(q->queue_lock, flags);
+       sdev = q->queuedata;
+       if (!sdev || !get_device(&sdev->sdev_gendev))
+               err = -ENODEV;
+       spin_unlock_irqrestore(q->queue_lock, flags);
+
+       if (!err) {
+               err = scsi_dh_handler_attach(sdev, scsi_dh);
+
+               put_device(&sdev->sdev_gendev);
+       }
+       return err;
+}
+EXPORT_SYMBOL_GPL(scsi_dh_attach);
+
+/*
+ * scsi_dh_handler_detach - Detach device handler
+ * @sdev - sdev the handler should be detached from
+ *
+ * This function will detach the device handler only
+ * if the sdev is not part of the internal list, ie
+ * if it has been attached manually.
+ */
+void scsi_dh_detach(struct request_queue *q)
+{
+       unsigned long flags;
+       struct scsi_device *sdev;
+       struct scsi_device_handler *scsi_dh = NULL;
+
+       spin_lock_irqsave(q->queue_lock, flags);
+       sdev = q->queuedata;
+       if (!sdev || !get_device(&sdev->sdev_gendev))
+               sdev = NULL;
+       spin_unlock_irqrestore(q->queue_lock, flags);
+
+       if (!sdev)
+               return;
+
+       if (sdev->scsi_dh_data) {
+               /* if sdev is not on internal list, detach */
+               scsi_dh = sdev->scsi_dh_data->scsi_dh;
+               if (!device_handler_match(scsi_dh, sdev))
+                       scsi_dh_handler_detach(sdev, scsi_dh);
+       }
+       put_device(&sdev->sdev_gendev);
+}
+EXPORT_SYMBOL_GPL(scsi_dh_detach);
+
+static struct notifier_block scsi_dh_nb = {
+       .notifier_call = scsi_dh_notifier
+};
+
+static int __init scsi_dh_init(void)
+{
+       int r;
+
+       r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);
+
+       if (!r)
+               bus_for_each_dev(&scsi_bus_type, NULL, NULL,
+                                scsi_dh_sysfs_attr_add);
+
+       return r;
+}
+
+static void __exit scsi_dh_exit(void)
+{
+       bus_for_each_dev(&scsi_bus_type, NULL, NULL,
+                        scsi_dh_sysfs_attr_remove);
+       bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
+}
+
+module_init(scsi_dh_init);
+module_exit(scsi_dh_exit);
+
 MODULE_DESCRIPTION("SCSI device handler");
 MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
new file mode 100644 (file)
index 0000000..fcdd73f
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ * Generic SCSI-3 ALUA SCSI Device Handler
+ *
+ * Copyright (C) 2007, 2008 Hannes Reinecke, SUSE Linux Products GmbH.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+#include <scsi/scsi.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_dh.h>
+
+#define ALUA_DH_NAME "alua"
+#define ALUA_DH_VER "1.2"
+
+#define TPGS_STATE_OPTIMIZED           0x0
+#define TPGS_STATE_NONOPTIMIZED                0x1
+#define TPGS_STATE_STANDBY             0x2
+#define TPGS_STATE_UNAVAILABLE         0x3
+#define TPGS_STATE_OFFLINE             0xe
+#define TPGS_STATE_TRANSITIONING       0xf
+
+#define TPGS_SUPPORT_NONE              0x00
+#define TPGS_SUPPORT_OPTIMIZED         0x01
+#define TPGS_SUPPORT_NONOPTIMIZED      0x02
+#define TPGS_SUPPORT_STANDBY           0x04
+#define TPGS_SUPPORT_UNAVAILABLE       0x08
+#define TPGS_SUPPORT_OFFLINE           0x40
+#define TPGS_SUPPORT_TRANSITION                0x80
+
+#define TPGS_MODE_UNINITIALIZED                 -1
+#define TPGS_MODE_NONE                 0x0
+#define TPGS_MODE_IMPLICIT             0x1
+#define TPGS_MODE_EXPLICIT             0x2
+
+#define ALUA_INQUIRY_SIZE              36
+#define ALUA_FAILOVER_TIMEOUT          (60 * HZ)
+#define ALUA_FAILOVER_RETRIES          5
+
+struct alua_dh_data {
+       int                     group_id;
+       int                     rel_port;
+       int                     tpgs;
+       int                     state;
+       unsigned char           inq[ALUA_INQUIRY_SIZE];
+       unsigned char           *buff;
+       int                     bufflen;
+       unsigned char           sense[SCSI_SENSE_BUFFERSIZE];
+       int                     senselen;
+};
+
+#define ALUA_POLICY_SWITCH_CURRENT     0
+#define ALUA_POLICY_SWITCH_ALL         1
+
+static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev)
+{
+       struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
+       BUG_ON(scsi_dh_data == NULL);
+       return ((struct alua_dh_data *) scsi_dh_data->buf);
+}
+
+static int realloc_buffer(struct alua_dh_data *h, unsigned len)
+{
+       if (h->buff && h->buff != h->inq)
+               kfree(h->buff);
+
+       h->buff = kmalloc(len, GFP_NOIO);
+       if (!h->buff) {
+               h->buff = h->inq;
+               h->bufflen = ALUA_INQUIRY_SIZE;
+               return 1;
+       }
+       h->bufflen = len;
+       return 0;
+}
+
+static struct request *get_alua_req(struct scsi_device *sdev,
+                                   void *buffer, unsigned buflen, int rw)
+{
+       struct request *rq;
+       struct request_queue *q = sdev->request_queue;
+
+       rq = blk_get_request(q, rw, GFP_NOIO);
+
+       if (!rq) {
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: blk_get_request failed\n", __func__);
+               return NULL;
+       }
+
+       if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
+               blk_put_request(rq);
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: blk_rq_map_kern failed\n", __func__);
+               return NULL;
+       }
+
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
+       rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
+       rq->retries = ALUA_FAILOVER_RETRIES;
+       rq->timeout = ALUA_FAILOVER_TIMEOUT;
+
+       return rq;
+}
+
+/*
+ * submit_std_inquiry - Issue a standard INQUIRY command
+ * @sdev: sdev the command should be send to
+ */
+static int submit_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
+{
+       struct request *rq;
+       int err = SCSI_DH_RES_TEMP_UNAVAIL;
+
+       rq = get_alua_req(sdev, h->inq, ALUA_INQUIRY_SIZE, READ);
+       if (!rq)
+               goto done;
+
+       /* Prepare the command. */
+       rq->cmd[0] = INQUIRY;
+       rq->cmd[1] = 0;
+       rq->cmd[2] = 0;
+       rq->cmd[4] = ALUA_INQUIRY_SIZE;
+       rq->cmd_len = COMMAND_SIZE(INQUIRY);
+
+       rq->sense = h->sense;
+       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       rq->sense_len = h->senselen = 0;
+
+       err = blk_execute_rq(rq->q, NULL, rq, 1);
+       if (err == -EIO) {
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: std inquiry failed with %x\n",
+                           ALUA_DH_NAME, rq->errors);
+               h->senselen = rq->sense_len;
+               err = SCSI_DH_IO;
+       }
+       blk_put_request(rq);
+done:
+       return err;
+}
+
+/*
+ * submit_vpd_inquiry - Issue an INQUIRY VPD page 0x83 command
+ * @sdev: sdev the command should be sent to
+ */
+static int submit_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
+{
+       struct request *rq;
+       int err = SCSI_DH_RES_TEMP_UNAVAIL;
+
+       rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
+       if (!rq)
+               goto done;
+
+       /* Prepare the command. */
+       rq->cmd[0] = INQUIRY;
+       rq->cmd[1] = 1;
+       rq->cmd[2] = 0x83;
+       rq->cmd[4] = h->bufflen;
+       rq->cmd_len = COMMAND_SIZE(INQUIRY);
+
+       rq->sense = h->sense;
+       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       rq->sense_len = h->senselen = 0;
+
+       err = blk_execute_rq(rq->q, NULL, rq, 1);
+       if (err == -EIO) {
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: evpd inquiry failed with %x\n",
+                           ALUA_DH_NAME, rq->errors);
+               h->senselen = rq->sense_len;
+               err = SCSI_DH_IO;
+       }
+       blk_put_request(rq);
+done:
+       return err;
+}
+
+/*
+ * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
+ * @sdev: sdev the command should be sent to
+ */
+static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
+{
+       struct request *rq;
+       int err = SCSI_DH_RES_TEMP_UNAVAIL;
+
+       rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
+       if (!rq)
+               goto done;
+
+       /* Prepare the command. */
+       rq->cmd[0] = MAINTENANCE_IN;
+       rq->cmd[1] = MI_REPORT_TARGET_PGS;
+       rq->cmd[6] = (h->bufflen >> 24) & 0xff;
+       rq->cmd[7] = (h->bufflen >> 16) & 0xff;
+       rq->cmd[8] = (h->bufflen >>  8) & 0xff;
+       rq->cmd[9] = h->bufflen & 0xff;
+       rq->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
+
+       rq->sense = h->sense;
+       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       rq->sense_len = h->senselen = 0;
+
+       err = blk_execute_rq(rq->q, NULL, rq, 1);
+       if (err == -EIO) {
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: rtpg failed with %x\n",
+                           ALUA_DH_NAME, rq->errors);
+               h->senselen = rq->sense_len;
+               err = SCSI_DH_IO;
+       }
+       blk_put_request(rq);
+done:
+       return err;
+}
+
+/*
+ * submit_stpg - Issue a SET TARGET GROUP STATES command
+ * @sdev: sdev the command should be sent to
+ *
+ * Currently we're only setting the current target port group state
+ * to 'active/optimized' and let the array firmware figure out
+ * the states of the remaining groups.
+ */
+static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
+{
+       struct request *rq;
+       int err = SCSI_DH_RES_TEMP_UNAVAIL;
+       int stpg_len = 8;
+
+       /* Prepare the data buffer */
+       memset(h->buff, 0, stpg_len);
+       h->buff[4] = TPGS_STATE_OPTIMIZED & 0x0f;
+       h->buff[6] = (h->group_id >> 8) & 0x0f;
+       h->buff[7] = h->group_id & 0x0f;
+
+       rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
+       if (!rq)
+               goto done;
+
+       /* Prepare the command. */
+       rq->cmd[0] = MAINTENANCE_OUT;
+       rq->cmd[1] = MO_SET_TARGET_PGS;
+       rq->cmd[6] = (stpg_len >> 24) & 0xff;
+       rq->cmd[7] = (stpg_len >> 16) & 0xff;
+       rq->cmd[8] = (stpg_len >>  8) & 0xff;
+       rq->cmd[9] = stpg_len & 0xff;
+       rq->cmd_len = COMMAND_SIZE(MAINTENANCE_OUT);
+
+       rq->sense = h->sense;
+       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       rq->sense_len = h->senselen = 0;
+
+       err = blk_execute_rq(rq->q, NULL, rq, 1);
+       if (err == -EIO) {
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: stpg failed with %x\n",
+                           ALUA_DH_NAME, rq->errors);
+               h->senselen = rq->sense_len;
+               err = SCSI_DH_IO;
+       }
+       blk_put_request(rq);
+done:
+       return err;
+}
+
+/*
+ * alua_std_inquiry - Evaluate standard INQUIRY command
+ * @sdev: device to be checked
+ *
+ * Just extract the TPGS setting to find out if ALUA
+ * is supported.
+ */
+static int alua_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
+{
+       int err;
+
+       err = submit_std_inquiry(sdev, h);
+
+       if (err != SCSI_DH_OK)
+               return err;
+
+       /* Check TPGS setting */
+       h->tpgs = (h->inq[5] >> 4) & 0x3;
+       switch (h->tpgs) {
+       case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: supports implicit and explicit TPGS\n",
+                           ALUA_DH_NAME);
+               break;
+       case TPGS_MODE_EXPLICIT:
+               sdev_printk(KERN_INFO, sdev, "%s: supports explicit TPGS\n",
+                           ALUA_DH_NAME);
+               break;
+       case TPGS_MODE_IMPLICIT:
+               sdev_printk(KERN_INFO, sdev, "%s: supports implicit TPGS\n",
+                           ALUA_DH_NAME);
+               break;
+       default:
+               h->tpgs = TPGS_MODE_NONE;
+               sdev_printk(KERN_INFO, sdev, "%s: not supported\n",
+                           ALUA_DH_NAME);
+               err = SCSI_DH_DEV_UNSUPP;
+               break;
+       }
+
+       return err;
+}
+
+/*
+ * alua_vpd_inquiry - Evaluate INQUIRY vpd page 0x83
+ * @sdev: device to be checked
+ *
+ * Extract the relative target port and the target port group
+ * descriptor from the list of identificators.
+ */
+static int alua_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
+{
+       int len;
+       unsigned err;
+       unsigned char *d;
+
+ retry:
+       err = submit_vpd_inquiry(sdev, h);
+
+       if (err != SCSI_DH_OK)
+               return err;
+
+       /* Check if vpd page exceeds initial buffer */
+       len = (h->buff[2] << 8) + h->buff[3] + 4;
+       if (len > h->bufflen) {
+               /* Resubmit with the correct length */
+               if (realloc_buffer(h, len)) {
+                       sdev_printk(KERN_WARNING, sdev,
+                                   "%s: kmalloc buffer failed\n",
+                                   ALUA_DH_NAME);
+                       /* Temporary failure, bypass */
+                       return SCSI_DH_DEV_TEMP_BUSY;
+               }
+               goto retry;
+       }
+
+       /*
+        * Now look for the correct descriptor.
+        */
+       d = h->buff + 4;
+       while (d < h->buff + len) {
+               switch (d[1] & 0xf) {
+               case 0x4:
+                       /* Relative target port */
+                       h->rel_port = (d[6] << 8) + d[7];
+                       break;
+               case 0x5:
+                       /* Target port group */
+                       h->group_id = (d[6] << 8) + d[7];
+                       break;
+               default:
+                       break;
+               }
+               d += d[3] + 4;
+       }
+
+       if (h->group_id == -1) {
+               /*
+                * Internal error; TPGS supported but required
+                * VPD identification descriptors not present.
+                * Disable ALUA support
+                */
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: No target port descriptors found\n",
+                           ALUA_DH_NAME);
+               h->state = TPGS_STATE_OPTIMIZED;
+               h->tpgs = TPGS_MODE_NONE;
+               err = SCSI_DH_DEV_UNSUPP;
+       } else {
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: port group %02x rel port %02x\n",
+                           ALUA_DH_NAME, h->group_id, h->rel_port);
+       }
+
+       return err;
+}
+
+static char print_alua_state(int state)
+{
+       switch (state) {
+       case TPGS_STATE_OPTIMIZED:
+               return 'A';
+       case TPGS_STATE_NONOPTIMIZED:
+               return 'N';
+       case TPGS_STATE_STANDBY:
+               return 'S';
+       case TPGS_STATE_UNAVAILABLE:
+               return 'U';
+       case TPGS_STATE_OFFLINE:
+               return 'O';
+       case TPGS_STATE_TRANSITIONING:
+               return 'T';
+       default:
+               return 'X';
+       }
+}
+
+static int alua_check_sense(struct scsi_device *sdev,
+                           struct scsi_sense_hdr *sense_hdr)
+{
+       switch (sense_hdr->sense_key) {
+       case NOT_READY:
+               if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a)
+                       /*
+                        * LUN Not Accessible - ALUA state transition
+                        */
+                       return NEEDS_RETRY;
+               if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0b)
+                       /*
+                        * LUN Not Accessible -- Target port in standby state
+                        */
+                       return SUCCESS;
+               if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0c)
+                       /*
+                        * LUN Not Accessible -- Target port in unavailable state
+                        */
+                       return SUCCESS;
+               if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x12)
+                       /*
+                        * LUN Not Ready -- Offline
+                        */
+                       return SUCCESS;
+               break;
+       case UNIT_ATTENTION:
+               if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
+                       /*
+                        * Power On, Reset, or Bus Device Reset, just retry.
+                        */
+                       return NEEDS_RETRY;
+               if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) {
+                       /*
+                        * ALUA state changed
+                        */
+                       return NEEDS_RETRY;
+               }
+               if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07) {
+                       /*
+                        * Implicit ALUA state transition failed
+                        */
+                       return NEEDS_RETRY;
+               }
+               break;
+       }
+
+       return SCSI_RETURN_NOT_HANDLED;
+}
+
+/*
+ * alua_stpg - Evaluate SET TARGET GROUP STATES
+ * @sdev: the device to be evaluated
+ * @state: the new target group state
+ *
+ * Send a SET TARGET GROUP STATES command to the device.
+ * We only have to test here if we should resubmit the command;
+ * any other error is assumed as a failure.
+ */
+static int alua_stpg(struct scsi_device *sdev, int state,
+                    struct alua_dh_data *h)
+{
+       struct scsi_sense_hdr sense_hdr;
+       unsigned err;
+       int retry = ALUA_FAILOVER_RETRIES;
+
+ retry:
+       err = submit_stpg(sdev, h);
+       if (err == SCSI_DH_IO && h->senselen > 0) {
+               err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
+                                          &sense_hdr);
+               if (!err)
+                       return SCSI_DH_IO;
+               err = alua_check_sense(sdev, &sense_hdr);
+               if (retry > 0 && err == NEEDS_RETRY) {
+                       retry--;
+                       goto retry;
+               }
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: stpg sense code: %02x/%02x/%02x\n",
+                           ALUA_DH_NAME, sense_hdr.sense_key,
+                           sense_hdr.asc, sense_hdr.ascq);
+               err = SCSI_DH_IO;
+       }
+       if (err == SCSI_DH_OK) {
+               h->state = state;
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: port group %02x switched to state %c\n",
+                           ALUA_DH_NAME, h->group_id,
+                           print_alua_state(h->state) );
+       }
+       return err;
+}
+
+/*
+ * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
+ * @sdev: the device to be evaluated.
+ *
+ * Evaluate the Target Port Group State.
+ * Returns SCSI_DH_DEV_OFFLINED if the path is
+ * found to be unuseable.
+ */
+static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
+{
+       struct scsi_sense_hdr sense_hdr;
+       int len, k, off, valid_states = 0;
+       char *ucp;
+       unsigned err;
+
+ retry:
+       err = submit_rtpg(sdev, h);
+
+       if (err == SCSI_DH_IO && h->senselen > 0) {
+               err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
+                                          &sense_hdr);
+               if (!err)
+                       return SCSI_DH_IO;
+
+               err = alua_check_sense(sdev, &sense_hdr);
+               if (err == NEEDS_RETRY)
+                       goto retry;
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: rtpg sense code %02x/%02x/%02x\n",
+                           ALUA_DH_NAME, sense_hdr.sense_key,
+                           sense_hdr.asc, sense_hdr.ascq);
+               err = SCSI_DH_IO;
+       }
+       if (err != SCSI_DH_OK)
+               return err;
+
+       len = (h->buff[0] << 24) + (h->buff[1] << 16) +
+               (h->buff[2] << 8) + h->buff[3] + 4;
+
+       if (len > h->bufflen) {
+               /* Resubmit with the correct length */
+               if (realloc_buffer(h, len)) {
+                       sdev_printk(KERN_WARNING, sdev,
+                                   "%s: kmalloc buffer failed\n",__func__);
+                       /* Temporary failure, bypass */
+                       return SCSI_DH_DEV_TEMP_BUSY;
+               }
+               goto retry;
+       }
+
+       for (k = 4, ucp = h->buff + 4; k < len; k += off, ucp += off) {
+               if (h->group_id == (ucp[2] << 8) + ucp[3]) {
+                       h->state = ucp[0] & 0x0f;
+                       valid_states = ucp[1];
+               }
+               off = 8 + (ucp[7] * 4);
+       }
+
+       sdev_printk(KERN_INFO, sdev,
+                   "%s: port group %02x state %c supports %c%c%c%c%c%c\n",
+                   ALUA_DH_NAME, h->group_id, print_alua_state(h->state),
+                   valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
+                   valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
+                   valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
+                   valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
+                   valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
+                   valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
+
+       if (h->tpgs & TPGS_MODE_EXPLICIT) {
+               switch (h->state) {
+               case TPGS_STATE_TRANSITIONING:
+                       /* State transition, retry */
+                       goto retry;
+                       break;
+               case TPGS_STATE_OFFLINE:
+                       /* Path is offline, fail */
+                       err = SCSI_DH_DEV_OFFLINED;
+                       break;
+               default:
+                       break;
+               }
+       } else {
+               /* Only Implicit ALUA support */
+               if (h->state == TPGS_STATE_OPTIMIZED ||
+                   h->state == TPGS_STATE_NONOPTIMIZED ||
+                   h->state == TPGS_STATE_STANDBY)
+                       /* Useable path if active */
+                       err = SCSI_DH_OK;
+               else
+                       /* Path unuseable for unavailable/offline */
+                       err = SCSI_DH_DEV_OFFLINED;
+       }
+       return err;
+}
+
+/*
+ * alua_initialize - Initialize ALUA state
+ * @sdev: the device to be initialized
+ *
+ * For the prep_fn to work correctly we have
+ * to initialize the ALUA state for the device.
+ */
+static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
+{
+       int err;
+
+       err = alua_std_inquiry(sdev, h);
+       if (err != SCSI_DH_OK)
+               goto out;
+
+       err = alua_vpd_inquiry(sdev, h);
+       if (err != SCSI_DH_OK)
+               goto out;
+
+       err = alua_rtpg(sdev, h);
+       if (err != SCSI_DH_OK)
+               goto out;
+
+out:
+       return err;
+}
+
+/*
+ * alua_activate - activate a path
+ * @sdev: device on the path to be activated
+ *
+ * We're currently switching the port group to be activated only and
+ * let the array figure out the rest.
+ * There may be other arrays which require us to switch all port groups
+ * based on a certain policy. But until we actually encounter them it
+ * should be okay.
+ */
+static int alua_activate(struct scsi_device *sdev)
+{
+       struct alua_dh_data *h = get_alua_data(sdev);
+       int err = SCSI_DH_OK;
+
+       if (h->group_id != -1) {
+               err = alua_rtpg(sdev, h);
+               if (err != SCSI_DH_OK)
+                       goto out;
+       }
+
+       if (h->tpgs == TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED)
+               err = alua_stpg(sdev, TPGS_STATE_OPTIMIZED, h);
+
+out:
+       return err;
+}
+
+/*
+ * alua_prep_fn - request callback
+ *
+ * Fail I/O to all paths not in state
+ * active/optimized or active/non-optimized.
+ */
+static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
+{
+       struct alua_dh_data *h = get_alua_data(sdev);
+       int ret = BLKPREP_OK;
+
+       if (h->state != TPGS_STATE_OPTIMIZED &&
+           h->state != TPGS_STATE_NONOPTIMIZED) {
+               ret = BLKPREP_KILL;
+               req->cmd_flags |= REQ_QUIET;
+       }
+       return ret;
+
+}
+
+const struct scsi_dh_devlist alua_dev_list[] = {
+       {"HP", "MSA VOLUME" },
+       {"HP", "HSV101" },
+       {"HP", "HSV111" },
+       {"HP", "HSV200" },
+       {"HP", "HSV210" },
+       {"HP", "HSV300" },
+       {"IBM", "2107900" },
+       {"IBM", "2145" },
+       {"Pillar", "Axiom" },
+       {NULL, NULL}
+};
+
+static int alua_bus_attach(struct scsi_device *sdev);
+static void alua_bus_detach(struct scsi_device *sdev);
+
+static struct scsi_device_handler alua_dh = {
+       .name = ALUA_DH_NAME,
+       .module = THIS_MODULE,
+       .devlist = alua_dev_list,
+       .attach = alua_bus_attach,
+       .detach = alua_bus_detach,
+       .prep_fn = alua_prep_fn,
+       .check_sense = alua_check_sense,
+       .activate = alua_activate,
+};
+
+/*
+ * alua_bus_attach - Attach device handler
+ * @sdev: device to be attached to
+ */
+static int alua_bus_attach(struct scsi_device *sdev)
+{
+       struct scsi_dh_data *scsi_dh_data;
+       struct alua_dh_data *h;
+       unsigned long flags;
+       int err = SCSI_DH_OK;
+
+       scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+                              + sizeof(*h) , GFP_KERNEL);
+       if (!scsi_dh_data) {
+               sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
+                           ALUA_DH_NAME);
+               return -ENOMEM;
+       }
+
+       scsi_dh_data->scsi_dh = &alua_dh;
+       h = (struct alua_dh_data *) scsi_dh_data->buf;
+       h->tpgs = TPGS_MODE_UNINITIALIZED;
+       h->state = TPGS_STATE_OPTIMIZED;
+       h->group_id = -1;
+       h->rel_port = -1;
+       h->buff = h->inq;
+       h->bufflen = ALUA_INQUIRY_SIZE;
+
+       err = alua_initialize(sdev, h);
+       if (err != SCSI_DH_OK)
+               goto failed;
+
+       if (!try_module_get(THIS_MODULE))
+               goto failed;
+
+       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
+       sdev->scsi_dh_data = scsi_dh_data;
+       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+
+       return 0;
+
+failed:
+       kfree(scsi_dh_data);
+       sdev_printk(KERN_ERR, sdev, "%s: not attached\n", ALUA_DH_NAME);
+       return -EINVAL;
+}
+
+/*
+ * alua_bus_detach - Detach device handler
+ * @sdev: device to be detached from
+ */
+static void alua_bus_detach(struct scsi_device *sdev)
+{
+       struct scsi_dh_data *scsi_dh_data;
+       struct alua_dh_data *h;
+       unsigned long flags;
+
+       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
+       scsi_dh_data = sdev->scsi_dh_data;
+       sdev->scsi_dh_data = NULL;
+       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+
+       h = (struct alua_dh_data *) scsi_dh_data->buf;
+       if (h->buff && h->inq != h->buff)
+               kfree(h->buff);
+       kfree(scsi_dh_data);
+       module_put(THIS_MODULE);
+       sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", ALUA_DH_NAME);
+}
+
+static int __init alua_init(void)
+{
+       int r;
+
+       r = scsi_register_device_handler(&alua_dh);
+       if (r != 0)
+               printk(KERN_ERR "%s: Failed to register scsi device handler",
+                       ALUA_DH_NAME);
+       return r;
+}
+
+static void __exit alua_exit(void)
+{
+       scsi_unregister_device_handler(&alua_dh);
+}
+
+module_init(alua_init);
+module_exit(alua_exit);
+
+MODULE_DESCRIPTION("DM Multipath ALUA support");
+MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ALUA_DH_VER);
index f2467e936e554ea703c60621d42e3dceeaf6760f..aa46b131b20eb44eef41c17c3a086ed6935d24ed 100644 (file)
 #include <scsi/scsi_dh.h>
 #include <scsi/scsi_device.h>
 
-#define CLARIION_NAME                  "emc_clariion"
+#define CLARIION_NAME                  "emc"
 
 #define CLARIION_TRESPASS_PAGE         0x22
-#define CLARIION_BUFFER_SIZE           0x80
+#define CLARIION_BUFFER_SIZE           0xFC
 #define CLARIION_TIMEOUT               (60 * HZ)
 #define CLARIION_RETRIES               3
 #define CLARIION_UNBOUND_LU            -1
+#define CLARIION_SP_A                  0
+#define CLARIION_SP_B                  1
 
-static unsigned char long_trespass[] = {
-       0, 0, 0, 0,
-       CLARIION_TRESPASS_PAGE, /* Page code */
-       0x09,                   /* Page length - 2 */
-       0x81,                   /* Trespass code + Honor reservation bit */
-       0xff, 0xff,             /* Trespass target */
-       0, 0, 0, 0, 0, 0        /* Reserved bytes / unknown */
-};
+/* Flags */
+#define CLARIION_SHORT_TRESPASS                1
+#define CLARIION_HONOR_RESERVATIONS    2
 
-static unsigned char long_trespass_hr[] = {
-       0, 0, 0, 0,
+/* LUN states */
+#define CLARIION_LUN_UNINITIALIZED     -1
+#define CLARIION_LUN_UNBOUND           0
+#define CLARIION_LUN_BOUND             1
+#define CLARIION_LUN_OWNED             2
+
+static unsigned char long_trespass[] = {
+       0, 0, 0, 0, 0, 0, 0, 0,
        CLARIION_TRESPASS_PAGE, /* Page code */
        0x09,                   /* Page length - 2 */
-       0x01,                   /* Trespass code + Honor reservation bit */
+       0x01,                   /* Trespass code */
        0xff, 0xff,             /* Trespass target */
        0, 0, 0, 0, 0, 0        /* Reserved bytes / unknown */
 };
@@ -55,39 +58,56 @@ static unsigned char short_trespass[] = {
        0, 0, 0, 0,
        CLARIION_TRESPASS_PAGE, /* Page code */
        0x02,                   /* Page length - 2 */
-       0x81,                   /* Trespass code + Honor reservation bit */
+       0x01,                   /* Trespass code */
        0xff,                   /* Trespass target */
 };
 
-static unsigned char short_trespass_hr[] = {
-       0, 0, 0, 0,
-       CLARIION_TRESPASS_PAGE, /* Page code */
-       0x02,                   /* Page length - 2 */
-       0x01,                   /* Trespass code + Honor reservation bit */
-       0xff,                   /* Trespass target */
+static const char * lun_state[] =
+{
+    "not bound",
+    "bound",
+    "owned",
 };
 
 struct clariion_dh_data {
        /*
+        * Flags:
+        *  CLARIION_SHORT_TRESPASS
         * Use short trespass command (FC-series) or the long version
         * (default for AX/CX CLARiiON arrays).
-        */
-       unsigned short_trespass;
-       /*
+        *
+        *  CLARIION_HONOR_RESERVATIONS
         * Whether or not (default) to honor SCSI reservations when
         * initiating a switch-over.
         */
-       unsigned hr;
-       /* I/O buffer for both MODE_SELECT and INQUIRY commands. */
+       unsigned flags;
+       /*
+        * I/O buffer for both MODE_SELECT and INQUIRY commands.
+        */
        char buffer[CLARIION_BUFFER_SIZE];
        /*
         * SCSI sense buffer for commands -- assumes serial issuance
         * and completion sequence of all commands for same multipath.
         */
        unsigned char sense[SCSI_SENSE_BUFFERSIZE];
-       /* which SP (A=0,B=1,UNBOUND=-1) is dflt SP for path's mapped dev */
+       unsigned int senselen;
+       /*
+        * LUN state
+        */
+       int lun_state;
+       /*
+        * SP Port number
+        */
+       int port;
+       /*
+        * which SP (A=0,B=1,UNBOUND=-1) is the default SP for this
+        * path's mapped LUN
+        */
        int default_sp;
-       /* which SP (A=0,B=1,UNBOUND=-1) is active for path's mapped dev */
+       /*
+        * which SP (A=0,B=1,UNBOUND=-1) is the active SP for this
+        * path's mapped LUN
+        */
        int current_sp;
 };
 
@@ -102,19 +122,16 @@ static inline struct clariion_dh_data
 /*
  * Parse MODE_SELECT cmd reply.
  */
-static int trespass_endio(struct scsi_device *sdev, int result)
+static int trespass_endio(struct scsi_device *sdev, char *sense)
 {
-       int err = SCSI_DH_OK;
+       int err = SCSI_DH_IO;
        struct scsi_sense_hdr sshdr;
-       struct clariion_dh_data *csdev = get_clariion_data(sdev);
-       char *sense = csdev->sense;
 
-       if (status_byte(result) == CHECK_CONDITION &&
-           scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) {
-               sdev_printk(KERN_ERR, sdev, "Found valid sense data 0x%2x, "
+       if (!scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) {
+               sdev_printk(KERN_ERR, sdev, "%s: Found valid sense data 0x%2x, "
                            "0x%2x, 0x%2x while sending CLARiiON trespass "
-                           "command.\n", sshdr.sense_key, sshdr.asc,
-                            sshdr.ascq);
+                           "command.\n", CLARIION_NAME, sshdr.sense_key,
+                           sshdr.asc, sshdr.ascq);
 
                if ((sshdr.sense_key == 0x05) && (sshdr.asc == 0x04) &&
                     (sshdr.ascq == 0x00)) {
@@ -122,9 +139,9 @@ static int trespass_endio(struct scsi_device *sdev, int result)
                         * Array based copy in progress -- do not send
                         * mode_select or copy will be aborted mid-stream.
                         */
-                       sdev_printk(KERN_INFO, sdev, "Array Based Copy in "
+                       sdev_printk(KERN_INFO, sdev, "%s: Array Based Copy in "
                                    "progress while sending CLARiiON trespass "
-                                   "command.\n");
+                                   "command.\n", CLARIION_NAME);
                        err = SCSI_DH_DEV_TEMP_BUSY;
                } else if ((sshdr.sense_key == 0x02) && (sshdr.asc == 0x04) &&
                            (sshdr.ascq == 0x03)) {
@@ -132,160 +149,153 @@ static int trespass_endio(struct scsi_device *sdev, int result)
                         * LUN Not Ready - Manual Intervention Required
                         * indicates in-progress ucode upgrade (NDU).
                         */
-                       sdev_printk(KERN_INFO, sdev, "Detected in-progress "
+                       sdev_printk(KERN_INFO, sdev, "%s: Detected in-progress "
                                    "ucode upgrade NDU operation while sending "
-                                   "CLARiiON trespass command.\n");
+                                   "CLARiiON trespass command.\n", CLARIION_NAME);
                        err = SCSI_DH_DEV_TEMP_BUSY;
                } else
                        err = SCSI_DH_DEV_FAILED;
-       } else if (result) {
-               sdev_printk(KERN_ERR, sdev, "Error 0x%x while sending "
-                           "CLARiiON trespass command.\n", result);
-               err = SCSI_DH_IO;
+       } else {
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: failed to send MODE SELECT, no sense available\n",
+                           CLARIION_NAME);
        }
-
        return err;
 }
 
-static int parse_sp_info_reply(struct scsi_device *sdev, int result,
-               int *default_sp, int *current_sp, int *new_current_sp)
+static int parse_sp_info_reply(struct scsi_device *sdev,
+                              struct clariion_dh_data *csdev)
 {
        int err = SCSI_DH_OK;
-       struct clariion_dh_data *csdev = get_clariion_data(sdev);
 
-       if (result == 0) {
-               /* check for in-progress ucode upgrade (NDU) */
-               if (csdev->buffer[48] != 0) {
-                       sdev_printk(KERN_NOTICE, sdev, "Detected in-progress "
-                              "ucode upgrade NDU operation while finding "
-                              "current active SP.");
-                       err = SCSI_DH_DEV_TEMP_BUSY;
-               } else {
-                       *default_sp = csdev->buffer[5];
-
-                       if (csdev->buffer[4] == 2)
-                               /* SP for path is current */
-                               *current_sp = csdev->buffer[8];
-                       else {
-                               if (csdev->buffer[4] == 1)
-                                       /* SP for this path is NOT current */
-                                       if (csdev->buffer[8] == 0)
-                                               *current_sp = 1;
-                                       else
-                                               *current_sp = 0;
-                               else
-                                       /* unbound LU or LUNZ */
-                                       *current_sp = CLARIION_UNBOUND_LU;
-                       }
-                       *new_current_sp =  csdev->buffer[8];
-               }
-       } else {
-               struct scsi_sense_hdr sshdr;
-
-               err = SCSI_DH_IO;
-
-               if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
-                                                          &sshdr))
-                       sdev_printk(KERN_ERR, sdev, "Found valid sense data "
-                             "0x%2x, 0x%2x, 0x%2x while finding current "
-                             "active SP.", sshdr.sense_key, sshdr.asc,
-                             sshdr.ascq);
-               else
-                       sdev_printk(KERN_ERR, sdev, "Error 0x%x finding "
-                             "current active SP.", result);
+       /* check for in-progress ucode upgrade (NDU) */
+       if (csdev->buffer[48] != 0) {
+               sdev_printk(KERN_NOTICE, sdev, "%s: Detected in-progress "
+                           "ucode upgrade NDU operation while finding "
+                           "current active SP.", CLARIION_NAME);
+               err = SCSI_DH_DEV_TEMP_BUSY;
+               goto out;
+       }
+       if (csdev->buffer[4] < 0 || csdev->buffer[4] > 2) {
+               /* Invalid buffer format */
+               sdev_printk(KERN_NOTICE, sdev,
+                           "%s: invalid VPD page 0xC0 format\n",
+                           CLARIION_NAME);
+               err = SCSI_DH_NOSYS;
+               goto out;
+       }
+       switch (csdev->buffer[28] & 0x0f) {
+       case 6:
+               sdev_printk(KERN_NOTICE, sdev,
+                           "%s: ALUA failover mode detected\n",
+                           CLARIION_NAME);
+               break;
+       case 4:
+               /* Linux failover */
+               break;
+       default:
+               sdev_printk(KERN_WARNING, sdev,
+                           "%s: Invalid failover mode %d\n",
+                           CLARIION_NAME, csdev->buffer[28] & 0x0f);
+               err = SCSI_DH_NOSYS;
+               goto out;
        }
 
+       csdev->default_sp = csdev->buffer[5];
+       csdev->lun_state = csdev->buffer[4];
+       csdev->current_sp = csdev->buffer[8];
+       csdev->port = csdev->buffer[7];
+
+out:
        return err;
 }
 
-static int sp_info_endio(struct scsi_device *sdev, int result,
-                                       int mode_select_sent, int *done)
+#define emc_default_str "FC (Legacy)"
+
+static char * parse_sp_model(struct scsi_device *sdev, unsigned char *buffer)
 {
-       struct clariion_dh_data *csdev = get_clariion_data(sdev);
-       int err_flags, default_sp, current_sp, new_current_sp;
+       unsigned char len = buffer[4] + 5;
+       char *sp_model = NULL;
+       unsigned char sp_len, serial_len;
+
+       if (len < 160) {
+               sdev_printk(KERN_WARNING, sdev,
+                           "%s: Invalid information section length %d\n",
+                           CLARIION_NAME, len);
+               /* Check for old FC arrays */
+               if (!strncmp(buffer + 8, "DGC", 3)) {
+                       /* Old FC array, not supporting extended information */
+                       sp_model = emc_default_str;
+               }
+               goto out;
+       }
 
-       err_flags = parse_sp_info_reply(sdev, result, &default_sp,
-                                            &current_sp, &new_current_sp);
+       /*
+        * Parse extended information for SP model number
+        */
+       serial_len = buffer[160];
+       if (serial_len == 0 || serial_len + 161 > len) {
+               sdev_printk(KERN_WARNING, sdev,
+                           "%s: Invalid array serial number length %d\n",
+                           CLARIION_NAME, serial_len);
+               goto out;
+       }
+       sp_len = buffer[99];
+       if (sp_len == 0 || serial_len + sp_len + 161 > len) {
+               sdev_printk(KERN_WARNING, sdev,
+                           "%s: Invalid model number length %d\n",
+                           CLARIION_NAME, sp_len);
+               goto out;
+       }
+       sp_model = &buffer[serial_len + 161];
+       /* Strip whitespace at the end */
+       while (sp_len > 1 && sp_model[sp_len - 1] == ' ')
+               sp_len--;
 
-       if (err_flags != SCSI_DH_OK)
-               goto done;
+       sp_model[sp_len] = '\0';
 
-       if (mode_select_sent) {
-               csdev->default_sp = default_sp;
-               csdev->current_sp = current_sp;
-       } else {
-               /*
-                * Issue the actual module_selec request IFF either
-                * (1) we do not know the identity of the current SP OR
-                * (2) what we think we know is actually correct.
-                */
-               if ((current_sp != CLARIION_UNBOUND_LU) &&
-                   (new_current_sp != current_sp)) {
-
-                       csdev->default_sp = default_sp;
-                       csdev->current_sp = current_sp;
-
-                       sdev_printk(KERN_INFO, sdev, "Ignoring path group "
-                              "switch-over command for CLARiiON SP%s since "
-                              " mapped device is already initialized.",
-                              current_sp ? "B" : "A");
-                       if (done)
-                               *done = 1; /* as good as doing it */
-               }
-       }
-done:
-       return err_flags;
+out:
+       return sp_model;
 }
 
 /*
-* Get block request for REQ_BLOCK_PC command issued to path.  Currently
-* limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
-*
-* Uses data and sense buffers in hardware handler context structure and
-* assumes serial servicing of commands, both issuance and completion.
-*/
-static struct request *get_req(struct scsi_device *sdev, int cmd)
+ * Get block request for REQ_BLOCK_PC command issued to path.  Currently
+ * limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
+ *
+ * Uses data and sense buffers in hardware handler context structure and
+ * assumes serial servicing of commands, both issuance and completion.
+ */
+static struct request *get_req(struct scsi_device *sdev, int cmd,
+                               unsigned char *buffer)
 {
-       struct clariion_dh_data *csdev = get_clariion_data(sdev);
        struct request *rq;
-       unsigned char *page22;
        int len = 0;
 
        rq = blk_get_request(sdev->request_queue,
-                       (cmd == MODE_SELECT) ? WRITE : READ, GFP_ATOMIC);
+                       (cmd == MODE_SELECT) ? WRITE : READ, GFP_NOIO);
        if (!rq) {
                sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed");
                return NULL;
        }
 
-       memset(&rq->cmd, 0, BLK_MAX_CDB);
+       memset(rq->cmd, 0, BLK_MAX_CDB);
+       rq->cmd_len = COMMAND_SIZE(cmd);
        rq->cmd[0] = cmd;
-       rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
 
        switch (cmd) {
        case MODE_SELECT:
-               if (csdev->short_trespass) {
-                       page22 = csdev->hr ? short_trespass_hr : short_trespass;
-                       len = sizeof(short_trespass);
-               } else {
-                       page22 = csdev->hr ? long_trespass_hr : long_trespass;
-                       len = sizeof(long_trespass);
-               }
-               /*
-                * Can't DMA from kernel BSS -- must copy selected trespass
-                * command mode page contents to context buffer which is
-                * allocated by kmalloc.
-                */
-               BUG_ON((len > CLARIION_BUFFER_SIZE));
-               memcpy(csdev->buffer, page22, len);
+               len = sizeof(short_trespass);
+               rq->cmd_flags |= REQ_RW;
+               rq->cmd[1] = 0x10;
+               break;
+       case MODE_SELECT_10:
+               len = sizeof(long_trespass);
                rq->cmd_flags |= REQ_RW;
                rq->cmd[1] = 0x10;
                break;
        case INQUIRY:
-               rq->cmd[1] = 0x1;
-               rq->cmd[2] = 0xC0;
                len = CLARIION_BUFFER_SIZE;
-               memset(csdev->buffer, 0, CLARIION_BUFFER_SIZE);
+               memset(buffer, 0, len);
                break;
        default:
                BUG_ON(1);
@@ -298,47 +308,94 @@ static struct request *get_req(struct scsi_device *sdev, int cmd)
        rq->timeout = CLARIION_TIMEOUT;
        rq->retries = CLARIION_RETRIES;
 
-       rq->sense = csdev->sense;
-       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-       rq->sense_len = 0;
-
-       if (blk_rq_map_kern(sdev->request_queue, rq, csdev->buffer,
-                                                       len, GFP_ATOMIC)) {
-               __blk_put_request(rq->q, rq);
+       if (blk_rq_map_kern(rq->q, rq, buffer, len, GFP_NOIO)) {
+               blk_put_request(rq);
                return NULL;
        }
 
        return rq;
 }
 
-static int send_cmd(struct scsi_device *sdev, int cmd)
+static int send_inquiry_cmd(struct scsi_device *sdev, int page,
+                           struct clariion_dh_data *csdev)
 {
-       struct request *rq = get_req(sdev, cmd);
+       struct request *rq = get_req(sdev, INQUIRY, csdev->buffer);
+       int err;
 
        if (!rq)
                return SCSI_DH_RES_TEMP_UNAVAIL;
 
-       return blk_execute_rq(sdev->request_queue, NULL, rq, 1);
+       rq->sense = csdev->sense;
+       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       rq->sense_len = csdev->senselen = 0;
+
+       rq->cmd[0] = INQUIRY;
+       if (page != 0) {
+               rq->cmd[1] = 1;
+               rq->cmd[2] = page;
+       }
+       err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
+       if (err == -EIO) {
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: failed to send %s INQUIRY: %x\n",
+                           CLARIION_NAME, page?"EVPD":"standard",
+                           rq->errors);
+               csdev->senselen = rq->sense_len;
+               err = SCSI_DH_IO;
+       }
+
+       blk_put_request(rq);
+
+       return err;
 }
 
-static int clariion_activate(struct scsi_device *sdev)
+static int send_trespass_cmd(struct scsi_device *sdev,
+                           struct clariion_dh_data *csdev)
 {
-       int result, done = 0;
+       struct request *rq;
+       unsigned char *page22;
+       int err, len, cmd;
+
+       if (csdev->flags & CLARIION_SHORT_TRESPASS) {
+               page22 = short_trespass;
+               if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS))
+                       /* Set Honor Reservations bit */
+                       page22[6] |= 0x80;
+               len = sizeof(short_trespass);
+               cmd = MODE_SELECT;
+       } else {
+               page22 = long_trespass;
+               if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS))
+                       /* Set Honor Reservations bit */
+                       page22[10] |= 0x80;
+               len = sizeof(long_trespass);
+               cmd = MODE_SELECT_10;
+       }
+       BUG_ON((len > CLARIION_BUFFER_SIZE));
+       memcpy(csdev->buffer, page22, len);
 
-       result = send_cmd(sdev, INQUIRY);
-       result = sp_info_endio(sdev, result, 0, &done);
-       if (result || done)
-               goto done;
+       rq = get_req(sdev, cmd, csdev->buffer);
+       if (!rq)
+               return SCSI_DH_RES_TEMP_UNAVAIL;
 
-       result = send_cmd(sdev, MODE_SELECT);
-       result = trespass_endio(sdev, result);
-       if (result)
-               goto done;
+       rq->sense = csdev->sense;
+       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       rq->sense_len = csdev->senselen = 0;
 
-       result = send_cmd(sdev, INQUIRY);
-       result = sp_info_endio(sdev, result, 1, NULL);
-done:
-       return result;
+       err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
+       if (err == -EIO) {
+               if (rq->sense_len) {
+                       err = trespass_endio(sdev, csdev->sense);
+               } else {
+                       sdev_printk(KERN_INFO, sdev,
+                                   "%s: failed to send MODE SELECT: %x\n",
+                                   CLARIION_NAME, rq->errors);
+               }
+       }
+
+       blk_put_request(rq);
+
+       return err;
 }
 
 static int clariion_check_sense(struct scsi_device *sdev,
@@ -386,99 +443,215 @@ static int clariion_check_sense(struct scsi_device *sdev,
                break;
        }
 
-       /* success just means we do not care what scsi-ml does */
-       return SUCCESS;
+       return SCSI_RETURN_NOT_HANDLED;
+}
+
+static int clariion_prep_fn(struct scsi_device *sdev, struct request *req)
+{
+       struct clariion_dh_data *h = get_clariion_data(sdev);
+       int ret = BLKPREP_OK;
+
+       if (h->lun_state != CLARIION_LUN_OWNED) {
+               ret = BLKPREP_KILL;
+               req->cmd_flags |= REQ_QUIET;
+       }
+       return ret;
+
+}
+
+static int clariion_std_inquiry(struct scsi_device *sdev,
+                               struct clariion_dh_data *csdev)
+{
+       int err;
+       char *sp_model;
+
+       err = send_inquiry_cmd(sdev, 0, csdev);
+       if (err != SCSI_DH_OK && csdev->senselen) {
+               struct scsi_sense_hdr sshdr;
+
+               if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
+                                        &sshdr)) {
+                       sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code "
+                                   "%02x/%02x/%02x\n", CLARIION_NAME,
+                                   sshdr.sense_key, sshdr.asc, sshdr.ascq);
+               }
+               err = SCSI_DH_IO;
+               goto out;
+       }
+
+       sp_model = parse_sp_model(sdev, csdev->buffer);
+       if (!sp_model) {
+               err = SCSI_DH_DEV_UNSUPP;
+               goto out;
+       }
+
+       /*
+        * FC Series arrays do not support long trespass
+        */
+       if (!strlen(sp_model) || !strncmp(sp_model, "FC",2))
+               csdev->flags |= CLARIION_SHORT_TRESPASS;
+
+       sdev_printk(KERN_INFO, sdev,
+                   "%s: detected Clariion %s, flags %x\n",
+                   CLARIION_NAME, sp_model, csdev->flags);
+out:
+       return err;
 }
 
-static const struct {
-       char *vendor;
-       char *model;
-} clariion_dev_list[] = {
+static int clariion_send_inquiry(struct scsi_device *sdev,
+                                struct clariion_dh_data *csdev)
+{
+       int err, retry = CLARIION_RETRIES;
+
+retry:
+       err = send_inquiry_cmd(sdev, 0xC0, csdev);
+       if (err != SCSI_DH_OK && csdev->senselen) {
+               struct scsi_sense_hdr sshdr;
+
+               err = scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
+                                          &sshdr);
+               if (!err)
+                       return SCSI_DH_IO;
+
+               err = clariion_check_sense(sdev, &sshdr);
+               if (retry > 0 && err == NEEDS_RETRY) {
+                       retry--;
+                       goto retry;
+               }
+               sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code "
+                           "%02x/%02x/%02x\n", CLARIION_NAME,
+                             sshdr.sense_key, sshdr.asc, sshdr.ascq);
+               err = SCSI_DH_IO;
+       } else {
+               err = parse_sp_info_reply(sdev, csdev);
+       }
+       return err;
+}
+
+static int clariion_activate(struct scsi_device *sdev)
+{
+       struct clariion_dh_data *csdev = get_clariion_data(sdev);
+       int result;
+
+       result = clariion_send_inquiry(sdev, csdev);
+       if (result != SCSI_DH_OK)
+               goto done;
+
+       if (csdev->lun_state == CLARIION_LUN_OWNED)
+               goto done;
+
+       result = send_trespass_cmd(sdev, csdev);
+       if (result != SCSI_DH_OK)
+               goto done;
+       sdev_printk(KERN_INFO, sdev,"%s: %s trespass command sent\n",
+                   CLARIION_NAME,
+                   csdev->flags&CLARIION_SHORT_TRESPASS?"short":"long" );
+
+       /* Update status */
+       result = clariion_send_inquiry(sdev, csdev);
+       if (result != SCSI_DH_OK)
+               goto done;
+
+done:
+       sdev_printk(KERN_INFO, sdev,
+                   "%s: at SP %c Port %d (%s, default SP %c)\n",
+                   CLARIION_NAME, csdev->current_sp + 'A',
+                   csdev->port, lun_state[csdev->lun_state],
+                   csdev->default_sp + 'A');
+
+       return result;
+}
+
+const struct scsi_dh_devlist clariion_dev_list[] = {
        {"DGC", "RAID"},
        {"DGC", "DISK"},
+       {"DGC", "VRAID"},
        {NULL, NULL},
 };
 
-static int clariion_bus_notify(struct notifier_block *, unsigned long, void *);
+static int clariion_bus_attach(struct scsi_device *sdev);
+static void clariion_bus_detach(struct scsi_device *sdev);
 
 static struct scsi_device_handler clariion_dh = {
        .name           = CLARIION_NAME,
        .module         = THIS_MODULE,
-       .nb.notifier_call = clariion_bus_notify,
+       .devlist        = clariion_dev_list,
+       .attach         = clariion_bus_attach,
+       .detach         = clariion_bus_detach,
        .check_sense    = clariion_check_sense,
        .activate       = clariion_activate,
+       .prep_fn        = clariion_prep_fn,
 };
 
 /*
  * TODO: need some interface so we can set trespass values
  */
-static int clariion_bus_notify(struct notifier_block *nb,
-                               unsigned long action, void *data)
+static int clariion_bus_attach(struct scsi_device *sdev)
 {
-       struct device *dev = data;
-       struct scsi_device *sdev;
        struct scsi_dh_data *scsi_dh_data;
        struct clariion_dh_data *h;
-       int i, found = 0;
        unsigned long flags;
+       int err;
 
-       if (!scsi_is_sdev_device(dev))
-               return 0;
+       scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+                              + sizeof(*h) , GFP_KERNEL);
+       if (!scsi_dh_data) {
+               sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
+                           CLARIION_NAME);
+               return -ENOMEM;
+       }
 
-       sdev = to_scsi_device(dev);
+       scsi_dh_data->scsi_dh = &clariion_dh;
+       h = (struct clariion_dh_data *) scsi_dh_data->buf;
+       h->lun_state = CLARIION_LUN_UNINITIALIZED;
+       h->default_sp = CLARIION_UNBOUND_LU;
+       h->current_sp = CLARIION_UNBOUND_LU;
 
-       if (action == BUS_NOTIFY_ADD_DEVICE) {
-               for (i = 0; clariion_dev_list[i].vendor; i++) {
-                       if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor,
-                                    strlen(clariion_dev_list[i].vendor)) &&
-                           !strncmp(sdev->model, clariion_dev_list[i].model,
-                                    strlen(clariion_dev_list[i].model))) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found)
-                       goto out;
-
-               scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
-                               + sizeof(*h) , GFP_KERNEL);
-               if (!scsi_dh_data) {
-                       sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
-                                   CLARIION_NAME);
-                       goto out;
-               }
+       err = clariion_std_inquiry(sdev, h);
+       if (err != SCSI_DH_OK)
+               goto failed;
 
-               scsi_dh_data->scsi_dh = &clariion_dh;
-               h = (struct clariion_dh_data *) scsi_dh_data->buf;
-               h->default_sp = CLARIION_UNBOUND_LU;
-               h->current_sp = CLARIION_UNBOUND_LU;
+       err = clariion_send_inquiry(sdev, h);
+       if (err != SCSI_DH_OK)
+               goto failed;
 
-               spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-               sdev->scsi_dh_data = scsi_dh_data;
-               spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+       if (!try_module_get(THIS_MODULE))
+               goto failed;
 
-               sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", CLARIION_NAME);
-               try_module_get(THIS_MODULE);
+       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
+       sdev->scsi_dh_data = scsi_dh_data;
+       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
 
-       } else if (action == BUS_NOTIFY_DEL_DEVICE) {
-               if (sdev->scsi_dh_data == NULL ||
-                               sdev->scsi_dh_data->scsi_dh != &clariion_dh)
-                       goto out;
+       sdev_printk(KERN_INFO, sdev,
+                   "%s: connected to SP %c Port %d (%s, default SP %c)\n",
+                   CLARIION_NAME, h->current_sp + 'A',
+                   h->port, lun_state[h->lun_state],
+                   h->default_sp + 'A');
 
-               spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-               scsi_dh_data = sdev->scsi_dh_data;
-               sdev->scsi_dh_data = NULL;
-               spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+       return 0;
 
-               sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n",
-                           CLARIION_NAME);
+failed:
+       kfree(scsi_dh_data);
+       sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
+                   CLARIION_NAME);
+       return -EINVAL;
+}
 
-               kfree(scsi_dh_data);
-               module_put(THIS_MODULE);
-       }
+static void clariion_bus_detach(struct scsi_device *sdev)
+{
+       struct scsi_dh_data *scsi_dh_data;
+       unsigned long flags;
 
-out:
-       return 0;
+       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
+       scsi_dh_data = sdev->scsi_dh_data;
+       sdev->scsi_dh_data = NULL;
+       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+
+       sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n",
+                   CLARIION_NAME);
+
+       kfree(scsi_dh_data);
+       module_put(THIS_MODULE);
 }
 
 static int __init clariion_init(void)
@@ -487,7 +660,8 @@ static int __init clariion_init(void)
 
        r = scsi_register_device_handler(&clariion_dh);
        if (r != 0)
-               printk(KERN_ERR "Failed to register scsi device handler.");
+               printk(KERN_ERR "%s: Failed to register scsi device handler.",
+                       CLARIION_NAME);
        return r;
 }
 
index ae6be87d6a8327d8b523236c0d3aadf1622f63c1..9c7a1f8ebb722df09e88c67b49235448ef006a60 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
  * Copyright (C) 2006 Mike Christie
+ * Copyright (C) 2008 Hannes Reinecke <hare@suse.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
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_dh.h>
 
-#define HP_SW_NAME     "hp_sw"
+#define HP_SW_NAME                     "hp_sw"
 
-#define HP_SW_TIMEOUT (60 * HZ)
-#define HP_SW_RETRIES 3
+#define HP_SW_TIMEOUT                  (60 * HZ)
+#define HP_SW_RETRIES                  3
+
+#define HP_SW_PATH_UNINITIALIZED       -1
+#define HP_SW_PATH_ACTIVE              0
+#define HP_SW_PATH_PASSIVE             1
 
 struct hp_sw_dh_data {
        unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+       int path_state;
        int retries;
 };
 
@@ -42,51 +48,161 @@ static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev)
        return ((struct hp_sw_dh_data *) scsi_dh_data->buf);
 }
 
-static int hp_sw_done(struct scsi_device *sdev)
+/*
+ * tur_done - Handle TEST UNIT READY return status
+ * @sdev: sdev the command has been sent to
+ * @errors: blk error code
+ *
+ * Returns SCSI_DH_DEV_OFFLINED if the sdev is on the passive path
+ */
+static int tur_done(struct scsi_device *sdev, unsigned char *sense)
 {
-       struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
        struct scsi_sense_hdr sshdr;
-       int rc;
-
-       sdev_printk(KERN_INFO, sdev, "hp_sw_done\n");
+       int ret;
 
-       rc = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, &sshdr);
-       if (!rc)
+       ret = scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr);
+       if (!ret) {
+               sdev_printk(KERN_WARNING, sdev,
+                           "%s: sending tur failed, no sense available\n",
+                           HP_SW_NAME);
+               ret = SCSI_DH_IO;
                goto done;
+       }
        switch (sshdr.sense_key) {
+       case UNIT_ATTENTION:
+               ret = SCSI_DH_IMM_RETRY;
+               break;
        case NOT_READY:
-               if ((sshdr.asc == 0x04) && (sshdr.ascq == 3)) {
-                       rc = SCSI_DH_RETRY;
-                       h->retries++;
+               if ((sshdr.asc == 0x04) && (sshdr.ascq == 2)) {
+                       /*
+                        * LUN not ready - Initialization command required
+                        *
+                        * This is the passive path
+                        */
+                       ret = SCSI_DH_DEV_OFFLINED;
                        break;
                }
-               /* fall through */
+               /* Fallthrough */
        default:
-               h->retries++;
-               rc = SCSI_DH_IMM_RETRY;
+               sdev_printk(KERN_WARNING, sdev,
+                          "%s: sending tur failed, sense %x/%x/%x\n",
+                          HP_SW_NAME, sshdr.sense_key, sshdr.asc,
+                          sshdr.ascq);
+               break;
        }
 
 done:
-       if (rc == SCSI_DH_OK || rc == SCSI_DH_IO)
-               h->retries = 0;
-       else if (h->retries > HP_SW_RETRIES) {
-               h->retries = 0;
+       return ret;
+}
+
+/*
+ * hp_sw_tur - Send TEST UNIT READY
+ * @sdev: sdev command should be sent to
+ *
+ * Use the TEST UNIT READY command to determine
+ * the path state.
+ */
+static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
+{
+       struct request *req;
+       int ret;
+
+       req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
+       if (!req)
+               return SCSI_DH_RES_TEMP_UNAVAIL;
+
+       req->cmd_type = REQ_TYPE_BLOCK_PC;
+       req->cmd_flags |= REQ_FAILFAST;
+       req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
+       memset(req->cmd, 0, MAX_COMMAND_SIZE);
+       req->cmd[0] = TEST_UNIT_READY;
+       req->timeout = HP_SW_TIMEOUT;
+       req->sense = h->sense;
+       memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       req->sense_len = 0;
+
+retry:
+       ret = blk_execute_rq(req->q, NULL, req, 1);
+       if (ret == -EIO) {
+               if (req->sense_len > 0) {
+                       ret = tur_done(sdev, h->sense);
+               } else {
+                       sdev_printk(KERN_WARNING, sdev,
+                                   "%s: sending tur failed with %x\n",
+                                   HP_SW_NAME, req->errors);
+                       ret = SCSI_DH_IO;
+               }
+       } else {
+               h->path_state = HP_SW_PATH_ACTIVE;
+               ret = SCSI_DH_OK;
+       }
+       if (ret == SCSI_DH_IMM_RETRY)
+               goto retry;
+       if (ret == SCSI_DH_DEV_OFFLINED) {
+               h->path_state = HP_SW_PATH_PASSIVE;
+               ret = SCSI_DH_OK;
+       }
+
+       blk_put_request(req);
+
+       return ret;
+}
+
+/*
+ * start_done - Handle START STOP UNIT return status
+ * @sdev: sdev the command has been sent to
+ * @errors: blk error code
+ */
+static int start_done(struct scsi_device *sdev, unsigned char *sense)
+{
+       struct scsi_sense_hdr sshdr;
+       int rc;
+
+       rc = scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr);
+       if (!rc) {
+               sdev_printk(KERN_WARNING, sdev,
+                           "%s: sending start_stop_unit failed, "
+                           "no sense available\n",
+                           HP_SW_NAME);
+               return SCSI_DH_IO;
+       }
+       switch (sshdr.sense_key) {
+       case NOT_READY:
+               if ((sshdr.asc == 0x04) && (sshdr.ascq == 3)) {
+                       /*
+                        * LUN not ready - manual intervention required
+                        *
+                        * Switch-over in progress, retry.
+                        */
+                       rc = SCSI_DH_RETRY;
+                       break;
+               }
+               /* fall through */
+       default:
+               sdev_printk(KERN_WARNING, sdev,
+                          "%s: sending start_stop_unit failed, sense %x/%x/%x\n",
+                          HP_SW_NAME, sshdr.sense_key, sshdr.asc,
+                          sshdr.ascq);
                rc = SCSI_DH_IO;
        }
+
        return rc;
 }
 
-static int hp_sw_activate(struct scsi_device *sdev)
+/*
+ * hp_sw_start_stop - Send START STOP UNIT command
+ * @sdev: sdev command should be sent to
+ *
+ * Sending START STOP UNIT activates the SP.
+ */
+static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
 {
-       struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
        struct request *req;
-       int ret = SCSI_DH_RES_TEMP_UNAVAIL;
+       int ret, retry;
 
-       req = blk_get_request(sdev->request_queue, WRITE, GFP_ATOMIC);
+       req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
        if (!req)
-               goto done;
-
-       sdev_printk(KERN_INFO, sdev, "sending START_STOP.");
+               return SCSI_DH_RES_TEMP_UNAVAIL;
 
        req->cmd_type = REQ_TYPE_BLOCK_PC;
        req->cmd_flags |= REQ_FAILFAST;
@@ -98,95 +214,153 @@ static int hp_sw_activate(struct scsi_device *sdev)
        req->sense = h->sense;
        memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
        req->sense_len = 0;
+       retry = h->retries;
 
+retry:
        ret = blk_execute_rq(req->q, NULL, req, 1);
-       if (!ret) /* SUCCESS */
-               ret = hp_sw_done(sdev);
-       else
+       if (ret == -EIO) {
+               if (req->sense_len > 0) {
+                       ret = start_done(sdev, h->sense);
+               } else {
+                       sdev_printk(KERN_WARNING, sdev,
+                                   "%s: sending start_stop_unit failed with %x\n",
+                                   HP_SW_NAME, req->errors);
+                       ret = SCSI_DH_IO;
+               }
+       } else
+               ret = SCSI_DH_OK;
+
+       if (ret == SCSI_DH_RETRY) {
+               if (--retry)
+                       goto retry;
                ret = SCSI_DH_IO;
-done:
+       }
+
+       blk_put_request(req);
+
+       return ret;
+}
+
+static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req)
+{
+       struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
+       int ret = BLKPREP_OK;
+
+       if (h->path_state != HP_SW_PATH_ACTIVE) {
+               ret = BLKPREP_KILL;
+               req->cmd_flags |= REQ_QUIET;
+       }
+       return ret;
+
+}
+
+/*
+ * hp_sw_activate - Activate a path
+ * @sdev: sdev on the path to be activated
+ *
+ * The HP Active/Passive firmware is pretty simple;
+ * the passive path reports NOT READY with sense codes
+ * 0x04/0x02; a START STOP UNIT command will then
+ * activate the passive path (and deactivate the
+ * previously active one).
+ */
+static int hp_sw_activate(struct scsi_device *sdev)
+{
+       int ret = SCSI_DH_OK;
+       struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
+
+       ret = hp_sw_tur(sdev, h);
+
+       if (ret == SCSI_DH_OK && h->path_state == HP_SW_PATH_PASSIVE) {
+               ret = hp_sw_start_stop(sdev, h);
+               if (ret == SCSI_DH_OK)
+                       sdev_printk(KERN_INFO, sdev,
+                                   "%s: activated path\n",
+                                   HP_SW_NAME);
+       }
+
        return ret;
 }
 
-static const struct {
-       char *vendor;
-       char *model;
-} hp_sw_dh_data_list[] = {
-       {"COMPAQ", "MSA"},
-       {"HP", "HSV"},
+const struct scsi_dh_devlist hp_sw_dh_data_list[] = {
+       {"COMPAQ", "MSA1000 VOLUME"},
+       {"COMPAQ", "HSV110"},
+       {"HP", "HSV100"},
        {"DEC", "HSG80"},
        {NULL, NULL},
 };
 
-static int hp_sw_bus_notify(struct notifier_block *, unsigned long, void *);
+static int hp_sw_bus_attach(struct scsi_device *sdev);
+static void hp_sw_bus_detach(struct scsi_device *sdev);
 
 static struct scsi_device_handler hp_sw_dh = {
        .name           = HP_SW_NAME,
        .module         = THIS_MODULE,
-       .nb.notifier_call = hp_sw_bus_notify,
+       .devlist        = hp_sw_dh_data_list,
+       .attach         = hp_sw_bus_attach,
+       .detach         = hp_sw_bus_detach,
        .activate       = hp_sw_activate,
+       .prep_fn        = hp_sw_prep_fn,
 };
 
-static int hp_sw_bus_notify(struct notifier_block *nb,
-                           unsigned long action, void *data)
+static int hp_sw_bus_attach(struct scsi_device *sdev)
 {
-       struct device *dev = data;
-       struct scsi_device *sdev;
        struct scsi_dh_data *scsi_dh_data;
-       int i, found = 0;
+       struct hp_sw_dh_data *h;
        unsigned long flags;
+       int ret;
 
-       if (!scsi_is_sdev_device(dev))
+       scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+                              + sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
+       if (!scsi_dh_data) {
+               sdev_printk(KERN_ERR, sdev, "%s: Attach Failed\n",
+                           HP_SW_NAME);
                return 0;
+       }
 
-       sdev = to_scsi_device(dev);
-
-       if (action == BUS_NOTIFY_ADD_DEVICE) {
-               for (i = 0; hp_sw_dh_data_list[i].vendor; i++) {
-                       if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor,
-                                    strlen(hp_sw_dh_data_list[i].vendor)) &&
-                           !strncmp(sdev->model, hp_sw_dh_data_list[i].model,
-                                    strlen(hp_sw_dh_data_list[i].model))) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found)
-                       goto out;
+       scsi_dh_data->scsi_dh = &hp_sw_dh;
+       h = (struct hp_sw_dh_data *) scsi_dh_data->buf;
+       h->path_state = HP_SW_PATH_UNINITIALIZED;
+       h->retries = HP_SW_RETRIES;
 
-               scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
-                               + sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
-               if (!scsi_dh_data) {
-                       sdev_printk(KERN_ERR, sdev, "Attach Failed %s.\n",
-                                   HP_SW_NAME);
-                       goto out;
-               }
+       ret = hp_sw_tur(sdev, h);
+       if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED)
+               goto failed;
 
-               scsi_dh_data->scsi_dh = &hp_sw_dh;
-               spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-               sdev->scsi_dh_data = scsi_dh_data;
-               spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-               try_module_get(THIS_MODULE);
+       if (!try_module_get(THIS_MODULE))
+               goto failed;
 
-               sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", HP_SW_NAME);
-       } else if (action == BUS_NOTIFY_DEL_DEVICE) {
-               if (sdev->scsi_dh_data == NULL ||
-                               sdev->scsi_dh_data->scsi_dh != &hp_sw_dh)
-                       goto out;
+       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
+       sdev->scsi_dh_data = scsi_dh_data;
+       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
 
-               spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-               scsi_dh_data = sdev->scsi_dh_data;
-               sdev->scsi_dh_data = NULL;
-               spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-               module_put(THIS_MODULE);
+       sdev_printk(KERN_INFO, sdev, "%s: attached to %s path\n",
+                   HP_SW_NAME, h->path_state == HP_SW_PATH_ACTIVE?
+                   "active":"passive");
 
-               sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", HP_SW_NAME);
+       return 0;
 
-               kfree(scsi_dh_data);
-       }
+failed:
+       kfree(scsi_dh_data);
+       sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
+                   HP_SW_NAME);
+       return -EINVAL;
+}
 
-out:
-       return 0;
+static void hp_sw_bus_detach( struct scsi_device *sdev )
+{
+       struct scsi_dh_data *scsi_dh_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
+       scsi_dh_data = sdev->scsi_dh_data;
+       sdev->scsi_dh_data = NULL;
+       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+       module_put(THIS_MODULE);
+
+       sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", HP_SW_NAME);
+
+       kfree(scsi_dh_data);
 }
 
 static int __init hp_sw_init(void)
@@ -202,6 +376,6 @@ static void __exit hp_sw_exit(void)
 module_init(hp_sw_init);
 module_exit(hp_sw_exit);
 
-MODULE_DESCRIPTION("HP MSA 1000");
+MODULE_DESCRIPTION("HP Active/Passive driver");
 MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu");
 MODULE_LICENSE("GPL");
index fdf34b0ec6e1770951181d82a314380a27934d50..b093a501f8ae673b980ca896d6d73d4ed407a78e 100644 (file)
@@ -173,6 +173,11 @@ struct rdac_dh_data {
 #define RDAC_STATE_ACTIVE      0
 #define RDAC_STATE_PASSIVE     1
        unsigned char           state;
+
+#define RDAC_LUN_UNOWNED       0
+#define RDAC_LUN_OWNED         1
+#define RDAC_LUN_AVT           2
+       char                    lun_state;
        unsigned char           sense[SCSI_SENSE_BUFFERSIZE];
        union                   {
                struct c2_inquiry c2;
@@ -182,6 +187,13 @@ struct rdac_dh_data {
        } inq;
 };
 
+static const char *lun_state[] =
+{
+       "unowned",
+       "owned",
+       "owned (AVT mode)",
+};
+
 static LIST_HEAD(ctlr_list);
 static DEFINE_SPINLOCK(list_lock);
 
@@ -197,9 +209,8 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
 {
        struct request *rq;
        struct request_queue *q = sdev->request_queue;
-       struct rdac_dh_data *h = get_rdac_data(sdev);
 
-       rq = blk_get_request(q, rw, GFP_KERNEL);
+       rq = blk_get_request(q, rw, GFP_NOIO);
 
        if (!rq) {
                sdev_printk(KERN_INFO, sdev,
@@ -207,17 +218,14 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
                return NULL;
        }
 
-       if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_KERNEL)) {
+       if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
                blk_put_request(rq);
                sdev_printk(KERN_INFO, sdev,
                                "get_rdac_req: blk_rq_map_kern failed.\n");
                return NULL;
        }
 
-       memset(&rq->cmd, 0, BLK_MAX_CDB);
-       rq->sense = h->sense;
-       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-       rq->sense_len = 0;
+       memset(rq->cmd, 0, BLK_MAX_CDB);
 
        rq->cmd_type = REQ_TYPE_BLOCK_PC;
        rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
@@ -227,12 +235,12 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
        return rq;
 }
 
-static struct request *rdac_failover_get(struct scsi_device *sdev)
+static struct request *rdac_failover_get(struct scsi_device *sdev,
+                                        struct rdac_dh_data *h)
 {
        struct request *rq;
        struct rdac_mode_common *common;
        unsigned data_size;
-       struct rdac_dh_data *h = get_rdac_data(sdev);
 
        if (h->ctlr->use_ms10) {
                struct rdac_pg_expanded *rdac_pg;
@@ -277,6 +285,10 @@ static struct request *rdac_failover_get(struct scsi_device *sdev)
        }
        rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
 
+       rq->sense = h->sense;
+       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       rq->sense_len = 0;
+
        return rq;
 }
 
@@ -321,11 +333,10 @@ done:
 }
 
 static int submit_inquiry(struct scsi_device *sdev, int page_code,
-               unsigned int len)
+                         unsigned int len, struct rdac_dh_data *h)
 {
        struct request *rq;
        struct request_queue *q = sdev->request_queue;
-       struct rdac_dh_data *h = get_rdac_data(sdev);
        int err = SCSI_DH_RES_TEMP_UNAVAIL;
 
        rq = get_rdac_req(sdev, &h->inq, len, READ);
@@ -338,59 +349,68 @@ static int submit_inquiry(struct scsi_device *sdev, int page_code,
        rq->cmd[2] = page_code;
        rq->cmd[4] = len;
        rq->cmd_len = COMMAND_SIZE(INQUIRY);
+
+       rq->sense = h->sense;
+       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+       rq->sense_len = 0;
+
        err = blk_execute_rq(q, NULL, rq, 1);
        if (err == -EIO)
                err = SCSI_DH_IO;
+
+       blk_put_request(rq);
 done:
        return err;
 }
 
-static int get_lun(struct scsi_device *sdev)
+static int get_lun(struct scsi_device *sdev, struct rdac_dh_data *h)
 {
        int err;
        struct c8_inquiry *inqp;
-       struct rdac_dh_data *h = get_rdac_data(sdev);
 
-       err = submit_inquiry(sdev, 0xC8, sizeof(struct c8_inquiry));
+       err = submit_inquiry(sdev, 0xC8, sizeof(struct c8_inquiry), h);
        if (err == SCSI_DH_OK) {
                inqp = &h->inq.c8;
-               h->lun = inqp->lun[7]; /* currently it uses only one byte */
+               if (inqp->page_code != 0xc8)
+                       return SCSI_DH_NOSYS;
+               if (inqp->page_id[0] != 'e' || inqp->page_id[1] != 'd' ||
+                   inqp->page_id[2] != 'i' || inqp->page_id[3] != 'd')
+                       return SCSI_DH_NOSYS;
+               h->lun = scsilun_to_int((struct scsi_lun *)inqp->lun);
        }
        return err;
 }
 
-#define RDAC_OWNED     0
-#define RDAC_UNOWNED   1
-#define RDAC_FAILED    2
-static int check_ownership(struct scsi_device *sdev)
+static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
 {
        int err;
        struct c9_inquiry *inqp;
-       struct rdac_dh_data *h = get_rdac_data(sdev);
 
-       err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry));
+       err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h);
        if (err == SCSI_DH_OK) {
-               err = RDAC_UNOWNED;
                inqp = &h->inq.c9;
-               /*
-                * If in AVT mode or if the path already owns the LUN,
-                * return RDAC_OWNED;
-                */
-               if (((inqp->avte_cvp >> 7) == 0x1) ||
-                                ((inqp->avte_cvp & 0x1) != 0))
-                       err = RDAC_OWNED;
-       } else
-               err = RDAC_FAILED;
+               if ((inqp->avte_cvp >> 7) == 0x1) {
+                       /* LUN in AVT mode */
+                       sdev_printk(KERN_NOTICE, sdev,
+                                   "%s: AVT mode detected\n",
+                                   RDAC_NAME);
+                       h->lun_state = RDAC_LUN_AVT;
+               } else if ((inqp->avte_cvp & 0x1) != 0) {
+                       /* LUN was owned by the controller */
+                       h->lun_state = RDAC_LUN_OWNED;
+               }
+       }
+
        return err;
 }
 
-static int initialize_controller(struct scsi_device *sdev)
+static int initialize_controller(struct scsi_device *sdev,
+                                struct rdac_dh_data *h)
 {
        int err;
        struct c4_inquiry *inqp;
-       struct rdac_dh_data *h = get_rdac_data(sdev);
 
-       err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry));
+       err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry), h);
        if (err == SCSI_DH_OK) {
                inqp = &h->inq.c4;
                h->ctlr = get_controller(inqp->subsys_id, inqp->slot_id);
@@ -400,13 +420,12 @@ static int initialize_controller(struct scsi_device *sdev)
        return err;
 }
 
-static int set_mode_select(struct scsi_device *sdev)
+static int set_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
 {
        int err;
        struct c2_inquiry *inqp;
-       struct rdac_dh_data *h = get_rdac_data(sdev);
 
-       err = submit_inquiry(sdev, 0xC2, sizeof(struct c2_inquiry));
+       err = submit_inquiry(sdev, 0xC2, sizeof(struct c2_inquiry), h);
        if (err == SCSI_DH_OK) {
                inqp = &h->inq.c2;
                /*
@@ -421,13 +440,13 @@ static int set_mode_select(struct scsi_device *sdev)
        return err;
 }
 
-static int mode_select_handle_sense(struct scsi_device *sdev)
+static int mode_select_handle_sense(struct scsi_device *sdev,
+                                   unsigned char *sensebuf)
 {
        struct scsi_sense_hdr sense_hdr;
-       struct rdac_dh_data *h = get_rdac_data(sdev);
        int sense, err = SCSI_DH_IO, ret;
 
-       ret = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
+       ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
        if (!ret)
                goto done;
 
@@ -451,14 +470,13 @@ done:
        return err;
 }
 
-static int send_mode_select(struct scsi_device *sdev)
+static int send_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
 {
        struct request *rq;
        struct request_queue *q = sdev->request_queue;
-       struct rdac_dh_data *h = get_rdac_data(sdev);
        int err = SCSI_DH_RES_TEMP_UNAVAIL;
 
-       rq = rdac_failover_get(sdev);
+       rq = rdac_failover_get(sdev, h);
        if (!rq)
                goto done;
 
@@ -466,9 +484,11 @@ static int send_mode_select(struct scsi_device *sdev)
 
        err = blk_execute_rq(q, NULL, rq, 1);
        if (err != SCSI_DH_OK)
-               err = mode_select_handle_sense(sdev);
+               err = mode_select_handle_sense(sdev, h->sense);
        if (err == SCSI_DH_OK)
                h->state = RDAC_STATE_ACTIVE;
+
+       blk_put_request(rq);
 done:
        return err;
 }
@@ -478,38 +498,23 @@ static int rdac_activate(struct scsi_device *sdev)
        struct rdac_dh_data *h = get_rdac_data(sdev);
        int err = SCSI_DH_OK;
 
-       if (h->lun == UNINITIALIZED_LUN) {
-               err = get_lun(sdev);
-               if (err != SCSI_DH_OK)
-                       goto done;
-       }
-
-       err = check_ownership(sdev);
-       switch (err) {
-       case RDAC_UNOWNED:
-               break;
-       case RDAC_OWNED:
-               err = SCSI_DH_OK;
-               goto done;
-       case RDAC_FAILED:
-       default:
-               err = SCSI_DH_IO;
+       err = check_ownership(sdev, h);
+       if (err != SCSI_DH_OK)
                goto done;
-       }
 
        if (!h->ctlr) {
-               err = initialize_controller(sdev);
+               err = initialize_controller(sdev, h);
                if (err != SCSI_DH_OK)
                        goto done;
        }
 
        if (h->ctlr->use_ms10 == -1) {
-               err = set_mode_select(sdev);
+               err = set_mode_select(sdev, h);
                if (err != SCSI_DH_OK)
                        goto done;
        }
-
-       err = send_mode_select(sdev);
+       if (h->lun_state == RDAC_LUN_UNOWNED)
+               err = send_mode_select(sdev, h);
 done:
        return err;
 }
@@ -569,10 +574,7 @@ static int rdac_check_sense(struct scsi_device *sdev,
        return SCSI_RETURN_NOT_HANDLED;
 }
 
-static const struct {
-       char *vendor;
-       char *model;
-} rdac_dev_list[] = {
+const struct scsi_dh_devlist rdac_dev_list[] = {
        {"IBM", "1722"},
        {"IBM", "1724"},
        {"IBM", "1726"},
@@ -590,89 +592,89 @@ static const struct {
        {NULL, NULL},
 };
 
-static int rdac_bus_notify(struct notifier_block *, unsigned long, void *);
+static int rdac_bus_attach(struct scsi_device *sdev);
+static void rdac_bus_detach(struct scsi_device *sdev);
 
 static struct scsi_device_handler rdac_dh = {
        .name = RDAC_NAME,
        .module = THIS_MODULE,
-       .nb.notifier_call = rdac_bus_notify,
+       .devlist = rdac_dev_list,
        .prep_fn = rdac_prep_fn,
        .check_sense = rdac_check_sense,
+       .attach = rdac_bus_attach,
+       .detach = rdac_bus_detach,
        .activate = rdac_activate,
 };
 
-/*
- * TODO: need some interface so we can set trespass values
- */
-static int rdac_bus_notify(struct notifier_block *nb,
-                           unsigned long action, void *data)
+static int rdac_bus_attach(struct scsi_device *sdev)
 {
-       struct device *dev = data;
-       struct scsi_device *sdev;
        struct scsi_dh_data *scsi_dh_data;
        struct rdac_dh_data *h;
-       int i, found = 0;
        unsigned long flags;
+       int err;
 
-       if (!scsi_is_sdev_device(dev))
+       scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+                              + sizeof(*h) , GFP_KERNEL);
+       if (!scsi_dh_data) {
+               sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
+                           RDAC_NAME);
                return 0;
+       }
 
-       sdev = to_scsi_device(dev);
-
-       if (action == BUS_NOTIFY_ADD_DEVICE) {
-               for (i = 0; rdac_dev_list[i].vendor; i++) {
-                       if (!strncmp(sdev->vendor, rdac_dev_list[i].vendor,
-                                    strlen(rdac_dev_list[i].vendor)) &&
-                           !strncmp(sdev->model, rdac_dev_list[i].model,
-                                    strlen(rdac_dev_list[i].model))) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found)
-                       goto out;
+       scsi_dh_data->scsi_dh = &rdac_dh;
+       h = (struct rdac_dh_data *) scsi_dh_data->buf;
+       h->lun = UNINITIALIZED_LUN;
+       h->state = RDAC_STATE_ACTIVE;
 
-               scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
-                               + sizeof(*h) , GFP_KERNEL);
-               if (!scsi_dh_data) {
-                       sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
-                                   RDAC_NAME);
-                       goto out;
-               }
+       err = get_lun(sdev, h);
+       if (err != SCSI_DH_OK)
+               goto failed;
 
-               scsi_dh_data->scsi_dh = &rdac_dh;
-               h = (struct rdac_dh_data *) scsi_dh_data->buf;
-               h->lun = UNINITIALIZED_LUN;
-               h->state = RDAC_STATE_ACTIVE;
-               spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-               sdev->scsi_dh_data = scsi_dh_data;
-               spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-               try_module_get(THIS_MODULE);
-
-               sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", RDAC_NAME);
-
-       } else if (action == BUS_NOTIFY_DEL_DEVICE) {
-               if (sdev->scsi_dh_data == NULL ||
-                               sdev->scsi_dh_data->scsi_dh != &rdac_dh)
-                       goto out;
-
-               spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-               scsi_dh_data = sdev->scsi_dh_data;
-               sdev->scsi_dh_data = NULL;
-               spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-
-               h = (struct rdac_dh_data *) scsi_dh_data->buf;
-               if (h->ctlr)
-                       kref_put(&h->ctlr->kref, release_controller);
-               kfree(scsi_dh_data);
-               module_put(THIS_MODULE);
-               sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", RDAC_NAME);
-       }
+       err = check_ownership(sdev, h);
+       if (err != SCSI_DH_OK)
+               goto failed;
+
+       if (!try_module_get(THIS_MODULE))
+               goto failed;
+
+       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
+       sdev->scsi_dh_data = scsi_dh_data;
+       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+
+       sdev_printk(KERN_NOTICE, sdev,
+                   "%s: LUN %d (%s)\n",
+                   RDAC_NAME, h->lun, lun_state[(int)h->lun_state]);
 
-out:
        return 0;
+
+failed:
+       kfree(scsi_dh_data);
+       sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
+                   RDAC_NAME);
+       return -EINVAL;
+}
+
+static void rdac_bus_detach( struct scsi_device *sdev )
+{
+       struct scsi_dh_data *scsi_dh_data;
+       struct rdac_dh_data *h;
+       unsigned long flags;
+
+       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
+       scsi_dh_data = sdev->scsi_dh_data;
+       sdev->scsi_dh_data = NULL;
+       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+
+       h = (struct rdac_dh_data *) scsi_dh_data->buf;
+       if (h->ctlr)
+               kref_put(&h->ctlr->kref, release_controller);
+       kfree(scsi_dh_data);
+       module_put(THIS_MODULE);
+       sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME);
 }
 
+
+
 static int __init rdac_init(void)
 {
        int r;
index eb702b96d57cf7ac631af7e18406493bf7eef6d9..ae560bc04f9d4df009ad8aef36abfa288dfca2f2 100644 (file)
@@ -521,9 +521,10 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
 static void ibmvfc_reinit_host(struct ibmvfc_host *vhost)
 {
        if (vhost->action == IBMVFC_HOST_ACTION_NONE) {
-               scsi_block_requests(vhost->host);
-               ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING);
-               ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
+               if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
+                       scsi_block_requests(vhost->host);
+                       ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
+               }
        } else
                vhost->reinit = 1;
 
@@ -854,39 +855,41 @@ static void ibmvfc_retry_host_init(struct ibmvfc_host *vhost)
 }
 
 /**
- * __ibmvfc_find_target - Find the specified scsi_target (no locking)
+ * __ibmvfc_get_target - Find the specified scsi_target (no locking)
  * @starget:   scsi target struct
  *
  * Return value:
  *     ibmvfc_target struct / NULL if not found
  **/
-static struct ibmvfc_target *__ibmvfc_find_target(struct scsi_target *starget)
+static struct ibmvfc_target *__ibmvfc_get_target(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        struct ibmvfc_host *vhost = shost_priv(shost);
        struct ibmvfc_target *tgt;
 
        list_for_each_entry(tgt, &vhost->targets, queue)
-               if (tgt->target_id == starget->id)
+               if (tgt->target_id == starget->id) {
+                       kref_get(&tgt->kref);
                        return tgt;
+               }
        return NULL;
 }
 
 /**
- * ibmvfc_find_target - Find the specified scsi_target
+ * ibmvfc_get_target - Find the specified scsi_target
  * @starget:   scsi target struct
  *
  * Return value:
  *     ibmvfc_target struct / NULL if not found
  **/
-static struct ibmvfc_target *ibmvfc_find_target(struct scsi_target *starget)
+static struct ibmvfc_target *ibmvfc_get_target(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        struct ibmvfc_target *tgt;
        unsigned long flags;
 
        spin_lock_irqsave(shost->host_lock, flags);
-       tgt = __ibmvfc_find_target(starget);
+       tgt = __ibmvfc_get_target(starget);
        spin_unlock_irqrestore(shost->host_lock, flags);
        return tgt;
 }
@@ -963,6 +966,9 @@ static void ibmvfc_get_host_port_state(struct Scsi_Host *shost)
        case IBMVFC_HALTED:
                fc_host_port_state(shost) = FC_PORTSTATE_BLOCKED;
                break;
+       case IBMVFC_NO_CRQ:
+               fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
+               break;
        default:
                ibmvfc_log(vhost, 3, "Unknown port state: %d\n", vhost->state);
                fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
@@ -987,6 +993,17 @@ static void ibmvfc_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
                rport->dev_loss_tmo = 1;
 }
 
+/**
+ * ibmvfc_release_tgt - Free memory allocated for a target
+ * @kref:              kref struct
+ *
+ **/
+static void ibmvfc_release_tgt(struct kref *kref)
+{
+       struct ibmvfc_target *tgt = container_of(kref, struct ibmvfc_target, kref);
+       kfree(tgt);
+}
+
 /**
  * ibmvfc_get_starget_node_name - Get SCSI target's node name
  * @starget:   scsi target struct
@@ -996,8 +1013,10 @@ static void ibmvfc_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
  **/
 static void ibmvfc_get_starget_node_name(struct scsi_target *starget)
 {
-       struct ibmvfc_target *tgt = ibmvfc_find_target(starget);
+       struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
        fc_starget_port_name(starget) = tgt ? tgt->ids.node_name : 0;
+       if (tgt)
+               kref_put(&tgt->kref, ibmvfc_release_tgt);
 }
 
 /**
@@ -1009,8 +1028,10 @@ static void ibmvfc_get_starget_node_name(struct scsi_target *starget)
  **/
 static void ibmvfc_get_starget_port_name(struct scsi_target *starget)
 {
-       struct ibmvfc_target *tgt = ibmvfc_find_target(starget);
+       struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
        fc_starget_port_name(starget) = tgt ? tgt->ids.port_name : 0;
+       if (tgt)
+               kref_put(&tgt->kref, ibmvfc_release_tgt);
 }
 
 /**
@@ -1022,8 +1043,10 @@ static void ibmvfc_get_starget_port_name(struct scsi_target *starget)
  **/
 static void ibmvfc_get_starget_port_id(struct scsi_target *starget)
 {
-       struct ibmvfc_target *tgt = ibmvfc_find_target(starget);
+       struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
        fc_starget_port_id(starget) = tgt ? tgt->scsi_id : -1;
+       if (tgt)
+               kref_put(&tgt->kref, ibmvfc_release_tgt);
 }
 
 /**
@@ -1113,7 +1136,7 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
        login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ;
        login_info->capabilities = IBMVFC_CAN_MIGRATE;
        login_info->async.va = vhost->async_crq.msg_token;
-       login_info->async.len = vhost->async_crq.size;
+       login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs);
        strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
        strncpy(login_info->device_name,
                vhost->host->shost_gendev.bus_id, IBMVFC_MAX_NAME);
@@ -1404,7 +1427,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
                err = cmd_status[index].name;
        }
 
-       if (!logerr && (vhost->log_level <= IBMVFC_DEFAULT_LOG_LEVEL))
+       if (!logerr && (vhost->log_level <= (IBMVFC_DEFAULT_LOG_LEVEL + 1)))
                return;
 
        if (rsp->flags & FCP_RSP_LEN_VALID)
@@ -2054,7 +2077,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
 {
        const char *desc = ibmvfc_get_ae_desc(crq->event);
 
-       ibmvfc_log(vhost, 2, "%s event received\n", desc);
+       ibmvfc_log(vhost, 3, "%s event received\n", desc);
 
        switch (crq->event) {
        case IBMVFC_AE_LINK_UP:
@@ -2647,17 +2670,6 @@ static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt,
                ibmvfc_init_tgt(tgt, job_step);
 }
 
-/**
- * ibmvfc_release_tgt - Free memory allocated for a target
- * @kref:              kref struct
- *
- **/
-static void ibmvfc_release_tgt(struct kref *kref)
-{
-       struct ibmvfc_target *tgt = container_of(kref, struct ibmvfc_target, kref);
-       kfree(tgt);
-}
-
 /**
  * ibmvfc_tgt_prli_done - Completion handler for Process Login
  * @evt:       ibmvfc event struct
@@ -2901,6 +2913,139 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt)
                tgt_dbg(tgt, "Sent Implicit Logout\n");
 }
 
+/**
+ * ibmvfc_adisc_needs_plogi - Does device need PLOGI?
+ * @mad:       ibmvfc passthru mad struct
+ * @tgt:       ibmvfc target struct
+ *
+ * Returns:
+ *     1 if PLOGI needed / 0 if PLOGI not needed
+ **/
+static int ibmvfc_adisc_needs_plogi(struct ibmvfc_passthru_mad *mad,
+                                   struct ibmvfc_target *tgt)
+{
+       if (memcmp(&mad->fc_iu.response[2], &tgt->ids.port_name,
+                  sizeof(tgt->ids.port_name)))
+               return 1;
+       if (memcmp(&mad->fc_iu.response[4], &tgt->ids.node_name,
+                  sizeof(tgt->ids.node_name)))
+               return 1;
+       if (mad->fc_iu.response[6] != tgt->scsi_id)
+               return 1;
+       return 0;
+}
+
+/**
+ * ibmvfc_tgt_adisc_done - Completion handler for ADISC
+ * @evt:       ibmvfc event struct
+ *
+ **/
+static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
+{
+       struct ibmvfc_target *tgt = evt->tgt;
+       struct ibmvfc_host *vhost = evt->vhost;
+       struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru;
+       u32 status = mad->common.status;
+       u8 fc_reason, fc_explain;
+
+       vhost->discovery_threads--;
+       ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
+
+       switch (status) {
+       case IBMVFC_MAD_SUCCESS:
+               tgt_dbg(tgt, "ADISC succeeded\n");
+               if (ibmvfc_adisc_needs_plogi(mad, tgt))
+                       tgt->need_login = 1;
+               break;
+       case IBMVFC_MAD_DRIVER_FAILED:
+               break;
+       case IBMVFC_MAD_FAILED:
+       default:
+               tgt->need_login = 1;
+               fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16;
+               fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8;
+               tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
+                        ibmvfc_get_cmd_error(mad->iu.status, mad->iu.error),
+                        mad->iu.status, mad->iu.error,
+                        ibmvfc_get_fc_type(fc_reason), fc_reason,
+                        ibmvfc_get_ls_explain(fc_explain), fc_explain, status);
+               break;
+       };
+
+       kref_put(&tgt->kref, ibmvfc_release_tgt);
+       ibmvfc_free_event(evt);
+       wake_up(&vhost->work_wait_q);
+}
+
+/**
+ * ibmvfc_init_passthru - Initialize an event struct for FC passthru
+ * @evt:               ibmvfc event struct
+ *
+ **/
+static void ibmvfc_init_passthru(struct ibmvfc_event *evt)
+{
+       struct ibmvfc_passthru_mad *mad = &evt->iu.passthru;
+
+       memset(mad, 0, sizeof(*mad));
+       mad->common.version = 1;
+       mad->common.opcode = IBMVFC_PASSTHRU;
+       mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu);
+       mad->cmd_ioba.va = (u64)evt->crq.ioba +
+               offsetof(struct ibmvfc_passthru_mad, iu);
+       mad->cmd_ioba.len = sizeof(mad->iu);
+       mad->iu.cmd_len = sizeof(mad->fc_iu.payload);
+       mad->iu.rsp_len = sizeof(mad->fc_iu.response);
+       mad->iu.cmd.va = (u64)evt->crq.ioba +
+               offsetof(struct ibmvfc_passthru_mad, fc_iu) +
+               offsetof(struct ibmvfc_passthru_fc_iu, payload);
+       mad->iu.cmd.len = sizeof(mad->fc_iu.payload);
+       mad->iu.rsp.va = (u64)evt->crq.ioba +
+               offsetof(struct ibmvfc_passthru_mad, fc_iu) +
+               offsetof(struct ibmvfc_passthru_fc_iu, response);
+       mad->iu.rsp.len = sizeof(mad->fc_iu.response);
+}
+
+/**
+ * ibmvfc_tgt_adisc - Initiate an ADISC for specified target
+ * @tgt:               ibmvfc target struct
+ *
+ **/
+static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
+{
+       struct ibmvfc_passthru_mad *mad;
+       struct ibmvfc_host *vhost = tgt->vhost;
+       struct ibmvfc_event *evt;
+
+       if (vhost->discovery_threads >= disc_threads)
+               return;
+
+       kref_get(&tgt->kref);
+       evt = ibmvfc_get_event(vhost);
+       vhost->discovery_threads++;
+       ibmvfc_init_event(evt, ibmvfc_tgt_adisc_done, IBMVFC_MAD_FORMAT);
+       evt->tgt = tgt;
+
+       ibmvfc_init_passthru(evt);
+       mad = &evt->iu.passthru;
+       mad->iu.flags = IBMVFC_FC_ELS;
+       mad->iu.scsi_id = tgt->scsi_id;
+
+       mad->fc_iu.payload[0] = IBMVFC_ADISC;
+       memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name,
+              sizeof(vhost->login_buf->resp.port_name));
+       memcpy(&mad->fc_iu.payload[4], &vhost->login_buf->resp.node_name,
+              sizeof(vhost->login_buf->resp.node_name));
+       mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff;
+
+       ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
+       if (ibmvfc_send_event(evt, vhost, default_timeout)) {
+               vhost->discovery_threads--;
+               ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
+               kref_put(&tgt->kref, ibmvfc_release_tgt);
+       } else
+               tgt_dbg(tgt, "Sent ADISC\n");
+}
+
 /**
  * ibmvfc_tgt_query_target_done - Completion handler for Query Target MAD
  * @evt:       ibmvfc event struct
@@ -2921,6 +3066,8 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
                tgt->new_scsi_id = rsp->scsi_id;
                if (rsp->scsi_id != tgt->scsi_id)
                        ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
+               else
+                       ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc);
                break;
        case IBMVFC_MAD_DRIVER_FAILED:
                break;
@@ -3336,6 +3483,7 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
                tgt_dbg(tgt, "rport add succeeded\n");
                rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff;
                rport->supported_classes = 0;
+               tgt->target_id = rport->scsi_target_id;
                if (tgt->service_parms.class1_parms[0] & 0x80000000)
                        rport->supported_classes |= FC_COS_CLASS1;
                if (tgt->service_parms.class2_parms[0] & 0x80000000)
@@ -3525,7 +3673,7 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
        crq->msg_token = dma_map_single(dev, crq->msgs,
                                        PAGE_SIZE, DMA_BIDIRECTIONAL);
 
-       if (dma_mapping_error(crq->msg_token))
+       if (dma_mapping_error(dev, crq->msg_token))
                goto map_failed;
 
        retrc = rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
@@ -3618,7 +3766,7 @@ static int ibmvfc_alloc_mem(struct ibmvfc_host *vhost)
                                            async_q->size * sizeof(*async_q->msgs),
                                            DMA_BIDIRECTIONAL);
 
-       if (dma_mapping_error(async_q->msg_token)) {
+       if (dma_mapping_error(dev, async_q->msg_token)) {
                dev_err(dev, "Failed to map async queue\n");
                goto free_async_crq;
        }
@@ -3800,10 +3948,12 @@ static int ibmvfc_remove(struct vio_dev *vdev)
 
        ENTER;
        ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr);
+       ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE);
+       ibmvfc_wait_while_resetting(vhost);
+       ibmvfc_release_crq_queue(vhost);
        kthread_stop(vhost->work_thread);
        fc_remove_host(vhost->host);
        scsi_remove_host(vhost->host);
-       ibmvfc_release_crq_queue(vhost);
 
        spin_lock_irqsave(vhost->host->host_lock, flags);
        ibmvfc_purge_requests(vhost, DID_ERROR);
@@ -3819,6 +3969,20 @@ static int ibmvfc_remove(struct vio_dev *vdev)
        return 0;
 }
 
+/**
+ * ibmvfc_get_desired_dma - Calculate DMA resources needed by the driver
+ * @vdev:      vio device struct
+ *
+ * Return value:
+ *     Number of bytes the driver will need to DMA map at the same time in
+ *     order to perform well.
+ */
+static unsigned long ibmvfc_get_desired_dma(struct vio_dev *vdev)
+{
+       unsigned long pool_dma = max_requests * sizeof(union ibmvfc_iu);
+       return pool_dma + ((512 * 1024) * driver_template.cmd_per_lun);
+}
+
 static struct vio_device_id ibmvfc_device_table[] __devinitdata = {
        {"fcp", "IBM,vfc-client"},
        { "", "" }
@@ -3829,6 +3993,7 @@ static struct vio_driver ibmvfc_driver = {
        .id_table = ibmvfc_device_table,
        .probe = ibmvfc_probe,
        .remove = ibmvfc_remove,
+       .get_desired_dma = ibmvfc_get_desired_dma,
        .driver = {
                .name = IBMVFC_NAME,
                .owner = THIS_MODULE,
index 057f3c01ed6106f1cbc146cd75b67aa1a85d1052..4bf6e374f076b854babc1eae897bd3500cdbed8a 100644 (file)
@@ -29,8 +29,8 @@
 #include "viosrp.h"
 
 #define IBMVFC_NAME    "ibmvfc"
-#define IBMVFC_DRIVER_VERSION          "1.0.0"
-#define IBMVFC_DRIVER_DATE             "(July 1, 2008)"
+#define IBMVFC_DRIVER_VERSION          "1.0.1"
+#define IBMVFC_DRIVER_DATE             "(July 11, 2008)"
 
 #define IBMVFC_DEFAULT_TIMEOUT 15
 #define IBMVFC_INIT_TIMEOUT            30
@@ -119,6 +119,7 @@ enum ibmvfc_mad_types {
        IBMVFC_PROCESS_LOGIN    = 0x0008,
        IBMVFC_QUERY_TARGET     = 0x0010,
        IBMVFC_IMPLICIT_LOGOUT  = 0x0040,
+       IBMVFC_PASSTHRU         = 0x0200,
        IBMVFC_TMF_MAD          = 0x0100,
 };
 
@@ -439,6 +440,37 @@ struct ibmvfc_cmd {
        struct ibmvfc_fcp_rsp rsp;
 }__attribute__((packed, aligned (8)));
 
+struct ibmvfc_passthru_fc_iu {
+       u32 payload[7];
+#define IBMVFC_ADISC   0x52000000
+       u32 response[7];
+};
+
+struct ibmvfc_passthru_iu {
+       u64 task_tag;
+       u32 cmd_len;
+       u32 rsp_len;
+       u16 status;
+       u16 error;
+       u32 flags;
+#define IBMVFC_FC_ELS          0x01
+       u32 cancel_key;
+       u32 reserved;
+       struct srp_direct_buf cmd;
+       struct srp_direct_buf rsp;
+       u64 correlation;
+       u64 scsi_id;
+       u64 tag;
+       u64 reserved2[2];
+}__attribute__((packed, aligned (8)));
+
+struct ibmvfc_passthru_mad {
+       struct ibmvfc_mad_common common;
+       struct srp_direct_buf cmd_ioba;
+       struct ibmvfc_passthru_iu iu;
+       struct ibmvfc_passthru_fc_iu fc_iu;
+}__attribute__((packed, aligned (8)));
+
 struct ibmvfc_trace_start_entry {
        u32 xfer_len;
 }__attribute__((packed));
@@ -531,6 +563,7 @@ union ibmvfc_iu {
        struct ibmvfc_implicit_logout implicit_logout;
        struct ibmvfc_tmf tmf;
        struct ibmvfc_cmd cmd;
+       struct ibmvfc_passthru_mad passthru;
 }__attribute__((packed, aligned (8)));
 
 enum ibmvfc_target_action {
@@ -656,6 +689,9 @@ struct ibmvfc_host {
 #define tgt_dbg(t, fmt, ...)                   \
        DBG_CMD(dev_info((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__))
 
+#define tgt_info(t, fmt, ...)          \
+       dev_info((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
+
 #define tgt_err(t, fmt, ...)           \
        dev_err((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
 
@@ -668,8 +704,8 @@ struct ibmvfc_host {
                        dev_err((vhost)->dev, ##__VA_ARGS__); \
        } while (0)
 
-#define ENTER DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Entering %s\n", __FUNCTION__))
-#define LEAVE DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Leaving %s\n", __FUNCTION__))
+#define ENTER DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Entering %s\n", __func__))
+#define LEAVE DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Leaving %s\n", __func__))
 
 #ifdef CONFIG_SCSI_IBMVFC_TRACE
 #define ibmvfc_create_trace_file(kobj, attr) sysfs_create_bin_file(kobj, attr)
index 5d23368a1bcee68e31bc04019cd696118132bea0..6b24b9cdb04cda6666837684cd232d271dfc4b10 100644 (file)
@@ -72,6 +72,7 @@
 #include <linux/delay.h>
 #include <asm/firmware.h>
 #include <asm/vio.h>
+#include <asm/firmware.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
@@ -426,8 +427,10 @@ static int map_sg_data(struct scsi_cmnd *cmd,
                                           SG_ALL * sizeof(struct srp_direct_buf),
                                           &evt_struct->ext_list_token, 0);
                if (!evt_struct->ext_list) {
-                       sdev_printk(KERN_ERR, cmd->device,
-                                   "Can't allocate memory for indirect table\n");
+                       if (!firmware_has_feature(FW_FEATURE_CMO))
+                               sdev_printk(KERN_ERR, cmd->device,
+                                           "Can't allocate memory "
+                                           "for indirect table\n");
                        return 0;
                }
        }
@@ -743,7 +746,9 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
        srp_cmd->lun = ((u64) lun) << 48;
 
        if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
-               sdev_printk(KERN_ERR, cmnd->device, "couldn't convert cmd to srp_cmd\n");
+               if (!firmware_has_feature(FW_FEATURE_CMO))
+                       sdev_printk(KERN_ERR, cmnd->device,
+                                   "couldn't convert cmd to srp_cmd\n");
                free_event_struct(&hostdata->pool, evt_struct);
                return SCSI_MLQUEUE_HOST_BUSY;
        }
@@ -854,8 +859,11 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
                                            sizeof(hostdata->madapter_info),
                                            DMA_BIDIRECTIONAL);
 
-       if (dma_mapping_error(req->buffer)) {
-               dev_err(hostdata->dev, "Unable to map request_buffer for adapter_info!\n");
+       if (dma_mapping_error(hostdata->dev, req->buffer)) {
+               if (!firmware_has_feature(FW_FEATURE_CMO))
+                       dev_err(hostdata->dev,
+                               "Unable to map request_buffer for "
+                               "adapter_info!\n");
                free_event_struct(&hostdata->pool, evt_struct);
                return;
        }
@@ -1399,8 +1407,10 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
                                                    length,
                                                    DMA_BIDIRECTIONAL);
 
-       if (dma_mapping_error(host_config->buffer)) {
-               dev_err(hostdata->dev, "dma_mapping error getting host config\n");
+       if (dma_mapping_error(hostdata->dev, host_config->buffer)) {
+               if (!firmware_has_feature(FW_FEATURE_CMO))
+                       dev_err(hostdata->dev,
+                               "dma_mapping error getting host config\n");
                free_event_struct(&hostdata->pool, evt_struct);
                return -1;
        }
@@ -1604,7 +1614,7 @@ static struct scsi_host_template driver_template = {
        .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler,
        .slave_configure = ibmvscsi_slave_configure,
        .change_queue_depth = ibmvscsi_change_queue_depth,
-       .cmd_per_lun = 16,
+       .cmd_per_lun = IBMVSCSI_CMDS_PER_LUN_DEFAULT,
        .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
        .this_id = -1,
        .sg_tablesize = SG_ALL,
@@ -1612,6 +1622,26 @@ static struct scsi_host_template driver_template = {
        .shost_attrs = ibmvscsi_attrs,
 };
 
+/**
+ * ibmvscsi_get_desired_dma - Calculate IO memory desired by the driver
+ *
+ * @vdev: struct vio_dev for the device whose desired IO mem is to be returned
+ *
+ * Return value:
+ *     Number of bytes of IO data the driver will need to perform well.
+ */
+static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev)
+{
+       /* iu_storage data allocated in initialize_event_pool */
+       unsigned long desired_io = max_requests * sizeof(union viosrp_iu);
+
+       /* add io space for sg data */
+       desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT *
+                            IBMVSCSI_CMDS_PER_LUN_DEFAULT);
+
+       return desired_io;
+}
+
 /**
  * Called by bus code for each adapter
  */
@@ -1641,7 +1671,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        hostdata->host = host;
        hostdata->dev = dev;
        atomic_set(&hostdata->request_limit, -1);
-       hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
+       hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
 
        rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
        if (rc != 0 && rc != H_RESOURCE) {
@@ -1735,6 +1765,7 @@ static struct vio_driver ibmvscsi_driver = {
        .id_table = ibmvscsi_device_table,
        .probe = ibmvscsi_probe,
        .remove = ibmvscsi_remove,
+       .get_desired_dma = ibmvscsi_get_desired_dma,
        .driver = {
                .name = "ibmvscsi",
                .owner = THIS_MODULE,
index 46e850e302c7918306d96218ff606229ae230183..2d4339d5e16e4e3c9cfed8b7b4fe30b87cb84932 100644 (file)
@@ -45,6 +45,8 @@ struct Scsi_Host;
 #define MAX_INDIRECT_BUFS 10
 
 #define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
+#define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16
+#define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */
 #define IBMVSCSI_MAX_CMDS_PER_LUN 64
 
 /* ------------------------------------------------------------
index 3b9514c8f1f17321a2b3532b9572336f81cf9c74..2a5b29d12172e4a72bb774453d2662b7d29192ee 100644 (file)
@@ -55,7 +55,7 @@
 /* tmp - will replace with SCSI logging stuff */
 #define eprintk(fmt, args...)                                  \
 do {                                                           \
-       printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args);  \
+       printk("%s(%d) " fmt, __func__, __LINE__, ##args);      \
 } while (0)
 /* #define dprintk eprintk */
 #define dprintk(fmt, args...)
@@ -564,7 +564,7 @@ static int crq_queue_create(struct crq_queue *queue, struct srp_target *target)
                                          queue->size * sizeof(*queue->msgs),
                                          DMA_BIDIRECTIONAL);
 
-       if (dma_mapping_error(queue->msg_token))
+       if (dma_mapping_error(target->dev, queue->msg_token))
                goto map_failed;
 
        err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token,
index 182146100dc12220ee20e55d44cb8e0d3a7bf618..462a8574dad96ffa6020c9aa27886c545b8a7988 100644 (file)
@@ -253,7 +253,7 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue,
                                          queue->size * sizeof(*queue->msgs),
                                          DMA_BIDIRECTIONAL);
 
-       if (dma_mapping_error(queue->msg_token))
+       if (dma_mapping_error(hostdata->dev, queue->msg_token))
                goto map_failed;
 
        gather_partition_info();
index 538552495d486da9f896e5cdc3067e360ea27109..b40a673985aa66fd2fe5310945b2993a0aa2feb2 100644 (file)
@@ -101,8 +101,13 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
 
        mutex_lock(&idescsi_ref_mutex);
        scsi = ide_scsi_g(disk);
-       if (scsi)
+       if (scsi) {
                scsi_host_get(scsi->host);
+               if (ide_device_get(scsi->drive)) {
+                       scsi_host_put(scsi->host);
+                       scsi = NULL;
+               }
+       }
        mutex_unlock(&idescsi_ref_mutex);
        return scsi;
 }
@@ -110,6 +115,7 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
 static void ide_scsi_put(struct ide_scsi_obj *scsi)
 {
        mutex_lock(&idescsi_ref_mutex);
+       ide_device_put(scsi->drive);
        scsi_host_put(scsi->host);
        mutex_unlock(&idescsi_ref_mutex);
 }
@@ -201,15 +207,15 @@ static int idescsi_check_condition(ide_drive_t *drive,
 
        /* stuff a sense request in front of our current request */
        pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
-       rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+       rq = blk_get_request(drive->queue, READ, GFP_ATOMIC);
        buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
        if (!pc || !rq || !buf) {
                kfree(buf);
-               kfree(rq);
+               if (rq)
+                       blk_put_request(rq);
                kfree(pc);
                return -ENOMEM;
        }
-       blk_rq_init(NULL, rq);
        rq->special = (char *) pc;
        pc->rq = rq;
        pc->buf = buf;
@@ -226,6 +232,7 @@ static int idescsi_check_condition(ide_drive_t *drive,
                ide_scsi_hex_dump(pc->c, 6);
        }
        rq->rq_disk = scsi->disk;
+       rq->ref_count++;
        memcpy(rq->cmd, pc->c, 12);
        ide_do_drive_cmd(drive, rq);
        return 0;
@@ -272,7 +279,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
                        SCSI_SENSE_BUFFERSIZE);
                kfree(pc->buf);
                kfree(pc);
-               kfree(rq);
+               blk_put_request(rq);
                pc = opc;
                rq = pc->rq;
                pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
@@ -303,7 +310,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
        pc->done(pc->scsi_cmd);
        spin_unlock_irqrestore(host->host_lock, flags);
        kfree(pc);
-       kfree(rq);
+       blk_put_request(rq);
        scsi->pc = NULL;
        return 0;
 }
@@ -577,6 +584,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
        ide_drive_t *drive = scsi->drive;
        struct request *rq = NULL;
        struct ide_atapi_pc *pc = NULL;
+       int write = cmd->sc_data_direction == DMA_TO_DEVICE;
 
        if (!drive) {
                scmd_printk (KERN_ERR, cmd, "drive not present\n");
@@ -584,7 +592,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
        }
        scsi = drive_to_idescsi(drive);
        pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
-       rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+       rq = blk_get_request(drive->queue, write, GFP_ATOMIC);
        if (rq == NULL || pc == NULL) {
                printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
                goto abort;
@@ -614,17 +622,18 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
                }
        }
 
-       blk_rq_init(NULL, rq);
        rq->special = (char *) pc;
        rq->cmd_type = REQ_TYPE_SPECIAL;
        spin_unlock_irq(host->host_lock);
+       rq->ref_count++;
        memcpy(rq->cmd, pc->c, 12);
        blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL);
        spin_lock_irq(host->host_lock);
        return 0;
 abort:
        kfree (pc);
-       kfree (rq);
+       if (rq)
+               blk_put_request(rq);
        cmd->result = DID_ERROR << 16;
        done(cmd);
        return 0;
@@ -672,7 +681,9 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
 
                if (blk_sense_request(scsi->pc->rq))
                        kfree(scsi->pc->buf);
-               kfree(scsi->pc->rq);
+               /* we need to call blk_put_request twice. */
+               blk_put_request(scsi->pc->rq);
+               blk_put_request(scsi->pc->rq);
                kfree(scsi->pc);
                scsi->pc = NULL;
 
@@ -724,7 +735,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
                kfree(scsi->pc->buf);
        kfree(scsi->pc);
        scsi->pc = NULL;
-       kfree(req);
+       blk_put_request(req);
 
        /* now nuke the drive queue */
        while ((req = elv_next_request(drive->queue))) {
index f97d172844be8e084cca57e3750752be77529816..c2a9a13d788f2bb6f68e7c921b71270a5dc6d20b 100644 (file)
@@ -163,7 +163,7 @@ static int imm_proc_info(struct Scsi_Host *host, char *buffer, char **start,
 
 #if IMM_DEBUG > 0
 #define imm_fail(x,y) printk("imm: imm_fail(%i) from %s at line %d\n",\
-          y, __FUNCTION__, __LINE__); imm_fail_func(x,y);
+          y, __func__, __LINE__); imm_fail_func(x,y);
 static inline void
 imm_fail_func(imm_struct *dev, int error_code)
 #else
index d93156671e93d7155505098242f821a46c1ed973..4871dd1f258296aa7fac16db51bc38c24fa104d5 100644 (file)
@@ -1403,10 +1403,10 @@ struct ipr_ucode_image_header {
 }
 
 #define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\
-       __FILE__, __FUNCTION__, __LINE__)
+       __FILE__, __func__, __LINE__)
 
-#define ENTER IPR_DBG_CMD(printk(KERN_INFO IPR_NAME": Entering %s\n", __FUNCTION__))
-#define LEAVE IPR_DBG_CMD(printk(KERN_INFO IPR_NAME": Leaving %s\n", __FUNCTION__))
+#define ENTER IPR_DBG_CMD(printk(KERN_INFO IPR_NAME": Entering %s\n", __func__))
+#define LEAVE IPR_DBG_CMD(printk(KERN_INFO IPR_NAME": Leaving %s\n", __func__))
 
 #define ipr_err_separator \
 ipr_err("----------------------------------------------------------\n")
index 744f06d04a363225cc9859b08df208a2cb0156ae..48ee8c7f5bdd270351bcdf0dae895e0ae572a3f2 100644 (file)
@@ -74,7 +74,7 @@ static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts)
                case SAS_OPEN_TO:
                case SAS_OPEN_REJECT:
                        SAS_DPRINTK("%s: Saw error %d.  What to do?\n",
-                                   __FUNCTION__, ts->stat);
+                                   __func__, ts->stat);
                        return AC_ERR_OTHER;
 
                case SAS_ABORTED_TASK:
@@ -115,7 +115,7 @@ static void sas_ata_task_done(struct sas_task *task)
        } else if (stat->stat != SAM_STAT_GOOD) {
                ac = sas_to_ata_err(stat);
                if (ac) {
-                       SAS_DPRINTK("%s: SAS error %x\n", __FUNCTION__,
+                       SAS_DPRINTK("%s: SAS error %x\n", __func__,
                                    stat->stat);
                        /* We saw a SAS error. Send a vague error. */
                        qc->err_mask = ac;
@@ -244,20 +244,20 @@ static void sas_ata_phy_reset(struct ata_port *ap)
                res = i->dft->lldd_I_T_nexus_reset(dev);
 
        if (res != TMF_RESP_FUNC_COMPLETE)
-               SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__);
+               SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__);
 
        switch (dev->sata_dev.command_set) {
                case ATA_COMMAND_SET:
-                       SAS_DPRINTK("%s: Found ATA device.\n", __FUNCTION__);
+                       SAS_DPRINTK("%s: Found ATA device.\n", __func__);
                        ap->link.device[0].class = ATA_DEV_ATA;
                        break;
                case ATAPI_COMMAND_SET:
-                       SAS_DPRINTK("%s: Found ATAPI device.\n", __FUNCTION__);
+                       SAS_DPRINTK("%s: Found ATAPI device.\n", __func__);
                        ap->link.device[0].class = ATA_DEV_ATAPI;
                        break;
                default:
                        SAS_DPRINTK("%s: Unknown SATA command set: %d.\n",
-                                   __FUNCTION__,
+                                   __func__,
                                    dev->sata_dev.command_set);
                        ap->link.device[0].class = ATA_DEV_UNKNOWN;
                        break;
@@ -299,7 +299,7 @@ static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
 {
        struct domain_device *dev = ap->private_data;
 
-       SAS_DPRINTK("STUB %s\n", __FUNCTION__);
+       SAS_DPRINTK("STUB %s\n", __func__);
        switch (sc_reg_in) {
                case SCR_STATUS:
                        dev->sata_dev.sstatus = val;
@@ -324,7 +324,7 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
 {
        struct domain_device *dev = ap->private_data;
 
-       SAS_DPRINTK("STUB %s\n", __FUNCTION__);
+       SAS_DPRINTK("STUB %s\n", __func__);
        switch (sc_reg_in) {
                case SCR_STATUS:
                        *val = dev->sata_dev.sstatus;
index aefd865a578862e3bf17b4a8d6a7f8a4a8aaffef..3da02e4367884b4f8fcc1015811b55b0bf88a968 100644 (file)
@@ -121,7 +121,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
                        break;
                } else {
                        SAS_DPRINTK("%s: task to dev %016llx response: 0x%x "
-                                   "status 0x%x\n", __FUNCTION__,
+                                   "status 0x%x\n", __func__,
                                    SAS_ADDR(dev->sas_addr),
                                    task->task_status.resp,
                                    task->task_status.stat);
@@ -1279,7 +1279,7 @@ static int sas_configure_present(struct domain_device *dev, int phy_id,
                        goto out;
                } else if (res != SMP_RESP_FUNC_ACC) {
                        SAS_DPRINTK("%s: dev %016llx phy 0x%x index 0x%x "
-                                   "result 0x%x\n", __FUNCTION__,
+                                   "result 0x%x\n", __func__,
                                    SAS_ADDR(dev->sas_addr), phy_id, i, res);
                        goto out;
                }
@@ -1901,7 +1901,7 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
        if (!rsp) {
                printk("%s: space for a smp response is missing\n",
-                      __FUNCTION__);
+                      __func__);
                return -EINVAL;
        }
 
@@ -1914,20 +1914,20 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        if (type != SAS_EDGE_EXPANDER_DEVICE &&
            type != SAS_FANOUT_EXPANDER_DEVICE) {
                printk("%s: can we send a smp request to a device?\n",
-                      __FUNCTION__);
+                      __func__);
                return -EINVAL;
        }
 
        dev = sas_find_dev_by_rphy(rphy);
        if (!dev) {
-               printk("%s: fail to find a domain_device?\n", __FUNCTION__);
+               printk("%s: fail to find a domain_device?\n", __func__);
                return -EINVAL;
        }
 
        /* do we need to support multiple segments? */
        if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
                printk("%s: multiple segments req %u %u, rsp %u %u\n",
-                      __FUNCTION__, req->bio->bi_vcnt, req->data_len,
+                      __func__, req->bio->bi_vcnt, req->data_len,
                       rsp->bio->bi_vcnt, rsp->data_len);
                return -EINVAL;
        }
index 39ae68a3b0ef57a14eefcff9112e9668deb6fe1f..139935a121b42a8eab5f1d5535db8adb8eca498f 100644 (file)
@@ -50,7 +50,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
                        sas_deform_port(phy);
                else {
                        SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n",
-                                   __FUNCTION__, phy->id, phy->port->id,
+                                   __func__, phy->id, phy->port->id,
                                    phy->port->num_phys);
                        return;
                }
@@ -78,7 +78,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
 
        if (i >= sas_ha->num_phys) {
                printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n",
-                      __FUNCTION__);
+                      __func__);
                spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
                return;
        }
index 601ec5b6a7f6ab1a240ff130b0dbc6f989b3ec4e..a8e3ef309070ae9e0da26381668e0bd847b68e0b 100644 (file)
@@ -343,7 +343,7 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
                                                       flags);
                                SAS_DPRINTK("%s: task 0x%p aborted from "
                                            "task_queue\n",
-                                           __FUNCTION__, task);
+                                           __func__, task);
                                return TASK_IS_ABORTED;
                        }
                }
@@ -351,13 +351,13 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
        }
 
        for (i = 0; i < 5; i++) {
-               SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
+               SAS_DPRINTK("%s: aborting task 0x%p\n", __func__, task);
                res = si->dft->lldd_abort_task(task);
 
                spin_lock_irqsave(&task->task_state_lock, flags);
                if (task->task_state_flags & SAS_TASK_STATE_DONE) {
                        spin_unlock_irqrestore(&task->task_state_lock, flags);
-                       SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
+                       SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
                                    task);
                        return TASK_IS_DONE;
                }
@@ -365,24 +365,24 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
 
                if (res == TMF_RESP_FUNC_COMPLETE) {
                        SAS_DPRINTK("%s: task 0x%p is aborted\n",
-                                   __FUNCTION__, task);
+                                   __func__, task);
                        return TASK_IS_ABORTED;
                } else if (si->dft->lldd_query_task) {
                        SAS_DPRINTK("%s: querying task 0x%p\n",
-                                   __FUNCTION__, task);
+                                   __func__, task);
                        res = si->dft->lldd_query_task(task);
                        switch (res) {
                        case TMF_RESP_FUNC_SUCC:
                                SAS_DPRINTK("%s: task 0x%p at LU\n",
-                                           __FUNCTION__, task);
+                                           __func__, task);
                                return TASK_IS_AT_LU;
                        case TMF_RESP_FUNC_COMPLETE:
                                SAS_DPRINTK("%s: task 0x%p not at LU\n",
-                                           __FUNCTION__, task);
+                                           __func__, task);
                                return TASK_IS_NOT_AT_LU;
                        case TMF_RESP_FUNC_FAILED:
                                 SAS_DPRINTK("%s: task 0x%p failed to abort\n",
-                                                __FUNCTION__, task);
+                                                __func__, task);
                                 return TASK_ABORT_FAILED;
                         }
 
@@ -545,7 +545,7 @@ Again:
 
                if (need_reset) {
                        SAS_DPRINTK("%s: task 0x%p requests reset\n",
-                                   __FUNCTION__, task);
+                                   __func__, task);
                        goto reset;
                }
 
@@ -556,13 +556,13 @@ Again:
 
                switch (res) {
                case TASK_IS_DONE:
-                       SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
+                       SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
                                    task);
                        sas_eh_finish_cmd(cmd);
                        continue;
                case TASK_IS_ABORTED:
                        SAS_DPRINTK("%s: task 0x%p is aborted\n",
-                                   __FUNCTION__, task);
+                                   __func__, task);
                        sas_eh_finish_cmd(cmd);
                        continue;
                case TASK_IS_AT_LU:
@@ -633,7 +633,7 @@ Again:
        }
        return list_empty(work_q);
 clear_q:
-       SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__);
+       SAS_DPRINTK("--- Exit %s -- clear_q\n", __func__);
        list_for_each_entry_safe(cmd, n, work_q, eh_entry)
                sas_eh_finish_cmd(cmd);
 
@@ -650,7 +650,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
        list_splice_init(&shost->eh_cmd_q, &eh_work_q);
        spin_unlock_irqrestore(shost->host_lock, flags);
 
-       SAS_DPRINTK("Enter %s\n", __FUNCTION__);
+       SAS_DPRINTK("Enter %s\n", __func__);
        /*
         * Deal with commands that still have SAS tasks (i.e. they didn't
         * complete via the normal sas_task completion mechanism)
@@ -669,7 +669,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
 
 out:
        scsi_eh_flush_done_q(&ha->eh_done_q);
-       SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
+       SAS_DPRINTK("--- Exit %s\n", __func__);
        return;
 }
 
@@ -990,7 +990,7 @@ int __sas_task_abort(struct sas_task *task)
        if (task->task_state_flags & SAS_TASK_STATE_ABORTED ||
            task->task_state_flags & SAS_TASK_STATE_DONE) {
                spin_unlock_irqrestore(&task->task_state_lock, flags);
-               SAS_DPRINTK("%s: Task %p already finished.\n", __FUNCTION__,
+               SAS_DPRINTK("%s: Task %p already finished.\n", __func__,
                            task);
                return 0;
        }
index 6d6a76e65a6c3fc9e391c17b2fe34cf61176f718..15e2d132e8b9e07b99d39c4079557a3d16604cc3 100644 (file)
@@ -39,7 +39,7 @@ enum srp_task_attributes {
 /* tmp - will replace with SCSI logging stuff */
 #define eprintk(fmt, args...)                                  \
 do {                                                           \
-       printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args);  \
+       printk("%s(%d) " fmt, __func__, __LINE__, ##args);      \
 } while (0)
 /* #define dprintk eprintk */
 #define dprintk(fmt, args...)
index 5b6e5395c8eb0313c1d23524a4bfd2b381ce3ed9..d51a2a4b43eb662f61a6603a21b3b5feb2337385 100644 (file)
@@ -2083,7 +2083,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
                if (iocbq_entry == NULL) {
                        printk(KERN_ERR "%s: only allocated %d iocbs of "
                                "expected %d count. Unloading driver.\n",
-                               __FUNCTION__, i, LPFC_IOCB_LIST_CNT);
+                               __func__, i, LPFC_IOCB_LIST_CNT);
                        error = -ENOMEM;
                        goto out_free_iocbq;
                }
@@ -2093,7 +2093,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
                        kfree (iocbq_entry);
                        printk(KERN_ERR "%s: failed to allocate IOTAG. "
                               "Unloading driver.\n",
-                               __FUNCTION__);
+                               __func__);
                        error = -ENOMEM;
                        goto out_free_iocbq;
                }
index c94da4f2b8a6eb8dc196ec1ee6b674242a020eb5..1bcebbd3dfacf8a3588abbeece892e19f44eadd3 100644 (file)
@@ -341,7 +341,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
                if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
                        printk(KERN_ERR "%s: Too many sg segments from "
                               "dma_map_sg.  Config %d, seg_cnt %d",
-                              __FUNCTION__, phba->cfg_sg_seg_cnt,
+                              __func__, phba->cfg_sg_seg_cnt,
                               lpfc_cmd->seg_cnt);
                        scsi_dma_unmap(scsi_cmnd);
                        return 1;
index f40aa7b905f716e335b4d30b33e1859ed478b214..50fe07646738cc20043de2d56452063f64673296 100644 (file)
@@ -219,7 +219,7 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
        case CMD_IOCB_LOGENTRY_CN:
        case CMD_IOCB_LOGENTRY_ASYNC_CN:
                printk("%s - Unhandled SLI-3 Command x%x\n",
-                               __FUNCTION__, iocb_cmnd);
+                               __func__, iocb_cmnd);
                type = LPFC_UNKNOWN_IOCB;
                break;
        default:
@@ -1715,7 +1715,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
                rspiocbp = __lpfc_sli_get_iocbq(phba);
                if (rspiocbp == NULL) {
                        printk(KERN_ERR "%s: out of buffers! Failing "
-                              "completion.\n", __FUNCTION__);
+                              "completion.\n", __func__);
                        break;
                }
 
@@ -3793,7 +3793,7 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
                break;
        default:
                printk(KERN_ERR "%s: Unknown context cmd type, value %d\n",
-                       __FUNCTION__, ctx_cmd);
+                       __func__, ctx_cmd);
                break;
        }
 
index f62ed468ada0bc5ce44ce371a42f708310f3d9d7..5ead1283a84424cfad432a6247e4020899ef7bdd 100644 (file)
@@ -265,7 +265,7 @@ typedef struct {
 #define ASSERT(expression)                                             \
        if (!(expression)) {                                            \
        ASSERT_ACTION("assertion failed:(%s), file: %s, line: %d:%s\n", \
-                       #expression, __FILE__, __LINE__, __FUNCTION__); \
+                       #expression, __FILE__, __LINE__, __func__);     \
        }
 #else
 #define ASSERT(expression)
index 70a0f11f48b235d769b1efb088d1c9bd2c98f949..805bb61dde1871946b5c4cce24c0314e7efa79e5 100644 (file)
@@ -458,7 +458,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        if (adapter == NULL) {
                con_log(CL_ANN, (KERN_WARNING
-               "megaraid: out of memory, %s %d.\n", __FUNCTION__, __LINE__));
+               "megaraid: out of memory, %s %d.\n", __func__, __LINE__));
 
                goto out_probe_one;
        }
@@ -1002,7 +1002,7 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
 
        if (!raid_dev->una_mbox64) {
                con_log(CL_ANN, (KERN_WARNING
-                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       "megaraid: out of memory, %s %d\n", __func__,
                        __LINE__));
                return -1;
        }
@@ -1030,7 +1030,7 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
        if (!adapter->ibuf) {
 
                con_log(CL_ANN, (KERN_WARNING
-                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       "megaraid: out of memory, %s %d\n", __func__,
                        __LINE__));
 
                goto out_free_common_mbox;
@@ -1052,7 +1052,7 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
 
        if (adapter->kscb_list == NULL) {
                con_log(CL_ANN, (KERN_WARNING
-                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       "megaraid: out of memory, %s %d\n", __func__,
                        __LINE__));
                goto out_free_ibuf;
        }
@@ -1060,7 +1060,7 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
        // memory allocation for our command packets
        if (megaraid_mbox_setup_dma_pools(adapter) != 0) {
                con_log(CL_ANN, (KERN_WARNING
-                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       "megaraid: out of memory, %s %d\n", __func__,
                        __LINE__));
                goto out_free_scb_list;
        }
@@ -2981,7 +2981,7 @@ megaraid_mbox_product_info(adapter_t *adapter)
 
        if (pinfo == NULL) {
                con_log(CL_ANN, (KERN_WARNING
-                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       "megaraid: out of memory, %s %d\n", __func__,
                        __LINE__));
 
                return -1;
@@ -3508,7 +3508,7 @@ megaraid_cmm_register(adapter_t *adapter)
 
        if (adapter->uscb_list == NULL) {
                con_log(CL_ANN, (KERN_WARNING
-                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       "megaraid: out of memory, %s %d\n", __func__,
                        __LINE__));
                return -1;
        }
@@ -3879,7 +3879,7 @@ megaraid_sysfs_alloc_resources(adapter_t *adapter)
                !raid_dev->sysfs_buffer) {
 
                con_log(CL_ANN, (KERN_WARNING
-                       "megaraid: out of memory, %s %d\n", __FUNCTION__,
+                       "megaraid: out of memory, %s %d\n", __func__,
                        __LINE__));
 
                rval = -ENOMEM;
index ac3b280c2a72abb7a310834b4ae45a924327db32..f680561d2c6f6101bac31fb4ad5ef7dcf2ded20c 100644 (file)
@@ -929,7 +929,7 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
                        !adapter->pthru_dma_pool) {
 
                con_log(CL_ANN, (KERN_WARNING
-                       "megaraid cmm: out of memory, %s %d\n", __FUNCTION__,
+                       "megaraid cmm: out of memory, %s %d\n", __func__,
                        __LINE__));
 
                rval = (-ENOMEM);
@@ -957,7 +957,7 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
 
                        con_log(CL_ANN, (KERN_WARNING
                                "megaraid cmm: out of memory, %s %d\n",
-                                       __FUNCTION__, __LINE__));
+                                       __func__, __LINE__));
 
                        rval = (-ENOMEM);
 
index 7fed35372150afe68d619d61d4faa4a2a4588437..edf9fdb3cb3c7dda1faa3059defdd66501eefe58 100644 (file)
@@ -299,9 +299,9 @@ static struct scsi_host_template nsp32_template = {
 #else
 # define NSP32_DEBUG_MASK            0xffffff
 # define nsp32_msg(type, args...) \
-       nsp32_message (__FUNCTION__, __LINE__, (type), args)
+       nsp32_message (__func__, __LINE__, (type), args)
 # define nsp32_dbg(mask, args...) \
-       nsp32_dmessage(__FUNCTION__, __LINE__, (mask), args)
+       nsp32_dmessage(__func__, __LINE__, (mask), args)
 #endif
 
 #define NSP32_DEBUG_QUEUECOMMAND       BIT(0)
index ef3c59cbcff601b6a1274e07349699c98efc240b..2fb3fb58858da6888accef3073f29f41423ff03d 100644 (file)
@@ -88,7 +88,7 @@ static void print_commandk (unsigned char *command)
        int i,s;
 //     printk(KERN_DEBUG);
        print_opcodek(command[0]);
-       /*printk(KERN_DEBUG "%s ", __FUNCTION__);*/
+       /*printk(KERN_DEBUG "%s ", __func__);*/
        if ((command[0] >> 5) == 6 ||
            (command[0] >> 5) == 7 ) {
                s = 12; /* vender specific */
index 5082ca3c6876035df3818035873a47f1e6d181f9..a221b6ef9fa991dac4e685c4e8ac290a6cb50be8 100644 (file)
@@ -107,9 +107,9 @@ static nsp_hw_data nsp_data_base; /* attach <-> detect glue */
 #else
 # define NSP_DEBUG_MASK                0xffffff
 # define nsp_msg(type, args...) \
-       nsp_cs_message (__FUNCTION__, __LINE__, (type), args)
+       nsp_cs_message (__func__, __LINE__, (type), args)
 # define nsp_dbg(mask, args...) \
-       nsp_cs_dmessage(__FUNCTION__, __LINE__, (mask), args)
+       nsp_cs_dmessage(__func__, __LINE__, (mask), args)
 #endif
 
 #define NSP_DEBUG_QUEUECOMMAND         BIT(0)
index 2f75fe6e35a732d5eb10d3f2f174207c2f56add4..3c6ef64fcbff709f233181411b81f50e23221e1b 100644 (file)
@@ -90,7 +90,7 @@ static void print_commandk (unsigned char *command)
        int i, s;
        printk(KERN_DEBUG);
        print_opcodek(command[0]);
-       /*printk(KERN_DEBUG "%s ", __FUNCTION__);*/
+       /*printk(KERN_DEBUG "%s ", __func__);*/
        if ((command[0] >> 5) == 6 ||
            (command[0] >> 5) == 7 ) {
                s = 12; /* vender specific */
index f655ae320b483cfc418a30691b601f23a271b328..8aa0bd987e29e95d2f18578e8d64c9900e59062e 100644 (file)
@@ -171,7 +171,7 @@ static int device_check(ppa_struct *dev);
 
 #if PPA_DEBUG > 0
 #define ppa_fail(x,y) printk("ppa: ppa_fail(%i) from %s at line %d\n",\
-          y, __FUNCTION__, __LINE__); ppa_fail_func(x,y);
+          y, __func__, __LINE__); ppa_fail_func(x,y);
 static inline void ppa_fail_func(ppa_struct *dev, int error_code)
 #else
 static inline void ppa_fail(ppa_struct *dev, int error_code)
index 3754ab87f89a0d89ca534db70d371527abd41c9c..37f9ba0cd798cf975a0139e5bf1fae99f5508923 100644 (file)
@@ -1695,7 +1695,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
        risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
 
        dprintk(1, "%s: DMA RISC code (%i) words\n",
-                       __FUNCTION__, risc_code_size);
+                       __func__, risc_code_size);
 
        num = 0;
        while (risc_code_size > 0) {
@@ -1721,7 +1721,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
                mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff;
                mb[6] = pci_dma_hi32(ha->request_dma) >> 16;
                dprintk(2, "%s: op=%d  0x%p = 0x%4x,0x%4x,0x%4x,0x%4x\n",
-                               __FUNCTION__, mb[0],
+                               __func__, mb[0],
                                (void *)(long)ha->request_dma,
                                mb[6], mb[7], mb[2], mb[3]);
                err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
@@ -1753,10 +1753,10 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
                        if (tbuf[i] != sp[i] && warn++ < 10) {
                                printk(KERN_ERR "%s: FW compare error @ "
                                                "byte(0x%x) loop#=%x\n",
-                                               __FUNCTION__, i, num);
+                                               __func__, i, num);
                                printk(KERN_ERR "%s: FWbyte=%x  "
                                                "FWfromChip=%x\n",
-                                               __FUNCTION__, sp[i], tbuf[i]);
+                                               __func__, sp[i], tbuf[i]);
                                /*break; */
                        }
                }
@@ -1781,7 +1781,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
        int err;
 
        dprintk(1, "%s: Verifying checksum of loaded RISC code.\n",
-                       __FUNCTION__);
+                       __func__);
 
        /* Verify checksum of loaded RISC code. */
        mb[0] = MBC_VERIFY_CHECKSUM;
@@ -1794,7 +1794,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
        }
 
        /* Start firmware execution. */
-       dprintk(1, "%s: start firmware running.\n", __FUNCTION__);
+       dprintk(1, "%s: start firmware running.\n", __func__);
        mb[0] = MBC_EXECUTE_FIRMWARE;
        mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
        err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
index 8dd88fc1244a60e688ed9e18a217707ee3976905..a319a20ed440748da301b5a268941d5e57d00294 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/kthread.h>
 #include <linux/vmalloc.h>
+#include <linux/delay.h>
 
 static int qla24xx_vport_disable(struct fc_vport *, bool);
 
@@ -20,18 +21,12 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
 {
        struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
-       char *rbuf = (char *)ha->fw_dump;
 
        if (ha->fw_dump_reading == 0)
                return 0;
-       if (off > ha->fw_dump_len)
-                return 0;
-       if (off + count > ha->fw_dump_len)
-               count = ha->fw_dump_len - off;
 
-       memcpy(buf, &rbuf[off], count);
-
-       return (count);
+       return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
+                                       ha->fw_dump_len);
 }
 
 static ssize_t
@@ -94,20 +89,13 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj,
 {
        struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
-       int             size = ha->nvram_size;
-       char            *nvram_cache = ha->nvram;
 
-       if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
+       if (!capable(CAP_SYS_ADMIN))
                return 0;
-       if (off + count > size) {
-               size -= off;
-               count = size;
-       }
 
        /* Read NVRAM data from cache. */
-       memcpy(buf, &nvram_cache[off], count);
-
-       return count;
+       return memory_read_from_buffer(buf, count, &off, ha->nvram,
+                                       ha->nvram_size);
 }
 
 static ssize_t
@@ -175,14 +163,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj,
 
        if (ha->optrom_state != QLA_SREADING)
                return 0;
-       if (off > ha->optrom_region_size)
-               return 0;
-       if (off + count > ha->optrom_region_size)
-               count = ha->optrom_region_size - off;
-
-       memcpy(buf, &ha->optrom_buffer[off], count);
 
-       return count;
+       return memory_read_from_buffer(buf, count, &off, ha->optrom_buffer,
+                                       ha->optrom_region_size);
 }
 
 static ssize_t
@@ -374,20 +357,12 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj,
 {
        struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
-       int           size = ha->vpd_size;
-       char          *vpd_cache = ha->vpd;
 
-       if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
+       if (!capable(CAP_SYS_ADMIN))
                return 0;
-       if (off + count > size) {
-               size -= off;
-               count = size;
-       }
 
        /* Read NVRAM data from cache. */
-       memcpy(buf, &vpd_cache[off], count);
-
-       return count;
+       return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
 }
 
 static ssize_t
@@ -557,8 +532,10 @@ qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
        scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
        uint32_t sn;
 
-       if (IS_FWI2_CAPABLE(ha))
-               return snprintf(buf, PAGE_SIZE, "\n");
+       if (IS_FWI2_CAPABLE(ha)) {
+               qla2xxx_get_vpd_field(ha, "SN", buf, PAGE_SIZE);
+               return snprintf(buf, PAGE_SIZE, "%s\n", buf);
+       }
 
        sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
        return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
@@ -809,6 +786,16 @@ qla2x00_optrom_fw_version_show(struct device *dev,
            ha->fw_revision[3]);
 }
 
+static ssize_t
+qla2x00_total_isp_aborts_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+           ha->qla_stats.total_isp_aborts);
+}
+
 static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
 static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
 static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
@@ -831,6 +818,8 @@ static DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
                   qla2x00_optrom_fcode_version_show, NULL);
 static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
                   NULL);
+static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
+                  NULL);
 
 struct device_attribute *qla2x00_host_attrs[] = {
        &dev_attr_driver_version,
@@ -849,6 +838,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
        &dev_attr_optrom_efi_version,
        &dev_attr_optrom_fcode_version,
        &dev_attr_optrom_fw_version,
+       &dev_attr_total_isp_aborts,
        NULL,
 };
 
@@ -972,26 +962,39 @@ qla2x00_get_starget_port_id(struct scsi_target *starget)
 }
 
 static void
-qla2x00_get_rport_loss_tmo(struct fc_rport *rport)
+qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
 {
-       struct Scsi_Host *host = rport_to_shost(rport);
-       scsi_qla_host_t *ha = shost_priv(host);
-
-       rport->dev_loss_tmo = ha->port_down_retry_count + 5;
+       if (timeout)
+               rport->dev_loss_tmo = timeout;
+       else
+               rport->dev_loss_tmo = 1;
 }
 
 static void
-qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
 {
        struct Scsi_Host *host = rport_to_shost(rport);
-       scsi_qla_host_t *ha = shost_priv(host);
+       fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+
+       qla2x00_abort_fcport_cmds(fcport);
+
+       /*
+        * Transport has effectively 'deleted' the rport, clear
+        * all local references.
+        */
+       spin_lock_irq(host->host_lock);
+       fcport->rport = NULL;
+       *((fc_port_t **)rport->dd_data) = NULL;
+       spin_unlock_irq(host->host_lock);
+}
 
-       if (timeout)
-               ha->port_down_retry_count = timeout;
-       else
-               ha->port_down_retry_count = 1;
+static void
+qla2x00_terminate_rport_io(struct fc_rport *rport)
+{
+       fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
 
-       rport->dev_loss_tmo = ha->port_down_retry_count + 5;
+       qla2x00_abort_fcport_cmds(fcport);
+       scsi_target_unblock(&rport->dev);
 }
 
 static int
@@ -1045,6 +1048,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
        pfc_host_stat->invalid_tx_word_count = stats->inval_xmit_word_cnt;
        pfc_host_stat->invalid_crc_count = stats->inval_crc_cnt;
        if (IS_FWI2_CAPABLE(ha)) {
+               pfc_host_stat->lip_count = stats->lip_cnt;
                pfc_host_stat->tx_frames = stats->tx_frames;
                pfc_host_stat->rx_frames = stats->rx_frames;
                pfc_host_stat->dumped_frames = stats->dumped_frames;
@@ -1173,17 +1177,16 @@ vport_create_failed_2:
 static int
 qla24xx_vport_delete(struct fc_vport *fc_vport)
 {
-       scsi_qla_host_t *ha = shost_priv(fc_vport->shost);
        scsi_qla_host_t *vha = fc_vport->dd_data;
+       scsi_qla_host_t *pha = to_qla_parent(vha);
+
+       while (test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags) ||
+           test_bit(FCPORT_UPDATE_NEEDED, &pha->dpc_flags))
+               msleep(1000);
 
        qla24xx_disable_vp(vha);
        qla24xx_deallocate_vp_id(vha);
 
-       mutex_lock(&ha->vport_lock);
-       ha->cur_vport_count--;
-       clear_bit(vha->vp_idx, ha->vp_idx_map);
-       mutex_unlock(&ha->vport_lock);
-
        kfree(vha->node_name);
        kfree(vha->port_name);
 
@@ -1248,11 +1251,12 @@ struct fc_function_template qla2xxx_transport_functions = {
        .get_starget_port_id  = qla2x00_get_starget_port_id,
        .show_starget_port_id = 1,
 
-       .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
        .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
        .show_rport_dev_loss_tmo = 1,
 
        .issue_fc_host_lip = qla2x00_issue_lip,
+       .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
+       .terminate_rport_io = qla2x00_terminate_rport_io,
        .get_fc_host_stats = qla2x00_get_fc_host_stats,
 
        .vport_create = qla24xx_vport_create,
@@ -1291,11 +1295,12 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
        .get_starget_port_id  = qla2x00_get_starget_port_id,
        .show_starget_port_id = 1,
 
-       .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
        .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
        .show_rport_dev_loss_tmo = 1,
 
        .issue_fc_host_lip = qla2x00_issue_lip,
+       .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
+       .terminate_rport_io = qla2x00_terminate_rport_io,
        .get_fc_host_stats = qla2x00_get_fc_host_stats,
 };
 
index cbef785765cf2ead72b64899a260a75bfca849d2..510ba64bc286e185cd85346c5728761bc09d7fa5 100644 (file)
@@ -216,7 +216,7 @@ qla24xx_soft_reset(scsi_qla_host_t *ha)
 
 static int
 qla2xxx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint16_t *ram,
-    uint16_t ram_words, void **nxt)
+    uint32_t ram_words, void **nxt)
 {
        int rval;
        uint32_t cnt, stat, timer, words, idx;
index 8dd600013bd1ca4d8c87dcf4b73b1b254a810474..6da31ba94404f7bf6b48f418a3ba18829569adb8 100644 (file)
@@ -864,7 +864,8 @@ struct link_statistics {
        uint32_t prim_seq_err_cnt;
        uint32_t inval_xmit_word_cnt;
        uint32_t inval_crc_cnt;
-       uint32_t unused1[0x1b];
+       uint32_t lip_cnt;
+       uint32_t unused1[0x1a];
        uint32_t tx_frames;
        uint32_t rx_frames;
        uint32_t dumped_frames;
@@ -1544,7 +1545,6 @@ typedef struct fc_port {
        int login_retry;
        atomic_t port_down_timer;
 
-       spinlock_t rport_lock;
        struct fc_rport *rport, *drport;
        u32 supported_classes;
 
@@ -2155,6 +2155,10 @@ struct qla_chip_state_84xx {
        uint32_t gold_fw_version;
 };
 
+struct qla_statistics {
+       uint32_t total_isp_aborts;
+};
+
 /*
  * Linux Host Adapter structure
  */
@@ -2166,7 +2170,6 @@ typedef struct scsi_qla_host {
        struct pci_dev  *pdev;
 
        unsigned long   host_no;
-       unsigned long   instance;
 
        volatile struct {
                uint32_t        init_done               :1;
@@ -2515,7 +2518,7 @@ typedef struct scsi_qla_host {
 
        uint8_t         model_number[16+1];
 #define BINZERO                "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-       char            *model_desc;
+       char            model_desc[80];
        uint8_t         adapter_id[16+1];
 
        uint8_t         *node_name;
@@ -2596,6 +2599,7 @@ typedef struct scsi_qla_host {
        int             cur_vport_count;
 
        struct qla_chip_state_84xx *cs84xx;
+       struct qla_statistics qla_stats;
 } scsi_qla_host_t;
 
 
index 9b4bebee6879fe6f19bcaad2f3433338659b40b2..0b156735e9a65ee8356b520004d3302b034d261e 100644 (file)
@@ -62,7 +62,7 @@ extern int ql2xfdmienable;
 extern int ql2xallocfwdump;
 extern int ql2xextended_error_logging;
 extern int ql2xqfullrampup;
-extern int num_hosts;
+extern int ql2xiidmaenable;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -71,6 +71,8 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
 extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
     uint16_t, uint16_t);
 
+extern void qla2x00_abort_fcport_cmds(fc_port_t *);
+
 /*
  * Global Functions in qla_mid.c source file.
  */
@@ -312,6 +314,7 @@ extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
     uint16_t, uint16_t);
 
 extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
+extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
 
 /*
  * Global Function Prototypes in qla_dbg.c source file.
index 4cb80b476c85c69c65277d5de2709f863f13a958..c2a4bfbcb05bc2ecf4ffa7a20d763ea7d86bf4b9 100644 (file)
@@ -1661,6 +1661,12 @@ qla2x00_fdmi_register(scsi_qla_host_t *ha)
 {
        int rval;
 
+       if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
+               DEBUG2(printk("scsi(%ld): FDMI unsupported on "
+                   "ISP2100/ISP2200.\n", ha->host_no));
+               return QLA_SUCCESS;
+       }
+
        rval = qla2x00_mgmt_svr_login(ha);
        if (rval)
                return rval;
index bbbc5a632a1d22f2334761283bfa1db4254a5ff2..601a6b29750c5beec1d52cc1b5638b396073f7f2 100644 (file)
@@ -334,6 +334,8 @@ static int
 qla2x00_isp_firmware(scsi_qla_host_t *ha)
 {
        int  rval;
+       uint16_t loop_id, topo, sw_cap;
+       uint8_t domain, area, al_pa;
 
        /* Assume loading risc code */
        rval = QLA_FUNCTION_FAILED;
@@ -345,6 +347,11 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha)
 
                /* Verify checksum of loaded RISC code. */
                rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address);
+               if (rval == QLA_SUCCESS) {
+                       /* And, verify we are not in ROM code. */
+                       rval = qla2x00_get_adapter_id(ha, &loop_id, &al_pa,
+                           &area, &domain, &topo, &sw_cap);
+               }
        }
 
        if (rval) {
@@ -722,7 +729,7 @@ qla24xx_chip_diag(scsi_qla_host_t *ha)
        /* Perform RISC reset. */
        qla24xx_reset_risc(ha);
 
-       ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024;
+       ha->fw_transfer_size = REQUEST_ENTRY_SIZE * ha->request_q_length;
 
        rval = qla2x00_mbx_reg_test(ha);
        if (rval) {
@@ -768,42 +775,16 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
                mem_size = (ha->fw_memory_size - 0x100000 + 1) *
                    sizeof(uint32_t);
 
-               /* Allocate memory for Extended Trace Buffer. */
-               tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
-                   GFP_KERNEL);
-               if (!tc) {
-                       qla_printk(KERN_WARNING, ha, "Unable to allocate "
-                           "(%d KB) for EFT.\n", EFT_SIZE / 1024);
-                       goto cont_alloc;
-               }
-
-               memset(tc, 0, EFT_SIZE);
-               rval = qla2x00_enable_eft_trace(ha, tc_dma, EFT_NUM_BUFFERS);
-               if (rval) {
-                       qla_printk(KERN_WARNING, ha, "Unable to initialize "
-                           "EFT (%d).\n", rval);
-                       dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
-                           tc_dma);
-                       goto cont_alloc;
-               }
-
-               qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n",
-                   EFT_SIZE / 1024);
-
-               eft_size = EFT_SIZE;
-               ha->eft_dma = tc_dma;
-               ha->eft = tc;
-
                /* Allocate memory for Fibre Channel Event Buffer. */
                if (!IS_QLA25XX(ha))
-                       goto cont_alloc;
+                       goto try_eft;
 
                tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
                    GFP_KERNEL);
                if (!tc) {
                        qla_printk(KERN_WARNING, ha, "Unable to allocate "
                            "(%d KB) for FCE.\n", FCE_SIZE / 1024);
-                       goto cont_alloc;
+                       goto try_eft;
                }
 
                memset(tc, 0, FCE_SIZE);
@@ -815,7 +796,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
                        dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
                            tc_dma);
                        ha->flags.fce_enabled = 0;
-                       goto cont_alloc;
+                       goto try_eft;
                }
 
                qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n",
@@ -825,6 +806,32 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
                ha->flags.fce_enabled = 1;
                ha->fce_dma = tc_dma;
                ha->fce = tc;
+try_eft:
+               /* Allocate memory for Extended Trace Buffer. */
+               tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
+                   GFP_KERNEL);
+               if (!tc) {
+                       qla_printk(KERN_WARNING, ha, "Unable to allocate "
+                           "(%d KB) for EFT.\n", EFT_SIZE / 1024);
+                       goto cont_alloc;
+               }
+
+               memset(tc, 0, EFT_SIZE);
+               rval = qla2x00_enable_eft_trace(ha, tc_dma, EFT_NUM_BUFFERS);
+               if (rval) {
+                       qla_printk(KERN_WARNING, ha, "Unable to initialize "
+                           "EFT (%d).\n", rval);
+                       dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
+                           tc_dma);
+                       goto cont_alloc;
+               }
+
+               qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n",
+                   EFT_SIZE / 1024);
+
+               eft_size = EFT_SIZE;
+               ha->eft_dma = tc_dma;
+               ha->eft = tc;
        }
 cont_alloc:
        req_q_size = ha->request_q_length * sizeof(request_t);
@@ -1501,18 +1508,25 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
                index = (ha->pdev->subsystem_device & 0xff);
                if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
                    index < QLA_MODEL_NAMES)
-                       ha->model_desc = qla2x00_model_name[index * 2 + 1];
+                       strncpy(ha->model_desc,
+                           qla2x00_model_name[index * 2 + 1],
+                           sizeof(ha->model_desc) - 1);
        } else {
                index = (ha->pdev->subsystem_device & 0xff);
                if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
                    index < QLA_MODEL_NAMES) {
                        strcpy(ha->model_number,
                            qla2x00_model_name[index * 2]);
-                       ha->model_desc = qla2x00_model_name[index * 2 + 1];
+                       strncpy(ha->model_desc,
+                           qla2x00_model_name[index * 2 + 1],
+                           sizeof(ha->model_desc) - 1);
                } else {
                        strcpy(ha->model_number, def);
                }
        }
+       if (IS_FWI2_CAPABLE(ha))
+               qla2xxx_get_vpd_field(ha, "\x82", ha->model_desc,
+                   sizeof(ha->model_desc));
 }
 
 /* On sparc systems, obtain port and node WWN from firmware
@@ -1864,12 +1878,11 @@ qla2x00_rport_del(void *data)
 {
        fc_port_t *fcport = data;
        struct fc_rport *rport;
-       unsigned long flags;
 
-       spin_lock_irqsave(&fcport->rport_lock, flags);
+       spin_lock_irq(fcport->ha->host->host_lock);
        rport = fcport->drport;
        fcport->drport = NULL;
-       spin_unlock_irqrestore(&fcport->rport_lock, flags);
+       spin_unlock_irq(fcport->ha->host->host_lock);
        if (rport)
                fc_remote_port_delete(rport);
 }
@@ -1898,7 +1911,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
        atomic_set(&fcport->state, FCS_UNCONFIGURED);
        fcport->flags = FCF_RLC_SUPPORT;
        fcport->supported_classes = FC_COS_UNSPECIFIED;
-       spin_lock_init(&fcport->rport_lock);
 
        return fcport;
 }
@@ -2007,8 +2019,10 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
        if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
                if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))
                        set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
-               if (test_bit(RSCN_UPDATE, &save_flags))
+               if (test_bit(RSCN_UPDATE, &save_flags)) {
+                       ha->flags.rscn_queue_overflow = 1;
                        set_bit(RSCN_UPDATE, &ha->dpc_flags);
+               }
        }
 
        return (rval);
@@ -2243,28 +2257,24 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
 {
        struct fc_rport_identifiers rport_ids;
        struct fc_rport *rport;
-       unsigned long flags;
 
        if (fcport->drport)
                qla2x00_rport_del(fcport);
-       if (fcport->rport)
-               return;
 
        rport_ids.node_name = wwn_to_u64(fcport->node_name);
        rport_ids.port_name = wwn_to_u64(fcport->port_name);
        rport_ids.port_id = fcport->d_id.b.domain << 16 |
            fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
        rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
-       rport = fc_remote_port_add(ha->host, 0, &rport_ids);
+       fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids);
        if (!rport) {
                qla_printk(KERN_WARNING, ha,
                    "Unable to allocate fc remote port!\n");
                return;
        }
-       spin_lock_irqsave(&fcport->rport_lock, flags);
-       fcport->rport = rport;
+       spin_lock_irq(fcport->ha->host->host_lock);
        *((fc_port_t **)rport->dd_data) = fcport;
-       spin_unlock_irqrestore(&fcport->rport_lock, flags);
+       spin_unlock_irq(fcport->ha->host->host_lock);
 
        rport->supported_classes = fcport->supported_classes;
 
@@ -2565,7 +2575,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
                } else if (qla2x00_gnn_id(ha, swl) != QLA_SUCCESS) {
                        kfree(swl);
                        swl = NULL;
-               } else if (qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) {
+               } else if (ql2xiidmaenable &&
+                   qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) {
                        qla2x00_gpsc(ha, swl);
                }
        }
@@ -3220,7 +3231,8 @@ qla2x00_update_fcports(scsi_qla_host_t *ha)
 
        /* Go with deferred removal of rport references. */
        list_for_each_entry(fcport, &ha->fcports, list)
-               if (fcport->drport)
+               if (fcport->drport &&
+                   atomic_read(&fcport->state) != FCS_UNCONFIGURED)
                        qla2x00_rport_del(fcport);
 }
 
@@ -3243,6 +3255,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
        if (ha->flags.online) {
                ha->flags.online = 0;
                clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+               ha->qla_stats.total_isp_aborts++;
 
                qla_printk(KERN_INFO, ha,
                    "Performing ISP error recovery - ha= %p.\n", ha);
@@ -3283,17 +3296,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
                        ha->isp_abort_cnt = 0;
                        clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
 
-                       if (ha->eft) {
-                               memset(ha->eft, 0, EFT_SIZE);
-                               rval = qla2x00_enable_eft_trace(ha,
-                                   ha->eft_dma, EFT_NUM_BUFFERS);
-                               if (rval) {
-                                       qla_printk(KERN_WARNING, ha,
-                                           "Unable to reinitialize EFT "
-                                           "(%d).\n", rval);
-                               }
-                       }
-
                        if (ha->fce) {
                                ha->flags.fce_enabled = 1;
                                memset(ha->fce, 0,
@@ -3308,6 +3310,17 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
                                        ha->flags.fce_enabled = 0;
                                }
                        }
+
+                       if (ha->eft) {
+                               memset(ha->eft, 0, EFT_SIZE);
+                               rval = qla2x00_enable_eft_trace(ha,
+                                   ha->eft_dma, EFT_NUM_BUFFERS);
+                               if (rval) {
+                                       qla_printk(KERN_WARNING, ha,
+                                           "Unable to reinitialize EFT "
+                                           "(%d).\n", rval);
+                               }
+                       }
                } else {        /* failed the ISP abort */
                        ha->flags.online = 1;
                        if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
@@ -4026,8 +4039,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha)
        ret = qla2x00_stop_firmware(ha);
        for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
            retries ; retries--) {
-               qla2x00_reset_chip(ha);
-               if (qla2x00_chip_diag(ha) != QLA_SUCCESS)
+               ha->isp_ops->reset_chip(ha);
+               if (ha->isp_ops->chip_diag(ha) != QLA_SUCCESS)
                        continue;
                if (qla2x00_setup_chip(ha) != QLA_SUCCESS)
                        continue;
@@ -4049,7 +4062,7 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
        rval = qla2x00_fw_ready(ha->parent);
        if (rval == QLA_SUCCESS) {
                clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
-               qla2x00_marker(ha->parent, 0, 0, MK_SYNC_ALL);
+               qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
        }
 
        ha->flags.management_server_logged_in = 0;
index 5489d5024673a326b5345f5545151a7dab37a533..d57669aa4615d33d80fe87cfe1f9550555466518 100644 (file)
@@ -454,10 +454,11 @@ qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
 {
        int ret;
        unsigned long flags = 0;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock_irqsave(&pha->hardware_lock, flags);
        ret = __qla2x00_marker(ha, loop_id, lun, type);
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irqrestore(&pha->hardware_lock, flags);
 
        return (ret);
 }
@@ -672,7 +673,7 @@ qla24xx_start_scsi(srb_t *sp)
 {
        int             ret, nseg;
        unsigned long   flags;
-       scsi_qla_host_t *ha;
+       scsi_qla_host_t *ha, *pha;
        struct scsi_cmnd *cmd;
        uint32_t        *clr_ptr;
        uint32_t        index;
@@ -686,6 +687,7 @@ qla24xx_start_scsi(srb_t *sp)
        /* Setup device pointers. */
        ret = 0;
        ha = sp->ha;
+       pha = to_qla_parent(ha);
        reg = &ha->iobase->isp24;
        cmd = sp->cmd;
        /* So we know we haven't pci_map'ed anything yet */
@@ -700,7 +702,7 @@ qla24xx_start_scsi(srb_t *sp)
        }
 
        /* Acquire ring specific lock */
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock_irqsave(&pha->hardware_lock, flags);
 
        /* Check for room in outstanding command list. */
        handle = ha->current_outstanding_cmd;
@@ -795,14 +797,14 @@ qla24xx_start_scsi(srb_t *sp)
            ha->response_ring_ptr->signature != RESPONSE_PROCESSED)
                qla24xx_process_response_queue(ha);
 
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irqrestore(&pha->hardware_lock, flags);
        return QLA_SUCCESS;
 
 queuing_error:
        if (tot_dsds)
                scsi_dma_unmap(cmd);
 
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irqrestore(&pha->hardware_lock, flags);
 
        return QLA_FUNCTION_FAILED;
 }
index ec63b79f900ae4216b02f95ec7ebb2b812d2541b..874d802edb7de482c79774bd760bdf61a7210ca4 100644 (file)
@@ -542,10 +542,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                break;
 
        case MBA_PORT_UPDATE:           /* Port database update */
-               /* Only handle SCNs for our Vport index. */
-               if (ha->parent && ha->vp_idx != (mb[3] & 0xff))
-                       break;
-
                /*
                 * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
                 * event etc. earlier indicating loop is down) then process
index 250d2f604397b02aca0840e5a8b4100f2378cb63..bc90d6b8d0a0d940bf1114c79c818cebc7ee81c5 100644 (file)
@@ -918,6 +918,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
        rval = qla2x00_mailbox_command(ha, mcp);
        if (mcp->mb[0] == MBS_COMMAND_ERROR)
                rval = QLA_COMMAND_ERROR;
+       else if (mcp->mb[0] == MBS_INVALID_COMMAND)
+               rval = QLA_INVALID_COMMAND;
 
        /* Return data. */
        *id = mcp->mb[1];
@@ -2161,17 +2163,18 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
        struct abort_entry_24xx *abt;
        dma_addr_t      abt_dma;
        uint32_t        handle;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        fcport = sp->fcport;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock_irqsave(&pha->hardware_lock, flags);
        for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
-               if (ha->outstanding_cmds[handle] == sp)
+               if (pha->outstanding_cmds[handle] == sp)
                        break;
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irqrestore(&pha->hardware_lock, flags);
        if (handle == MAX_OUTSTANDING_COMMANDS) {
                /* Command not found. */
                return QLA_FUNCTION_FAILED;
index 62a3ad6e8ecb0d1a0c457e3617019b39298344ba..50baf6a1d67cbc732eac8ec5578d36ea20b59fba 100644 (file)
@@ -43,6 +43,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
 
        set_bit(vp_id, ha->vp_idx_map);
        ha->num_vhosts++;
+       ha->cur_vport_count++;
        vha->vp_idx = vp_id;
        list_add_tail(&vha->vp_list, &ha->vp_list);
        mutex_unlock(&ha->vport_lock);
@@ -58,6 +59,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
        mutex_lock(&ha->vport_lock);
        vp_id = vha->vp_idx;
        ha->num_vhosts--;
+       ha->cur_vport_count--;
        clear_bit(vp_id, ha->vp_idx_map);
        list_del(&vha->vp_list);
        mutex_unlock(&ha->vport_lock);
@@ -103,8 +105,8 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
                    "loop_id=0x%04x :%x\n",
                    vha->host_no, fcport->loop_id, fcport->vp_idx));
 
-               atomic_set(&fcport->state, FCS_DEVICE_DEAD);
                qla2x00_mark_device_lost(vha, fcport, 0, 0);
+               atomic_set(&fcport->state, FCS_UNCONFIGURED);
        }
 }
 
@@ -276,7 +278,8 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
                clear_bit(RESET_ACTIVE, &vha->dpc_flags);
        }
 
-       if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
+       if (atomic_read(&vha->vp_state) == VP_ACTIVE &&
+           test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
                if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))) {
                        qla2x00_loop_resync(vha);
                        clear_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags);
@@ -390,7 +393,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
        vha->parent = ha;
        vha->fc_vport = fc_vport;
        vha->device_flags = 0;
-       vha->instance = num_hosts;
        vha->vp_idx = qla24xx_allocate_vp_id(vha);
        if (vha->vp_idx > ha->max_npiv_vports) {
                DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n",
@@ -428,7 +430,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
        host->max_cmd_len = MAX_CMDSZ;
        host->max_channel = MAX_BUSES - 1;
        host->max_lun = MAX_LUNS;
-       host->unique_id = vha->instance;
+       host->unique_id = host->host_no;
        host->max_id = MAX_TARGETS_2200;
        host->transportt = qla2xxx_transport_vport_template;
 
@@ -436,12 +438,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
            vha->host_no, vha));
 
        vha->flags.init_done = 1;
-       num_hosts++;
-
-       mutex_lock(&ha->vport_lock);
-       set_bit(vha->vp_idx, ha->vp_idx_map);
-       ha->cur_vport_count++;
-       mutex_unlock(&ha->vport_lock);
 
        return vha;
 
index 48eaa3bb5433892b2167f18215e6fe35e1cbe113..7c8af7ed2a5dc0d841fa797050d82fd5baefdfb1 100644 (file)
@@ -27,7 +27,6 @@ char qla2x00_version_str[40];
  */
 static struct kmem_cache *srb_cachep;
 
-int num_hosts;
 int ql2xlogintimeout = 20;
 module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xlogintimeout,
@@ -87,6 +86,13 @@ MODULE_PARM_DESC(ql2xqfullrampup,
                "depth for a device after a queue-full condition has been "
                "detected.  Default is 120 seconds.");
 
+int ql2xiidmaenable=1;
+module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xiidmaenable,
+               "Enables iIDMA settings "
+               "Default is 1 - perform iIDMA. 0 - no iIDMA.");
+
+
 /*
  * SCSI host template entry points
  */
@@ -388,7 +394,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
        }
 
        /* Close window on fcport/rport state-transitioning. */
-       if (!*(fc_port_t **)rport->dd_data) {
+       if (fcport->drport) {
                cmd->result = DID_IMM_RETRY << 16;
                goto qc_fail_command;
        }
@@ -443,7 +449,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
        int rval;
        scsi_qla_host_t *pha = to_qla_parent(ha);
 
-       if (unlikely(pci_channel_offline(ha->pdev))) {
+       if (unlikely(pci_channel_offline(pha->pdev))) {
                cmd->result = DID_REQUEUE << 16;
                goto qc24_fail_command;
        }
@@ -455,7 +461,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
        }
 
        /* Close window on fcport/rport state-transitioning. */
-       if (!*(fc_port_t **)rport->dd_data) {
+       if (fcport->drport) {
                cmd->result = DID_IMM_RETRY << 16;
                goto qc24_fail_command;
        }
@@ -617,6 +623,40 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
        return (return_status);
 }
 
+void
+qla2x00_abort_fcport_cmds(fc_port_t *fcport)
+{
+       int cnt;
+       unsigned long flags;
+       srb_t *sp;
+       scsi_qla_host_t *ha = fcport->ha;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
+
+       spin_lock_irqsave(&pha->hardware_lock, flags);
+       for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+               sp = pha->outstanding_cmds[cnt];
+               if (!sp)
+                       continue;
+               if (sp->fcport != fcport)
+                       continue;
+
+               spin_unlock_irqrestore(&pha->hardware_lock, flags);
+               if (ha->isp_ops->abort_command(ha, sp)) {
+                       DEBUG2(qla_printk(KERN_WARNING, ha,
+                           "Abort failed --  %lx\n", sp->cmd->serial_number));
+               } else {
+                       if (qla2x00_eh_wait_on_command(ha, sp->cmd) !=
+                           QLA_SUCCESS)
+                               DEBUG2(qla_printk(KERN_WARNING, ha,
+                                   "Abort failed while waiting --  %lx\n",
+                                   sp->cmd->serial_number));
+
+               }
+               spin_lock_irqsave(&pha->hardware_lock, flags);
+       }
+       spin_unlock_irqrestore(&pha->hardware_lock, flags);
+}
+
 static void
 qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
 {
@@ -1073,7 +1113,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
        else
                scsi_deactivate_tcq(sdev, ha->max_q_depth);
 
-       rport->dev_loss_tmo = ha->port_down_retry_count + 5;
+       rport->dev_loss_tmo = ha->port_down_retry_count;
 
        return 0;
 }
@@ -1629,9 +1669,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        }
        host->can_queue = ha->request_q_length + 128;
 
-       /* load the F/W, read paramaters, and init the H/W */
-       ha->instance = num_hosts;
-
        mutex_init(&ha->vport_lock);
        init_completion(&ha->mbx_cmd_comp);
        complete(&ha->mbx_cmd_comp);
@@ -1679,7 +1716,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        host->this_id = 255;
        host->cmd_per_lun = 3;
-       host->unique_id = ha->instance;
+       host->unique_id = host->host_no;
        host->max_cmd_len = MAX_CMDSZ;
        host->max_channel = MAX_BUSES - 1;
        host->max_lun = MAX_LUNS;
@@ -1700,8 +1737,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->flags.init_done = 1;
        ha->flags.online = 1;
 
-       num_hosts++;
-
        ret = scsi_add_host(host, &pdev->dev);
        if (ret)
                goto probe_failed;
@@ -1813,27 +1848,21 @@ static inline void
 qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
     int defer)
 {
-       unsigned long flags;
        struct fc_rport *rport;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
 
        if (!fcport->rport)
                return;
 
        rport = fcport->rport;
        if (defer) {
-               spin_lock_irqsave(&fcport->rport_lock, flags);
+               spin_lock_irq(ha->host->host_lock);
                fcport->drport = rport;
-               fcport->rport = NULL;
-               *(fc_port_t **)rport->dd_data = NULL;
-               spin_unlock_irqrestore(&fcport->rport_lock, flags);
-               set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
-       } else {
-               spin_lock_irqsave(&fcport->rport_lock, flags);
-               fcport->rport = NULL;
-               *(fc_port_t **)rport->dd_data = NULL;
-               spin_unlock_irqrestore(&fcport->rport_lock, flags);
+               spin_unlock_irq(ha->host->host_lock);
+               set_bit(FCPORT_UPDATE_NEEDED, &pha->dpc_flags);
+               qla2xxx_wake_dpc(pha);
+       } else
                fc_remote_port_delete(rport);
-       }
 }
 
 /*
@@ -1903,7 +1932,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
        scsi_qla_host_t *pha = to_qla_parent(ha);
 
        list_for_each_entry(fcport, &pha->fcports, list) {
-               if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx)
+               if (ha->vp_idx != fcport->vp_idx)
                        continue;
                /*
                 * No point in marking the device as lost, if the device is
@@ -1911,17 +1940,10 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
                 */
                if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
                        continue;
-               if (atomic_read(&fcport->state) == FCS_ONLINE) {
-                       if (defer)
-                               qla2x00_schedule_rport_del(ha, fcport, defer);
-                       else if (ha->vp_idx == fcport->vp_idx)
-                               qla2x00_schedule_rport_del(ha, fcport, defer);
-               }
+               if (atomic_read(&fcport->state) == FCS_ONLINE)
+                       qla2x00_schedule_rport_del(ha, fcport, defer);
                atomic_set(&fcport->state, FCS_DEVICE_LOST);
        }
-
-       if (defer)
-               qla2xxx_wake_dpc(ha);
 }
 
 /*
@@ -2156,7 +2178,7 @@ qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
 static int
 qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
 {
-       unsigned long flags;
+       unsigned long uninitialized_var(flags);
        scsi_qla_host_t *pha = to_qla_parent(ha);
 
        if (!locked)
@@ -2313,8 +2335,10 @@ qla2x00_do_dpc(void *data)
                            ha->host_no));
                }
 
-               if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))
+               if (test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags)) {
                        qla2x00_update_fcports(ha);
+                       clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
+               }
 
                if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) &&
                    (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) {
index 1728ab3ccb201f19677885d488d8b12726cf094d..1bca744749353d24e7d1651efde761a4f473c93f 100644 (file)
@@ -869,11 +869,9 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
        uint32_t i;
        uint32_t *dwptr;
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
-       unsigned long flags;
 
        ret = QLA_SUCCESS;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
        /* Enable flash write. */
        WRT_REG_DWORD(&reg->ctrl_status,
            RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
@@ -907,7 +905,6 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
        WRT_REG_DWORD(&reg->ctrl_status,
            RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
        RD_REG_DWORD(&reg->ctrl_status);        /* PCI Posting. */
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        return ret;
 }
@@ -2305,6 +2302,51 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
        return ret;
 }
 
+static int
+qla2xxx_is_vpd_valid(uint8_t *pos, uint8_t *end)
+{
+       if (pos >= end || *pos != 0x82)
+               return 0;
+
+       pos += 3 + pos[1];
+       if (pos >= end || *pos != 0x90)
+               return 0;
+
+       pos += 3 + pos[1];
+       if (pos >= end || *pos != 0x78)
+               return 0;
+
+       return 1;
+}
+
+int
+qla2xxx_get_vpd_field(scsi_qla_host_t *ha, char *key, char *str, size_t size)
+{
+       uint8_t *pos = ha->vpd;
+       uint8_t *end = pos + ha->vpd_size;
+       int len = 0;
+
+       if (!IS_FWI2_CAPABLE(ha) || !qla2xxx_is_vpd_valid(pos, end))
+               return 0;
+
+       while (pos < end && *pos != 0x78) {
+               len = (*pos == 0x82) ? pos[1] : pos[2];
+
+               if (!strncmp(pos, key, strlen(key)))
+                       break;
+
+               if (*pos != 0x90 && *pos != 0x91)
+                       pos += len;
+
+               pos += 3;
+       }
+
+       if (pos < end - len && *pos != 0x78)
+               return snprintf(str, size, "%.*s", len, pos + 3);
+
+       return 0;
+}
+
 static int
 qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
 {
index d058c8862b358465b793adedf8ff403269d4962a..676c390db354c18c58d816154be7d41f3c8811c8 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.02.01-k4"
+#define QLA2XXX_VERSION      "8.02.01-k6"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   2
index 5822dd595826ddd8651078e8232a4461b5dda618..88bebb13bc520ab0d3959426adcaf3f30986a320 100644 (file)
@@ -46,6 +46,8 @@ MODULE_PARM_DESC(ql4xextended_error_logging,
 
 int ql4_mod_unload = 0;
 
+#define QL4_DEF_QDEPTH 32
+
 /*
  * SCSI host template entry points
  */
@@ -1387,7 +1389,7 @@ static int qla4xxx_slave_alloc(struct scsi_device *sdev)
 
        sdev->hostdata = ddb;
        sdev->tagged_supported = 1;
-       scsi_activate_tcq(sdev, sdev->host->can_queue);
+       scsi_activate_tcq(sdev, QL4_DEF_QDEPTH);
        return 0;
 }
 
index 36c92f961e154fb46b94690b36dd09d624e59666..ee6be596503d1515dc855e6e5715267ac4edb4e1 100644 (file)
@@ -197,10 +197,42 @@ static void
 scsi_pool_free_command(struct scsi_host_cmd_pool *pool,
                         struct scsi_cmnd *cmd)
 {
+       if (cmd->prot_sdb)
+               kmem_cache_free(scsi_sdb_cache, cmd->prot_sdb);
+
        kmem_cache_free(pool->sense_slab, cmd->sense_buffer);
        kmem_cache_free(pool->cmd_slab, cmd);
 }
 
+/**
+ * scsi_host_alloc_command - internal function to allocate command
+ * @shost:     SCSI host whose pool to allocate from
+ * @gfp_mask:  mask for the allocation
+ *
+ * Returns a fully allocated command with sense buffer and protection
+ * data buffer (where applicable) or NULL on failure
+ */
+static struct scsi_cmnd *
+scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask)
+{
+       struct scsi_cmnd *cmd;
+
+       cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
+       if (!cmd)
+               return NULL;
+
+       if (scsi_host_get_prot(shost) >= SHOST_DIX_TYPE0_PROTECTION) {
+               cmd->prot_sdb = kmem_cache_zalloc(scsi_sdb_cache, gfp_mask);
+
+               if (!cmd->prot_sdb) {
+                       scsi_pool_free_command(shost->cmd_pool, cmd);
+                       return NULL;
+               }
+       }
+
+       return cmd;
+}
+
 /**
  * __scsi_get_command - Allocate a struct scsi_cmnd
  * @shost: host to transmit command
@@ -214,7 +246,7 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
        struct scsi_cmnd *cmd;
        unsigned char *buf;
 
-       cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
+       cmd = scsi_host_alloc_command(shost, gfp_mask);
 
        if (unlikely(!cmd)) {
                unsigned long flags;
@@ -457,7 +489,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
        /*
         * Get one backup command for this host.
         */
-       cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
+       cmd = scsi_host_alloc_command(shost, gfp_mask);
        if (!cmd) {
                scsi_put_host_cmd_pool(gfp_mask);
                shost->cmd_pool = NULL;
@@ -902,11 +934,20 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
 
        spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
 
-       /* Check to see if the queue is managed by the block layer.
-        * If it is, and we fail to adjust the depth, exit. */
-       if (blk_queue_tagged(sdev->request_queue) &&
-           blk_queue_resize_tags(sdev->request_queue, tags) != 0)
-               goto out;
+       /*
+        * Check to see if the queue is managed by the block layer.
+        * If it is, and we fail to adjust the depth, exit.
+        *
+        * Do not resize the tag map if it is a host wide share bqt,
+        * because the size should be the hosts's can_queue. If there
+        * is more IO than the LLD's can_queue (so there are not enuogh
+        * tags) request_fn's host queue ready check will handle it.
+        */
+       if (!sdev->host->bqt) {
+               if (blk_queue_tagged(sdev->request_queue) &&
+                   blk_queue_resize_tags(sdev->request_queue, tags) != 0)
+                       goto out;
+       }
 
        sdev->queue_depth = tags;
        switch (tagged) {
index 01d11a01ffbf7f5925235cdcf8cf68f8ce6cb76a..27c633f557945f8cfb99ce433bcf53ca774f2df8 100644 (file)
@@ -1753,7 +1753,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
                open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
                if (!open_devip) {
                        printk(KERN_ERR "%s: out of memory at line %d\n",
-                               __FUNCTION__, __LINE__);
+                               __func__, __LINE__);
                        return NULL;
                }
        }
@@ -2656,7 +2656,7 @@ static int sdebug_add_adapter(void)
         sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
         if (NULL == sdbg_host) {
                 printk(KERN_ERR "%s: out of memory at line %d\n",
-                       __FUNCTION__, __LINE__);
+                       __func__, __LINE__);
                 return -ENOMEM;
         }
 
@@ -2667,7 +2667,7 @@ static int sdebug_add_adapter(void)
                sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
                if (!sdbg_devinfo) {
                         printk(KERN_ERR "%s: out of memory at line %d\n",
-                               __FUNCTION__, __LINE__);
+                               __func__, __LINE__);
                         error = -ENOMEM;
                        goto clean;
                 }
@@ -2987,7 +2987,7 @@ static int sdebug_driver_probe(struct device * dev)
 
         hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
         if (NULL == hpnt) {
-                printk(KERN_ERR "%s: scsi_register failed\n", __FUNCTION__);
+                printk(KERN_ERR "%s: scsi_register failed\n", __func__);
                 error = -ENODEV;
                return error;
         }
@@ -3002,7 +3002,7 @@ static int sdebug_driver_probe(struct device * dev)
 
         error = scsi_add_host(hpnt, &sdbg_host->dev);
         if (error) {
-                printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__);
+                printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
                 error = -ENODEV;
                scsi_host_put(hpnt);
         } else
@@ -3021,7 +3021,7 @@ static int sdebug_driver_remove(struct device * dev)
 
        if (!sdbg_host) {
                printk(KERN_ERR "%s: Unable to locate host info\n",
-                      __FUNCTION__);
+                      __func__);
                return -ENODEV;
        }
 
index a235802f298150e648eb5bdf3f054dae4b1721c8..4969e4ec75ea9f7b985c6c979763d8eae40bcb93 100644 (file)
@@ -272,7 +272,7 @@ static void scsi_strcpy_devinfo(char *name, char *to, size_t to_length,
        }
        if (from_length > to_length)
                 printk(KERN_WARNING "%s: %s string '%s' is too long\n",
-                       __FUNCTION__, name, from);
+                       __func__, name, from);
 }
 
 /**
@@ -298,7 +298,7 @@ static int scsi_dev_info_list_add(int compatible, char *vendor, char *model,
 
        devinfo = kmalloc(sizeof(*devinfo), GFP_KERNEL);
        if (!devinfo) {
-               printk(KERN_ERR "%s: no memory\n", __FUNCTION__);
+               printk(KERN_ERR "%s: no memory\n", __func__);
                return -ENOMEM;
        }
 
@@ -363,7 +363,7 @@ static int scsi_dev_info_list_add_str(char *dev_list)
                        strflags = strsep(&next, next_check);
                if (!model || !strflags) {
                        printk(KERN_ERR "%s: bad dev info string '%s' '%s'"
-                              " '%s'\n", __FUNCTION__, vendor, model,
+                              " '%s'\n", __func__, vendor, model,
                               strflags);
                        res = -EINVAL;
                } else
index 006a95916f72ae4aff8cae52db9122a9d5e4bf9c..880051c89bde082320f7379b39adeb4e7823c12d 100644 (file)
@@ -139,7 +139,7 @@ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
        scmd->eh_timeout.function = (void (*)(unsigned long)) complete;
 
        SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p, time:"
-                                         " %d, (%p)\n", __FUNCTION__,
+                                         " %d, (%p)\n", __func__,
                                          scmd, timeout, complete));
 
        add_timer(&scmd->eh_timeout);
@@ -163,7 +163,7 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
        rtn = del_timer(&scmd->eh_timeout);
 
        SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p,"
-                                        " rtn: %d\n", __FUNCTION__,
+                                        " rtn: %d\n", __func__,
                                         scmd, rtn));
 
        scmd->eh_timeout.data = (unsigned long)NULL;
@@ -233,7 +233,7 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev)
 
        online = scsi_device_online(sdev);
 
-       SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __FUNCTION__,
+       SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __func__,
                                          online));
 
        return online;
@@ -271,7 +271,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
                        SCSI_LOG_ERROR_RECOVERY(3,
                                sdev_printk(KERN_INFO, sdev,
                                            "%s: cmds failed: %d, cancel: %d\n",
-                                           __FUNCTION__, cmd_failed,
+                                           __func__, cmd_failed,
                                            cmd_cancel));
                        cmd_cancel = 0;
                        cmd_failed = 0;
@@ -344,6 +344,9 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
                return /* soft_error */ SUCCESS;
 
        case ABORTED_COMMAND:
+               if (sshdr.asc == 0x10) /* DIF */
+                       return SUCCESS;
+
                return NEEDS_RETRY;
        case NOT_READY:
        case UNIT_ATTENTION:
@@ -470,7 +473,7 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
 
        SCSI_LOG_ERROR_RECOVERY(3,
                printk("%s scmd: %p result: %x\n",
-                       __FUNCTION__, scmd, scmd->result));
+                       __func__, scmd, scmd->result));
 
        eh_action = scmd->device->host->eh_action;
        if (eh_action)
@@ -487,7 +490,7 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
        int rtn;
 
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
-                                         __FUNCTION__));
+                                         __func__));
 
        if (!scmd->device->host->hostt->eh_host_reset_handler)
                return FAILED;
@@ -516,7 +519,7 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
        int rtn;
 
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
-                                         __FUNCTION__));
+                                         __func__));
 
        if (!scmd->device->host->hostt->eh_bus_reset_handler)
                return FAILED;
@@ -664,7 +667,10 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
        ses->sdb = scmd->sdb;
        ses->next_rq = scmd->request->next_rq;
        ses->result = scmd->result;
+       ses->underflow = scmd->underflow;
+       ses->prot_op = scmd->prot_op;
 
+       scmd->prot_op = SCSI_PROT_NORMAL;
        scmd->cmnd = ses->eh_cmnd;
        memset(scmd->cmnd, 0, BLK_MAX_CDB);
        memset(&scmd->sdb, 0, sizeof(scmd->sdb));
@@ -722,6 +728,8 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
        scmd->sdb = ses->sdb;
        scmd->request->next_rq = ses->next_rq;
        scmd->result = ses->result;
+       scmd->underflow = ses->underflow;
+       scmd->prot_op = ses->prot_op;
 }
 EXPORT_SYMBOL(scsi_eh_restore_cmnd);
 
@@ -766,7 +774,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
 
        SCSI_LOG_ERROR_RECOVERY(3,
                printk("%s: scmd: %p, timeleft: %ld\n",
-                       __FUNCTION__, scmd, timeleft));
+                       __func__, scmd, timeleft));
 
        /*
         * If there is time left scsi_eh_done got called, and we will
@@ -778,7 +786,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
                rtn = scsi_eh_completed_normally(scmd);
                SCSI_LOG_ERROR_RECOVERY(3,
                        printk("%s: scsi_eh_completed_normally %x\n",
-                              __FUNCTION__, rtn));
+                              __func__, rtn));
 
                switch (rtn) {
                case SUCCESS:
@@ -913,7 +921,7 @@ retry_tur:
        rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, SENSE_TIMEOUT, 0);
 
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
-               __FUNCTION__, scmd, rtn));
+               __func__, scmd, rtn));
 
        switch (rtn) {
        case NEEDS_RETRY:
@@ -1296,7 +1304,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
        if (!scsi_device_online(scmd->device)) {
                SCSI_LOG_ERROR_RECOVERY(5, printk("%s: device offline - report"
                                                  " as SUCCESS\n",
-                                                 __FUNCTION__));
+                                                 __func__));
                return SUCCESS;
        }
 
@@ -1511,7 +1519,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
         * ioctls to queued block devices.
         */
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
-                                         __FUNCTION__));
+                                         __func__));
 
        spin_lock_irqsave(shost->host_lock, flags);
        if (scsi_host_set_state(shost, SHOST_RUNNING))
@@ -1835,7 +1843,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
         */
        SCSI_LOG_ERROR_RECOVERY(3,
                printk("%s: waking up host to restart after TMF\n",
-               __FUNCTION__));
+               __func__));
 
        wake_up(&shost->host_wait);
 
index 88d1b5f44e59f2847bfca483a035b686e57de051..ff5d56b3ee4d5c66a6ee4ab34609fc1800cd347b 100644 (file)
@@ -65,7 +65,7 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = {
 };
 #undef SP
 
-static struct kmem_cache *scsi_sdb_cache;
+struct kmem_cache *scsi_sdb_cache;
 
 static void scsi_run_queue(struct request_queue *q);
 
@@ -787,6 +787,9 @@ void scsi_release_buffers(struct scsi_cmnd *cmd)
                kmem_cache_free(scsi_sdb_cache, bidi_sdb);
                cmd->request->next_rq->special = NULL;
        }
+
+       if (scsi_prot_sg_count(cmd))
+               scsi_free_sgtable(cmd->prot_sdb);
 }
 EXPORT_SYMBOL(scsi_release_buffers);
 
@@ -947,9 +950,14 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                 * 6-byte command.
                                 */
                                scsi_requeue_command(q, cmd);
-                               return;
-                       } else {
+                       } else if (sshdr.asc == 0x10) /* DIX */
+                               scsi_end_request(cmd, -EIO, this_count, 0);
+                       else
                                scsi_end_request(cmd, -EIO, this_count, 1);
+                       return;
+               case ABORTED_COMMAND:
+                       if (sshdr.asc == 0x10) { /* DIF */
+                               scsi_end_request(cmd, -EIO, this_count, 0);
                                return;
                        }
                        break;
@@ -1072,6 +1080,26 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
                        goto err_exit;
        }
 
+       if (blk_integrity_rq(cmd->request)) {
+               struct scsi_data_buffer *prot_sdb = cmd->prot_sdb;
+               int ivecs, count;
+
+               BUG_ON(prot_sdb == NULL);
+               ivecs = blk_rq_count_integrity_sg(cmd->request);
+
+               if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask)) {
+                       error = BLKPREP_DEFER;
+                       goto err_exit;
+               }
+
+               count = blk_rq_map_integrity_sg(cmd->request,
+                                               prot_sdb->table.sgl);
+               BUG_ON(unlikely(count > ivecs));
+
+               cmd->prot_sdb = prot_sdb;
+               cmd->prot_sdb->table.nents = count;
+       }
+
        return BLKPREP_OK ;
 
 err_exit:
@@ -1367,7 +1395,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
 
        if (unlikely(cmd == NULL)) {
                printk(KERN_CRIT "impossible request in %s.\n",
-                                __FUNCTION__);
+                                __func__);
                BUG();
        }
 
@@ -1491,12 +1519,27 @@ static void scsi_request_fn(struct request_queue *q)
                        printk(KERN_CRIT "impossible request in %s.\n"
                                         "please mail a stack trace to "
                                         "linux-scsi@vger.kernel.org\n",
-                                        __FUNCTION__);
+                                        __func__);
                        blk_dump_rq_flags(req, "foo");
                        BUG();
                }
                spin_lock(shost->host_lock);
 
+               /*
+                * We hit this when the driver is using a host wide
+                * tag map. For device level tag maps the queue_depth check
+                * in the device ready fn would prevent us from trying
+                * to allocate a tag. Since the map is a shared host resource
+                * we add the dev to the starved list so it eventually gets
+                * a run when a tag is freed.
+                */
+               if (blk_queue_tagged(q) && !blk_rq_tagged(req)) {
+                       if (list_empty(&sdev->starved_entry))
+                               list_add_tail(&sdev->starved_entry,
+                                             &shost->starved_list);
+                       goto not_ready;
+               }
+
                if (!scsi_host_queue_ready(q, shost, sdev))
                        goto not_ready;
                if (scsi_target(sdev)->single_lun) {
@@ -2486,7 +2529,7 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count,
        if (unlikely(i == sg_count)) {
                printk(KERN_ERR "%s: Bytes in sg: %zu, requested offset %zu, "
                        "elements %d\n",
-                      __FUNCTION__, sg_len, *offset, sg_count);
+                      __func__, sg_len, *offset, sg_count);
                WARN_ON(1);
                return NULL;
        }
index 370c78cc1cb562f20af68017489a78b6650374a0..ae7ed9a226623db41e1354a12c6f97d5d83bc324 100644 (file)
@@ -55,7 +55,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
                if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) ||
                    (skb->len < nlh->nlmsg_len)) {
                        printk(KERN_WARNING "%s: discarding partial skb\n",
-                                __FUNCTION__);
+                                __func__);
                        return;
                }
 
@@ -82,7 +82,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
 
                if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) {
                        printk(KERN_WARNING "%s: discarding partial message\n",
-                                __FUNCTION__);
+                                __func__);
                        return;
                }
 
@@ -139,7 +139,7 @@ scsi_netlink_init(void)
        error = netlink_register_notifier(&scsi_netlink_notifier);
        if (error) {
                printk(KERN_ERR "%s: register of event handler failed - %d\n",
-                               __FUNCTION__, error);
+                               __func__, error);
                return;
        }
 
@@ -148,7 +148,7 @@ scsi_netlink_init(void)
                                THIS_MODULE);
        if (!scsi_nl_sock) {
                printk(KERN_ERR "%s: register of recieve handler failed\n",
-                               __FUNCTION__);
+                               __func__);
                netlink_unregister_notifier(&scsi_netlink_notifier);
        }
 
index b33e72516ef83ee685a5186e0894b0585faba4fd..79f0f7511204594186a36bae6e62acb4c3cd1a9c 100644 (file)
@@ -77,6 +77,7 @@ extern void scsi_exit_queue(void);
 struct request_queue;
 struct request;
 extern int scsi_prep_fn(struct request_queue *, struct request *);
+extern struct kmem_cache *scsi_sdb_cache;
 
 /* scsi_proc.c */
 #ifdef CONFIG_SCSI_PROC_FS
index e4a0d2f9b35752a47c2e84b7e99dafa67fce04f7..c6a904a45bf9871677e50ea762ceaf3c468ae049 100644 (file)
@@ -114,7 +114,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
                sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
                if (!sht->proc_dir)
                        printk(KERN_ERR "%s: proc_mkdir failed for %s\n",
-                              __FUNCTION__, sht->proc_name);
+                              __func__, sht->proc_name);
                else
                        sht->proc_dir->owner = sht->module;
        }
@@ -157,7 +157,7 @@ void scsi_proc_host_add(struct Scsi_Host *shost)
                        sht->proc_dir, proc_scsi_read, shost);
        if (!p) {
                printk(KERN_ERR "%s: Failed to register host %d in"
-                      "%s\n", __FUNCTION__, shost->host_no,
+                      "%s\n", __func__, shost->host_no,
                       sht->proc_name);
                return;
        } 
index 196fe3af0d5efaab057619c723d54d2b3d76429c..84b4879cff114f8a6e709deed6e18c67966d9140 100644 (file)
@@ -318,7 +318,7 @@ out_device_destroy:
        put_device(&sdev->sdev_gendev);
 out:
        if (display_failure_msg)
-               printk(ALLOC_FAILURE_MSG, __FUNCTION__);
+               printk(ALLOC_FAILURE_MSG, __func__);
        return NULL;
 }
 
@@ -404,7 +404,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
 
        starget = kzalloc(size, GFP_KERNEL);
        if (!starget) {
-               printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
+               printk(KERN_ERR "%s: allocation failure\n", __func__);
                return NULL;
        }
        dev = &starget->dev;
@@ -1337,7 +1337,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
        lun_data = kmalloc(length, GFP_ATOMIC |
                           (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0));
        if (!lun_data) {
-               printk(ALLOC_FAILURE_MSG, __FUNCTION__);
+               printk(ALLOC_FAILURE_MSG, __func__);
                goto out;
        }
 
@@ -1649,7 +1649,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
 {
        SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost,
                "%s: <%u:%u:%u>\n",
-               __FUNCTION__, channel, id, lun));
+               __func__, channel, id, lun));
 
        if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
            ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
@@ -1703,7 +1703,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
                return NULL;
 
        if (shost->async_scan) {
-               printk("%s called twice for host %d", __FUNCTION__,
+               printk("%s called twice for host %d", __func__,
                                shost->host_no);
                dump_stack();
                return NULL;
@@ -1757,9 +1757,10 @@ static void scsi_finish_async_scan(struct async_scan_data *data)
        mutex_lock(&shost->scan_mutex);
 
        if (!shost->async_scan) {
-               printk("%s called twice for host %d", __FUNCTION__,
+               printk("%s called twice for host %d", __func__,
                                shost->host_no);
                dump_stack();
+               mutex_unlock(&shost->scan_mutex);
                return;
        }
 
index b6e5610597794c553a011231f9a097785e529bf9..ab3c71869be55d9deeb8ca101c59faf80e140561 100644 (file)
@@ -249,6 +249,8 @@ shost_rd_attr(cmd_per_lun, "%hd\n");
 shost_rd_attr(can_queue, "%hd\n");
 shost_rd_attr(sg_tablesize, "%hu\n");
 shost_rd_attr(unchecked_isa_dma, "%d\n");
+shost_rd_attr(prot_capabilities, "%u\n");
+shost_rd_attr(prot_guard_type, "%hd\n");
 shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
 
 static struct attribute *scsi_sysfs_shost_attrs[] = {
@@ -263,6 +265,8 @@ static struct attribute *scsi_sysfs_shost_attrs[] = {
        &dev_attr_hstate.attr,
        &dev_attr_supported_mode.attr,
        &dev_attr_active_mode.attr,
+       &dev_attr_prot_capabilities.attr,
+       &dev_attr_prot_guard_type.attr,
        NULL
 };
 
index cb92888948f9a04756a19bf994e389c02c03a350..fe4c62177f78f8394b3e1c230a5b4766c53db869 100644 (file)
@@ -6,7 +6,7 @@ struct task_struct;
 /* tmp - will replace with SCSI logging stuff */
 #define eprintk(fmt, args...)                                  \
 do {                                                           \
-       printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args);  \
+       printk("%s(%d) " fmt, __func__, __LINE__, ##args);      \
 } while (0)
 
 #define dprintk(fmt, args...)
index a272b9a2c86945314a8ae4693cc18b2a37dce2cb..56823fd1fb8418811da8fc4418ec271b846b65da 100644 (file)
@@ -571,7 +571,7 @@ send_fail:
        name = get_fc_host_event_code_name(event_code);
        printk(KERN_WARNING
                "%s: Dropped Event : host %d %s data 0x%08x - err %d\n",
-               __FUNCTION__, shost->host_no,
+               __func__, shost->host_no,
                (name) ? name : "<unknown>", event_data, err);
        return;
 }
@@ -644,7 +644,7 @@ send_vendor_fail_skb:
 send_vendor_fail:
        printk(KERN_WARNING
                "%s: Dropped Event : host %d vendor_unique - err %d\n",
-               __FUNCTION__, shost->host_no, err);
+               __func__, shost->host_no, err);
        return;
 }
 EXPORT_SYMBOL(fc_host_post_vendor_event);
@@ -2464,7 +2464,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
        size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size);
        rport = kzalloc(size, GFP_KERNEL);
        if (unlikely(!rport)) {
-               printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
+               printk(KERN_ERR "%s: allocation failure\n", __func__);
                return NULL;
        }
 
@@ -3137,7 +3137,7 @@ fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
        size = (sizeof(struct fc_vport) + fci->f->dd_fcvport_size);
        vport = kzalloc(size, GFP_KERNEL);
        if (unlikely(!vport)) {
-               printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
+               printk(KERN_ERR "%s: allocation failure\n", __func__);
                return -ENOMEM;
        }
 
@@ -3201,7 +3201,7 @@ fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
                        printk(KERN_ERR
                                "%s: Cannot create vport symlinks for "
                                "%s, err=%d\n",
-                               __FUNCTION__, dev->bus_id, error);
+                               __func__, dev->bus_id, error);
        }
        spin_lock_irqsave(shost->host_lock, flags);
        vport->flags &= ~FC_VPORT_CREATING;
@@ -3314,7 +3314,7 @@ fc_vport_sched_delete(struct work_struct *work)
        if (stat)
                dev_printk(KERN_ERR, vport->dev.parent,
                        "%s: %s could not be deleted created via "
-                       "shost%d channel %d - error %d\n", __FUNCTION__,
+                       "shost%d channel %d - error %d\n", __func__,
                        vport->dev.bus_id, vport->shost->host_no,
                        vport->channel, stat);
 }
index f4461d35ffb9157d6cc3e634f692ef0937b5a9c5..366609386be108341875da60d0f58ac02583d6d0 100644 (file)
@@ -779,7 +779,7 @@ static void sas_port_create_link(struct sas_port *port,
        return;
 err:
        printk(KERN_ERR "%s: Cannot create port links, err=%d\n",
-              __FUNCTION__, res);
+              __func__, res);
 }
 
 static void sas_port_delete_link(struct sas_port *port,
@@ -1029,7 +1029,7 @@ void sas_port_mark_backlink(struct sas_port *port)
        return;
 err:
        printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n",
-              __FUNCTION__, res);
+              __func__, res);
 
 }
 EXPORT_SYMBOL(sas_port_mark_backlink);
index 0c63947d8a9d8fce2b4fa6240d9847036289f3b2..e5e7d78564545543925fc6136c6e7c7fc994c028 100644 (file)
@@ -99,8 +99,7 @@ static void scsi_disk_release(struct device *cdev);
 static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
 static void sd_print_result(struct scsi_disk *, int);
 
-static DEFINE_IDR(sd_index_idr);
-static DEFINE_SPINLOCK(sd_index_lock);
+static DEFINE_IDA(sd_index_ida);
 
 /* This semaphore is used to mediate the 0->1 reference get in the
  * face of object destruction (i.e. we can't allow a get on an
@@ -234,6 +233,24 @@ sd_show_allow_restart(struct device *dev, struct device_attribute *attr,
        return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
 }
 
+static ssize_t
+sd_show_protection_type(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+       return snprintf(buf, 20, "%u\n", sdkp->protection_type);
+}
+
+static ssize_t
+sd_show_app_tag_own(struct device *dev, struct device_attribute *attr,
+                   char *buf)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+       return snprintf(buf, 20, "%u\n", sdkp->ATO);
+}
+
 static struct device_attribute sd_disk_attrs[] = {
        __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
               sd_store_cache_type),
@@ -242,6 +259,8 @@ static struct device_attribute sd_disk_attrs[] = {
               sd_store_allow_restart),
        __ATTR(manage_start_stop, S_IRUGO|S_IWUSR, sd_show_manage_start_stop,
               sd_store_manage_start_stop),
+       __ATTR(protection_type, S_IRUGO, sd_show_protection_type, NULL),
+       __ATTR(app_tag_own, S_IRUGO, sd_show_app_tag_own, NULL),
        __ATTR_NULL,
 };
 
@@ -354,7 +373,9 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        struct scsi_cmnd *SCpnt;
        struct scsi_device *sdp = q->queuedata;
        struct gendisk *disk = rq->rq_disk;
+       struct scsi_disk *sdkp;
        sector_t block = rq->sector;
+       sector_t threshold;
        unsigned int this_count = rq->nr_sectors;
        unsigned int timeout = sdp->timeout;
        int ret;
@@ -370,6 +391,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        if (ret != BLKPREP_OK)
                goto out;
        SCpnt = rq->special;
+       sdkp = scsi_disk(disk);
 
        /* from here on until we're complete, any goto out
         * is used for a killable error condition */
@@ -401,13 +423,21 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        }
 
        /*
-        * Some devices (some sdcards for one) don't like it if the
-        * last sector gets read in a larger then 1 sector read.
+        * Some SD card readers can't handle multi-sector accesses which touch
+        * the last one or two hardware sectors.  Split accesses as needed.
         */
-       if (unlikely(sdp->last_sector_bug &&
-           rq->nr_sectors > sdp->sector_size / 512 &&
-           block + this_count == get_capacity(disk)))
-               this_count -= sdp->sector_size / 512;
+       threshold = get_capacity(disk) - SD_LAST_BUGGY_SECTORS *
+               (sdp->sector_size / 512);
+
+       if (unlikely(sdp->last_sector_bug && block + this_count > threshold)) {
+               if (block < threshold) {
+                       /* Access up to the threshold but not beyond */
+                       this_count = threshold - block;
+               } else {
+                       /* Access only a single hardware sector */
+                       this_count = sdp->sector_size / 512;
+               }
+       }
 
        SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
                                        (unsigned long long)block));
@@ -459,6 +489,11 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
                }
                SCpnt->cmnd[0] = WRITE_6;
                SCpnt->sc_data_direction = DMA_TO_DEVICE;
+
+               if (blk_integrity_rq(rq) &&
+                   sd_dif_prepare(rq, block, sdp->sector_size) == -EIO)
+                       goto out;
+
        } else if (rq_data_dir(rq) == READ) {
                SCpnt->cmnd[0] = READ_6;
                SCpnt->sc_data_direction = DMA_FROM_DEVICE;
@@ -473,8 +508,12 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
                                        "writing" : "reading", this_count,
                                        rq->nr_sectors));
 
-       SCpnt->cmnd[1] = 0;
-       
+       /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */
+       if (scsi_host_dif_capable(sdp->host, sdkp->protection_type))
+               SCpnt->cmnd[1] = 1 << 5;
+       else
+               SCpnt->cmnd[1] = 0;
+
        if (block > 0xffffffff) {
                SCpnt->cmnd[0] += READ_16 - READ_6;
                SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0;
@@ -492,6 +531,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
                SCpnt->cmnd[13] = (unsigned char) this_count & 0xff;
                SCpnt->cmnd[14] = SCpnt->cmnd[15] = 0;
        } else if ((this_count > 0xff) || (block > 0x1fffff) ||
+                  scsi_device_protection(SCpnt->device) ||
                   SCpnt->device->use_10_for_rw) {
                if (this_count > 0xffff)
                        this_count = 0xffff;
@@ -526,6 +566,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        }
        SCpnt->sdb.length = this_count * sdp->sector_size;
 
+       /* If DIF or DIX is enabled, tell HBA how to handle request */
+       if (sdkp->protection_type || scsi_prot_sg_count(SCpnt))
+               sd_dif_op(SCpnt, sdkp->protection_type, scsi_prot_sg_count(SCpnt));
+
        /*
         * We shouldn't disconnect in the middle of a sector, so with a dumb
         * host adapter, it's safe to assume that we can at least transfer
@@ -920,6 +964,48 @@ static struct block_device_operations sd_fops = {
        .revalidate_disk        = sd_revalidate_disk,
 };
 
+static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
+{
+       u64 start_lba = scmd->request->sector;
+       u64 end_lba = scmd->request->sector + (scsi_bufflen(scmd) / 512);
+       u64 bad_lba;
+       int info_valid;
+
+       if (!blk_fs_request(scmd->request))
+               return 0;
+
+       info_valid = scsi_get_sense_info_fld(scmd->sense_buffer,
+                                            SCSI_SENSE_BUFFERSIZE,
+                                            &bad_lba);
+       if (!info_valid)
+               return 0;
+
+       if (scsi_bufflen(scmd) <= scmd->device->sector_size)
+               return 0;
+
+       if (scmd->device->sector_size < 512) {
+               /* only legitimate sector_size here is 256 */
+               start_lba <<= 1;
+               end_lba <<= 1;
+       } else {
+               /* be careful ... don't want any overflows */
+               u64 factor = scmd->device->sector_size / 512;
+               do_div(start_lba, factor);
+               do_div(end_lba, factor);
+       }
+
+       /* The bad lba was reported incorrectly, we have no idea where
+        * the error is.
+        */
+       if (bad_lba < start_lba  || bad_lba >= end_lba)
+               return 0;
+
+       /* This computation should always be done in terms of
+        * the resolution of the device's medium.
+        */
+       return (bad_lba - start_lba) * scmd->device->sector_size;
+}
+
 /**
  *     sd_done - bottom half handler: called when the lower level
  *     driver has completed (successfully or otherwise) a scsi command.
@@ -930,15 +1016,10 @@ static struct block_device_operations sd_fops = {
 static int sd_done(struct scsi_cmnd *SCpnt)
 {
        int result = SCpnt->result;
-       unsigned int xfer_size = scsi_bufflen(SCpnt);
-       unsigned int good_bytes = result ? 0 : xfer_size;
-       u64 start_lba = SCpnt->request->sector;
-       u64 end_lba = SCpnt->request->sector + (xfer_size / 512);
-       u64 bad_lba;
+       unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt);
        struct scsi_sense_hdr sshdr;
        int sense_valid = 0;
        int sense_deferred = 0;
-       int info_valid;
 
        if (result) {
                sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr);
@@ -963,36 +1044,7 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        switch (sshdr.sense_key) {
        case HARDWARE_ERROR:
        case MEDIUM_ERROR:
-               if (!blk_fs_request(SCpnt->request))
-                       goto out;
-               info_valid = scsi_get_sense_info_fld(SCpnt->sense_buffer,
-                                                    SCSI_SENSE_BUFFERSIZE,
-                                                    &bad_lba);
-               if (!info_valid)
-                       goto out;
-               if (xfer_size <= SCpnt->device->sector_size)
-                       goto out;
-               if (SCpnt->device->sector_size < 512) {
-                       /* only legitimate sector_size here is 256 */
-                       start_lba <<= 1;
-                       end_lba <<= 1;
-               } else {
-                       /* be careful ... don't want any overflows */
-                       u64 factor = SCpnt->device->sector_size / 512;
-                       do_div(start_lba, factor);
-                       do_div(end_lba, factor);
-               }
-
-               if (bad_lba < start_lba  || bad_lba >= end_lba)
-                       /* the bad lba was reported incorrectly, we have
-                        * no idea where the error is
-                        */
-                       goto out;
-
-               /* This computation should always be done in terms of
-                * the resolution of the device's medium.
-                */
-               good_bytes = (bad_lba - start_lba)*SCpnt->device->sector_size;
+               good_bytes = sd_completed_bytes(SCpnt);
                break;
        case RECOVERED_ERROR:
        case NO_SENSE:
@@ -1002,10 +1054,23 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                scsi_print_sense("sd", SCpnt);
                SCpnt->result = 0;
                memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-               good_bytes = xfer_size;
+               good_bytes = scsi_bufflen(SCpnt);
+               break;
+       case ABORTED_COMMAND:
+               if (sshdr.asc == 0x10) { /* DIF: Disk detected corruption */
+                       scsi_print_result(SCpnt);
+                       scsi_print_sense("sd", SCpnt);
+                       good_bytes = sd_completed_bytes(SCpnt);
+               }
                break;
        case ILLEGAL_REQUEST:
-               if (SCpnt->device->use_10_for_rw &&
+               if (sshdr.asc == 0x10) { /* DIX: HBA detected corruption */
+                       scsi_print_result(SCpnt);
+                       scsi_print_sense("sd", SCpnt);
+                       good_bytes = sd_completed_bytes(SCpnt);
+               }
+               if (!scsi_device_protection(SCpnt->device) &&
+                   SCpnt->device->use_10_for_rw &&
                    (SCpnt->cmnd[0] == READ_10 ||
                     SCpnt->cmnd[0] == WRITE_10))
                        SCpnt->device->use_10_for_rw = 0;
@@ -1018,6 +1083,9 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                break;
        }
  out:
+       if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt))
+               sd_dif_complete(SCpnt, good_bytes);
+
        return good_bytes;
 }
 
@@ -1165,6 +1233,49 @@ sd_spinup_disk(struct scsi_disk *sdkp)
        }
 }
 
+
+/*
+ * Determine whether disk supports Data Integrity Field.
+ */
+void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+       struct scsi_device *sdp = sdkp->device;
+       u8 type;
+
+       if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0)
+               type = 0;
+       else
+               type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
+
+       switch (type) {
+       case SD_DIF_TYPE0_PROTECTION:
+               sdkp->protection_type = 0;
+               break;
+
+       case SD_DIF_TYPE1_PROTECTION:
+       case SD_DIF_TYPE3_PROTECTION:
+               sdkp->protection_type = type;
+               break;
+
+       case SD_DIF_TYPE2_PROTECTION:
+               sd_printk(KERN_ERR, sdkp, "formatted with DIF Type 2 "  \
+                         "protection which is currently unsupported. " \
+                         "Disabling disk!\n");
+               goto disable;
+
+       default:
+               sd_printk(KERN_ERR, sdkp, "formatted with unknown "     \
+                         "protection type %d. Disabling disk!\n", type);
+               goto disable;
+       }
+
+       return;
+
+disable:
+       sdkp->protection_type = 0;
+       sdkp->capacity = 0;
+}
+
 /*
  * read disk capacity
  */
@@ -1174,7 +1285,8 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
        unsigned char cmd[16];
        int the_result, retries;
        int sector_size = 0;
-       int longrc = 0;
+       /* Force READ CAPACITY(16) when PROTECT=1 */
+       int longrc = scsi_device_protection(sdkp->device) ? 1 : 0;
        struct scsi_sense_hdr sshdr;
        int sense_valid = 0;
        struct scsi_device *sdp = sdkp->device;
@@ -1186,8 +1298,8 @@ repeat:
                        memset((void *) cmd, 0, 16);
                        cmd[0] = SERVICE_ACTION_IN;
                        cmd[1] = SAI_READ_CAPACITY_16;
-                       cmd[13] = 12;
-                       memset((void *) buffer, 0, 12);
+                       cmd[13] = 13;
+                       memset((void *) buffer, 0, 13);
                } else {
                        cmd[0] = READ_CAPACITY;
                        memset((void *) &cmd[1], 0, 9);
@@ -1195,7 +1307,7 @@ repeat:
                }
                
                the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
-                                             buffer, longrc ? 12 : 8, &sshdr,
+                                             buffer, longrc ? 13 : 8, &sshdr,
                                              SD_TIMEOUT, SD_MAX_RETRIES);
 
                if (media_not_present(sdkp, &sshdr))
@@ -1270,6 +1382,8 @@ repeat:
                        
                sector_size = (buffer[8] << 24) |
                        (buffer[9] << 16) | (buffer[10] << 8) | buffer[11];
+
+               sd_read_protection_type(sdkp, buffer);
        }       
 
        /* Some devices return the total number of sectors, not the
@@ -1531,6 +1645,52 @@ defaults:
        sdkp->DPOFUA = 0;
 }
 
+/*
+ * The ATO bit indicates whether the DIF application tag is available
+ * for use by the operating system.
+ */
+void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+       int res, offset;
+       struct scsi_device *sdp = sdkp->device;
+       struct scsi_mode_data data;
+       struct scsi_sense_hdr sshdr;
+
+       if (sdp->type != TYPE_DISK)
+               return;
+
+       if (sdkp->protection_type == 0)
+               return;
+
+       res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT,
+                             SD_MAX_RETRIES, &data, &sshdr);
+
+       if (!scsi_status_is_good(res) || !data.header_length ||
+           data.length < 6) {
+               sd_printk(KERN_WARNING, sdkp,
+                         "getting Control mode page failed, assume no ATO\n");
+
+               if (scsi_sense_valid(&sshdr))
+                       sd_print_sense_hdr(sdkp, &sshdr);
+
+               return;
+       }
+
+       offset = data.header_length + data.block_descriptor_length;
+
+       if ((buffer[offset] & 0x3f) != 0x0a) {
+               sd_printk(KERN_ERR, sdkp, "ATO Got wrong page\n");
+               return;
+       }
+
+       if ((buffer[offset + 5] & 0x80) == 0)
+               return;
+
+       sdkp->ATO = 1;
+
+       return;
+}
+
 /**
  *     sd_revalidate_disk - called the first time a new disk is seen,
  *     performs disk spin up, read_capacity, etc.
@@ -1567,6 +1727,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
        sdkp->write_prot = 0;
        sdkp->WCE = 0;
        sdkp->RCD = 0;
+       sdkp->ATO = 0;
 
        sd_spinup_disk(sdkp);
 
@@ -1578,6 +1739,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
                sd_read_capacity(sdkp, buffer);
                sd_read_write_protect_flag(sdkp, buffer);
                sd_read_cache_type(sdkp, buffer);
+               sd_read_app_tag_own(sdkp, buffer);
        }
 
        /*
@@ -1643,18 +1805,20 @@ static int sd_probe(struct device *dev)
        if (!gd)
                goto out_free;
 
-       if (!idr_pre_get(&sd_index_idr, GFP_KERNEL))
-               goto out_put;
+       do {
+               if (!ida_pre_get(&sd_index_ida, GFP_KERNEL))
+                       goto out_put;
 
-       spin_lock(&sd_index_lock);
-       error = idr_get_new(&sd_index_idr, NULL, &index);
-       spin_unlock(&sd_index_lock);
+               error = ida_get_new(&sd_index_ida, &index);
+       } while (error == -EAGAIN);
 
-       if (index >= SD_MAX_DISKS)
-               error = -EBUSY;
        if (error)
                goto out_put;
 
+       error = -EBUSY;
+       if (index >= SD_MAX_DISKS)
+               goto out_free_index;
+
        sdkp->device = sdp;
        sdkp->driver = &sd_template;
        sdkp->disk = gd;
@@ -1675,7 +1839,7 @@ static int sd_probe(struct device *dev)
        strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
 
        if (device_add(&sdkp->dev))
-               goto out_put;
+               goto out_free_index;
 
        get_device(&sdp->sdev_gendev);
 
@@ -1711,12 +1875,15 @@ static int sd_probe(struct device *dev)
 
        dev_set_drvdata(dev, sdkp);
        add_disk(gd);
+       sd_dif_config_host(sdkp);
 
        sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
                  sdp->removable ? "removable " : "");
 
        return 0;
 
+ out_free_index:
+       ida_remove(&sd_index_ida, index);
  out_put:
        put_disk(gd);
  out_free:
@@ -1766,9 +1933,7 @@ static void scsi_disk_release(struct device *dev)
        struct scsi_disk *sdkp = to_scsi_disk(dev);
        struct gendisk *disk = sdkp->disk;
        
-       spin_lock(&sd_index_lock);
-       idr_remove(&sd_index_idr, sdkp->index);
-       spin_unlock(&sd_index_lock);
+       ida_remove(&sd_index_ida, sdkp->index);
 
        disk->private_data = NULL;
        put_disk(disk);
index 03a3d45cfa4237c26a545c209e1e2c8e30a1903c..95b9f06534d579bf72797c20ecd5546970f4b190 100644 (file)
  */
 #define SD_BUF_SIZE            512
 
+/*
+ * Number of sectors at the end of the device to avoid multi-sector
+ * accesses to in the case of last_sector_bug
+ */
+#define SD_LAST_BUGGY_SECTORS  8
+
 struct scsi_disk {
        struct scsi_driver *driver;     /* always &sd_template */
        struct scsi_device *device;
@@ -41,7 +47,9 @@ struct scsi_disk {
        u32             index;
        u8              media_present;
        u8              write_prot;
+       u8              protection_type;/* Data Integrity Field */
        unsigned        previous_state : 1;
+       unsigned        ATO : 1;        /* state of disk ATO bit */
        unsigned        WCE : 1;        /* state of disk WCE bit */
        unsigned        RCD : 1;        /* state of disk RCD bit, unused */
        unsigned        DPOFUA : 1;     /* state of disk DPOFUA bit */
@@ -59,4 +67,50 @@ static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
                    (sdsk)->disk->disk_name, ##a) :                     \
        sdev_printk(prefix, (sdsk)->device, fmt, ##a)
 
+/*
+ * A DIF-capable target device can be formatted with different
+ * protection schemes.  Currently 0 through 3 are defined:
+ *
+ * Type 0 is regular (unprotected) I/O
+ *
+ * Type 1 defines the contents of the guard and reference tags
+ *
+ * Type 2 defines the contents of the guard and reference tags and
+ * uses 32-byte commands to seed the latter
+ *
+ * Type 3 defines the contents of the guard tag only
+ */
+
+enum sd_dif_target_protection_types {
+       SD_DIF_TYPE0_PROTECTION = 0x0,
+       SD_DIF_TYPE1_PROTECTION = 0x1,
+       SD_DIF_TYPE2_PROTECTION = 0x2,
+       SD_DIF_TYPE3_PROTECTION = 0x3,
+};
+
+/*
+ * Data Integrity Field tuple.
+ */
+struct sd_dif_tuple {
+       __be16 guard_tag;       /* Checksum */
+       __be16 app_tag;         /* Opaque storage */
+       __be32 ref_tag;         /* Target LBA or indirect LBA */
+};
+
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+
+extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int);
+extern void sd_dif_config_host(struct scsi_disk *);
+extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int);
+extern void sd_dif_complete(struct scsi_cmnd *, unsigned int);
+
+#else /* CONFIG_BLK_DEV_INTEGRITY */
+
+#define sd_dif_op(a, b, c)                     do { } while (0)
+#define sd_dif_config_host(a)                  do { } while (0)
+#define sd_dif_prepare(a, b, c)                        (0)
+#define sd_dif_complete(a, b)                  (0)
+
+#endif /* CONFIG_BLK_DEV_INTEGRITY */
+
 #endif /* _SCSI_DISK_H */
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
new file mode 100644 (file)
index 0000000..4d17f3d
--- /dev/null
@@ -0,0 +1,538 @@
+/*
+ * sd_dif.c - SCSI Data Integrity Field
+ *
+ * Copyright (C) 2007, 2008 Oracle Corporation
+ * Written by: Martin K. Petersen <martin.petersen@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/crc-t10dif.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/scsicam.h>
+
+#include <net/checksum.h>
+
+#include "sd.h"
+
+typedef __u16 (csum_fn) (void *, unsigned int);
+
+static __u16 sd_dif_crc_fn(void *data, unsigned int len)
+{
+       return cpu_to_be16(crc_t10dif(data, len));
+}
+
+static __u16 sd_dif_ip_fn(void *data, unsigned int len)
+{
+       return ip_compute_csum(data, len);
+}
+
+/*
+ * Type 1 and Type 2 protection use the same format: 16 bit guard tag,
+ * 16 bit app tag, 32 bit reference tag.
+ */
+static void sd_dif_type1_generate(struct blk_integrity_exchg *bix, csum_fn *fn)
+{
+       void *buf = bix->data_buf;
+       struct sd_dif_tuple *sdt = bix->prot_buf;
+       sector_t sector = bix->sector;
+       unsigned int i;
+
+       for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
+               sdt->guard_tag = fn(buf, bix->sector_size);
+               sdt->ref_tag = cpu_to_be32(sector & 0xffffffff);
+               sdt->app_tag = 0;
+
+               buf += bix->sector_size;
+               sector++;
+       }
+}
+
+static void sd_dif_type1_generate_crc(struct blk_integrity_exchg *bix)
+{
+       sd_dif_type1_generate(bix, sd_dif_crc_fn);
+}
+
+static void sd_dif_type1_generate_ip(struct blk_integrity_exchg *bix)
+{
+       sd_dif_type1_generate(bix, sd_dif_ip_fn);
+}
+
+static int sd_dif_type1_verify(struct blk_integrity_exchg *bix, csum_fn *fn)
+{
+       void *buf = bix->data_buf;
+       struct sd_dif_tuple *sdt = bix->prot_buf;
+       sector_t sector = bix->sector;
+       unsigned int i;
+       __u16 csum;
+
+       for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
+               /* Unwritten sectors */
+               if (sdt->app_tag == 0xffff)
+                       return 0;
+
+               /* Bad ref tag received from disk */
+               if (sdt->ref_tag == 0xffffffff) {
+                       printk(KERN_ERR
+                              "%s: bad phys ref tag on sector %lu\n",
+                              bix->disk_name, (unsigned long)sector);
+                       return -EIO;
+               }
+
+               if (be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
+                       printk(KERN_ERR
+                              "%s: ref tag error on sector %lu (rcvd %u)\n",
+                              bix->disk_name, (unsigned long)sector,
+                              be32_to_cpu(sdt->ref_tag));
+                       return -EIO;
+               }
+
+               csum = fn(buf, bix->sector_size);
+
+               if (sdt->guard_tag != csum) {
+                       printk(KERN_ERR "%s: guard tag error on sector %lu " \
+                              "(rcvd %04x, data %04x)\n", bix->disk_name,
+                              (unsigned long)sector,
+                              be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
+                       return -EIO;
+               }
+
+               buf += bix->sector_size;
+               sector++;
+       }
+
+       return 0;
+}
+
+static int sd_dif_type1_verify_crc(struct blk_integrity_exchg *bix)
+{
+       return sd_dif_type1_verify(bix, sd_dif_crc_fn);
+}
+
+static int sd_dif_type1_verify_ip(struct blk_integrity_exchg *bix)
+{
+       return sd_dif_type1_verify(bix, sd_dif_ip_fn);
+}
+
+/*
+ * Functions for interleaving and deinterleaving application tags
+ */
+static void sd_dif_type1_set_tag(void *prot, void *tag_buf, unsigned int sectors)
+{
+       struct sd_dif_tuple *sdt = prot;
+       char *tag = tag_buf;
+       unsigned int i, j;
+
+       for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
+               sdt->app_tag = tag[j] << 8 | tag[j+1];
+               BUG_ON(sdt->app_tag == 0xffff);
+       }
+}
+
+static void sd_dif_type1_get_tag(void *prot, void *tag_buf, unsigned int sectors)
+{
+       struct sd_dif_tuple *sdt = prot;
+       char *tag = tag_buf;
+       unsigned int i, j;
+
+       for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
+               tag[j] = (sdt->app_tag & 0xff00) >> 8;
+               tag[j+1] = sdt->app_tag & 0xff;
+       }
+}
+
+static struct blk_integrity dif_type1_integrity_crc = {
+       .name                   = "T10-DIF-TYPE1-CRC",
+       .generate_fn            = sd_dif_type1_generate_crc,
+       .verify_fn              = sd_dif_type1_verify_crc,
+       .get_tag_fn             = sd_dif_type1_get_tag,
+       .set_tag_fn             = sd_dif_type1_set_tag,
+       .tuple_size             = sizeof(struct sd_dif_tuple),
+       .tag_size               = 0,
+};
+
+static struct blk_integrity dif_type1_integrity_ip = {
+       .name                   = "T10-DIF-TYPE1-IP",
+       .generate_fn            = sd_dif_type1_generate_ip,
+       .verify_fn              = sd_dif_type1_verify_ip,
+       .get_tag_fn             = sd_dif_type1_get_tag,
+       .set_tag_fn             = sd_dif_type1_set_tag,
+       .tuple_size             = sizeof(struct sd_dif_tuple),
+       .tag_size               = 0,
+};
+
+
+/*
+ * Type 3 protection has a 16-bit guard tag and 16 + 32 bits of opaque
+ * tag space.
+ */
+static void sd_dif_type3_generate(struct blk_integrity_exchg *bix, csum_fn *fn)
+{
+       void *buf = bix->data_buf;
+       struct sd_dif_tuple *sdt = bix->prot_buf;
+       unsigned int i;
+
+       for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
+               sdt->guard_tag = fn(buf, bix->sector_size);
+               sdt->ref_tag = 0;
+               sdt->app_tag = 0;
+
+               buf += bix->sector_size;
+       }
+}
+
+static void sd_dif_type3_generate_crc(struct blk_integrity_exchg *bix)
+{
+       sd_dif_type3_generate(bix, sd_dif_crc_fn);
+}
+
+static void sd_dif_type3_generate_ip(struct blk_integrity_exchg *bix)
+{
+       sd_dif_type3_generate(bix, sd_dif_ip_fn);
+}
+
+static int sd_dif_type3_verify(struct blk_integrity_exchg *bix, csum_fn *fn)
+{
+       void *buf = bix->data_buf;
+       struct sd_dif_tuple *sdt = bix->prot_buf;
+       sector_t sector = bix->sector;
+       unsigned int i;
+       __u16 csum;
+
+       for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
+               /* Unwritten sectors */
+               if (sdt->app_tag == 0xffff && sdt->ref_tag == 0xffffffff)
+                       return 0;
+
+               csum = fn(buf, bix->sector_size);
+
+               if (sdt->guard_tag != csum) {
+                       printk(KERN_ERR "%s: guard tag error on sector %lu " \
+                              "(rcvd %04x, data %04x)\n", bix->disk_name,
+                              (unsigned long)sector,
+                              be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
+                       return -EIO;
+               }
+
+               buf += bix->sector_size;
+               sector++;
+       }
+
+       return 0;
+}
+
+static int sd_dif_type3_verify_crc(struct blk_integrity_exchg *bix)
+{
+       return sd_dif_type3_verify(bix, sd_dif_crc_fn);
+}
+
+static int sd_dif_type3_verify_ip(struct blk_integrity_exchg *bix)
+{
+       return sd_dif_type3_verify(bix, sd_dif_ip_fn);
+}
+
+static void sd_dif_type3_set_tag(void *prot, void *tag_buf, unsigned int sectors)
+{
+       struct sd_dif_tuple *sdt = prot;
+       char *tag = tag_buf;
+       unsigned int i, j;
+
+       for (i = 0, j = 0 ; i < sectors ; i++, j += 6, sdt++) {
+               sdt->app_tag = tag[j] << 8 | tag[j+1];
+               sdt->ref_tag = tag[j+2] << 24 | tag[j+3] << 16 |
+                       tag[j+4] << 8 | tag[j+5];
+       }
+}
+
+static void sd_dif_type3_get_tag(void *prot, void *tag_buf, unsigned int sectors)
+{
+       struct sd_dif_tuple *sdt = prot;
+       char *tag = tag_buf;
+       unsigned int i, j;
+
+       for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
+               tag[j] = (sdt->app_tag & 0xff00) >> 8;
+               tag[j+1] = sdt->app_tag & 0xff;
+               tag[j+2] = (sdt->ref_tag & 0xff000000) >> 24;
+               tag[j+3] = (sdt->ref_tag & 0xff0000) >> 16;
+               tag[j+4] = (sdt->ref_tag & 0xff00) >> 8;
+               tag[j+5] = sdt->ref_tag & 0xff;
+               BUG_ON(sdt->app_tag == 0xffff || sdt->ref_tag == 0xffffffff);
+       }
+}
+
+static struct blk_integrity dif_type3_integrity_crc = {
+       .name                   = "T10-DIF-TYPE3-CRC",
+       .generate_fn            = sd_dif_type3_generate_crc,
+       .verify_fn              = sd_dif_type3_verify_crc,
+       .get_tag_fn             = sd_dif_type3_get_tag,
+       .set_tag_fn             = sd_dif_type3_set_tag,
+       .tuple_size             = sizeof(struct sd_dif_tuple),
+       .tag_size               = 0,
+};
+
+static struct blk_integrity dif_type3_integrity_ip = {
+       .name                   = "T10-DIF-TYPE3-IP",
+       .generate_fn            = sd_dif_type3_generate_ip,
+       .verify_fn              = sd_dif_type3_verify_ip,
+       .get_tag_fn             = sd_dif_type3_get_tag,
+       .set_tag_fn             = sd_dif_type3_set_tag,
+       .tuple_size             = sizeof(struct sd_dif_tuple),
+       .tag_size               = 0,
+};
+
+/*
+ * Configure exchange of protection information between OS and HBA.
+ */
+void sd_dif_config_host(struct scsi_disk *sdkp)
+{
+       struct scsi_device *sdp = sdkp->device;
+       struct gendisk *disk = sdkp->disk;
+       u8 type = sdkp->protection_type;
+
+       /* If this HBA doesn't support DIX, resort to normal I/O or DIF */
+       if (scsi_host_dix_capable(sdp->host, type) == 0) {
+
+               if (type == SD_DIF_TYPE0_PROTECTION)
+                       return;
+
+               if (scsi_host_dif_capable(sdp->host, type) == 0) {
+                       sd_printk(KERN_INFO, sdkp, "Type %d protection " \
+                                 "unsupported by HBA. Disabling DIF.\n", type);
+                       sdkp->protection_type = 0;
+                       return;
+               }
+
+               sd_printk(KERN_INFO, sdkp, "Enabling DIF Type %d protection\n",
+                         type);
+
+               return;
+       }
+
+       /* Enable DMA of protection information */
+       if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP)
+               if (type == SD_DIF_TYPE3_PROTECTION)
+                       blk_integrity_register(disk, &dif_type3_integrity_ip);
+               else
+                       blk_integrity_register(disk, &dif_type1_integrity_ip);
+       else
+               if (type == SD_DIF_TYPE3_PROTECTION)
+                       blk_integrity_register(disk, &dif_type3_integrity_crc);
+               else
+                       blk_integrity_register(disk, &dif_type1_integrity_crc);
+
+       sd_printk(KERN_INFO, sdkp,
+                 "Enabling %s integrity protection\n", disk->integrity->name);
+
+       /* Signal to block layer that we support sector tagging */
+       if (type && sdkp->ATO) {
+               if (type == SD_DIF_TYPE3_PROTECTION)
+                       disk->integrity->tag_size = sizeof(u16) + sizeof(u32);
+               else
+                       disk->integrity->tag_size = sizeof(u16);
+
+               sd_printk(KERN_INFO, sdkp, "DIF application tag size %u\n",
+                         disk->integrity->tag_size);
+       }
+}
+
+/*
+ * DIF DMA operation magic decoder ring.
+ */
+void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix)
+{
+       int csum_convert, prot_op;
+
+       prot_op = 0;
+
+       /* Convert checksum? */
+       if (scsi_host_get_guard(scmd->device->host) != SHOST_DIX_GUARD_CRC)
+               csum_convert = 1;
+       else
+               csum_convert = 0;
+
+       switch (scmd->cmnd[0]) {
+       case READ_10:
+       case READ_12:
+       case READ_16:
+               if (dif && dix)
+                       if (csum_convert)
+                               prot_op = SCSI_PROT_READ_CONVERT;
+                       else
+                               prot_op = SCSI_PROT_READ_PASS;
+               else if (dif && !dix)
+                       prot_op = SCSI_PROT_READ_STRIP;
+               else if (!dif && dix)
+                       prot_op = SCSI_PROT_READ_INSERT;
+
+               break;
+
+       case WRITE_10:
+       case WRITE_12:
+       case WRITE_16:
+               if (dif && dix)
+                       if (csum_convert)
+                               prot_op = SCSI_PROT_WRITE_CONVERT;
+                       else
+                               prot_op = SCSI_PROT_WRITE_PASS;
+               else if (dif && !dix)
+                       prot_op = SCSI_PROT_WRITE_INSERT;
+               else if (!dif && dix)
+                       prot_op = SCSI_PROT_WRITE_STRIP;
+
+               break;
+       }
+
+       scsi_set_prot_op(scmd, prot_op);
+       scsi_set_prot_type(scmd, dif);
+}
+
+/*
+ * The virtual start sector is the one that was originally submitted
+ * by the block layer. Due to partitioning, MD/DM cloning, etc. the
+ * actual physical start sector is likely to be different.  Remap
+ * protection information to match the physical LBA.
+ *
+ * From a protocol perspective there's a slight difference between
+ * Type 1 and 2.  The latter uses 32-byte CDBs exclusively, and the
+ * reference tag is seeded in the CDB.  This gives us the potential to
+ * avoid virt->phys remapping during write.  However, at read time we
+ * don't know whether the virt sector is the same as when we wrote it
+ * (we could be reading from real disk as opposed to MD/DM device.  So
+ * we always remap Type 2 making it identical to Type 1.
+ *
+ * Type 3 does not have a reference tag so no remapping is required.
+ */
+int sd_dif_prepare(struct request *rq, sector_t hw_sector, unsigned int sector_sz)
+{
+       const int tuple_sz = sizeof(struct sd_dif_tuple);
+       struct bio *bio;
+       struct scsi_disk *sdkp;
+       struct sd_dif_tuple *sdt;
+       unsigned int i, j;
+       u32 phys, virt;
+
+       /* Already remapped? */
+       if (rq->cmd_flags & REQ_INTEGRITY)
+               return 0;
+
+       sdkp = rq->bio->bi_bdev->bd_disk->private_data;
+
+       if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION)
+               return 0;
+
+       rq->cmd_flags |= REQ_INTEGRITY;
+       phys = hw_sector & 0xffffffff;
+
+       __rq_for_each_bio(bio, rq) {
+               struct bio_vec *iv;
+
+               virt = bio->bi_integrity->bip_sector & 0xffffffff;
+
+               bip_for_each_vec(iv, bio->bi_integrity, i) {
+                       sdt = kmap_atomic(iv->bv_page, KM_USER0)
+                               + iv->bv_offset;
+
+                       for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {
+
+                               if (be32_to_cpu(sdt->ref_tag) != virt)
+                                       goto error;
+
+                               sdt->ref_tag = cpu_to_be32(phys);
+                               virt++;
+                               phys++;
+                       }
+
+                       kunmap_atomic(sdt, KM_USER0);
+               }
+       }
+
+       return 0;
+
+error:
+       kunmap_atomic(sdt, KM_USER0);
+       sd_printk(KERN_ERR, sdkp, "%s: virt %u, phys %u, ref %u\n",
+                 __func__, virt, phys, be32_to_cpu(sdt->ref_tag));
+
+       return -EIO;
+}
+
+/*
+ * Remap physical sector values in the reference tag to the virtual
+ * values expected by the block layer.
+ */
+void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
+{
+       const int tuple_sz = sizeof(struct sd_dif_tuple);
+       struct scsi_disk *sdkp;
+       struct bio *bio;
+       struct sd_dif_tuple *sdt;
+       unsigned int i, j, sectors, sector_sz;
+       u32 phys, virt;
+
+       sdkp = scsi_disk(scmd->request->rq_disk);
+
+       if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0)
+               return;
+
+       sector_sz = scmd->device->sector_size;
+       sectors = good_bytes / sector_sz;
+
+       phys = scmd->request->sector & 0xffffffff;
+       if (sector_sz == 4096)
+               phys >>= 3;
+
+       __rq_for_each_bio(bio, scmd->request) {
+               struct bio_vec *iv;
+
+               virt = bio->bi_integrity->bip_sector & 0xffffffff;
+
+               bip_for_each_vec(iv, bio->bi_integrity, i) {
+                       sdt = kmap_atomic(iv->bv_page, KM_USER0)
+                               + iv->bv_offset;
+
+                       for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {
+
+                               if (sectors == 0) {
+                                       kunmap_atomic(sdt, KM_USER0);
+                                       return;
+                               }
+
+                               if (be32_to_cpu(sdt->ref_tag) != phys &&
+                                   sdt->app_tag != 0xffff)
+                                       sdt->ref_tag = 0xffffffff; /* Bad ref */
+                               else
+                                       sdt->ref_tag = cpu_to_be32(virt);
+
+                               virt++;
+                               phys++;
+                               sectors--;
+                       }
+
+                       kunmap_atomic(sdt, KM_USER0);
+               }
+       }
+}
+
index 4684cc716aa4033575b7738ded7ca3196cadd850..c2bb53e3d941faee5d29f5902ac757093102d772 100644 (file)
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static const char *verstr = "20080224";
+static const char *verstr = "20080504";
 
 #include <linux/module.h>
 
@@ -631,7 +631,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
 /* Flush the write buffer (never need to write if variable blocksize). */
 static int st_flush_write_buffer(struct scsi_tape * STp)
 {
-       int offset, transfer, blks;
+       int transfer, blks;
        int result;
        unsigned char cmd[MAX_COMMAND_SIZE];
        struct st_request *SRpnt;
@@ -644,14 +644,10 @@ static int st_flush_write_buffer(struct scsi_tape * STp)
        result = 0;
        if (STp->dirty == 1) {
 
-               offset = (STp->buffer)->buffer_bytes;
-               transfer = ((offset + STp->block_size - 1) /
-                           STp->block_size) * STp->block_size;
+               transfer = STp->buffer->buffer_bytes;
                 DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n",
                                tape_name(STp), transfer));
 
-               memset((STp->buffer)->b_data + offset, 0, transfer - offset);
-
                memset(cmd, 0, MAX_COMMAND_SIZE);
                cmd[0] = WRITE_6;
                cmd[1] = 1;
@@ -1670,6 +1666,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
                                if (undone <= do_count) {
                                        /* Only data from this write is not written */
                                        count += undone;
+                                       b_point -= undone;
                                        do_count -= undone;
                                        if (STp->block_size)
                                                blks = (transfer - undone) / STp->block_size;
index f308a030882916aed13c1805ef9213758e1313eb..3790906a77d10c06705b3616a22c5650d50f1948 100644 (file)
@@ -467,7 +467,7 @@ stex_slave_alloc(struct scsi_device *sdev)
        /* Cheat: usually extracted from Inquiry data */
        sdev->tagged_supported = 1;
 
-       scsi_activate_tcq(sdev, sdev->host->can_queue);
+       scsi_activate_tcq(sdev, ST_CMD_PER_LUN);
 
        return 0;
 }
index 2c87db98cdfb81f8abc48dc50defb5b35b494b92..f9cf7015136648380aa6bc86f18809ed3eacd2c5 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/mm.h>
 #include <linux/init.h>
 
 #include <asm/irq.h>
index 22a6aae78699ab06762858f7c1c7f6c3bcbb4958..98df1651404faff46e9241e7a776f4e69f45885f 100644 (file)
@@ -5741,6 +5741,8 @@ void sym_hcb_free(struct sym_hcb *np)
 
        for (target = 0; target < SYM_CONF_MAX_TARGET ; target++) {
                tp = &np->target[target];
+               if (tp->luntbl)
+                       sym_mfree_dma(tp->luntbl, 256, "LUNTBL");
 #if SYM_CONF_MAX_LUN > 1
                kfree(tp->lunmp);
 #endif 
index 5b04ddfed26c6162c0234963963598998d79a4b3..1723d71cbf3fa383ed99e706721027e918fa80da 100644 (file)
@@ -452,7 +452,7 @@ static int dc390_pci_map (struct dc390_srb* pSRB)
                /* TODO: error handling */
                if (pSRB->SGcount != 1)
                        error = 1;
-               DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle));
+               DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __func__, pcmd->sense_buffer, cmdp->saved_dma_handle));
        /* Map SG list */
        } else if (scsi_sg_count(pcmd)) {
                int nseg;
@@ -466,7 +466,7 @@ static int dc390_pci_map (struct dc390_srb* pSRB)
                if (nseg < 0)
                        error = 1;
                DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
-                             __FUNCTION__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
+                             __func__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
        /* Map single segment */
        } else
                pSRB->SGcount = 0;
@@ -483,11 +483,11 @@ static void dc390_pci_unmap (struct dc390_srb* pSRB)
 
        if (pSRB->SRBFlag) {
                pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
-               DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
+               DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __func__, cmdp->saved_dma_handle));
        } else {
                scsi_dma_unmap(pcmd);
                DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
-                             __FUNCTION__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
+                             __func__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
        }
 }
 
index c975c01b3a02431000f071116f3b40caffd4f3f8..d4c13561f4a6f39d9e719ba6df45f5692c83e26b 100644 (file)
  *
  * 2002/10/04 - Alan Cox <alan@redhat.com>
  *
- * Use dev_id for interrupts, kill __FUNCTION__ pasting
+ * Use dev_id for interrupts, kill __func__ pasting
  * Add a lock for the scb pool, clean up all other cli/sti usage stuff
  * Use the adapter lock for the other places we had the cli's
  *
@@ -640,12 +640,12 @@ static int __init wd7000_setup(char *str)
        (void) get_options(str, ARRAY_SIZE(ints), ints);
 
        if (wd7000_card_num >= NUM_CONFIGS) {
-               printk(KERN_ERR "%s: Too many \"wd7000=\" configurations in " "command line!\n", __FUNCTION__);
+               printk(KERN_ERR "%s: Too many \"wd7000=\" configurations in " "command line!\n", __func__);
                return 0;
        }
 
        if ((ints[0] < 3) || (ints[0] > 5)) {
-               printk(KERN_ERR "%s: Error in command line!  " "Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>" "[,<BUS_OFF>]]\n", __FUNCTION__);
+               printk(KERN_ERR "%s: Error in command line!  " "Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>" "[,<BUS_OFF>]]\n", __func__);
        } else {
                for (i = 0; i < NUM_IRQS; i++)
                        if (ints[1] == wd7000_irq[i])
@@ -1642,7 +1642,7 @@ static int wd7000_biosparam(struct scsi_device *sdev,
                        ip[2] = info[2];
 
                        if (info[0] == 255)
-                               printk(KERN_INFO "%s: current partition table is " "using extended translation.\n", __FUNCTION__);
+                               printk(KERN_INFO "%s: current partition table is " "using extended translation.\n", __func__);
                }
        }
 
index 4b5f908d35c308c26f76afd8a7cbb0100dc2cce4..3c4a300494a40843b49c6e86c730408a8716c832 100644 (file)
@@ -68,11 +68,11 @@ lasi_scsi_clock(void * hpa, int defaultclock)
        if (status == PDC_RET_OK) {
                clock = (int) pdc_result[16];
        } else {
-               printk(KERN_WARNING "%s: pdc_iodc_read returned %d\n", __FUNCTION__, status);
+               printk(KERN_WARNING "%s: pdc_iodc_read returned %d\n", __func__, status);
                clock = defaultclock; 
        }
 
-       printk(KERN_DEBUG "%s: SCSI clock %d\n", __FUNCTION__, clock);
+       printk(KERN_DEBUG "%s: SCSI clock %d\n", __func__, clock);
        return clock;
 }
 #endif
@@ -108,13 +108,13 @@ zalon_probe(struct parisc_device *dev)
        */
        dev->irq = gsc_alloc_irq(&gsc_irq);
 
-       printk(KERN_INFO "%s: Zalon version %d, IRQ %d\n", __FUNCTION__,
+       printk(KERN_INFO "%s: Zalon version %d, IRQ %d\n", __func__,
                zalon_vers, dev->irq);
 
        __raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, zalon + IO_MODULE_EIM);
 
        if (zalon_vers == 0)
-               printk(KERN_WARNING "%s: Zalon 1.1 or earlier\n", __FUNCTION__);
+               printk(KERN_WARNING "%s: Zalon 1.1 or earlier\n", __func__);
 
        memset(&device, 0, sizeof(struct ncr_device));
 
index 27f34a9f9cb750297ea6527ce5d181b47b0ca660..a97f1ae11f786c5c81205fac0e12db6d45537d55 100644 (file)
@@ -1293,7 +1293,18 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
        char flag;
 
        do {
-               ch = serial_inp(up, UART_RX);
+               if (likely(lsr & UART_LSR_DR))
+                       ch = serial_inp(up, UART_RX);
+               else
+                       /*
+                        * Intel 82571 has a Serial Over Lan device that will
+                        * set UART_LSR_BI without setting UART_LSR_DR when
+                        * it receives a break. To avoid reading from the
+                        * receive buffer without UART_LSR_DR bit set, we
+                        * just force the read character to be 0
+                        */
+                       ch = 0;
+
                flag = TTY_NORMAL;
                up->port.icount.rx++;
 
@@ -1342,7 +1353,7 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
 
 ignore_char:
                lsr = serial_inp(up, UART_LSR);
-       } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
+       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
        spin_unlock(&up->port.lock);
        tty_flip_buffer_push(tty);
        spin_lock(&up->port.lock);
@@ -1425,7 +1436,7 @@ serial8250_handle_port(struct uart_8250_port *up)
 
        DEBUG_INTR("status = %x...", status);
 
-       if (status & UART_LSR_DR)
+       if (status & (UART_LSR_DR | UART_LSR_BI))
                receive_chars(up, &status);
        check_modem_status(up);
        if (status & UART_LSR_THRE)
index 4eb7437a404a5fa5e4c4d8087d040a55891a2eb8..0416ad3bc127bd6f45b3302319dd7f15aff7fafd 100644 (file)
@@ -119,3 +119,5 @@ int __init probe_serial_gsc(void)
 }
 
 module_init(probe_serial_gsc);
+
+MODULE_LICENSE("GPL");
index 1b36087665a22f118dbce91cca27e6a4e9297b42..c2f23933155b1cbfdff132b035f76d84b143a73a 100644 (file)
@@ -767,6 +767,9 @@ pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
 #define PCI_SUBDEVICE_ID_POCTAL232     0x0308
 #define PCI_SUBDEVICE_ID_POCTAL422     0x0408
 
+/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
+#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
+
 /*
  * Master list of serial port init/setup/exit quirks.
  * This does not describe the general nature of the port.
@@ -880,6 +883,15 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .setup          = pci_default_setup,
                .exit           = __devexit_p(pci_plx9050_exit),
        },
+       {
+               .vendor         = PCI_VENDOR_ID_PLX,
+               .device         = PCI_DEVICE_ID_PLX_9050,
+               .subvendor      = PCI_VENDOR_ID_PLX,
+               .subdevice      = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
+               .init           = pci_plx9050_init,
+               .setup          = pci_default_setup,
+               .exit           = __devexit_p(pci_plx9050_exit),
+       },
        {
                .vendor         = PCI_VENDOR_ID_PLX,
                .device         = PCI_DEVICE_ID_PLX_ROMULUS,
@@ -2197,6 +2209,11 @@ static struct pci_device_id serial_pci_tbl[] = {
        {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                pbn_b2_4_921600 },
+       /* Unknown card - subdevice 0x1584 */
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_VENDOR_ID_PLX,
+               PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
+               pbn_b0_4_115200 },
        {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
                PCI_SUBVENDOR_ID_KEYSPAN,
                PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
index 8fc7451c00496a17e34123c5be0d6d8e1bf31e1a..3b4a14e355c1ac386a39c96ce0993d39ccf9e6b6 100644 (file)
@@ -942,22 +942,6 @@ config SERIAL_IP22_ZILOG_CONSOLE
        depends on SERIAL_IP22_ZILOG=y
        select SERIAL_CORE_CONSOLE
 
-config V850E_UART
-       bool "NEC V850E on-chip UART support"
-       depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1
-       select SERIAL_CORE
-       default y
-
-config V850E_UARTB
-        bool
-       depends on V850E_UART && V850E_ME2
-       default y
-
-config V850E_UART_CONSOLE
-       bool "Use NEC V850E on-chip UART for console"
-       depends on V850E_UART
-       select SERIAL_CORE_CONSOLE
-
 config SERIAL_SH_SCI
        tristate "SuperH SCI(F) serial port support"
        depends on SUPERH || H8300
index 1ff80de177db21be26be01ffa35831854821e97d..a4f86927a74bfd830e51a9fdd4ae008ebd1ac65e 100644 (file)
@@ -435,10 +435,13 @@ static void cpm_uart_shutdown(struct uart_port *port)
                }
 
                /* Shut them really down and reinit buffer descriptors */
-               if (IS_SMC(pinfo))
+               if (IS_SMC(pinfo)) {
+                       out_be16(&pinfo->smcup->smc_brkcr, 0);
                        cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
-               else
+               } else {
+                       out_be16(&pinfo->sccup->scc_brkcr, 0);
                        cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
+               }
 
                cpm_uart_initbd(pinfo);
        }
@@ -554,9 +557,11 @@ static void cpm_uart_set_termios(struct uart_port *port,
                 * enables, because we want to put them back if they were
                 * present.
                 */
-               prev_mode = in_be16(&smcp->smc_smcmr);
-               out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval | SMCMR_SM_UART);
-               setbits16(&smcp->smc_smcmr, (prev_mode & (SMCMR_REN | SMCMR_TEN)));
+               prev_mode = in_be16(&smcp->smc_smcmr) & (SMCMR_REN | SMCMR_TEN);
+               /* Output in *one* operation, so we don't interrupt RX/TX if they
+                * were already enabled. */
+               out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval |
+                   SMCMR_SM_UART | prev_mode);
        } else {
                out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
        }
@@ -1198,12 +1203,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
        udbg_putc = NULL;
 #endif
 
-       cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
-
        if (IS_SMC(pinfo)) {
+               out_be16(&pinfo->smcup->smc_brkcr, 0);
+               cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
                clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
                clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
        } else {
+               out_be16(&pinfo->sccup->scc_brkcr, 0);
+               cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
                clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
                clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
        }
index a81d2c2ff8a2d9d1a71e26cbbdc1411668582ade..6042b87797a1b74cc4fa2cddefe91dd2d9d625fd 100644 (file)
@@ -642,6 +642,26 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
        spin_unlock_irqrestore(&dport->port.lock, flags);
 }
 
+/*
+ * Hack alert!
+ * Required solely so that the initial PROM-based console
+ * works undisturbed in parallel with this one.
+ */
+static void dz_pm(struct uart_port *uport, unsigned int state,
+                 unsigned int oldstate)
+{
+       struct dz_port *dport = to_dport(uport);
+       unsigned long flags;
+
+       spin_lock_irqsave(&dport->port.lock, flags);
+       if (state < 3)
+               dz_start_tx(&dport->port);
+       else
+               dz_stop_tx(&dport->port);
+       spin_unlock_irqrestore(&dport->port.lock, flags);
+}
+
+
 static const char *dz_type(struct uart_port *uport)
 {
        return "DZ";
@@ -738,6 +758,7 @@ static struct uart_ops dz_ops = {
        .startup        = dz_startup,
        .shutdown       = dz_shutdown,
        .set_termios    = dz_set_termios,
+       .pm             = dz_pm,
        .type           = dz_type,
        .release_port   = dz_release_port,
        .request_port   = dz_request_port,
@@ -861,7 +882,10 @@ static int __init dz_console_setup(struct console *co, char *options)
        if (ret)
                return ret;
 
+       spin_lock_init(&dport->port.lock);      /* For dz_pm().  */
+
        dz_reset(dport);
+       dz_pm(uport, 0, -1);
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
index 208e42ba945533083323db7d2b3bce9c297187c7..3df2aaec829fe874a633fecc3def9d5369e64446 100644 (file)
@@ -410,7 +410,6 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7763) || \
     defined(CONFIG_CPU_SUBTYPE_SH7780) || \
     defined(CONFIG_CPU_SUBTYPE_SH7785)
 static inline int scif_txroom(struct uart_port *port)
@@ -422,6 +421,22 @@ static inline int scif_rxroom(struct uart_port *port)
 {
        return sci_in(port, SCRFDR) & 0xff;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
+static inline int scif_txroom(struct uart_port *port)
+{
+       if((port->mapbase == 0xffe00000) || (port->mapbase == 0xffe08000)) /* SCIF0/1*/
+               return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff);
+       else /* SCIF2 */
+               return SCIF2_TXROOM_MAX - (sci_in(port, SCFDR) >> 8);
+}
+
+static inline int scif_rxroom(struct uart_port *port)
+{
+       if((port->mapbase == 0xffe00000) || (port->mapbase == 0xffe08000)) /* SCIF0/1*/
+               return sci_in(port, SCRFDR) & 0xff;
+       else /* SCIF2 */
+               return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
+}
 #else
 static inline int scif_txroom(struct uart_port *port)
 {
index eb84833233fd98e690a1f08831b6cacf42fe2289..cd728df6a01a4122c73f4c7fff3c082afdc8204c 100644 (file)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
 # define SCSPTR0 0xffe00024 /* 16 bit SCIF */
 # define SCSPTR1 0xffe08024 /* 16 bit SCIF */
+# define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */
 # define SCIF_ORER 0x0001  /* overrun error bit */
-# define SCSCR_INIT(port)      0x3a    /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCSCR_INIT(port)      0x38    /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH7770)
 # define SCSPTR0 0xff923020 /* 16 bit SCIF */
     defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
     defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
     defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7763)  || \
     defined(CONFIG_CPU_SUBTYPE_SH7780)  || \
     defined(CONFIG_CPU_SUBTYPE_SH7785)  || \
     defined(CONFIG_CPU_SUBTYPE_SHX3)
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721)
-#define SCIF_ORER    0x0200
-#define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER)
-#define SCIF_RFDC_MASK 0x007f
-#define SCIF_TXROOM_MAX 64
+# define SCIF_ORER    0x0200
+# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER)
+# define SCIF_RFDC_MASK 0x007f
+# define SCIF_TXROOM_MAX 64
+#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
+# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK )
+# define SCIF_RFDC_MASK 0x007f
+# define SCIF_TXROOM_MAX 64
+/* SH7763 SCIF2 support */
+# define SCIF2_RFDC_MASK 0x001f
+# define SCIF2_TXROOM_MAX 16
 #else
-#define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
-#define SCIF_RFDC_MASK 0x001f
-#define SCIF_TXROOM_MAX 16
+# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
+# define SCIF_RFDC_MASK 0x001f
+# define SCIF_TXROOM_MAX 16
 #endif
 
 #if defined(SCI_ONLY)
@@ -445,11 +454,16 @@ SCIF_FNS(SCFCR,                      0x0c,  8, 0x18, 16)
     defined(CONFIG_CPU_SUBTYPE_SH7763) || \
     defined(CONFIG_CPU_SUBTYPE_SH7780) || \
     defined(CONFIG_CPU_SUBTYPE_SH7785)
-SCIF_FNS(SCFDR,                             0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCTFDR,                    0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCRFDR,                    0x0e, 16, 0x20, 16)
 SCIF_FNS(SCSPTR,                       0,  0, 0x24, 16)
 SCIF_FNS(SCLSR,                                0,  0, 0x28, 16)
+#if defined(CONFIG_CPU_SUBTYPE_SH7763)
+/* SH7763 SCIF2 */
+SCIF_FNS(SCFDR,                                0,  0, 0x1C, 16)
+SCIF_FNS(SCSPTR2,                      0,  0, 0x20, 16)
+SCIF_FNS(SCLSR2,                       0,  0, 0x24, 16)
+#endif /* CONFIG_CPU_SUBTYPE_SH7763 */
 #else
 SCIF_FNS(SCFDR,                      0x0e, 16, 0x1C, 16)
 #if defined(CONFIG_CPU_SUBTYPE_SH7722)
@@ -652,6 +666,9 @@ static inline int sci_rxd_in(struct uart_port *port)
                return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
        if (port->mapbase == 0xffe08000)
                return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffe10000)
+               return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF/IRDA */
+
        return 1;
 }
 #elif defined(CONFIG_CPU_SUBTYPE_SH7770)
@@ -764,8 +781,7 @@ static inline int sci_rxd_in(struct uart_port *port)
  * -- Mitch Davis - 15 Jul 2000
  */
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+#if defined(CONFIG_CPU_SUBTYPE_SH7780) || \
     defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
index bd45b6230fd8ceb9eeb54f83f4d95485d9552ef1..9e6a873f8203ec83f7965fe2711a026089c476fa 100644 (file)
@@ -787,7 +787,6 @@ static int zs_startup(struct uart_port *uport)
        zport->regs[1] &= ~RxINT_MASK;
        zport->regs[1] |= RxINT_ALL | TxINT_ENAB | EXT_INT_ENAB;
        zport->regs[3] |= RxENABLE;
-       zport->regs[5] |= TxENAB;
        zport->regs[15] |= BRKIE;
        write_zsreg(zport, R1, zport->regs[1]);
        write_zsreg(zport, R3, zport->regs[3]);
@@ -814,7 +813,6 @@ static void zs_shutdown(struct uart_port *uport)
 
        spin_lock_irqsave(&scc->zlock, flags);
 
-       zport->regs[5] &= ~TxENAB;
        zport->regs[3] &= ~RxENABLE;
        write_zsreg(zport, R5, zport->regs[5]);
        write_zsreg(zport, R3, zport->regs[3]);
@@ -959,6 +957,23 @@ static void zs_set_termios(struct uart_port *uport, struct ktermios *termios,
        spin_unlock_irqrestore(&scc->zlock, flags);
 }
 
+/*
+ * Hack alert!
+ * Required solely so that the initial PROM-based console
+ * works undisturbed in parallel with this one.
+ */
+static void zs_pm(struct uart_port *uport, unsigned int state,
+                 unsigned int oldstate)
+{
+       struct zs_port *zport = to_zport(uport);
+
+       if (state < 3)
+               zport->regs[5] |= TxENAB;
+       else
+               zport->regs[5] &= ~TxENAB;
+       write_zsreg(zport, R5, zport->regs[5]);
+}
+
 
 static const char *zs_type(struct uart_port *uport)
 {
@@ -1041,6 +1056,7 @@ static struct uart_ops zs_ops = {
        .startup        = zs_startup,
        .shutdown       = zs_shutdown,
        .set_termios    = zs_set_termios,
+       .pm             = zs_pm,
        .type           = zs_type,
        .release_port   = zs_release_port,
        .request_port   = zs_request_port,
@@ -1190,6 +1206,7 @@ static int __init zs_console_setup(struct console *co, char *options)
                return ret;
 
        zs_reset(zport);
+       zs_pm(uport, 0, -1);
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
index 66ec5d8808de83c5393fd0d35fb0d6352bc24161..2303521b4f0984efa7fcc7c1719de1d33a71e74e 100644 (file)
@@ -49,25 +49,26 @@ config SPI_MASTER
          controller and the protocol drivers for the SPI slave chips
          that are connected.
 
+if SPI_MASTER
+
 comment "SPI Master Controller Drivers"
-       depends on SPI_MASTER
 
 config SPI_ATMEL
        tristate "Atmel SPI Controller"
-       depends on (ARCH_AT91 || AVR32) && SPI_MASTER
+       depends on (ARCH_AT91 || AVR32)
        help
          This selects a driver for the Atmel SPI Controller, present on
          many AT32 (AVR32) and AT91 (ARM) chips.
 
 config SPI_BFIN
        tristate "SPI controller driver for ADI Blackfin5xx"
-       depends on SPI_MASTER && BLACKFIN
+       depends on BLACKFIN
        help
          This is the SPI controller master driver for Blackfin 5xx processor.
 
 config SPI_AU1550
        tristate "Au1550/Au12x0 SPI Controller"
-       depends on SPI_MASTER && (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
+       depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
        select SPI_BITBANG
        help
          If you say yes to this option, support will be included for the
@@ -78,7 +79,6 @@ config SPI_AU1550
 
 config SPI_BITBANG
        tristate "Bitbanging SPI master"
-       depends on SPI_MASTER && EXPERIMENTAL
        help
          With a few GPIO pins, your system can bitbang the SPI protocol.
          Select this to get SPI support through I/O pins (GPIO, parallel
@@ -92,7 +92,7 @@ config SPI_BITBANG
 
 config SPI_BUTTERFLY
        tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
-       depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+       depends on PARPORT
        select SPI_BITBANG
        help
          This uses a custom parallel port cable to connect to an AVR
@@ -102,14 +102,14 @@ config SPI_BUTTERFLY
 
 config SPI_IMX
        tristate "Freescale iMX SPI controller"
-       depends on SPI_MASTER && ARCH_IMX && EXPERIMENTAL
+       depends on ARCH_IMX && EXPERIMENTAL
        help
          This enables using the Freescale iMX SPI controller in master
          mode.
 
 config SPI_LM70_LLP
        tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
-       depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+       depends on PARPORT && EXPERIMENTAL
        select SPI_BITBANG
        help
          This driver supports the NS LM70 LLP Evaluation Board,
@@ -118,14 +118,14 @@ config SPI_LM70_LLP
 
 config SPI_MPC52xx_PSC
        tristate "Freescale MPC52xx PSC SPI controller"
-       depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
+       depends on PPC_MPC52xx && EXPERIMENTAL
        help
          This enables using the Freescale MPC52xx Programmable Serial
          Controller in master SPI mode.
 
 config SPI_MPC83xx
        tristate "Freescale MPC83xx/QUICC Engine SPI controller"
-       depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
+       depends on (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
        help
          This enables using the Freescale MPC83xx and QUICC Engine SPI
          controllers in master mode.
@@ -137,21 +137,21 @@ config SPI_MPC83xx
 
 config SPI_OMAP_UWIRE
        tristate "OMAP1 MicroWire"
-       depends on SPI_MASTER && ARCH_OMAP1
+       depends on ARCH_OMAP1
        select SPI_BITBANG
        help
          This hooks up to the MicroWire controller on OMAP1 chips.
 
 config SPI_OMAP24XX
        tristate "McSPI driver for OMAP24xx/OMAP34xx"
-       depends on SPI_MASTER && (ARCH_OMAP24XX || ARCH_OMAP34XX)
+       depends on ARCH_OMAP24XX || ARCH_OMAP34XX
        help
          SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI
          (McSPI) modules.
 
 config SPI_PXA2XX
        tristate "PXA2xx SSP SPI master"
-       depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
+       depends on ARCH_PXA && EXPERIMENTAL
        select PXA_SSP
        help
          This enables using a PXA2xx SSP port as a SPI master controller.
@@ -160,14 +160,14 @@ config SPI_PXA2XX
 
 config SPI_S3C24XX
        tristate "Samsung S3C24XX series SPI"
-       depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+       depends on ARCH_S3C2410 && EXPERIMENTAL
        select SPI_BITBANG
        help
          SPI driver for Samsung S3C24XX series ARM SoCs
 
 config SPI_S3C24XX_GPIO
        tristate "Samsung S3C24XX series SPI by GPIO"
-       depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+       depends on ARCH_S3C2410 && EXPERIMENTAL
        select SPI_BITBANG
        help
          SPI driver for Samsung S3C24XX series ARM SoCs using
@@ -177,20 +177,20 @@ config SPI_S3C24XX_GPIO
 
 config SPI_SH_SCI
        tristate "SuperH SCI SPI controller"
-       depends on SPI_MASTER && SUPERH
+       depends on SUPERH
        select SPI_BITBANG
        help
          SPI driver for SuperH SCI blocks.
 
 config SPI_TXX9
        tristate "Toshiba TXx9 SPI controller"
-       depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
+       depends on GENERIC_GPIO && CPU_TX49XX
        help
          SPI driver for Toshiba TXx9 MIPS SoCs
 
 config SPI_XILINX
        tristate "Xilinx SPI controller"
-       depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL
+       depends on XILINX_VIRTEX && EXPERIMENTAL
        select SPI_BITBANG
        help
          This exposes the SPI controller IP from the Xilinx EDK.
@@ -207,11 +207,10 @@ config SPI_XILINX
 # being probably the most widely used ones.
 #
 comment "SPI Protocol Masters"
-       depends on SPI_MASTER
 
 config SPI_AT25
        tristate "SPI EEPROMs from most vendors"
-       depends on SPI_MASTER && SYSFS
+       depends on SYSFS
        help
          Enable this driver to get read/write support to most SPI EEPROMs,
          after you configure the board init code to know about each eeprom
@@ -222,7 +221,7 @@ config SPI_AT25
 
 config SPI_SPIDEV
        tristate "User mode SPI device driver support"
-       depends on SPI_MASTER && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          This supports user mode SPI protocol drivers.
 
@@ -231,7 +230,7 @@ config SPI_SPIDEV
 
 config SPI_TLE62X0
        tristate "Infineon TLE62X0 (for power switching)"
-       depends on SPI_MASTER && SYSFS
+       depends on SYSFS
        help
          SPI driver for Infineon TLE62X0 series line driver chips,
          such as the TLE6220, TLE6230 and TLE6240.  This provides a
@@ -242,6 +241,8 @@ config SPI_TLE62X0
 # Add new SPI protocol masters in alphabetical order above this line
 #
 
+endif # SPI_MASTER
+
 # (slave support would go here)
 
 endif # SPI
index e81d59d789108041fee33e62b22b82d14e34fef3..0c7165660853a7194b16f8b2ed3cbf4849d78eb2 100644 (file)
@@ -313,14 +313,14 @@ atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
                xfer->tx_dma = dma_map_single(dev,
                                (void *) xfer->tx_buf, xfer->len,
                                DMA_TO_DEVICE);
-               if (dma_mapping_error(xfer->tx_dma))
+               if (dma_mapping_error(dev, xfer->tx_dma))
                        return -ENOMEM;
        }
        if (xfer->rx_buf) {
                xfer->rx_dma = dma_map_single(dev,
                                xfer->rx_buf, xfer->len,
                                DMA_FROM_DEVICE);
-               if (dma_mapping_error(xfer->rx_dma)) {
+               if (dma_mapping_error(dev, xfer->rx_dma)) {
                        if (xfer->tx_buf)
                                dma_unmap_single(dev,
                                                xfer->tx_dma, xfer->len,
index 072c4a595334dd41de5ed7d7ec2f9bc85d6817b4..87b73e0169c51eb2137d29679ceccbbf179b1568 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/errno.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/resource.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/dma-mapping.h>
@@ -81,6 +82,7 @@ struct au1550_spi {
        struct spi_master *master;
        struct device *dev;
        struct au1550_spi_info *pdata;
+       struct resource *ioarea;
 };
 
 
@@ -96,6 +98,8 @@ static dbdev_tab_t au1550_spi_mem_dbdev =
        .dev_intpolarity        = 0
 };
 
+static int ddma_memid; /* id to above mem dma device */
+
 static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw);
 
 
@@ -330,7 +334,7 @@ static int au1550_spi_dma_rxtmp_alloc(struct au1550_spi *hw, unsigned size)
        hw->dma_rx_tmpbuf_size = size;
        hw->dma_rx_tmpbuf_addr = dma_map_single(hw->dev, hw->dma_rx_tmpbuf,
                        size, DMA_FROM_DEVICE);
-       if (dma_mapping_error(hw->dma_rx_tmpbuf_addr)) {
+       if (dma_mapping_error(hw->dev, hw->dma_rx_tmpbuf_addr)) {
                kfree(hw->dma_rx_tmpbuf);
                hw->dma_rx_tmpbuf = 0;
                hw->dma_rx_tmpbuf_size = 0;
@@ -374,7 +378,7 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
                        dma_rx_addr = dma_map_single(hw->dev,
                                        (void *)t->rx_buf,
                                        t->len, DMA_FROM_DEVICE);
-                       if (dma_mapping_error(dma_rx_addr))
+                       if (dma_mapping_error(hw->dev, dma_rx_addr))
                                dev_err(hw->dev, "rx dma map error\n");
                }
        } else {
@@ -397,7 +401,7 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
                        dma_tx_addr = dma_map_single(hw->dev,
                                        (void *)t->tx_buf,
                                        t->len, DMA_TO_DEVICE);
-                       if (dma_mapping_error(dma_tx_addr))
+                       if (dma_mapping_error(hw->dev, dma_tx_addr))
                                dev_err(hw->dev, "tx dma map error\n");
                }
        } else {
@@ -480,9 +484,13 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
                au1xxx_dbdma_reset(hw->dma_tx_ch);
                au1550_spi_reset_fifos(hw);
 
-               dev_err(hw->dev,
-                       "Unexpected SPI error: event=0x%x stat=0x%x!\n",
-                       evnt, stat);
+               if (evnt == PSC_SPIEVNT_RO)
+                       dev_err(hw->dev,
+                               "dma transfer: receive FIFO overflow!\n");
+               else
+                       dev_err(hw->dev,
+                               "dma transfer: unexpected SPI error "
+                               "(event=0x%x stat=0x%x)!\n", evnt, stat);
 
                complete(&hw->master_done);
                return IRQ_HANDLED;
@@ -592,17 +600,17 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
 
        if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
                                | PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
-                               | PSC_SPIEVNT_TU | PSC_SPIEVNT_SD))
+                               | PSC_SPIEVNT_SD))
                        != 0) {
-               dev_err(hw->dev,
-                       "Unexpected SPI error: event=0x%x stat=0x%x!\n",
-                       evnt, stat);
                /*
                 * due to an error we consider transfer as done,
                 * so mask all events until before next transfer start
                 */
                au1550_spi_mask_ack_all(hw);
                au1550_spi_reset_fifos(hw);
+               dev_err(hw->dev,
+                       "pio transfer: unexpected SPI error "
+                       "(event=0x%x stat=0x%x)!\n", evnt, stat);
                complete(&hw->master_done);
                return IRQ_HANDLED;
        }
@@ -616,27 +624,50 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
                stat = hw->regs->psc_spistat;
                au_sync();
 
-               if ((stat & PSC_SPISTAT_RE) == 0 && hw->rx_count < hw->len) {
+               /*
+                * Take care to not let the Rx FIFO overflow.
+                *
+                * We only write a byte if we have read one at least. Initially,
+                * the write fifo is full, so we should read from the read fifo
+                * first.
+                * In case we miss a word from the read fifo, we should get a
+                * RO event and should back out.
+                */
+               if (!(stat & PSC_SPISTAT_RE) && hw->rx_count < hw->len) {
                        hw->rx_word(hw);
-                       /* ack the receive request event */
-                       hw->regs->psc_spievent = PSC_SPIEVNT_RR;
-                       au_sync();
                        busy = 1;
-               }
 
-               if ((stat & PSC_SPISTAT_TF) == 0 && hw->tx_count < hw->len) {
-                       hw->tx_word(hw);
-                       /* ack the transmit request event */
-                       hw->regs->psc_spievent = PSC_SPIEVNT_TR;
-                       au_sync();
-                       busy = 1;
+                       if (!(stat & PSC_SPISTAT_TF) && hw->tx_count < hw->len)
+                               hw->tx_word(hw);
                }
        } while (busy);
 
-       evnt = hw->regs->psc_spievent;
+       hw->regs->psc_spievent = PSC_SPIEVNT_RR | PSC_SPIEVNT_TR;
        au_sync();
 
-       if (hw->rx_count >= hw->len || (evnt & PSC_SPIEVNT_MD) != 0) {
+       /*
+        * Restart the SPI transmission in case of a transmit underflow.
+        * This seems to work despite the notes in the Au1550 data book
+        * of Figure 8-4 with flowchart for SPI master operation:
+        *
+        * """Note 1: An XFR Error Interrupt occurs, unless masked,
+        * for any of the following events: Tx FIFO Underflow,
+        * Rx FIFO Overflow, or Multiple-master Error
+        *    Note 2: In case of a Tx Underflow Error, all zeroes are
+        * transmitted."""
+        *
+        * By simply restarting the spi transfer on Tx Underflow Error,
+        * we assume that spi transfer was paused instead of zeroes
+        * transmittion mentioned in the Note 2 of Au1550 data book.
+        */
+       if (evnt & PSC_SPIEVNT_TU) {
+               hw->regs->psc_spievent = PSC_SPIEVNT_TU | PSC_SPIEVNT_MD;
+               au_sync();
+               hw->regs->psc_spipcr = PSC_SPIPCR_MS;
+               au_sync();
+       }
+
+       if (hw->rx_count >= hw->len) {
                /* transfer completed successfully */
                au1550_spi_mask_ack_all(hw);
                complete(&hw->master_done);
@@ -725,6 +756,8 @@ static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
                stat = hw->regs->psc_spistat;
                au_sync();
        } while ((stat & PSC_SPISTAT_DR) == 0);
+
+       au1550_spi_reset_fifos(hw);
 }
 
 
@@ -732,6 +765,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
 {
        struct au1550_spi *hw;
        struct spi_master *master;
+       struct resource *r;
        int err = 0;
 
        master = spi_alloc_master(&pdev->dev, sizeof(struct au1550_spi));
@@ -753,76 +787,64 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
                goto err_no_pdata;
        }
 
-       platform_set_drvdata(pdev, hw);
-
-       init_completion(&hw->master_done);
-
-       hw->bitbang.master = hw->master;
-       hw->bitbang.setup_transfer = au1550_spi_setupxfer;
-       hw->bitbang.chipselect = au1550_spi_chipsel;
-       hw->bitbang.master->setup = au1550_spi_setup;
-       hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
+       r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!r) {
+               dev_err(&pdev->dev, "no IRQ\n");
+               err = -ENODEV;
+               goto err_no_iores;
+       }
+       hw->irq = r->start;
+
+       hw->usedma = 0;
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (r) {
+               hw->dma_tx_id = r->start;
+               r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+               if (r) {
+                       hw->dma_rx_id = r->start;
+                       if (usedma && ddma_memid) {
+                               if (pdev->dev.dma_mask == NULL)
+                                       dev_warn(&pdev->dev, "no dma mask\n");
+                               else
+                                       hw->usedma = 1;
+                       }
+               }
+       }
 
-       switch (hw->pdata->bus_num) {
-       case 0:
-               hw->irq = AU1550_PSC0_INT;
-               hw->regs = (volatile psc_spi_t *)PSC0_BASE_ADDR;
-               hw->dma_rx_id = DSCR_CMD0_PSC0_RX;
-               hw->dma_tx_id = DSCR_CMD0_PSC0_TX;
-               break;
-       case 1:
-               hw->irq = AU1550_PSC1_INT;
-               hw->regs = (volatile psc_spi_t *)PSC1_BASE_ADDR;
-               hw->dma_rx_id = DSCR_CMD0_PSC1_RX;
-               hw->dma_tx_id = DSCR_CMD0_PSC1_TX;
-               break;
-       case 2:
-               hw->irq = AU1550_PSC2_INT;
-               hw->regs = (volatile psc_spi_t *)PSC2_BASE_ADDR;
-               hw->dma_rx_id = DSCR_CMD0_PSC2_RX;
-               hw->dma_tx_id = DSCR_CMD0_PSC2_TX;
-               break;
-       case 3:
-               hw->irq = AU1550_PSC3_INT;
-               hw->regs = (volatile psc_spi_t *)PSC3_BASE_ADDR;
-               hw->dma_rx_id = DSCR_CMD0_PSC3_RX;
-               hw->dma_tx_id = DSCR_CMD0_PSC3_TX;
-               break;
-       default:
-               dev_err(&pdev->dev, "Wrong bus_num of SPI\n");
-               err = -ENOENT;
-               goto err_no_pdata;
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               dev_err(&pdev->dev, "no mmio resource\n");
+               err = -ENODEV;
+               goto err_no_iores;
        }
 
-       if (request_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t),
-                       pdev->name) == NULL) {
+       hw->ioarea = request_mem_region(r->start, sizeof(psc_spi_t),
+                                       pdev->name);
+       if (!hw->ioarea) {
                dev_err(&pdev->dev, "Cannot reserve iomem region\n");
                err = -ENXIO;
                goto err_no_iores;
        }
 
-
-       if (usedma) {
-               if (pdev->dev.dma_mask == NULL)
-                       dev_warn(&pdev->dev, "no dma mask\n");
-               else
-                       hw->usedma = 1;
+       hw->regs = (psc_spi_t __iomem *)ioremap(r->start, sizeof(psc_spi_t));
+       if (!hw->regs) {
+               dev_err(&pdev->dev, "cannot ioremap\n");
+               err = -ENXIO;
+               goto err_ioremap;
        }
 
-       if (hw->usedma) {
-               /*
-                * create memory device with 8 bits dev_devwidth
-                * needed for proper byte ordering to spi fifo
-                */
-               int memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
-               if (!memid) {
-                       dev_err(&pdev->dev,
-                               "Cannot create dma 8 bit mem device\n");
-                       err = -ENXIO;
-                       goto err_dma_add_dev;
-               }
+       platform_set_drvdata(pdev, hw);
+
+       init_completion(&hw->master_done);
+
+       hw->bitbang.master = hw->master;
+       hw->bitbang.setup_transfer = au1550_spi_setupxfer;
+       hw->bitbang.chipselect = au1550_spi_chipsel;
+       hw->bitbang.master->setup = au1550_spi_setup;
+       hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
 
-               hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(memid,
+       if (hw->usedma) {
+               hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(ddma_memid,
                        hw->dma_tx_id, NULL, (void *)hw);
                if (hw->dma_tx_ch == 0) {
                        dev_err(&pdev->dev,
@@ -841,7 +863,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
 
 
                hw->dma_rx_ch = au1xxx_dbdma_chan_alloc(hw->dma_rx_id,
-                       memid, NULL, (void *)hw);
+                       ddma_memid, NULL, (void *)hw);
                if (hw->dma_rx_ch == 0) {
                        dev_err(&pdev->dev,
                                "Cannot allocate rx dma channel\n");
@@ -874,7 +896,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
                goto err_no_irq;
        }
 
-       master->bus_num = hw->pdata->bus_num;
+       master->bus_num = pdev->id;
        master->num_chipselect = hw->pdata->num_chipselect;
 
        /*
@@ -924,8 +946,11 @@ err_no_txdma_descr:
                au1xxx_dbdma_chan_free(hw->dma_tx_ch);
 
 err_no_txdma:
-err_dma_add_dev:
-       release_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t));
+       iounmap((void __iomem *)hw->regs);
+
+err_ioremap:
+       release_resource(hw->ioarea);
+       kfree(hw->ioarea);
 
 err_no_iores:
 err_no_pdata:
@@ -944,7 +969,9 @@ static int __exit au1550_spi_remove(struct platform_device *pdev)
 
        spi_bitbang_stop(&hw->bitbang);
        free_irq(hw->irq, hw);
-       release_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t));
+       iounmap((void __iomem *)hw->regs);
+       release_resource(hw->ioarea);
+       kfree(hw->ioarea);
 
        if (hw->usedma) {
                au1550_spi_dma_rxtmp_free(hw);
@@ -971,12 +998,24 @@ static struct platform_driver au1550_spi_drv = {
 
 static int __init au1550_spi_init(void)
 {
+       /*
+        * create memory device with 8 bits dev_devwidth
+        * needed for proper byte ordering to spi fifo
+        */
+       if (usedma) {
+               ddma_memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
+               if (!ddma_memid)
+                       printk(KERN_ERR "au1550-spi: cannot add memory"
+                                       "dbdma device\n");
+       }
        return platform_driver_probe(&au1550_spi_drv, au1550_spi_probe);
 }
 module_init(au1550_spi_init);
 
 static void __exit au1550_spi_exit(void)
 {
+       if (usedma && ddma_memid)
+               au1xxx_ddma_del_device(ddma_memid);
        platform_driver_unregister(&au1550_spi_drv);
 }
 module_exit(au1550_spi_exit);
index 604e5f0a2d951d5ae347a380733c342848198792..25eda71f4bf4c29c442633c5ff2914dad2839e5a 100644 (file)
@@ -148,7 +148,6 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
        unsigned rfalarm;
        unsigned send_at_once = MPC52xx_PSC_BUFSIZE;
        unsigned recv_at_once;
-       unsigned bpw = mps->bits_per_word / 8;
 
        if (!t->tx_buf && !t->rx_buf && t->len)
                return -EINVAL;
@@ -164,22 +163,15 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
                }
 
                dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once);
-               if (tx_buf) {
-                       for (; send_at_once; sb++, send_at_once--) {
-                               /* set EOF flag */
-                               if (mps->bits_per_word
-                                               && (sb + 1) % bpw == 0)
-                                       out_8(&psc->ircr2, 0x01);
+               for (; send_at_once; sb++, send_at_once--) {
+                       /* set EOF flag before the last word is sent */
+                       if (send_at_once == 1)
+                               out_8(&psc->ircr2, 0x01);
+
+                       if (tx_buf)
                                out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]);
-                       }
-               } else {
-                       for (; send_at_once; sb++, send_at_once--) {
-                               /* set EOF flag */
-                               if (mps->bits_per_word
-                                               && ((sb + 1) % bpw) == 0)
-                                       out_8(&psc->ircr2, 0x01);
+                       else
                                out_8(&psc->mpc52xx_psc_buffer_8, 0);
-                       }
                }
 
 
index b1cc148036c1e378ef870c0fa30f614f2a92745a..f6f987bb71ca39413192c0a3de0e8f2a2ac2e6a0 100644 (file)
@@ -836,7 +836,7 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
                if (tx_buf != NULL) {
                        t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
                                        len, DMA_TO_DEVICE);
-                       if (dma_mapping_error(t->tx_dma)) {
+                       if (dma_mapping_error(&spi->dev, t->tx_dma)) {
                                dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
                                                'T', len);
                                return -EINVAL;
@@ -845,7 +845,7 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
                if (rx_buf != NULL) {
                        t->rx_dma = dma_map_single(&spi->dev, rx_buf, t->len,
                                        DMA_FROM_DEVICE);
-                       if (dma_mapping_error(t->rx_dma)) {
+                       if (dma_mapping_error(&spi->dev, t->rx_dma)) {
                                dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
                                                'R', len);
                                if (tx_buf != NULL)
index 0c452c46ab0778bf3e1c5458dcec0c270a979016..067299d6d1921045f81771530c0ebba268e51b3b 100644 (file)
@@ -353,7 +353,7 @@ static int map_dma_buffers(struct driver_data *drv_data)
        drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
                                                drv_data->rx_map_len,
                                                DMA_FROM_DEVICE);
-       if (dma_mapping_error(drv_data->rx_dma))
+       if (dma_mapping_error(dev, drv_data->rx_dma))
                return 0;
 
        /* Stream map the tx buffer */
@@ -361,7 +361,7 @@ static int map_dma_buffers(struct driver_data *drv_data)
                                                drv_data->tx_map_len,
                                                DMA_TO_DEVICE);
 
-       if (dma_mapping_error(drv_data->tx_dma)) {
+       if (dma_mapping_error(dev, drv_data->tx_dma)) {
                dma_unmap_single(dev, drv_data->rx_dma,
                                        drv_data->rx_map_len, DMA_FROM_DEVICE);
                return 0;
index 1771b2456bfaf8f60ab3d0fdfafdd443813b3138..964124b60db2560b12f15d08dbdeeff43a058e16 100644 (file)
@@ -178,6 +178,96 @@ struct boardinfo {
 static LIST_HEAD(board_list);
 static DEFINE_MUTEX(board_lock);
 
+/**
+ * spi_alloc_device - Allocate a new SPI device
+ * @master: Controller to which device is connected
+ * Context: can sleep
+ *
+ * Allows a driver to allocate and initialize a spi_device without
+ * registering it immediately.  This allows a driver to directly
+ * fill the spi_device with device parameters before calling
+ * spi_add_device() on it.
+ *
+ * Caller is responsible to call spi_add_device() on the returned
+ * spi_device structure to add it to the SPI master.  If the caller
+ * needs to discard the spi_device without adding it, then it should
+ * call spi_dev_put() on it.
+ *
+ * Returns a pointer to the new device, or NULL.
+ */
+struct spi_device *spi_alloc_device(struct spi_master *master)
+{
+       struct spi_device       *spi;
+       struct device           *dev = master->dev.parent;
+
+       if (!spi_master_get(master))
+               return NULL;
+
+       spi = kzalloc(sizeof *spi, GFP_KERNEL);
+       if (!spi) {
+               dev_err(dev, "cannot alloc spi_device\n");
+               spi_master_put(master);
+               return NULL;
+       }
+
+       spi->master = master;
+       spi->dev.parent = dev;
+       spi->dev.bus = &spi_bus_type;
+       spi->dev.release = spidev_release;
+       device_initialize(&spi->dev);
+       return spi;
+}
+EXPORT_SYMBOL_GPL(spi_alloc_device);
+
+/**
+ * spi_add_device - Add spi_device allocated with spi_alloc_device
+ * @spi: spi_device to register
+ *
+ * Companion function to spi_alloc_device.  Devices allocated with
+ * spi_alloc_device can be added onto the spi bus with this function.
+ *
+ * Returns 0 on success; non-zero on failure
+ */
+int spi_add_device(struct spi_device *spi)
+{
+       struct device *dev = spi->master->dev.parent;
+       int status;
+
+       /* Chipselects are numbered 0..max; validate. */
+       if (spi->chip_select >= spi->master->num_chipselect) {
+               dev_err(dev, "cs%d >= max %d\n",
+                       spi->chip_select,
+                       spi->master->num_chipselect);
+               return -EINVAL;
+       }
+
+       /* Set the bus ID string */
+       snprintf(spi->dev.bus_id, sizeof spi->dev.bus_id,
+                       "%s.%u", spi->master->dev.bus_id,
+                       spi->chip_select);
+
+       /* drivers may modify this initial i/o setup */
+       status = spi->master->setup(spi);
+       if (status < 0) {
+               dev_err(dev, "can't %s %s, status %d\n",
+                               "setup", spi->dev.bus_id, status);
+               return status;
+       }
+
+       /* driver core catches callers that misbehave by defining
+        * devices that already exist.
+        */
+       status = device_add(&spi->dev);
+       if (status < 0) {
+               dev_err(dev, "can't %s %s, status %d\n",
+                               "add", spi->dev.bus_id, status);
+               return status;
+       }
+
+       dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(spi_add_device);
 
 /**
  * spi_new_device - instantiate one new SPI device
@@ -197,7 +287,6 @@ struct spi_device *spi_new_device(struct spi_master *master,
                                  struct spi_board_info *chip)
 {
        struct spi_device       *proxy;
-       struct device           *dev = master->dev.parent;
        int                     status;
 
        /* NOTE:  caller did any chip->bus_num checks necessary.
@@ -207,64 +296,28 @@ struct spi_device *spi_new_device(struct spi_master *master,
         * suggests syslogged diagnostics are best here (ugh).
         */
 
-       /* Chipselects are numbered 0..max; validate. */
-       if (chip->chip_select >= master->num_chipselect) {
-               dev_err(dev, "cs%d > max %d\n",
-                       chip->chip_select,
-                       master->num_chipselect);
+       proxy = spi_alloc_device(master);
+       if (!proxy)
                return NULL;
-       }
 
-       if (!spi_master_get(master))
-               return NULL;
+       WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
 
-       proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
-       if (!proxy) {
-               dev_err(dev, "can't alloc dev for cs%d\n",
-                       chip->chip_select);
-               goto fail;
-       }
-       proxy->master = master;
        proxy->chip_select = chip->chip_select;
        proxy->max_speed_hz = chip->max_speed_hz;
        proxy->mode = chip->mode;
        proxy->irq = chip->irq;
-       proxy->modalias = chip->modalias;
-
-       snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
-                       "%s.%u", master->dev.bus_id,
-                       chip->chip_select);
-       proxy->dev.parent = dev;
-       proxy->dev.bus = &spi_bus_type;
+       strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
        proxy->dev.platform_data = (void *) chip->platform_data;
        proxy->controller_data = chip->controller_data;
        proxy->controller_state = NULL;
-       proxy->dev.release = spidev_release;
 
-       /* drivers may modify this initial i/o setup */
-       status = master->setup(proxy);
+       status = spi_add_device(proxy);
        if (status < 0) {
-               dev_err(dev, "can't %s %s, status %d\n",
-                               "setup", proxy->dev.bus_id, status);
-               goto fail;
+               spi_dev_put(proxy);
+               return NULL;
        }
 
-       /* driver core catches callers that misbehave by defining
-        * devices that already exist.
-        */
-       status = device_register(&proxy->dev);
-       if (status < 0) {
-               dev_err(dev, "can't %s %s, status %d\n",
-                               "add", proxy->dev.bus_id, status);
-               goto fail;
-       }
-       dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id);
        return proxy;
-
-fail:
-       spi_master_put(master);
-       kfree(proxy);
-       return NULL;
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
index 54ac7bea5f8c0e35204d20d004ca4be3d6da736d..6fb77fcc49711548bed2cd1248cb8246b5b770fb 100644 (file)
@@ -491,7 +491,7 @@ static int map_dma_buffers(struct driver_data *drv_data)
                                                        buf,
                                                        drv_data->tx_map_len,
                                                        DMA_TO_DEVICE);
-                       if (dma_mapping_error(drv_data->tx_dma))
+                       if (dma_mapping_error(dev, drv_data->tx_dma))
                                return -1;
 
                        drv_data->tx_dma_needs_unmap = 1;
@@ -516,7 +516,7 @@ static int map_dma_buffers(struct driver_data *drv_data)
                                        buf,
                                        drv_data->len,
                                        DMA_FROM_DEVICE);
-               if (dma_mapping_error(drv_data->rx_dma))
+               if (dma_mapping_error(dev, drv_data->rx_dma))
                        return -1;
                drv_data->rx_dma_needs_unmap = 1;
        }
@@ -534,7 +534,7 @@ static int map_dma_buffers(struct driver_data *drv_data)
                                        buf,
                                        drv_data->tx_map_len,
                                        DMA_TO_DEVICE);
-       if (dma_mapping_error(drv_data->tx_dma)) {
+       if (dma_mapping_error(dev, drv_data->tx_dma)) {
                if (drv_data->rx_dma) {
                        dma_unmap_single(dev,
                                        drv_data->rx_dma,
index 6832da6f7109c32a379c169b1943abd56ac6af99..070c6219e2d605a617c55547984cc61548a27bf3 100644 (file)
@@ -266,21 +266,24 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 
        cs->hw_mode |= SPMODE_LEN(bits_per_word);
 
-       if ((mpc83xx_spi->spibrg / hz) >= 64) {
-               pm = mpc83xx_spi->spibrg / (hz * 64) - 1;
-               if (pm > 0x0f) {
-                       dev_err(&spi->dev, "Requested speed is too "
-                               "low: %d Hz. Will use %d Hz instead.\n",
-                               hz, mpc83xx_spi->spibrg / 1024);
-                       pm = 0x0f;
+       if ((mpc83xx_spi->spibrg / hz) > 64) {
+               pm = mpc83xx_spi->spibrg / (hz * 64);
+               if (pm > 16) {
+                       cs->hw_mode |= SPMODE_DIV16;
+                       pm /= 16;
+                       if (pm > 16) {
+                               dev_err(&spi->dev, "Requested speed is too "
+                                       "low: %d Hz. Will use %d Hz instead.\n",
+                                       hz, mpc83xx_spi->spibrg / 1024);
+                               pm = 16;
+                       }
                }
-               cs->hw_mode |= SPMODE_PM(pm) | SPMODE_DIV16;
-       } else {
+       } else
                pm = mpc83xx_spi->spibrg / (hz * 4);
-               if (pm)
-                       pm--;
-               cs->hw_mode |= SPMODE_PM(pm);
-       }
+       if (pm)
+               pm--;
+
+       cs->hw_mode |= SPMODE_PM(pm);
        regval =  mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
        if (cs->hw_mode != regval) {
                unsigned long flags;
index 0885cc357a371552dc2190a6da682f98a652abdb..1c643c9e1f15ff793e5d7c140e9f93ee96320544 100644 (file)
@@ -270,6 +270,7 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev)
        /* setup the master state. */
 
        master->num_chipselect = hw->pdata->num_cs;
+       master->bus_num = pdata->bus_num;
 
        /* setup the state for the bitbang driver */
 
index 2833fd772a24feb160f33a07e4bbbcc23a5cbb21..e5e0cfed5e3b3fedff7f81983a73f4b94a9de8ca 100644 (file)
@@ -228,7 +228,6 @@ static int spidev_message(struct spidev_data *spidev,
         * We walk the array of user-provided transfers, using each one
         * to initialize a kernel version of the same transfer.
         */
-       mutex_lock(&spidev->buf_lock);
        buf = spidev->buffer;
        total = 0;
        for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
@@ -296,14 +295,12 @@ static int spidev_message(struct spidev_data *spidev,
        status = total;
 
 done:
-       mutex_unlock(&spidev->buf_lock);
        kfree(k_xfers);
        return status;
 }
 
-static int
-spidev_ioctl(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+static long
+spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        int                     err = 0;
        int                     retval = 0;
@@ -341,6 +338,14 @@ spidev_ioctl(struct inode *inode, struct file *filp,
        if (spi == NULL)
                return -ESHUTDOWN;
 
+       /* use the buffer lock here for triple duty:
+        *  - prevent I/O (from us) so calling spi_setup() is safe;
+        *  - prevent concurrent SPI_IOC_WR_* from morphing
+        *    data fields while SPI_IOC_RD_* reads them;
+        *  - SPI_IOC_MESSAGE needs the buffer locked "normally".
+        */
+       mutex_lock(&spidev->buf_lock);
+
        switch (cmd) {
        /* read requests */
        case SPI_IOC_RD_MODE:
@@ -456,6 +461,8 @@ spidev_ioctl(struct inode *inode, struct file *filp,
                kfree(ioc);
                break;
        }
+
+       mutex_unlock(&spidev->buf_lock);
        spi_dev_put(spi);
        return retval;
 }
@@ -533,7 +540,7 @@ static struct file_operations spidev_fops = {
         */
        .write =        spidev_write,
        .read =         spidev_read,
-       .ioctl =        spidev_ioctl,
+       .unlocked_ioctl = spidev_ioctl,
        .open =         spidev_open,
        .release =      spidev_release,
 };
index 113a0468ffcbd3291402c136322596ac75ab28e2..68d6f4988fb52a7aca99f5315697d6cb4ca6cf91 100644 (file)
@@ -353,11 +353,12 @@ static int __init xilinx_spi_probe(struct platform_device *dev)
                goto put_master;
        }
 
-       xspi->irq = platform_get_irq(dev, 0);
-       if (xspi->irq < 0) {
+       ret = platform_get_irq(dev, 0);
+       if (ret < 0) {
                ret = -ENXIO;
                goto unmap_io;
        }
+       xspi->irq = ret;
 
        master->bus_num = pdata->bus_num;
        master->num_chipselect = pdata->num_chipselect;
index 49cd9793404f33c5165d5b77e0d9657c3f7c1b20..ec7aeb502d1548ecbfd64c521518c11857e308de 100644 (file)
@@ -6095,15 +6095,15 @@ static int capabilities_check(IXJ *j, struct phone_capability *pcreq)
        return retval;
 }
 
-static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg)
+static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg)
 {
        IXJ_TONE ti;
        IXJ_FILTER jf;
        IXJ_FILTER_RAW jfr;
        void __user *argp = (void __user *)arg;
-
-       unsigned int raise, mant;
+       struct inode *inode = file_p->f_path.dentry->d_inode;
        unsigned int minor = iminor(inode);
+       unsigned int raise, mant;
        int board = NUM(inode);
 
        IXJ *j = get_ixj(NUM(inode));
@@ -6661,6 +6661,15 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
        return retval;
 }
 
+static long ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg)
+{
+       long ret;
+       lock_kernel();
+       ret = do_ixj_ioctl(file_p, cmd, arg);
+       unlock_kernel();
+       return ret;
+}
+
 static int ixj_fasync(int fd, struct file *file_p, int mode)
 {
        IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
@@ -6674,7 +6683,7 @@ static const struct file_operations ixj_fops =
         .read           = ixj_enhanced_read,
         .write          = ixj_enhanced_write,
         .poll           = ixj_poll,
-        .ioctl          = ixj_ioctl,
+        .unlocked_ioctl = ixj_ioctl,
         .release        = ixj_release,
         .fasync         = ixj_fasync
 };
index a973f2a50fb959509472aa66db390817c78f1a7d..c65d62295890e94584045ab9f0cc4b872ab29711 100644 (file)
@@ -171,7 +171,7 @@ struct at91_request {
 #endif
 
 #define ERR(stuff...)          pr_err("udc: " stuff)
-#define WARN(stuff...)         pr_warning("udc: " stuff)
+#define WARNING(stuff...)      pr_warning("udc: " stuff)
 #define INFO(stuff...)         pr_info("udc: " stuff)
 #define DBG(stuff...)          pr_debug("udc: " stuff)
 
index d490d0289507290a752b90655323cc2ee7e8871f..a39a4b940c33c93aa129fb5aab06fd4c326e556d 100644 (file)
@@ -170,7 +170,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
                 * but if the controller isn't recognized at all then
                 * that assumption is a bit more likely to be wrong.
                 */
-               WARN(cdev, "controller '%s' not recognized; trying %s\n",
+               WARNING(cdev, "controller '%s' not recognized; trying %s\n",
                                gadget->name,
                                cdc_config_driver.label);
                device_desc.bcdDevice =
index d7aaaa29b1e1978b78cfeaad0495ad4e2e455f6e..bcac2e68660d5ba51fd8c253fa136c4385e9c058 100644 (file)
@@ -293,7 +293,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
                 * but if the controller isn't recognized at all then
                 * that assumption is a bit more likely to be wrong.
                 */
-               WARN(cdev, "controller '%s' not recognized; trying %s\n",
+               WARNING(cdev, "controller '%s' not recognized; trying %s\n",
                                gadget->name,
                                eth_config_driver.label);
                device_desc.bcdDevice =
index 15c24edbb61adb29a40db7a5e7c83dc63a4a777f..ea2c31d18080d2a23025979a4c798f5133ceba48 100644 (file)
@@ -308,7 +308,7 @@ MODULE_LICENSE("Dual BSD/GPL");
        dev_vdbg(&(d)->gadget->dev , fmt , ## args)
 #define ERROR(d, fmt, args...) \
        dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
+#define WARNING(d, fmt, args...) \
        dev_warn(&(d)->gadget->dev , fmt , ## args)
 #define INFO(d, fmt, args...) \
        dev_info(&(d)->gadget->dev , fmt , ## args)
@@ -1091,7 +1091,7 @@ static int ep0_queue(struct fsg_dev *fsg)
        if (rc != 0 && rc != -ESHUTDOWN) {
 
                /* We can't do much more than wait for a reset */
-               WARN(fsg, "error in submission: %s --> %d\n",
+               WARNING(fsg, "error in submission: %s --> %d\n",
                                fsg->ep0->name, rc);
        }
        return rc;
@@ -1227,7 +1227,7 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 
        /* Save the command for later */
        if (fsg->cbbuf_cmnd_size)
-               WARN(fsg, "CB[I] overwriting previous command\n");
+               WARNING(fsg, "CB[I] overwriting previous command\n");
        fsg->cbbuf_cmnd_size = req->actual;
        memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
 
@@ -1506,7 +1506,7 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
                 * submissions if DMA is enabled. */
                if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
                                                req->length == 0))
-                       WARN(fsg, "error in submission: %s --> %d\n",
+                       WARNING(fsg, "error in submission: %s --> %d\n",
                                        ep->name, rc);
        }
 }
@@ -2294,7 +2294,7 @@ static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
                VDBG(fsg, "delayed bulk-in endpoint halt\n");
        while (rc != 0) {
                if (rc != -EAGAIN) {
-                       WARN(fsg, "usb_ep_set_halt -> %d\n", rc);
+                       WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
                        rc = 0;
                        break;
                }
@@ -2317,7 +2317,7 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
                VDBG(fsg, "delayed bulk-in endpoint wedge\n");
        while (rc != 0) {
                if (rc != -EAGAIN) {
-                       WARN(fsg, "usb_ep_set_wedge -> %d\n", rc);
+                       WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
                        rc = 0;
                        break;
                }
@@ -3755,7 +3755,7 @@ static int __init check_parameters(struct fsg_dev *fsg)
                if (gcnum >= 0)
                        mod_data.release = 0x0300 + gcnum;
                else {
-                       WARN(fsg, "controller '%s' not recognized\n",
+                       WARNING(fsg, "controller '%s' not recognized\n",
                                fsg->gadget->name);
                        mod_data.release = 0x0399;
                }
index 1695382f30fe5ce3a4898f067b12b8a632429f96..1cfccf102a2dc9fdc9948daf4aadaf5a32c793cf 100644 (file)
@@ -1538,7 +1538,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
 
                /* If the ep is configured */
                if (curr_ep->name == NULL) {
-                       WARN("Invalid EP?");
+                       WARNING("Invalid EP?");
                        continue;
                }
 
index 98b1483ef6a511459e44b2b8f17ada3329570ec1..6131752a38bcc617f5f7388fcb83da41c03df474 100644 (file)
@@ -552,7 +552,7 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length)
 #endif
 
 #define ERR(stuff...)          pr_err("udc: " stuff)
-#define WARN(stuff...)         pr_warning("udc: " stuff)
+#define WARNING(stuff...)              pr_warning("udc: " stuff)
 #define INFO(stuff...)         pr_info("udc: " stuff)
 
 /*-------------------------------------------------------------------------*/
index 7f4d4828e3aabaca7db67bd512017f094b419992..ea8651e3da1a53a205ffe67e88889b87d5073a89 100644 (file)
@@ -138,8 +138,6 @@ static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req);
        dev_vdbg(&(d)->gadget->dev , fmt , ## args)
 #define ERROR(d, fmt, args...) \
        dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
-       dev_warn(&(d)->gadget->dev , fmt , ## args)
 #define INFO(d, fmt, args...) \
        dev_info(&(d)->gadget->dev , fmt , ## args)
 
index 48f1c63b70136ec17d458091e4ae7cba8528aaf5..60aa04847b189255522cf60489cb1d88a16e737b 100644 (file)
@@ -1768,7 +1768,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
         * usb_gadget_driver_{register,unregister}() must change.
         */
        if (the_controller) {
-               WARN(dev, "ignoring %s\n", pci_name(pdev));
+               WARNING(dev, "ignoring %s\n", pci_name(pdev));
                return -EBUSY;
        }
        if (!pdev->irq) {
index bc4eb1e0b507213c4da4ae1abbefdc7701340863..566cb23190565288ec500fc3c525944801982910 100644 (file)
@@ -285,7 +285,7 @@ struct goku_udc {
 
 #define ERROR(dev,fmt,args...) \
        xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
+#define WARNING(dev,fmt,args...) \
        xprintk(dev , KERN_WARNING , fmt , ## args)
 #define INFO(dev,fmt,args...) \
        xprintk(dev , KERN_INFO , fmt , ## args)
index 04692d59fc1cda8d22a883beaca7b7d976f49aa5..f4585d3e90d7a54fd4836648e2cb50eed7d7a947 100644 (file)
@@ -262,8 +262,6 @@ static const char *CHIP;
 
 #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)
 
index b67ab677af725dd2d5d685ed3f982651f085d5a6..5cfb5ebf388159546ae4aa59bd71b42b04b83c9b 100644 (file)
@@ -1007,7 +1007,7 @@ static void scan_dma_completions (struct net2280_ep *ep)
                         * 0122, and 0124; not all cases trigger the warning.
                         */
                        if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
-                               WARN (ep->dev, "%s lost packet sync!\n",
+                               WARNING (ep->dev, "%s lost packet sync!\n",
                                                ep->ep.name);
                                req->req.status = -EOVERFLOW;
                        } else if ((tmp = readl (&ep->regs->ep_avail)) != 0) {
index 1f2af398a9a405df9e78192080474114c2ac95f6..81a71dbdc2c6c029df26500ef37754f0c77c366e 100644 (file)
@@ -272,7 +272,7 @@ static inline void net2280_led_shutdown (struct net2280 *dev)
 
 #define ERROR(dev,fmt,args...) \
        xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
+#define WARNING(dev,fmt,args...) \
        xprintk(dev , KERN_WARNING , fmt , ## args)
 #define INFO(dev,fmt,args...) \
        xprintk(dev , KERN_INFO , fmt , ## args)
index 4b79a8509e848e8ebb3d6d656d684d3d3af080f9..395bd18444828577a97487ca87f9cd289d8e1095 100644 (file)
@@ -1120,7 +1120,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
                        status = -EINVAL;
                else if (value) {
                        if (ep->udc->ep0_set_config) {
-                               WARN("error changing config?\n");
+                               WARNING("error changing config?\n");
                                omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
                        }
                        omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
@@ -1764,7 +1764,7 @@ do_stall:
                                        u.r.bRequestType, u.r.bRequest, status);
                        if (udc->ep0_set_config) {
                                if (udc->ep0_reset_config)
-                                       WARN("error resetting config?\n");
+                                       WARNING("error resetting config?\n");
                                else
                                        omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
                        }
@@ -3076,7 +3076,7 @@ static int omap_udc_suspend(struct platform_device *dev, pm_message_t message)
         * which would prevent entry to deep sleep...
         */
        if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) {
-               WARN("session active; suspend requires disconnect\n");
+               WARNING("session active; suspend requires disconnect\n");
                omap_pullup(&udc->gadget, 0);
        }
 
index 8522bbb12278a37dcac839a587aae062dc541a58..29edc51b6b2212dba3df4853dea948cd5c878223 100644 (file)
@@ -188,7 +188,7 @@ struct omap_udc {
 #endif
 
 #define ERR(stuff...)          pr_err("udc: " stuff)
-#define WARN(stuff...)         pr_warning("udc: " stuff)
+#define WARNING(stuff...)      pr_warning("udc: " stuff)
 #define INFO(stuff...)         pr_info("udc: " stuff)
 #define DBG(stuff...)          pr_debug("udc: " stuff)
 
index 49cd9e145a9bfbcdba12c76192f93ae3073b716d..e0090085b78ee74824ff2a3940a419a129e9570b 100644 (file)
@@ -179,7 +179,7 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
 
 #define ERROR(dev, fmt, args...) \
        xprintk(dev, KERN_ERR, fmt, ## args)
-#define WARN(dev, fmt, args...) \
+#define WARNING(dev, fmt, args...) \
        xprintk(dev, KERN_WARNING, fmt, ## args)
 #define INFO(dev, fmt, args...) \
        xprintk(dev, KERN_INFO, fmt, ## args)
index 8fb0066609bb4a9db0e22a045e70b14909cc809c..7e6725d8997663b81b719a87e48b974f120b00cb 100644 (file)
@@ -342,7 +342,7 @@ pxa25x_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
        struct pxa25x_request   *req;
 
        req = container_of (_req, struct pxa25x_request, req);
-       WARN_ON (!list_empty (&req->queue));
+       WARN_ON(!list_empty (&req->queue));
        kfree(req);
 }
 
@@ -1556,7 +1556,7 @@ config_change:
                                         * tell us about config change events,
                                         * so later ones may fail...
                                         */
-                                       WARN("config change %02x fail %d?\n",
+                                       WARNING("config change %02x fail %d?\n",
                                                u.r.bRequest, i);
                                        return;
                                        /* TODO experiment:  if has_cfr,
@@ -2330,7 +2330,7 @@ static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state)
        unsigned long flags;
 
        if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
-               WARN("USB host won't detect disconnect!\n");
+               WARNING("USB host won't detect disconnect!\n");
        udc->suspended = 1;
 
        local_irq_save(flags);
index 4d11ece7c95f0d5cf49c4343bb9002cd02a35115..c8a13215e02c6c5c7294839b33b7409b9aaeb228 100644 (file)
@@ -259,7 +259,7 @@ dump_state(struct pxa25x_udc *dev)
 #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
 
 #define ERR(stuff...)          pr_err("udc: " stuff)
-#define WARN(stuff...)         pr_warning("udc: " stuff)
+#define WARNING(stuff...)      pr_warning("udc: " stuff)
 #define INFO(stuff...)         pr_info("udc: " stuff)
 
 
index 5458f43a866856731cd932e8b98229040fe560ee..3791e6271903e7384a2a6773281d323c9de4b833 100644 (file)
@@ -116,7 +116,6 @@ static inline int qlen(struct usb_gadget *gadget)
 #undef DBG
 #undef VDBG
 #undef ERROR
-#undef WARN
 #undef INFO
 
 #define xprintk(d, level, fmt, args...) \
@@ -140,8 +139,6 @@ static inline int qlen(struct usb_gadget *gadget)
 
 #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)
 
index 31178e10cbbecca030561792a4ae97f457f877ed..ce1ca0ba0515c9a848d320dee18aaa29e5738808 100644 (file)
@@ -882,7 +882,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
        for (i = 0; i < 100 && !list_empty(&hep->urb_list); i++)
                msleep(3);
        if (!list_empty(&hep->urb_list))
-               WARN("ep %p not empty?\n", ep);
+               WARNING("ep %p not empty?\n", ep);
 
        kfree(ep);
        hep->hcpriv = NULL;
index 595b90a9984880c819011ad4e181a223d8d6d50b..aa211bafcff9dacc41457d10894f9eb6e8c82812 100644 (file)
@@ -338,7 +338,7 @@ struct isp116x_ep {
 #endif
 
 #define ERR(stuff...)          printk(KERN_ERR "116x: " stuff)
-#define WARN(stuff...)         printk(KERN_WARNING "116x: " stuff)
+#define WARNING(stuff...)      printk(KERN_WARNING "116x: " stuff)
 #define INFO(stuff...)         printk(KERN_INFO "116x: " stuff)
 
 /* ------------------------------------------------- */
index 340d72da554ad8e545defea9778874de2f0ff5bb..8a74bbb57d08bee72ec63fea25ad6e7aa96d0bff 100644 (file)
@@ -1026,7 +1026,7 @@ sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
        if (!list_empty(&hep->urb_list))
                msleep(3);
        if (!list_empty(&hep->urb_list))
-               WARN("ep %p not empty?\n", ep);
+               WARNING("ep %p not empty?\n", ep);
 
        kfree(ep);
        hep->hcpriv = NULL;
index 7690d98e42a7b8ce25d96f43b127dd7025a46ad3..b6b8c1f233dd8caa62caebf5b44c92a8480a9b37 100644 (file)
@@ -261,6 +261,6 @@ sl811_read_buf(struct sl811 *sl811, int addr, void *buf, size_t count)
 #endif
 
 #define ERR(stuff...)          printk(KERN_ERR "sl811: " stuff)
-#define WARN(stuff...)         printk(KERN_WARNING "sl811: " stuff)
+#define WARNING(stuff...)      printk(KERN_WARNING "sl811: " stuff)
 #define INFO(stuff...)         printk(KERN_INFO "sl811: " stuff)
 
index 054dedd2812718c1c1350acb058f983e1dda3331..b358c4e1cf212f114bbad89416f358c244311bc3 100644 (file)
@@ -81,7 +81,7 @@ static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test)
 
 #define ERROR(tdev, fmt, args...) \
        dev_err(&(tdev)->intf->dev , fmt , ## args)
-#define WARN(tdev, fmt, args...) \
+#define WARNING(tdev, fmt, args...) \
        dev_warn(&(tdev)->intf->dev , fmt , ## args)
 
 /*-------------------------------------------------------------------------*/
@@ -1946,7 +1946,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
 
                        status = get_endpoints (dev, intf);
                        if (status < 0) {
-                               WARN(dev, "couldn't get endpoints, %d\n",
+                               WARNING(dev, "couldn't get endpoints, %d\n",
                                                status);
                                return status;
                        }
index 5e3e4e9b6c77040c46cecefca82714ecbc4f4af1..1f715436d6d3dec14a96639aa6abde814c9818b4 100644 (file)
@@ -87,7 +87,7 @@ struct mon_reader_text {
 
 static struct dentry *mon_dir;         /* Usually /sys/kernel/debug/usbmon */
 
-static void mon_text_ctor(struct kmem_cache *, void *);
+static void mon_text_ctor(void *);
 
 struct mon_text_ptr {
        int cnt, limit;
@@ -720,7 +720,7 @@ void mon_text_del(struct mon_bus *mbus)
 /*
  * Slab interface: constructor.
  */
-static void mon_text_ctor(struct kmem_cache *slab, void *mem)
+static void mon_text_ctor(void *mem)
 {
        /*
         * Nothing to initialize. No, really!
index 832a5a4f3cb3ca9ab3394b9795b7685c8f80d7b1..cd9a2e138c8b35f3a3cacb4cd60525ed39d179b6 100644 (file)
@@ -651,15 +651,17 @@ static int ipaq_open(struct tty_struct *tty,
         */
 
        kfree(port->bulk_in_buffer);
+       kfree(port->bulk_out_buffer);
+       /* make sure the generic serial code knows */
+       port->bulk_out_buffer = NULL;
+
        port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
-       if (port->bulk_in_buffer == NULL) {
-               port->bulk_out_buffer = NULL; /* prevent double free */
+       if (port->bulk_in_buffer == NULL)
                goto enomem;
-       }
 
-       kfree(port->bulk_out_buffer);
        port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
        if (port->bulk_out_buffer == NULL) {
+               /* the buffer is useless, free it */
                kfree(port->bulk_in_buffer);
                port->bulk_in_buffer = NULL;
                goto enomem;
index 9b887ef64ff1c27c857602833211dd2b6b2d7716..70d135e0cc47c37d148eb97f7d97219cb33b1412 100644 (file)
@@ -1658,6 +1658,32 @@ config FB_PM3
          similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
          and maybe other boards.
 
+config FB_CARMINE
+       tristate "Fujitsu carmine frame buffer support"
+       depends on FB && PCI
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the frame buffer device driver for the Fujitsu Carmine chip.
+         The driver provides two independent frame buffer devices.
+
+choice
+       depends on FB_CARMINE
+       prompt "DRAM timing"
+       default FB_CARMINE_DRAM_EVAL
+
+config FB_CARMINE_DRAM_EVAL
+       bool "Eval board timings"
+       help
+         Use timings which work on the eval card.
+
+config CARMINE_DRAM_CUSTOM
+       bool "Custom board timings"
+       help
+         Use custom board timings.
+endchoice
+
 config FB_AU1100
        bool "Au1100 LCD Driver"
        depends on (FB = y) && MIPS && SOC_AU1100
@@ -1840,6 +1866,16 @@ config FB_W100
 
          If unsure, say N.
 
+config FB_SH_MOBILE_LCDC
+       tristate "SuperH Mobile LCDC framebuffer support"
+       depends on FB && SUPERH
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       default m
+       ---help---
+         Frame buffer driver for the on-chip SH-Mobile LCD controller.
+
 config FB_S3C2410
        tristate "S3C2410 LCD framebuffer support"
        depends on FB && ARCH_S3C2410
@@ -1951,6 +1987,23 @@ config FB_AM200EPD
          This enables support for the Metronome display controller used on
          the E-Ink AM-200 EPD devkit.
 
+config FB_COBALT
+       tristate "Cobalt server LCD frame buffer support"
+       depends on FB && MIPS_COBALT
+
+config FB_SH7760
+       bool "SH7760/SH7763 LCDC support"
+       depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763)
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         Support for the SH7760/SH7763 integrated (D)STN/TFT LCD Controller.
+         Supports display resolutions up to 1024x1024 pixel, grayscale and
+         color operation, with depths ranging from 1 bpp to 8 bpp monochrome
+         and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for
+         panels <= 320 pixel horizontal resolution.
+
 config FB_VIRTUAL
        tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
        depends on FB
index 04bca35403ff6d0333270e63d44a51d97a072f41..0ebc1bfd251491ad8f48fac32b0450bd50e28240 100644 (file)
@@ -106,17 +106,22 @@ obj-$(CONFIG_FB_PMAGB_B)    += pmagb-b-fb.o
 obj-$(CONFIG_FB_MAXINE)                  += maxinefb.o
 obj-$(CONFIG_FB_METRONOME)        += metronomefb.o
 obj-$(CONFIG_FB_S1D13XXX)        += s1d13xxxfb.o
+obj-$(CONFIG_FB_SH7760)                  += sh7760fb.o
 obj-$(CONFIG_FB_IMX)              += imxfb.o
 obj-$(CONFIG_FB_S3C2410)         += s3c2410fb.o
 obj-$(CONFIG_FB_FSL_DIU)         += fsl-diu-fb.o
+obj-$(CONFIG_FB_COBALT)           += cobalt_lcdfb.o
 obj-$(CONFIG_FB_PNX4008_DUM)     += pnx4008/
 obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
 obj-$(CONFIG_FB_IBM_GXT4500)     += gxt4500.o
 obj-$(CONFIG_FB_PS3)             += ps3fb.o
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
+obj-$(CONFIG_FB_SH_MOBILE_LCDC)          += sh_mobile_lcdcfb.o
+obj-$(CONFIG_FB_SH7343VOU)       += sh7343_voufb.o
 obj-$(CONFIG_FB_OMAP)             += omap/
 obj-$(CONFIG_XEN_FBDEV_FRONTEND)  += xen-fbfront.o
+obj-$(CONFIG_FB_CARMINE)          += carminefb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
index eedb8285e32fa389930152148d32224db3ac947a..017233d0c48131d67bc635eb6309cc84c27b245f 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/platform_device.h>
index 51e26c1f5e8b747310cc5b6e2aff47c5661336a9..32dd85126931479f16d79685721e4c2e038a4daf 100644 (file)
@@ -221,7 +221,7 @@ static int am200_setup_irq(struct fb_info *info)
                return retval;
        }
 
-       return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING);
+       return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQ_TYPE_EDGE_FALLING);
 }
 
 static void am200_set_rst(struct metronomefb_par *par, int state)
index 45c154ade9ca4901710716356f02abdcd336929c..b8e9a8682f2de98011502b762062285febbd6552 100644 (file)
@@ -1136,7 +1136,6 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg
         * Interface to the low level console driver
         */
 
-int amifb_init(void);
 static void amifb_deinit(void);
 
        /*
@@ -2048,13 +2047,16 @@ static void amifb_copyarea(struct fb_info *info,
        width = x2 - dx;
        height = y2 - dy;
 
+       if (area->sx + dx < area->dx || area->sy + dy < area->dy)
+               return;
+
        /* update sx,sy */
        sx = area->sx + (dx - area->dx);
        sy = area->sy + (dy - area->dy);
 
        /* the source must be completely inside the virtual screen */
-       if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
-           (sy + height) > info->var.yres_virtual)
+       if (sx + width > info->var.xres_virtual ||
+                       sy + height > info->var.yres_virtual)
                return;
 
        if (dy > sy || (dy == sy && dx > sx)) {
@@ -2245,7 +2247,7 @@ static inline void chipfree(void)
         * Initialisation
         */
 
-int __init amifb_init(void)
+static int __init amifb_init(void)
 {
        int tag, i, err = 0;
        u_long chipptr;
@@ -3790,16 +3792,14 @@ static void ami_rebuild_copper(void)
        }
 }
 
-
-module_init(amifb_init);
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-void cleanup_module(void)
+static void __exit amifb_exit(void)
 {
        unregister_framebuffer(&fb_info);
        amifb_deinit();
        amifb_video_off();
 }
-#endif /* MODULE */
+
+module_init(amifb_init);
+module_exit(amifb_exit);
+
+MODULE_LICENSE("GPL");
index fa55d356b5354202e8f6f8236c358593074e3077..77eb8b34fbfaee0e478ce39eef506dd605826212 100644 (file)
@@ -2593,13 +2593,16 @@ static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
        width = x2 - dx;
        height = y2 - dy;
 
+       if (area->sx + dx < area->dx || area->sy + dy < area->dy)
+               return;
+
        /* update sx,sy */
        sx = area->sx + (dx - area->dx);
        sy = area->sy + (dy - area->dy);
 
        /* the source must be completely inside the virtual screen */
-       if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
-           (sy + height) > info->var.yres_virtual)
+       if (sx + width > info->var.xres_virtual ||
+                       sy + height > info->var.yres_virtual)
                return;
 
        if (dy > sy || (dy == sy && dx > sx)) {
index b004036d40873aec5a5c8905a626722ab8b29533..5b3a15dffb5f536304eca7d1746b44c0e62c86ad 100644 (file)
@@ -256,6 +256,20 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
        return 0;
 }
 
+static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var,
+                                                    struct fb_info *info)
+{
+       struct fb_videomode varfbmode;
+       const struct fb_videomode *fbmode = NULL;
+
+       fb_var_to_videomode(&varfbmode, var);
+       fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist);
+       if (fbmode)
+               fb_videomode_to_var(var, fbmode);
+       return fbmode;
+}
+
+
 /**
  *      atmel_lcdfb_check_var - Validates a var passed in.
  *      @var: frame buffer variable screen structure
@@ -289,6 +303,15 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
        clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
 
        dev_dbg(dev, "%s:\n", __func__);
+
+       if (!(var->pixclock && var->bits_per_pixel)) {
+               /* choose a suitable mode if possible */
+               if (!atmel_lcdfb_choose_mode(var, info)) {
+                       dev_err(dev, "needed value not specified\n");
+                       return -EINVAL;
+               }
+       }
+
        dev_dbg(dev, "  resolution: %ux%u\n", var->xres, var->yres);
        dev_dbg(dev, "  pixclk:     %lu KHz\n", PICOS2KHZ(var->pixclock));
        dev_dbg(dev, "  bpp:        %u\n", var->bits_per_pixel);
@@ -299,6 +322,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
        }
 
+       /* Do not allow to have real resoulution larger than virtual */
+       if (var->xres > var->xres_virtual)
+               var->xres_virtual = var->xres;
+
+       if (var->yres > var->yres_virtual)
+               var->yres_virtual = var->yres;
+
        /* Force same alignment for each line */
        var->xres = (var->xres + 3) & ~3UL;
        var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
@@ -379,6 +409,35 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
        return 0;
 }
 
+/*
+ * LCD reset sequence
+ */
+static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
+{
+       might_sleep();
+
+       /* LCD power off */
+       lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+
+       /* wait for the LCDC core to become idle */
+       while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
+               msleep(10);
+
+       /* DMA disable */
+       lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+
+       /* wait for DMA engine to become idle */
+       while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
+               msleep(10);
+
+       /* LCD power on */
+       lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+               (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
+
+       /* DMA enable */
+       lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+}
+
 /**
  *      atmel_lcdfb_set_par - Alters the hardware state.
  *      @info: frame buffer structure that represents a single frame buffer
@@ -401,6 +460,8 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
        unsigned long clk_value_khz;
        unsigned long bits_per_line;
 
+       might_sleep();
+
        dev_dbg(info->device, "%s:\n", __func__);
        dev_dbg(info->device, "  * resolution: %ux%u (%ux%u virtual)\n",
                 info->var.xres, info->var.yres,
@@ -511,6 +572,8 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
 
        /* Disable all interrupts */
        lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
+       /* Enable FIFO & DMA errors */
+       lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
 
        /* ...wait for DMA engine to become idle... */
        while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
@@ -645,10 +708,26 @@ static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
        u32 status;
 
        status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
-       lcdc_writel(sinfo, ATMEL_LCDC_IDR, status);
+       if (status & ATMEL_LCDC_UFLWI) {
+               dev_warn(info->device, "FIFO underflow %#x\n", status);
+               /* reset DMA and FIFO to avoid screen shifting */
+               schedule_work(&sinfo->task);
+       }
+       lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
        return IRQ_HANDLED;
 }
 
+/*
+ * LCD controller task (to reset the LCD)
+ */
+static void atmel_lcdfb_task(struct work_struct *work)
+{
+       struct atmel_lcdfb_info *sinfo =
+               container_of(work, struct atmel_lcdfb_info, task);
+
+       atmel_lcdfb_reset(sinfo);
+}
+
 static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
 {
        struct fb_info *info = sinfo->info;
@@ -691,6 +770,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
        struct fb_info *info;
        struct atmel_lcdfb_info *sinfo;
        struct atmel_lcdfb_info *pdata_sinfo;
+       struct fb_videomode fbmode;
        struct resource *regs = NULL;
        struct resource *map = NULL;
        int ret;
@@ -824,6 +904,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
                goto unmap_mmio;
        }
 
+       /* Some operations on the LCDC might sleep and
+        * require a preemptible task context */
+       INIT_WORK(&sinfo->task, atmel_lcdfb_task);
+
        ret = atmel_lcdfb_init_fbinfo(sinfo);
        if (ret < 0) {
                dev_err(dev, "init fbinfo failed: %d\n", ret);
@@ -853,6 +937,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
                goto free_cmap;
        }
 
+       /* add selected videomode to modelist */
+       fb_var_to_videomode(&fbmode, &info->var);
+       fb_add_videomode(&fbmode, &info->modelist);
+
        /* Power up the LCDC screen */
        if (sinfo->atmel_lcdfb_power_control)
                sinfo->atmel_lcdfb_power_control(1);
@@ -866,6 +954,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 free_cmap:
        fb_dealloc_cmap(&info->cmap);
 unregister_irqs:
+       cancel_work_sync(&sinfo->task);
        free_irq(sinfo->irq_base, info);
 unmap_mmio:
        exit_backlight(sinfo);
@@ -903,6 +992,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
        if (!sinfo)
                return 0;
 
+       cancel_work_sync(&sinfo->task);
        exit_backlight(sinfo);
        if (sinfo->atmel_lcdfb_power_control)
                sinfo->atmel_lcdfb_power_control(0);
index 07b6addbb3c1a2631990db635e238703a891a82c..243ea4ab20c8b78e6a61bf5d1a949fdcf37013b8 100644 (file)
@@ -1339,10 +1339,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
        if (vclk * 12 < c.ppll_min)
                vclk = c.ppll_min/12;
 
-       pll->post_divider = -1;
-
        /* now, find an acceptable divider */
-       for (i = 0; i < sizeof(post_dividers); i++) {
+       for (i = 0; i < ARRAY_SIZE(post_dividers); i++) {
                output_freq = post_dividers[i] * vclk;
                if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) {
                        pll->post_divider = post_dividers[i];
@@ -1350,7 +1348,7 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
                }
        }
 
-       if (pll->post_divider < 0)
+       if (i == ARRAY_SIZE(post_dividers))
                return -EINVAL;
 
        /* calculate feedback divider */
index bd4ac0bafecbc486bfa232e712d56ede43a0c0c7..620ba8120368524c18ff7c71fc28f085bac6108b 100644 (file)
@@ -424,7 +424,6 @@ static struct {
 #endif /* CONFIG_FB_ATY_CT */
 };
 
-/* can not fail */
 static int __devinit correct_chipset(struct atyfb_par *par)
 {
        u8 rev;
@@ -437,6 +436,9 @@ static int __devinit correct_chipset(struct atyfb_par *par)
                if (par->pci_id == aty_chips[i].pci_id)
                        break;
 
+       if (i < 0)
+               return -ENODEV;
+
        name = aty_chips[i].name;
        par->pll_limits.pll_max = aty_chips[i].pll;
        par->pll_limits.mclk = aty_chips[i].mclk;
@@ -2229,6 +2231,7 @@ static int __devinit aty_init(struct fb_info *info)
        const char *ramname = NULL, *xtal;
        int gtb_memsize, has_var = 0;
        struct fb_var_screeninfo var;
+       int ret;
 
        init_waitqueue_head(&par->vblank.wait);
        spin_lock_init(&par->int_lock);
@@ -2610,7 +2613,8 @@ static int __devinit aty_init(struct fb_info *info)
                        var.yres_virtual = var.yres;
        }
 
-       if (atyfb_check_var(&var, info)) {
+       ret = atyfb_check_var(&var, info);
+       if (ret) {
                PRINTKE("can't set default video mode\n");
                goto aty_init_exit;
        }
@@ -2621,10 +2625,12 @@ static int __devinit aty_init(struct fb_info *info)
 #endif /* CONFIG_FB_ATY_CT */
        info->var = var;
 
-       if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (ret < 0)
                goto aty_init_exit;
 
-       if (register_framebuffer(info) < 0) {
+       ret = register_framebuffer(info);
+       if (ret < 0) {
                fb_dealloc_cmap(&info->cmap);
                goto aty_init_exit;
        }
@@ -2650,7 +2656,7 @@ aty_init_exit:
            par->mtrr_aper = -1;
        }
 #endif
-       return -1;
+       return ret;
 }
 
 static void aty_resume_chip(struct fb_info *info)
@@ -2709,8 +2715,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
        if (par->lock_blank || par->asleep)
                return 0;
 
-#ifdef CONFIG_FB_ATY_BACKLIGHT
-#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
        if (par->lcd_table && blank > FB_BLANK_NORMAL &&
            (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
                u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -2739,8 +2744,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
        }
        aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
 
-#ifdef CONFIG_FB_ATY_BACKLIGHT
-#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
        if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
            (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
                u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -3331,7 +3335,7 @@ static int __devinit init_from_bios(struct atyfb_par *par)
                PRINTKE("no BIOS frequency table found, use parameters\n");
                ret = -ENXIO;
        }
-       iounmap((void* __iomem )bios_base);
+       iounmap((void __iomem *)bios_base);
 
        return ret;
 }
@@ -3418,14 +3422,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
        struct fb_info *info;
        struct resource *rp;
        struct atyfb_par *par;
-       int i, rc = -ENOMEM;
-
-       for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
-               if (pdev->device == aty_chips[i].pci_id)
-                       break;
-
-       if (i < 0)
-               return -ENODEV;
+       int rc = -ENOMEM;
 
        /* Enable device in PCI config */
        if (pci_enable_device(pdev)) {
@@ -3456,7 +3453,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
        par = info->par;
        info->fix = atyfb_fix;
        info->device = &pdev->dev;
-       par->pci_id = aty_chips[i].pci_id;
+       par->pci_id = pdev->device;
        par->res_start = res_start;
        par->res_size = res_size;
        par->irq = pdev->irq;
@@ -3474,7 +3471,8 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
        pci_set_drvdata(pdev, info);
 
        /* Init chip & register framebuffer */
-       if (aty_init(info))
+       rc = aty_init(info);
+       if (rc)
                goto err_release_io;
 
 #ifdef __sparc__
@@ -3655,18 +3653,62 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
        atyfb_remove(info);
 }
 
-/*
- * This driver uses its own matching table. That will be more difficult
- * to fix, so for now, we just match against any ATI ID and let the
- * probe() function find out what's up. That also mean we don't have
- * a module ID table though.
- */
 static struct pci_device_id atyfb_pci_tbl[] = {
-       { PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-         PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 },
-       { 0, }
+#ifdef CONFIG_FB_ATY_GX
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GX) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CX) },
+#endif /* CONFIG_FB_ATY_GX */
+
+#ifdef CONFIG_FB_ATY_CT
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CT) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64ET) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LT) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VT) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GT) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VU) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GU) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LG) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VV) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GV) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GW) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GY) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GZ) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GB) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GD) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GI) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GP) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GQ) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LB) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LD) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LI) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LP) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LQ) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GM) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GN) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GO) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GL) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GR) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GS) },
+
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LM) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LN) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LR) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LS) },
+#endif /* CONFIG_FB_ATY_CT */
+       { }
 };
 
+MODULE_DEVICE_TABLE(pci, atyfb_pci_tbl);
+
 static struct pci_driver atyfb_driver = {
        .name           = "atyfb",
        .id_table       = atyfb_pci_tbl,
index 400e9264e4564877cc481d8e57c7a83f69ba6a63..652273e9f5f9223fc80261d035c114765ea59f71 100644 (file)
@@ -2098,15 +2098,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
 
 static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid)
 {
-       if (off > EDID_LENGTH)
-               return 0;
-
-       if (off + count > EDID_LENGTH)
-               count = EDID_LENGTH - off;
-
-       memcpy(buf, edid + off, count);
-
-       return count;
+       return memory_read_from_buffer(buf, count, &off, edid, EDID_LENGTH);
 }
 
 
@@ -2161,6 +2153,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
        struct radeonfb_info *rinfo;
        int ret;
        unsigned char c1, c2;
+       int err = 0;
 
        pr_debug("radeonfb_pci_register BEGIN\n");
        
@@ -2340,9 +2333,14 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
 
        /* Register some sysfs stuff (should be done better) */
        if (rinfo->mon1_EDID)
-               sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
+               err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
+                                               &edid1_attr);
        if (rinfo->mon2_EDID)
-               sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+               err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
+                                               &edid2_attr);
+       if (err)
+               pr_warning("%s() Creating sysfs files failed, continuing\n",
+                          __func__);
 
        /* save current mode regs before we switch into the new one
         * so we can restore this upon __exit
index 30bf7f2f163599b8c3a5aa1d5c2d0cce1ef20193..452b770d8cc9a51f8c32261eb4247f14e515ab48 100644 (file)
@@ -36,6 +36,30 @@ config LCD_LTV350QV
 
          The LTV350QV panel is present on all ATSTK1000 boards.
 
+config LCD_ILI9320
+       tristate
+       depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT
+       default n
+       help
+         If you have a panel based on the ILI9320 controller chip
+         then say y to include a power driver for it.
+
+config LCD_VGG2432A4
+       tristate "VGG2432A4 LCM device support"
+       depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER
+       select LCD_ILI9320
+       default n
+       help
+         If you have a VGG2432A4 panel based on the ILI9320 controller chip
+         then say y to include a power driver for it.
+
+config LCD_PLATFORM
+       tristate "Platform LCD controls"
+       depends on LCD_CLASS_DEVICE
+       help
+         This driver provides a platform-device registered LCD power
+         control interface.
+
 #
 # Backlight
 #
@@ -63,6 +87,18 @@ config BACKLIGHT_ATMEL_LCDC
          If in doubt, it's safe to enable this option; it doesn't kick
          in unless the board's description says it's wired that way.
 
+config BACKLIGHT_ATMEL_PWM
+       tristate "Atmel PWM backlight control"
+       depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM
+       default n
+       help
+         Say Y here if you want to use the PWM peripheral in Atmel AT91 and
+         AVR32 devices. This driver will need additional platform data to know
+         which PWM instance to use and how to configure it.
+
+         To compile this driver as a module, choose M here: the module will be
+         called atmel-pwm-bl.
+
 config BACKLIGHT_CORGI
        tristate "Generic (aka Sharp Corgi) Backlight Driver"
        depends on BACKLIGHT_CLASS_DEVICE
@@ -119,3 +155,12 @@ config BACKLIGHT_PWM
        help
          If you have a LCD backlight adjustable by PWM, say Y to enable
          this driver.
+
+config BACKLIGHT_MBP_NVIDIA
+       tristate "MacBook Pro Nvidia Backlight Driver"
+       depends on BACKLIGHT_CLASS_DEVICE && X86
+       default n
+       help
+         If you have an Apple Macbook Pro with Nvidia graphics hardware say Y
+        to enable a driver for its backlight
+
index b51a7cd12500f382445dc3f7e2b1891ba9c676b8..b405aace803fe829a1e82192215926b3a1733753 100644 (file)
@@ -1,9 +1,13 @@
 # Backlight & LCD drivers
 
 obj-$(CONFIG_LCD_CLASS_DEVICE)     += lcd.o
-obj-$(CONFIG_LCD_LTV350QV)     += ltv350qv.o
+obj-$(CONFIG_LCD_LTV350QV)        += ltv350qv.o
+obj-$(CONFIG_LCD_ILI9320)         += ili9320.o
+obj-$(CONFIG_LCD_PLATFORM)        += platform_lcd.o
+obj-$(CONFIG_LCD_VGG2432A4)       += vgg2432a4.o
 
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
+obj-$(CONFIG_BACKLIGHT_ATMEL_PWM)    += atmel-pwm-bl.o
 obj-$(CONFIG_BACKLIGHT_CORGI)  += corgi_bl.o
 obj-$(CONFIG_BACKLIGHT_HP680)  += hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
@@ -11,3 +15,5 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
 obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
 obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_PWM)    += pwm_bl.o
+obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
+
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
new file mode 100644 (file)
index 0000000..505c082
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2008 Atmel Corporation
+ *
+ * Backlight driver using Atmel PWM peripheral.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/backlight.h>
+#include <linux/atmel_pwm.h>
+#include <linux/atmel-pwm-bl.h>
+
+struct atmel_pwm_bl {
+       const struct atmel_pwm_bl_platform_data *pdata;
+       struct backlight_device                 *bldev;
+       struct platform_device                  *pdev;
+       struct pwm_channel                      pwmc;
+       int                                     gpio_on;
+};
+
+static int atmel_pwm_bl_set_intensity(struct backlight_device *bd)
+{
+       struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
+       int intensity = bd->props.brightness;
+       int pwm_duty;
+
+       if (bd->props.power != FB_BLANK_UNBLANK)
+               intensity = 0;
+       if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+               intensity = 0;
+
+       if (pwmbl->pdata->pwm_active_low)
+               pwm_duty = pwmbl->pdata->pwm_duty_min + intensity;
+       else
+               pwm_duty = pwmbl->pdata->pwm_duty_max - intensity;
+
+       if (pwm_duty > pwmbl->pdata->pwm_duty_max)
+               pwm_duty = pwmbl->pdata->pwm_duty_max;
+       if (pwm_duty < pwmbl->pdata->pwm_duty_min)
+               pwm_duty = pwmbl->pdata->pwm_duty_min;
+
+       if (!intensity) {
+               if (pwmbl->gpio_on != -1) {
+                       gpio_set_value(pwmbl->gpio_on,
+                                       0 ^ pwmbl->pdata->on_active_low);
+               }
+               pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
+               pwm_channel_disable(&pwmbl->pwmc);
+       } else {
+               pwm_channel_enable(&pwmbl->pwmc);
+               pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
+               if (pwmbl->gpio_on != -1) {
+                       gpio_set_value(pwmbl->gpio_on,
+                                       1 ^ pwmbl->pdata->on_active_low);
+               }
+       }
+
+       return 0;
+}
+
+static int atmel_pwm_bl_get_intensity(struct backlight_device *bd)
+{
+       struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
+       u8 intensity;
+
+       if (pwmbl->pdata->pwm_active_low) {
+               intensity = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY) -
+                       pwmbl->pdata->pwm_duty_min;
+       } else {
+               intensity = pwmbl->pdata->pwm_duty_max -
+                       pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY);
+       }
+
+       return intensity;
+}
+
+static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
+{
+       unsigned long pwm_rate = pwmbl->pwmc.mck;
+       unsigned long prescale = DIV_ROUND_UP(pwm_rate,
+                       (pwmbl->pdata->pwm_frequency *
+                        pwmbl->pdata->pwm_compare_max)) - 1;
+
+       /*
+        * Prescale must be power of two and maximum 0xf in size because of
+        * hardware limit. PWM speed will be:
+        *      PWM module clock speed / (2 ^ prescale).
+        */
+       prescale = fls(prescale);
+       if (prescale > 0xf)
+               prescale = 0xf;
+
+       pwm_channel_writel(&pwmbl->pwmc, PWM_CMR, prescale);
+       pwm_channel_writel(&pwmbl->pwmc, PWM_CDTY,
+                       pwmbl->pdata->pwm_duty_min +
+                       pwmbl->bldev->props.brightness);
+       pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD,
+                       pwmbl->pdata->pwm_compare_max);
+
+       dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver "
+                       "(%lu Hz)\n", pwmbl->pwmc.mck /
+                       pwmbl->pdata->pwm_compare_max /
+                       (1 << prescale));
+
+       return pwm_channel_enable(&pwmbl->pwmc);
+}
+
+static struct backlight_ops atmel_pwm_bl_ops = {
+       .get_brightness = atmel_pwm_bl_get_intensity,
+       .update_status  = atmel_pwm_bl_set_intensity,
+};
+
+static int atmel_pwm_bl_probe(struct platform_device *pdev)
+{
+       const struct atmel_pwm_bl_platform_data *pdata;
+       struct backlight_device *bldev;
+       struct atmel_pwm_bl *pwmbl;
+       int retval;
+
+       pwmbl = kzalloc(sizeof(struct atmel_pwm_bl), GFP_KERNEL);
+       if (!pwmbl)
+               return -ENOMEM;
+
+       pwmbl->pdev = pdev;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               retval = -ENODEV;
+               goto err_free_mem;
+       }
+
+       if (pdata->pwm_compare_max < pdata->pwm_duty_max ||
+                       pdata->pwm_duty_min > pdata->pwm_duty_max ||
+                       pdata->pwm_frequency == 0) {
+               retval = -EINVAL;
+               goto err_free_mem;
+       }
+
+       pwmbl->pdata = pdata;
+       pwmbl->gpio_on = pdata->gpio_on;
+
+       retval = pwm_channel_alloc(pdata->pwm_channel, &pwmbl->pwmc);
+       if (retval)
+               goto err_free_mem;
+
+       if (pwmbl->gpio_on != -1) {
+               retval = gpio_request(pwmbl->gpio_on, "gpio_atmel_pwm_bl");
+               if (retval) {
+                       pwmbl->gpio_on = -1;
+                       goto err_free_pwm;
+               }
+
+               /* Turn display off by defatult. */
+               retval = gpio_direction_output(pwmbl->gpio_on,
+                               0 ^ pdata->on_active_low);
+               if (retval)
+                       goto err_free_gpio;
+       }
+
+       bldev = backlight_device_register("atmel-pwm-bl",
+                       &pdev->dev, pwmbl, &atmel_pwm_bl_ops);
+       if (IS_ERR(bldev)) {
+               retval = PTR_ERR(bldev);
+               goto err_free_gpio;
+       }
+
+       pwmbl->bldev = bldev;
+
+       platform_set_drvdata(pdev, pwmbl);
+
+       /* Power up the backlight by default at middle intesity. */
+       bldev->props.power = FB_BLANK_UNBLANK;
+       bldev->props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
+       bldev->props.brightness = bldev->props.max_brightness / 2;
+
+       retval = atmel_pwm_bl_init_pwm(pwmbl);
+       if (retval)
+               goto err_free_bl_dev;
+
+       atmel_pwm_bl_set_intensity(bldev);
+
+       return 0;
+
+err_free_bl_dev:
+       platform_set_drvdata(pdev, NULL);
+       backlight_device_unregister(bldev);
+err_free_gpio:
+       if (pwmbl->gpio_on != -1)
+               gpio_free(pwmbl->gpio_on);
+err_free_pwm:
+       pwm_channel_free(&pwmbl->pwmc);
+err_free_mem:
+       kfree(pwmbl);
+       return retval;
+}
+
+static int __exit atmel_pwm_bl_remove(struct platform_device *pdev)
+{
+       struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev);
+
+       if (pwmbl->gpio_on != -1) {
+               gpio_set_value(pwmbl->gpio_on, 0);
+               gpio_free(pwmbl->gpio_on);
+       }
+       pwm_channel_disable(&pwmbl->pwmc);
+       pwm_channel_free(&pwmbl->pwmc);
+       backlight_device_unregister(pwmbl->bldev);
+       platform_set_drvdata(pdev, NULL);
+       kfree(pwmbl);
+
+       return 0;
+}
+
+static struct platform_driver atmel_pwm_bl_driver = {
+       .driver = {
+               .name = "atmel-pwm-bl",
+       },
+       /* REVISIT add suspend() and resume() */
+       .remove = __exit_p(atmel_pwm_bl_remove),
+};
+
+static int __init atmel_pwm_bl_init(void)
+{
+       return platform_driver_probe(&atmel_pwm_bl_driver, atmel_pwm_bl_probe);
+}
+module_init(atmel_pwm_bl_init);
+
+static void __exit atmel_pwm_bl_exit(void)
+{
+       platform_driver_unregister(&atmel_pwm_bl_driver);
+}
+module_exit(atmel_pwm_bl_exit);
+
+MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_DESCRIPTION("Atmel PWM backlight driver");
+MODULE_LICENSE("GPL");
index 39394757679c0882f9a2765486163383bee0935c..fab0bc874b58d46992b64b90d47be82677b2f543 100644 (file)
@@ -191,6 +191,7 @@ static struct device_attribute bl_device_attributes[] = {
  *   backlight_device class.
  * @name: the name of the new object(must be the same as the name of the
  *   respective framebuffer device).
+ * @parent: a pointer to the parent device
  * @devdata: an optional pointer to be stored for private driver use. The
  *   methods may retrieve it by using bl_get_data(bd).
  * @ops: the backlight operations structure.
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
new file mode 100644 (file)
index 0000000..ba89b41
--- /dev/null
@@ -0,0 +1,330 @@
+/* drivers/video/backlight/ili9320.c
+ *
+ * ILI9320 LCD controller driver core.
+ *
+ * Copyright 2007 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+
+#include <linux/spi/spi.h>
+
+#include <video/ili9320.h>
+
+#include "ili9320.h"
+
+
+static inline int ili9320_write_spi(struct ili9320 *ili,
+                                   unsigned int reg,
+                                   unsigned int value)
+{
+       struct ili9320_spi *spi = &ili->access.spi;
+       unsigned char *addr = spi->buffer_addr;
+       unsigned char *data = spi->buffer_data;
+
+       /* spi message consits of:
+        * first byte: ID and operation
+        */
+
+       addr[0] = spi->id | ILI9320_SPI_INDEX | ILI9320_SPI_WRITE;
+       addr[1] = reg >> 8;
+       addr[2] = reg;
+
+       /* second message is the data to transfer */
+
+       data[0] = spi->id | ILI9320_SPI_DATA  | ILI9320_SPI_WRITE;
+       data[1] = value >> 8;
+       data[2] = value;
+
+       return spi_sync(spi->dev, &spi->message);
+}
+
+int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value)
+{
+       dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value);
+       return ili->write(ili, reg, value);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_write);
+
+int ili9320_write_regs(struct ili9320 *ili,
+                      struct ili9320_reg *values,
+                      int nr_values)
+{
+       int index;
+       int ret;
+
+       for (index = 0; index < nr_values; index++, values++) {
+               ret = ili9320_write(ili, values->address, values->value);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_write_regs);
+
+static void ili9320_reset(struct ili9320 *lcd)
+{
+       struct ili9320_platdata *cfg = lcd->platdata;
+
+       cfg->reset(1);
+       mdelay(50);
+
+       cfg->reset(0);
+       mdelay(50);
+
+       cfg->reset(1);
+       mdelay(100);
+}
+
+static inline int ili9320_init_chip(struct ili9320 *lcd)
+{
+       int ret;
+
+       ili9320_reset(lcd);
+
+       ret = lcd->client->init(lcd, lcd->platdata);
+       if (ret != 0) {
+               dev_err(lcd->dev, "failed to initialise display\n");
+               return ret;
+       }
+
+       lcd->initialised = 1;
+       return 0;
+}
+
+static inline int ili9320_power_on(struct ili9320 *lcd)
+{
+       if (!lcd->initialised)
+               ili9320_init_chip(lcd);
+
+       lcd->display1 |= (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
+       ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+       return 0;
+}
+
+static inline int ili9320_power_off(struct ili9320 *lcd)
+{
+       lcd->display1 &= ~(ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
+       ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+       return 0;
+}
+
+#define POWER_IS_ON(pwr)       ((pwr) <= FB_BLANK_NORMAL)
+
+static int ili9320_power(struct ili9320 *lcd, int power)
+{
+       int ret = 0;
+
+       dev_dbg(lcd->dev, "power %d => %d\n", lcd->power, power);
+
+       if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
+               ret = ili9320_power_on(lcd);
+       else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
+               ret = ili9320_power_off(lcd);
+
+       if (ret == 0)
+               lcd->power = power;
+       else
+               dev_warn(lcd->dev, "failed to set power mode %d\n", power);
+
+       return ret;
+}
+
+static inline struct ili9320 *to_our_lcd(struct lcd_device *lcd)
+{
+       return lcd_get_data(lcd);
+}
+
+static int ili9320_set_power(struct lcd_device *ld, int power)
+{
+       struct ili9320 *lcd = to_our_lcd(ld);
+
+       return ili9320_power(lcd, power);
+}
+
+static int ili9320_get_power(struct lcd_device *ld)
+{
+       struct ili9320 *lcd = to_our_lcd(ld);
+
+       return lcd->power;
+}
+
+static struct lcd_ops ili9320_ops = {
+       .get_power      = ili9320_get_power,
+       .set_power      = ili9320_set_power,
+};
+
+static void __devinit ili9320_setup_spi(struct ili9320 *ili,
+                                       struct spi_device *dev)
+{
+       struct ili9320_spi *spi = &ili->access.spi;
+
+       ili->write = ili9320_write_spi;
+       spi->dev = dev;
+
+       /* fill the two messages we are going to use to send the data
+        * with, the first the address followed by the data. The datasheet
+        * says they should be done as two distinct cycles of the SPI CS line.
+        */
+
+       spi->xfer[0].tx_buf = spi->buffer_addr;
+       spi->xfer[1].tx_buf = spi->buffer_data;
+       spi->xfer[0].len = 3;
+       spi->xfer[1].len = 3;
+       spi->xfer[0].bits_per_word = 8;
+       spi->xfer[1].bits_per_word = 8;
+       spi->xfer[0].cs_change = 1;
+
+       spi_message_init(&spi->message);
+       spi_message_add_tail(&spi->xfer[0], &spi->message);
+       spi_message_add_tail(&spi->xfer[1], &spi->message);
+}
+
+int __devinit ili9320_probe_spi(struct spi_device *spi,
+                               struct ili9320_client *client)
+{
+       struct ili9320_platdata *cfg = spi->dev.platform_data;
+       struct device *dev = &spi->dev;
+       struct ili9320 *ili;
+       struct lcd_device *lcd;
+       int ret = 0;
+
+       /* verify we where given some information */
+
+       if (cfg == NULL) {
+               dev_err(dev, "no platform data supplied\n");
+               return -EINVAL;
+       }
+
+       if (cfg->hsize <= 0 || cfg->vsize <= 0 || cfg->reset == NULL) {
+               dev_err(dev, "invalid platform data supplied\n");
+               return -EINVAL;
+       }
+
+       /* allocate and initialse our state */
+
+       ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL);
+       if (ili == NULL) {
+               dev_err(dev, "no memory for device\n");
+               return -ENOMEM;
+       }
+
+       ili->access.spi.id = ILI9320_SPI_IDCODE | ILI9320_SPI_ID(1);
+
+       ili->dev = dev;
+       ili->client = client;
+       ili->power = FB_BLANK_POWERDOWN;
+       ili->platdata = cfg;
+
+       dev_set_drvdata(&spi->dev, ili);
+
+       ili9320_setup_spi(ili, spi);
+
+       lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
+       if (IS_ERR(lcd)) {
+               dev_err(dev, "failed to register lcd device\n");
+               ret = PTR_ERR(lcd);
+               goto err_free;
+       }
+
+       ili->lcd = lcd;
+
+       dev_info(dev, "initialising %s\n", client->name);
+
+       ret = ili9320_power(ili, FB_BLANK_UNBLANK);
+       if (ret != 0) {
+               dev_err(dev, "failed to set lcd power state\n");
+               goto err_unregister;
+       }
+
+       return 0;
+
+ err_unregister:
+       lcd_device_unregister(lcd);
+
+ err_free:
+       kfree(ili);
+
+       return ret;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_probe_spi);
+
+int __devexit ili9320_remove(struct ili9320 *ili)
+{
+       ili9320_power(ili, FB_BLANK_POWERDOWN);
+
+       lcd_device_unregister(ili->lcd);
+       kfree(ili);
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_remove);
+
+#ifdef CONFIG_PM
+int ili9320_suspend(struct ili9320 *lcd, pm_message_t state)
+{
+       int ret;
+
+       dev_dbg(lcd->dev, "%s: event %d\n", __func__, state.event);
+
+       if (state.event == PM_EVENT_SUSPEND) {
+               ret = ili9320_power(lcd, FB_BLANK_POWERDOWN);
+
+               if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+                       ili9320_write(lcd, ILI9320_POWER1, lcd->power1 |
+                                     ILI9320_POWER1_SLP |
+                                     ILI9320_POWER1_DSTB);
+                       lcd->initialised = 0;
+               }
+
+               return ret;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_suspend);
+
+int ili9320_resume(struct ili9320 *lcd)
+{
+       dev_info(lcd->dev, "resuming from power state %d\n", lcd->power);
+
+       if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+               ili9320_write(lcd, ILI9320_POWER1, 0x00);
+       }
+
+       return ili9320_power(lcd, FB_BLANK_UNBLANK);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_resume);
+#endif
+
+/* Power down all displays on reboot, poweroff or halt */
+void ili9320_shutdown(struct ili9320 *lcd)
+{
+       ili9320_power(lcd, FB_BLANK_POWERDOWN);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_shutdown);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("ILI9320 LCD Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h
new file mode 100644 (file)
index 0000000..e388eca
--- /dev/null
@@ -0,0 +1,80 @@
+/* drivers/video/backlight/ili9320.h
+ *
+ * ILI9320 LCD controller driver core.
+ *
+ * Copyright 2007 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.
+*/
+
+/* Holder for register and value pairs. */
+struct ili9320_reg {
+       unsigned short          address;
+       unsigned short          value;
+};
+
+struct ili9320;
+
+struct ili9320_client {
+       const char      *name;
+       int     (*init)(struct ili9320 *ili, struct ili9320_platdata *cfg);
+
+};
+/* Device attached via an SPI bus. */
+struct  ili9320_spi {
+       struct spi_device       *dev;
+       struct spi_message      message;
+       struct spi_transfer     xfer[2];
+
+       unsigned char           id;
+       unsigned char           buffer_addr[4];
+       unsigned char           buffer_data[4];
+};
+
+/* ILI9320 device state. */
+struct ili9320 {
+       union {
+               struct ili9320_spi      spi;    /* SPI attachged device. */
+       } access;                               /* Register access method. */
+
+       struct device                   *dev;
+       struct lcd_device               *lcd;   /* LCD device we created. */
+       struct ili9320_client           *client;
+       struct ili9320_platdata         *platdata;
+
+       int                              power; /* current power state. */
+       int                              initialised;
+
+       unsigned short                   display1;
+       unsigned short                   power1;
+
+       int (*write)(struct ili9320 *ili, unsigned int reg, unsigned int val);
+};
+
+
+/* ILI9320 register access routines */
+
+extern int ili9320_write(struct ili9320 *ili,
+                        unsigned int reg, unsigned int value);
+
+extern int ili9320_write_regs(struct ili9320 *ili,
+                             struct ili9320_reg *values,
+                             int nr_values);
+
+/* Device probe */
+
+extern int ili9320_probe_spi(struct spi_device *spi,
+                            struct ili9320_client *cli);
+
+extern int ili9320_remove(struct ili9320 *lcd);
+extern void ili9320_shutdown(struct ili9320 *lcd);
+
+/* PM */
+
+extern int ili9320_suspend(struct ili9320 *lcd, pm_message_t state);
+extern int ili9320_resume(struct ili9320 *lcd);
index 299fd318dd45828a4466d982069b69f221b27b5a..b15b2b84a6f7c951e809391f1cae019a4584af1e 100644 (file)
@@ -33,7 +33,7 @@ static int fb_notifier_callback(struct notifier_block *self,
        ld = container_of(self, struct lcd_device, fb_notif);
        mutex_lock(&ld->ops_lock);
        if (ld->ops)
-               if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info))
+               if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info))
                        ld->ops->set_power(ld, *(int *)evdata->data);
        mutex_unlock(&ld->ops_lock);
        return 0;
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
new file mode 100644 (file)
index 0000000..385cba4
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  Backlight Driver for Nvidia 8600 in Macbook Pro
+ *
+ *  Copyright (c) Red Hat <mjg@redhat.com>
+ *  Based on code from Pommed:
+ *  Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch>
+ *  Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org>
+ *  Copyright (C) 2007 Julien BLACHE <jb@jblache.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This driver triggers SMIs which cause the firmware to change the
+ *  backlight brightness. This is icky in many ways, but it's impractical to
+ *  get at the firmware code in order to figure out what it's actually doing.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/dmi.h>
+#include <linux/io.h>
+
+static struct backlight_device *mbp_backlight_device;
+
+static struct dmi_system_id __initdata mbp_device_table[] = {
+       {
+               .ident = "3,1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
+               },
+       },
+       {
+               .ident = "3,2",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
+               },
+       },
+       {
+               .ident = "4,1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
+               },
+       },
+       { }
+};
+
+static int mbp_send_intensity(struct backlight_device *bd)
+{
+       int intensity = bd->props.brightness;
+
+       outb(0x04 | (intensity << 4), 0xb3);
+       outb(0xbf, 0xb2);
+
+       return 0;
+}
+
+static int mbp_get_intensity(struct backlight_device *bd)
+{
+       outb(0x03, 0xb3);
+       outb(0xbf, 0xb2);
+       return inb(0xb3) >> 4;
+}
+
+static struct backlight_ops mbp_ops = {
+       .get_brightness = mbp_get_intensity,
+       .update_status  = mbp_send_intensity,
+};
+
+static int __init mbp_init(void)
+{
+       if (!dmi_check_system(mbp_device_table))
+               return -ENODEV;
+
+       if (!request_region(0xb2, 2, "Macbook Pro backlight"))
+               return -ENXIO;
+
+       mbp_backlight_device = backlight_device_register("mbp_backlight",
+                                                        NULL, NULL,
+                                                        &mbp_ops);
+       if (IS_ERR(mbp_backlight_device)) {
+               release_region(0xb2, 2);
+               return PTR_ERR(mbp_backlight_device);
+       }
+
+       mbp_backlight_device->props.max_brightness = 15;
+       mbp_backlight_device->props.brightness =
+               mbp_get_intensity(mbp_backlight_device);
+       backlight_update_status(mbp_backlight_device);
+
+       return 0;
+}
+
+static void __exit mbp_exit(void)
+{
+       backlight_device_unregister(mbp_backlight_device);
+
+       release_region(0xb2, 2);
+}
+
+module_init(mbp_init);
+module_exit(mbp_exit);
+
+MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
+MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,1");
+MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,2");
+MODULE_ALIAS("svnAppleInc.:pnMacBookPro4,1");
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
new file mode 100644 (file)
index 0000000..72d44db
--- /dev/null
@@ -0,0 +1,172 @@
+/* drivers/video/backlight/platform_lcd.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Generic platform-device LCD power control interface.
+ *
+ * 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/platform_device.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+
+#include <video/platform_lcd.h>
+
+struct platform_lcd {
+       struct device           *us;
+       struct lcd_device       *lcd;
+       struct plat_lcd_data    *pdata;
+
+       unsigned int             power;
+       unsigned int             suspended : 1;
+};
+
+static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd)
+{
+       return lcd_get_data(lcd);
+}
+
+static int platform_lcd_get_power(struct lcd_device *lcd)
+{
+       struct platform_lcd *plcd = to_our_lcd(lcd);
+
+       return plcd->power;
+}
+
+static int platform_lcd_set_power(struct lcd_device *lcd, int power)
+{
+       struct platform_lcd *plcd = to_our_lcd(lcd);
+       int lcd_power = 1;
+
+       if (power == FB_BLANK_POWERDOWN || plcd->suspended)
+               lcd_power = 0;
+
+       plcd->pdata->set_power(plcd->pdata, lcd_power);
+       plcd->power = power;
+
+       return 0;
+}
+
+static int platform_lcd_match(struct lcd_device *lcd, struct fb_info *info)
+{
+       struct platform_lcd *plcd = to_our_lcd(lcd);
+       struct plat_lcd_data *pdata = plcd->pdata;
+
+       if (pdata->match_fb)
+               return pdata->match_fb(pdata, info);
+
+       return plcd->us->parent == info->device;
+}
+
+static struct lcd_ops platform_lcd_ops = {
+       .get_power      = platform_lcd_get_power,
+       .set_power      = platform_lcd_set_power,
+       .check_fb       = platform_lcd_match,
+};
+
+static int __devinit platform_lcd_probe(struct platform_device *pdev)
+{
+       struct plat_lcd_data *pdata;
+       struct platform_lcd *plcd;
+       struct device *dev = &pdev->dev;
+       int err;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(dev, "no platform data supplied\n");
+               return -EINVAL;
+       }
+
+       plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL);
+       if (!plcd) {
+               dev_err(dev, "no memory for state\n");
+               return -ENOMEM;
+       }
+
+       plcd->us = dev;
+       plcd->pdata = pdata;
+       plcd->lcd = lcd_device_register("platform-lcd", dev,
+                                       plcd, &platform_lcd_ops);
+       if (IS_ERR(plcd->lcd)) {
+               dev_err(dev, "cannot register lcd device\n");
+               err = PTR_ERR(plcd->lcd);
+               goto err_mem;
+       }
+
+       platform_set_drvdata(pdev, plcd);
+       return 0;
+
+ err_mem:
+       kfree(plcd);
+       return err;
+}
+
+static int __devexit platform_lcd_remove(struct platform_device *pdev)
+{
+       struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+       lcd_device_unregister(plcd->lcd);
+       kfree(plcd);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int platform_lcd_suspend(struct platform_device *pdev, pm_message_t st)
+{
+       struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+       plcd->suspended = 1;
+       platform_lcd_set_power(plcd->lcd, plcd->power);
+
+       return 0;
+}
+
+static int platform_lcd_resume(struct platform_device *pdev)
+{
+       struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+       plcd->suspended = 0;
+       platform_lcd_set_power(plcd->lcd, plcd->power);
+
+       return 0;
+}
+#else
+#define platform_lcd_suspend NULL
+#define platform_lcd_resume NULL
+#endif
+
+static struct platform_driver platform_lcd_driver = {
+       .driver         = {
+               .name   = "platform-lcd",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = platform_lcd_probe,
+       .remove         = __devexit_p(platform_lcd_remove),
+       .suspend        = platform_lcd_suspend,
+       .resume         = platform_lcd_resume,
+};
+
+static int __init platform_lcd_init(void)
+{
+       return platform_driver_register(&platform_lcd_driver);
+}
+
+static void __exit platform_lcd_cleanup(void)
+{
+       platform_driver_unregister(&platform_lcd_driver);
+}
+
+module_init(platform_lcd_init);
+module_exit(platform_lcd_cleanup);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:platform-lcd");
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
new file mode 100644 (file)
index 0000000..593c768
--- /dev/null
@@ -0,0 +1,284 @@
+/* drivers/video/backlight/vgg2432a4.c
+ *
+ * VGG2432A4 (ILI9320) LCD controller driver.
+ *
+ * Copyright 2007 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+
+#include <linux/spi/spi.h>
+
+#include <video/ili9320.h>
+
+#include "ili9320.h"
+
+/* Device initialisation sequences */
+
+static struct ili9320_reg vgg_init1[] = {
+       {
+               .address = ILI9320_POWER1,
+               .value   = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0),
+       }, {
+               .address = ILI9320_POWER2,
+               .value   = (ILI9320_POWER2_VC(7) |
+                           ILI9320_POWER2_DC0(0) | ILI9320_POWER2_DC1(0)),
+       }, {
+               .address = ILI9320_POWER3,
+               .value   = ILI9320_POWER3_VRH(0),
+       }, {
+               .address = ILI9320_POWER4,
+               .value   = ILI9320_POWER4_VREOUT(0),
+       },
+};
+
+static struct ili9320_reg vgg_init2[] = {
+       {
+               .address = ILI9320_POWER1,
+               .value   = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE |
+                           ILI9320_POWER1_BT(7) | ILI9320_POWER1_SAP),
+       }, {
+               .address = ILI9320_POWER2,
+               .value   = ILI9320_POWER2_VC(7) | ILI9320_POWER2_DC0(3),
+       }
+};
+
+static struct ili9320_reg vgg_gamma[] = {
+       {
+               .address = ILI9320_GAMMA1,
+               .value   = 0x0000,
+       }, {
+               .address = ILI9320_GAMMA2,
+               .value   = 0x0505,
+       }, {
+               .address = ILI9320_GAMMA3,
+               .value   = 0x0004,
+       }, {
+               .address = ILI9320_GAMMA4,
+               .value   = 0x0006,
+       }, {
+               .address = ILI9320_GAMMA5,
+               .value   = 0x0707,
+       }, {
+               .address = ILI9320_GAMMA6,
+               .value   = 0x0105,
+       }, {
+               .address = ILI9320_GAMMA7,
+               .value   = 0x0002,
+       }, {
+               .address = ILI9320_GAMMA8,
+               .value   = 0x0707,
+       }, {
+               .address = ILI9320_GAMMA9,
+               .value   = 0x0704,
+       }, {
+               .address = ILI9320_GAMMA10,
+               .value   = 0x807,
+       }
+
+};
+
+static struct ili9320_reg vgg_init0[] = {
+       [0]     = {
+               /* set direction and scan mode gate */
+               .address = ILI9320_DRIVER,
+               .value   = ILI9320_DRIVER_SS,
+       }, {
+               .address = ILI9320_DRIVEWAVE,
+               .value   = (ILI9320_DRIVEWAVE_MUSTSET |
+                           ILI9320_DRIVEWAVE_EOR | ILI9320_DRIVEWAVE_BC),
+       }, {
+               .address = ILI9320_ENTRYMODE,
+               .value   = ILI9320_ENTRYMODE_ID(3) | ILI9320_ENTRYMODE_BGR,
+       }, {
+               .address = ILI9320_RESIZING,
+               .value   = 0x0,
+       },
+};
+
+
+static int vgg2432a4_lcd_init(struct ili9320 *lcd,
+                             struct ili9320_platdata *cfg)
+{
+       unsigned int addr;
+       int ret;
+
+       /* Set VCore before anything else (VGG243237-6UFLWA) */
+       ret = ili9320_write(lcd, 0x00e5, 0x8000);
+       if (ret)
+               goto err_initial;
+
+       /* Start the oscillator up before we can do anything else. */
+       ret = ili9320_write(lcd, ILI9320_OSCILATION, ILI9320_OSCILATION_OSC);
+       if (ret)
+               goto err_initial;
+
+       /* must wait at-lesat 10ms after starting */
+       mdelay(15);
+
+       ret = ili9320_write_regs(lcd, vgg_init0, ARRAY_SIZE(vgg_init0));
+       if (ret != 0)
+               goto err_initial;
+
+       ili9320_write(lcd, ILI9320_DISPLAY2, cfg->display2);
+       ili9320_write(lcd, ILI9320_DISPLAY3, cfg->display3);
+       ili9320_write(lcd, ILI9320_DISPLAY4, cfg->display4);
+
+       ili9320_write(lcd, ILI9320_RGB_IF1, cfg->rgb_if1);
+       ili9320_write(lcd, ILI9320_FRAMEMAKER, 0x0);
+       ili9320_write(lcd, ILI9320_RGB_IF2, ILI9320_RGBIF2_DPL);
+
+       ret = ili9320_write_regs(lcd, vgg_init1, ARRAY_SIZE(vgg_init1));
+       if (ret != 0)
+               goto err_vgg;
+
+       mdelay(300);
+
+       ret = ili9320_write_regs(lcd, vgg_init2, ARRAY_SIZE(vgg_init2));
+       if (ret != 0)
+               goto err_vgg2;
+
+       mdelay(100);
+
+       ili9320_write(lcd, ILI9320_POWER3, 0x13c);
+
+       mdelay(100);
+
+       ili9320_write(lcd, ILI9320_POWER4, 0x1c00);
+       ili9320_write(lcd, ILI9320_POWER7, 0x000e);
+
+       mdelay(100);
+
+       ili9320_write(lcd, ILI9320_GRAM_HORIZ_ADDR, 0x00);
+       ili9320_write(lcd, ILI9320_GRAM_VERT_ADD, 0x00);
+
+       ret = ili9320_write_regs(lcd, vgg_gamma, ARRAY_SIZE(vgg_gamma));
+       if (ret != 0)
+               goto err_vgg3;
+
+       ili9320_write(lcd, ILI9320_HORIZ_START, 0x0);
+       ili9320_write(lcd, ILI9320_HORIZ_END, cfg->hsize - 1);
+       ili9320_write(lcd, ILI9320_VERT_START, 0x0);
+       ili9320_write(lcd, ILI9320_VERT_END, cfg->vsize - 1);
+
+       ili9320_write(lcd, ILI9320_DRIVER2,
+                     ILI9320_DRIVER2_NL(((cfg->vsize - 240) / 8) + 0x1D));
+
+       ili9320_write(lcd, ILI9320_BASE_IMAGE, 0x1);
+       ili9320_write(lcd, ILI9320_VERT_SCROLL, 0x00);
+
+       for (addr = ILI9320_PARTIAL1_POSITION; addr <= ILI9320_PARTIAL2_END;
+            addr++) {
+               ili9320_write(lcd, addr, 0x0);
+       }
+
+       ili9320_write(lcd, ILI9320_INTERFACE1, 0x10);
+       ili9320_write(lcd, ILI9320_INTERFACE2, cfg->interface2);
+       ili9320_write(lcd, ILI9320_INTERFACE3, cfg->interface3);
+       ili9320_write(lcd, ILI9320_INTERFACE4, cfg->interface4);
+       ili9320_write(lcd, ILI9320_INTERFACE5, cfg->interface5);
+       ili9320_write(lcd, ILI9320_INTERFACE6, cfg->interface6);
+
+       lcd->display1 = (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_DTE |
+                        ILI9320_DISPLAY1_GON | ILI9320_DISPLAY1_BASEE |
+                        0x40);
+
+       ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+       return 0;
+
+ err_vgg3:
+ err_vgg2:
+ err_vgg:
+ err_initial:
+       return ret;
+}
+
+#ifdef CONFIG_PM
+static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state)
+{
+       return ili9320_suspend(dev_get_drvdata(&spi->dev), state);
+}
+
+static int vgg2432a4_resume(struct spi_device *spi)
+{
+       return ili9320_resume(dev_get_drvdata(&spi->dev));
+}
+#else
+#define vgg2432a4_suspend      NULL
+#define vgg2432a4_resume       NULL
+#endif
+
+static struct ili9320_client vgg2432a4_client = {
+       .name   = "VGG2432A4",
+       .init   = vgg2432a4_lcd_init,
+};
+
+/* Device probe */
+
+static int __devinit vgg2432a4_probe(struct spi_device *spi)
+{
+       int ret;
+
+       ret = ili9320_probe_spi(spi, &vgg2432a4_client);
+       if (ret != 0) {
+               dev_err(&spi->dev, "failed to initialise ili9320\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int __devexit vgg2432a4_remove(struct spi_device *spi)
+{
+       return ili9320_remove(dev_get_drvdata(&spi->dev));
+}
+
+static void vgg2432a4_shutdown(struct spi_device *spi)
+{
+       ili9320_shutdown(dev_get_drvdata(&spi->dev));
+}
+
+static struct spi_driver vgg2432a4_driver = {
+       .driver = {
+               .name           = "VGG2432A4",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = vgg2432a4_probe,
+       .remove         = __devexit_p(vgg2432a4_remove),
+       .shutdown       = vgg2432a4_shutdown,
+       .suspend        = vgg2432a4_suspend,
+       .resume         = vgg2432a4_resume,
+};
+
+/* Device driver initialisation */
+
+static int __init vgg2432a4_init(void)
+{
+       return spi_register_driver(&vgg2432a4_driver);
+}
+
+static void __exit vgg2432a4_exit(void)
+{
+       spi_unregister_driver(&vgg2432a4_driver);
+}
+
+module_init(vgg2432a4_init);
+module_exit(vgg2432a4_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("VGG2432A4 LCD Driver");
+MODULE_LICENSE("GPL v2");
+
+
index 49834a67a623351e3f27b5add2e1e2bbf6f114e9..940467aed13f27864849db15ba36b70e4ad2b846 100644 (file)
@@ -478,7 +478,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
        return 0;
 }
 
-static int bfin_lcd_check_fb(struct fb_info *fi)
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
 {
        if (!fi || (fi == &bfin_bf54x_fb))
                return 1;
index 135d6dd7e6729ded15706dcc16a2f78a68086e5e..7d1b819e501c780f4e9ddc1929ac8d155d633148 100644 (file)
@@ -396,7 +396,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
        return 0;
 }
 
-static int bfin_lcd_check_fb(struct fb_info *fi)
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
 {
        if (!fi || (fi == &bfin_t350mcqb_fb))
                return 1;
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
new file mode 100644 (file)
index 0000000..e15bb44
--- /dev/null
@@ -0,0 +1,790 @@
+/*
+ * Frame buffer driver for the Carmine GPU.
+ *
+ * The driver configures the GPU as follows
+ * - FB0 is display 0 with unique memory area
+ * - FB1 is display 1 with unique memory area
+ * - both display use 32 bit colors
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#include "carminefb.h"
+#include "carminefb_regs.h"
+
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+#error  "The endianness of the target host has not been defined."
+#endif
+
+/*
+ * The initial video mode can be supplied via two different ways:
+ * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
+ * - as an integer that picks the video mode from carmine_modedb[] (module
+ *   option fb_mode)
+ *
+ * If nothing is used than the initial video mode will be the
+ * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
+ */
+#define CARMINEFB_DEFAULT_VIDEO_MODE   1
+
+static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
+module_param(fb_mode, uint, 444);
+MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
+
+static char *fb_mode_str;
+module_param(fb_mode_str, charp, 444);
+MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
+
+/*
+ * Carminefb displays:
+ * 0b000 None
+ * 0b001 Display 0
+ * 0b010 Display 1
+ */
+static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
+module_param(fb_displays, int, 444);
+MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
+
+struct carmine_hw {
+       void __iomem *v_regs;
+       void __iomem *screen_mem;
+       struct fb_info *fb[MAX_DISPLAY];
+};
+
+struct carmine_resolution {
+       u32 htp;
+       u32 hsp;
+       u32 hsw;
+       u32 hdp;
+       u32 vtr;
+       u32 vsp;
+       u32 vsw;
+       u32 vdp;
+       u32 disp_mode;
+};
+
+struct carmine_fb {
+       void __iomem *display_reg;
+       void __iomem *screen_base;
+       u32 smem_offset;
+       u32 cur_mode;
+       u32 new_mode;
+       struct carmine_resolution *res;
+       u32 pseudo_palette[16];
+};
+
+static struct fb_fix_screeninfo carminefb_fix __devinitdata = {
+       .id = "Carmine",
+       .type = FB_TYPE_PACKED_PIXELS,
+       .visual = FB_VISUAL_TRUECOLOR,
+       .accel = FB_ACCEL_NONE,
+};
+
+static const struct fb_videomode carmine_modedb[] = {
+       {
+               .name           = "640x480",
+               .xres           = 640,
+               .yres           = 480,
+       }, {
+               .name           = "800x600",
+               .xres           = 800,
+               .yres           = 600,
+       },
+};
+
+static struct carmine_resolution car_modes[] = {
+       {
+               /* 640x480 */
+               .htp = 800,
+               .hsp = 672,
+               .hsw = 96,
+               .hdp = 640,
+               .vtr = 525,
+               .vsp = 490,
+               .vsw = 2,
+               .vdp = 480,
+               .disp_mode = 0x1400,
+       },
+       {
+               /* 800x600 */
+               .htp = 1060,
+               .hsp = 864,
+               .hsw = 72,
+               .hdp = 800,
+               .vtr = 628,
+               .vsp = 601,
+               .vsw = 2,
+               .vdp = 600,
+               .disp_mode = 0x0d00,
+       }
+};
+
+static int carmine_find_mode(const struct fb_var_screeninfo *var)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(car_modes); i++)
+               if (car_modes[i].hdp == var->xres &&
+                   car_modes[i].vdp == var->yres)
+                       return i;
+       return -EINVAL;
+}
+
+static void c_set_disp_reg(const struct carmine_fb *par,
+               u32 offset, u32 val)
+{
+       writel(val, par->display_reg + offset);
+}
+
+static u32 c_get_disp_reg(const struct carmine_fb *par,
+               u32 offset)
+{
+       return readl(par->display_reg + offset);
+}
+
+static void c_set_hw_reg(const struct carmine_hw *hw,
+               u32 offset, u32 val)
+{
+       writel(val, hw->v_regs + offset);
+}
+
+static u32 c_get_hw_reg(const struct carmine_hw *hw,
+               u32 offset)
+{
+       return readl(hw->v_regs + offset);
+}
+
+static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
+               unsigned blue, unsigned transp, struct fb_info *info)
+{
+       if (regno >= 16)
+               return 1;
+
+       red >>= 8;
+       green >>= 8;
+       blue >>= 8;
+       transp >>= 8;
+
+       ((u32 *)info->pseudo_palette)[regno] = be32_to_cpu(transp << 24 |
+               red << 0 | green << 8 | blue << 16);
+       return 0;
+}
+
+static int carmine_check_var(struct fb_var_screeninfo *var,
+               struct fb_info *info)
+{
+       int ret;
+
+       ret = carmine_find_mode(var);
+       if (ret < 0)
+               return ret;
+
+       if (var->grayscale || var->rotate || var->nonstd)
+               return -EINVAL;
+
+       var->xres_virtual = var->xres;
+       var->yres_virtual = var->yres;
+
+       var->bits_per_pixel = 32;
+
+#ifdef __BIG_ENDIAN
+       var->transp.offset = 24;
+       var->red.offset = 0;
+       var->green.offset = 8;
+       var->blue.offset = 16;
+#else
+       var->transp.offset = 24;
+       var->red.offset = 16;
+       var->green.offset = 8;
+       var->blue.offset = 0;
+#endif
+
+       var->red.length = 8;
+       var->green.length = 8;
+       var->blue.length = 8;
+       var->transp.length = 8;
+
+       var->red.msb_right = 0;
+       var->green.msb_right = 0;
+       var->blue.msb_right = 0;
+       var->transp.msb_right = 0;
+       return 0;
+}
+
+static void carmine_init_display_param(struct carmine_fb *par)
+{
+       u32 width;
+       u32 height;
+       u32 param;
+       u32 window_size;
+       u32 soffset = par->smem_offset;
+
+       c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
+                       CARMINE_CURSOR0_PRIORITY_MASK |
+                       CARMINE_CURSOR1_PRIORITY_MASK |
+                       CARMINE_CURSOR_CUTZ_MASK);
+
+       /* Set default cursor position */
+       c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
+
+       /* Set default display mode */
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
+                       CARMINE_EXT_CMODE_DIRECT24_RGBA);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
+                       CARMINE_EXT_CMODE_DIRECT24_RGBA);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
+                       CARMINE_EXT_CMODE_DIRECT24_RGBA);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
+                       CARMINE_EXT_CMODE_DIRECT24_RGBA);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
+                       CARMINE_EXT_CMODE_DIRECT24_RGBA);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE |
+                       CARMINE_EXT_CMODE_DIRECT24_RGBA);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE |
+                       CARMINE_EXT_CMODE_DIRECT24_RGBA);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE |
+                       CARMINE_EXT_CMODE_DIRECT24_RGBA);
+
+       /* Set default frame size to layer mode register */
+       width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT;
+       width = width << CARMINE_DISP_WIDTH_SHIFT;
+
+       height = par->res->vdp - 1;
+       param = width | height;
+
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param);
+
+       /* Set default pos and size */
+       window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT;
+       window_size |= par->res->hdp;
+
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size);
+
+       /* Set default origin address */
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset);
+
+       /* Set default display address */
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset);
+
+       /* Set default display position */
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0);
+
+       /* Set default blend mode */
+       c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0);
+
+       /* default transparency mode */
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0);
+
+       /* Set default read skip parameter */
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0);
+
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0);
+
+       c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0);
+       c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0);
+}
+
+static void set_display_parameters(struct carmine_fb *par)
+{
+       u32 mode;
+       u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw;
+
+       /*
+        * display timing. Parameters are decreased by one because hardware
+        * spec is 0 to (n - 1)
+        * */
+       hdp = par->res->hdp - 1;
+       vdp = par->res->vdp - 1;
+       htp = par->res->htp - 1;
+       hsp = par->res->hsp - 1;
+       hsw = par->res->hsw - 1;
+       vtr = par->res->vtr - 1;
+       vsp = par->res->vsp - 1;
+       vsw = par->res->vsw - 1;
+
+       c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL,
+                       htp << CARMINE_DISP_HTP_SHIFT);
+       c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD,
+                       (hdp << CARMINE_DISP_HDB_SHIFT) | hdp);
+       c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS,
+                       (vsw << CARMINE_DISP_VSW_SHIFT) |
+                       (hsw << CARMINE_DISP_HSW_SHIFT) |
+                       (hsp));
+       c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL,
+                       vtr << CARMINE_DISP_VTR_SHIFT);
+       c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS,
+                       (vdp << CARMINE_DISP_VDP_SHIFT) | vsp);
+
+       /* clock */
+       mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);
+       mode = (mode & ~CARMINE_DISP_DCM_MASK) |
+               (par->res->disp_mode & CARMINE_DISP_DCM_MASK);
+       /* enable video output and layer 0 */
+       mode |= CARMINE_DEN | CARMINE_L0E;
+       c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);
+}
+
+static int carmine_set_par(struct fb_info *info)
+{
+       struct carmine_fb *par = info->par;
+       int ret;
+
+       ret = carmine_find_mode(&info->var);
+       if (ret < 0)
+               return ret;
+
+       par->new_mode = ret;
+       if (par->cur_mode != par->new_mode) {
+
+               par->cur_mode = par->new_mode;
+               par->res = &car_modes[par->new_mode];
+
+               carmine_init_display_param(par);
+               set_display_parameters(par);
+       }
+
+       info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
+       return 0;
+}
+
+static int init_hardware(struct carmine_hw *hw)
+{
+       u32 flags;
+       u32 loops;
+       u32 ret;
+
+       /* Initalize Carmine */
+       /* Sets internal clock */
+       c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
+                       CARMINE_DFLT_IP_CLOCK_ENABLE);
+
+       /* Video signal output is turned off */
+       c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
+       c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
+
+       /* Software reset */
+       c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);
+       c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);
+
+       /* I/O mode settings */
+       flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |
+               CARMINE_DFLT_IP_DCTL_IO_CONT0;
+       c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,
+                       flags);
+
+       /* DRAM initial sequence */
+       flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;
+       c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,
+                       flags);
+
+       flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |
+               CARMINE_DFLT_IP_DCTL_EMODE;
+       c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,
+                       flags);
+
+       flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |
+               CARMINE_DFLT_IP_DCTL_SET_TIME2;
+       c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,
+                       flags);
+
+       flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |
+               CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;
+       c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);
+
+       flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;
+       c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,
+                       flags);
+
+       flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
+               CARMINE_DFLT_IP_DCTL_STATES;
+       c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
+                       flags);
+
+       /* Executes DLL reset */
+       if (CARMINE_DCTL_DLL_RESET) {
+               for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {
+
+                       ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +
+                                       CARMINE_DCTL_REG_RSV0_STATES);
+                       ret &= CARMINE_DCTL_REG_STATES_MASK;
+                       if (!ret)
+                               break;
+
+                       mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);
+               }
+
+               if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {
+                       printk(KERN_ERR "DRAM init failed\n");
+                       return -EIO;
+               }
+       }
+
+       flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |
+               CARMINE_DFLT_IP_DCTL_ADD;
+       c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);
+
+       flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
+               CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;
+       c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
+                       flags);
+
+       /* Initialize the write back register */
+       c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,
+                       CARMINE_WB_REG_WBM_DEFAULT);
+
+       /* Initialize the Kottos registers */
+       c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);
+       c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);
+
+       /* Set DC offsets */
+       c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);
+       c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);
+       c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);
+       c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);
+       c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);
+       c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);
+       return 0;
+}
+
+static struct fb_ops carminefb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+
+       .fb_check_var   = carmine_check_var,
+       .fb_set_par     = carmine_set_par,
+       .fb_setcolreg   = carmine_setcolreg,
+};
+
+static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
+               int smem_offset, struct device *device, struct fb_info **rinfo)
+{
+       int ret;
+       struct fb_info *info;
+       struct carmine_fb *par;
+
+       info = framebuffer_alloc(sizeof *par, device);
+       if (!info)
+               return -ENOMEM;
+
+       par = info->par;
+       par->display_reg = regs;
+       par->smem_offset = smem_offset;
+
+       info->screen_base = smem_base + smem_offset;
+       info->screen_size = CARMINE_DISPLAY_MEM;
+       info->fbops = &carminefb_ops;
+
+       info->fix = carminefb_fix;
+       info->pseudo_palette = par->pseudo_palette;
+       info->flags = FBINFO_DEFAULT;
+
+       ret = fb_alloc_cmap(&info->cmap, 256, 1);
+       if (ret < 0)
+               goto err_free_fb;
+
+       if (fb_mode > ARRAY_SIZE(carmine_modedb))
+               fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
+
+       par->cur_mode = par->new_mode = ~0;
+
+       ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,
+                       ARRAY_SIZE(carmine_modedb),
+                       &carmine_modedb[fb_mode], 32);
+       if (!ret || ret == 4) {
+               ret = -EINVAL;
+               goto err_dealloc_cmap;
+       }
+
+       fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),
+                       &info->modelist);
+
+       ret = register_framebuffer(info);
+       if (ret < 0)
+               goto err_dealloc_cmap;
+
+       printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+                       info->fix.id);
+
+       *rinfo = info;
+       return 0;
+
+err_dealloc_cmap:
+       fb_dealloc_cmap(&info->cmap);
+err_free_fb:
+       framebuffer_release(info);
+       return ret;
+}
+
+static void cleanup_fb_device(struct fb_info *info)
+{
+       if (info) {
+               unregister_framebuffer(info);
+               fb_dealloc_cmap(&info->cmap);
+               framebuffer_release(info);
+       }
+}
+
+static int __devinit carminefb_probe(struct pci_dev *dev,
+               const struct pci_device_id *ent)
+{
+       struct carmine_hw *hw;
+       struct device *device = &dev->dev;
+       struct fb_info *info;
+       int ret;
+
+       ret = pci_enable_device(dev);
+       if (ret)
+               return ret;
+
+       ret = -ENOMEM;
+       hw = kzalloc(sizeof *hw, GFP_KERNEL);
+       if (!hw)
+               goto err_enable_pci;
+
+       carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);
+       carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);
+
+       if (!request_mem_region(carminefb_fix.mmio_start,
+                               carminefb_fix.mmio_len,
+                               "carminefb regbase")) {
+               printk(KERN_ERR "carminefb: Can't reserve regbase.\n");
+               ret = -EBUSY;
+               goto err_free_hw;
+       }
+       hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start,
+                       carminefb_fix.mmio_len);
+       if (!hw->v_regs) {
+               printk(KERN_ERR "carminefb: Can't remap %s register.\n",
+                               carminefb_fix.id);
+               goto err_free_reg_mmio;
+       }
+
+       carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);
+       carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);
+
+       /* The memory area tends to be very large (256 MiB). Remap only what
+        * is required for that largest resolution to avoid remaps at run
+        * time
+        */
+       if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)
+               carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;
+
+       else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {
+               printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
+                               "are required.", carminefb_fix.smem_len,
+                               CARMINE_TOTAL_DIPLAY_MEM);
+               goto err_free_reg_mmio;
+       }
+
+       if (!request_mem_region(carminefb_fix.smem_start,
+                               carminefb_fix.smem_len, "carminefb smem")) {
+               printk(KERN_ERR "carminefb: Can't reserve smem.\n");
+               goto err_unmap_vregs;
+       }
+
+       hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start,
+                       carminefb_fix.smem_len);
+       if (!hw->screen_mem) {
+               printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
+               release_mem_region(carminefb_fix.smem_start,
+                               carminefb_fix.smem_len);
+               goto err_reg_smem;
+       }
+
+       ret = init_hardware(hw);
+       if (ret)
+               goto err_unmap_screen;
+
+       info = NULL;
+       if (fb_displays & CARMINE_USE_DISPLAY0) {
+               ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,
+                               hw->screen_mem, CARMINE_DISPLAY_MEM * 0,
+                               device, &info);
+               if (ret)
+                       goto err_deinit_hw;
+       }
+
+       hw->fb[0] = info;
+
+       info = NULL;
+       if (fb_displays & CARMINE_USE_DISPLAY1) {
+               ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,
+                               hw->screen_mem, CARMINE_DISPLAY_MEM * 1,
+                               device, &info);
+               if (ret)
+                       goto err_cleanup_fb0;
+       }
+
+       hw->fb[1] = info;
+       info = NULL;
+
+       pci_set_drvdata(dev, hw);
+       return 0;
+
+err_cleanup_fb0:
+       cleanup_fb_device(hw->fb[0]);
+err_deinit_hw:
+       /* disable clock, etc */
+       c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
+err_unmap_screen:
+       iounmap(hw->screen_mem);
+err_reg_smem:
+       release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
+err_unmap_vregs:
+       iounmap(hw->v_regs);
+err_free_reg_mmio:
+       release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
+err_free_hw:
+       kfree(hw);
+err_enable_pci:
+       pci_disable_device(dev);
+       return ret;
+}
+
+static void __devexit carminefb_remove(struct pci_dev *dev)
+{
+       struct carmine_hw *hw = pci_get_drvdata(dev);
+       struct fb_fix_screeninfo fix;
+       int i;
+
+       /* in case we use only fb1 and not fb1 */
+       if (hw->fb[0])
+               fix = hw->fb[0]->fix;
+       else
+               fix = hw->fb[1]->fix;
+
+       /* deactivate display(s) and switch clocks */
+       c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
+       c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
+       c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
+
+       for (i = 0; i < MAX_DISPLAY; i++)
+               cleanup_fb_device(hw->fb[i]);
+
+       iounmap(hw->screen_mem);
+       release_mem_region(fix.smem_start, fix.smem_len);
+       iounmap(hw->v_regs);
+       release_mem_region(fix.mmio_start, fix.mmio_len);
+
+       pci_set_drvdata(dev, NULL);
+       pci_disable_device(dev);
+       kfree(hw);
+}
+
+#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
+static struct pci_device_id carmine_devices[] __devinitdata = {
+{
+       PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
+       {0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, carmine_devices);
+
+static struct pci_driver carmine_pci_driver = {
+       .name           = "carminefb",
+       .id_table       = carmine_devices,
+       .probe          = carminefb_probe,
+       .remove         = __devexit_p(carminefb_remove),
+};
+
+static int __init carminefb_init(void)
+{
+       if (!(fb_displays &
+               (CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {
+               printk(KERN_ERR "If you disable both displays than you don't "
+                               "need the driver at all\n");
+               return -EINVAL;
+       }
+       return pci_register_driver(&carmine_pci_driver);
+}
+module_init(carminefb_init);
+
+static void __exit carminefb_cleanup(void)
+{
+       pci_unregister_driver(&carmine_pci_driver);
+}
+module_exit(carminefb_cleanup);
+
+MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/carminefb.h b/drivers/video/carminefb.h
new file mode 100644 (file)
index 0000000..05306de
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef CARMINE_CARMINE_H
+#define CARMINE_CARMINE_H
+
+#define CARMINE_MEMORY_BAR     2
+#define CARMINE_CONFIG_BAR     3
+
+#define MAX_DISPLAY    2
+#define CARMINE_DISPLAY_MEM    (800 * 600 * 4)
+#define CARMINE_TOTAL_DIPLAY_MEM       (CARMINE_DISPLAY_MEM * MAX_DISPLAY)
+
+#define CARMINE_USE_DISPLAY0   (1 << 0)
+#define CARMINE_USE_DISPLAY1   (1 << 1)
+
+/*
+ * This values work on the eval card. Custom boards may use different timings,
+ * here an example :)
+ */
+
+/* DRAM initialization values */
+#ifdef CONFIG_FB_CARMINE_DRAM_EVAL
+
+#define CARMINE_DFLT_IP_CLOCK_ENABLE           (0x03ff)
+#define CARMINE_DFLT_IP_DCTL_ADD               (0x05c3)
+#define CARMINE_DFLT_IP_DCTL_MODE              (0x0121)
+#define CARMINE_DFLT_IP_DCTL_EMODE             (0x8000)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME1         (0x4749)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME2         (0x2a22)
+#define CARMINE_DFLT_IP_DCTL_REFRESH           (0x0042)
+#define CARMINE_DFLT_IP_DCTL_STATES            (0x0003)
+#define CARMINE_DFLT_IP_DCTL_RESERVE0          (0x0020)
+#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH                (0x000f)
+#define CARMINE_DFLT_IP_DCTL_RESERVE2          (0x0000)
+#define CARMINE_DFLT_IP_DCTL_DDRIF1            (0x6646)
+#define CARMINE_DFLT_IP_DCTL_DDRIF2            (0x0055)
+#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST      (0x0021)
+#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST    (0x0002)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT0          (0x0555)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT1          (0x0555)
+#define CARMINE_DCTL_DLL_RESET                 (1)
+#endif
+
+#ifdef CONFIG_CARMINE_DRAM_CUSTOM
+
+#define CARMINE_DFLT_IP_CLOCK_ENABLE           (0x03ff)
+#define CARMINE_DFLT_IP_DCTL_ADD               (0x03b2)
+#define CARMINE_DFLT_IP_DCTL_MODE              (0x0161)
+#define CARMINE_DFLT_IP_DCTL_EMODE             (0x8000)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME1         (0x2628)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME2         (0x1a09)
+#define CARMINE_DFLT_IP_DCTL_REFRESH           (0x00fe)
+#define CARMINE_DFLT_IP_DCTL_STATES            (0x0003)
+#define CARMINE_DFLT_IP_DCTL_RESERVE0          (0x0020)
+#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH                (0x000f)
+#define CARMINE_DFLT_IP_DCTL_RESERVE2          (0x0000)
+#define CARMINE_DFLT_IP_DCTL_DDRIF1            (0x0646)
+#define CARMINE_DFLT_IP_DCTL_DDRIF2            (0x55aa)
+#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST      (0x0061)
+#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST    (0x0002)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT0          (0x0555)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT1          (0x0555)
+#define CARMINE_DCTL_DLL_RESET                 (1)
+#endif
+
+#endif
diff --git a/drivers/video/carminefb_regs.h b/drivers/video/carminefb_regs.h
new file mode 100644 (file)
index 0000000..0452156
--- /dev/null
@@ -0,0 +1,159 @@
+#ifndef _CARMINEFB_REGS_H
+#define _CARMINEFB_REGS_H
+
+#define CARMINE_OVERLAY_EXT_MODE       (0x00000002)
+#define CARMINE_GRAPH_REG              (0x00000000)
+#define CARMINE_DISP0_REG              (0x00100000)
+#define CARMINE_DISP1_REG              (0x00140000)
+#define CARMINE_WB_REG                 (0x00180000)
+#define CARMINE_DCTL_REG               (0x00300000)
+#define CARMINE_CTL_REG                        (0x00400000)
+#define CARMINE_WINDOW_MODE            (0x00000001)
+#define CARMINE_EXTEND_MODE            (CARMINE_WINDOW_MODE | \
+                                       CARMINE_OVERLAY_EXT_MODE)
+#define CARMINE_L0E                    (1 << 16)
+#define CARMINE_L2E                    (1 << 18)
+#define CARMINE_DEN                    (1 << 31)
+
+#define CARMINE_EXT_CMODE_DIRECT24_RGBA                (0xC0000000)
+#define CARMINE_DCTL_REG_MODE_ADD              (0x00)
+#define CARMINE_DCTL_REG_SETTIME1_EMODE                (0x04)
+#define CARMINE_DCTL_REG_REFRESH_SETTIME2      (0x08)
+#define CARMINE_DCTL_REG_RSV0_STATES           (0x0C)
+#define CARMINE_DCTL_REG_RSV2_RSV1             (0x10)
+#define CARMINE_DCTL_REG_DDRIF2_DDRIF1         (0x14)
+#define CARMINE_DCTL_REG_IOCONT1_IOCONT0       (0x24)
+#define CARMINE_DCTL_REG_STATES_MASK           (0x000F)
+#define CARMINE_DCTL_INIT_WAIT_INTERVAL                (1)
+#define CARMINE_DCTL_INIT_WAIT_LIMIT           (5000)
+#define CARMINE_WB_REG_WBM_DEFAULT             (0x0001c020)
+#define CARMINE_DISP_REG_L0RM                  (0x1880)
+#define CARMINE_DISP_REG_L0PX                  (0x1884)
+#define CARMINE_DISP_REG_L0PY                  (0x1888)
+#define CARMINE_DISP_REG_L2RM                  (0x18A0)
+#define CARMINE_DISP_REG_L2PX                  (0x18A4)
+#define CARMINE_DISP_REG_L2PY                  (0x18A8)
+#define CARMINE_DISP_REG_L3RM                  (0x18B0)
+#define CARMINE_DISP_REG_L3PX                  (0x18B4)
+#define CARMINE_DISP_REG_L3PY                  (0x18B8)
+#define CARMINE_DISP_REG_L4RM                  (0x18C0)
+#define CARMINE_DISP_REG_L4PX                  (0x18C4)
+#define CARMINE_DISP_REG_L4PY                  (0x18C8)
+#define CARMINE_DISP_REG_L5RM                  (0x18D0)
+#define CARMINE_DISP_REG_L5PX                  (0x18D4)
+#define CARMINE_DISP_REG_L5PY                  (0x18D8)
+#define CARMINE_DISP_REG_L6RM                  (0x1924)
+#define CARMINE_DISP_REG_L6PX                  (0x1928)
+#define CARMINE_DISP_REG_L6PY                  (0x192C)
+#define CARMINE_DISP_REG_L7RM                  (0x1964)
+#define CARMINE_DISP_REG_L7PX                  (0x1968)
+#define CARMINE_DISP_REG_L7PY                  (0x196C)
+#define CARMINE_WB_REG_WBM                     (0x0004)
+#define CARMINE_DISP_HTP_SHIFT                 (16)
+#define CARMINE_DISP_HDB_SHIFT                 (16)
+#define CARMINE_DISP_HSW_SHIFT                 (16)
+#define CARMINE_DISP_VSW_SHIFT                 (24)
+#define CARMINE_DISP_VTR_SHIFT                 (16)
+#define CARMINE_DISP_VDP_SHIFT                 (16)
+#define CARMINE_CURSOR_CUTZ_MASK               (0x00000100)
+#define CARMINE_CURSOR0_PRIORITY_MASK          (0x00010000)
+#define CARMINE_CURSOR1_PRIORITY_MASK          (0x00020000)
+#define CARMINE_DISP_WIDTH_SHIFT               (16)
+#define CARMINE_DISP_WIN_H_SHIFT               (16)
+#define CARMINE_DISP_REG_H_TOTAL               (0x0004)
+#define CARMINE_DISP_REG_H_PERIOD              (0x0008)
+#define CARMINE_DISP_REG_V_H_W_H_POS           (0x000C)
+#define CARMINE_DISP_REG_V_TOTAL               (0x0010)
+#define CARMINE_DISP_REG_V_PERIOD_POS          (0x0014)
+#define CARMINE_DISP_REG_L0_MODE_W_H           (0x0020)
+#define CARMINE_DISP_REG_L0_ORG_ADR            (0x0024)
+#define CARMINE_DISP_REG_L0_DISP_ADR           (0x0028)
+#define CARMINE_DISP_REG_L0_DISP_POS           (0x002C)
+#define CARMINE_DISP_REG_L1_WIDTH              (0x0030)
+#define CARMINE_DISP_REG_L1_ORG_ADR            (0x0034)
+#define CARMINE_DISP_REG_L2_MODE_W_H           (0x0040)
+#define CARMINE_DISP_REG_L2_ORG_ADR1           (0x0044)
+#define CARMINE_DISP_REG_L2_DISP_ADR1          (0x0048)
+#define CARMINE_DISP_REG_L2_DISP_POS           (0x0054)
+#define CARMINE_DISP_REG_L3_MODE_W_H           (0x0058)
+#define CARMINE_DISP_REG_L3_ORG_ADR1           (0x005C)
+#define CARMINE_DISP_REG_L3_DISP_ADR1          (0x0060)
+#define CARMINE_DISP_REG_L3_DISP_POS           (0x006C)
+#define CARMINE_DISP_REG_L4_MODE_W_H           (0x0070)
+#define CARMINE_DISP_REG_L4_ORG_ADR1           (0x0074)
+#define CARMINE_DISP_REG_L4_DISP_ADR1          (0x0078)
+#define CARMINE_DISP_REG_L4_DISP_POS           (0x0084)
+#define CARMINE_DISP_REG_L5_MODE_W_H           (0x0088)
+#define CARMINE_DISP_REG_L5_ORG_ADR1           (0x008C)
+#define CARMINE_DISP_REG_L5_DISP_ADR1          (0x0090)
+#define CARMINE_DISP_REG_L5_DISP_POS           (0x009C)
+#define CARMINE_DISP_REG_CURSOR_MODE           (0x00A0)
+#define CARMINE_DISP_REG_CUR1_POS              (0x00A8)
+#define CARMINE_DISP_REG_CUR2_POS              (0x00B0)
+#define CARMINE_DISP_REG_C_TRANS               (0x00BC)
+#define CARMINE_DISP_REG_MLMR_TRANS            (0x00C0)
+#define CARMINE_DISP_REG_L0_EXT_MODE           (0x0110)
+#define CARMINE_DISP_REG_L0_WIN_POS            (0x0114)
+#define CARMINE_DISP_REG_L0_WIN_SIZE           (0x0118)
+#define CARMINE_DISP_REG_L1_EXT_MODE           (0x0120)
+#define CARMINE_DISP_REG_L1_WIN_POS            (0x0124)
+#define CARMINE_DISP_REG_L1_WIN_SIZE           (0x0128)
+#define CARMINE_DISP_REG_L2_EXT_MODE           (0x0130)
+#define CARMINE_DISP_REG_L2_WIN_POS            (0x0134)
+#define CARMINE_DISP_REG_L2_WIN_SIZE           (0x0138)
+#define CARMINE_DISP_REG_L3_EXT_MODE           (0x0140)
+#define CARMINE_DISP_REG_L3_WIN_POS            (0x0144)
+#define CARMINE_DISP_REG_L3_WIN_SIZE           (0x0148)
+#define CARMINE_DISP_REG_L4_EXT_MODE           (0x0150)
+#define CARMINE_DISP_REG_L4_WIN_POS            (0x0154)
+#define CARMINE_DISP_REG_L4_WIN_SIZE           (0x0158)
+#define CARMINE_DISP_REG_L5_EXT_MODE           (0x0160)
+#define CARMINE_DISP_REG_L5_WIN_POS            (0x0164)
+#define CARMINE_DISP_REG_L5_WIN_SIZE           (0x0168)
+#define CARMINE_DISP_REG_L6_EXT_MODE           (0x1918)
+#define CARMINE_DISP_REG_L6_WIN_POS            (0x191c)
+#define CARMINE_DISP_REG_L6_WIN_SIZE           (0x1920)
+#define CARMINE_DISP_REG_L7_EXT_MODE           (0x1958)
+#define CARMINE_DISP_REG_L7_WIN_POS            (0x195c)
+#define CARMINE_DISP_REG_L7_WIN_SIZE           (0x1960)
+#define CARMINE_DISP_REG_BLEND_MODE_L0         (0x00B4)
+#define CARMINE_DISP_REG_BLEND_MODE_L1         (0x0188)
+#define CARMINE_DISP_REG_BLEND_MODE_L2         (0x018C)
+#define CARMINE_DISP_REG_BLEND_MODE_L3         (0x0190)
+#define CARMINE_DISP_REG_BLEND_MODE_L4         (0x0194)
+#define CARMINE_DISP_REG_BLEND_MODE_L5         (0x0198)
+#define CARMINE_DISP_REG_BLEND_MODE_L6         (0x1990)
+#define CARMINE_DISP_REG_BLEND_MODE_L7         (0x1994)
+#define CARMINE_DISP_REG_L0_TRANS              (0x01A0)
+#define CARMINE_DISP_REG_L1_TRANS              (0x01A4)
+#define CARMINE_DISP_REG_L2_TRANS              (0x01A8)
+#define CARMINE_DISP_REG_L3_TRANS              (0x01AC)
+#define CARMINE_DISP_REG_L4_TRANS              (0x01B0)
+#define CARMINE_DISP_REG_L5_TRANS              (0x01B4)
+#define CARMINE_DISP_REG_L6_TRANS              (0x1998)
+#define CARMINE_DISP_REG_L7_TRANS              (0x199c)
+#define CARMINE_EXTEND_MODE_MASK               (0x00000003)
+#define CARMINE_DISP_DCM_MASK                  (0x0000FFFF)
+#define CARMINE_DISP_REG_DCM1                  (0x0100)
+#define CARMINE_DISP_WIDTH_UNIT                        (64)
+#define CARMINE_DISP_REG_L6_MODE_W_H           (0x1900)
+#define CARMINE_DISP_REG_L6_ORG_ADR1           (0x1904)
+#define CARMINE_DISP_REG_L6_DISP_ADR0          (0x1908)
+#define CARMINE_DISP_REG_L6_DISP_POS           (0x1914)
+#define CARMINE_DISP_REG_L7_MODE_W_H           (0x1940)
+#define CARMINE_DISP_REG_L7_ORG_ADR1           (0x1944)
+#define CARMINE_DISP_REG_L7_DISP_ADR0          (0x1948)
+#define CARMINE_DISP_REG_L7_DISP_POS           (0x1954)
+#define CARMINE_CTL_REG_CLOCK_ENABLE           (0x000C)
+#define CARMINE_CTL_REG_SOFTWARE_RESET         (0x0010)
+#define CARMINE_CTL_REG_IST_MASK_ALL           (0x07FFFFFF)
+#define CARMINE_GRAPH_REG_VRINTM               (0x00028064)
+#define CARMINE_GRAPH_REG_VRERRM               (0x0002806C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_PX         (0x0004005C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_PY         (0x00040060)
+#define CARMINE_GRAPH_REG_DC_OFFSET_LX         (0x00040064)
+#define CARMINE_GRAPH_REG_DC_OFFSET_LY         (0x00040068)
+#define CARMINE_GRAPH_REG_DC_OFFSET_TX         (0x0004006C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_TY         (0x00040070)
+
+#endif
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
new file mode 100644 (file)
index 0000000..7bad24e
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ *  Cobalt server LCD frame buffer driver.
+ *
+ *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  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/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+
+/*
+ * Cursor position address
+ * \X  0    1    2  ...  14   15
+ * Y+----+----+----+---+----+----+
+ * 0|0x00|0x01|0x02|...|0x0e|0x0f|
+ *  +----+----+----+---+----+----+
+ * 1|0x40|0x41|0x42|...|0x4e|0x4f|
+ *  +----+----+----+---+----+----+
+ */
+#define LCD_DATA_REG_OFFSET    0x10
+#define LCD_XRES_MAX           16
+#define LCD_YRES_MAX           2
+#define LCD_CHARS_MAX          32
+
+#define LCD_CLEAR              0x01
+#define LCD_CURSOR_MOVE_HOME   0x02
+#define LCD_RESET              0x06
+#define LCD_OFF                        0x08
+#define LCD_CURSOR_OFF         0x0c
+#define LCD_CURSOR_BLINK_OFF   0x0e
+#define LCD_CURSOR_ON          0x0f
+#define LCD_ON                 LCD_CURSOR_ON
+#define LCD_CURSOR_MOVE_LEFT   0x10
+#define LCD_CURSOR_MOVE_RIGHT  0x14
+#define LCD_DISPLAY_LEFT       0x18
+#define LCD_DISPLAY_RIGHT      0x1c
+#define LCD_PRERESET           0x3f    /* execute 4 times continuously */
+#define LCD_BUSY               0x80
+
+#define LCD_GRAPHIC_MODE       0x40
+#define LCD_TEXT_MODE          0x80
+#define LCD_CUR_POS_MASK       0x7f
+
+#define LCD_CUR_POS(x)         ((x) & LCD_CUR_POS_MASK)
+#define LCD_TEXT_POS(x)                ((x) | LCD_TEXT_MODE)
+
+static inline void lcd_write_control(struct fb_info *info, u8 control)
+{
+       writel((u32)control << 24, info->screen_base);
+}
+
+static inline u8 lcd_read_control(struct fb_info *info)
+{
+       return readl(info->screen_base) >> 24;
+}
+
+static inline void lcd_write_data(struct fb_info *info, u8 data)
+{
+       writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET);
+}
+
+static inline u8 lcd_read_data(struct fb_info *info)
+{
+       return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24;
+}
+
+static int lcd_busy_wait(struct fb_info *info)
+{
+       u8 val = 0;
+       int timeout = 10, retval = 0;
+
+       do {
+               val = lcd_read_control(info);
+               val &= LCD_BUSY;
+               if (val != LCD_BUSY)
+                       break;
+
+               if (msleep_interruptible(1))
+                       return -EINTR;
+
+               timeout--;
+       } while (timeout);
+
+       if (val == LCD_BUSY)
+               retval = -EBUSY;
+
+       return retval;
+}
+
+static void lcd_clear(struct fb_info *info)
+{
+       int i;
+
+       for (i = 0; i < 4; i++) {
+               udelay(150);
+
+               lcd_write_control(info, LCD_PRERESET);
+       }
+
+       udelay(150);
+
+       lcd_write_control(info, LCD_CLEAR);
+
+       udelay(150);
+
+       lcd_write_control(info, LCD_RESET);
+}
+
+static struct fb_fix_screeninfo cobalt_lcdfb_fix __initdata = {
+       .id             = "cobalt-lcd",
+       .type           = FB_TYPE_TEXT,
+       .type_aux       = FB_AUX_TEXT_MDA,
+       .visual         = FB_VISUAL_MONO01,
+       .line_length    = LCD_XRES_MAX,
+       .accel          = FB_ACCEL_NONE,
+};
+
+static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       char src[LCD_CHARS_MAX];
+       unsigned long pos;
+       int len, retval = 0;
+
+       pos = *ppos;
+       if (pos >= LCD_CHARS_MAX || count == 0)
+               return 0;
+
+       if (count > LCD_CHARS_MAX)
+               count = LCD_CHARS_MAX;
+
+       if (pos + count > LCD_CHARS_MAX)
+               count = LCD_CHARS_MAX - pos;
+
+       for (len = 0; len < count; len++) {
+               retval = lcd_busy_wait(info);
+               if (retval < 0)
+                       break;
+
+               lcd_write_control(info, LCD_TEXT_POS(pos));
+
+               retval = lcd_busy_wait(info);
+               if (retval < 0)
+                       break;
+
+               src[len] = lcd_read_data(info);
+               if (pos == 0x0f)
+                       pos = 0x40;
+               else
+                       pos++;
+       }
+
+       if (retval < 0 && signal_pending(current))
+               return -ERESTARTSYS;
+
+       if (copy_to_user(buf, src, len))
+               return -EFAULT;
+
+       *ppos += len;
+
+       return len;
+}
+
+static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf,
+                                 size_t count, loff_t *ppos)
+{
+       char dst[LCD_CHARS_MAX];
+       unsigned long pos;
+       int len, retval = 0;
+
+       pos = *ppos;
+       if (pos >= LCD_CHARS_MAX || count == 0)
+               return 0;
+
+       if (count > LCD_CHARS_MAX)
+               count = LCD_CHARS_MAX;
+
+       if (pos + count > LCD_CHARS_MAX)
+               count = LCD_CHARS_MAX - pos;
+
+       if (copy_from_user(dst, buf, count))
+               return -EFAULT;
+
+       for (len = 0; len < count; len++) {
+               retval = lcd_busy_wait(info);
+               if (retval < 0)
+                       break;
+
+               lcd_write_control(info, LCD_TEXT_POS(pos));
+
+               retval = lcd_busy_wait(info);
+               if (retval < 0)
+                       break;
+
+               lcd_write_data(info, dst[len]);
+               if (pos == 0x0f)
+                       pos = 0x40;
+               else
+                       pos++;
+       }
+
+       if (retval < 0 && signal_pending(current))
+               return -ERESTARTSYS;
+
+       *ppos += len;
+
+       return len;
+}
+
+static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info)
+{
+       int retval;
+
+       retval = lcd_busy_wait(info);
+       if (retval < 0)
+               return retval;
+
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               lcd_write_control(info, LCD_ON);
+               break;
+       default:
+               lcd_write_control(info, LCD_OFF);
+               break;
+       }
+
+       return 0;
+}
+
+static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+       u32 x, y;
+       int retval;
+
+       switch (cursor->set) {
+       case FB_CUR_SETPOS:
+               x = cursor->image.dx;
+               y = cursor->image.dy;
+               if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX)
+                       return -EINVAL;
+
+               retval = lcd_busy_wait(info);
+               if (retval < 0)
+                       return retval;
+
+               lcd_write_control(info,
+                                 LCD_TEXT_POS(info->fix.line_length * y + x));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       retval = lcd_busy_wait(info);
+       if (retval < 0)
+               return retval;
+
+       if (cursor->enable)
+               lcd_write_control(info, LCD_CURSOR_ON);
+       else
+               lcd_write_control(info, LCD_CURSOR_OFF);
+
+       return 0;
+}
+
+static struct fb_ops cobalt_lcd_fbops = {
+       .owner          = THIS_MODULE,
+       .fb_read        = cobalt_lcdfb_read,
+       .fb_write       = cobalt_lcdfb_write,
+       .fb_blank       = cobalt_lcdfb_blank,
+       .fb_cursor      = cobalt_lcdfb_cursor,
+};
+
+static int __init cobalt_lcdfb_probe(struct platform_device *dev)
+{
+       struct fb_info *info;
+       struct resource *res;
+       int retval;
+
+       info = framebuffer_alloc(0, &dev->dev);
+       if (!info)
+               return -ENOMEM;
+
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (!res) {
+               framebuffer_release(info);
+               return -EBUSY;
+       }
+
+       info->screen_size = res->end - res->start + 1;
+       info->screen_base = ioremap(res->start, info->screen_size);
+       info->fbops = &cobalt_lcd_fbops;
+       info->fix = cobalt_lcdfb_fix;
+       info->fix.smem_start = res->start;
+       info->fix.smem_len = info->screen_size;
+       info->pseudo_palette = NULL;
+       info->par = NULL;
+       info->flags = FBINFO_DEFAULT;
+
+       retval = register_framebuffer(info);
+       if (retval < 0) {
+               iounmap(info->screen_base);
+               framebuffer_release(info);
+               return retval;
+       }
+
+       platform_set_drvdata(dev, info);
+
+       lcd_clear(info);
+
+       printk(KERN_INFO "fb%d: Cobalt server LCD frame buffer device\n",
+               info->node);
+
+       return 0;
+}
+
+static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
+{
+       struct fb_info *info;
+
+       info = platform_get_drvdata(dev);
+       if (info) {
+               iounmap(info->screen_base);
+               unregister_framebuffer(info);
+               framebuffer_release(info);
+       }
+
+       return 0;
+}
+
+static struct platform_driver cobalt_lcdfb_driver = {
+       .probe  = cobalt_lcdfb_probe,
+       .remove = __devexit_p(cobalt_lcdfb_remove),
+       .driver = {
+               .name   = "cobalt-lcd",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init cobalt_lcdfb_init(void)
+{
+       return platform_driver_register(&cobalt_lcdfb_driver);
+}
+
+static void __exit cobalt_lcdfb_exit(void)
+{
+       platform_driver_unregister(&cobalt_lcdfb_driver);
+}
+
+module_init(cobalt_lcdfb_init);
+module_exit(cobalt_lcdfb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Yoichi Yuasa");
+MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver");
index 4be3b46c069be3e33853fc7dd4b83023576eb8f1..3ccfa76d9b2a0c7f523dcb6e37dc10ad3fac59ea 100644 (file)
@@ -107,9 +107,7 @@ static struct display fb_display[MAX_NR_CONSOLES];
 
 static signed char con2fb_map[MAX_NR_CONSOLES];
 static signed char con2fb_map_boot[MAX_NR_CONSOLES];
-#ifndef MODULE
-static int logo_height;
-#endif
+
 static int logo_lines;
 /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
    enums.  */
@@ -607,6 +605,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
        struct fbcon_ops *ops = info->fbcon_par;
        int cnt, erase = vc->vc_video_erase_char, step;
        unsigned short *save = NULL, *r, *q;
+       int logo_height;
 
        if (info->flags & FBINFO_MODULE) {
                logo_shown = FBCON_LOGO_DONTSHOW;
index 0135e03954562713a83b8839b3cd4f57fc21de3b..de1b1365279b90dcafc6dd34ab804e7b7d33ab49 100644 (file)
@@ -92,7 +92,7 @@ struct fbcon_ops {
 #define attr_fgcol(fgshift,s)    \
        (((s) >> (fgshift)) & 0x0f)
 #define attr_bgcol(bgshift,s)    \
-       (((s) >> (bgshift)) & 0x0f)
+       (((s) >> (bgshift)) & 0x07)
 
 /* Monochrome */
 #define attr_bold(s) \
@@ -146,10 +146,8 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
        return is_fg ? fg : bg;
 }
 
-#define attr_bgcol_ec(bgshift,vc,info)         \
-       attr_col_ec(bgshift,vc,info,0);
-#define attr_fgcol_ec(fgshift,vc,info)         \
-       attr_col_ec(fgshift,vc,info,1);
+#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0)
+#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1)
 
 /* Font */
 #define REFCOUNT(fd)   (((int *)(fd))[-1])
index 38a296bbdfc97a9a67ba1c0d74d2a81357698989..9901064199bd165599a163deacf45737f7d210c2 100644 (file)
@@ -71,13 +71,15 @@ static char *mda_type_name;
 
 /* console information */
 
-static int     mda_first_vc = 1;
+static int     mda_first_vc = 13;
 static int     mda_last_vc  = 16;
 
 static struct vc_data  *mda_display_fg = NULL;
 
 module_param(mda_first_vc, int, 0);
+MODULE_PARM_DESC(mda_first_vc, "First virtual console. Default: 13");
 module_param(mda_last_vc, int, 0);
+MODULE_PARM_DESC(mda_last_vc, "Last virtual console. Default: 16");
 
 /* MDA register values
  */
index a11cc2fdd4cd5eb59eb714652b108c3f825b507c..4055dbdd1b428e0dd978704204e0b182f364301d 100644 (file)
@@ -370,7 +370,7 @@ static const struct consw sti_con = {
 
 
 
-int __init sticonsole_init(void)
+static int __init sticonsole_init(void)
 {
     /* already initialized ? */
     if (sticon_sti)
index e9ab657f0bb795634b21e5bc57217dfb560c56a3..d7822af0e00a2353b6b2fe75e40c5e8513902e73 100644 (file)
@@ -29,7 +29,7 @@
 
 #define STI_DRIVERVERSION "Version 0.9a"
 
-struct sti_struct *default_sti __read_mostly;
+static struct sti_struct *default_sti __read_mostly;
 
 /* number of STI ROMS found and their ptrs to each struct */
 static int num_sti_roms __read_mostly;
@@ -68,8 +68,7 @@ static const struct sti_init_flags default_init_flags = {
        .init_cmap_tx = 1,
 };
 
-int
-sti_init_graph(struct sti_struct *sti) 
+static int sti_init_graph(struct sti_struct *sti)
 {
        struct sti_init_inptr_ext inptr_ext = { 0, };
        struct sti_init_inptr inptr = {
@@ -100,8 +99,7 @@ static const struct sti_conf_flags default_conf_flags = {
        .wait   = STI_WAIT,
 };
 
-void
-sti_inq_conf(struct sti_struct *sti)
+static void sti_inq_conf(struct sti_struct *sti)
 {
        struct sti_conf_inptr inptr = { 0, };
        unsigned long flags;
@@ -237,8 +235,8 @@ static void sti_flush(unsigned long start, unsigned long end)
        flush_icache_range(start, end);
 }
 
-void __devinit
-sti_rom_copy(unsigned long base, unsigned long count, void *dest)
+static void __devinit sti_rom_copy(unsigned long base, unsigned long count,
+                                  void *dest)
 {
        unsigned long dest_start = (unsigned long) dest;
 
@@ -478,8 +476,8 @@ sti_init_glob_cfg(struct sti_struct *sti,
 }
 
 #ifdef CONFIG_FB
-struct sti_cooked_font * __devinit
-sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
+static struct sti_cooked_font __devinit
+*sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
 {
        const struct font_desc *fbfont;
        unsigned int size, bpc;
@@ -534,16 +532,16 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
        return cooked_font;
 }
 #else
-struct sti_cooked_font * __devinit
-sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
+static struct sti_cooked_font __devinit
+*sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
 {
        return NULL;
 }
 #endif
 
-struct sti_cooked_font * __devinit
-sti_select_font(struct sti_cooked_rom *rom,
-           int (*search_font_fnc) (struct sti_cooked_rom *,int,int) )
+static struct sti_cooked_font __devinit
+*sti_select_font(struct sti_cooked_rom *rom,
+                int (*search_font_fnc)(struct sti_cooked_rom *, int, int))
 {
        struct sti_cooked_font *font;
        int i;
@@ -707,8 +705,7 @@ sti_get_bmode_rom (unsigned long address)
        return raw;
 }
 
-struct sti_rom * __devinit
-sti_get_wmode_rom (unsigned long address)
+static struct sti_rom __devinit *sti_get_wmode_rom(unsigned long address)
 {
        struct sti_rom *raw;
        unsigned long size;
@@ -723,8 +720,8 @@ sti_get_wmode_rom (unsigned long address)
        return raw;
 }
 
-int __devinit
-sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
+static int __devinit sti_read_rom(int wordmode, struct sti_struct *sti,
+                                 unsigned long address)
 {
        struct sti_cooked_rom *cooked;
        struct sti_rom *raw = NULL;
index 1cd5071e53621f26a1cfe77b784a9dd8da725799..6b487801eeaedc96e8b65a330363156e32452f6c 100644 (file)
@@ -848,9 +848,8 @@ int
 fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
 {
        struct fb_fix_screeninfo *fix = &info->fix;
-        int xoffset = var->xoffset;
-        int yoffset = var->yoffset;
-        int err = 0, yres = info->var.yres;
+       unsigned int yres = info->var.yres;
+       int err = 0;
 
        if (var->yoffset > 0) {
                if (var->vmode & FB_VMODE_YWRAP) {
@@ -866,8 +865,8 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
                                 (var->xoffset % fix->xpanstep)))
                err = -EINVAL;
 
-        if (err || !info->fbops->fb_pan_display || xoffset < 0 ||
-           yoffset < 0 || var->yoffset + yres > info->var.yres_virtual ||
+       if (err || !info->fbops->fb_pan_display ||
+           var->yoffset + yres > info->var.yres_virtual ||
            var->xoffset + info->var.xres > info->var.xres_virtual)
                return -EINVAL;
 
index 052e180584987260a19a96a2e253b768af71f11e..6a0aa180c266e0b3d03e8cc2a4dc890f1605d329 100644 (file)
@@ -879,7 +879,7 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
                if (edid_is_timing_block(block)) {
                        var->xres = var->xres_virtual = H_ACTIVE;
                        var->yres = var->yres_virtual = V_ACTIVE;
-                       var->height = var->width = -1;
+                       var->height = var->width = 0;
                        var->right_margin = H_SYNC_OFFSET;
                        var->left_margin = (H_ACTIVE + H_BLANKING) -
                                (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
index 09d7e22c6fefa3ee277cba3d5c85191dddc86ecb..9cd36c223d334c05768b61c055ac8e1b16d81cb0 100644 (file)
@@ -279,58 +279,42 @@ static struct diu_hw dr = {
 
 static struct diu_pool pool;
 
-/*     To allocate memory for framebuffer. First try __get_free_pages(). If it
- *     fails, try rh_alloc. The reason is __get_free_pages() cannot allocate
- *     very large memory (more than 4MB). We don't want to allocate all memory
- *     in rheap since small memory allocation/deallocation will fragment the
- *     rheap and make the furture large allocation fail.
+/**
+ * fsl_diu_alloc - allocate memory for the DIU
+ * @size: number of bytes to allocate
+ * @param: returned physical address of memory
+ *
+ * This function allocates a physically-contiguous block of memory.
  */
-
-static void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
+static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
 {
        void *virt;
 
-       pr_debug("size=%lu\n", size);
+       pr_debug("size=%zu\n", size);
 
-       virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size));
+       virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
        if (virt) {
                *phys = virt_to_phys(virt);
-               pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys);
-               return virt;
-       }
-       if (!diu_ops.diu_mem) {
-               printk(KERN_INFO "%s: no diu_mem."
-                       " To reserve more memory, put 'diufb=15M' "
-                       "in the command line\n", __func__);
-               return NULL;
-       }
-
-       virt = (void *)rh_alloc(&diu_ops.diu_rh_info, size, "DIU");
-       if (virt) {
-               *phys = virt_to_bus(virt);
-               memset(virt, 0, size);
+               pr_debug("virt=%p phys=%llx\n", virt,
+                       (unsigned long long)*phys);
        }
 
-       pr_debug("rh virt=%p phys=%llx\n", virt, (unsigned long long)*phys);
-
        return virt;
 }
 
-static void fsl_diu_free(void *p, unsigned long size)
+/**
+ * fsl_diu_free - release DIU memory
+ * @virt: pointer returned by fsl_diu_alloc()
+ * @size: number of bytes allocated by fsl_diu_alloc()
+ *
+ * This function releases memory allocated by fsl_diu_alloc().
+ */
+static void fsl_diu_free(void *virt, size_t size)
 {
-       pr_debug("p=%p size=%lu\n", p, size);
+       pr_debug("virt=%p size=%zu\n", virt, size);
 
-       if (!p)
-               return;
-
-       if ((p >= diu_ops.diu_mem) &&
-           (p < (diu_ops.diu_mem + diu_ops.diu_size))) {
-               pr_debug("rh\n");
-               rh_free(&diu_ops.diu_rh_info, (unsigned long) p);
-       } else {
-               pr_debug("dma\n");
-               free_pages((unsigned long)p, get_order(size));
-       }
+       if (virt && size)
+               free_pages_exact(virt, size);
 }
 
 static int fsl_diu_enable_panel(struct fb_info *info)
index 3b9416f4ee20fba2143169e97b886633e4d63fa5..6a51448fd3f74d53cf4880a9a22ff71062ea18d3 100644 (file)
@@ -51,8 +51,6 @@ static inline unsigned int lx_get_pitch(unsigned int xres, int bpp)
 }
 
 void lx_set_mode(struct fb_info *);
-void lx_get_gamma(struct fb_info *, unsigned int *, int);
-void lx_set_gamma(struct fb_info *, unsigned int *, int);
 unsigned int lx_framebuffer_size(void);
 int lx_blank_display(struct fb_info *, int);
 void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
index aaef9165ec9bf09f8dcb00dc71a61b29b47a647f..b1cd49c9935618a6af9db4602021f41e8aaf23d4 100644 (file)
@@ -517,25 +517,25 @@ void lx_set_palette_reg(struct fb_info *info, unsigned regno,
 int lx_blank_display(struct fb_info *info, int blank_mode)
 {
        struct lxfb_par *par = info->par;
-       u32 dcfg, fp_pm;
-       int blank, hsync, vsync, crt;
+       u32 dcfg, misc, fp_pm;
+       int blank, hsync, vsync;
 
        /* CRT power saving modes. */
        switch (blank_mode) {
        case FB_BLANK_UNBLANK:
-               blank = 0; hsync = 1; vsync = 1; crt = 1;
+               blank = 0; hsync = 1; vsync = 1;
                break;
        case FB_BLANK_NORMAL:
-               blank = 1; hsync = 1; vsync = 1; crt = 1;
+               blank = 1; hsync = 1; vsync = 1;
                break;
        case FB_BLANK_VSYNC_SUSPEND:
-               blank = 1; hsync = 1; vsync = 0; crt = 1;
+               blank = 1; hsync = 1; vsync = 0;
                break;
        case FB_BLANK_HSYNC_SUSPEND:
-               blank = 1; hsync = 0; vsync = 1; crt = 1;
+               blank = 1; hsync = 0; vsync = 1;
                break;
        case FB_BLANK_POWERDOWN:
-               blank = 1; hsync = 0; vsync = 0; crt = 0;
+               blank = 1; hsync = 0; vsync = 0;
                break;
        default:
                return -EINVAL;
@@ -545,15 +545,23 @@ int lx_blank_display(struct fb_info *info, int blank_mode)
        dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
                        VP_DCFG_CRT_EN);
        if (!blank)
-               dcfg |= VP_DCFG_DAC_BL_EN;
+               dcfg |= VP_DCFG_DAC_BL_EN | VP_DCFG_CRT_EN;
        if (hsync)
                dcfg |= VP_DCFG_HSYNC_EN;
        if (vsync)
                dcfg |= VP_DCFG_VSYNC_EN;
-       if (crt)
-               dcfg |= VP_DCFG_CRT_EN;
+
        write_vp(par, VP_DCFG, dcfg);
 
+       misc = read_vp(par, VP_MISC);
+
+       if (vsync && hsync)
+               misc &= ~VP_MISC_DACPWRDN;
+       else
+               misc |= VP_MISC_DACPWRDN;
+
+       write_vp(par, VP_MISC, misc);
+
        /* Power on/off flat panel */
 
        if (par->output & OUTPUT_PANEL) {
index c18880d9db1fd677150cd217a712a7813914ac45..0129c044f6d68ac5ffe6dea92021843c00313311 100644 (file)
@@ -551,7 +551,7 @@ static struct fb_ops hgafb_ops = {
         *  Initialization
         */
 
-static int __init hgafb_probe(struct device *device)
+static int __init hgafb_probe(struct platform_device *pdev)
 {
        struct fb_info *info;
 
@@ -565,7 +565,7 @@ static int __init hgafb_probe(struct device *device)
        printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
                hga_type_name, hga_vram_len/1024);
 
-       info = framebuffer_alloc(0, NULL);
+       info = framebuffer_alloc(0, &pdev->dev);
        if (!info) {
                iounmap(hga_vram);
                return -ENOMEM;
@@ -593,13 +593,13 @@ static int __init hgafb_probe(struct device *device)
 
         printk(KERN_INFO "fb%d: %s frame buffer device\n",
                info->node, info->fix.id);
-       dev_set_drvdata(device, info);
+       platform_set_drvdata(pdev, info);
        return 0;
 }
 
-static int hgafb_remove(struct device *device)
+static int hgafb_remove(struct platform_device *pdev)
 {
-       struct fb_info *info = dev_get_drvdata(device);
+       struct fb_info *info = platform_get_drvdata(pdev);
 
        hga_txt_mode();
        hga_clear_screen();
@@ -620,16 +620,15 @@ static int hgafb_remove(struct device *device)
        return 0;
 }
 
-static struct device_driver hgafb_driver = {
-       .name = "hgafb",
-       .bus  = &platform_bus_type,
+static struct platform_driver hgafb_driver = {
        .probe = hgafb_probe,
        .remove = hgafb_remove,
+       .driver = {
+               .name = "hgafb",
+       },
 };
 
-static struct platform_device hgafb_device = {
-       .name = "hgafb",
-};
+static struct platform_device *hgafb_device;
 
 static int __init hgafb_init(void)
 {
@@ -638,12 +637,15 @@ static int __init hgafb_init(void)
        if (fb_get_options("hgafb", NULL))
                return -ENODEV;
 
-       ret = driver_register(&hgafb_driver);
+       ret = platform_driver_register(&hgafb_driver);
 
        if (!ret) {
-               ret = platform_device_register(&hgafb_device);
-               if (ret)
-                       driver_unregister(&hgafb_driver);
+               hgafb_device = platform_device_register_simple("hgafb", 0, NULL, 0);
+
+               if (IS_ERR(hgafb_device)) {
+                       platform_driver_unregister(&hgafb_driver);
+                       ret = PTR_ERR(hgafb_device);
+               }
        }
 
        return ret;
@@ -651,8 +653,8 @@ static int __init hgafb_init(void)
 
 static void __exit hgafb_exit(void)
 {
-       platform_device_unregister(&hgafb_device);
-       driver_unregister(&hgafb_driver);
+       platform_device_unregister(hgafb_device);
+       platform_driver_unregister(&hgafb_driver);
 }
 
 /* -------------------------------------------------------------------------
index 94e4d3ac1a05b3a265b9d86aecdf3d94025b96b6..0c5a475c1caecfe4545218b985932bfb35997e4b 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/fb.h>
 #include <linux/delay.h>
 #include <linux/init.h>
index aa8c714d62456904acdd937329517cb9330e406b..b790ddff76f9f5f91d70dd181f69699d0f4b613b 100644 (file)
@@ -596,7 +596,7 @@ static struct fb_ops macfb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-void __init macfb_setup(char *options)
+static void __init macfb_setup(char *options)
 {
        char *this_opt;
        
index 5246b0402d76ce7bedd9504c460b34a36bcca9b2..25172b2a2a941e15fe684e9130293c019467981d 100644 (file)
@@ -201,7 +201,6 @@ static int neoFindMode(int xres, int yres, int depth)
  *
  * Determine the closest clock frequency to the one requested.
  */
-#define REF_FREQ 0xe517                /* 14.31818 in 20.12 fixed point */
 #define MAX_N 127
 #define MAX_D 31
 #define MAX_F 1
@@ -211,27 +210,24 @@ static void neoCalcVCLK(const struct fb_info *info,
 {
        int n, d, f;
        int n_best = 0, d_best = 0, f_best = 0;
-       long f_best_diff = (0x7ffff << 12);     /* 20.12 */
-       long f_target = (freq << 12) / 1000;    /* 20.12 */
+       long f_best_diff = 0x7ffff;
 
        for (f = 0; f <= MAX_F; f++)
-               for (n = 0; n <= MAX_N; n++)
-                       for (d = 0; d <= MAX_D; d++) {
-                               long f_out;     /* 20.12 */
-                               long f_diff;    /* 20.12 */
-
-                               f_out =
-                                   ((((n + 1) << 12) / ((d +
-                                                         1) *
-                                                        (1 << f))) >> 12)
-                                   * REF_FREQ;
-                               f_diff = abs(f_out - f_target);
-                               if (f_diff < f_best_diff) {
+               for (d = 0; d <= MAX_D; d++)
+                       for (n = 0; n <= MAX_N; n++) {
+                               long f_out;
+                               long f_diff;
+
+                               f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
+                               f_diff = abs(f_out - freq);
+                               if (f_diff <= f_best_diff) {
                                        f_best_diff = f_diff;
                                        n_best = n;
                                        d_best = d;
                                        f_best = f;
                                }
+                               if (f_out > freq)
+                                       break;
                        }
 
        if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
@@ -248,11 +244,11 @@ static void neoCalcVCLK(const struct fb_info *info,
        par->VCLK3Denominator = d_best;
 
 #ifdef NEOFB_DEBUG
-       printk("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n",
-              f_target >> 12,
+       printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
+              freq,
               par->VCLK3NumeratorLow,
               par->VCLK3NumeratorHigh,
-              par->VCLK3Denominator, f_best_diff >> 12);
+              par->VCLK3Denominator, f_best_diff);
 #endif
 }
 
@@ -263,15 +259,20 @@ static void neoCalcVCLK(const struct fb_info *info,
  */
 
 static int vgaHWInit(const struct fb_var_screeninfo *var,
-                    const struct fb_info *info,
-                    struct neofb_par *par, struct xtimings *timings)
+                    struct neofb_par *par)
 {
+       int hsync_end = var->xres + var->right_margin + var->hsync_len;
+       int htotal = (hsync_end + var->left_margin) >> 3;
+       int vsync_start = var->yres + var->lower_margin;
+       int vsync_end = vsync_start + var->vsync_len;
+       int vtotal = vsync_end + var->upper_margin;
+
        par->MiscOutReg = 0x23;
 
-       if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
+       if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
                par->MiscOutReg |= 0x40;
 
-       if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
+       if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
                par->MiscOutReg |= 0x80;
 
        /*
@@ -286,25 +287,25 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
        /*
         * CRTC Controller
         */
-       par->CRTC[0] = (timings->HTotal >> 3) - 5;
-       par->CRTC[1] = (timings->HDisplay >> 3) - 1;
-       par->CRTC[2] = (timings->HDisplay >> 3) - 1;
-       par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80;
-       par->CRTC[4] = (timings->HSyncStart >> 3);
-       par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2)
-           | (((timings->HSyncEnd >> 3)) & 0x1F);
-       par->CRTC[6] = (timings->VTotal - 2) & 0xFF;
-       par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8)
-           | (((timings->VDisplay - 1) & 0x100) >> 7)
-           | ((timings->VSyncStart & 0x100) >> 6)
-           | (((timings->VDisplay - 1) & 0x100) >> 5)
-           | 0x10 | (((timings->VTotal - 2) & 0x200) >> 4)
-           | (((timings->VDisplay - 1) & 0x200) >> 3)
-           | ((timings->VSyncStart & 0x200) >> 2);
+       par->CRTC[0] = htotal - 5;
+       par->CRTC[1] = (var->xres >> 3) - 1;
+       par->CRTC[2] = (var->xres >> 3) - 1;
+       par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
+       par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
+       par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
+           | (((hsync_end >> 3)) & 0x1F);
+       par->CRTC[6] = (vtotal - 2) & 0xFF;
+       par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
+           | (((var->yres - 1) & 0x100) >> 7)
+           | ((vsync_start & 0x100) >> 6)
+           | (((var->yres - 1) & 0x100) >> 5)
+           | 0x10 | (((vtotal - 2) & 0x200) >> 4)
+           | (((var->yres - 1) & 0x200) >> 3)
+           | ((vsync_start & 0x200) >> 2);
        par->CRTC[8] = 0x00;
-       par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40;
+       par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
 
-       if (timings->dblscan)
+       if (var->vmode & FB_VMODE_DOUBLE)
                par->CRTC[9] |= 0x80;
 
        par->CRTC[10] = 0x00;
@@ -313,13 +314,13 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
        par->CRTC[13] = 0x00;
        par->CRTC[14] = 0x00;
        par->CRTC[15] = 0x00;
-       par->CRTC[16] = timings->VSyncStart & 0xFF;
-       par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20;
-       par->CRTC[18] = (timings->VDisplay - 1) & 0xFF;
+       par->CRTC[16] = vsync_start & 0xFF;
+       par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
+       par->CRTC[18] = (var->yres - 1) & 0xFF;
        par->CRTC[19] = var->xres_virtual >> 4;
        par->CRTC[20] = 0x00;
-       par->CRTC[21] = (timings->VDisplay - 1) & 0xFF;
-       par->CRTC[22] = (timings->VTotal - 1) & 0xFF;
+       par->CRTC[21] = (var->yres - 1) & 0xFF;
+       par->CRTC[22] = (vtotal - 1) & 0xFF;
        par->CRTC[23] = 0xC3;
        par->CRTC[24] = 0xFF;
 
@@ -483,7 +484,8 @@ static inline int neo2200_sync(struct fb_info *info)
 {
        struct neofb_par *par = info->par;
 
-       while (readl(&par->neo2200->bltStat) & 1);
+       while (readl(&par->neo2200->bltStat) & 1)
+               cpu_relax();
        return 0;
 }
 
@@ -591,34 +593,14 @@ static int
 neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
        struct neofb_par *par = info->par;
-       unsigned int pixclock = var->pixclock;
-       struct xtimings timings;
        int memlen, vramlen;
        int mode_ok = 0;
 
        DBG("neofb_check_var");
 
-       if (!pixclock)
-               pixclock = 10000;       /* 10ns = 100MHz */
-       timings.pixclock = 1000000000 / pixclock;
-       if (timings.pixclock < 1)
-               timings.pixclock = 1;
-
-       if (timings.pixclock > par->maxClock)
+       if (PICOS2KHZ(var->pixclock) > par->maxClock)
                return -EINVAL;
 
-       timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
-       timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
-       timings.HDisplay = var->xres;
-       timings.HSyncStart = timings.HDisplay + var->right_margin;
-       timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
-       timings.HTotal = timings.HSyncEnd + var->left_margin;
-       timings.VDisplay = var->yres;
-       timings.VSyncStart = timings.VDisplay + var->lower_margin;
-       timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
-       timings.VTotal = timings.VSyncEnd + var->upper_margin;
-       timings.sync = var->sync;
-
        /* Is the mode larger than the LCD panel? */
        if (par->internal_display &&
             ((var->xres > par->NeoPanelWidth) ||
@@ -759,11 +741,11 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 static int neofb_set_par(struct fb_info *info)
 {
        struct neofb_par *par = info->par;
-       struct xtimings timings;
        unsigned char temp;
        int i, clock_hi = 0;
        int lcd_stretch;
        int hoffset, voffset;
+       int vsync_start, vtotal;
 
        DBG("neofb_set_par");
 
@@ -771,28 +753,15 @@ static int neofb_set_par(struct fb_info *info)
 
        vgaHWProtect(1);        /* Blank the screen */
 
-       timings.dblscan = info->var.vmode & FB_VMODE_DOUBLE;
-       timings.interlaced = info->var.vmode & FB_VMODE_INTERLACED;
-       timings.HDisplay = info->var.xres;
-       timings.HSyncStart = timings.HDisplay + info->var.right_margin;
-       timings.HSyncEnd = timings.HSyncStart + info->var.hsync_len;
-       timings.HTotal = timings.HSyncEnd + info->var.left_margin;
-       timings.VDisplay = info->var.yres;
-       timings.VSyncStart = timings.VDisplay + info->var.lower_margin;
-       timings.VSyncEnd = timings.VSyncStart + info->var.vsync_len;
-       timings.VTotal = timings.VSyncEnd + info->var.upper_margin;
-       timings.sync = info->var.sync;
-       timings.pixclock = PICOS2KHZ(info->var.pixclock);
-
-       if (timings.pixclock < 1)
-               timings.pixclock = 1;
+       vsync_start = info->var.yres + info->var.lower_margin;
+       vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
 
        /*
         * This will allocate the datastructure and initialize all of the
         * generic VGA registers.
         */
 
-       if (vgaHWInit(&info->var, info, par, &timings))
+       if (vgaHWInit(&info->var, par))
                return -EINVAL;
 
        /*
@@ -831,10 +800,10 @@ static int neofb_set_par(struct fb_info *info)
        par->ExtCRTDispAddr = 0x10;
 
        /* Vertical Extension */
-       par->VerticalExt = (((timings.VTotal - 2) & 0x400) >> 10)
-           | (((timings.VDisplay - 1) & 0x400) >> 9)
-           | (((timings.VSyncStart) & 0x400) >> 8)
-           | (((timings.VSyncStart) & 0x400) >> 7);
+       par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
+           | (((info->var.yres - 1) & 0x400) >> 9)
+           | (((vsync_start) & 0x400) >> 8)
+           | (((vsync_start) & 0x400) >> 7);
 
        /* Fast write bursts on unless disabled. */
        if (par->pci_burst)
@@ -995,7 +964,7 @@ static int neofb_set_par(struct fb_info *info)
         * Calculate the VCLK that most closely matches the requested dot
         * clock.
         */
-       neoCalcVCLK(info, par, timings.pixclock);
+       neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
 
        /* Since we program the clocks ourselves, always use VCLK3. */
        par->MiscOutReg |= 0x0C;
@@ -1927,9 +1896,6 @@ static int __devinit neo_init_hw(struct fb_info *info)
        int maxClock = 65000;
        int CursorMem = 1024;
        int CursorOff = 0x100;
-       int linearSize = 1024;
-       int maxWidth = 1024;
-       int maxHeight = 1024;
 
        DBG("neo_init_hw");
 
@@ -1948,81 +1914,52 @@ static int __devinit neo_init_hw(struct fb_info *info)
        case FB_ACCEL_NEOMAGIC_NM2070:
                videoRam = 896;
                maxClock = 65000;
-               CursorMem = 2048;
-               CursorOff = 0x100;
-               linearSize = 1024;
-               maxWidth = 1024;
-               maxHeight = 1024;
                break;
        case FB_ACCEL_NEOMAGIC_NM2090:
        case FB_ACCEL_NEOMAGIC_NM2093:
-               videoRam = 1152;
-               maxClock = 80000;
-               CursorMem = 2048;
-               CursorOff = 0x100;
-               linearSize = 2048;
-               maxWidth = 1024;
-               maxHeight = 1024;
-               break;
        case FB_ACCEL_NEOMAGIC_NM2097:
                videoRam = 1152;
                maxClock = 80000;
-               CursorMem = 1024;
-               CursorOff = 0x100;
-               linearSize = 2048;
-               maxWidth = 1024;
-               maxHeight = 1024;
                break;
        case FB_ACCEL_NEOMAGIC_NM2160:
                videoRam = 2048;
                maxClock = 90000;
-               CursorMem = 1024;
-               CursorOff = 0x100;
-               linearSize = 2048;
-               maxWidth = 1024;
-               maxHeight = 1024;
                break;
        case FB_ACCEL_NEOMAGIC_NM2200:
                videoRam = 2560;
                maxClock = 110000;
-               CursorMem = 1024;
-               CursorOff = 0x1000;
-               linearSize = 4096;
-               maxWidth = 1280;
-               maxHeight = 1024;       /* ???? */
-
-               par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
                break;
        case FB_ACCEL_NEOMAGIC_NM2230:
                videoRam = 3008;
                maxClock = 110000;
-               CursorMem = 1024;
-               CursorOff = 0x1000;
-               linearSize = 4096;
-               maxWidth = 1280;
-               maxHeight = 1024;       /* ???? */
-
-               par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
                break;
        case FB_ACCEL_NEOMAGIC_NM2360:
                videoRam = 4096;
                maxClock = 110000;
-               CursorMem = 1024;
-               CursorOff = 0x1000;
-               linearSize = 4096;
-               maxWidth = 1280;
-               maxHeight = 1024;       /* ???? */
-
-               par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
                break;
        case FB_ACCEL_NEOMAGIC_NM2380:
                videoRam = 6144;
                maxClock = 110000;
+               break;
+       }
+       switch (info->fix.accel) {
+       case FB_ACCEL_NEOMAGIC_NM2070:
+       case FB_ACCEL_NEOMAGIC_NM2090:
+       case FB_ACCEL_NEOMAGIC_NM2093:
+               CursorMem = 2048;
+               CursorOff = 0x100;
+               break;
+       case FB_ACCEL_NEOMAGIC_NM2097:
+       case FB_ACCEL_NEOMAGIC_NM2160:
+               CursorMem = 1024;
+               CursorOff = 0x100;
+               break;
+       case FB_ACCEL_NEOMAGIC_NM2200:
+       case FB_ACCEL_NEOMAGIC_NM2230:
+       case FB_ACCEL_NEOMAGIC_NM2360:
+       case FB_ACCEL_NEOMAGIC_NM2380:
                CursorMem = 1024;
                CursorOff = 0x1000;
-               linearSize = 8192;
-               maxWidth = 1280;
-               maxHeight = 1024;       /* ???? */
 
                par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
                break;
@@ -2036,7 +1973,7 @@ static int __devinit neo_init_hw(struct fb_info *info)
 */
        par->maxClock = maxClock;
        par->cursorOff = CursorOff;
-       return ((videoRam * 1024));
+       return videoRam * 1024;
 }
 
 
index ab32ceb061781fdb1a2c155991ec1b879dc53133..ab77c51fe9d620bc4f41f0816fb4999d7e1bddaf 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
+#include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/clk.h>
 #include <linux/io.h>
index 14d0f7a1114587fd3496918a8495b636d9152059..f85af5c4fa688a2c6d9be356fa6bd974c89a74f7 100644 (file)
@@ -25,6 +25,7 @@
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 #include <linux/platform_device.h>
+#include <linux/mm.h>
 #include <linux/uaccess.h>
 
 #include <asm/mach-types.h>
index 81dbcf53cf0e50536fc8ebc76b87f38c62ba4fcc..fafd0f26b90f78028afff02d220673a588f6252b 100644 (file)
@@ -646,7 +646,7 @@ static int sossi_init(struct omapfb_device *fbdev)
        sossi_write_reg(SOSSI_INIT1_REG, l);
 
        if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq,
-                            IRQT_FALLING,
+                            IRQ_TYPE_EDGE_FALLING,
             "sossi_match", sossi.fbdev->dev)) < 0) {
                dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n");
                goto err;
index bb2514369507aa9171c361472b3ed0add14eff16..69de2fed6c58a1b28979cdd2c27877638e958787 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/fb.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -40,6 +41,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/completion.h>
+#include <linux/mutex.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
@@ -1116,7 +1118,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
 {
        u_int old_state;
 
-       down(&fbi->ctrlr_sem);
+       mutex_lock(&fbi->ctrlr_lock);
 
        old_state = fbi->state;
 
@@ -1204,7 +1206,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
                }
                break;
        }
-       up(&fbi->ctrlr_sem);
+       mutex_unlock(&fbi->ctrlr_lock);
 }
 
 /*
@@ -1334,7 +1336,7 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
                fbi->dma_buff_phys = fbi->map_dma;
                fbi->palette_cpu = (u16 *) fbi->dma_buff->palette;
 
-               pr_debug("pxafb: palette_mem_size = 0x%08lx\n", fbi->palette_size*sizeof(u16));
+               pr_debug("pxafb: palette_mem_size = 0x%08x\n", fbi->palette_size*sizeof(u16));
 
 #ifdef CONFIG_FB_PXA_SMARTPANEL
                fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
@@ -1457,7 +1459,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
 
        init_waitqueue_head(&fbi->ctrlr_wait);
        INIT_WORK(&fbi->task, pxafb_task);
-       init_MUTEX(&fbi->ctrlr_sem);
+       mutex_init(&fbi->ctrlr_lock);
        init_completion(&fbi->disable_done);
 #ifdef CONFIG_FB_PXA_SMARTPANEL
        init_completion(&fbi->command_done);
index 8238dc8264297fb42c1b2b40226fb64edfb53c32..31541b86f13d2d0e509fb9649342fbcb7b666126 100644 (file)
@@ -106,7 +106,7 @@ struct pxafb_info {
 
        volatile u_char         state;
        volatile u_char         task_state;
-       struct semaphore        ctrlr_sem;
+       struct mutex            ctrlr_lock;
        wait_queue_head_t       ctrlr_wait;
        struct work_struct      task;
 
index ab2b2110478bc212a2f274f02bd24358ce371188..78bcdbc3f4841bf5ce1c3bdebb25964d650fbc18 100644 (file)
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/fb.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/mutex.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -1107,7 +1109,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
 {
        u_int old_state;
 
-       down(&fbi->ctrlr_sem);
+       mutex_lock(&fbi->ctrlr_lock);
 
        old_state = fbi->state;
 
@@ -1192,7 +1194,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
                }
                break;
        }
-       up(&fbi->ctrlr_sem);
+       mutex_unlock(&fbi->ctrlr_lock);
 }
 
 /*
@@ -1444,7 +1446,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
 
        init_waitqueue_head(&fbi->ctrlr_wait);
        INIT_WORK(&fbi->task, sa1100fb_task);
-       init_MUTEX(&fbi->ctrlr_sem);
+       mutex_init(&fbi->ctrlr_lock);
 
        return fbi;
 }
index f465b27ed860e610b353a14d5c2953ab1d1aec21..86831db9a042d880886d9bc022ac5d6232087159 100644 (file)
@@ -100,7 +100,7 @@ struct sa1100fb_info {
 
        volatile u_char         state;
        volatile u_char         task_state;
-       struct semaphore        ctrlr_sem;
+       struct mutex            ctrlr_lock;
        wait_queue_head_t       ctrlr_wait;
        struct work_struct      task;
 
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
new file mode 100644 (file)
index 0000000..8d0212d
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ * SH7760/SH7763 LCDC Framebuffer driver.
+ *
+ * (c) 2006-2008 MSC Vertriebsges.m.b.H.,
+ *             Manuel Lauss <mano@roarinelk.homelinux.net>
+ * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.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.
+ *
+ * PLEASE HAVE A LOOK AT Documentation/fb/sh7760fb.txt!
+ *
+ * Thanks to Siegfried Schaefer <s.schaefer at schaefer-edv.de>
+ *     for his original source and testing!
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/sh7760fb.h>
+
+struct sh7760fb_par {
+       void __iomem *base;
+       int irq;
+
+       struct sh7760fb_platdata *pd;   /* display information */
+
+       dma_addr_t fbdma;       /* physical address */
+
+       int rot;                /* rotation enabled? */
+
+       u32 pseudo_palette[16];
+
+       struct platform_device *dev;
+       struct resource *ioarea;
+       struct completion vsync;        /* vsync irq event */
+};
+
+static irqreturn_t sh7760fb_irq(int irq, void *data)
+{
+       struct completion *c = data;
+
+       complete(c);
+
+       return IRQ_HANDLED;
+}
+
+static void sh7760fb_wait_vsync(struct fb_info *info)
+{
+       struct sh7760fb_par *par = info->par;
+
+       if (par->pd->novsync)
+               return;
+
+       iowrite16(ioread16(par->base + LDINTR) & ~VINT_CHECK,
+                 par->base + LDINTR);
+
+       if (par->irq < 0) {
+               /* poll for vert. retrace: status bit is sticky */
+               while (!(ioread16(par->base + LDINTR) & VINT_CHECK))
+                       cpu_relax();
+       } else {
+               /* a "wait_for_irq_event(par->irq)" would be extremely nice */
+               init_completion(&par->vsync);
+               enable_irq(par->irq);
+               wait_for_completion(&par->vsync);
+               disable_irq_nosync(par->irq);
+       }
+}
+
+/* wait_for_lps - wait until power supply has reached a certain state. */
+static int wait_for_lps(struct sh7760fb_par *par, int val)
+{
+       int i = 100;
+       while (--i && ((ioread16(par->base + LDPMMR) & 3) != val))
+               msleep(1);
+
+       if (i <= 0)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+/* en/disable the LCDC */
+static int sh7760fb_blank(int blank, struct fb_info *info)
+{
+       struct sh7760fb_par *par = info->par;
+       struct sh7760fb_platdata *pd = par->pd;
+       unsigned short cntr = ioread16(par->base + LDCNTR);
+       unsigned short intr = ioread16(par->base + LDINTR);
+       int lps;
+
+       if (blank == FB_BLANK_UNBLANK) {
+               intr |= VINT_START;
+               cntr = LDCNTR_DON2 | LDCNTR_DON;
+               lps = 3;
+       } else {
+               intr &= ~VINT_START;
+               cntr = LDCNTR_DON2;
+               lps = 0;
+       }
+
+       if (pd->blank)
+               pd->blank(blank);
+
+       iowrite16(intr, par->base + LDINTR);
+       iowrite16(cntr, par->base + LDCNTR);
+
+       return wait_for_lps(par, lps);
+}
+
+/* set color registers */
+static int sh7760fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+       struct sh7760fb_par *par = info->par;
+       u32 s = cmap->start;
+       u32 l = cmap->len;
+       u16 *r = cmap->red;
+       u16 *g = cmap->green;
+       u16 *b = cmap->blue;
+       u32 col, tmo;
+       int ret;
+
+       ret = 0;
+
+       sh7760fb_wait_vsync(info);
+
+       /* request palette access */
+       iowrite16(LDPALCR_PALEN, par->base + LDPALCR);
+
+       /* poll for access grant */
+       tmo = 100;
+       while (!(ioread16(par->base + LDPALCR) & LDPALCR_PALS) && (--tmo))
+               cpu_relax();
+
+       if (!tmo) {
+               ret = 1;
+               dev_dbg(info->dev, "no palette access!\n");
+               goto out;
+       }
+
+       while (l && (s < 256)) {
+               col = ((*r) & 0xff) << 16;
+               col |= ((*g) & 0xff) << 8;
+               col |= ((*b) & 0xff);
+               col &= SH7760FB_PALETTE_MASK;
+               iowrite32(col, par->base + LDPR(s));
+
+               if (s < 16)
+                       ((u32 *) (info->pseudo_palette))[s] = s;
+
+               s++;
+               l--;
+               r++;
+               g++;
+               b++;
+       }
+out:
+       iowrite16(0, par->base + LDPALCR);
+       return ret;
+}
+
+static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info,
+                      unsigned long stride)
+{
+       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+       strcpy(fix->id, "sh7760-lcdc");
+
+       fix->smem_start = (unsigned long)info->screen_base;
+       fix->smem_len = info->screen_size;
+
+       fix->line_length = stride;
+}
+
+static int sh7760fb_get_color_info(struct device *dev,
+                                  u16 lddfr, int *bpp, int *gray)
+{
+       int lbpp, lgray;
+
+       lgray = lbpp = 0;
+
+       switch (lddfr & LDDFR_COLOR_MASK) {
+       case LDDFR_1BPP_MONO:
+               lgray = 1;
+               lbpp = 1;
+               break;
+       case LDDFR_2BPP_MONO:
+               lgray = 1;
+               lbpp = 2;
+               break;
+       case LDDFR_4BPP_MONO:
+               lgray = 1;
+       case LDDFR_4BPP:
+               lbpp = 4;
+               break;
+       case LDDFR_6BPP_MONO:
+               lgray = 1;
+       case LDDFR_8BPP:
+               lbpp = 8;
+               break;
+       case LDDFR_16BPP_RGB555:
+       case LDDFR_16BPP_RGB565:
+               lbpp = 16;
+               lgray = 0;
+               break;
+       default:
+               dev_dbg(dev, "unsupported LDDFR bit depth.\n");
+               return -EINVAL;
+       }
+
+       if (bpp)
+               *bpp = lbpp;
+       if (gray)
+               *gray = lgray;
+
+       return 0;
+}
+
+static int sh7760fb_check_var(struct fb_var_screeninfo *var,
+                             struct fb_info *info)
+{
+       struct fb_fix_screeninfo *fix = &info->fix;
+       struct sh7760fb_par *par = info->par;
+       int ret, bpp;
+
+       /* get color info from register value */
+       ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
+       if (ret)
+               return ret;
+
+       var->bits_per_pixel = bpp;
+
+       if ((var->grayscale) && (var->bits_per_pixel == 1))
+               fix->visual = FB_VISUAL_MONO10;
+       else if (var->bits_per_pixel >= 15)
+               fix->visual = FB_VISUAL_TRUECOLOR;
+       else
+               fix->visual = FB_VISUAL_PSEUDOCOLOR;
+
+       /* TODO: add some more validation here */
+       return 0;
+}
+
+/*
+ * sh7760fb_set_par - set videomode.
+ *
+ * NOTE: The rotation, grayscale and DSTN codepaths are
+ *     totally untested!
+ */
+static int sh7760fb_set_par(struct fb_info *info)
+{
+       struct sh7760fb_par *par = info->par;
+       struct fb_videomode *vm = par->pd->def_mode;
+       unsigned long sbase, dstn_off, ldsarl, stride;
+       unsigned short hsynp, hsynw, htcn, hdcn;
+       unsigned short vsynp, vsynw, vtln, vdln;
+       unsigned short lddfr, ldmtr;
+       int ret, bpp, gray;
+
+       par->rot = par->pd->rotate;
+
+       /* rotate only works with xres <= 320 */
+       if (par->rot && (vm->xres > 320)) {
+               dev_dbg(info->dev, "rotation disabled due to display size\n");
+               par->rot = 0;
+       }
+
+       /* calculate LCDC reg vals from display parameters */
+       hsynp = vm->right_margin + vm->xres;
+       hsynw = vm->hsync_len;
+       htcn = vm->left_margin + hsynp + hsynw;
+       hdcn = vm->xres;
+       vsynp = vm->lower_margin + vm->yres;
+       vsynw = vm->vsync_len;
+       vtln = vm->upper_margin + vsynp + vsynw;
+       vdln = vm->yres;
+
+       /* get color info from register value */
+       ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, &gray);
+       if (ret)
+               return ret;
+
+       dev_dbg(info->dev, "%dx%d %dbpp %s (orientation %s)\n", hdcn,
+               vdln, bpp, gray ? "grayscale" : "color",
+               par->rot ? "rotated" : "normal");
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+       lddfr = par->pd->lddfr | (1 << 8);
+#else
+       lddfr = par->pd->lddfr & ~(1 << 8);
+#endif
+
+       ldmtr = par->pd->ldmtr;
+
+       if (!(vm->sync & FB_SYNC_HOR_HIGH_ACT))
+               ldmtr |= LDMTR_CL1POL;
+       if (!(vm->sync & FB_SYNC_VERT_HIGH_ACT))
+               ldmtr |= LDMTR_FLMPOL;
+
+       /* shut down LCDC before changing display parameters */
+       sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+
+       iowrite16(par->pd->ldickr, par->base + LDICKR); /* pixclock */
+       iowrite16(ldmtr, par->base + LDMTR);    /* polarities */
+       iowrite16(lddfr, par->base + LDDFR);    /* color/depth */
+       iowrite16((par->rot ? 1 << 13 : 0), par->base + LDSMR); /* rotate */
+       iowrite16(par->pd->ldpmmr, par->base + LDPMMR); /* Power Management */
+       iowrite16(par->pd->ldpspr, par->base + LDPSPR); /* Power Supply Ctrl */
+
+       /* display resolution */
+       iowrite16(((htcn >> 3) - 1) | (((hdcn >> 3) - 1) << 8),
+                 par->base + LDHCNR);
+       iowrite16(vdln - 1, par->base + LDVDLNR);
+       iowrite16(vtln - 1, par->base + LDVTLNR);
+       /* h/v sync signals */
+       iowrite16((vsynp - 1) | ((vsynw - 1) << 12), par->base + LDVSYNR);
+       iowrite16(((hsynp >> 3) - 1) | (((hsynw >> 3) - 1) << 12),
+                 par->base + LDHSYNR);
+       /* AC modulation sig */
+       iowrite16(par->pd->ldaclnr, par->base + LDACLNR);
+
+       stride = (par->rot) ? vtln : hdcn;
+       if (!gray)
+               stride *= (bpp + 7) >> 3;
+       else {
+               if (bpp == 1)
+                       stride >>= 3;
+               else if (bpp == 2)
+                       stride >>= 2;
+               else if (bpp == 4)
+                       stride >>= 1;
+               /* 6 bpp == 8 bpp */
+       }
+
+       /* if rotated, stride must be power of 2 */
+       if (par->rot) {
+               unsigned long bit = 1 << 31;
+               while (bit) {
+                       if (stride & bit)
+                               break;
+                       bit >>= 1;
+               }
+               if (stride & ~bit)
+                       stride = bit << 1;      /* not P-o-2, round up */
+       }
+       iowrite16(stride, par->base + LDLAOR);
+
+       /* set display mem start address */
+       sbase = (unsigned long)par->fbdma;
+       if (par->rot)
+               sbase += (hdcn - 1) * stride;
+
+       iowrite32(sbase, par->base + LDSARU);
+
+       /*
+        * for DSTN need to set address for lower half.
+        * I (mlau) don't know which address to set it to,
+        * so I guessed at (stride * yres/2).
+        */
+       if (((ldmtr & 0x003f) >= LDMTR_DSTN_MONO_8) &&
+           ((ldmtr & 0x003f) <= LDMTR_DSTN_COLOR_16)) {
+
+               dev_dbg(info->dev, " ***** DSTN untested! *****\n");
+
+               dstn_off = stride;
+               if (par->rot)
+                       dstn_off *= hdcn >> 1;
+               else
+                       dstn_off *= vdln >> 1;
+
+               ldsarl = sbase + dstn_off;
+       } else
+               ldsarl = 0;
+
+       iowrite32(ldsarl, par->base + LDSARL);  /* mem for lower half of DSTN */
+
+       encode_fix(&info->fix, info, stride);
+       sh7760fb_check_var(&info->var, info);
+
+       sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */
+
+       dev_dbg(info->dev, "hdcn  : %6d htcn  : %6d\n", hdcn, htcn);
+       dev_dbg(info->dev, "hsynw : %6d hsynp : %6d\n", hsynw, hsynp);
+       dev_dbg(info->dev, "vdln  : %6d vtln  : %6d\n", vdln, vtln);
+       dev_dbg(info->dev, "vsynw : %6d vsynp : %6d\n", vsynw, vsynp);
+       dev_dbg(info->dev, "clksrc: %6d clkdiv: %6d\n",
+               (par->pd->ldickr >> 12) & 3, par->pd->ldickr & 0x1f);
+       dev_dbg(info->dev, "ldpmmr: 0x%04x ldpspr: 0x%04x\n", par->pd->ldpmmr,
+               par->pd->ldpspr);
+       dev_dbg(info->dev, "ldmtr : 0x%04x lddfr : 0x%04x\n", ldmtr, lddfr);
+       dev_dbg(info->dev, "ldlaor: %ld\n", stride);
+       dev_dbg(info->dev, "ldsaru: 0x%08lx ldsarl: 0x%08lx\n", sbase, ldsarl);
+
+       return 0;
+}
+
+static struct fb_ops sh7760fb_ops = {
+       .owner = THIS_MODULE,
+       .fb_blank = sh7760fb_blank,
+       .fb_check_var = sh7760fb_check_var,
+       .fb_setcmap = sh7760fb_setcmap,
+       .fb_set_par = sh7760fb_set_par,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea,
+       .fb_imageblit = cfb_imageblit,
+};
+
+static void sh7760fb_free_mem(struct fb_info *info)
+{
+       struct sh7760fb_par *par = info->par;
+
+       if (!info->screen_base)
+               return;
+
+       dma_free_coherent(info->dev, info->screen_size,
+                         info->screen_base, par->fbdma);
+
+       par->fbdma = 0;
+       info->screen_base = NULL;
+       info->screen_size = 0;
+}
+
+/* allocate the framebuffer memory. This memory must be in Area3,
+ * (dictated by the DMA engine) and contiguous, at a 512 byte boundary.
+ */
+static int sh7760fb_alloc_mem(struct fb_info *info)
+{
+       struct sh7760fb_par *par = info->par;
+       void *fbmem;
+       unsigned long vram;
+       int ret, bpp;
+
+       if (info->screen_base)
+               return 0;
+
+       /* get color info from register value */
+       ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
+       if (ret) {
+               printk(KERN_ERR "colinfo\n");
+               return ret;
+       }
+
+       /* min VRAM: xres_min = 16, yres_min = 1, bpp = 1: 2byte -> 1 page
+          max VRAM: xres_max = 1024, yres_max = 1024, bpp = 16: 2MB */
+
+       vram = info->var.xres * info->var.yres;
+       if (info->var.grayscale) {
+               if (bpp == 1)
+                       vram >>= 3;
+               else if (bpp == 2)
+                       vram >>= 2;
+               else if (bpp == 4)
+                       vram >>= 1;
+       } else if (bpp > 8)
+               vram *= 2;
+       if ((vram < 1) || (vram > 1024 * 2048)) {
+               dev_dbg(info->dev, "too much VRAM required. Check settings\n");
+               return -ENODEV;
+       }
+
+       if (vram < PAGE_SIZE)
+               vram = PAGE_SIZE;
+
+       fbmem = dma_alloc_coherent(info->dev, vram, &par->fbdma, GFP_KERNEL);
+
+       if (!fbmem)
+               return -ENOMEM;
+
+       if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) {
+               sh7760fb_free_mem(info);
+               dev_err(info->dev, "kernel gave me memory at 0x%08lx, which is"
+                       "unusable for the LCDC\n", (unsigned long)par->fbdma);
+               return -ENOMEM;
+       }
+
+       info->screen_base = fbmem;
+       info->screen_size = vram;
+
+       return 0;
+}
+
+static int __devinit sh7760fb_probe(struct platform_device *pdev)
+{
+       struct fb_info *info;
+       struct resource *res;
+       struct sh7760fb_par *par;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (unlikely(res == NULL)) {
+               dev_err(&pdev->dev, "invalid resource\n");
+               return -EINVAL;
+       }
+
+       info = framebuffer_alloc(sizeof(struct sh7760fb_par), &pdev->dev);
+       if (!info)
+               return -ENOMEM;
+
+       par = info->par;
+       par->dev = pdev;
+
+       par->pd = pdev->dev.platform_data;
+       if (!par->pd) {
+               dev_dbg(info->dev, "no display setup data!\n");
+               ret = -ENODEV;
+               goto out_fb;
+       }
+
+       par->ioarea = request_mem_region(res->start,
+                                        (res->end - res->start), pdev->name);
+       if (!par->ioarea) {
+               dev_err(&pdev->dev, "mmio area busy\n");
+               ret = -EBUSY;
+               goto out_fb;
+       }
+
+       par->base = ioremap_nocache(res->start, res->end - res->start + 1);
+       if (!par->base) {
+               dev_err(&pdev->dev, "cannot remap\n");
+               ret = -ENODEV;
+               goto out_res;
+       }
+
+       iowrite16(0, par->base + LDINTR);       /* disable vsync irq */
+       par->irq = platform_get_irq(pdev, 0);
+       if (par->irq >= 0) {
+               ret = request_irq(par->irq, sh7760fb_irq, 0,
+                                 "sh7760-lcdc", &par->vsync);
+               if (ret) {
+                       dev_err(&pdev->dev, "cannot grab IRQ\n");
+                       par->irq = -ENXIO;
+               } else
+                       disable_irq_nosync(par->irq);
+       }
+
+       fb_videomode_to_var(&info->var, par->pd->def_mode);
+
+       ret = sh7760fb_alloc_mem(info);
+       if (ret) {
+               dev_dbg(info->dev, "framebuffer memory allocation failed!\n");
+               goto out_unmap;
+       }
+
+       info->pseudo_palette = par->pseudo_palette;
+
+       /* fixup color register bitpositions. These are fixed by hardware */
+       info->var.red.offset = 11;
+       info->var.red.length = 5;
+       info->var.red.msb_right = 0;
+
+       info->var.green.offset = 5;
+       info->var.green.length = 6;
+       info->var.green.msb_right = 0;
+
+       info->var.blue.offset = 0;
+       info->var.blue.length = 5;
+       info->var.blue.msb_right = 0;
+
+       info->var.transp.offset = 0;
+       info->var.transp.length = 0;
+       info->var.transp.msb_right = 0;
+
+       /* set the DON2 bit now, before cmap allocation, as it will randomize
+        * palette memory.
+        */
+       iowrite16(LDCNTR_DON2, par->base + LDCNTR);
+       info->fbops = &sh7760fb_ops;
+
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (ret) {
+               dev_dbg(info->dev, "Unable to allocate cmap memory\n");
+               goto out_mem;
+       }
+
+       ret = register_framebuffer(info);
+       if (ret < 0) {
+               dev_dbg(info->dev, "cannot register fb!\n");
+               goto out_cmap;
+       }
+       platform_set_drvdata(pdev, info);
+
+       printk(KERN_INFO "%s: memory at phys 0x%08lx-0x%08lx, size %ld KiB\n",
+              pdev->name,
+              (unsigned long)par->fbdma,
+              (unsigned long)(par->fbdma + info->screen_size - 1),
+              info->screen_size >> 10);
+
+       return 0;
+
+out_cmap:
+       sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+       fb_dealloc_cmap(&info->cmap);
+out_mem:
+       sh7760fb_free_mem(info);
+out_unmap:
+       if (par->irq >= 0)
+               free_irq(par->irq, &par->vsync);
+       iounmap(par->base);
+out_res:
+       release_resource(par->ioarea);
+       kfree(par->ioarea);
+out_fb:
+       framebuffer_release(info);
+       return ret;
+}
+
+static int __devexit sh7760fb_remove(struct platform_device *dev)
+{
+       struct fb_info *info = platform_get_drvdata(dev);
+       struct sh7760fb_par *par = info->par;
+
+       sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+       unregister_framebuffer(info);
+       fb_dealloc_cmap(&info->cmap);
+       sh7760fb_free_mem(info);
+       if (par->irq >= 0)
+               free_irq(par->irq, par);
+       iounmap(par->base);
+       release_resource(par->ioarea);
+       kfree(par->ioarea);
+       framebuffer_release(info);
+       platform_set_drvdata(dev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver sh7760_lcdc_driver = {
+       .driver = {
+                  .name = "sh7760-lcdc",
+                  .owner = THIS_MODULE,
+                  },
+       .probe = sh7760fb_probe,
+       .remove = __devexit_p(sh7760fb_remove),
+};
+
+static int __init sh7760fb_init(void)
+{
+       return platform_driver_register(&sh7760_lcdc_driver);
+}
+
+static void __exit sh7760fb_exit(void)
+{
+       platform_driver_unregister(&sh7760_lcdc_driver);
+}
+
+module_init(sh7760fb_init);
+module_exit(sh7760fb_exit);
+
+MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
+MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
new file mode 100644 (file)
index 0000000..f6ef6cc
--- /dev/null
@@ -0,0 +1,725 @@
+/*
+ * SuperH Mobile LCDC Framebuffer
+ *
+ * Copyright (c) 2008 Magnus Damm
+ *
+ * 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/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <asm/sh_mobile_lcdc.h>
+
+#define PALETTE_NR 16
+
+struct sh_mobile_lcdc_priv;
+struct sh_mobile_lcdc_chan {
+       struct sh_mobile_lcdc_priv *lcdc;
+       unsigned long *reg_offs;
+       unsigned long ldmt1r_value;
+       unsigned long enabled; /* ME and SE in LDCNT2R */
+       struct sh_mobile_lcdc_chan_cfg cfg;
+       u32 pseudo_palette[PALETTE_NR];
+       struct fb_info info;
+       dma_addr_t dma_handle;
+};
+
+struct sh_mobile_lcdc_priv {
+       void __iomem *base;
+       struct clk *clk;
+       unsigned long lddckr;
+       struct sh_mobile_lcdc_chan ch[2];
+};
+
+/* shared registers */
+#define _LDDCKR 0x410
+#define _LDDCKSTPR 0x414
+#define _LDINTR 0x468
+#define _LDSR 0x46c
+#define _LDCNT1R 0x470
+#define _LDCNT2R 0x474
+#define _LDDDSR 0x47c
+#define _LDDWD0R 0x800
+#define _LDDRDR 0x840
+#define _LDDWAR 0x900
+#define _LDDRAR 0x904
+
+/* per-channel registers */
+enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
+       LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR };
+
+static unsigned long lcdc_offs_mainlcd[] = {
+       [LDDCKPAT1R] = 0x400,
+       [LDDCKPAT2R] = 0x404,
+       [LDMT1R] = 0x418,
+       [LDMT2R] = 0x41c,
+       [LDMT3R] = 0x420,
+       [LDDFR] = 0x424,
+       [LDSM1R] = 0x428,
+       [LDSA1R] = 0x430,
+       [LDMLSR] = 0x438,
+       [LDHCNR] = 0x448,
+       [LDHSYNR] = 0x44c,
+       [LDVLNR] = 0x450,
+       [LDVSYNR] = 0x454,
+       [LDPMR] = 0x460,
+};
+
+static unsigned long lcdc_offs_sublcd[] = {
+       [LDDCKPAT1R] = 0x408,
+       [LDDCKPAT2R] = 0x40c,
+       [LDMT1R] = 0x600,
+       [LDMT2R] = 0x604,
+       [LDMT3R] = 0x608,
+       [LDDFR] = 0x60c,
+       [LDSM1R] = 0x610,
+       [LDSA1R] = 0x618,
+       [LDMLSR] = 0x620,
+       [LDHCNR] = 0x624,
+       [LDHSYNR] = 0x628,
+       [LDVLNR] = 0x62c,
+       [LDVSYNR] = 0x630,
+       [LDPMR] = 0x63c,
+};
+
+#define START_LCDC     0x00000001
+#define LCDC_RESET     0x00000100
+#define DISPLAY_BEU    0x00000008
+#define LCDC_ENABLE    0x00000001
+
+static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
+                           int reg_nr, unsigned long data)
+{
+       iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
+}
+
+static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
+                                   int reg_nr)
+{
+       return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
+}
+
+static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
+                      unsigned long reg_offs, unsigned long data)
+{
+       iowrite32(data, priv->base + reg_offs);
+}
+
+static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
+                              unsigned long reg_offs)
+{
+       return ioread32(priv->base + reg_offs);
+}
+
+static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
+                         unsigned long reg_offs,
+                         unsigned long mask, unsigned long until)
+{
+       while ((lcdc_read(priv, reg_offs) & mask) != until)
+               cpu_relax();
+}
+
+static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
+{
+       return chan->cfg.chan == LCDC_CHAN_SUBLCD;
+}
+
+static void lcdc_sys_write_index(void *handle, unsigned long data)
+{
+       struct sh_mobile_lcdc_chan *ch = handle;
+
+       lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
+       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+       lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+}
+
+static void lcdc_sys_write_data(void *handle, unsigned long data)
+{
+       struct sh_mobile_lcdc_chan *ch = handle;
+
+       lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
+       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+       lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+}
+
+static unsigned long lcdc_sys_read_data(void *handle)
+{
+       struct sh_mobile_lcdc_chan *ch = handle;
+
+       lcdc_write(ch->lcdc, _LDDRDR, 0x01000000);
+       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+       lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+       udelay(1);
+
+       return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff;
+}
+
+struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
+       lcdc_sys_write_index,
+       lcdc_sys_write_data,
+       lcdc_sys_read_data,
+};
+
+static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
+                                     int start)
+{
+       unsigned long tmp = lcdc_read(priv, _LDCNT2R);
+       int k;
+
+       /* start or stop the lcdc */
+       if (start)
+               lcdc_write(priv, _LDCNT2R, tmp | START_LCDC);
+       else
+               lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC);
+
+       /* wait until power is applied/stopped on all channels */
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
+               if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
+                       while (1) {
+                               tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3;
+                               if (start && tmp == 3)
+                                       break;
+                               if (!start && tmp == 0)
+                                       break;
+                               cpu_relax();
+                       }
+
+       if (!start)
+               lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
+}
+
+static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+{
+       struct sh_mobile_lcdc_chan *ch;
+       struct fb_videomode *lcd_cfg;
+       struct sh_mobile_lcdc_board_cfg *board_cfg;
+       unsigned long tmp;
+       int k, m;
+       int ret = 0;
+
+       /* reset */
+       lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
+       lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
+
+       /* enable LCDC channels */
+       tmp = lcdc_read(priv, _LDCNT2R);
+       tmp |= priv->ch[0].enabled;
+       tmp |= priv->ch[1].enabled;
+       lcdc_write(priv, _LDCNT2R, tmp);
+
+       /* read data from external memory, avoid using the BEU for now */
+       lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
+
+       /* stop the lcdc first */
+       sh_mobile_lcdc_start_stop(priv, 0);
+
+       /* configure clocks */
+       tmp = priv->lddckr;
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+               ch = &priv->ch[k];
+
+               if (!priv->ch[k].enabled)
+                       continue;
+
+               m = ch->cfg.clock_divider;
+               if (!m)
+                       continue;
+
+               if (m == 1)
+                       m = 1 << 6;
+               tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
+
+               lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000);
+               lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
+       }
+
+       lcdc_write(priv, _LDDCKR, tmp);
+
+       /* start dotclock again */
+       lcdc_write(priv, _LDDCKSTPR, 0);
+       lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
+
+       /* interrupts are disabled */
+       lcdc_write(priv, _LDINTR, 0);
+
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+               ch = &priv->ch[k];
+               lcd_cfg = &ch->cfg.lcd_cfg;
+
+               if (!ch->enabled)
+                       continue;
+
+               tmp = ch->ldmt1r_value;
+               tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
+               tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
+               lcdc_write_chan(ch, LDMT1R, tmp);
+
+               /* setup SYS bus */
+               lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
+               lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
+
+               /* horizontal configuration */
+               tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
+               tmp += lcd_cfg->left_margin;
+               tmp += lcd_cfg->right_margin;
+               tmp /= 8; /* HTCN */
+               tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
+               lcdc_write_chan(ch, LDHCNR, tmp);
+
+               tmp = lcd_cfg->xres;
+               tmp += lcd_cfg->right_margin;
+               tmp /= 8; /* HSYNP */
+               tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
+               lcdc_write_chan(ch, LDHSYNR, tmp);
+
+               /* power supply */
+               lcdc_write_chan(ch, LDPMR, 0);
+
+               /* vertical configuration */
+               tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
+               tmp += lcd_cfg->upper_margin;
+               tmp += lcd_cfg->lower_margin; /* VTLN */
+               tmp |= lcd_cfg->yres << 16; /* VDLN */
+               lcdc_write_chan(ch, LDVLNR, tmp);
+
+               tmp = lcd_cfg->yres;
+               tmp += lcd_cfg->lower_margin; /* VSYNP */
+               tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
+               lcdc_write_chan(ch, LDVSYNR, tmp);
+
+               board_cfg = &ch->cfg.board_cfg;
+               if (board_cfg->setup_sys)
+                       ret = board_cfg->setup_sys(board_cfg->board_data, ch,
+                                                  &sh_mobile_lcdc_sys_bus_ops);
+               if (ret)
+                       return ret;
+       }
+
+       /* --- display_lcdc_data() --- */
+       lcdc_write(priv, _LDINTR, 0x00000f00);
+
+       /* word and long word swap */
+       lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
+
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+               ch = &priv->ch[k];
+
+               if (!priv->ch[k].enabled)
+                       continue;
+
+               /* set bpp format in PKF[4:0] */
+               tmp = lcdc_read_chan(ch, LDDFR);
+               tmp &= ~(0x0001001f);
+               tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0;
+               lcdc_write_chan(ch, LDDFR, tmp);
+
+               /* point out our frame buffer */
+               lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start);
+
+               /* set line size */
+               lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length);
+
+               /* continuous read mode */
+               lcdc_write_chan(ch, LDSM1R, 0);
+       }
+
+       /* display output */
+       lcdc_write(priv, _LDCNT1R, LCDC_ENABLE);
+
+       /* start the lcdc */
+       sh_mobile_lcdc_start_stop(priv, 1);
+
+       /* tell the board code to enable the panel */
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+               ch = &priv->ch[k];
+               board_cfg = &ch->cfg.board_cfg;
+               if (board_cfg->display_on)
+                       board_cfg->display_on(board_cfg->board_data);
+       }
+
+       return 0;
+}
+
+static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
+{
+       struct sh_mobile_lcdc_chan *ch;
+       struct sh_mobile_lcdc_board_cfg *board_cfg;
+       int k;
+
+       /* tell the board code to disable the panel */
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+               ch = &priv->ch[k];
+               board_cfg = &ch->cfg.board_cfg;
+               if (board_cfg->display_off)
+                       board_cfg->display_off(board_cfg->board_data);
+       }
+
+       /* stop the lcdc */
+       sh_mobile_lcdc_start_stop(priv, 0);
+}
+
+static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
+{
+       int ifm, miftyp;
+
+       switch (ch->cfg.interface_type) {
+       case RGB8: ifm = 0; miftyp = 0; break;
+       case RGB9: ifm = 0; miftyp = 4; break;
+       case RGB12A: ifm = 0; miftyp = 5; break;
+       case RGB12B: ifm = 0; miftyp = 6; break;
+       case RGB16: ifm = 0; miftyp = 7; break;
+       case RGB18: ifm = 0; miftyp = 10; break;
+       case RGB24: ifm = 0; miftyp = 11; break;
+       case SYS8A: ifm = 1; miftyp = 0; break;
+       case SYS8B: ifm = 1; miftyp = 1; break;
+       case SYS8C: ifm = 1; miftyp = 2; break;
+       case SYS8D: ifm = 1; miftyp = 3; break;
+       case SYS9: ifm = 1; miftyp = 4; break;
+       case SYS12: ifm = 1; miftyp = 5; break;
+       case SYS16A: ifm = 1; miftyp = 7; break;
+       case SYS16B: ifm = 1; miftyp = 8; break;
+       case SYS16C: ifm = 1; miftyp = 9; break;
+       case SYS18: ifm = 1; miftyp = 10; break;
+       case SYS24: ifm = 1; miftyp = 11; break;
+       default: goto bad;
+       }
+
+       /* SUBLCD only supports SYS interface */
+       if (lcdc_chan_is_sublcd(ch)) {
+               if (ifm == 0)
+                       goto bad;
+               else
+                       ifm = 0;
+       }
+
+       ch->ldmt1r_value = (ifm << 12) | miftyp;
+       return 0;
+ bad:
+       return -EINVAL;
+}
+
+static int sh_mobile_lcdc_setup_clocks(struct device *dev, int clock_source,
+                                      struct sh_mobile_lcdc_priv *priv)
+{
+       char *str;
+       int icksel;
+
+       switch (clock_source) {
+       case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break;
+       case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break;
+       case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break;
+       default:
+               return -EINVAL;
+       }
+
+       priv->lddckr = icksel << 16;
+
+       if (str) {
+               priv->clk = clk_get(dev, str);
+               if (IS_ERR(priv->clk)) {
+                       dev_err(dev, "cannot get clock %s\n", str);
+                       return PTR_ERR(priv->clk);
+               }
+
+               clk_enable(priv->clk);
+       }
+
+       return 0;
+}
+
+static int sh_mobile_lcdc_setcolreg(u_int regno,
+                                   u_int red, u_int green, u_int blue,
+                                   u_int transp, struct fb_info *info)
+{
+       u32 *palette = info->pseudo_palette;
+
+       if (regno >= PALETTE_NR)
+               return -EINVAL;
+
+       /* only FB_VISUAL_TRUECOLOR supported */
+
+       red >>= 16 - info->var.red.length;
+       green >>= 16 - info->var.green.length;
+       blue >>= 16 - info->var.blue.length;
+       transp >>= 16 - info->var.transp.length;
+
+       palette[regno] = (red << info->var.red.offset) |
+         (green << info->var.green.offset) |
+         (blue << info->var.blue.offset) |
+         (transp << info->var.transp.offset);
+
+       return 0;
+}
+
+static struct fb_fix_screeninfo sh_mobile_lcdc_fix  = {
+       .id =           "SH Mobile LCDC",
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_TRUECOLOR,
+       .accel =        FB_ACCEL_NONE,
+};
+
+static struct fb_ops sh_mobile_lcdc_ops = {
+       .fb_setcolreg   = sh_mobile_lcdc_setcolreg,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+};
+
+static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
+{
+       switch (bpp) {
+       case 16: /* PKF[4:0] = 00011 - 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;
+
+       case 32: /* PKF[4:0] = 00000 - RGB 888
+                 * sh7722 pdf says 00RRGGBB but reality is GGBB00RR
+                 * this may be because LDDDSR has word swap enabled..
+                 */
+               var->red.offset = 0;
+               var->red.length = 8;
+               var->green.offset = 24;
+               var->green.length = 8;
+               var->blue.offset = 16;
+               var->blue.length = 8;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+       var->bits_per_pixel = bpp;
+       var->red.msb_right = 0;
+       var->green.msb_right = 0;
+       var->blue.msb_right = 0;
+       var->transp.msb_right = 0;
+       return 0;
+}
+
+static int sh_mobile_lcdc_remove(struct platform_device *pdev);
+
+static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
+{
+       struct fb_info *info;
+       struct sh_mobile_lcdc_priv *priv;
+       struct sh_mobile_lcdc_info *pdata;
+       struct sh_mobile_lcdc_chan_cfg *cfg;
+       struct resource *res;
+       int error;
+       void *buf;
+       int i, j;
+
+       if (!pdev->dev.platform_data) {
+               dev_err(&pdev->dev, "no platform data defined\n");
+               error = -EINVAL;
+               goto err0;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "cannot find IO resource\n");
+               error = -ENOENT;
+               goto err0;
+       }
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               dev_err(&pdev->dev, "cannot allocate device data\n");
+               error = -ENOMEM;
+               goto err0;
+       }
+
+       platform_set_drvdata(pdev, priv);
+       pdata = pdev->dev.platform_data;
+
+       j = 0;
+       for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
+               priv->ch[j].lcdc = priv;
+               memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
+
+               error = sh_mobile_lcdc_check_interface(&priv->ch[i]);
+               if (error) {
+                       dev_err(&pdev->dev, "unsupported interface type\n");
+                       goto err1;
+               }
+
+               switch (pdata->ch[i].chan) {
+               case LCDC_CHAN_MAINLCD:
+                       priv->ch[j].enabled = 1 << 1;
+                       priv->ch[j].reg_offs = lcdc_offs_mainlcd;
+                       j++;
+                       break;
+               case LCDC_CHAN_SUBLCD:
+                       priv->ch[j].enabled = 1 << 2;
+                       priv->ch[j].reg_offs = lcdc_offs_sublcd;
+                       j++;
+                       break;
+               }
+       }
+
+       if (!j) {
+               dev_err(&pdev->dev, "no channels defined\n");
+               error = -EINVAL;
+               goto err1;
+       }
+
+       error = sh_mobile_lcdc_setup_clocks(&pdev->dev,
+                                           pdata->clock_source, priv);
+       if (error) {
+               dev_err(&pdev->dev, "unable to setup clocks\n");
+               goto err1;
+       }
+
+       priv->lddckr = pdata->lddckr;
+       priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
+
+       for (i = 0; i < j; i++) {
+               info = &priv->ch[i].info;
+               cfg = &priv->ch[i].cfg;
+
+               info->fbops = &sh_mobile_lcdc_ops;
+               info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
+               info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres;
+               info->var.activate = FB_ACTIVATE_NOW;
+               error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp);
+               if (error)
+                       break;
+
+               info->fix = sh_mobile_lcdc_fix;
+               info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8);
+               info->fix.smem_len = info->fix.line_length * cfg->lcd_cfg.yres;
+
+               buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
+                                        &priv->ch[i].dma_handle, GFP_KERNEL);
+               if (!buf) {
+                       dev_err(&pdev->dev, "unable to allocate buffer\n");
+                       error = -ENOMEM;
+                       break;
+               }
+
+               info->pseudo_palette = &priv->ch[i].pseudo_palette;
+               info->flags = FBINFO_FLAG_DEFAULT;
+
+               error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
+               if (error < 0) {
+                       dev_err(&pdev->dev, "unable to allocate cmap\n");
+                       dma_free_coherent(&pdev->dev, info->fix.smem_len,
+                                         buf, priv->ch[i].dma_handle);
+                       break;
+               }
+
+               memset(buf, 0, info->fix.smem_len);
+               info->fix.smem_start = priv->ch[i].dma_handle;
+               info->screen_base = buf;
+               info->device = &pdev->dev;
+       }
+
+       if (error)
+               goto err1;
+
+       error = sh_mobile_lcdc_start(priv);
+       if (error) {
+               dev_err(&pdev->dev, "unable to start hardware\n");
+               goto err1;
+       }
+
+       for (i = 0; i < j; i++) {
+               error = register_framebuffer(&priv->ch[i].info);
+               if (error < 0)
+                       goto err1;
+       }
+
+       for (i = 0; i < j; i++) {
+               info = &priv->ch[i].info;
+               dev_info(info->dev,
+                        "registered %s/%s as %dx%d %dbpp.\n",
+                        pdev->name,
+                        (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ?
+                        "mainlcd" : "sublcd",
+                        (int) priv->ch[i].cfg.lcd_cfg.xres,
+                        (int) priv->ch[i].cfg.lcd_cfg.yres,
+                        priv->ch[i].cfg.bpp);
+       }
+
+       return 0;
+ err1:
+       sh_mobile_lcdc_remove(pdev);
+ err0:
+       return error;
+}
+
+static int sh_mobile_lcdc_remove(struct platform_device *pdev)
+{
+       struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+       struct fb_info *info;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
+               if (priv->ch[i].info.dev)
+                       unregister_framebuffer(&priv->ch[i].info);
+
+       sh_mobile_lcdc_stop(priv);
+
+       for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+               info = &priv->ch[i].info;
+
+               if (!info->device)
+                       continue;
+
+               dma_free_coherent(&pdev->dev, info->fix.smem_len,
+                                 info->screen_base, priv->ch[i].dma_handle);
+               fb_dealloc_cmap(&info->cmap);
+       }
+
+       if (priv->clk) {
+               clk_disable(priv->clk);
+               clk_put(priv->clk);
+       }
+
+       if (priv->base)
+               iounmap(priv->base);
+
+       kfree(priv);
+       return 0;
+}
+
+static struct platform_driver sh_mobile_lcdc_driver = {
+       .driver         = {
+               .name           = "sh_mobile_lcdc_fb",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = sh_mobile_lcdc_probe,
+       .remove         = sh_mobile_lcdc_remove,
+};
+
+static int __init sh_mobile_lcdc_init(void)
+{
+       return platform_driver_register(&sh_mobile_lcdc_driver);
+}
+
+static void __exit sh_mobile_lcdc_exit(void)
+{
+       platform_driver_unregister(&sh_mobile_lcdc_driver);
+}
+
+module_init(sh_mobile_lcdc_init);
+module_exit(sh_mobile_lcdc_exit);
+
+MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL v2");
index f40a680df86f26fa555ca86b35f32fb0c70dbbad..b96005c39c67fdbe4d63e034123a328e53282cd0 100644 (file)
@@ -73,7 +73,6 @@
 #ifdef SIS_CP
 #undef SIS_CP
 #endif
-#include <linux/version.h>
 #include <linux/types.h>
 #include <asm/io.h>
 #include <linux/fb.h>
index 7708e1e1d99e4509b87785d21b0131f3819eee95..51d99222375dd9034c94c5a66eba731f60299e05 100644 (file)
@@ -67,7 +67,6 @@
 #ifdef SIS_CP
 #undef SIS_CP
 #endif
-#include <linux/version.h>
 #include <linux/types.h>
 #include <asm/io.h>
 #include <linux/fb.h>
index 47a33501549d729f8770e8b90441e43ea23774c7..99c04a4855d13671925301f1f219a2d991160f86 100644 (file)
@@ -30,7 +30,6 @@
 #include "vgatypes.h"
 #include "vstruct.h"
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/fb.h>
 
index c1492782cb182dadc2173afe01769ef9fe323b47..6ff8f988a1a73dc5900691c6ed1d6cf49e58e2dc 100644 (file)
@@ -87,7 +87,6 @@
 /**********************************************************************/
 
 #ifdef SIS_LINUX_KERNEL
-#include <linux/version.h>
 
 #ifdef CONFIG_FB_SIS_300
 #define SIS300
index a14e822110375bf7c946d9848014ad891f3ab03b..7c5710e3fb567272dc0952778bef930c8f2ba70b 100644 (file)
@@ -24,8 +24,6 @@
 #ifndef _SIS_H_
 #define _SIS_H_
 
-#include <linux/version.h>
-
 #include "osdef.h"
 #include <video/sisfb.h>
 
 #define SIS_NEW_CONFIG_COMPAT
 #endif /* CONFIG_COMPAT */
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
-#define SIS_IOTYPE1 void __iomem
-#define SIS_IOTYPE2 __iomem
-#define SISINITSTATIC static
-#else
-#define SIS_IOTYPE1 unsigned char
-#define SIS_IOTYPE2
-#define SISINITSTATIC
-#endif
-
 #undef SISFBDEBUG
 
 #ifdef SISFBDEBUG
@@ -505,8 +493,8 @@ struct sis_video_info {
 
        unsigned long   UMAsize, LFBsize;
 
-       SIS_IOTYPE1     *video_vbase;
-       SIS_IOTYPE1     *mmio_vbase;
+       void __iomem    *video_vbase;
+       void __iomem    *mmio_vbase;
 
        unsigned char   *bios_abase;
 
@@ -533,8 +521,8 @@ struct sis_video_info {
        int             sisfb_nocrt2rate;
 
        u32             heapstart;              /* offset  */
-       SIS_IOTYPE1     *sisfb_heap_start;      /* address */
-       SIS_IOTYPE1     *sisfb_heap_end;        /* address */
+       void __iomem    *sisfb_heap_start;      /* address */
+       void __iomem    *sisfb_heap_end;        /* address */
        u32             sisfb_heap_size;
        int             havenoheap;
 
@@ -612,7 +600,7 @@ struct sis_video_info {
        u8              detectedpdca;
        u8              detectedlcda;
 
-       SIS_IOTYPE1     *hwcursor_vbase;
+       void __iomem    *hwcursor_vbase;
 
        int             chronteltype;
        int             tvxpos, tvypos;
index 7addf91d2feab2068b65b627b52994ef3d42c3ac..ceb434c95c0d56b166a7c6a1b9ee19de7ca4cda8 100644 (file)
@@ -28,7 +28,6 @@
  *                     for more information and updates)
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/fb.h>
index b9343844cd1f4cd31645147fcc105adf6e34c0e7..346d6458cf76a64ef3a96af133e810c2d8c19505 100644 (file)
@@ -33,7 +33,6 @@
  *
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
-#include <linux/tty.h>
-#else
 #include <linux/screen_info.h>
-#endif
-
 #include <linux/slab.h>
 #include <linux/fb.h>
 #include <linux/selection.h>
@@ -1167,11 +1160,7 @@ sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
        unsigned short modeno = ivideo->mode_no;
 
        /* >=2.6.12's fbcon clears the screen anyway */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
-       if(!clrscrn) modeno |= 0x80;
-#else
        modeno |= 0x80;
-#endif
 
        outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
@@ -1436,11 +1425,8 @@ sisfb_set_par(struct fb_info *info)
        if((err = sisfb_do_set_var(&info->var, 1, info)))
                return err;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
-       sisfb_get_fix(&info->fix, info->currcon, info);
-#else
        sisfb_get_fix(&info->fix, -1, info);
-#endif
+
        return 0;
 }
 
@@ -1676,14 +1662,8 @@ sisfb_blank(int blank, struct fb_info *info)
 
 /* ----------- FBDev related routines for all series ---------- */
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
 static int     sisfb_ioctl(struct fb_info *info, unsigned int cmd,
                            unsigned long arg)
-#else
-static int     sisfb_ioctl(struct inode *inode, struct file *file,
-                               unsigned int cmd, unsigned long arg,
-                               struct fb_info *info)
-#endif
 {
        struct sis_video_info   *ivideo = (struct sis_video_info *)info->par;
        struct sis_memreq       sismemreq;
@@ -3986,8 +3966,7 @@ sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_comm
 }
 
 #ifndef MODULE
-SISINITSTATIC int __init
-sisfb_setup(char *options)
+static int __init sisfb_setup(char *options)
 {
        char *this_opt;
 
@@ -4086,9 +4065,9 @@ sisfb_setup(char *options)
 #endif
 
 static int __devinit
-sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
+sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
 {
-       SIS_IOTYPE1 *rom;
+       void __iomem *rom;
        int romptr;
 
        if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
@@ -4117,10 +4096,9 @@ static unsigned char * __devinit
 sisfb_find_rom(struct pci_dev *pdev)
 {
        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-       SIS_IOTYPE1 *rom_base;
+       void __iomem *rom_base;
        unsigned char *myrombase = NULL;
        u32 temp;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
        size_t romsize;
 
        /* First, try the official pci ROM functions (except
@@ -4151,7 +4129,6 @@ sisfb_find_rom(struct pci_dev *pdev)
        }
 
        if(myrombase) return myrombase;
-#endif
 
        /* Otherwise do it the conventional way. */
 
@@ -4225,7 +4202,7 @@ sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
 static int __devinit
 sisfb_post_300_buswidth(struct sis_video_info *ivideo)
 {
-       SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
+       void __iomem *FBAddress = ivideo->video_vbase;
        unsigned short temp;
        unsigned char reg;
        int i, j;
@@ -4273,7 +4250,7 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth
                        int PseudoRankCapacity, int PseudoAdrPinCount,
                        unsigned int mapsize)
 {
-       SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
+       void __iomem *FBAddr = ivideo->video_vbase;
        unsigned short sr14;
        unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
        unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
@@ -5829,7 +5806,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        ivideo->engineok = 0;
 
        ivideo->sisfb_was_boot_device = 0;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+
        if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
                if(ivideo->sisvga_enabled)
                        ivideo->sisfb_was_boot_device = 1;
@@ -5840,7 +5817,6 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                "as the primary VGA device\n");
                }
        }
-#endif
 
        ivideo->sisfb_parm_mem = sisfb_parm_mem;
        ivideo->sisfb_accel = sisfb_accel;
@@ -6010,7 +5986,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                ivideo->modeprechange = reg & 0x7f;
        } else if(ivideo->sisvga_enabled) {
 #if defined(__i386__) || defined(__x86_64__)
-               unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
+               unsigned char __iomem *tt = ioremap(0x400, 0x100);
                if(tt) {
                        ivideo->modeprechange = readb(tt + 0x49);
                        iounmap(tt);
@@ -6503,7 +6479,7 @@ static struct pci_driver sisfb_driver = {
        .remove         = __devexit_p(sisfb_remove)
 };
 
-SISINITSTATIC int __init sisfb_init(void)
+static int __init sisfb_init(void)
 {
 #ifndef MODULE
        char *options = NULL;
index 3e3b7fa05d6c3d27ff54dc8bfc2d18f702069a57..9540e977270e3932c1d536990546541cefa4258d 100644 (file)
@@ -665,11 +665,11 @@ static struct _customttable {
 
 /* Interface used by the world */
 #ifndef MODULE
-SISINITSTATIC int sisfb_setup(char *options);
+static int sisfb_setup(char *options);
 #endif
 
 /* Interface to the low level console driver */
-SISINITSTATIC int sisfb_init(void);
+static int sisfb_init(void);
 
 /* fbdev routines */
 static int     sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
index b532fbd2b04c1c2612937a030c0f3747ee931199..81a22eaabfde0f43abced33a8c4a0cd998acdc0d 100644 (file)
 #ifndef _VGATYPES_H_
 #define _VGATYPES_H_
 
-#ifdef SIS_LINUX_KERNEL
-#include <linux/version.h>
-#endif
-
 #define SISIOMEMTYPE
 
 #ifdef SIS_LINUX_KERNEL
index 62321458f71a2e88cdf6766108d1bb3e166e319a..df5336561d1304d4e35c586fead0d6942d9892cf 100644 (file)
@@ -675,13 +675,13 @@ static struct fb_ops xxxfb_ops = {
      *  Initialization
      */
 
-/* static int __init xxfb_probe (struct device *device) -- for platform devs */
+/* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */
 static int __devinit xxxfb_probe(struct pci_dev *dev,
                              const struct pci_device_id *ent)
 {
     struct fb_info *info;
     struct xxx_par *par;
-    struct device* device = &dev->dev; /* for pci drivers */
+    struct device *device = &dev->dev; /* or &pdev->dev */
     int cmap_len, retval;      
    
     /*
@@ -824,18 +824,18 @@ static int __devinit xxxfb_probe(struct pci_dev *dev,
        return -EINVAL;
     printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
           info->fix.id);
-    pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
+    pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */
     return 0;
 }
 
     /*
      *  Cleanup
      */
-/* static void __devexit xxxfb_remove(struct device *device) */
+/* static void __devexit xxxfb_remove(struct platform_device *pdev) */
 static void __devexit xxxfb_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
-       /* or dev_get_drvdata(device); */
+       /* or platform_get_drvdata(pdev); */
 
        if (info) {
                unregister_framebuffer(info);
@@ -961,18 +961,17 @@ static int xxxfb_resume(struct platform_dev *dev)
 #define xxxfb_resume NULL
 #endif /* CONFIG_PM */
 
-static struct device_driver xxxfb_driver = {
-       .name = "xxxfb",
-       .bus  = &platform_bus_type,
+static struct platform_device_driver xxxfb_driver = {
        .probe = xxxfb_probe,
        .remove = xxxfb_remove,
        .suspend = xxxfb_suspend, /* optional but recommended */
        .resume = xxxfb_resume,   /* optional but recommended */
+       .driver = {
+               .name = "xxxfb",
+       },
 };
 
-static struct platform_device xxxfb_device = {
-       .name = "xxxfb",
-};
+static struct platform_device *xxxfb_device;
 
 #ifndef MODULE
     /*
@@ -1002,12 +1001,16 @@ static int __init xxxfb_init(void)
                return -ENODEV;
        xxxfb_setup(option);
 #endif
-       ret = driver_register(&xxxfb_driver);
+       ret = platform_driver_register(&xxxfb_driver);
 
        if (!ret) {
-               ret = platform_device_register(&xxxfb_device);
-               if (ret)
-                       driver_unregister(&xxxfb_driver);
+               xxxfb_device = platform_device_register_simple("xxxfb", 0,
+                                                               NULL, 0);
+
+               if (IS_ERR(xxxfb_device)) {
+                       platform_driver_unregister(&xxxfb_driver);
+                       ret = PTR_ERR(xxxfb_device);
+               }
        }
 
        return ret;
@@ -1015,8 +1018,8 @@ static int __init xxxfb_init(void)
 
 static void __exit xxxfb_exit(void)
 {
-       platform_device_unregister(&xxxfb_device);
-       driver_unregister(&xxxfb_driver);
+       platform_device_unregister(xxxfb_device);
+       platform_driver_unregister(&xxxfb_driver);
 }
 #endif /* CONFIG_PCI */
 
index 15d4a768b1f6f21b29f817a9f9ecee877dc60eb9..f94ae84a58cd54eabd267a9e4d33384b346755ec 100644 (file)
@@ -48,10 +48,15 @@ enum sm501_controller {
        HEAD_PANEL      = 1,
 };
 
-/* SM501 memory address */
+/* SM501 memory address.
+ *
+ * This structure is used to track memory usage within the SM501 framebuffer
+ * allocation. The sm_addr field is stored as an offset as it is often used
+ * against both the physical and mapped addresses.
+ */
 struct sm501_mem {
        unsigned long    size;
-       unsigned long    sm_addr;
+       unsigned long    sm_addr;       /* offset from base of sm501 fb. */
        void __iomem    *k_addr;
 };
 
@@ -142,31 +147,68 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info)
 static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
                           unsigned int why, size_t size)
 {
-       unsigned int ptr = 0;
+       struct sm501fb_par *par;
+       struct fb_info *fbi;
+       unsigned int ptr;
+       unsigned int end;
 
        switch (why) {
        case SM501_MEMF_CURSOR:
                ptr = inf->fbmem_len - size;
-               inf->fbmem_len = ptr;
+               inf->fbmem_len = ptr;   /* adjust available memory. */
                break;
 
        case SM501_MEMF_PANEL:
                ptr = inf->fbmem_len - size;
-               if (ptr < inf->fb[0]->fix.smem_len)
+               fbi = inf->fb[HEAD_CRT];
+
+               /* round down, some programs such as directfb do not draw
+                * 0,0 correctly unless the start is aligned to a page start.
+                */
+
+               if (ptr > 0)
+                       ptr &= ~(PAGE_SIZE - 1);
+
+               if (fbi && ptr < fbi->fix.smem_len)
+                       return -ENOMEM;
+
+               if (ptr < 0)
                        return -ENOMEM;
 
                break;
 
        case SM501_MEMF_CRT:
                ptr = 0;
+
+               /* check to see if we have panel memory allocated
+                * which would put an limit on available memory. */
+
+               fbi = inf->fb[HEAD_PANEL];
+               if (fbi) {
+                       par = fbi->par;
+                       end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len;
+               } else
+                       end = inf->fbmem_len;
+
+               if ((ptr + size) > end)
+                       return -ENOMEM;
+
                break;
 
        case SM501_MEMF_ACCEL:
-               ptr = inf->fb[0]->fix.smem_len;
+               fbi = inf->fb[HEAD_CRT];
+               ptr = fbi ? fbi->fix.smem_len : 0;
+
+               fbi = inf->fb[HEAD_PANEL];
+               if (fbi) {
+                       par = fbi->par;
+                       end = par->screen.sm_addr;
+               } else
+                       end = inf->fbmem_len;
 
-               if ((ptr + size) >
-                   (inf->fb[1]->fix.smem_start - inf->fbmem_res->start))
+               if ((ptr + size) > end)
                        return -ENOMEM;
+
                break;
 
        default:
@@ -663,15 +705,25 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
                sm501fb_sync_regs(fbi);
                mdelay(10);
 
+               /* VBIASEN */
+
                if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
-                       control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */
+                       if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+                               control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+                       else
+                               control |= SM501_DC_PANEL_CONTROL_BIAS;
+
                        writel(control, ctrl_reg);
                        sm501fb_sync_regs(fbi);
                        mdelay(10);
                }
 
                if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
-                       control |= SM501_DC_PANEL_CONTROL_FPEN;
+                       if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+                               control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+                       else
+                               control |= SM501_DC_PANEL_CONTROL_FPEN;
+
                        writel(control, ctrl_reg);
                        sm501fb_sync_regs(fbi);
                        mdelay(10);
@@ -679,14 +731,22 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
        } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
                /* disable panel power */
                if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
-                       control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+                       if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+                               control |= SM501_DC_PANEL_CONTROL_FPEN;
+                       else
+                               control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+
                        writel(control, ctrl_reg);
                        sm501fb_sync_regs(fbi);
                        mdelay(10);
                }
 
                if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
-                       control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+                       if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+                               control |= SM501_DC_PANEL_CONTROL_BIAS;
+                       else
+                               control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+
                        writel(control, ctrl_reg);
                        sm501fb_sync_regs(fbi);
                        mdelay(10);
@@ -1210,39 +1270,6 @@ static struct fb_ops sm501fb_ops_pnl = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-/* sm501fb_info_alloc
- *
- * creates and initialises an sm501fb_info structure
-*/
-
-static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
-                                              struct fb_info *fbinfo_pnl)
-{
-       struct sm501fb_info *info;
-       struct sm501fb_par  *par;
-
-       info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
-       if (info) {
-               /* set the references back */
-
-               par = fbinfo_crt->par;
-               par->info = info;
-               par->head = HEAD_CRT;
-               fbinfo_crt->pseudo_palette = &par->pseudo_palette;
-
-               par = fbinfo_pnl->par;
-               par->info = info;
-               par->head = HEAD_PANEL;
-               fbinfo_pnl->pseudo_palette = &par->pseudo_palette;
-
-               /* store the two fbs into our info */
-               info->fb[HEAD_CRT] = fbinfo_crt;
-               info->fb[HEAD_PANEL] = fbinfo_pnl;
-       }
-
-       return info;
-}
-
 /* sm501_init_cursor
  *
  * initialise hw cursor parameters
@@ -1250,10 +1277,16 @@ static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
 
 static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
 {
-       struct sm501fb_par *par = fbi->par;
-       struct sm501fb_info *info = par->info;
+       struct sm501fb_par *par;
+       struct sm501fb_info *info;
        int ret;
 
+       if (fbi == NULL)
+               return 0;
+
+       par = fbi->par;
+       info = par->info;
+
        par->cursor_regs = info->regs + reg_base;
 
        ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024);
@@ -1281,13 +1314,10 @@ static int sm501fb_start(struct sm501fb_info *info,
                         struct platform_device *pdev)
 {
        struct resource *res;
-       struct device *dev;
+       struct device *dev = &pdev->dev;
        int k;
        int ret;
 
-       info->dev = dev = &pdev->dev;
-       platform_set_drvdata(pdev, info);
-
        info->irq = ret = platform_get_irq(pdev, 0);
        if (ret < 0) {
                /* we currently do not use the IRQ */
@@ -1390,11 +1420,6 @@ static void sm501fb_stop(struct sm501fb_info *info)
        kfree(info->regs_res);
 }
 
-static void sm501fb_info_release(struct sm501fb_info *info)
-{
-       kfree(info);
-}
-
 static int sm501fb_init_fb(struct fb_info *fb,
                           enum sm501_controller head,
                           const char *fbname)
@@ -1539,36 +1564,93 @@ static struct sm501_platdata_fb sm501fb_def_pdata = {
 static char driver_name_crt[] = "sm501fb-crt";
 static char driver_name_pnl[] = "sm501fb-panel";
 
-static int __init sm501fb_probe(struct platform_device *pdev)
+static int __devinit sm501fb_probe_one(struct sm501fb_info *info,
+                                      enum sm501_controller head)
 {
-       struct sm501fb_info *info;
-       struct device       *dev = &pdev->dev;
-       struct fb_info      *fbinfo_crt;
-       struct fb_info      *fbinfo_pnl;
-       int                  ret;
+       unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel";
+       struct sm501_platdata_fbsub *pd;
+       struct sm501fb_par *par;
+       struct fb_info *fbi;
 
-       /* allocate our framebuffers */
+       pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl;
+
+       /* Do not initialise if we've not been given any platform data */
+       if (pd == NULL) {
+               dev_info(info->dev, "no data for fb %s (disabled)\n", name);
+               return 0;
+       }
 
-       fbinfo_crt = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
-       if (fbinfo_crt == NULL) {
-               dev_err(dev, "cannot allocate crt framebuffer\n");
+       fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev);
+       if (fbi == NULL) {
+               dev_err(info->dev, "cannot allocate %s framebuffer\n", name);
                return -ENOMEM;
        }
 
-       fbinfo_pnl = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
-       if (fbinfo_pnl == NULL) {
-               dev_err(dev, "cannot allocate panel framebuffer\n");
-               ret = -ENOMEM;
-               goto fbinfo_crt_alloc_fail;
+       par = fbi->par;
+       par->info = info;
+       par->head = head;
+       fbi->pseudo_palette = &par->pseudo_palette;
+
+       info->fb[head] = fbi;
+
+       return 0;
+}
+
+/* Free up anything allocated by sm501fb_init_fb */
+
+static void sm501_free_init_fb(struct sm501fb_info *info,
+                               enum sm501_controller head)
+{
+       struct fb_info *fbi = info->fb[head];
+
+       fb_dealloc_cmap(&fbi->cmap);
+}
+
+static int __devinit sm501fb_start_one(struct sm501fb_info *info,
+                                      enum sm501_controller head,
+                                      const char *drvname)
+{
+       struct fb_info *fbi = info->fb[head];
+       int ret;
+
+       if (!fbi)
+               return 0;
+
+       ret = sm501fb_init_fb(info->fb[head], head, drvname);
+       if (ret) {
+               dev_err(info->dev, "cannot initialise fb %s\n", drvname);
+               return ret;
+       }
+
+       ret = register_framebuffer(info->fb[head]);
+       if (ret) {
+               dev_err(info->dev, "failed to register fb %s\n", drvname);
+               sm501_free_init_fb(info, head);
+               return ret;
        }
 
-       info = sm501fb_info_alloc(fbinfo_crt, fbinfo_pnl);
-       if (info == NULL) {
-               dev_err(dev, "cannot allocate par\n");
-               ret = -ENOMEM;
-               goto sm501fb_alloc_fail;
+       dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id);
+
+       return 0;
+}
+
+static int __devinit sm501fb_probe(struct platform_device *pdev)
+{
+       struct sm501fb_info *info;
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       /* allocate our framebuffers */
+
+       info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
+       if (!info) {
+               dev_err(dev, "failed to allocate state\n");
+               return -ENOMEM;
        }
 
+       info->dev = dev = &pdev->dev;
+       platform_set_drvdata(pdev, info);
+
        if (dev->parent->platform_data) {
                struct sm501_platdata *pd = dev->parent->platform_data;
                info->pdata = pd->fb;
@@ -1579,90 +1661,88 @@ static int __init sm501fb_probe(struct platform_device *pdev)
                info->pdata = &sm501fb_def_pdata;
        }
 
-       /* start the framebuffers */
+       /* probe for the presence of each panel */
 
-       ret = sm501fb_start(info, pdev);
-       if (ret) {
-               dev_err(dev, "cannot initialise SM501\n");
-               goto sm501fb_start_fail;
+       ret = sm501fb_probe_one(info, HEAD_CRT);
+       if (ret < 0) {
+               dev_err(dev, "failed to probe CRT\n");
+               goto err_alloc;
        }
 
-       /* CRT framebuffer setup */
+       ret = sm501fb_probe_one(info, HEAD_PANEL);
+       if (ret < 0) {
+               dev_err(dev, "failed to probe PANEL\n");
+               goto err_probed_crt;
+       }
 
-       ret = sm501fb_init_fb(fbinfo_crt, HEAD_CRT, driver_name_crt);
-       if (ret) {
-               dev_err(dev, "cannot initialise CRT fb\n");
-               goto sm501fb_start_fail;
+       if (info->fb[HEAD_PANEL] == NULL &&
+           info->fb[HEAD_CRT] == NULL) {
+               dev_err(dev, "no framebuffers found\n");
+               goto err_alloc;
        }
 
-       /* Panel framebuffer setup */
+       /* get the resources for both of the framebuffers */
 
-       ret = sm501fb_init_fb(fbinfo_pnl, HEAD_PANEL, driver_name_pnl);
+       ret = sm501fb_start(info, pdev);
        if (ret) {
-               dev_err(dev, "cannot initialise Panel fb\n");
-               goto sm501fb_start_fail;
+               dev_err(dev, "cannot initialise SM501\n");
+               goto err_probed_panel;
        }
 
-       /* register framebuffers */
-
-       ret = register_framebuffer(fbinfo_crt);
-       if (ret < 0) {
-               dev_err(dev, "failed to register CRT fb (%d)\n", ret);
-               goto register_crt_fail;
+       ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt);
+       if (ret) {
+               dev_err(dev, "failed to start CRT\n");
+               goto err_started;
        }
 
-       ret = register_framebuffer(fbinfo_pnl);
-       if (ret < 0) {
-               dev_err(dev, "failed to register panel fb (%d)\n", ret);
-               goto register_pnl_fail;
+       ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl);
+       if (ret) {
+               dev_err(dev, "failed to start Panel\n");
+               goto err_started_crt;
        }
 
-       dev_info(dev, "fb%d: %s frame buffer device\n",
-                fbinfo_crt->node, fbinfo_crt->fix.id);
-
-       dev_info(dev, "fb%d: %s frame buffer device\n",
-              fbinfo_pnl->node, fbinfo_pnl->fix.id);
-
        /* create device files */
 
        ret = device_create_file(dev, &dev_attr_crt_src);
        if (ret)
-               goto crtsrc_fail;
+               goto err_started_panel;
 
        ret = device_create_file(dev, &dev_attr_fbregs_pnl);
        if (ret)
-               goto fbregs_pnl_fail;
+               goto err_attached_crtsrc_file;
 
        ret = device_create_file(dev, &dev_attr_fbregs_crt);
        if (ret)
-               goto fbregs_crt_fail;
+               goto err_attached_pnlregs_file;
 
        /* we registered, return ok */
        return 0;
 
- fbregs_crt_fail:
+err_attached_pnlregs_file:
        device_remove_file(dev, &dev_attr_fbregs_pnl);
 
- fbregs_pnl_fail:
+err_attached_crtsrc_file:
        device_remove_file(dev, &dev_attr_crt_src);
 
- crtsrc_fail:
-       unregister_framebuffer(fbinfo_pnl);
+err_started_panel:
+       unregister_framebuffer(info->fb[HEAD_PANEL]);
+       sm501_free_init_fb(info, HEAD_PANEL);
 
- register_pnl_fail:
-       unregister_framebuffer(fbinfo_crt);
+err_started_crt:
+       unregister_framebuffer(info->fb[HEAD_CRT]);
+       sm501_free_init_fb(info, HEAD_CRT);
 
- register_crt_fail:
+err_started:
        sm501fb_stop(info);
 
- sm501fb_start_fail:
-       sm501fb_info_release(info);
+err_probed_panel:
+       framebuffer_release(info->fb[HEAD_PANEL]);
 
- sm501fb_alloc_fail:
-       framebuffer_release(fbinfo_pnl);
+err_probed_crt:
+       framebuffer_release(info->fb[HEAD_CRT]);
 
- fbinfo_crt_alloc_fail:
-       framebuffer_release(fbinfo_crt);
+err_alloc:
+       kfree(info);
 
        return ret;
 }
@@ -1681,11 +1761,14 @@ static int sm501fb_remove(struct platform_device *pdev)
        device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
        device_remove_file(&pdev->dev, &dev_attr_crt_src);
 
+       sm501_free_init_fb(info, HEAD_CRT);
+       sm501_free_init_fb(info, HEAD_PANEL);
+
        unregister_framebuffer(fbinfo_crt);
        unregister_framebuffer(fbinfo_pnl);
 
        sm501fb_stop(info);
-       sm501fb_info_release(info);
+       kfree(info);
 
        framebuffer_release(fbinfo_pnl);
        framebuffer_release(fbinfo_crt);
index 1a9a60c74be3111b7b765d0fbba6b33b12332be6..7fe5be4bc70e4ad3ff073ef576cb9c52533e40ed 100644 (file)
@@ -352,8 +352,6 @@ struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */
 
 /* functions to call the STI ROM directly */
 
-int  sti_init_graph(struct sti_struct *sti);
-void sti_inq_conf(struct sti_struct *sti);
 void sti_putc(struct sti_struct *sti, int c, int y, int x);
 void sti_set(struct sti_struct *sti, int src_y, int src_x,
             int height, int width, u8 color);
index 598d35eff935ae18e8db7e77e6cfebbab493d462..166481402412538fc2b778924524ff67ae3fe9a6 100644 (file)
@@ -1078,8 +1078,7 @@ static struct fb_ops stifb_ops = {
  *  Initialization
  */
 
-int __init
-stifb_init_fb(struct sti_struct *sti, int bpp_pref)
+static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
 {
        struct fb_fix_screeninfo *fix;
        struct fb_var_screeninfo *var;
@@ -1315,8 +1314,7 @@ static int stifb_disabled __initdata;
 int __init
 stifb_setup(char *options);
 
-int __init
-stifb_init(void)
+static int __init stifb_init(void)
 {
        struct sti_struct *sti;
        struct sti_struct *def_sti;
index ea9f19d2559799155c0eb330d395f8f7f3786f92..77aafcfae0373ce0b50a0f8210ad0e9f85c67dec 100644 (file)
@@ -836,16 +836,12 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
        struct tdfx_par *par = info->par;
        u32 addr = var->yoffset * info->fix.line_length;
 
-       if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))
-               return -EINVAL;
-       if ((var->yoffset + var->yres > var->yres_virtual && nowrap))
+       if (nopan || var->xoffset)
                return -EINVAL;
 
        banshee_make_room(par, 1);
        tdfx_outl(par, VIDDESKSTART, addr);
 
-       info->var.xoffset = var->xoffset;
-       info->var.yoffset = var->yoffset;
        return 0;
 }
 
@@ -1426,6 +1422,8 @@ MODULE_LICENSE("GPL");
 module_param(hwcursor, int, 0644);
 MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
                        "(1=enable, 0=disable, default=1)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
 #ifdef CONFIG_MTRR
 module_param(nomtrr, bool, 0);
 MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)");
index beefab2992c042834fff60ad45a6ee92680ffcb0..479b2e79ad68ea569882bf7ce7df7645d648a02d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Frame buffer driver for Trident Blade and Image series
+ * Frame buffer driver for Trident TGUI, Blade and Image series
  *
  * Copyright 2001, 2002 - Jani Monoses   <jani@iv.ro>
  *
@@ -13,7 +13,6 @@
  *     code, suggestions
  * TODO:
  *     timing value tweaking so it looks good on every monitor in every mode
- *     TGUI acceleration
  */
 
 #include <linux/module.h>
 #include <linux/pci.h>
 
 #include <linux/delay.h>
+#include <video/vga.h>
 #include <video/trident.h>
 
-#define VERSION                "0.7.8-NEWAPI"
-
 struct tridentfb_par {
        void __iomem *io_virt;  /* iospace virtual memory address */
+       u32 pseudo_pal[16];
+       int chip_id;
+       int flatpanel;
+       void (*init_accel) (struct tridentfb_par *, int, int);
+       void (*wait_engine) (struct tridentfb_par *);
+       void (*fill_rect)
+               (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
+       void (*copy_rect)
+               (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
+       void (*image_blit)
+               (struct tridentfb_par *par, const char*,
+                u32, u32, u32, u32, u32, u32);
+       unsigned char eng_oper; /* engine operation... */
 };
 
-static unsigned char eng_oper; /* engine operation... */
-static struct fb_ops tridentfb_ops;
-
-static struct tridentfb_par default_par;
-
-/* FIXME:kmalloc these 3 instead */
-static struct fb_info fb_info;
-static u32 pseudo_pal[16];
-
-static struct fb_var_screeninfo default_var;
-
 static struct fb_fix_screeninfo tridentfb_fix = {
        .id = "Trident",
        .type = FB_TYPE_PACKED_PIXELS,
@@ -49,27 +49,22 @@ static struct fb_fix_screeninfo tridentfb_fix = {
        .accel = FB_ACCEL_NONE,
 };
 
-static int chip_id;
-
-static int defaultaccel;
-static int displaytype;
-
 /* defaults which are normally overriden by user values */
 
 /* video mode */
-static char *mode_option __devinitdata = "640x480";
-static int bpp = 8;
+static char *mode_option __devinitdata = "640x480-8@60";
+static int bpp __devinitdata = 8;
 
-static int noaccel;
+static int noaccel __devinitdata;
 
 static int center;
 static int stretch;
 
-static int fp;
-static int crt;
+static int fp __devinitdata;
+static int crt __devinitdata;
 
-static int memsize;
-static int memdiff;
+static int memsize __devinitdata;
+static int memdiff __devinitdata;
 static int nativex;
 
 module_param(mode_option, charp, 0);
@@ -84,25 +79,53 @@ module_param(memsize, int, 0);
 module_param(memdiff, int, 0);
 module_param(nativex, int, 0);
 module_param(fp, int, 0);
+MODULE_PARM_DESC(fp, "Define if flatpanel is connected");
 module_param(crt, int, 0);
+MODULE_PARM_DESC(crt, "Define if CRT is connected");
+
+static inline int is_oldclock(int id)
+{
+       return  (id == TGUI9440) ||
+               (id == TGUI9660) ||
+               (id == CYBER9320);
+}
+
+static inline int is_oldprotect(int id)
+{
+       return  is_oldclock(id) ||
+               (id == PROVIDIA9685) ||
+               (id == CYBER9382) ||
+               (id == CYBER9385);
+}
+
+static inline int is_blade(int id)
+{
+       return  (id == BLADE3D) ||
+               (id == CYBERBLADEE4) ||
+               (id == CYBERBLADEi7) ||
+               (id == CYBERBLADEi7D) ||
+               (id == CYBERBLADEi1) ||
+               (id == CYBERBLADEi1D) ||
+               (id == CYBERBLADEAi1) ||
+               (id == CYBERBLADEAi1D);
+}
 
-static int chip3D;
-static int chipcyber;
+static inline int is_xp(int id)
+{
+       return  (id == CYBERBLADEXPAi1) ||
+               (id == CYBERBLADEXPm8) ||
+               (id == CYBERBLADEXPm16);
+}
 
-static int is3Dchip(int id)
+static inline int is3Dchip(int id)
 {
-       return ((id == BLADE3D) || (id == CYBERBLADEE4) ||
-               (id == CYBERBLADEi7) || (id == CYBERBLADEi7D) ||
+       return  is_blade(id) || is_xp(id) ||
                (id == CYBER9397) || (id == CYBER9397DVD) ||
                (id == CYBER9520) || (id == CYBER9525DVD) ||
-               (id == IMAGE975) || (id == IMAGE985) ||
-               (id == CYBERBLADEi1) || (id == CYBERBLADEi1D) ||
-               (id == CYBERBLADEAi1) || (id == CYBERBLADEAi1D) ||
-               (id == CYBERBLADEXPm8) || (id == CYBERBLADEXPm16) ||
-               (id == CYBERBLADEXPAi1));
+               (id == IMAGE975) || (id == IMAGE985);
 }
 
-static int iscyber(int id)
+static inline int iscyber(int id)
 {
        switch (id) {
        case CYBER9388:
@@ -122,12 +145,7 @@ static int iscyber(int id)
                return 1;
 
        case CYBER9320:
-       case TGUI9660:
-       case IMAGE975:
-       case IMAGE985:
-       case BLADE3D:
        case CYBERBLADEi7:      /* VIA MPV4 integrated version */
-
        default:
                /* case CYBERBLDAEXPm8:  Strange */
                /* case CYBERBLDAEXPm16: Strange */
@@ -135,147 +153,110 @@ static int iscyber(int id)
        }
 }
 
-#define CRT 0x3D0              /* CRTC registers offset for color display */
-
-#ifndef TRIDENT_MMIO
-       #define TRIDENT_MMIO 1
-#endif
-
-#if TRIDENT_MMIO
-       #define t_outb(val, reg)        writeb(val,((struct tridentfb_par *)(fb_info.par))->io_virt + reg)
-       #define t_inb(reg)      readb(((struct tridentfb_par*)(fb_info.par))->io_virt + reg)
-#else
-       #define t_outb(val, reg) outb(val, reg)
-       #define t_inb(reg) inb(reg)
-#endif
+static inline void t_outb(struct tridentfb_par *p, u8 val, u16 reg)
+{
+       fb_writeb(val, p->io_virt + reg);
+}
 
+static inline u8 t_inb(struct tridentfb_par *p, u16 reg)
+{
+       return fb_readb(p->io_virt + reg);
+}
 
-static struct accel_switch {
-       void (*init_accel) (int, int);
-       void (*wait_engine) (void);
-       void (*fill_rect) (u32, u32, u32, u32, u32, u32);
-       void (*copy_rect) (u32, u32, u32, u32, u32, u32);
-} *acc;
+static inline void writemmr(struct tridentfb_par *par, u16 r, u32 v)
+{
+       fb_writel(v, par->io_virt + r);
+}
 
-#define writemmr(r, v) writel(v, ((struct tridentfb_par *)fb_info.par)->io_virt + r)
-#define readmmr(r)     readl(((struct tridentfb_par *)fb_info.par)->io_virt + r)
+static inline u32 readmmr(struct tridentfb_par *par, u16 r)
+{
+       return fb_readl(par->io_virt + r);
+}
 
 /*
  * Blade specific acceleration.
  */
 
 #define point(x, y) ((y) << 16 | (x))
-#define STA    0x2120
-#define CMD    0x2144
-#define ROP    0x2148
-#define CLR    0x2160
-#define SR1    0x2100
-#define SR2    0x2104
-#define DR1    0x2108
-#define DR2    0x210C
-
-#define ROP_S  0xCC
-
-static void blade_init_accel(int pitch, int bpp)
+
+static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp)
 {
        int v1 = (pitch >> 3) << 20;
-       int tmp = 0, v2;
-       switch (bpp) {
-       case 8:
-               tmp = 0;
-               break;
-       case 15:
-               tmp = 5;
-               break;
-       case 16:
-               tmp = 1;
-               break;
-       case 24:
-       case 32:
-               tmp = 2;
-               break;
-       }
-       v2 = v1 | (tmp << 29);
-       writemmr(0x21C0, v2);
-       writemmr(0x21C4, v2);
-       writemmr(0x21B8, v2);
-       writemmr(0x21BC, v2);
-       writemmr(0x21D0, v1);
-       writemmr(0x21D4, v1);
-       writemmr(0x21C8, v1);
-       writemmr(0x21CC, v1);
-       writemmr(0x216C, 0);
+       int tmp = bpp == 24 ? 2 : (bpp >> 4);
+       int v2 = v1 | (tmp << 29);
+
+       writemmr(par, 0x21C0, v2);
+       writemmr(par, 0x21C4, v2);
+       writemmr(par, 0x21B8, v2);
+       writemmr(par, 0x21BC, v2);
+       writemmr(par, 0x21D0, v1);
+       writemmr(par, 0x21D4, v1);
+       writemmr(par, 0x21C8, v1);
+       writemmr(par, 0x21CC, v1);
+       writemmr(par, 0x216C, 0);
 }
 
-static void blade_wait_engine(void)
+static void blade_wait_engine(struct tridentfb_par *par)
 {
-       while (readmmr(STA) & 0xFA800000) ;
+       while (readmmr(par, STATUS) & 0xFA800000)
+               cpu_relax();
 }
 
-static void blade_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+static void blade_fill_rect(struct tridentfb_par *par,
+                           u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
 {
-       writemmr(CLR, c);
-       writemmr(ROP, rop ? 0x66 : ROP_S);
-       writemmr(CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
+       writemmr(par, COLOR, c);
+       writemmr(par, ROP, rop ? ROP_X : ROP_S);
+       writemmr(par, CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
 
-       writemmr(DR1, point(x, y));
-       writemmr(DR2, point(x + w - 1, y + h - 1));
+       writemmr(par, DST1, point(x, y));
+       writemmr(par, DST2, point(x + w - 1, y + h - 1));
 }
 
-static void blade_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+static void blade_image_blit(struct tridentfb_par *par, const char *data,
+                            u32 x, u32 y, u32 w, u32 h, u32 c, u32 b)
+{
+       unsigned size = ((w + 31) >> 5) * h;
+
+       writemmr(par, COLOR, c);
+       writemmr(par, BGCOLOR, b);
+       writemmr(par, CMD, 0xa0000000 | 3 << 19);
+
+       writemmr(par, DST1, point(x, y));
+       writemmr(par, DST2, point(x + w - 1, y + h - 1));
+
+       memcpy(par->io_virt + 0x10000, data, 4 * size);
+}
+
+static void blade_copy_rect(struct tridentfb_par *par,
+                           u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
 {
-       u32 s1, s2, d1, d2;
        int direction = 2;
-       s1 = point(x1, y1);
-       s2 = point(x1 + w - 1, y1 + h - 1);
-       d1 = point(x2, y2);
-       d2 = point(x2 + w - 1, y2 + h - 1);
+       u32 s1 = point(x1, y1);
+       u32 s2 = point(x1 + w - 1, y1 + h - 1);
+       u32 d1 = point(x2, y2);
+       u32 d2 = point(x2 + w - 1, y2 + h - 1);
 
        if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
                direction = 0;
 
-       writemmr(ROP, ROP_S);
-       writemmr(CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
+       writemmr(par, ROP, ROP_S);
+       writemmr(par, CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
 
-       writemmr(SR1, direction ? s2 : s1);
-       writemmr(SR2, direction ? s1 : s2);
-       writemmr(DR1, direction ? d2 : d1);
-       writemmr(DR2, direction ? d1 : d2);
+       writemmr(par, SRC1, direction ? s2 : s1);
+       writemmr(par, SRC2, direction ? s1 : s2);
+       writemmr(par, DST1, direction ? d2 : d1);
+       writemmr(par, DST2, direction ? d1 : d2);
 }
 
-static struct accel_switch accel_blade = {
-       blade_init_accel,
-       blade_wait_engine,
-       blade_fill_rect,
-       blade_copy_rect,
-};
-
 /*
  * BladeXP specific acceleration functions
  */
 
-#define ROP_P 0xF0
-#define masked_point(x, y) ((y & 0xffff)<<16|(x & 0xffff))
-
-static void xp_init_accel(int pitch, int bpp)
+static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp)
 {
-       int tmp = 0, v1;
-       unsigned char x = 0;
-
-       switch (bpp) {
-       case 8:
-               x = 0;
-               break;
-       case 16:
-               x = 1;
-               break;
-       case 24:
-               x = 3;
-               break;
-       case 32:
-               x = 2;
-               break;
-       }
+       unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
+       int v1 = pitch << (bpp == 24 ? 20 : (18 + x));
 
        switch (pitch << (bpp >> 3)) {
        case 8192:
@@ -293,42 +274,21 @@ static void xp_init_accel(int pitch, int bpp)
                break;
        }
 
-       t_outb(x, 0x2125);
-
-       eng_oper = x | 0x40;
-
-       switch (bpp) {
-       case 8:
-               tmp = 18;
-               break;
-       case 15:
-       case 16:
-               tmp = 19;
-               break;
-       case 24:
-       case 32:
-               tmp = 20;
-               break;
-       }
+       t_outb(par, x, 0x2125);
 
-       v1 = pitch << tmp;
+       par->eng_oper = x | 0x40;
 
-       writemmr(0x2154, v1);
-       writemmr(0x2150, v1);
-       t_outb(3, 0x2126);
+       writemmr(par, 0x2154, v1);
+       writemmr(par, 0x2150, v1);
+       t_outb(par, 3, 0x2126);
 }
 
-static void xp_wait_engine(void)
+static void xp_wait_engine(struct tridentfb_par *par)
 {
-       int busy;
-       int count, timeout;
-
-       count = 0;
-       timeout = 0;
-       for (;;) {
-               busy = t_inb(STA) & 0x80;
-               if (busy != 0x80)
-                       return;
+       int count = 0;
+       int timeout = 0;
+
+       while (t_inb(par, STATUS) & 0x80) {
                count++;
                if (count == 10000000) {
                        /* Timeout */
@@ -336,30 +296,31 @@ static void xp_wait_engine(void)
                        timeout++;
                        if (timeout == 8) {
                                /* Reset engine */
-                               t_outb(0x00, 0x2120);
+                               t_outb(par, 0x00, STATUS);
                                return;
                        }
                }
+               cpu_relax();
        }
 }
 
-static void xp_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+static void xp_fill_rect(struct tridentfb_par *par,
+                        u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
 {
-       writemmr(0x2127, ROP_P);
-       writemmr(0x2158, c);
-       writemmr(0x2128, 0x4000);
-       writemmr(0x2140, masked_point(h, w));
-       writemmr(0x2138, masked_point(y, x));
-       t_outb(0x01, 0x2124);
-       t_outb(eng_oper, 0x2125);
+       writemmr(par, 0x2127, ROP_P);
+       writemmr(par, 0x2158, c);
+       writemmr(par, DRAWFL, 0x4000);
+       writemmr(par, OLDDIM, point(h, w));
+       writemmr(par, OLDDST, point(y, x));
+       t_outb(par, 0x01, OLDCMD);
+       t_outb(par, par->eng_oper, 0x2125);
 }
 
-static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+static void xp_copy_rect(struct tridentfb_par *par,
+                        u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
 {
-       int direction;
        u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
-
-       direction = 0x0004;
+       int direction = 0x0004;
 
        if ((x1 < x2) && (y1 == y2)) {
                direction |= 0x0200;
@@ -379,103 +340,152 @@ static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
                y2_tmp = y2;
        }
 
-       writemmr(0x2128, direction);
-       t_outb(ROP_S, 0x2127);
-       writemmr(0x213C, masked_point(y1_tmp, x1_tmp));
-       writemmr(0x2138, masked_point(y2_tmp, x2_tmp));
-       writemmr(0x2140, masked_point(h, w));
-       t_outb(0x01, 0x2124);
+       writemmr(par, DRAWFL, direction);
+       t_outb(par, ROP_S, 0x2127);
+       writemmr(par, OLDSRC, point(y1_tmp, x1_tmp));
+       writemmr(par, OLDDST, point(y2_tmp, x2_tmp));
+       writemmr(par, OLDDIM, point(h, w));
+       t_outb(par, 0x01, OLDCMD);
 }
 
-static struct accel_switch accel_xp = {
-       xp_init_accel,
-       xp_wait_engine,
-       xp_fill_rect,
-       xp_copy_rect,
-};
-
 /*
  * Image specific acceleration functions
  */
-static void image_init_accel(int pitch, int bpp)
+static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp)
 {
-       int tmp = 0;
-       switch (bpp) {
-       case 8:
-               tmp = 0;
-               break;
-       case 15:
-               tmp = 5;
-               break;
-       case 16:
-               tmp = 1;
-               break;
-       case 24:
-       case 32:
-               tmp = 2;
-               break;
-       }
-       writemmr(0x2120, 0xF0000000);
-       writemmr(0x2120, 0x40000000 | tmp);
-       writemmr(0x2120, 0x80000000);
-       writemmr(0x2144, 0x00000000);
-       writemmr(0x2148, 0x00000000);
-       writemmr(0x2150, 0x00000000);
-       writemmr(0x2154, 0x00000000);
-       writemmr(0x2120, 0x60000000 | (pitch << 16) | pitch);
-       writemmr(0x216C, 0x00000000);
-       writemmr(0x2170, 0x00000000);
-       writemmr(0x217C, 0x00000000);
-       writemmr(0x2120, 0x10000000);
-       writemmr(0x2130, (2047 << 16) | 2047);
+       int tmp = bpp == 24 ? 2: (bpp >> 4);
+
+       writemmr(par, 0x2120, 0xF0000000);
+       writemmr(par, 0x2120, 0x40000000 | tmp);
+       writemmr(par, 0x2120, 0x80000000);
+       writemmr(par, 0x2144, 0x00000000);
+       writemmr(par, 0x2148, 0x00000000);
+       writemmr(par, 0x2150, 0x00000000);
+       writemmr(par, 0x2154, 0x00000000);
+       writemmr(par, 0x2120, 0x60000000 | (pitch << 16) | pitch);
+       writemmr(par, 0x216C, 0x00000000);
+       writemmr(par, 0x2170, 0x00000000);
+       writemmr(par, 0x217C, 0x00000000);
+       writemmr(par, 0x2120, 0x10000000);
+       writemmr(par, 0x2130, (2047 << 16) | 2047);
 }
 
-static void image_wait_engine(void)
+static void image_wait_engine(struct tridentfb_par *par)
 {
-       while (readmmr(0x2164) & 0xF0000000) ;
+       while (readmmr(par, 0x2164) & 0xF0000000)
+               cpu_relax();
 }
 
-static void image_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+static void image_fill_rect(struct tridentfb_par *par,
+                           u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
 {
-       writemmr(0x2120, 0x80000000);
-       writemmr(0x2120, 0x90000000 | ROP_S);
+       writemmr(par, 0x2120, 0x80000000);
+       writemmr(par, 0x2120, 0x90000000 | ROP_S);
 
-       writemmr(0x2144, c);
+       writemmr(par, 0x2144, c);
 
-       writemmr(DR1, point(x, y));
-       writemmr(DR2, point(x + w - 1, y + h - 1));
+       writemmr(par, DST1, point(x, y));
+       writemmr(par, DST2, point(x + w - 1, y + h - 1));
 
-       writemmr(0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
+       writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
 }
 
-static void image_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+static void image_copy_rect(struct tridentfb_par *par,
+                           u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
 {
-       u32 s1, s2, d1, d2;
-       int direction = 2;
-       s1 = point(x1, y1);
-       s2 = point(x1 + w - 1, y1 + h - 1);
-       d1 = point(x2, y2);
-       d2 = point(x2 + w - 1, y2 + h - 1);
+       int direction = 0x4;
+       u32 s1 = point(x1, y1);
+       u32 s2 = point(x1 + w - 1, y1 + h - 1);
+       u32 d1 = point(x2, y2);
+       u32 d2 = point(x2 + w - 1, y2 + h - 1);
 
        if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
                direction = 0;
 
-       writemmr(0x2120, 0x80000000);
-       writemmr(0x2120, 0x90000000 | ROP_S);
+       writemmr(par, 0x2120, 0x80000000);
+       writemmr(par, 0x2120, 0x90000000 | ROP_S);
 
-       writemmr(SR1, direction ? s2 : s1);
-       writemmr(SR2, direction ? s1 : s2);
-       writemmr(DR1, direction ? d2 : d1);
-       writemmr(DR2, direction ? d1 : d2);
-       writemmr(0x2124, 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
+       writemmr(par, SRC1, direction ? s2 : s1);
+       writemmr(par, SRC2, direction ? s1 : s2);
+       writemmr(par, DST1, direction ? d2 : d1);
+       writemmr(par, DST2, direction ? d1 : d2);
+       writemmr(par, 0x2124,
+                0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
 }
 
-static struct accel_switch accel_image = {
-       image_init_accel,
-       image_wait_engine,
-       image_fill_rect,
-       image_copy_rect,
-};
+/*
+ * TGUI 9440/96XX acceleration
+ */
+
+static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp)
+{
+       unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
+
+       /* disable clipping */
+       writemmr(par, 0x2148, 0);
+       writemmr(par, 0x214C, point(4095, 2047));
+
+       switch ((pitch * bpp) / 8) {
+       case 8192:
+       case 512:
+               x |= 0x00;
+               break;
+       case 1024:
+               x |= 0x04;
+               break;
+       case 2048:
+               x |= 0x08;
+               break;
+       case 4096:
+               x |= 0x0C;
+               break;
+       }
+
+       fb_writew(x, par->io_virt + 0x2122);
+}
+
+static void tgui_fill_rect(struct tridentfb_par *par,
+                          u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+{
+       t_outb(par, ROP_P, 0x2127);
+       writemmr(par, OLDCLR, c);
+       writemmr(par, DRAWFL, 0x4020);
+       writemmr(par, OLDDIM, point(w - 1, h - 1));
+       writemmr(par, OLDDST, point(x, y));
+       t_outb(par, 1, OLDCMD);
+}
+
+static void tgui_copy_rect(struct tridentfb_par *par,
+                          u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+{
+       int flags = 0;
+       u16 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
+
+       if ((x1 < x2) && (y1 == y2)) {
+               flags |= 0x0200;
+               x1_tmp = x1 + w - 1;
+               x2_tmp = x2 + w - 1;
+       } else {
+               x1_tmp = x1;
+               x2_tmp = x2;
+       }
+
+       if (y1 < y2) {
+               flags |= 0x0100;
+               y1_tmp = y1 + h - 1;
+               y2_tmp = y2 + h - 1;
+       } else {
+               y1_tmp = y1;
+               y2_tmp = y2;
+       }
+
+       writemmr(par, DRAWFL, 0x4 | flags);
+       t_outb(par, ROP_S, 0x2127);
+       writemmr(par, OLDSRC, point(x1_tmp, y1_tmp));
+       writemmr(par, OLDDST, point(x2_tmp, y2_tmp));
+       writemmr(par, OLDDIM, point(w - 1, h - 1));
+       t_outb(par, 1, OLDCMD);
+}
 
 /*
  * Accel functions called by the upper layers
@@ -484,129 +494,162 @@ static struct accel_switch accel_image = {
 static void tridentfb_fillrect(struct fb_info *info,
                               const struct fb_fillrect *fr)
 {
-       int bpp = info->var.bits_per_pixel;
-       int col = 0;
+       struct tridentfb_par *par = info->par;
+       int col;
 
-       switch (bpp) {
-       default:
-       case 8:
-               col |= fr->color;
+       if (info->flags & FBINFO_HWACCEL_DISABLED) {
+               cfb_fillrect(info, fr);
+               return;
+       }
+       if (info->var.bits_per_pixel == 8) {
+               col = fr->color;
                col |= col << 8;
                col |= col << 16;
-               break;
-       case 16:
+       } else
                col = ((u32 *)(info->pseudo_palette))[fr->color];
-               break;
-       case 32:
-               col = ((u32 *)(info->pseudo_palette))[fr->color];
-               break;
+
+       par->wait_engine(par);
+       par->fill_rect(par, fr->dx, fr->dy, fr->width,
+                      fr->height, col, fr->rop);
+}
+
+static void tridentfb_imageblit(struct fb_info *info,
+                               const struct fb_image *img)
+{
+       struct tridentfb_par *par = info->par;
+       int col, bgcol;
+
+       if ((info->flags & FBINFO_HWACCEL_DISABLED) || img->depth != 1) {
+               cfb_imageblit(info, img);
+               return;
+       }
+       if (info->var.bits_per_pixel == 8) {
+               col = img->fg_color;
+               col |= col << 8;
+               col |= col << 16;
+               bgcol = img->bg_color;
+               bgcol |= bgcol << 8;
+               bgcol |= bgcol << 16;
+       } else {
+               col = ((u32 *)(info->pseudo_palette))[img->fg_color];
+               bgcol = ((u32 *)(info->pseudo_palette))[img->bg_color];
        }
 
-       acc->fill_rect(fr->dx, fr->dy, fr->width, fr->height, col, fr->rop);
-       acc->wait_engine();
+       par->wait_engine(par);
+       if (par->image_blit)
+               par->image_blit(par, img->data, img->dx, img->dy,
+                               img->width, img->height, col, bgcol);
+       else
+               cfb_imageblit(info, img);
 }
+
 static void tridentfb_copyarea(struct fb_info *info,
                               const struct fb_copyarea *ca)
 {
-       acc->copy_rect(ca->sx, ca->sy, ca->dx, ca->dy, ca->width, ca->height);
-       acc->wait_engine();
+       struct tridentfb_par *par = info->par;
+
+       if (info->flags & FBINFO_HWACCEL_DISABLED) {
+               cfb_copyarea(info, ca);
+               return;
+       }
+       par->wait_engine(par);
+       par->copy_rect(par, ca->sx, ca->sy, ca->dx, ca->dy,
+                      ca->width, ca->height);
+}
+
+static int tridentfb_sync(struct fb_info *info)
+{
+       struct tridentfb_par *par = info->par;
+
+       if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+               par->wait_engine(par);
+       return 0;
 }
-#else /* !CONFIG_FB_TRIDENT_ACCEL */
+#else
 #define tridentfb_fillrect cfb_fillrect
 #define tridentfb_copyarea cfb_copyarea
+#define tridentfb_imageblit cfb_imageblit
 #endif /* CONFIG_FB_TRIDENT_ACCEL */
 
-
 /*
  * Hardware access functions
  */
 
-static inline unsigned char read3X4(int reg)
+static inline unsigned char read3X4(struct tridentfb_par *par, int reg)
 {
-       struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par;
-       writeb(reg, par->io_virt + CRT + 4);
-       return readb(par->io_virt + CRT + 5);
+       return vga_mm_rcrt(par->io_virt, reg);
 }
 
-static inline void write3X4(int reg, unsigned char val)
+static inline void write3X4(struct tridentfb_par *par, int reg,
+                           unsigned char val)
 {
-       struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par;
-       writeb(reg, par->io_virt + CRT + 4);
-       writeb(val, par->io_virt + CRT + 5);
+       vga_mm_wcrt(par->io_virt, reg, val);
 }
 
-static inline unsigned char read3C4(int reg)
+static inline unsigned char read3CE(struct tridentfb_par *par,
+                                   unsigned char reg)
 {
-       t_outb(reg, 0x3C4);
-       return t_inb(0x3C5);
+       return vga_mm_rgfx(par->io_virt, reg);
 }
 
-static inline void write3C4(int reg, unsigned char val)
+static inline void writeAttr(struct tridentfb_par *par, int reg,
+                            unsigned char val)
 {
-       t_outb(reg, 0x3C4);
-       t_outb(val, 0x3C5);
+       fb_readb(par->io_virt + VGA_IS1_RC);    /* flip-flop to index */
+       vga_mm_wattr(par->io_virt, reg, val);
 }
 
-static inline unsigned char read3CE(int reg)
+static inline void write3CE(struct tridentfb_par *par, int reg,
+                           unsigned char val)
 {
-       t_outb(reg, 0x3CE);
-       return t_inb(0x3CF);
+       vga_mm_wgfx(par->io_virt, reg, val);
 }
 
-static inline void writeAttr(int reg, unsigned char val)
-{
-       readb(((struct tridentfb_par *)fb_info.par)->io_virt + CRT + 0x0A);     /* flip-flop to index */
-       t_outb(reg, 0x3C0);
-       t_outb(val, 0x3C0);
-}
-
-static inline void write3CE(int reg, unsigned char val)
-{
-       t_outb(reg, 0x3CE);
-       t_outb(val, 0x3CF);
-}
-
-static void enable_mmio(void)
+static void enable_mmio(struct tridentfb_par *par)
 {
        /* Goto New Mode */
-       outb(0x0B, 0x3C4);
-       inb(0x3C5);
+       vga_io_rseq(0x0B);
 
        /* Unprotect registers */
-       outb(NewMode1, 0x3C4);
-       outb(0x80, 0x3C5);
+       vga_io_wseq(NewMode1, 0x80);
+       if (!is_oldprotect(par->chip_id))
+               vga_io_wseq(Protection, 0x92);
 
        /* Enable MMIO */
        outb(PCIReg, 0x3D4);
        outb(inb(0x3D5) | 0x01, 0x3D5);
 }
 
-static void disable_mmio(void)
+static void disable_mmio(struct tridentfb_par *par)
 {
        /* Goto New Mode */
-       t_outb(0x0B, 0x3C4);
-       t_inb(0x3C5);
+       vga_mm_rseq(par->io_virt, 0x0B);
 
        /* Unprotect registers */
-       t_outb(NewMode1, 0x3C4);
-       t_outb(0x80, 0x3C5);
+       vga_mm_wseq(par->io_virt, NewMode1, 0x80);
+       if (!is_oldprotect(par->chip_id))
+               vga_mm_wseq(par->io_virt, Protection, 0x92);
 
        /* Disable MMIO */
-       t_outb(PCIReg, 0x3D4);
-       t_outb(t_inb(0x3D5) & ~0x01, 0x3D5);
+       t_outb(par, PCIReg, 0x3D4);
+       t_outb(par, t_inb(par, 0x3D5) & ~0x01, 0x3D5);
 }
 
-#define crtc_unlock()  write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
+static inline void crtc_unlock(struct tridentfb_par *par)
+{
+       write3X4(par, VGA_CRTC_V_SYNC_END,
+                read3X4(par, VGA_CRTC_V_SYNC_END) & 0x7F);
+}
 
 /*  Return flat panel's maximum x resolution */
-static int __devinit get_nativex(void)
+static int __devinit get_nativex(struct tridentfb_par *par)
 {
        int x, y, tmp;
 
        if (nativex)
                return nativex;
 
-       tmp = (read3CE(VertStretch) >> 4) & 3;
+       tmp = (read3CE(par, VertStretch) >> 4) & 3;
 
        switch (tmp) {
        case 0:
@@ -632,77 +675,92 @@ static int __devinit get_nativex(void)
 }
 
 /* Set pitch */
-static void set_lwidth(int width)
+static inline void set_lwidth(struct tridentfb_par *par, int width)
 {
-       write3X4(Offset, width & 0xFF);
-       write3X4(AddColReg,
-                (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >> 4));
+       write3X4(par, VGA_CRTC_OFFSET, width & 0xFF);
+       write3X4(par, AddColReg,
+                (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4));
 }
 
 /* For resolutions smaller than FP resolution stretch */
-static void screen_stretch(void)
+static void screen_stretch(struct tridentfb_par *par)
 {
-       if (chip_id != CYBERBLADEXPAi1)
-               write3CE(BiosReg, 0);
+       if (par->chip_id != CYBERBLADEXPAi1)
+               write3CE(par, BiosReg, 0);
        else
-               write3CE(BiosReg, 8);
-       write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 1);
-       write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 1);
+               write3CE(par, BiosReg, 8);
+       write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 1);
+       write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 1);
 }
 
 /* For resolutions smaller than FP resolution center */
-static void screen_center(void)
+static inline void screen_center(struct tridentfb_par *par)
 {
-       write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 0x80);
-       write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 0x80);
+       write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 0x80);
+       write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 0x80);
 }
 
 /* Address of first shown pixel in display memory */
-static void set_screen_start(int base)
+static void set_screen_start(struct tridentfb_par *par, int base)
 {
-       write3X4(StartAddrLow, base & 0xFF);
-       write3X4(StartAddrHigh, (base & 0xFF00) >> 8);
-       write3X4(CRTCModuleTest,
-                (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >> 11));
-       write3X4(CRTHiOrd,
-                (read3X4(CRTHiOrd) & 0xF8) | ((base & 0xE0000) >> 17));
+       u8 tmp;
+       write3X4(par, VGA_CRTC_START_LO, base & 0xFF);
+       write3X4(par, VGA_CRTC_START_HI, (base & 0xFF00) >> 8);
+       tmp = read3X4(par, CRTCModuleTest) & 0xDF;
+       write3X4(par, CRTCModuleTest, tmp | ((base & 0x10000) >> 11));
+       tmp = read3X4(par, CRTHiOrd) & 0xF8;
+       write3X4(par, CRTHiOrd, tmp | ((base & 0xE0000) >> 17));
 }
 
 /* Set dotclock frequency */
-static void set_vclk(unsigned long freq)
+static void set_vclk(struct tridentfb_par *par, unsigned long freq)
 {
        int m, n, k;
-       unsigned long f, fi, d, di;
-       unsigned char lo = 0, hi = 0;
+       unsigned long fi, d, di;
+       unsigned char best_m = 0, best_n = 0, best_k = 0;
+       unsigned char hi, lo;
+       unsigned char shift = !is_oldclock(par->chip_id) ? 2 : 1;
 
        d = 20000;
-       for (k = 2; k >= 0; k--)
-               for (m = 0; m < 63; m++)
-                       for (n = 0; n < 128; n++) {
+       for (k = shift; k >= 0; k--)
+               for (m = 1; m < 32; m++) {
+                       n = ((m + 2) << shift) - 8;
+                       for (n = (n < 0 ? 0 : n); n < 122; n++) {
                                fi = ((14318l * (n + 8)) / (m + 2)) >> k;
-                               if ((di = abs(fi - freq)) < d) {
+                               di = abs(fi - freq);
+                               if (di < d || (di == d && k == best_k)) {
                                        d = di;
-                                       f = fi;
-                                       lo = n;
-                                       hi = (k << 6) | m;
+                                       best_n = n;
+                                       best_m = m;
+                                       best_k = k;
                                }
                                if (fi > freq)
                                        break;
                        }
-       if (chip3D) {
-               write3C4(ClockHigh, hi);
-               write3C4(ClockLow, lo);
+               }
+
+       if (is_oldclock(par->chip_id)) {
+               lo = best_n | (best_m << 7);
+               hi = (best_m >> 1) | (best_k << 4);
        } else {
-               outb(lo, 0x43C8);
-               outb(hi, 0x43C9);
+               lo = best_n;
+               hi = best_m | (best_k << 6);
+       }
+
+       if (is3Dchip(par->chip_id)) {
+               vga_mm_wseq(par->io_virt, ClockHigh, hi);
+               vga_mm_wseq(par->io_virt, ClockLow, lo);
+       } else {
+               t_outb(par, lo, 0x43C8);
+               t_outb(par, hi, 0x43C9);
        }
        debug("VCLK = %X %X\n", hi, lo);
 }
 
 /* Set number of lines for flat panels*/
-static void set_number_of_lines(int lines)
+static void set_number_of_lines(struct tridentfb_par *par, int lines)
 {
-       int tmp = read3CE(CyberEnhance) & 0x8F;
+       int tmp = read3CE(par, CyberEnhance) & 0x8F;
        if (lines > 1024)
                tmp |= 0x50;
        else if (lines > 768)
@@ -711,24 +769,24 @@ static void set_number_of_lines(int lines)
                tmp |= 0x20;
        else if (lines > 480)
                tmp |= 0x10;
-       write3CE(CyberEnhance, tmp);
+       write3CE(par, CyberEnhance, tmp);
 }
 
 /*
  * If we see that FP is active we assume we have one.
- * Otherwise we have a CRT display.User can override.
+ * Otherwise we have a CRT display. User can override.
  */
-static unsigned int __devinit get_displaytype(void)
+static int __devinit is_flatpanel(struct tridentfb_par *par)
 {
        if (fp)
-               return DISPLAY_FP;
-       if (crt || !chipcyber)
-               return DISPLAY_CRT;
-       return (read3CE(FPConfig) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
+               return 1;
+       if (crt || !iscyber(par->chip_id))
+               return 0;
+       return (read3CE(par, FPConfig) & 0x10) ? 1 : 0;
 }
 
 /* Try detecting the video memory size */
-static unsigned int __devinit get_memsize(void)
+static unsigned int __devinit get_memsize(struct tridentfb_par *par)
 {
        unsigned char tmp, tmp2;
        unsigned int k;
@@ -737,12 +795,12 @@ static unsigned int __devinit get_memsize(void)
        if (memsize)
                k = memsize * Kb;
        else
-               switch (chip_id) {
+               switch (par->chip_id) {
                case CYBER9525DVD:
                        k = 2560 * Kb;
                        break;
                default:
-                       tmp = read3X4(SPR) & 0x0F;
+                       tmp = read3X4(par, SPR) & 0x0F;
                        switch (tmp) {
 
                        case 0x01:
@@ -774,7 +832,7 @@ static unsigned int __devinit get_memsize(void)
                                break;
                        case 0x0E:              /* XP */
 
-                               tmp2 = read3C4(0xC1);
+                               tmp2 = vga_mm_rseq(par->io_virt, 0xC1);
                                switch (tmp2) {
                                case 0x00:
                                        k = 20 * Mb;
@@ -812,26 +870,67 @@ static unsigned int __devinit get_memsize(void)
 static int tridentfb_check_var(struct fb_var_screeninfo *var,
                               struct fb_info *info)
 {
+       struct tridentfb_par *par = info->par;
        int bpp = var->bits_per_pixel;
+       int line_length;
+       int ramdac = 230000; /* 230MHz for most 3D chips */
        debug("enter\n");
 
        /* check color depth */
        if (bpp == 24)
                bpp = var->bits_per_pixel = 32;
+       if (bpp != 8 && bpp != 16 && bpp != 32)
+               return -EINVAL;
+       if (par->chip_id == TGUI9440 && bpp == 32)
+               return -EINVAL;
        /* check whether resolution fits on panel and in memory */
-       if (flatpanel && nativex && var->xres > nativex)
+       if (par->flatpanel && nativex && var->xres > nativex)
+               return -EINVAL;
+       /* various resolution checks */
+       var->xres = (var->xres + 7) & ~0x7;
+       if (var->xres > var->xres_virtual)
+               var->xres_virtual = var->xres;
+       if (var->yres > var->yres_virtual)
+               var->yres_virtual = var->yres;
+       if (var->xres_virtual > 4095 || var->yres > 2048)
                return -EINVAL;
-       if (var->xres * var->yres_virtual * bpp / 8 > info->fix.smem_len)
+       /* prevent from position overflow for acceleration */
+       if (var->yres_virtual > 0xffff)
+               return -EINVAL;
+       line_length = var->xres_virtual * bpp / 8;
+
+       if (!is3Dchip(par->chip_id) &&
+           !(info->flags & FBINFO_HWACCEL_DISABLED)) {
+               /* acceleration requires line length to be power of 2 */
+               if (line_length <= 512)
+                       var->xres_virtual = 512 * 8 / bpp;
+               else if (line_length <= 1024)
+                       var->xres_virtual = 1024 * 8 / bpp;
+               else if (line_length <= 2048)
+                       var->xres_virtual = 2048 * 8 / bpp;
+               else if (line_length <= 4096)
+                       var->xres_virtual = 4096 * 8 / bpp;
+               else if (line_length <= 8192)
+                       var->xres_virtual = 8192 * 8 / bpp;
+               else
+                       return -EINVAL;
+
+               line_length = var->xres_virtual * bpp / 8;
+       }
+
+       /* datasheet specifies how to set panning only up to 4 MB */
+       if (line_length * (var->yres_virtual - var->yres) > (4 << 20))
+               var->yres_virtual = ((4 << 20) / line_length) + var->yres;
+
+       if (line_length * var->yres_virtual > info->fix.smem_len)
                return -EINVAL;
 
        switch (bpp) {
        case 8:
                var->red.offset = 0;
-               var->green.offset = 0;
-               var->blue.offset = 0;
-               var->red.length = 6;
-               var->green.length = 6;
-               var->blue.length = 6;
+               var->red.length = 8;
+               var->green = var->red;
+               var->blue = var->red;
                break;
        case 16:
                var->red.offset = 11;
@@ -852,6 +951,33 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
        default:
                return -EINVAL;
        }
+
+       if (is_xp(par->chip_id))
+               ramdac = 350000;
+
+       switch (par->chip_id) {
+       case TGUI9440:
+               ramdac = (bpp >= 16) ? 45000 : 90000;
+               break;
+       case CYBER9320:
+       case TGUI9660:
+               ramdac = 135000;
+               break;
+       case PROVIDIA9685:
+       case CYBER9388:
+       case CYBER9382:
+       case CYBER9385:
+               ramdac = 170000;
+               break;
+       }
+
+       /* The clock is doubled for 32 bpp */
+       if (bpp == 32)
+               ramdac /= 2;
+
+       if (PICOS2KHZ(var->pixclock) > ramdac)
+               return -EINVAL;
+
        debug("exit\n");
 
        return 0;
@@ -862,25 +988,31 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
 static int tridentfb_pan_display(struct fb_var_screeninfo *var,
                                 struct fb_info *info)
 {
+       struct tridentfb_par *par = info->par;
        unsigned int offset;
 
        debug("enter\n");
-       offset = (var->xoffset + (var->yoffset * var->xres))
+       offset = (var->xoffset + (var->yoffset * var->xres_virtual))
                * var->bits_per_pixel / 32;
-       info->var.xoffset = var->xoffset;
-       info->var.yoffset = var->yoffset;
-       set_screen_start(offset);
+       set_screen_start(par, offset);
        debug("exit\n");
        return 0;
 }
 
-#define shadowmode_on()  write3CE(CyberControl, read3CE(CyberControl) | 0x81)
-#define shadowmode_off() write3CE(CyberControl, read3CE(CyberControl) & 0x7E)
+static inline void shadowmode_on(struct tridentfb_par *par)
+{
+       write3CE(par, CyberControl, read3CE(par, CyberControl) | 0x81);
+}
+
+static inline void shadowmode_off(struct tridentfb_par *par)
+{
+       write3CE(par, CyberControl, read3CE(par, CyberControl) & 0x7E);
+}
 
 /* Set the hardware to the requested video mode */
 static int tridentfb_set_par(struct fb_info *info)
 {
-       struct tridentfb_par *par = (struct tridentfb_par *)(info->par);
+       struct tridentfb_par *par = info->par;
        u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend;
        u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend;
        struct fb_var_screeninfo *var = &info->var;
@@ -891,58 +1023,73 @@ static int tridentfb_set_par(struct fb_info *info)
        debug("enter\n");
        hdispend = var->xres / 8 - 1;
        hsyncstart = (var->xres + var->right_margin) / 8;
-       hsyncend = var->hsync_len / 8;
-       htotal =
-               (var->xres + var->left_margin + var->right_margin +
-                var->hsync_len) / 8 - 10;
+       hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8;
+       htotal = (var->xres + var->left_margin + var->right_margin +
+                 var->hsync_len) / 8 - 5;
        hblankstart = hdispend + 1;
-       hblankend = htotal + 5;
+       hblankend = htotal + 3;
 
        vdispend = var->yres - 1;
        vsyncstart = var->yres + var->lower_margin;
-       vsyncend = var->vsync_len;
-       vtotal = var->upper_margin + vsyncstart + vsyncend - 2;
-       vblankstart = var->yres;
-       vblankend = vtotal + 2;
+       vsyncend = vsyncstart + var->vsync_len;
+       vtotal = var->upper_margin + vsyncend - 2;
+       vblankstart = vdispend + 1;
+       vblankend = vtotal;
+
+       if (info->var.vmode & FB_VMODE_INTERLACED) {
+               vtotal /= 2;
+               vdispend /= 2;
+               vsyncstart /= 2;
+               vsyncend /= 2;
+               vblankstart /= 2;
+               vblankend /= 2;
+       }
 
-       crtc_unlock();
-       write3CE(CyberControl, 8);
+       enable_mmio(par);
+       crtc_unlock(par);
+       write3CE(par, CyberControl, 8);
+       tmp = 0xEB;
+       if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+               tmp &= ~0x40;
+       if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+               tmp &= ~0x80;
 
-       if (flatpanel && var->xres < nativex) {
+       if (par->flatpanel && var->xres < nativex) {
                /*
                 * on flat panels with native size larger
                 * than requested resolution decide whether
                 * we stretch or center
                 */
-               t_outb(0xEB, 0x3C2);
+               t_outb(par, tmp | 0xC0, VGA_MIS_W);
 
-               shadowmode_on();
+               shadowmode_on(par);
 
                if (center)
-                       screen_center();
+                       screen_center(par);
                else if (stretch)
-                       screen_stretch();
+                       screen_stretch(par);
 
        } else {
-               t_outb(0x2B, 0x3C2);
-               write3CE(CyberControl, 8);
+               t_outb(par, tmp, VGA_MIS_W);
+               write3CE(par, CyberControl, 8);
        }
 
        /* vertical timing values */
-       write3X4(CRTVTotal, vtotal & 0xFF);
-       write3X4(CRTVDispEnd, vdispend & 0xFF);
-       write3X4(CRTVSyncStart, vsyncstart & 0xFF);
-       write3X4(CRTVSyncEnd, (vsyncend & 0x0F));
-       write3X4(CRTVBlankStart, vblankstart & 0xFF);
-       write3X4(CRTVBlankEnd, 0 /* p->vblankend & 0xFF */ );
+       write3X4(par, VGA_CRTC_V_TOTAL, vtotal & 0xFF);
+       write3X4(par, VGA_CRTC_V_DISP_END, vdispend & 0xFF);
+       write3X4(par, VGA_CRTC_V_SYNC_START, vsyncstart & 0xFF);
+       write3X4(par, VGA_CRTC_V_SYNC_END, (vsyncend & 0x0F));
+       write3X4(par, VGA_CRTC_V_BLANK_START, vblankstart & 0xFF);
+       write3X4(par, VGA_CRTC_V_BLANK_END, vblankend & 0xFF);
 
        /* horizontal timing values */
-       write3X4(CRTHTotal, htotal & 0xFF);
-       write3X4(CRTHDispEnd, hdispend & 0xFF);
-       write3X4(CRTHSyncStart, hsyncstart & 0xFF);
-       write3X4(CRTHSyncEnd, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
-       write3X4(CRTHBlankStart, hblankstart & 0xFF);
-       write3X4(CRTHBlankEnd, 0 /* (p->hblankend & 0x1F) */ );
+       write3X4(par, VGA_CRTC_H_TOTAL, htotal & 0xFF);
+       write3X4(par, VGA_CRTC_H_DISP, hdispend & 0xFF);
+       write3X4(par, VGA_CRTC_H_SYNC_START, hsyncstart & 0xFF);
+       write3X4(par, VGA_CRTC_H_SYNC_END,
+                (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
+       write3X4(par, VGA_CRTC_H_BLANK_START, hblankstart & 0xFF);
+       write3X4(par, VGA_CRTC_H_BLANK_END, hblankend & 0x1F);
 
        /* higher bits of vertical timing values */
        tmp = 0x10;
@@ -954,39 +1101,43 @@ static int tridentfb_set_par(struct fb_info *info)
        if (vtotal & 0x200) tmp |= 0x20;
        if (vdispend & 0x200) tmp |= 0x40;
        if (vsyncstart & 0x200) tmp |= 0x80;
-       write3X4(CRTOverflow, tmp);
+       write3X4(par, VGA_CRTC_OVERFLOW, tmp);
 
-       tmp = read3X4(CRTHiOrd) | 0x08; /* line compare bit 10 */
+       tmp = read3X4(par, CRTHiOrd) & 0x07;
+       tmp |= 0x08;    /* line compare bit 10 */
        if (vtotal & 0x400) tmp |= 0x80;
        if (vblankstart & 0x400) tmp |= 0x40;
        if (vsyncstart & 0x400) tmp |= 0x20;
        if (vdispend & 0x400) tmp |= 0x10;
-       write3X4(CRTHiOrd, tmp);
+       write3X4(par, CRTHiOrd, tmp);
 
-       tmp = 0;
-       if (htotal & 0x800) tmp |= 0x800 >> 11;
-       if (hblankstart & 0x800) tmp |= 0x800 >> 7;
-       write3X4(HorizOverflow, tmp);
+       tmp = (htotal >> 8) & 0x01;
+       tmp |= (hdispend >> 7) & 0x02;
+       tmp |= (hsyncstart >> 5) & 0x08;
+       tmp |= (hblankstart >> 4) & 0x10;
+       write3X4(par, HorizOverflow, tmp);
 
        tmp = 0x40;
        if (vblankstart & 0x200) tmp |= 0x20;
 //FIXME        if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80;  /* double scan for 200 line modes */
-       write3X4(CRTMaxScanLine, tmp);
+       write3X4(par, VGA_CRTC_MAX_SCAN, tmp);
 
-       write3X4(CRTLineCompare, 0xFF);
-       write3X4(CRTPRowScan, 0);
-       write3X4(CRTModeControl, 0xC3);
+       write3X4(par, VGA_CRTC_LINE_COMPARE, 0xFF);
+       write3X4(par, VGA_CRTC_PRESET_ROW, 0);
+       write3X4(par, VGA_CRTC_MODE, 0xC3);
 
-       write3X4(LinearAddReg, 0x20);   /* enable linear addressing */
+       write3X4(par, LinearAddReg, 0x20);      /* enable linear addressing */
 
        tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80;
-       write3X4(CRTCModuleTest, tmp);  /* enable access extended memory */
-
-       write3X4(GraphEngReg, 0x80);    /* enable GE for text acceleration */
+       /* enable access extended memory */
+       write3X4(par, CRTCModuleTest, tmp);
+       tmp = read3CE(par, MiscIntContReg) & ~0x4;
+       if (info->var.vmode & FB_VMODE_INTERLACED)
+               tmp |= 0x4;
+       write3CE(par, MiscIntContReg, tmp);
 
-#ifdef CONFIG_FB_TRIDENT_ACCEL
-       acc->init_accel(info->var.xres, bpp);
-#endif
+       /* enable GE for text acceleration */
+       write3X4(par, GraphEngReg, 0x80);
 
        switch (bpp) {
        case 8:
@@ -1003,57 +1154,59 @@ static int tridentfb_set_par(struct fb_info *info)
                break;
        }
 
-       write3X4(PixelBusReg, tmp);
+       write3X4(par, PixelBusReg, tmp);
 
-       tmp = 0x10;
-       if (chipcyber)
+       tmp = read3X4(par, DRAMControl);
+       if (!is_oldprotect(par->chip_id))
+               tmp |= 0x10;
+       if (iscyber(par->chip_id))
                tmp |= 0x20;
-       write3X4(DRAMControl, tmp);     /* both IO, linear enable */
-
-       write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40);
-       write3X4(Performance, 0x92);
-       write3X4(PCIReg, 0x07);         /* MMIO & PCI read and write burst enable */
+       write3X4(par, DRAMControl, tmp);        /* both IO, linear enable */
+
+       write3X4(par, InterfaceSel, read3X4(par, InterfaceSel) | 0x40);
+       if (!is_xp(par->chip_id))
+               write3X4(par, Performance, read3X4(par, Performance) | 0x10);
+       /* MMIO & PCI read and write burst enable */
+       if (par->chip_id != TGUI9440 && par->chip_id != IMAGE975)
+               write3X4(par, PCIReg, read3X4(par, PCIReg) | 0x06);
+
+       vga_mm_wseq(par->io_virt, 0, 3);
+       vga_mm_wseq(par->io_virt, 1, 1); /* set char clock 8 dots wide */
+       /* enable 4 maps because needed in chain4 mode */
+       vga_mm_wseq(par->io_virt, 2, 0x0F);
+       vga_mm_wseq(par->io_virt, 3, 0);
+       vga_mm_wseq(par->io_virt, 4, 0x0E); /* memory mode enable bitmaps ?? */
 
        /* convert from picoseconds to kHz */
        vclk = PICOS2KHZ(info->var.pixclock);
-       if (bpp == 32)
+
+       /* divide clock by 2 if 32bpp chain4 mode display and CPU path */
+       tmp = read3CE(par, MiscExtFunc) & 0xF0;
+       if (bpp == 32 || (par->chip_id == TGUI9440 && bpp == 16)) {
+               tmp |= 8;
                vclk *= 2;
-       set_vclk(vclk);
-
-       write3C4(0, 3);
-       write3C4(1, 1);         /* set char clock 8 dots wide */
-       write3C4(2, 0x0F);      /* enable 4 maps because needed in chain4 mode */
-       write3C4(3, 0);
-       write3C4(4, 0x0E);      /* memory mode enable bitmaps ?? */
-
-       write3CE(MiscExtFunc, (bpp == 32) ? 0x1A : 0x12);       /* divide clock by 2 if 32bpp */
-                                                       /* chain4 mode display and CPU path */
-       write3CE(0x5, 0x40);    /* no CGA compat, allow 256 col */
-       write3CE(0x6, 0x05);    /* graphics mode */
-       write3CE(0x7, 0x0F);    /* planes? */
-
-       if (chip_id == CYBERBLADEXPAi1) {
-               /* This fixes snow-effect in 32 bpp */
-               write3X4(CRTHSyncStart, 0x84);
        }
+       set_vclk(par, vclk);
+       write3CE(par, MiscExtFunc, tmp | 0x12);
+       write3CE(par, 0x5, 0x40);       /* no CGA compat, allow 256 col */
+       write3CE(par, 0x6, 0x05);       /* graphics mode */
+       write3CE(par, 0x7, 0x0F);       /* planes? */
 
-       writeAttr(0x10, 0x41);  /* graphics mode and support 256 color modes */
-       writeAttr(0x12, 0x0F);  /* planes */
-       writeAttr(0x13, 0);     /* horizontal pel panning */
+       /* graphics mode and support 256 color modes */
+       writeAttr(par, 0x10, 0x41);
+       writeAttr(par, 0x12, 0x0F);     /* planes */
+       writeAttr(par, 0x13, 0);        /* horizontal pel panning */
 
        /* colors */
        for (tmp = 0; tmp < 0x10; tmp++)
-               writeAttr(tmp, tmp);
-       readb(par->io_virt + CRT + 0x0A);       /* flip-flop to index */
-       t_outb(0x20, 0x3C0);                    /* enable attr */
+               writeAttr(par, tmp, tmp);
+       fb_readb(par->io_virt + VGA_IS1_RC);    /* flip-flop to index */
+       t_outb(par, 0x20, VGA_ATT_W);           /* enable attr */
 
        switch (bpp) {
        case 8:
                tmp = 0;
                break;
-       case 15:
-               tmp = 0x10;
-               break;
        case 16:
                tmp = 0x30;
                break;
@@ -1063,19 +1216,23 @@ static int tridentfb_set_par(struct fb_info *info)
                break;
        }
 
-       t_inb(0x3C8);
-       t_inb(0x3C6);
-       t_inb(0x3C6);
-       t_inb(0x3C6);
-       t_inb(0x3C6);
-       t_outb(tmp, 0x3C6);
-       t_inb(0x3C8);
-
-       if (flatpanel)
-               set_number_of_lines(info->var.yres);
-       set_lwidth(info->var.xres * bpp / (4 * 16));
+       t_inb(par, VGA_PEL_IW);
+       t_inb(par, VGA_PEL_MSK);
+       t_inb(par, VGA_PEL_MSK);
+       t_inb(par, VGA_PEL_MSK);
+       t_inb(par, VGA_PEL_MSK);
+       t_outb(par, tmp, VGA_PEL_MSK);
+       t_inb(par, VGA_PEL_IW);
+
+       if (par->flatpanel)
+               set_number_of_lines(par, info->var.yres);
+       info->fix.line_length = info->var.xres_virtual * bpp / 8;
+       set_lwidth(par, info->fix.line_length / 8);
+
+       if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+               par->init_accel(par, info->var.xres_virtual, bpp);
+
        info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-       info->fix.line_length = info->var.xres * (bpp >> 3);
        info->cmap.len = (bpp == 8) ? 256 : 16;
        debug("exit\n");
        return 0;
@@ -1087,17 +1244,18 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                               struct fb_info *info)
 {
        int bpp = info->var.bits_per_pixel;
+       struct tridentfb_par *par = info->par;
 
        if (regno >= info->cmap.len)
                return 1;
 
        if (bpp == 8) {
-               t_outb(0xFF, 0x3C6);
-               t_outb(regno, 0x3C8);
+               t_outb(par, 0xFF, VGA_PEL_MSK);
+               t_outb(par, regno, VGA_PEL_IW);
 
-               t_outb(red >> 10, 0x3C9);
-               t_outb(green >> 10, 0x3C9);
-               t_outb(blue >> 10, 0x3C9);
+               t_outb(par, red >> 10, VGA_PEL_D);
+               t_outb(par, green >> 10, VGA_PEL_D);
+               t_outb(par, blue >> 10, VGA_PEL_D);
 
        } else if (regno < 16) {
                if (bpp == 16) {        /* RGB 565 */
@@ -1108,28 +1266,28 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                        col |= col << 16;
                        ((u32 *)(info->pseudo_palette))[regno] = col;
                } else if (bpp == 32)           /* ARGB 8888 */
-                       ((u32*)info->pseudo_palette)[regno] =
+                       ((u32 *)info->pseudo_palette)[regno] =
                                ((transp & 0xFF00) << 16)       |
                                ((red & 0xFF00) << 8)           |
                                ((green & 0xFF00))              |
                                ((blue & 0xFF00) >> 8);
        }
 
-/*     debug("exit\n"); */
        return 0;
 }
 
-/* Try blanking the screen.For flat panels it does nothing */
+/* Try blanking the screen. For flat panels it does nothing */
 static int tridentfb_blank(int blank_mode, struct fb_info *info)
 {
        unsigned char PMCont, DPMSCont;
+       struct tridentfb_par *par = info->par;
 
        debug("enter\n");
-       if (flatpanel)
+       if (par->flatpanel)
                return 0;
-       t_outb(0x04, 0x83C8); /* Read DPMS Control */
-       PMCont = t_inb(0x83C6) & 0xFC;
-       DPMSCont = read3CE(PowerStatus) & 0xFC;
+       t_outb(par, 0x04, 0x83C8); /* Read DPMS Control */
+       PMCont = t_inb(par, 0x83C6) & 0xFC;
+       DPMSCont = read3CE(par, PowerStatus) & 0xFC;
        switch (blank_mode) {
        case FB_BLANK_UNBLANK:
                /* Screen: On, HSync: On, VSync: On */
@@ -1155,9 +1313,9 @@ static int tridentfb_blank(int blank_mode, struct fb_info *info)
                break;
        }
 
-       write3CE(PowerStatus, DPMSCont);
-       t_outb(4, 0x83C8);
-       t_outb(PMCont, 0x83C6);
+       write3CE(par, PowerStatus, DPMSCont);
+       t_outb(par, 4, 0x83C8);
+       t_outb(par, PMCont, 0x83C6);
 
        debug("exit\n");
 
@@ -1174,33 +1332,46 @@ static struct fb_ops tridentfb_ops = {
        .fb_set_par = tridentfb_set_par,
        .fb_fillrect = tridentfb_fillrect,
        .fb_copyarea = tridentfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
+       .fb_imageblit = tridentfb_imageblit,
+#ifdef CONFIG_FB_TRIDENT_ACCEL
+       .fb_sync = tridentfb_sync,
+#endif
 };
 
-static int __devinit trident_pci_probe(struct pci_dev * dev,
-                                      const struct pci_device_id * id)
+static int __devinit trident_pci_probe(struct pci_dev *dev,
+                                      const struct pci_device_id *id)
 {
        int err;
        unsigned char revision;
+       struct fb_info *info;
+       struct tridentfb_par *default_par;
+       int chip3D;
+       int chip_id;
 
        err = pci_enable_device(dev);
        if (err)
                return err;
 
-       chip_id = id->device;
+       info = framebuffer_alloc(sizeof(struct tridentfb_par), &dev->dev);
+       if (!info)
+               return -ENOMEM;
+       default_par = info->par;
 
-       if (chip_id == CYBERBLADEi1)
-               output("*** Please do use cyblafb, Cyberblade/i1 support "
-                      "will soon be removed from tridentfb!\n");
+       chip_id = id->device;
 
+#ifndef CONFIG_FB_TRIDENT_ACCEL
+       noaccel = 1;
+#endif
 
        /* If PCI id is 0x9660 then further detect chip type */
 
        if (chip_id == TGUI9660) {
-               outb(RevisionID, 0x3C4);
-               revision = inb(0x3C5);
+               revision = vga_io_rseq(RevisionID);
 
                switch (revision) {
+               case 0x21:
+                       chip_id = PROVIDIA9685;
+                       break;
                case 0x22:
                case 0x23:
                        chip_id = CYBER9397;
@@ -1229,123 +1400,170 @@ static int __devinit trident_pci_probe(struct pci_dev * dev,
        }
 
        chip3D = is3Dchip(chip_id);
-       chipcyber = iscyber(chip_id);
 
        if (is_xp(chip_id)) {
-               acc = &accel_xp;
+               default_par->init_accel = xp_init_accel;
+               default_par->wait_engine = xp_wait_engine;
+               default_par->fill_rect = xp_fill_rect;
+               default_par->copy_rect = xp_copy_rect;
+               tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADEXP;
        } else if (is_blade(chip_id)) {
-               acc = &accel_blade;
-       } else {
-               acc = &accel_image;
+               default_par->init_accel = blade_init_accel;
+               default_par->wait_engine = blade_wait_engine;
+               default_par->fill_rect = blade_fill_rect;
+               default_par->copy_rect = blade_copy_rect;
+               default_par->image_blit = blade_image_blit;
+               tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D;
+       } else if (chip3D) {                    /* 3DImage family left */
+               default_par->init_accel = image_init_accel;
+               default_par->wait_engine = image_wait_engine;
+               default_par->fill_rect = image_fill_rect;
+               default_par->copy_rect = image_copy_rect;
+               tridentfb_fix.accel = FB_ACCEL_TRIDENT_3DIMAGE;
+       } else {                                /* TGUI 9440/96XX family */
+               default_par->init_accel = tgui_init_accel;
+               default_par->wait_engine = xp_wait_engine;
+               default_par->fill_rect = tgui_fill_rect;
+               default_par->copy_rect = tgui_copy_rect;
+               tridentfb_fix.accel = FB_ACCEL_TRIDENT_TGUI;
        }
 
-       /* acceleration is on by default for 3D chips */
-       defaultaccel = chip3D && !noaccel;
-
-       fb_info.par = &default_par;
+       default_par->chip_id = chip_id;
 
        /* setup MMIO region */
        tridentfb_fix.mmio_start = pci_resource_start(dev, 1);
-       tridentfb_fix.mmio_len = chip3D ? 0x20000 : 0x10000;
+       tridentfb_fix.mmio_len = pci_resource_len(dev, 1);
 
-       if (!request_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len, "tridentfb")) {
+       if (!request_mem_region(tridentfb_fix.mmio_start,
+                               tridentfb_fix.mmio_len, "tridentfb")) {
                debug("request_region failed!\n");
+               framebuffer_release(info);
                return -1;
        }
 
-       default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+       default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start,
+                                              tridentfb_fix.mmio_len);
 
-       if (!default_par.io_virt) {
+       if (!default_par->io_virt) {
                debug("ioremap failed\n");
                err = -1;
                goto out_unmap1;
        }
 
-       enable_mmio();
+       enable_mmio(default_par);
 
        /* setup framebuffer memory */
        tridentfb_fix.smem_start = pci_resource_start(dev, 0);
-       tridentfb_fix.smem_len = get_memsize();
+       tridentfb_fix.smem_len = get_memsize(default_par);
 
-       if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) {
+       if (!request_mem_region(tridentfb_fix.smem_start,
+                               tridentfb_fix.smem_len, "tridentfb")) {
                debug("request_mem_region failed!\n");
-               disable_mmio();
+               disable_mmio(info->par);
                err = -1;
                goto out_unmap1;
        }
 
-       fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start,
-                                             tridentfb_fix.smem_len);
+       info->screen_base = ioremap_nocache(tridentfb_fix.smem_start,
+                                           tridentfb_fix.smem_len);
 
-       if (!fb_info.screen_base) {
+       if (!info->screen_base) {
                debug("ioremap failed\n");
                err = -1;
                goto out_unmap2;
        }
 
-       output("%s board found\n", pci_name(dev));
-       displaytype = get_displaytype();
+       default_par->flatpanel = is_flatpanel(default_par);
 
-       if (flatpanel)
-               nativex = get_nativex();
+       if (default_par->flatpanel)
+               nativex = get_nativex(default_par);
 
-       fb_info.fix = tridentfb_fix;
-       fb_info.fbops = &tridentfb_ops;
+       info->fix = tridentfb_fix;
+       info->fbops = &tridentfb_ops;
+       info->pseudo_palette = default_par->pseudo_pal;
 
+       info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+       if (!noaccel && default_par->init_accel) {
+               info->flags &= ~FBINFO_HWACCEL_DISABLED;
+               info->flags |= FBINFO_HWACCEL_COPYAREA;
+               info->flags |= FBINFO_HWACCEL_FILLRECT;
+       } else
+               info->flags |= FBINFO_HWACCEL_DISABLED;
 
-       fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-#ifdef CONFIG_FB_TRIDENT_ACCEL
-       fb_info.flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
-#endif
-       fb_info.pseudo_palette = pseudo_pal;
+       info->pixmap.addr = kmalloc(4096, GFP_KERNEL);
+       if (!info->pixmap.addr) {
+               err = -ENOMEM;
+               goto out_unmap2;
+       }
+
+       info->pixmap.size = 4096;
+       info->pixmap.buf_align = 4;
+       info->pixmap.scan_align = 1;
+       info->pixmap.access_align = 32;
+       info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
-       if (!fb_find_mode(&default_var, &fb_info,
+       if (default_par->image_blit) {
+               info->flags |= FBINFO_HWACCEL_IMAGEBLIT;
+               info->pixmap.scan_align = 4;
+       }
+
+       if (noaccel) {
+               printk(KERN_DEBUG "disabling acceleration\n");
+               info->flags |= FBINFO_HWACCEL_DISABLED;
+               info->pixmap.scan_align = 1;
+       }
+
+       if (!fb_find_mode(&info->var, info,
                          mode_option, NULL, 0, NULL, bpp)) {
                err = -EINVAL;
                goto out_unmap2;
        }
-       err = fb_alloc_cmap(&fb_info.cmap, 256, 0);
+       err = fb_alloc_cmap(&info->cmap, 256, 0);
        if (err < 0)
                goto out_unmap2;
 
-       if (defaultaccel && acc)
-               default_var.accel_flags |= FB_ACCELF_TEXT;
-       else
-               default_var.accel_flags &= ~FB_ACCELF_TEXT;
-       default_var.activate |= FB_ACTIVATE_NOW;
-       fb_info.var = default_var;
-       fb_info.device = &dev->dev;
-       if (register_framebuffer(&fb_info) < 0) {
-               printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
-               fb_dealloc_cmap(&fb_info.cmap);
+       info->var.activate |= FB_ACTIVATE_NOW;
+       info->device = &dev->dev;
+       if (register_framebuffer(info) < 0) {
+               printk(KERN_ERR "tridentfb: could not register framebuffer\n");
+               fb_dealloc_cmap(&info->cmap);
                err = -EINVAL;
                goto out_unmap2;
        }
        output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
-          fb_info.node, fb_info.fix.id, default_var.xres,
-          default_var.yres, default_var.bits_per_pixel);
+          info->node, info->fix.id, info->var.xres,
+          info->var.yres, info->var.bits_per_pixel);
+
+       pci_set_drvdata(dev, info);
        return 0;
 
 out_unmap2:
-       if (fb_info.screen_base)
-               iounmap(fb_info.screen_base);
+       kfree(info->pixmap.addr);
+       if (info->screen_base)
+               iounmap(info->screen_base);
        release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
-       disable_mmio();
+       disable_mmio(info->par);
 out_unmap1:
-       if (default_par.io_virt)
-               iounmap(default_par.io_virt);
+       if (default_par->io_virt)
+               iounmap(default_par->io_virt);
        release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+       framebuffer_release(info);
        return err;
 }
 
 static void __devexit trident_pci_remove(struct pci_dev *dev)
 {
-       struct tridentfb_par *par = (struct tridentfb_par*)fb_info.par;
-       unregister_framebuffer(&fb_info);
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct tridentfb_par *par = info->par;
+
+       unregister_framebuffer(info);
        iounmap(par->io_virt);
-       iounmap(fb_info.screen_base);
+       iounmap(info->screen_base);
        release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
        release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+       pci_set_drvdata(dev, NULL);
+       kfree(info->pixmap.addr);
+       framebuffer_release(info);
 }
 
 /* List of boards that we are trying to support */
@@ -1358,6 +1576,7 @@ static struct pci_device_id trident_devices[] = {
        {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VENDOR_ID_TRIDENT, TGUI9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -1399,9 +1618,9 @@ static int __init tridentfb_setup(char *options)
                if (!strncmp(opt, "noaccel", 7))
                        noaccel = 1;
                else if (!strncmp(opt, "fp", 2))
-                       displaytype = DISPLAY_FP;
+                       fp = 1;
                else if (!strncmp(opt, "crt", 3))
-                       displaytype = DISPLAY_CRT;
+                       fp = 0;
                else if (!strncmp(opt, "bpp=", 4))
                        bpp = simple_strtoul(opt + 4, NULL, 0);
                else if (!strncmp(opt, "center", 6))
@@ -1430,7 +1649,6 @@ static int __init tridentfb_init(void)
                return -ENODEV;
        tridentfb_setup(option);
 #endif
-       output("Trident framebuffer %s initializing\n", VERSION);
        return pci_register_driver(&tridentfb_pci_driver);
 }
 
index cdbb56edb6cbdde9b34231b5e985c70c3e39efb4..50744229c7a947b2d7fc5dfff928664755232165 100644 (file)
@@ -2054,8 +2054,8 @@ MODULE_PARM_DESC(maxhf,
 module_param(maxvf, ushort, 0);
 MODULE_PARM_DESC(maxvf,
        "Maximum vertical frequency [Hz], overrides EDID data");
-module_param_named(mode, mode_option, charp, 0);
-MODULE_PARM_DESC(mode,
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option,
        "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
 module_param(vbemode, ushort, 0);
 MODULE_PARM_DESC(vbemode,
index 072638a9528aa71573626f959c290525ec9f6643..93fe08d6c78f6f2a36b84c8977ad95c2781ff6f1 100644 (file)
@@ -443,19 +443,29 @@ static int vfb_mmap(struct fb_info *info,
 }
 
 #ifndef MODULE
+/*
+ * The virtual framebuffer driver is only enabled if explicitly
+ * requested by passing 'video=vfb:' (or any actual options).
+ */
 static int __init vfb_setup(char *options)
 {
        char *this_opt;
 
+       vfb_enable = 0;
+
+       if (!options)
+               return 1;
+
        vfb_enable = 1;
 
-       if (!options || !*options)
+       if (!*options)
                return 1;
 
        while ((this_opt = strsep(&options, ",")) != NULL) {
                if (!*this_opt)
                        continue;
-               if (!strncmp(this_opt, "disable", 7))
+               /* Test disable for backwards compatibility */
+               if (!strcmp(this_opt, "disable"))
                        vfb_enable = 0;
        }
        return 1;
index 9b3c5923365e7dd62e60982f9d6c27341f68cdf5..e31bca8a0cb2d8a5ecc6394c449bbc91f1705dc1 100644 (file)
 #include <asm/io.h>
 #include <video/vga.h>
 
-#define GRAPHICS_ADDR_REG VGA_GFX_I    /* Graphics address register. */
-#define GRAPHICS_DATA_REG VGA_GFX_D    /* Graphics data register. */
-
-#define SET_RESET_INDEX        VGA_GFX_SR_VALUE        /* Set/Reset Register index. */
-#define ENABLE_SET_RESET_INDEX VGA_GFX_SR_ENABLE       /* Enable Set/Reset Register index. */
-#define DATA_ROTATE_INDEX      VGA_GFX_DATA_ROTATE     /* Data Rotate Register index. */
-#define GRAPHICS_MODE_INDEX    VGA_GFX_MODE            /* Graphics Mode Register index. */
-#define BIT_MASK_INDEX         VGA_GFX_BIT_MASK        /* Bit Mask Register index. */
-
-#define dac_reg        (VGA_PEL_IW)
-#define dac_val        (VGA_PEL_D)
-
 #define VGA_FB_PHYS 0xA0000
 #define VGA_FB_PHYS_LEN 65536
 
@@ -108,7 +96,7 @@ static struct fb_fix_screeninfo vga16fb_fix __initdata = {
        .visual         = FB_VISUAL_PSEUDOCOLOR,
        .xpanstep       = 8,
        .ypanstep       = 1,
-       .line_length    = 640/8,
+       .line_length    = 640 / 8,
        .accel          = FB_ACCEL_NONE
 };
 
@@ -135,23 +123,22 @@ static inline int setmode(int mode)
 {
        int oldmode;
        
-       vga_io_w(GRAPHICS_ADDR_REG, GRAPHICS_MODE_INDEX);
-       oldmode = vga_io_r(GRAPHICS_DATA_REG);
-       vga_io_w(GRAPHICS_DATA_REG, mode);
+       oldmode = vga_io_rgfx(VGA_GFX_MODE);
+       vga_io_w(VGA_GFX_D, mode);
        return oldmode;
 }
 
 /* Select the Bit Mask Register and return its value. */
 static inline int selectmask(void)
 {
-       return vga_io_rgfx(BIT_MASK_INDEX);
+       return vga_io_rgfx(VGA_GFX_BIT_MASK);
 }
 
 /* Set the value of the Bit Mask Register.  It must already have been
    selected with selectmask(). */
 static inline void setmask(int mask)
 {
-       vga_io_w(GRAPHICS_DATA_REG, mask);
+       vga_io_w(VGA_GFX_D, mask);
 }
 
 /* Set the Data Rotate Register and return its old value. 
@@ -161,9 +148,8 @@ static inline int setop(int op)
 {
        int oldop;
        
-       vga_io_w(GRAPHICS_ADDR_REG, DATA_ROTATE_INDEX);
-       oldop = vga_io_r(GRAPHICS_DATA_REG);
-       vga_io_w(GRAPHICS_DATA_REG, op);
+       oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
+       vga_io_w(VGA_GFX_D, op);
        return oldop;
 }
 
@@ -173,9 +159,8 @@ static inline int setsr(int sr)
 {
        int oldsr;
 
-       vga_io_w(GRAPHICS_ADDR_REG, ENABLE_SET_RESET_INDEX);
-       oldsr = vga_io_r(GRAPHICS_DATA_REG);
-       vga_io_w(GRAPHICS_DATA_REG, sr);
+       oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE);
+       vga_io_w(VGA_GFX_D, sr);
        return oldsr;
 }
 
@@ -184,22 +169,21 @@ static inline int setcolor(int color)
 {
        int oldcolor;
 
-       vga_io_w(GRAPHICS_ADDR_REG, SET_RESET_INDEX);
-       oldcolor = vga_io_r(GRAPHICS_DATA_REG);
-       vga_io_w(GRAPHICS_DATA_REG, color);
+       oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE);
+       vga_io_w(VGA_GFX_D, color);
        return oldcolor;
 }
 
 /* Return the value in the Graphics Address Register. */
 static inline int getindex(void)
 {
-       return vga_io_r(GRAPHICS_ADDR_REG);
+       return vga_io_r(VGA_GFX_I);
 }
 
 /* Set the value in the Graphics Address Register. */
 static inline void setindex(int index)
 {
-       vga_io_w(GRAPHICS_ADDR_REG, index);
+       vga_io_w(VGA_GFX_I, index);
 }
 
 static void vga16fb_pan_var(struct fb_info *info, 
@@ -672,10 +656,10 @@ static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned b
 
 static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
 {
-       outb(regno,       dac_reg);
-       outb(red   >> 10, dac_val);
-       outb(green >> 10, dac_val);
-       outb(blue  >> 10, dac_val);
+       outb(regno,       VGA_PEL_IW);
+       outb(red   >> 10, VGA_PEL_D);
+       outb(green >> 10, VGA_PEL_D);
+       outb(blue  >> 10, VGA_PEL_D);
 }
 
 static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -719,28 +703,15 @@ static int vga16fb_pan_display(struct fb_var_screeninfo *var,
    blanking code was originally by Huang shi chao, and modified by
    Christoph Rimek (chrimek@toppoint.de) and todd j. derr
    (tjd@barefoot.org) for Linux. */
-#define attrib_port            VGA_ATC_IW
-#define seq_port_reg           VGA_SEQ_I
-#define seq_port_val           VGA_SEQ_D
-#define gr_port_reg            VGA_GFX_I
-#define gr_port_val            VGA_GFX_D
-#define video_misc_rd          VGA_MIS_R
-#define video_misc_wr          VGA_MIS_W
-#define vga_video_port_reg     VGA_CRT_IC
-#define vga_video_port_val     VGA_CRT_DC
 
 static void vga_vesa_blank(struct vga16fb_par *par, int mode)
 {
-       unsigned char SeqCtrlIndex;
-       unsigned char CrtCtrlIndex;
+       unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+       unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
        
-       //cli();
-       SeqCtrlIndex = vga_io_r(seq_port_reg);
-       CrtCtrlIndex = vga_io_r(vga_video_port_reg);
-
        /* save original values of VGA controller registers */
        if(!par->vesa_blanked) {
-               par->vga_state.CrtMiscIO = vga_io_r(video_misc_rd);
+               par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
                //sti();
 
                par->vga_state.HorizontalTotal = vga_io_rcrt(0x00);     /* HorizontalTotal */
@@ -756,12 +727,11 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
 
        /* assure that video is enabled */
        /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
-       //cli();
        vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
 
        /* test for vertical retrace in process.... */
        if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
-               vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO & 0xef);
+               vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef);
 
        /*
         * Set <End of vertical retrace> to minimum (0) and
@@ -769,12 +739,10 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
         * Result: turn off vertical sync (VSync) pulse.
         */
        if (mode & FB_BLANK_VSYNC_SUSPEND) {
-               outb_p(0x10,vga_video_port_reg);        /* StartVertRetrace */
-               outb_p(0xff,vga_video_port_val);        /* maximum value */
-               outb_p(0x11,vga_video_port_reg);        /* EndVertRetrace */
-               outb_p(0x40,vga_video_port_val);        /* minimum (bits 0..3)  */
-               outb_p(0x07,vga_video_port_reg);        /* Overflow */
-               outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
+               vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff);
+               vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40);
+               /* bits 9,10 of vert. retrace */
+               vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84);
        }
 
        if (mode & FB_BLANK_HSYNC_SUSPEND) {
@@ -783,29 +751,22 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
                 *  <Start of horizontal Retrace> to maximum
                 * Result: turn off horizontal sync (HSync) pulse.
                 */
-               outb_p(0x04,vga_video_port_reg);        /* StartHorizRetrace */
-               outb_p(0xff,vga_video_port_val);        /* maximum */
-               outb_p(0x05,vga_video_port_reg);        /* EndHorizRetrace */
-               outb_p(0x00,vga_video_port_val);        /* minimum (0) */
+               vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff);
+               vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00);
        }
 
        /* restore both index registers */
-       outb_p(SeqCtrlIndex,seq_port_reg);
-       outb_p(CrtCtrlIndex,vga_video_port_reg);
-       //sti();
+       outb_p(SeqCtrlIndex, VGA_SEQ_I);
+       outb_p(CrtCtrlIndex, VGA_CRT_IC);
 }
 
 static void vga_vesa_unblank(struct vga16fb_par *par)
 {
-       unsigned char SeqCtrlIndex;
-       unsigned char CrtCtrlIndex;
+       unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+       unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
        
-       //cli();
-       SeqCtrlIndex = vga_io_r(seq_port_reg);
-       CrtCtrlIndex = vga_io_r(vga_video_port_reg);
-
        /* restore original values of VGA controller registers */
-       vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO);
+       vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
 
        /* HorizontalTotal */
        vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
@@ -827,9 +788,8 @@ static void vga_vesa_unblank(struct vga16fb_par *par)
        vga_io_wseq(0x01, par->vga_state.ClockingMode);
 
        /* restore index/control registers */
-       vga_io_w(seq_port_reg, SeqCtrlIndex);
-       vga_io_w(vga_video_port_reg, CrtCtrlIndex);
-       //sti();
+       vga_io_w(VGA_SEQ_I, SeqCtrlIndex);
+       vga_io_w(VGA_CRT_IC, CrtCtrlIndex);
 }
 
 static void vga_pal_blank(void)
@@ -837,10 +797,10 @@ static void vga_pal_blank(void)
        int i;
 
        for (i=0; i<16; i++) {
-               outb_p (i, dac_reg) ;
-               outb_p (0, dac_val) ;
-               outb_p (0, dac_val) ;
-               outb_p (0, dac_val) ;
+               outb_p(i, VGA_PEL_IW);
+               outb_p(0, VGA_PEL_D);
+               outb_p(0, VGA_PEL_D);
+               outb_p(0, VGA_PEL_D);
        }
 }
 
@@ -1087,12 +1047,15 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
        width = x2 - dx;
        height = y2 - dy;
 
+       if (sx + dx < old_dx || sy + dy < old_dy)
+               return;
+
        /* update sx1,sy1 */
        sx += (dx - old_dx);
        sy += (dy - old_dy);
 
        /* the source must be completely inside the virtual screen */
-       if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres)
+       if (sx + width > vxres || sy + height > vyres)
                return;
 
        switch (info->fix.type) {
@@ -1482,6 +1445,7 @@ static void __exit vga16fb_exit(void)
        platform_driver_unregister(&vga16fb_driver);
 }
 
+MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
 MODULE_LICENSE("GPL");
 module_init(vga16fb_init);
 module_exit(vga16fb_exit);
index 7084e7e146c0b6fbc319bb9ceefcf419b7111a13..5b78fd0aff0a6d50306c75f80d99f52f97dbe99e 100644 (file)
@@ -71,13 +71,6 @@ static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env)
                              dev->id.device, dev->id.vendor);
 }
 
-static struct bus_type virtio_bus = {
-       .name  = "virtio",
-       .match = virtio_dev_match,
-       .dev_attrs = virtio_dev_attrs,
-       .uevent = virtio_uevent,
-};
-
 static void add_status(struct virtio_device *dev, unsigned status)
 {
        dev->config->set_status(dev, dev->config->get_status(dev) | status);
@@ -120,12 +113,16 @@ static int virtio_dev_probe(struct device *_d)
                        set_bit(f, dev->features);
        }
 
+       /* Transport features always preserved to pass to finalize_features. */
+       for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++)
+               if (device_features & (1 << i))
+                       set_bit(i, dev->features);
+
        err = drv->probe(dev);
        if (err)
                add_status(dev, VIRTIO_CONFIG_S_FAILED);
        else {
-               /* They should never have set feature bits beyond 32 */
-               dev->config->set_features(dev, dev->features[0]);
+               dev->config->finalize_features(dev);
                add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
        }
        return err;
@@ -147,13 +144,20 @@ static int virtio_dev_remove(struct device *_d)
        return 0;
 }
 
+static struct bus_type virtio_bus = {
+       .name  = "virtio",
+       .match = virtio_dev_match,
+       .dev_attrs = virtio_dev_attrs,
+       .uevent = virtio_uevent,
+       .probe = virtio_dev_probe,
+       .remove = virtio_dev_remove,
+};
+
 int register_virtio_driver(struct virtio_driver *driver)
 {
        /* Catch this early. */
        BUG_ON(driver->feature_table_size && !driver->feature_table);
        driver->driver.bus = &virtio_bus;
-       driver->driver.probe = virtio_dev_probe;
-       driver->driver.remove = virtio_dev_remove;
        return driver_register(&driver->driver);
 }
 EXPORT_SYMBOL_GPL(register_virtio_driver);
index eae7236310e450ce1647a25a480eccad9147dec4..c7dc37c7cce91592326fff43187097ae4049ed33 100644 (file)
@@ -94,12 +94,17 @@ static u32 vp_get_features(struct virtio_device *vdev)
        return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
 }
 
-/* virtio config->set_features() implementation */
-static void vp_set_features(struct virtio_device *vdev, u32 features)
+/* virtio config->finalize_features() implementation */
+static void vp_finalize_features(struct virtio_device *vdev)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 
-       iowrite32(features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
+       /* Give virtio_ring a chance to accept features. */
+       vring_transport_features(vdev);
+
+       /* We only support 32 feature bits. */
+       BUILD_BUG_ON(ARRAY_SIZE(vdev->features) != 1);
+       iowrite32(vdev->features[0], vp_dev->ioaddr+VIRTIO_PCI_GUEST_FEATURES);
 }
 
 /* virtio config->get() implementation */
@@ -297,7 +302,7 @@ static struct virtio_config_ops virtio_pci_config_ops = {
        .find_vq        = vp_find_vq,
        .del_vq         = vp_del_vq,
        .get_features   = vp_get_features,
-       .set_features   = vp_set_features,
+       .finalize_features = vp_finalize_features,
 };
 
 /* the PCI probing function */
index 72bf8bc090142f02a9065c0ff0448299a5e9a2e7..6eb5303fed11b20613083ed960aa27cb8e2d4bd9 100644 (file)
@@ -18,6 +18,7 @@
  */
 #include <linux/virtio.h>
 #include <linux/virtio_ring.h>
+#include <linux/virtio_config.h>
 #include <linux/device.h>
 
 #ifdef DEBUG
@@ -87,8 +88,11 @@ static int vring_add_buf(struct virtqueue *_vq,
        if (vq->num_free < out + in) {
                pr_debug("Can't add buf len %i - avail = %i\n",
                         out + in, vq->num_free);
-               /* We notify *even if* VRING_USED_F_NO_NOTIFY is set here. */
-               vq->notify(&vq->vq);
+               /* FIXME: for historical reasons, we force a notify here if
+                * there are outgoing parts to the buffer.  Presumably the
+                * host should service the ring ASAP. */
+               if (out)
+                       vq->notify(&vq->vq);
                END_USE(vq);
                return -ENOSPC;
        }
@@ -320,4 +324,19 @@ void vring_del_virtqueue(struct virtqueue *vq)
 }
 EXPORT_SYMBOL_GPL(vring_del_virtqueue);
 
+/* Manipulates transport-specific feature bits. */
+void vring_transport_features(struct virtio_device *vdev)
+{
+       unsigned int i;
+
+       for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) {
+               switch (i) {
+               default:
+                       /* We don't understand this bit. */
+                       clear_bit(i, vdev->features);
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(vring_transport_features);
+
 MODULE_LICENSE("GPL");
index ccb78f66c2b6c3a24c509bb62f6341347152ec4f..48399e134c0de37d31cfcd05fc16213b7bc7dc0e 100644 (file)
@@ -788,8 +788,6 @@ config WATCHDOG_RIO
          machines.  The watchdog timeout period is normally one minute but
          can be changed with a boot-time parameter.
 
-# V850 Architecture
-
 # XTENSA Architecture
 
 #
index 25b352b664d96511a2e7bae9074947f60831b7b3..edd305a64e6334583d62376dfc39b399f29f584c 100644 (file)
@@ -119,8 +119,6 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
 
 # SPARC64 Architecture
 
-# V850 Architecture
-
 # XTENSA Architecture
 
 # Architecture Independant
index d4427cb869791cd0f1b910f5371f78aefe42c626..fff987b10e0f2fdd54da38f5692f9540d74713ca 100644 (file)
@@ -60,7 +60,7 @@
 
 #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
 
-#define BALLOON_CLASS_NAME "memory"
+#define BALLOON_CLASS_NAME "xen_memory"
 
 struct balloon_stats {
        /* We aim for 'current allocation' == 'target allocation'. */
@@ -226,9 +226,8 @@ static int increase_reservation(unsigned long nr_pages)
        }
 
        set_xen_guest_handle(reservation.extent_start, frame_list);
-       reservation.nr_extents   = nr_pages;
-       rc = HYPERVISOR_memory_op(
-               XENMEM_populate_physmap, &reservation);
+       reservation.nr_extents = nr_pages;
+       rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
        if (rc < nr_pages) {
                if (rc > 0) {
                        int ret;
@@ -236,7 +235,7 @@ static int increase_reservation(unsigned long nr_pages)
                        /* We hit the Xen hard limit: reprobe. */
                        reservation.nr_extents = rc;
                        ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
-                                       &reservation);
+                                                  &reservation);
                        BUG_ON(ret != rc);
                }
                if (rc >= 0)
@@ -464,136 +463,13 @@ static void balloon_exit(void)
 
 module_exit(balloon_exit);
 
-static void balloon_update_driver_allowance(long delta)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&balloon_lock, flags);
-       balloon_stats.driver_pages += delta;
-       spin_unlock_irqrestore(&balloon_lock, flags);
-}
-
-static int dealloc_pte_fn(
-       pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
-{
-       unsigned long mfn = pte_mfn(*pte);
-       int ret;
-       struct xen_memory_reservation reservation = {
-               .nr_extents   = 1,
-               .extent_order = 0,
-               .domid        = DOMID_SELF
-       };
-       set_xen_guest_handle(reservation.extent_start, &mfn);
-       set_pte_at(&init_mm, addr, pte, __pte_ma(0ull));
-       set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
-       ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
-       BUG_ON(ret != 1);
-       return 0;
-}
-
-static struct page **alloc_empty_pages_and_pagevec(int nr_pages)
-{
-       unsigned long vaddr, flags;
-       struct page *page, **pagevec;
-       int i, ret;
-
-       pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
-       if (pagevec == NULL)
-               return NULL;
-
-       for (i = 0; i < nr_pages; i++) {
-               page = pagevec[i] = alloc_page(GFP_KERNEL);
-               if (page == NULL)
-                       goto err;
-
-               vaddr = (unsigned long)page_address(page);
-
-               scrub_page(page);
-
-               spin_lock_irqsave(&balloon_lock, flags);
-
-               if (xen_feature(XENFEAT_auto_translated_physmap)) {
-                       unsigned long gmfn = page_to_pfn(page);
-                       struct xen_memory_reservation reservation = {
-                               .nr_extents   = 1,
-                               .extent_order = 0,
-                               .domid        = DOMID_SELF
-                       };
-                       set_xen_guest_handle(reservation.extent_start, &gmfn);
-                       ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
-                                                  &reservation);
-                       if (ret == 1)
-                               ret = 0; /* success */
-               } else {
-                       ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
-                                                 dealloc_pte_fn, NULL);
-               }
-
-               if (ret != 0) {
-                       spin_unlock_irqrestore(&balloon_lock, flags);
-                       __free_page(page);
-                       goto err;
-               }
-
-               totalram_pages = --balloon_stats.current_pages;
-
-               spin_unlock_irqrestore(&balloon_lock, flags);
-       }
-
- out:
-       schedule_work(&balloon_worker);
-       flush_tlb_all();
-       return pagevec;
-
- err:
-       spin_lock_irqsave(&balloon_lock, flags);
-       while (--i >= 0)
-               balloon_append(pagevec[i]);
-       spin_unlock_irqrestore(&balloon_lock, flags);
-       kfree(pagevec);
-       pagevec = NULL;
-       goto out;
-}
-
-static void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
-{
-       unsigned long flags;
-       int i;
-
-       if (pagevec == NULL)
-               return;
-
-       spin_lock_irqsave(&balloon_lock, flags);
-       for (i = 0; i < nr_pages; i++) {
-               BUG_ON(page_count(pagevec[i]) != 1);
-               balloon_append(pagevec[i]);
-       }
-       spin_unlock_irqrestore(&balloon_lock, flags);
-
-       kfree(pagevec);
-
-       schedule_work(&balloon_worker);
-}
-
-static void balloon_release_driver_page(struct page *page)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&balloon_lock, flags);
-       balloon_append(page);
-       balloon_stats.driver_pages--;
-       spin_unlock_irqrestore(&balloon_lock, flags);
-
-       schedule_work(&balloon_worker);
-}
-
-
-#define BALLOON_SHOW(name, format, args...)                    \
-       static ssize_t show_##name(struct sys_device *dev,      \
-                                  char *buf)                   \
-       {                                                       \
-               return sprintf(buf, format, ##args);            \
-       }                                                       \
+#define BALLOON_SHOW(name, format, args...)                            \
+       static ssize_t show_##name(struct sys_device *dev,              \
+                                  struct sysdev_attribute *attr,       \
+                                  char *buf)                           \
+       {                                                               \
+               return sprintf(buf, format, ##args);                    \
+       }                                                               \
        static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
 
 BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
@@ -604,7 +480,8 @@ BALLOON_SHOW(hard_limit_kb,
             (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
 BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
 
-static ssize_t show_target_kb(struct sys_device *dev, char *buf)
+static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr,
+                             char *buf)
 {
        return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
 }
@@ -614,19 +491,14 @@ static ssize_t store_target_kb(struct sys_device *dev,
                               const char *buf,
                               size_t count)
 {
-       char memstring[64], *endchar;
+       char *endchar;
        unsigned long long target_bytes;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (count <= 1)
-               return -EBADMSG; /* runt */
-       if (count > sizeof(memstring))
-               return -EFBIG;   /* too long */
-       strcpy(memstring, buf);
+       target_bytes = memparse(buf, &endchar);
 
-       target_bytes = memparse(memstring, &endchar);
        balloon_set_new_target(target_bytes >> PAGE_SHIFT);
 
        return count;
@@ -694,20 +566,4 @@ static int register_balloon(struct sys_device *sysdev)
        return error;
 }
 
-static void unregister_balloon(struct sys_device *sysdev)
-{
-       int i;
-
-       sysfs_remove_group(&sysdev->kobj, &balloon_info_group);
-       for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++)
-               sysdev_remove_file(sysdev, balloon_attrs[i]);
-       sysdev_unregister(sysdev);
-       sysdev_class_unregister(&balloon_sysdev_class);
-}
-
-static void balloon_sysfs_exit(void)
-{
-       unregister_balloon(&balloon_sysdev);
-}
-
 MODULE_LICENSE("GPL");
index 3da712cc7708c43986765f13e2b51880ba7aca39..5290552d2ef7e0525f12f6fecfdbecd756088e7e 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/zorro.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/fs.h>
 
 #include "zorro.h"
 
index 37db79a2ff9578e162fcfd8a346d2c6254a95c7f..d3873583360b84d69afa0632bbc070bb34584f3c 100644 (file)
@@ -902,65 +902,7 @@ endif # BLOCK
 
 menu "Pseudo filesystems"
 
-config PROC_FS
-       bool "/proc file system support" if EMBEDDED
-       default y
-       help
-         This is a virtual file system providing information about the status
-         of the system. "Virtual" means that it doesn't take up any space on
-         your hard disk: the files are created on the fly by the kernel when
-         you try to access them. Also, you cannot read the files with older
-         version of the program less: you need to use more or cat.
-
-         It's totally cool; for example, "cat /proc/interrupts" gives
-         information about what the different IRQs are used for at the moment
-         (there is a small number of Interrupt ReQuest lines in your computer
-         that are used by the attached devices to gain the CPU's attention --
-         often a source of trouble if two devices are mistakenly configured
-         to use the same IRQ). The program procinfo to display some
-         information about your system gathered from the /proc file system.
-
-         Before you can use the /proc file system, it has to be mounted,
-         meaning it has to be given a location in the directory hierarchy.
-         That location should be /proc. A command such as "mount -t proc proc
-         /proc" or the equivalent line in /etc/fstab does the job.
-
-         The /proc file system is explained in the file
-         <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage
-         ("man 5 proc").
-
-         This option will enlarge your kernel by about 67 KB. Several
-         programs depend on this, so everyone should say Y here.
-
-config PROC_KCORE
-       bool "/proc/kcore support" if !ARM
-       depends on PROC_FS && MMU
-
-config PROC_VMCORE
-        bool "/proc/vmcore support (EXPERIMENTAL)"
-        depends on PROC_FS && CRASH_DUMP
-       default y
-        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.
+source "fs/proc/Kconfig"
 
 config SYSFS
        bool "sysfs file system support" if EMBEDDED
@@ -1441,6 +1383,19 @@ config MINIX_FS
          partition (the one containing the directory /) cannot be compiled as
          a module.
 
+config OMFS_FS
+       tristate "SonicBlue Optimized MPEG File System support"
+       depends on BLOCK
+       select CRC_ITU_T
+       help
+         This is the proprietary file system used by the Rio Karma music
+         player and ReplayTV DVR.  Despite the name, this filesystem is not
+         more efficient than a standard FS for MPEG files, in fact likely
+         the opposite is true.  Say Y if you have either of these devices
+         and wish to mount its disk.
+
+         To compile this file system support as a module, choose M here: the
+         module will be called omfs.  If unsure, say N.
 
 config HPFS_FS
        tristate "OS/2 HPFS file system support"
@@ -2093,20 +2048,6 @@ config CODA_FS
          To compile the coda client support as a module, choose M here: the
          module will be called coda.
 
-config CODA_FS_OLD_API
-       bool "Use 96-bit Coda file identifiers"
-       depends on CODA_FS
-       help
-         A new kernel-userspace API had to be introduced for Coda v6.0
-         to support larger 128-bit file identifiers as needed by the
-         new realms implementation.
-
-         However this new API is not backward compatible with older
-         clients. If you really need to run the old Coda userspace
-         cache manager then say Y.
-
-         For most cases you probably want to say N.
-
 config AFS_FS
        tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
        depends on INET && EXPERIMENTAL
index 3263084eef9e37394ac6f736a9dc769f5be50db1..4a551af6f3fc956ffc4032e4c79d16c3b61294df 100644 (file)
@@ -30,7 +30,7 @@ config COMPAT_BINFMT_ELF
 config BINFMT_ELF_FDPIC
        bool "Kernel support for FDPIC ELF binaries"
        default y
-       depends on (FRV || BLACKFIN)
+       depends on (FRV || BLACKFIN || (SUPERH32 && !MMU))
        help
          ELF FDPIC binaries are based on ELF, but allow the individual load
          segments of a binary to be located in memory independently of each
index 3b2178b4bb66a6a776aa34b287123c8ef6552d3f..a1482a5eff153384c4f1f4b2e9a1a30b8f113d4d 100644 (file)
@@ -111,6 +111,7 @@ obj-$(CONFIG_ADFS_FS)               += adfs/
 obj-$(CONFIG_FUSE_FS)          += fuse/
 obj-$(CONFIG_UDF_FS)           += udf/
 obj-$(CONFIG_SUN_OPENPROMFS)   += openpromfs/
+obj-$(CONFIG_OMFS_FS)          += omfs/
 obj-$(CONFIG_JFS_FS)           += jfs/
 obj-$(CONFIG_XFS_FS)           += xfs/
 obj-$(CONFIG_9P_FS)            += 9p/
index 9e421eeb672bed6ae53f85ff9a4eaf7cdcf92c92..26f3b43726bb98d88f1bdfbd7de19579844300de 100644 (file)
@@ -249,7 +249,7 @@ static void adfs_destroy_inode(struct inode *inode)
        kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct adfs_inode_info *ei = (struct adfs_inode_info *) foo;
 
index 223b1917093ea357ffe68440199cddd7abdd0489..e9ec915f7553f1e7e821d40a7ee9671b5c9eea1b 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/amigaffs.h>
+#include <linux/mutex.h>
 
 /* AmigaOS allows file names with up to 30 characters length.
  * Names longer than that will be silently truncated. If you
@@ -98,7 +99,7 @@ struct affs_sb_info {
        gid_t s_gid;                    /* gid to override */
        umode_t s_mode;                 /* mode to override */
        struct buffer_head *s_root_bh;  /* Cached root block. */
-       struct semaphore s_bmlock;      /* Protects bitmap access. */
+       struct mutex s_bmlock;          /* Protects bitmap access. */
        struct affs_bm_info *s_bitmap;  /* Bitmap infos. */
        u32 s_bmap_count;               /* # of bitmap blocks. */
        u32 s_bmap_bits;                /* # of bits in one bitmap blocks */
index c4a5ad09ddf2c2a76d38ddf4d91f7126058029c3..dc5ef14bdc1c24c58f3e31316240dcae52107c85 100644 (file)
@@ -45,14 +45,14 @@ affs_count_free_blocks(struct super_block *sb)
        if (sb->s_flags & MS_RDONLY)
                return 0;
 
-       down(&AFFS_SB(sb)->s_bmlock);
+       mutex_lock(&AFFS_SB(sb)->s_bmlock);
 
        bm = AFFS_SB(sb)->s_bitmap;
        free = 0;
        for (i = AFFS_SB(sb)->s_bmap_count; i > 0; bm++, i--)
                free += bm->bm_free;
 
-       up(&AFFS_SB(sb)->s_bmlock);
+       mutex_unlock(&AFFS_SB(sb)->s_bmlock);
 
        return free;
 }
@@ -76,7 +76,7 @@ affs_free_block(struct super_block *sb, u32 block)
        bit     = blk % sbi->s_bmap_bits;
        bm      = &sbi->s_bitmap[bmap];
 
-       down(&sbi->s_bmlock);
+       mutex_lock(&sbi->s_bmlock);
 
        bh = sbi->s_bmap_bh;
        if (sbi->s_last_bmap != bmap) {
@@ -105,19 +105,19 @@ affs_free_block(struct super_block *sb, u32 block)
        sb->s_dirt = 1;
        bm->bm_free++;
 
-       up(&sbi->s_bmlock);
+       mutex_unlock(&sbi->s_bmlock);
        return;
 
 err_free:
        affs_warning(sb,"affs_free_block","Trying to free block %u which is already free", block);
-       up(&sbi->s_bmlock);
+       mutex_unlock(&sbi->s_bmlock);
        return;
 
 err_bh_read:
        affs_error(sb,"affs_free_block","Cannot read bitmap block %u", bm->bm_key);
        sbi->s_bmap_bh = NULL;
        sbi->s_last_bmap = ~0;
-       up(&sbi->s_bmlock);
+       mutex_unlock(&sbi->s_bmlock);
        return;
 
 err_range:
@@ -168,7 +168,7 @@ affs_alloc_block(struct inode *inode, u32 goal)
        bmap = blk / sbi->s_bmap_bits;
        bm = &sbi->s_bitmap[bmap];
 
-       down(&sbi->s_bmlock);
+       mutex_lock(&sbi->s_bmlock);
 
        if (bm->bm_free)
                goto find_bmap_bit;
@@ -249,7 +249,7 @@ find_bit:
        mark_buffer_dirty(bh);
        sb->s_dirt = 1;
 
-       up(&sbi->s_bmlock);
+       mutex_unlock(&sbi->s_bmlock);
 
        pr_debug("%d\n", blk);
        return blk;
@@ -259,7 +259,7 @@ err_bh_read:
        sbi->s_bmap_bh = NULL;
        sbi->s_last_bmap = ~0;
 err_full:
-       up(&sbi->s_bmlock);
+       mutex_unlock(&sbi->s_bmlock);
        pr_debug("failed\n");
        return 0;
 }
index 6eac7bdeec94dc320924d7be0892fb89a23cde72..1377b1240b6eadba12cf89c5b961d5d90d33c594 100644 (file)
@@ -46,8 +46,6 @@ const struct inode_operations affs_file_inode_operations = {
 static int
 affs_file_open(struct inode *inode, struct file *filp)
 {
-       if (atomic_read(&filp->f_count) != 1)
-               return 0;
        pr_debug("AFFS: open(%lu,%d)\n",
                 inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
        atomic_inc(&AFFS_I(inode)->i_opencnt);
@@ -57,8 +55,6 @@ affs_file_open(struct inode *inode, struct file *filp)
 static int
 affs_file_release(struct inode *inode, struct file *filp)
 {
-       if (atomic_read(&filp->f_count) != 0)
-               return 0;
        pr_debug("AFFS: release(%lu, %d)\n",
                 inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
 
index d214837d5e42a868009d75084e27716f7937e0b2..3a89094f93d0f1c772526be731648e90b3e5f002 100644 (file)
@@ -90,7 +90,7 @@ static void affs_destroy_inode(struct inode *inode)
        kmem_cache_free(affs_inode_cachep, AFFS_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct affs_inode_info *ei = (struct affs_inode_info *) foo;
 
@@ -290,7 +290,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       init_MUTEX(&sbi->s_bmlock);
+       mutex_init(&sbi->s_bmlock);
 
        if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
                                &blocksize,&sbi->s_prefix,
index 7102824ba8479c6e2d006816fb3555311d56df61..3cb6920ff30bc6ee7f22a98a390b04119d1ae81c 100644 (file)
@@ -469,8 +469,6 @@ extern bool afs_cm_incoming_call(struct afs_call *);
 extern const struct inode_operations afs_dir_inode_operations;
 extern const struct file_operations afs_dir_file_operations;
 
-extern int afs_permission(struct inode *, int, struct nameidata *);
-
 /*
  * file.c
  */
@@ -605,7 +603,7 @@ extern void afs_clear_permits(struct afs_vnode *);
 extern void afs_cache_permit(struct afs_vnode *, struct key *, long);
 extern void afs_zap_permits(struct rcu_head *);
 extern struct key *afs_request_key(struct afs_cell *);
-extern int afs_permission(struct inode *, int, struct nameidata *);
+extern int afs_permission(struct inode *, int);
 
 /*
  * server.c
index 3bcbeceba1bb6a778b08328ea459023927a2ccc8..3ef504370034c2311fdd50f631856ac95ab76903 100644 (file)
@@ -284,7 +284,7 @@ static int afs_check_permit(struct afs_vnode *vnode, struct key *key,
  * - AFS ACLs are attached to directories only, and a file is controlled by its
  *   parent directory's ACL
  */
-int afs_permission(struct inode *inode, int mask, struct nameidata *nd)
+int afs_permission(struct inode *inode, int mask)
 {
        struct afs_vnode *vnode = AFS_FS_I(inode);
        afs_access_t uninitialized_var(access);
index 7e3faeef6818b104698096f910c50e113e9bed4d..250d8c4d66e40f765c383ed4531ead183112faad 100644 (file)
@@ -27,7 +27,7 @@
 
 #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
 
-static void afs_i_init_once(struct kmem_cache *cachep, void *foo);
+static void afs_i_init_once(void *foo);
 static int afs_get_sb(struct file_system_type *fs_type,
                      int flags, const char *dev_name,
                      void *data, struct vfsmount *mnt);
@@ -449,7 +449,7 @@ static void afs_put_super(struct super_block *sb)
 /*
  * initialise an inode cache slab element prior to any use
  */
-static void afs_i_init_once(struct kmem_cache *cachep, void *_vnode)
+static void afs_i_init_once(void *_vnode)
 {
        struct afs_vnode *vnode = _vnode;
 
index 0fb3117ddd93d8a517720a744cd415a4b914f63c..f658441d5666c9d108f8ec337b2e0909686723bb 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -512,8 +512,8 @@ static void aio_fput_routine(struct work_struct *data)
  */
 static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
 {
-       dprintk(KERN_DEBUG "aio_put(%p): f_count=%d\n",
-               req, atomic_read(&req->ki_filp->f_count));
+       dprintk(KERN_DEBUG "aio_put(%p): f_count=%ld\n",
+               req, atomic_long_read(&req->ki_filp->f_count));
 
        assert_spin_locked(&ctx->ctx_lock);
 
@@ -528,7 +528,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
        /* Must be done under the lock to serialise against cancellation.
         * Call this aio_fput as it duplicates fput via the fput_work.
         */
-       if (unlikely(atomic_dec_and_test(&req->ki_filp->f_count))) {
+       if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) {
                get_ioctx(ctx);
                spin_lock(&fput_lock);
                list_add(&req->ki_list, &fput_head);
@@ -586,7 +586,6 @@ static void use_mm(struct mm_struct *mm)
        struct task_struct *tsk = current;
 
        task_lock(tsk);
-       tsk->flags |= PF_BORROWED_MM;
        active_mm = tsk->active_mm;
        atomic_inc(&mm->mm_count);
        tsk->mm = mm;
@@ -610,7 +609,6 @@ static void unuse_mm(struct mm_struct *mm)
        struct task_struct *tsk = current;
 
        task_lock(tsk);
-       tsk->flags &= ~PF_BORROWED_MM;
        tsk->mm = NULL;
        /* active_mm is still 'mm' */
        enter_lazy_tlb(mm, tsk);
index 977ef208c05193bbe555a4b4bce50853f0483616..3662dd44896b71586e3a493193261d3a1adf92a6 100644 (file)
@@ -58,8 +58,9 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
  *                    of the file
  *
  * @name:    [in]    name of the "class" of the new file
- * @fops     [in]    file operations for the new file
- * @priv     [in]    private data for the new file (will be file's private_data)
+ * @fops:    [in]    file operations for the new file
+ * @priv:    [in]    private data for the new file (will be file's private_data)
+ * @flags:   [in]    flags
  *
  * Creates a new file by hooking it on a single inode. This is useful for files
  * that do not need to have a full-fledged inode in order to operate correctly.
@@ -68,7 +69,7 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
  * setup.  Returns new descriptor or -error.
  */
 int anon_inode_getfd(const char *name, const struct file_operations *fops,
-                    void *priv)
+                    void *priv, int flags)
 {
        struct qstr this;
        struct dentry *dentry;
@@ -78,7 +79,7 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
        if (IS_ERR(anon_inode_inode))
                return -ENODEV;
 
-       error = get_unused_fd();
+       error = get_unused_fd_flags(flags);
        if (error < 0)
                return error;
        fd = error;
@@ -115,7 +116,7 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
        file->f_mapping = anon_inode_inode->i_mapping;
 
        file->f_pos = 0;
-       file->f_flags = O_RDWR;
+       file->f_flags = O_RDWR | (flags & O_NONBLOCK);
        file->f_version = 0;
        file->private_data = priv;
 
index 966b73e25f82e06f69ad0eca22a3f6fe268c4cd0..26c71ba1eed49d2f500c9e8044e68693492a47ee 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -51,7 +51,7 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
        }
 
        /* Check for setting the inode time. */
-       if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
+       if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) {
                if (!is_owner_or_cap(inode))
                        goto error;
        }
@@ -108,6 +108,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
        struct timespec now;
        unsigned int ia_valid = attr->ia_valid;
 
+       if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) {
+               if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+                       return -EPERM;
+       }
+
        now = current_fs_time(inode->i_sb);
 
        attr->ia_ctime = now;
index c3d352d7fa9304cb44c6ec4e4542bbc46f8ec2b2..69a2f5c9231943f6adbe4497915b294fe7991a28 100644 (file)
@@ -52,7 +52,10 @@ struct autofs_info {
 
        int             flags;
 
-       struct list_head rehash;
+       struct completion expire_complete;
+
+       struct list_head active;
+       struct list_head expiring;
 
        struct autofs_sb_info *sbi;
        unsigned long last_used;
@@ -68,15 +71,14 @@ struct autofs_info {
 };
 
 #define AUTOFS_INF_EXPIRING    (1<<0) /* dentry is in the process of expiring */
+#define AUTOFS_INF_MOUNTPOINT  (1<<1) /* mountpoint status for direct expire */
 
 struct autofs_wait_queue {
        wait_queue_head_t queue;
        struct autofs_wait_queue *next;
        autofs_wqt_t wait_queue_token;
        /* We use the following to see what we are waiting for */
-       unsigned int hash;
-       unsigned int len;
-       char *name;
+       struct qstr name;
        u32 dev;
        u64 ino;
        uid_t uid;
@@ -85,7 +87,7 @@ struct autofs_wait_queue {
        pid_t tgid;
        /* This is for status reporting upon return */
        int status;
-       atomic_t wait_ctr;
+       unsigned int wait_ctr;
 };
 
 #define AUTOFS_SBI_MAGIC 0x6d4a556d
@@ -112,8 +114,9 @@ struct autofs_sb_info {
        struct mutex wq_mutex;
        spinlock_t fs_lock;
        struct autofs_wait_queue *queues; /* Wait queue pointer */
-       spinlock_t rehash_lock;
-       struct list_head rehash_list;
+       spinlock_t lookup_lock;
+       struct list_head active_list;
+       struct list_head expiring_list;
 };
 
 static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb)
@@ -138,18 +141,14 @@ static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) {
 static inline int autofs4_ispending(struct dentry *dentry)
 {
        struct autofs_info *inf = autofs4_dentry_ino(dentry);
-       int pending = 0;
 
        if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
                return 1;
 
-       if (inf) {
-               spin_lock(&inf->sbi->fs_lock);
-               pending = inf->flags & AUTOFS_INF_EXPIRING;
-               spin_unlock(&inf->sbi->fs_lock);
-       }
+       if (inf->flags & AUTOFS_INF_EXPIRING)
+               return 1;
 
-       return pending;
+       return 0;
 }
 
 static inline void autofs4_copy_atime(struct file *src, struct file *dst)
@@ -164,6 +163,7 @@ void autofs4_free_ino(struct autofs_info *);
 
 /* Expiration */
 int is_autofs4_dentry(struct dentry *);
+int autofs4_expire_wait(struct dentry *dentry);
 int autofs4_expire_run(struct super_block *, struct vfsmount *,
                        struct autofs_sb_info *,
                        struct autofs_packet_expire __user *);
index 894fee54d4d83bd1ce22c50817871f1dc8c6f0da..cdabb796ff018aa65eb20c4d6ec034613ab8e1c8 100644 (file)
@@ -259,13 +259,15 @@ static struct dentry *autofs4_expire_direct(struct super_block *sb,
        now = jiffies;
        timeout = sbi->exp_timeout;
 
-       /* Lock the tree as we must expire as a whole */
        spin_lock(&sbi->fs_lock);
        if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
                struct autofs_info *ino = autofs4_dentry_ino(root);
-
-               /* Set this flag early to catch sys_chdir and the like */
+               if (d_mountpoint(root)) {
+                       ino->flags |= AUTOFS_INF_MOUNTPOINT;
+                       root->d_mounted--;
+               }
                ino->flags |= AUTOFS_INF_EXPIRING;
+               init_completion(&ino->expire_complete);
                spin_unlock(&sbi->fs_lock);
                return root;
        }
@@ -292,6 +294,8 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
        struct list_head *next;
        int do_now = how & AUTOFS_EXP_IMMEDIATE;
        int exp_leaves = how & AUTOFS_EXP_LEAVES;
+       struct autofs_info *ino;
+       unsigned int ino_count;
 
        if (!root)
                return NULL;
@@ -316,6 +320,9 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
                dentry = dget(dentry);
                spin_unlock(&dcache_lock);
 
+               spin_lock(&sbi->fs_lock);
+               ino = autofs4_dentry_ino(dentry);
+
                /*
                 * Case 1: (i) indirect mount or top level pseudo direct mount
                 *         (autofs-4.1).
@@ -326,6 +333,11 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
                        DPRINTK("checking mountpoint %p %.*s",
                                dentry, (int)dentry->d_name.len, dentry->d_name.name);
 
+                       /* Path walk currently on this dentry? */
+                       ino_count = atomic_read(&ino->count) + 2;
+                       if (atomic_read(&dentry->d_count) > ino_count)
+                               goto next;
+
                        /* Can we umount this guy */
                        if (autofs4_mount_busy(mnt, dentry))
                                goto next;
@@ -343,23 +355,25 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
 
                /* Case 2: tree mount, expire iff entire tree is not busy */
                if (!exp_leaves) {
-                       /* Lock the tree as we must expire as a whole */
-                       spin_lock(&sbi->fs_lock);
-                       if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
-                               struct autofs_info *inf = autofs4_dentry_ino(dentry);
+                       /* Path walk currently on this dentry? */
+                       ino_count = atomic_read(&ino->count) + 1;
+                       if (atomic_read(&dentry->d_count) > ino_count)
+                               goto next;
 
-                               /* Set this flag early to catch sys_chdir and the like */
-                               inf->flags |= AUTOFS_INF_EXPIRING;
-                               spin_unlock(&sbi->fs_lock);
+                       if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
                                expired = dentry;
                                goto found;
                        }
-                       spin_unlock(&sbi->fs_lock);
                /*
                 * Case 3: pseudo direct mount, expire individual leaves
                 *         (autofs-4.1).
                 */
                } else {
+                       /* Path walk currently on this dentry? */
+                       ino_count = atomic_read(&ino->count) + 1;
+                       if (atomic_read(&dentry->d_count) > ino_count)
+                               goto next;
+
                        expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
                        if (expired) {
                                dput(dentry);
@@ -367,6 +381,7 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
                        }
                }
 next:
+               spin_unlock(&sbi->fs_lock);
                dput(dentry);
                spin_lock(&dcache_lock);
                next = next->next;
@@ -377,12 +392,45 @@ next:
 found:
        DPRINTK("returning %p %.*s",
                expired, (int)expired->d_name.len, expired->d_name.name);
+       ino = autofs4_dentry_ino(expired);
+       ino->flags |= AUTOFS_INF_EXPIRING;
+       init_completion(&ino->expire_complete);
+       spin_unlock(&sbi->fs_lock);
        spin_lock(&dcache_lock);
        list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
        spin_unlock(&dcache_lock);
        return expired;
 }
 
+int autofs4_expire_wait(struct dentry *dentry)
+{
+       struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+       struct autofs_info *ino = autofs4_dentry_ino(dentry);
+       int status;
+
+       /* Block on any pending expire */
+       spin_lock(&sbi->fs_lock);
+       if (ino->flags & AUTOFS_INF_EXPIRING) {
+               spin_unlock(&sbi->fs_lock);
+
+               DPRINTK("waiting for expire %p name=%.*s",
+                        dentry, dentry->d_name.len, dentry->d_name.name);
+
+               status = autofs4_wait(sbi, dentry, NFY_NONE);
+               wait_for_completion(&ino->expire_complete);
+
+               DPRINTK("expire done status=%d", status);
+
+               if (d_unhashed(dentry))
+                       return -EAGAIN;
+
+               return status;
+       }
+       spin_unlock(&sbi->fs_lock);
+
+       return 0;
+}
+
 /* Perform an expiry operation */
 int autofs4_expire_run(struct super_block *sb,
                      struct vfsmount *mnt,
@@ -390,7 +438,9 @@ int autofs4_expire_run(struct super_block *sb,
                      struct autofs_packet_expire __user *pkt_p)
 {
        struct autofs_packet_expire pkt;
+       struct autofs_info *ino;
        struct dentry *dentry;
+       int ret = 0;
 
        memset(&pkt,0,sizeof pkt);
 
@@ -406,9 +456,15 @@ int autofs4_expire_run(struct super_block *sb,
        dput(dentry);
 
        if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
-               return -EFAULT;
+               ret = -EFAULT;
 
-       return 0;
+       spin_lock(&sbi->fs_lock);
+       ino = autofs4_dentry_ino(dentry);
+       ino->flags &= ~AUTOFS_INF_EXPIRING;
+       complete_all(&ino->expire_complete);
+       spin_unlock(&sbi->fs_lock);
+
+       return ret;
 }
 
 /* Call repeatedly until it returns -EAGAIN, meaning there's nothing
@@ -433,9 +489,16 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
 
                /* This is synchronous because it makes the daemon a
                    little easier */
-               ino->flags |= AUTOFS_INF_EXPIRING;
                ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
+
+               spin_lock(&sbi->fs_lock);
+               if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
+                       sb->s_root->d_mounted++;
+                       ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
+               }
                ino->flags &= ~AUTOFS_INF_EXPIRING;
+               complete_all(&ino->expire_complete);
+               spin_unlock(&sbi->fs_lock);
                dput(dentry);
        }
 
index 2fdcf5e1d236a7d309283c009ed67ecda6796bcb..7bb3e5ba0537e29e6b11f438619f4ccecb71dac0 100644 (file)
 
 static void ino_lnkfree(struct autofs_info *ino)
 {
-       kfree(ino->u.symlink);
-       ino->u.symlink = NULL;
+       if (ino->u.symlink) {
+               kfree(ino->u.symlink);
+               ino->u.symlink = NULL;
+       }
 }
 
 struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
@@ -41,16 +43,18 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
        if (ino == NULL)
                return NULL;
 
-       ino->flags = 0;
-       ino->mode = mode;
-       ino->inode = NULL;
-       ino->dentry = NULL;
-       ino->size = 0;
-
-       INIT_LIST_HEAD(&ino->rehash);
+       if (!reinit) {
+               ino->flags = 0;
+               ino->inode = NULL;
+               ino->dentry = NULL;
+               ino->size = 0;
+               INIT_LIST_HEAD(&ino->active);
+               INIT_LIST_HEAD(&ino->expiring);
+               atomic_set(&ino->count, 0);
+       }
 
+       ino->mode = mode;
        ino->last_used = jiffies;
-       atomic_set(&ino->count, 0);
 
        ino->sbi = sbi;
 
@@ -159,8 +163,8 @@ void autofs4_kill_sb(struct super_block *sb)
        if (!sbi)
                goto out_kill_sb;
 
-       if (!sbi->catatonic)
-               autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */
+       /* Free wait queues, close pipe */
+       autofs4_catatonic_mode(sbi);
 
        /* Clean up and release dangling references */
        autofs4_force_release(sbi);
@@ -338,8 +342,9 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
        mutex_init(&sbi->wq_mutex);
        spin_lock_init(&sbi->fs_lock);
        sbi->queues = NULL;
-       spin_lock_init(&sbi->rehash_lock);
-       INIT_LIST_HEAD(&sbi->rehash_list);
+       spin_lock_init(&sbi->lookup_lock);
+       INIT_LIST_HEAD(&sbi->active_list);
+       INIT_LIST_HEAD(&sbi->expiring_list);
        s->s_blocksize = 1024;
        s->s_blocksize_bits = 10;
        s->s_magic = AUTOFS_SUPER_MAGIC;
index edf5b6bddb528a43bb85e51eb834ecbdb14a7877..bcfb2dc0a61bf56d0e1c4be07612f24454834c08 100644 (file)
@@ -25,25 +25,25 @@ static int autofs4_dir_rmdir(struct inode *,struct dentry *);
 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
 static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
 static int autofs4_dir_open(struct inode *inode, struct file *file);
-static int autofs4_dir_close(struct inode *inode, struct file *file);
-static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
-static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
 static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
 static void *autofs4_follow_link(struct dentry *, struct nameidata *);
 
+#define TRIGGER_FLAGS   (LOOKUP_CONTINUE | LOOKUP_DIRECTORY)
+#define TRIGGER_INTENTS (LOOKUP_OPEN | LOOKUP_CREATE)
+
 const struct file_operations autofs4_root_operations = {
        .open           = dcache_dir_open,
        .release        = dcache_dir_close,
        .read           = generic_read_dir,
-       .readdir        = autofs4_root_readdir,
+       .readdir        = dcache_readdir,
        .ioctl          = autofs4_root_ioctl,
 };
 
 const struct file_operations autofs4_dir_operations = {
        .open           = autofs4_dir_open,
-       .release        = autofs4_dir_close,
+       .release        = dcache_dir_close,
        .read           = generic_read_dir,
-       .readdir        = autofs4_dir_readdir,
+       .readdir        = dcache_readdir,
 };
 
 const struct inode_operations autofs4_indirect_root_inode_operations = {
@@ -70,42 +70,10 @@ const struct inode_operations autofs4_dir_inode_operations = {
        .rmdir          = autofs4_dir_rmdir,
 };
 
-static int autofs4_root_readdir(struct file *file, void *dirent,
-                               filldir_t filldir)
-{
-       struct autofs_sb_info *sbi = autofs4_sbi(file->f_path.dentry->d_sb);
-       int oz_mode = autofs4_oz_mode(sbi);
-
-       DPRINTK("called, filp->f_pos = %lld", file->f_pos);
-
-       /*
-        * Don't set reghost flag if:
-        * 1) f_pos is larger than zero -- we've already been here.
-        * 2) we haven't even enabled reghosting in the 1st place.
-        * 3) this is the daemon doing a readdir
-        */
-       if (oz_mode && file->f_pos == 0 && sbi->reghost_enabled)
-               sbi->needs_reghost = 1;
-
-       DPRINTK("needs_reghost = %d", sbi->needs_reghost);
-
-       return dcache_readdir(file, dirent, filldir);
-}
-
 static int autofs4_dir_open(struct inode *inode, struct file *file)
 {
        struct dentry *dentry = file->f_path.dentry;
-       struct vfsmount *mnt = file->f_path.mnt;
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-       struct dentry *cursor;
-       int status;
-
-       status = dcache_dir_open(inode, file);
-       if (status)
-               goto out;
-
-       cursor = file->private_data;
-       cursor->d_fsdata = NULL;
 
        DPRINTK("file=%p dentry=%p %.*s",
                file, dentry, dentry->d_name.len, dentry->d_name.name);
@@ -113,159 +81,32 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
        if (autofs4_oz_mode(sbi))
                goto out;
 
-       if (autofs4_ispending(dentry)) {
-               DPRINTK("dentry busy");
-               dcache_dir_close(inode, file);
-               status = -EBUSY;
-               goto out;
-       }
-
-       status = -ENOENT;
-       if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) {
-               struct nameidata nd;
-               int empty, ret;
-
-               /* In case there are stale directory dentrys from a failed mount */
-               spin_lock(&dcache_lock);
-               empty = list_empty(&dentry->d_subdirs);
+       /*
+        * An empty directory in an autofs file system is always a
+        * mount point. The daemon must have failed to mount this
+        * during lookup so it doesn't exist. This can happen, for
+        * example, if user space returns an incorrect status for a
+        * mount request. Otherwise we're doing a readdir on the
+        * autofs file system so just let the libfs routines handle
+        * it.
+        */
+       spin_lock(&dcache_lock);
+       if (!d_mountpoint(dentry) && __simple_empty(dentry)) {
                spin_unlock(&dcache_lock);
-
-               if (!empty)
-                       d_invalidate(dentry);
-
-               nd.flags = LOOKUP_DIRECTORY;
-               ret = (dentry->d_op->d_revalidate)(dentry, &nd);
-
-               if (ret <= 0) {
-                       if (ret < 0)
-                               status = ret;
-                       dcache_dir_close(inode, file);
-                       goto out;
-               }
+               return -ENOENT;
        }
+       spin_unlock(&dcache_lock);
 
-       if (d_mountpoint(dentry)) {
-               struct file *fp = NULL;
-               struct path fp_path = { .dentry = dentry, .mnt = mnt };
-
-               path_get(&fp_path);
-
-               if (!autofs4_follow_mount(&fp_path.mnt, &fp_path.dentry)) {
-                       path_put(&fp_path);
-                       dcache_dir_close(inode, file);
-                       goto out;
-               }
-
-               fp = dentry_open(fp_path.dentry, fp_path.mnt, file->f_flags);
-               status = PTR_ERR(fp);
-               if (IS_ERR(fp)) {
-                       dcache_dir_close(inode, file);
-                       goto out;
-               }
-               cursor->d_fsdata = fp;
-       }
-       return 0;
-out:
-       return status;
-}
-
-static int autofs4_dir_close(struct inode *inode, struct file *file)
-{
-       struct dentry *dentry = file->f_path.dentry;
-       struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-       struct dentry *cursor = file->private_data;
-       int status = 0;
-
-       DPRINTK("file=%p dentry=%p %.*s",
-               file, dentry, dentry->d_name.len, dentry->d_name.name);
-
-       if (autofs4_oz_mode(sbi))
-               goto out;
-
-       if (autofs4_ispending(dentry)) {
-               DPRINTK("dentry busy");
-               status = -EBUSY;
-               goto out;
-       }
-
-       if (d_mountpoint(dentry)) {
-               struct file *fp = cursor->d_fsdata;
-               if (!fp) {
-                       status = -ENOENT;
-                       goto out;
-               }
-               filp_close(fp, current->files);
-       }
-out:
-       dcache_dir_close(inode, file);
-       return status;
-}
-
-static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
-{
-       struct dentry *dentry = file->f_path.dentry;
-       struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-       struct dentry *cursor = file->private_data;
-       int status;
-
-       DPRINTK("file=%p dentry=%p %.*s",
-               file, dentry, dentry->d_name.len, dentry->d_name.name);
-
-       if (autofs4_oz_mode(sbi))
-               goto out;
-
-       if (autofs4_ispending(dentry)) {
-               DPRINTK("dentry busy");
-               return -EBUSY;
-       }
-
-       if (d_mountpoint(dentry)) {
-               struct file *fp = cursor->d_fsdata;
-
-               if (!fp)
-                       return -ENOENT;
-
-               if (!fp->f_op || !fp->f_op->readdir)
-                       goto out;
-
-               status = vfs_readdir(fp, filldir, dirent);
-               file->f_pos = fp->f_pos;
-               if (status)
-                       autofs4_copy_atime(file, fp);
-               return status;
-       }
 out:
-       return dcache_readdir(file, dirent, filldir);
+       return dcache_dir_open(inode, file);
 }
 
 static int try_to_fill_dentry(struct dentry *dentry, int flags)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
-       struct dentry *new;
        int status;
 
-       /* Block on any pending expiry here; invalidate the dentry
-           when expiration is done to trigger mount request with a new
-           dentry */
-       if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
-               DPRINTK("waiting for expire %p name=%.*s",
-                        dentry, dentry->d_name.len, dentry->d_name.name);
-
-               status = autofs4_wait(sbi, dentry, NFY_NONE);
-
-               DPRINTK("expire done status=%d", status);
-
-               /*
-                * If the directory still exists the mount request must
-                * continue otherwise it can't be followed at the right
-                * time during the walk.
-                */
-               status = d_invalidate(dentry);
-               if (status != -EBUSY)
-                       return -EAGAIN;
-       }
-
        DPRINTK("dentry=%p %.*s ino=%p",
                 dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
 
@@ -292,7 +133,8 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
                        return status;
                }
        /* Trigger mount for path component or follow link */
-       } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) ||
+       } else if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
+                       flags & (TRIGGER_FLAGS | TRIGGER_INTENTS) ||
                        current->link_count) {
                DPRINTK("waiting for mount name=%.*s",
                        dentry->d_name.len, dentry->d_name.name);
@@ -320,26 +162,6 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
        dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
        spin_unlock(&dentry->d_lock);
 
-       /*
-        * The dentry that is passed in from lookup may not be the one
-        * we end up using, as mkdir can create a new one.  If this
-        * happens, and another process tries the lookup at the same time,
-        * it will set the PENDING flag on this new dentry, but add itself
-        * to our waitq.  Then, if after the lookup succeeds, the first
-        * process that requested the mount performs another lookup of the
-        * same directory, it will show up as still pending!  So, we need
-        * to redo the lookup here and clear pending on that dentry.
-        */
-       if (d_unhashed(dentry)) {
-               new = d_lookup(dentry->d_parent, &dentry->d_name);
-               if (new) {
-                       spin_lock(&new->d_lock);
-                       new->d_flags &= ~DCACHE_AUTOFS_PENDING;
-                       spin_unlock(&new->d_lock);
-                       dput(new);
-               }
-       }
-
        return 0;
 }
 
@@ -355,51 +177,63 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
        DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d",
                dentry, dentry->d_name.len, dentry->d_name.name, oz_mode,
                nd->flags);
-
-       /* If it's our master or we shouldn't trigger a mount we're done */
-       lookup_type = nd->flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY);
-       if (oz_mode || !lookup_type)
+       /*
+        * For an expire of a covered direct or offset mount we need
+        * to beeak out of follow_down() at the autofs mount trigger
+        * (d_mounted--), so we can see the expiring flag, and manage
+        * the blocking and following here until the expire is completed.
+        */
+       if (oz_mode) {
+               spin_lock(&sbi->fs_lock);
+               if (ino->flags & AUTOFS_INF_EXPIRING) {
+                       spin_unlock(&sbi->fs_lock);
+                       /* Follow down to our covering mount. */
+                       if (!follow_down(&nd->path.mnt, &nd->path.dentry))
+                               goto done;
+                       goto follow;
+               }
+               spin_unlock(&sbi->fs_lock);
                goto done;
+       }
 
-       /* If an expire request is pending wait for it. */
-       if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
-               DPRINTK("waiting for active request %p name=%.*s",
-                       dentry, dentry->d_name.len, dentry->d_name.name);
-
-               status = autofs4_wait(sbi, dentry, NFY_NONE);
+       /* If an expire request is pending everyone must wait. */
+       autofs4_expire_wait(dentry);
 
-               DPRINTK("request done status=%d", status);
-       }
+       /* We trigger a mount for almost all flags */
+       lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS);
+       if (!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING))
+               goto follow;
 
        /*
-        * If the dentry contains directories then it is an
-        * autofs multi-mount with no root mount offset. So
-        * don't try to mount it again.
+        * If the dentry contains directories then it is an autofs
+        * multi-mount with no root mount offset. So don't try to
+        * mount it again.
         */
        spin_lock(&dcache_lock);
-       if (!d_mountpoint(dentry) && __simple_empty(dentry)) {
+       if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
+           (!d_mountpoint(dentry) && __simple_empty(dentry))) {
                spin_unlock(&dcache_lock);
 
                status = try_to_fill_dentry(dentry, 0);
                if (status)
                        goto out_error;
 
-               /*
-                * The mount succeeded but if there is no root mount
-                * it must be an autofs multi-mount with no root offset
-                * so we don't need to follow the mount.
-                */
-               if (d_mountpoint(dentry)) {
-                       if (!autofs4_follow_mount(&nd->path.mnt,
-                                                 &nd->path.dentry)) {
-                               status = -ENOENT;
-                               goto out_error;
-                       }
-               }
-
-               goto done;
+               goto follow;
        }
        spin_unlock(&dcache_lock);
+follow:
+       /*
+        * If there is no root mount it must be an autofs
+        * multi-mount with no root offset so we don't need
+        * to follow it.
+        */
+       if (d_mountpoint(dentry)) {
+               if (!autofs4_follow_mount(&nd->path.mnt,
+                                         &nd->path.dentry)) {
+                       status = -ENOENT;
+                       goto out_error;
+               }
+       }
 
 done:
        return NULL;
@@ -424,11 +258,22 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
        int status = 1;
 
        /* Pending dentry */
+       spin_lock(&sbi->fs_lock);
        if (autofs4_ispending(dentry)) {
                /* The daemon never causes a mount to trigger */
+               spin_unlock(&sbi->fs_lock);
+
                if (oz_mode)
                        return 1;
 
+               /*
+                * If the directory has gone away due to an expire
+                * we have been called as ->d_revalidate() and so
+                * we need to return false and proceed to ->lookup().
+                */
+               if (autofs4_expire_wait(dentry) == -EAGAIN)
+                       return 0;
+
                /*
                 * A zero status is success otherwise we have a
                 * negative error code.
@@ -437,17 +282,9 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
                if (status == 0)
                        return 1;
 
-               /*
-                * A status of EAGAIN here means that the dentry has gone
-                * away while waiting for an expire to complete. If we are
-                * racing with expire lookup will wait for it so this must
-                * be a revalidate and we need to send it to lookup.
-                */
-               if (status == -EAGAIN)
-                       return 0;
-
                return status;
        }
+       spin_unlock(&sbi->fs_lock);
 
        /* Negative dentry.. invalidate if "old" */
        if (dentry->d_inode == NULL)
@@ -461,6 +298,7 @@ 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);
+
                /* The daemon never causes a mount to trigger */
                if (oz_mode)
                        return 1;
@@ -493,10 +331,12 @@ void autofs4_dentry_release(struct dentry *de)
                struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb);
 
                if (sbi) {
-                       spin_lock(&sbi->rehash_lock);
-                       if (!list_empty(&inf->rehash))
-                               list_del(&inf->rehash);
-                       spin_unlock(&sbi->rehash_lock);
+                       spin_lock(&sbi->lookup_lock);
+                       if (!list_empty(&inf->active))
+                               list_del(&inf->active);
+                       if (!list_empty(&inf->expiring))
+                               list_del(&inf->expiring);
+                       spin_unlock(&sbi->lookup_lock);
                }
 
                inf->dentry = NULL;
@@ -518,7 +358,7 @@ static struct dentry_operations autofs4_dentry_operations = {
        .d_release      = autofs4_dentry_release,
 };
 
-static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
+static struct dentry *autofs4_lookup_active(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
 {
        unsigned int len = name->len;
        unsigned int hash = name->hash;
@@ -526,14 +366,66 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct
        struct list_head *p, *head;
 
        spin_lock(&dcache_lock);
-       spin_lock(&sbi->rehash_lock);
-       head = &sbi->rehash_list;
+       spin_lock(&sbi->lookup_lock);
+       head = &sbi->active_list;
        list_for_each(p, head) {
                struct autofs_info *ino;
                struct dentry *dentry;
                struct qstr *qstr;
 
-               ino = list_entry(p, struct autofs_info, rehash);
+               ino = list_entry(p, struct autofs_info, active);
+               dentry = ino->dentry;
+
+               spin_lock(&dentry->d_lock);
+
+               /* Already gone? */
+               if (atomic_read(&dentry->d_count) == 0)
+                       goto next;
+
+               qstr = &dentry->d_name;
+
+               if (dentry->d_name.hash != hash)
+                       goto next;
+               if (dentry->d_parent != parent)
+                       goto next;
+
+               if (qstr->len != len)
+                       goto next;
+               if (memcmp(qstr->name, str, len))
+                       goto next;
+
+               if (d_unhashed(dentry)) {
+                       dget(dentry);
+                       spin_unlock(&dentry->d_lock);
+                       spin_unlock(&sbi->lookup_lock);
+                       spin_unlock(&dcache_lock);
+                       return dentry;
+               }
+next:
+               spin_unlock(&dentry->d_lock);
+       }
+       spin_unlock(&sbi->lookup_lock);
+       spin_unlock(&dcache_lock);
+
+       return NULL;
+}
+
+static struct dentry *autofs4_lookup_expiring(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
+{
+       unsigned int len = name->len;
+       unsigned int hash = name->hash;
+       const unsigned char *str = name->name;
+       struct list_head *p, *head;
+
+       spin_lock(&dcache_lock);
+       spin_lock(&sbi->lookup_lock);
+       head = &sbi->expiring_list;
+       list_for_each(p, head) {
+               struct autofs_info *ino;
+               struct dentry *dentry;
+               struct qstr *qstr;
+
+               ino = list_entry(p, struct autofs_info, expiring);
                dentry = ino->dentry;
 
                spin_lock(&dentry->d_lock);
@@ -555,33 +447,16 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct
                        goto next;
 
                if (d_unhashed(dentry)) {
-                       struct inode *inode = dentry->d_inode;
-
-                       ino = autofs4_dentry_ino(dentry);
-                       list_del_init(&ino->rehash);
                        dget(dentry);
-                       /*
-                        * Make the rehashed dentry negative so the VFS
-                        * behaves as it should.
-                        */
-                       if (inode) {
-                               dentry->d_inode = NULL;
-                               list_del_init(&dentry->d_alias);
-                               spin_unlock(&dentry->d_lock);
-                               spin_unlock(&sbi->rehash_lock);
-                               spin_unlock(&dcache_lock);
-                               iput(inode);
-                               return dentry;
-                       }
                        spin_unlock(&dentry->d_lock);
-                       spin_unlock(&sbi->rehash_lock);
+                       spin_unlock(&sbi->lookup_lock);
                        spin_unlock(&dcache_lock);
                        return dentry;
                }
 next:
                spin_unlock(&dentry->d_lock);
        }
-       spin_unlock(&sbi->rehash_lock);
+       spin_unlock(&sbi->lookup_lock);
        spin_unlock(&dcache_lock);
 
        return NULL;
@@ -591,7 +466,8 @@ next:
 static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
        struct autofs_sb_info *sbi;
-       struct dentry *unhashed;
+       struct autofs_info *ino;
+       struct dentry *expiring, *unhashed;
        int oz_mode;
 
        DPRINTK("name = %.*s",
@@ -607,8 +483,26 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
        DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
                 current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode);
 
-       unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name);
-       if (!unhashed) {
+       expiring = autofs4_lookup_expiring(sbi, dentry->d_parent, &dentry->d_name);
+       if (expiring) {
+               /*
+                * If we are racing with expire the request might not
+                * be quite complete but the directory has been removed
+                * so it must have been successful, so just wait for it.
+                */
+               ino = autofs4_dentry_ino(expiring);
+               autofs4_expire_wait(expiring);
+               spin_lock(&sbi->lookup_lock);
+               if (!list_empty(&ino->expiring))
+                       list_del_init(&ino->expiring);
+               spin_unlock(&sbi->lookup_lock);
+               dput(expiring);
+       }
+
+       unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name);
+       if (unhashed)
+               dentry = unhashed;
+       else {
                /*
                 * Mark the dentry incomplete but don't hash it. We do this
                 * to serialize our inode creation operations (symlink and
@@ -622,39 +516,34 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
                 */
                dentry->d_op = &autofs4_root_dentry_operations;
 
-               dentry->d_fsdata = NULL;
-               d_instantiate(dentry, NULL);
-       } else {
-               struct autofs_info *ino = autofs4_dentry_ino(unhashed);
-               DPRINTK("rehash %p with %p", dentry, unhashed);
                /*
-                * If we are racing with expire the request might not
-                * be quite complete but the directory has been removed
-                * so it must have been successful, so just wait for it.
-                * We need to ensure the AUTOFS_INF_EXPIRING flag is clear
-                * before continuing as revalidate may fail when calling
-                * try_to_fill_dentry (returning EAGAIN) if we don't.
+                * And we need to ensure that the same dentry is used for
+                * all following lookup calls until it is hashed so that
+                * the dentry flags are persistent throughout the request.
                 */
-               while (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
-                       DPRINTK("wait for incomplete expire %p name=%.*s",
-                               unhashed, unhashed->d_name.len,
-                               unhashed->d_name.name);
-                       autofs4_wait(sbi, unhashed, NFY_NONE);
-                       DPRINTK("request completed");
-               }
-               dentry = unhashed;
+               ino = autofs4_init_ino(NULL, sbi, 0555);
+               if (!ino)
+                       return ERR_PTR(-ENOMEM);
+
+               dentry->d_fsdata = ino;
+               ino->dentry = dentry;
+
+               spin_lock(&sbi->lookup_lock);
+               list_add(&ino->active, &sbi->active_list);
+               spin_unlock(&sbi->lookup_lock);
+
+               d_instantiate(dentry, NULL);
        }
 
        if (!oz_mode) {
                spin_lock(&dentry->d_lock);
                dentry->d_flags |= DCACHE_AUTOFS_PENDING;
                spin_unlock(&dentry->d_lock);
-       }
-
-       if (dentry->d_op && dentry->d_op->d_revalidate) {
-               mutex_unlock(&dir->i_mutex);
-               (dentry->d_op->d_revalidate)(dentry, nd);
-               mutex_lock(&dir->i_mutex);
+               if (dentry->d_op && dentry->d_op->d_revalidate) {
+                       mutex_unlock(&dir->i_mutex);
+                       (dentry->d_op->d_revalidate)(dentry, nd);
+                       mutex_lock(&dir->i_mutex);
+               }
        }
 
        /*
@@ -673,9 +562,11 @@ 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);
+               if (!oz_mode) {
+                       spin_lock(&dentry->d_lock);
+                       dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
+                       spin_unlock(&dentry->d_lock);
+               }
        }
 
        /*
@@ -706,7 +597,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
        }
 
        if (unhashed)
-               return dentry;
+               return unhashed;
 
        return NULL;
 }
@@ -728,20 +619,31 @@ static int autofs4_dir_symlink(struct inode *dir,
                return -EACCES;
 
        ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555);
-       if (ino == NULL)
-               return -ENOSPC;
+       if (!ino)
+               return -ENOMEM;
 
-       ino->size = strlen(symname);
-       ino->u.symlink = cp = kmalloc(ino->size + 1, GFP_KERNEL);
+       spin_lock(&sbi->lookup_lock);
+       if (!list_empty(&ino->active))
+               list_del_init(&ino->active);
+       spin_unlock(&sbi->lookup_lock);
 
-       if (cp == NULL) {
-               kfree(ino);
-               return -ENOSPC;
+       ino->size = strlen(symname);
+       cp = kmalloc(ino->size + 1, GFP_KERNEL);
+       if (!cp) {
+               if (!dentry->d_fsdata)
+                       kfree(ino);
+               return -ENOMEM;
        }
 
        strcpy(cp, symname);
 
        inode = autofs4_get_inode(dir->i_sb, ino);
+       if (!inode) {
+               kfree(cp);
+               if (!dentry->d_fsdata)
+                       kfree(ino);
+               return -ENOMEM;
+       }
        d_add(dentry, inode);
 
        if (dir == dir->i_sb->s_root->d_inode)
@@ -757,6 +659,7 @@ static int autofs4_dir_symlink(struct inode *dir,
                atomic_inc(&p_ino->count);
        ino->inode = inode;
 
+       ino->u.symlink = cp;
        dir->i_mtime = CURRENT_TIME;
 
        return 0;
@@ -769,9 +672,8 @@ static int autofs4_dir_symlink(struct inode *dir,
  * that the file no longer exists. However, doing that means that the
  * VFS layer can turn the dentry into a negative dentry.  We don't want
  * this, because the unlink is probably the result of an expire.
- * We simply d_drop it and add it to a rehash candidates list in the
- * super block, which allows the dentry lookup to reuse it retaining
- * the flags, such as expire in progress, in case we're racing with expire.
+ * We simply d_drop it and add it to a expiring list in the super block,
+ * which allows the dentry lookup to check for an incomplete expire.
  *
  * If a process is blocked on the dentry waiting for the expire to finish,
  * it will invalidate the dentry and try to mount with a new one.
@@ -801,9 +703,10 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
        dir->i_mtime = CURRENT_TIME;
 
        spin_lock(&dcache_lock);
-       spin_lock(&sbi->rehash_lock);
-       list_add(&ino->rehash, &sbi->rehash_list);
-       spin_unlock(&sbi->rehash_lock);
+       spin_lock(&sbi->lookup_lock);
+       if (list_empty(&ino->expiring))
+               list_add(&ino->expiring, &sbi->expiring_list);
+       spin_unlock(&sbi->lookup_lock);
        spin_lock(&dentry->d_lock);
        __d_drop(dentry);
        spin_unlock(&dentry->d_lock);
@@ -829,9 +732,10 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
                spin_unlock(&dcache_lock);
                return -ENOTEMPTY;
        }
-       spin_lock(&sbi->rehash_lock);
-       list_add(&ino->rehash, &sbi->rehash_list);
-       spin_unlock(&sbi->rehash_lock);
+       spin_lock(&sbi->lookup_lock);
+       if (list_empty(&ino->expiring))
+               list_add(&ino->expiring, &sbi->expiring_list);
+       spin_unlock(&sbi->lookup_lock);
        spin_lock(&dentry->d_lock);
        __d_drop(dentry);
        spin_unlock(&dentry->d_lock);
@@ -866,10 +770,20 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                dentry, dentry->d_name.len, dentry->d_name.name);
 
        ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555);
-       if (ino == NULL)
-               return -ENOSPC;
+       if (!ino)
+               return -ENOMEM;
+
+       spin_lock(&sbi->lookup_lock);
+       if (!list_empty(&ino->active))
+               list_del_init(&ino->active);
+       spin_unlock(&sbi->lookup_lock);
 
        inode = autofs4_get_inode(dir->i_sb, ino);
+       if (!inode) {
+               if (!dentry->d_fsdata)
+                       kfree(ino);
+               return -ENOMEM;
+       }
        d_add(dentry, inode);
 
        if (dir == dir->i_sb->s_root->d_inode)
@@ -921,44 +835,6 @@ static inline int autofs4_get_protosubver(struct autofs_sb_info *sbi, int __user
        return put_user(sbi->sub_version, p);
 }
 
-/*
- * Tells the daemon whether we need to reghost or not. Also, clears
- * the reghost_needed flag.
- */
-static inline int autofs4_ask_reghost(struct autofs_sb_info *sbi, int __user *p)
-{
-       int status;
-
-       DPRINTK("returning %d", sbi->needs_reghost);
-
-       status = put_user(sbi->needs_reghost, p);
-       if (status)
-               return status;
-
-       sbi->needs_reghost = 0;
-       return 0;
-}
-
-/*
- * Enable / Disable reghosting ioctl() operation
- */
-static inline int autofs4_toggle_reghost(struct autofs_sb_info *sbi, int __user *p)
-{
-       int status;
-       int val;
-
-       status = get_user(val, p);
-
-       DPRINTK("reghost = %d", val);
-
-       if (status)
-               return status;
-
-       /* turn on/off reghosting, with the val */
-       sbi->reghost_enabled = val;
-       return 0;
-}
-
 /*
 * Tells the daemon whether it can umount the autofs mount.
 */
@@ -1023,11 +899,6 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp,
        case AUTOFS_IOC_SETTIMEOUT:
                return autofs4_get_set_timeout(sbi, p);
 
-       case AUTOFS_IOC_TOGGLEREGHOST:
-               return autofs4_toggle_reghost(sbi, p);
-       case AUTOFS_IOC_ASKREGHOST:
-               return autofs4_ask_reghost(sbi, p);
-
        case AUTOFS_IOC_ASKUMOUNT:
                return autofs4_ask_umount(filp->f_path.mnt, p);
 
index 75e5955c3f6d4fe5cf30b3ffcc3d6bc21a9fbffb..35216d18d8b56fa5a6b0ff8f07f37771698a0b75 100644 (file)
@@ -28,6 +28,12 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
 {
        struct autofs_wait_queue *wq, *nwq;
 
+       mutex_lock(&sbi->wq_mutex);
+       if (sbi->catatonic) {
+               mutex_unlock(&sbi->wq_mutex);
+               return;
+       }
+
        DPRINTK("entering catatonic mode");
 
        sbi->catatonic = 1;
@@ -36,13 +42,18 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
        while (wq) {
                nwq = wq->next;
                wq->status = -ENOENT; /* Magic is gone - report failure */
-               kfree(wq->name);
-               wq->name = NULL;
+               if (wq->name.name) {
+                       kfree(wq->name.name);
+                       wq->name.name = NULL;
+               }
+               wq->wait_ctr--;
                wake_up_interruptible(&wq->queue);
                wq = nwq;
        }
        fput(sbi->pipe);        /* Close the pipe */
        sbi->pipe = NULL;
+       sbi->pipefd = -1;
+       mutex_unlock(&sbi->wq_mutex);
 }
 
 static int autofs4_write(struct file *file, const void *addr, int bytes)
@@ -89,10 +100,11 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
                union autofs_packet_union v4_pkt;
                union autofs_v5_packet_union v5_pkt;
        } pkt;
+       struct file *pipe = NULL;
        size_t pktsz;
 
        DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d",
-               wq->wait_queue_token, wq->len, wq->name, type);
+               wq->wait_queue_token, wq->name.len, wq->name.name, type);
 
        memset(&pkt,0,sizeof pkt); /* For security reasons */
 
@@ -107,9 +119,9 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
                pktsz = sizeof(*mp);
 
                mp->wait_queue_token = wq->wait_queue_token;
-               mp->len = wq->len;
-               memcpy(mp->name, wq->name, wq->len);
-               mp->name[wq->len] = '\0';
+               mp->len = wq->name.len;
+               memcpy(mp->name, wq->name.name, wq->name.len);
+               mp->name[wq->name.len] = '\0';
                break;
        }
        case autofs_ptype_expire_multi:
@@ -119,9 +131,9 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
                pktsz = sizeof(*ep);
 
                ep->wait_queue_token = wq->wait_queue_token;
-               ep->len = wq->len;
-               memcpy(ep->name, wq->name, wq->len);
-               ep->name[wq->len] = '\0';
+               ep->len = wq->name.len;
+               memcpy(ep->name, wq->name.name, wq->name.len);
+               ep->name[wq->name.len] = '\0';
                break;
        }
        /*
@@ -138,9 +150,9 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
                pktsz = sizeof(*packet);
 
                packet->wait_queue_token = wq->wait_queue_token;
-               packet->len = wq->len;
-               memcpy(packet->name, wq->name, wq->len);
-               packet->name[wq->len] = '\0';
+               packet->len = wq->name.len;
+               memcpy(packet->name, wq->name.name, wq->name.len);
+               packet->name[wq->name.len] = '\0';
                packet->dev = wq->dev;
                packet->ino = wq->ino;
                packet->uid = wq->uid;
@@ -154,8 +166,19 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
                return;
        }
 
-       if (autofs4_write(sbi->pipe, &pkt, pktsz))
-               autofs4_catatonic_mode(sbi);
+       /* Check if we have become catatonic */
+       mutex_lock(&sbi->wq_mutex);
+       if (!sbi->catatonic) {
+               pipe = sbi->pipe;
+               get_file(pipe);
+       }
+       mutex_unlock(&sbi->wq_mutex);
+
+       if (pipe) {
+               if (autofs4_write(pipe, &pkt, pktsz))
+                       autofs4_catatonic_mode(sbi);
+               fput(pipe);
+       }
 }
 
 static int autofs4_getpath(struct autofs_sb_info *sbi,
@@ -191,58 +214,55 @@ static int autofs4_getpath(struct autofs_sb_info *sbi,
 }
 
 static struct autofs_wait_queue *
-autofs4_find_wait(struct autofs_sb_info *sbi,
-                 char *name, unsigned int hash, unsigned int len)
+autofs4_find_wait(struct autofs_sb_info *sbi, struct qstr *qstr)
 {
        struct autofs_wait_queue *wq;
 
        for (wq = sbi->queues; wq; wq = wq->next) {
-               if (wq->hash == hash &&
-                   wq->len == len &&
-                   wq->name && !memcmp(wq->name, name, len))
+               if (wq->name.hash == qstr->hash &&
+                   wq->name.len == qstr->len &&
+                   wq->name.name &&
+                        !memcmp(wq->name.name, qstr->name, qstr->len))
                        break;
        }
        return wq;
 }
 
-int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
-               enum autofs_notify notify)
+/*
+ * Check if we have a valid request.
+ * Returns
+ * 1 if the request should continue.
+ *   In this case we can return an autofs_wait_queue entry if one is
+ *   found or NULL to idicate a new wait needs to be created.
+ * 0 or a negative errno if the request shouldn't continue.
+ */
+static int validate_request(struct autofs_wait_queue **wait,
+                           struct autofs_sb_info *sbi,
+                           struct qstr *qstr,
+                           struct dentry*dentry, enum autofs_notify notify)
 {
-       struct autofs_info *ino;
        struct autofs_wait_queue *wq;
-       char *name;
-       unsigned int len = 0;
-       unsigned int hash = 0;
-       int status, type;
-
-       /* In catatonic mode, we don't wait for nobody */
-       if (sbi->catatonic)
-               return -ENOENT;
-       
-       name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
-       if (!name)
-               return -ENOMEM;
+       struct autofs_info *ino;
 
-       /* If this is a direct mount request create a dummy name */
-       if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT))
-               len = sprintf(name, "%p", dentry);
-       else {
-               len = autofs4_getpath(sbi, dentry, &name);
-               if (!len) {
-                       kfree(name);
-                       return -ENOENT;
-               }
+       /* Wait in progress, continue; */
+       wq = autofs4_find_wait(sbi, qstr);
+       if (wq) {
+               *wait = wq;
+               return 1;
        }
-       hash = full_name_hash(name, len);
 
-       if (mutex_lock_interruptible(&sbi->wq_mutex)) {
-               kfree(name);
-               return -EINTR;
-       }
+       *wait = NULL;
 
-       wq = autofs4_find_wait(sbi, name, hash, len);
+       /* If we don't yet have any info this is a new request */
        ino = autofs4_dentry_ino(dentry);
-       if (!wq && ino && notify == NFY_NONE) {
+       if (!ino)
+               return 1;
+
+       /*
+        * If we've been asked to wait on an existing expire (NFY_NONE)
+        * but there is no wait in the queue ...
+        */
+       if (notify == NFY_NONE) {
                /*
                 * Either we've betean the pending expire to post it's
                 * wait or it finished while we waited on the mutex.
@@ -253,13 +273,14 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                while (ino->flags & AUTOFS_INF_EXPIRING) {
                        mutex_unlock(&sbi->wq_mutex);
                        schedule_timeout_interruptible(HZ/10);
-                       if (mutex_lock_interruptible(&sbi->wq_mutex)) {
-                               kfree(name);
+                       if (mutex_lock_interruptible(&sbi->wq_mutex))
                                return -EINTR;
+
+                       wq = autofs4_find_wait(sbi, qstr);
+                       if (wq) {
+                               *wait = wq;
+                               return 1;
                        }
-                       wq = autofs4_find_wait(sbi, name, hash, len);
-                       if (wq)
-                               break;
                }
 
                /*
@@ -267,18 +288,96 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                 * cases where we wait on NFY_NONE neither depend on the
                 * return status of the wait.
                 */
-               if (!wq) {
+               return 0;
+       }
+
+       /*
+        * If we've been asked to trigger a mount and the request
+        * completed while we waited on the mutex ...
+        */
+       if (notify == NFY_MOUNT) {
+               /*
+                * If the dentry isn't hashed just go ahead and try the
+                * mount again with a new wait (not much else we can do).
+               */
+               if (!d_unhashed(dentry)) {
+                       /*
+                        * But if the dentry is hashed, that means that we
+                        * got here through the revalidate path.  Thus, we
+                        * need to check if the dentry has been mounted
+                        * while we waited on the wq_mutex. If it has,
+                        * simply return success.
+                        */
+                       if (d_mountpoint(dentry))
+                               return 0;
+               }
+       }
+
+       return 1;
+}
+
+int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
+               enum autofs_notify notify)
+{
+       struct autofs_wait_queue *wq;
+       struct qstr qstr;
+       char *name;
+       int status, ret, type;
+
+       /* In catatonic mode, we don't wait for nobody */
+       if (sbi->catatonic)
+               return -ENOENT;
+
+       if (!dentry->d_inode) {
+               /*
+                * A wait for a negative dentry is invalid for certain
+                * cases. A direct or offset mount "always" has its mount
+                * point directory created and so the request dentry must
+                * be positive or the map key doesn't exist. The situation
+                * is very similar for indirect mounts except only dentrys
+                * in the root of the autofs file system may be negative.
+                */
+               if (sbi->type & (AUTOFS_TYPE_DIRECT|AUTOFS_TYPE_OFFSET))
+                       return -ENOENT;
+               else if (!IS_ROOT(dentry->d_parent))
+                       return -ENOENT;
+       }
+
+       name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
+       if (!name)
+               return -ENOMEM;
+
+       /* If this is a direct mount request create a dummy name */
+       if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT))
+               qstr.len = sprintf(name, "%p", dentry);
+       else {
+               qstr.len = autofs4_getpath(sbi, dentry, &name);
+               if (!qstr.len) {
                        kfree(name);
-                       mutex_unlock(&sbi->wq_mutex);
-                       return 0;
+                       return -ENOENT;
                }
        }
+       qstr.name = name;
+       qstr.hash = full_name_hash(name, qstr.len);
+
+       if (mutex_lock_interruptible(&sbi->wq_mutex)) {
+               kfree(qstr.name);
+               return -EINTR;
+       }
+
+       ret = validate_request(&wq, sbi, &qstr, dentry, notify);
+       if (ret <= 0) {
+               if (ret == 0)
+                       mutex_unlock(&sbi->wq_mutex);
+               kfree(qstr.name);
+               return ret;
+       }
 
        if (!wq) {
                /* Create a new wait queue */
                wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
                if (!wq) {
-                       kfree(name);
+                       kfree(qstr.name);
                        mutex_unlock(&sbi->wq_mutex);
                        return -ENOMEM;
                }
@@ -289,9 +388,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                wq->next = sbi->queues;
                sbi->queues = wq;
                init_waitqueue_head(&wq->queue);
-               wq->hash = hash;
-               wq->name = name;
-               wq->len = len;
+               memcpy(&wq->name, &qstr, sizeof(struct qstr));
                wq->dev = autofs4_get_dev(sbi);
                wq->ino = autofs4_get_ino(sbi);
                wq->uid = current->uid;
@@ -299,7 +396,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                wq->pid = current->pid;
                wq->tgid = current->tgid;
                wq->status = -EINTR; /* Status return if interrupted */
-               atomic_set(&wq->wait_ctr, 2);
+               wq->wait_ctr = 2;
                mutex_unlock(&sbi->wq_mutex);
 
                if (sbi->version < 5) {
@@ -319,28 +416,25 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                }
 
                DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
-                       (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
+                       (unsigned long) wq->wait_queue_token, wq->name.len,
+                       wq->name.name, notify);
 
                /* autofs4_notify_daemon() may block */
                autofs4_notify_daemon(sbi, wq, type);
        } else {
-               atomic_inc(&wq->wait_ctr);
+               wq->wait_ctr++;
                mutex_unlock(&sbi->wq_mutex);
-               kfree(name);
+               kfree(qstr.name);
                DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
-                       (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
-       }
-
-       /* wq->name is NULL if and only if the lock is already released */
-
-       if (sbi->catatonic) {
-               /* We might have slept, so check again for catatonic mode */
-               wq->status = -ENOENT;
-               kfree(wq->name);
-               wq->name = NULL;
+                       (unsigned long) wq->wait_queue_token, wq->name.len,
+                       wq->name.name, notify);
        }
 
-       if (wq->name) {
+       /*
+        * wq->name.name is NULL iff the lock is already released
+        * or the mount has been made catatonic.
+        */
+       if (wq->name.name) {
                /* Block all but "shutdown" signals while waiting */
                sigset_t oldset;
                unsigned long irqflags;
@@ -351,7 +445,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                recalc_sigpending();
                spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
 
-               wait_event_interruptible(wq->queue, wq->name == NULL);
+               wait_event_interruptible(wq->queue, wq->name.name == NULL);
 
                spin_lock_irqsave(&current->sighand->siglock, irqflags);
                current->blocked = oldset;
@@ -364,8 +458,10 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
        status = wq->status;
 
        /* Are we the last process to need status? */
-       if (atomic_dec_and_test(&wq->wait_ctr))
+       mutex_lock(&sbi->wq_mutex);
+       if (!--wq->wait_ctr)
                kfree(wq);
+       mutex_unlock(&sbi->wq_mutex);
 
        return status;
 }
@@ -387,16 +483,13 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok
        }
 
        *wql = wq->next;        /* Unlink from chain */
-       mutex_unlock(&sbi->wq_mutex);
-       kfree(wq->name);
-       wq->name = NULL;        /* Do not wait on this queue */
-
+       kfree(wq->name.name);
+       wq->name.name = NULL;   /* Do not wait on this queue */
        wq->status = status;
-
-       if (atomic_dec_and_test(&wq->wait_ctr)) /* Is anyone still waiting for this guy? */
+       wake_up_interruptible(&wq->queue);
+       if (!--wq->wait_ctr)
                kfree(wq);
-       else
-               wake_up_interruptible(&wq->queue);
+       mutex_unlock(&sbi->wq_mutex);
 
        return 0;
 }
index f1c2ea8342f514c974539dd5a676b650efbf6e5f..5f1538c03b1bbeb068c089146cc28fc502bb0d83 100644 (file)
@@ -243,8 +243,7 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer,
        return -EIO;
 }
 
-static int bad_inode_permission(struct inode *inode, int mask,
-                       struct nameidata *nd)
+static int bad_inode_permission(struct inode *inode, int mask)
 {
        return -EIO;
 }
index e8717de3bab34f16f551004048fd91a4c6029cb1..02c6e62b72f80c031db4ec6d1d248e70a067168c 100644 (file)
@@ -289,7 +289,7 @@ befs_destroy_inode(struct inode *inode)
         kmem_cache_free(befs_inode_cachep, BEFS_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
         struct befs_inode_info *bi = (struct befs_inode_info *) foo;
 
index 70f5d3a8eede460af9faf2f6e45407cc01f7d086..7109e451abf7604083f7687087cb0e6a7f1006a1 100644 (file)
@@ -16,8 +16,9 @@ struct bfs_sb_info {
        unsigned long si_freei;
        unsigned long si_lf_eblk;
        unsigned long si_lasti;
-       unsigned long * si_imap;
-       struct buffer_head * si_sbh;            /* buffer header w/superblock */
+       unsigned long *si_imap;
+       struct buffer_head *si_sbh;             /* buffer header w/superblock */
+       struct mutex bfs_lock;
 };
 
 /*
index 034950cb3cbebde650e4e4544ee0428e765ed2b2..87ee5ccee3489970b86231a3acfa1052862136db 100644 (file)
@@ -32,16 +32,17 @@ static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
        struct inode *dir = f->f_path.dentry->d_inode;
        struct buffer_head *bh;
        struct bfs_dirent *de;
+       struct bfs_sb_info *info = BFS_SB(dir->i_sb);
        unsigned int offset;
        int block;
 
-       lock_kernel();
+       mutex_lock(&info->bfs_lock);
 
        if (f->f_pos & (BFS_DIRENT_SIZE - 1)) {
                printf("Bad f_pos=%08lx for %s:%08lx\n",
                                        (unsigned long)f->f_pos,
                                        dir->i_sb->s_id, dir->i_ino);
-               unlock_kernel();
+               mutex_unlock(&info->bfs_lock);
                return -EBADF;
        }
 
@@ -61,7 +62,7 @@ static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
                                                le16_to_cpu(de->ino),
                                                DT_UNKNOWN) < 0) {
                                        brelse(bh);
-                                       unlock_kernel();
+                                       mutex_unlock(&info->bfs_lock);
                                        return 0;
                                }
                        }
@@ -71,7 +72,7 @@ static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
                brelse(bh);
        }
 
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
        return 0;       
 }
 
@@ -95,10 +96,10 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
        inode = new_inode(s);
        if (!inode)
                return -ENOSPC;
-       lock_kernel();
+       mutex_lock(&info->bfs_lock);
        ino = find_first_zero_bit(info->si_imap, info->si_lasti);
        if (ino > info->si_lasti) {
-               unlock_kernel();
+               mutex_unlock(&info->bfs_lock);
                iput(inode);
                return -ENOSPC;
        }
@@ -125,10 +126,10 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
        if (err) {
                inode_dec_link_count(inode);
                iput(inode);
-               unlock_kernel();
+               mutex_unlock(&info->bfs_lock);
                return err;
        }
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
        d_instantiate(dentry, inode);
        return 0;
 }
@@ -139,22 +140,23 @@ static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
        struct inode *inode = NULL;
        struct buffer_head *bh;
        struct bfs_dirent *de;
+       struct bfs_sb_info *info = BFS_SB(dir->i_sb);
 
        if (dentry->d_name.len > BFS_NAMELEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-       lock_kernel();
+       mutex_lock(&info->bfs_lock);
        bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
        if (bh) {
                unsigned long ino = (unsigned long)le16_to_cpu(de->ino);
                brelse(bh);
                inode = bfs_iget(dir->i_sb, ino);
                if (IS_ERR(inode)) {
-                       unlock_kernel();
+                       mutex_unlock(&info->bfs_lock);
                        return ERR_CAST(inode);
                }
        }
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
        d_add(dentry, inode);
        return NULL;
 }
@@ -163,13 +165,14 @@ static int bfs_link(struct dentry *old, struct inode *dir,
                                                struct dentry *new)
 {
        struct inode *inode = old->d_inode;
+       struct bfs_sb_info *info = BFS_SB(inode->i_sb);
        int err;
 
-       lock_kernel();
+       mutex_lock(&info->bfs_lock);
        err = bfs_add_entry(dir, new->d_name.name, new->d_name.len,
                                                        inode->i_ino);
        if (err) {
-               unlock_kernel();
+               mutex_unlock(&info->bfs_lock);
                return err;
        }
        inc_nlink(inode);
@@ -177,19 +180,19 @@ static int bfs_link(struct dentry *old, struct inode *dir,
        mark_inode_dirty(inode);
        atomic_inc(&inode->i_count);
        d_instantiate(new, inode);
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
        return 0;
 }
 
 static int bfs_unlink(struct inode *dir, struct dentry *dentry)
 {
        int error = -ENOENT;
-       struct inode *inode;
+       struct inode *inode = dentry->d_inode;
        struct buffer_head *bh;
        struct bfs_dirent *de;
+       struct bfs_sb_info *info = BFS_SB(inode->i_sb);
 
-       inode = dentry->d_inode;
-       lock_kernel();
+       mutex_lock(&info->bfs_lock);
        bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
        if (!bh || (le16_to_cpu(de->ino) != inode->i_ino))
                goto out_brelse;
@@ -210,7 +213,7 @@ static int bfs_unlink(struct inode *dir, struct dentry *dentry)
 
 out_brelse:
        brelse(bh);
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
        return error;
 }
 
@@ -220,6 +223,7 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct inode *old_inode, *new_inode;
        struct buffer_head *old_bh, *new_bh;
        struct bfs_dirent *old_de, *new_de;
+       struct bfs_sb_info *info;
        int error = -ENOENT;
 
        old_bh = new_bh = NULL;
@@ -227,7 +231,9 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (S_ISDIR(old_inode->i_mode))
                return -EINVAL;
 
-       lock_kernel();
+       info = BFS_SB(old_inode->i_sb);
+
+       mutex_lock(&info->bfs_lock);
        old_bh = bfs_find_entry(old_dir, 
                                old_dentry->d_name.name, 
                                old_dentry->d_name.len, &old_de);
@@ -264,7 +270,7 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        error = 0;
 
 end_rename:
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
        brelse(old_bh);
        brelse(new_bh);
        return error;
index b11e63e8fbcd88389e4fb2e2a62b41465595dc04..6a021265f018e5e42717c9b7001b47fe69a744e9 100644 (file)
@@ -99,7 +99,7 @@ static int bfs_get_block(struct inode *inode, sector_t block,
                return -ENOSPC;
 
        /* The rest has to be protected against itself. */
-       lock_kernel();
+       mutex_lock(&info->bfs_lock);
 
        /*
         * If the last data block for this file is the last allocated
@@ -151,7 +151,7 @@ static int bfs_get_block(struct inode *inode, sector_t block,
        mark_buffer_dirty(sbh);
        map_bh(bh_result, sb, phys);
 out:
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
        return err;
 }
 
index 8db623838b50c78c819b70ec59e813ac13497277..0ed57b5ee012c362fe298f7b7be24cfd49121e2d 100644 (file)
@@ -104,6 +104,7 @@ static int bfs_write_inode(struct inode *inode, int unused)
        struct bfs_inode *di;
        struct buffer_head *bh;
        int block, off;
+       struct bfs_sb_info *info = BFS_SB(inode->i_sb);
 
         dprintf("ino=%08x\n", ino);
 
@@ -112,13 +113,13 @@ static int bfs_write_inode(struct inode *inode, int unused)
                return -EIO;
        }
 
-       lock_kernel();
+       mutex_lock(&info->bfs_lock);
        block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
        bh = sb_bread(inode->i_sb, block);
        if (!bh) {
                printf("Unable to read inode %s:%08x\n",
                                inode->i_sb->s_id, ino);
-               unlock_kernel();
+               mutex_unlock(&info->bfs_lock);
                return -EIO;
        }
 
@@ -145,7 +146,7 @@ static int bfs_write_inode(struct inode *inode, int unused)
 
        mark_buffer_dirty(bh);
        brelse(bh);
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
        return 0;
 }
 
@@ -170,7 +171,7 @@ static void bfs_delete_inode(struct inode *inode)
        
        inode->i_size = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
-       lock_kernel();
+       mutex_lock(&info->bfs_lock);
        mark_inode_dirty(inode);
 
        block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
@@ -178,7 +179,7 @@ static void bfs_delete_inode(struct inode *inode)
        if (!bh) {
                printf("Unable to read inode %s:%08lx\n",
                                        inode->i_sb->s_id, ino);
-               unlock_kernel();
+               mutex_unlock(&info->bfs_lock);
                return;
        }
        off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
@@ -204,14 +205,16 @@ static void bfs_delete_inode(struct inode *inode)
                info->si_lf_eblk = bi->i_sblock - 1;
                mark_buffer_dirty(info->si_sbh);
        }
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
        clear_inode(inode);
 }
 
 static void bfs_put_super(struct super_block *s)
 {
        struct bfs_sb_info *info = BFS_SB(s);
+
        brelse(info->si_sbh);
+       mutex_destroy(&info->bfs_lock);
        kfree(info->si_imap);
        kfree(info);
        s->s_fs_info = NULL;
@@ -236,11 +239,13 @@ static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 
 static void bfs_write_super(struct super_block *s)
 {
-       lock_kernel();
+       struct bfs_sb_info *info = BFS_SB(s);
+
+       mutex_lock(&info->bfs_lock);
        if (!(s->s_flags & MS_RDONLY))
-               mark_buffer_dirty(BFS_SB(s)->si_sbh);
+               mark_buffer_dirty(info->si_sbh);
        s->s_dirt = 0;
-       unlock_kernel();
+       mutex_unlock(&info->bfs_lock);
 }
 
 static struct kmem_cache *bfs_inode_cachep;
@@ -259,7 +264,7 @@ static void bfs_destroy_inode(struct inode *inode)
        kmem_cache_free(bfs_inode_cachep, BFS_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct bfs_inode_info *bi = foo;
 
@@ -380,7 +385,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
                struct bfs_inode *di;
                int block = (i - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
                int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
-               unsigned long sblock, eblock;
+               unsigned long eblock;
 
                if (!off) {
                        brelse(bh);
@@ -399,7 +404,6 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
                set_bit(i, info->si_imap);
                info->si_freeb -= BFS_FILEBLOCKS(di);
 
-               sblock =  le32_to_cpu(di->i_sblock);
                eblock =  le32_to_cpu(di->i_eblock);
                if (eblock > info->si_lf_eblk)
                        info->si_lf_eblk = eblock;
@@ -410,6 +414,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
                s->s_dirt = 1;
        } 
        dump_imap("read_super", s);
+       mutex_init(&info->bfs_lock);
        return 0;
 
 out:
index ba4cddb92f1ddf02330760e7b7614d7b261a5a64..204cfd1d76762e22cf2e62bd447fb6c7fd7da0d9 100644 (file)
@@ -444,12 +444,6 @@ beyond_if:
        regs->gp = ex.a_gpvalue;
 #endif
        start_thread(regs, ex.a_entry, current->mm->start_stack);
-       if (unlikely(current->ptrace & PT_PTRACED)) {
-               if (current->ptrace & PT_TRACE_EXEC)
-                       ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
-               else
-                       send_sig(SIGTRAP, current, 0);
-       }
        return 0;
 }
 
index 639d2d8b57106ac6e524c4ab7c940ea2fad895da..655ed8d30a86ef7e963414a9cb56d6ed7dc5d3c4 100644 (file)
@@ -131,6 +131,15 @@ static int padzero(unsigned long elf_bss)
 #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; })
 #endif
 
+#ifndef ELF_BASE_PLATFORM
+/*
+ * AT_BASE_PLATFORM indicates the "real" hardware/microarchitecture.
+ * If the arch defines ELF_BASE_PLATFORM (in asm/elf.h), the value
+ * will be copied to the user stack in the same manner as AT_PLATFORM.
+ */
+#define ELF_BASE_PLATFORM NULL
+#endif
+
 static int
 create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
                unsigned long load_addr, unsigned long interp_load_addr)
@@ -142,7 +151,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
        elf_addr_t __user *envp;
        elf_addr_t __user *sp;
        elf_addr_t __user *u_platform;
+       elf_addr_t __user *u_base_platform;
        const char *k_platform = ELF_PLATFORM;
+       const char *k_base_platform = ELF_BASE_PLATFORM;
        int items;
        elf_addr_t *elf_info;
        int ei_index = 0;
@@ -172,6 +183,19 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
                        return -EFAULT;
        }
 
+       /*
+        * If this architecture has a "base" platform capability
+        * string, copy it to userspace.
+        */
+       u_base_platform = NULL;
+       if (k_base_platform) {
+               size_t len = strlen(k_base_platform) + 1;
+
+               u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
+               if (__copy_to_user(u_base_platform, k_base_platform, len))
+                       return -EFAULT;
+       }
+
        /* Create the ELF interpreter info */
        elf_info = (elf_addr_t *)current->mm->saved_auxv;
        /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */
@@ -209,6 +233,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
                NEW_AUX_ENT(AT_PLATFORM,
                            (elf_addr_t)(unsigned long)u_platform);
        }
+       if (k_base_platform) {
+               NEW_AUX_ENT(AT_BASE_PLATFORM,
+                           (elf_addr_t)(unsigned long)u_base_platform);
+       }
        if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
                NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
        }
@@ -975,12 +1003,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 #endif
 
        start_thread(regs, elf_entry, bprm->p);
-       if (unlikely(current->ptrace & PT_PTRACED)) {
-               if (current->ptrace & PT_TRACE_EXEC)
-                       ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
-               else
-                       send_sig(SIGTRAP, current, 0);
-       }
        retval = 0;
 out:
        kfree(loc);
@@ -1478,7 +1500,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
        const struct user_regset_view *view = task_user_regset_view(dump_task);
        struct elf_thread_core_info *t;
        struct elf_prpsinfo *psinfo;
-       struct task_struct *g, *p;
+       struct core_thread *ct;
        unsigned int i;
 
        info->size = 0;
@@ -1517,31 +1539,26 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
        /*
         * Allocate a structure for each thread.
         */
-       rcu_read_lock();
-       do_each_thread(g, p)
-               if (p->mm == dump_task->mm) {
-                       t = kzalloc(offsetof(struct elf_thread_core_info,
-                                            notes[info->thread_notes]),
-                                   GFP_ATOMIC);
-                       if (unlikely(!t)) {
-                               rcu_read_unlock();
-                               return 0;
-                       }
-                       t->task = p;
-                       if (p == dump_task || !info->thread) {
-                               t->next = info->thread;
-                               info->thread = t;
-                       } else {
-                               /*
-                                * Make sure to keep the original task at
-                                * the head of the list.
-                                */
-                               t->next = info->thread->next;
-                               info->thread->next = t;
-                       }
+       for (ct = &dump_task->mm->core_state->dumper; ct; ct = ct->next) {
+               t = kzalloc(offsetof(struct elf_thread_core_info,
+                                    notes[info->thread_notes]),
+                           GFP_KERNEL);
+               if (unlikely(!t))
+                       return 0;
+
+               t->task = ct->task;
+               if (ct->task == dump_task || !info->thread) {
+                       t->next = info->thread;
+                       info->thread = t;
+               } else {
+                       /*
+                        * Make sure to keep the original task at
+                        * the head of the list.
+                        */
+                       t->next = info->thread->next;
+                       info->thread->next = t;
                }
-       while_each_thread(g, p);
-       rcu_read_unlock();
+       }
 
        /*
         * Now fill in each thread's information.
@@ -1688,7 +1705,6 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
 {
 #define        NUM_NOTES       6
        struct list_head *t;
-       struct task_struct *g, *p;
 
        info->notes = NULL;
        info->prstatus = NULL;
@@ -1720,20 +1736,19 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
 
        info->thread_status_size = 0;
        if (signr) {
+               struct core_thread *ct;
                struct elf_thread_status *ets;
-               rcu_read_lock();
-               do_each_thread(g, p)
-                       if (current->mm == p->mm && current != p) {
-                               ets = kzalloc(sizeof(*ets), GFP_ATOMIC);
-                               if (!ets) {
-                                       rcu_read_unlock();
-                                       return 0;
-                               }
-                               ets->thread = p;
-                               list_add(&ets->list, &info->thread_list);
-                       }
-               while_each_thread(g, p);
-               rcu_read_unlock();
+
+               for (ct = current->mm->core_state->dumper.next;
+                                               ct; ct = ct->next) {
+                       ets = kzalloc(sizeof(*ets), GFP_KERNEL);
+                       if (!ets)
+                               return 0;
+
+                       ets->thread = ct->task;
+                       list_add(&ets->list, &info->thread_list);
+               }
+
                list_for_each(t, &info->thread_list) {
                        int sz;
 
index d051a32e6270ec31975da904476e1cefbaa9be1f..80c1f952ef7814fc36b099457c6ab11c670c1884 100644 (file)
@@ -433,13 +433,6 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
        entryaddr = interp_params.entry_addr ?: exec_params.entry_addr;
        start_thread(regs, entryaddr, current->mm->start_stack);
 
-       if (unlikely(current->ptrace & PT_PTRACED)) {
-               if (current->ptrace & PT_TRACE_EXEC)
-                       ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
-               else
-                       send_sig(SIGTRAP, current, 0);
-       }
-
        retval = 0;
 
 error:
@@ -477,6 +470,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
        char __user *u_platform, *p;
        long hwcap;
        int loop;
+       int nr; /* reset for each csp adjustment */
 
        /* we're going to shovel a whole load of stuff onto the stack */
 #ifdef CONFIG_MMU
@@ -549,10 +543,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
        /* force 16 byte _final_ alignment here for generality */
 #define DLINFO_ITEMS 13
 
-       nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0);
-#ifdef DLINFO_ARCH_ITEMS
-       nitems += DLINFO_ARCH_ITEMS;
-#endif
+       nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0) + AT_VECTOR_SIZE_ARCH;
 
        csp = sp;
        sp -= nitems * 2 * sizeof(unsigned long);
@@ -564,39 +555,46 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
        sp -= sp & 15UL;
 
        /* put the ELF interpreter info on the stack */
-#define NEW_AUX_ENT(nr, id, val)                                       \
+#define NEW_AUX_ENT(id, val)                                           \
        do {                                                            \
                struct { unsigned long _id, _val; } __user *ent;        \
                                                                        \
                ent = (void __user *) csp;                              \
                __put_user((id), &ent[nr]._id);                         \
                __put_user((val), &ent[nr]._val);                       \
+               nr++;                                                   \
        } while (0)
 
+       nr = 0;
        csp -= 2 * sizeof(unsigned long);
-       NEW_AUX_ENT(0, AT_NULL, 0);
+       NEW_AUX_ENT(AT_NULL, 0);
        if (k_platform) {
+               nr = 0;
                csp -= 2 * sizeof(unsigned long);
-               NEW_AUX_ENT(0, AT_PLATFORM,
+               NEW_AUX_ENT(AT_PLATFORM,
                            (elf_addr_t) (unsigned long) u_platform);
        }
 
+       nr = 0;
        csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
-       NEW_AUX_ENT( 0, AT_HWCAP,       hwcap);
-       NEW_AUX_ENT( 1, AT_PAGESZ,      PAGE_SIZE);
-       NEW_AUX_ENT( 2, AT_CLKTCK,      CLOCKS_PER_SEC);
-       NEW_AUX_ENT( 3, AT_PHDR,        exec_params->ph_addr);
-       NEW_AUX_ENT( 4, AT_PHENT,       sizeof(struct elf_phdr));
-       NEW_AUX_ENT( 5, AT_PHNUM,       exec_params->hdr.e_phnum);
-       NEW_AUX_ENT( 6, AT_BASE,        interp_params->elfhdr_addr);
-       NEW_AUX_ENT( 7, AT_FLAGS,       0);
-       NEW_AUX_ENT( 8, AT_ENTRY,       exec_params->entry_addr);
-       NEW_AUX_ENT( 9, AT_UID,         (elf_addr_t) current->uid);
-       NEW_AUX_ENT(10, AT_EUID,        (elf_addr_t) current->euid);
-       NEW_AUX_ENT(11, AT_GID,         (elf_addr_t) current->gid);
-       NEW_AUX_ENT(12, AT_EGID,        (elf_addr_t) current->egid);
+       NEW_AUX_ENT(AT_HWCAP,   hwcap);
+       NEW_AUX_ENT(AT_PAGESZ,  PAGE_SIZE);
+       NEW_AUX_ENT(AT_CLKTCK,  CLOCKS_PER_SEC);
+       NEW_AUX_ENT(AT_PHDR,    exec_params->ph_addr);
+       NEW_AUX_ENT(AT_PHENT,   sizeof(struct elf_phdr));
+       NEW_AUX_ENT(AT_PHNUM,   exec_params->hdr.e_phnum);
+       NEW_AUX_ENT(AT_BASE,    interp_params->elfhdr_addr);
+       NEW_AUX_ENT(AT_FLAGS,   0);
+       NEW_AUX_ENT(AT_ENTRY,   exec_params->entry_addr);
+       NEW_AUX_ENT(AT_UID,     (elf_addr_t) current->uid);
+       NEW_AUX_ENT(AT_EUID,    (elf_addr_t) current->euid);
+       NEW_AUX_ENT(AT_GID,     (elf_addr_t) current->gid);
+       NEW_AUX_ENT(AT_EGID,    (elf_addr_t) current->egid);
 
 #ifdef ARCH_DLINFO
+       nr = 0;
+       csp -= AT_VECTOR_SIZE_ARCH * 2 * sizeof(unsigned long);
+
        /* ARCH_DLINFO must come last so platform specific code can enforce
         * special alignment requirements on the AUXV if necessary (eg. PPC).
         */
@@ -1573,7 +1571,6 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
        struct memelfnote *notes = NULL;
        struct elf_prstatus *prstatus = NULL;   /* NT_PRSTATUS */
        struct elf_prpsinfo *psinfo = NULL;     /* NT_PRPSINFO */
-       struct task_struct *g, *p;
        LIST_HEAD(thread_list);
        struct list_head *t;
        elf_fpregset_t *fpu = NULL;
@@ -1622,20 +1619,19 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
 #endif
 
        if (signr) {
+               struct core_thread *ct;
                struct elf_thread_status *tmp;
-               rcu_read_lock();
-               do_each_thread(g,p)
-                       if (current->mm == p->mm && current != p) {
-                               tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
-                               if (!tmp) {
-                                       rcu_read_unlock();
-                                       goto cleanup;
-                               }
-                               tmp->thread = p;
-                               list_add(&tmp->list, &thread_list);
-                       }
-               while_each_thread(g,p);
-               rcu_read_unlock();
+
+               for (ct = current->mm->core_state->dumper.next;
+                                               ct; ct = ct->next) {
+                       tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+                       if (!tmp)
+                               goto cleanup;
+
+                       tmp->thread = ct->task;
+                       list_add(&tmp->list, &thread_list);
+               }
+
                list_for_each(t, &thread_list) {
                        struct elf_thread_status *tmp;
                        int sz;
index 2cb1acda3a82f70a9f809e880d499999e39edd9d..56372ecf16909d8dd7c2e37062c044d2aa147c23 100644 (file)
@@ -920,9 +920,6 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        
        start_thread(regs, start_addr, current->mm->start_stack);
 
-       if (current->ptrace & PT_PTRACED)
-               send_sig(SIGTRAP, current, 0);
-
        return 0;
 }
 
index 7191306367c5d11912ceed01c5fce4925b528eba..756205314c24401fc31ebbb6eb7c479aa4c92145 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/syscalls.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 
@@ -535,31 +536,16 @@ static ssize_t
 bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
 {
        Node *e = file->f_path.dentry->d_inode->i_private;
-       loff_t pos = *ppos;
        ssize_t res;
        char *page;
-       int len;
 
        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
                return -ENOMEM;
 
        entry_status(e, page);
-       len = strlen(page);
 
-       res = -EINVAL;
-       if (pos < 0)
-               goto out;
-       res = 0;
-       if (pos >= len)
-               goto out;
-       if (len < pos + nbytes)
-               nbytes = len - pos;
-       res = -EFAULT;
-       if (copy_to_user(buf, page + pos, nbytes))
-               goto out;
-       *ppos = pos + nbytes;
-       res = nbytes;
-out:
+       res = simple_read_from_buffer(buf, nbytes, ppos, page, strlen(page));
+
        free_page((unsigned long) page);
        return res;
 }
index fdc36bfd6a7beb8d1b63b91520ece0a7d2a347b7..68be580ba289fc3135a0dcd93595ce5b66062206 100644 (file)
@@ -274,8 +274,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        map_hpux_gateway_page(current,current->mm);
 
        start_thread_som(regs, som_entry, bprm->p);
-       if (current->ptrace & PT_PTRACED)
-               send_sig(SIGTRAP, current, 0);
        return 0;
 
        /* error cleanup */
index 63e2ee63058de4edb3e5d5036ade3b9a79e92ffa..c3e174b35fe6a179baac8ef098b465f0ab51f515 100644 (file)
@@ -705,7 +705,6 @@ void __init bio_integrity_init_slab(void)
        bio_integrity_slab = KMEM_CACHE(bio_integrity_payload,
                                        SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 }
-EXPORT_SYMBOL(bio_integrity_init_slab);
 
 static int __init integrity_init(void)
 {
index 88322b066acb68f8279e79eeca5842c6b02bd8ce..25f1af0d81e5bee47ee8487b27ca8e0152b6d156 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -721,12 +721,8 @@ static struct bio *__bio_map_user_iov(struct request_queue *q,
                const int local_nr_pages = end - start;
                const int page_limit = cur_page + local_nr_pages;
                
-               down_read(&current->mm->mmap_sem);
-               ret = get_user_pages(current, current->mm, uaddr,
-                                    local_nr_pages,
-                                    write_to_vm, 0, &pages[cur_page], NULL);
-               up_read(&current->mm->mmap_sem);
-
+               ret = get_user_pages_fast(uaddr, local_nr_pages,
+                               write_to_vm, &pages[cur_page]);
                if (ret < local_nr_pages) {
                        ret = -EFAULT;
                        goto out_unmap;
index 10d8a0aa871a096eb3d8577b01d285aa9c1fa433..dcf37cada3697d898c2d0c70c875450826845440 100644 (file)
@@ -271,7 +271,7 @@ static void bdev_destroy_inode(struct inode *inode)
        kmem_cache_free(bdev_cachep, bdi);
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct bdev_inode *ei = (struct bdev_inode *) foo;
        struct block_device *bdev = &ei->bdev;
index d48caee12e2a4adaae056451f7dcef71205ccfa5..ca12a6bb82b10f6a45da86f3019f1e7d692dfc61 100644 (file)
@@ -706,7 +706,7 @@ static int __set_page_dirty(struct page *page,
        if (TestSetPageDirty(page))
                return 0;
 
-       write_lock_irq(&mapping->tree_lock);
+       spin_lock_irq(&mapping->tree_lock);
        if (page->mapping) {    /* Race with truncate? */
                WARN_ON_ONCE(warn && !PageUptodate(page));
 
@@ -719,7 +719,7 @@ static int __set_page_dirty(struct page *page,
                radix_tree_tag_set(&mapping->page_tree,
                                page_index(page), PAGECACHE_TAG_DIRTY);
        }
-       write_unlock_irq(&mapping->tree_lock);
+       spin_unlock_irq(&mapping->tree_lock);
        __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
 
        return 1;
@@ -1214,8 +1214,7 @@ void __brelse(struct buffer_head * buf)
                put_bh(buf);
                return;
        }
-       printk(KERN_ERR "VFS: brelse: Trying to free free buffer\n");
-       WARN_ON(1);
+       WARN(1, KERN_ERR "VFS: brelse: Trying to free free buffer\n");
 }
 
 /*
@@ -2096,6 +2095,52 @@ int generic_write_end(struct file *file, struct address_space *mapping,
 }
 EXPORT_SYMBOL(generic_write_end);
 
+/*
+ * block_is_partially_uptodate checks whether buffers within a page are
+ * uptodate or not.
+ *
+ * Returns true if all buffers which correspond to a file portion
+ * we want to read are uptodate.
+ */
+int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
+                                       unsigned long from)
+{
+       struct inode *inode = page->mapping->host;
+       unsigned block_start, block_end, blocksize;
+       unsigned to;
+       struct buffer_head *bh, *head;
+       int ret = 1;
+
+       if (!page_has_buffers(page))
+               return 0;
+
+       blocksize = 1 << inode->i_blkbits;
+       to = min_t(unsigned, PAGE_CACHE_SIZE - from, desc->count);
+       to = from + to;
+       if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize)
+               return 0;
+
+       head = page_buffers(page);
+       bh = head;
+       block_start = 0;
+       do {
+               block_end = block_start + blocksize;
+               if (block_end > from && block_start < to) {
+                       if (!buffer_uptodate(bh)) {
+                               ret = 0;
+                               break;
+                       }
+                       if (block_end >= to)
+                               break;
+               }
+               block_start = block_end;
+               bh = bh->b_this_page;
+       } while (bh != head);
+
+       return ret;
+}
+EXPORT_SYMBOL(block_is_partially_uptodate);
+
 /*
  * Generic "read page" function for block devices that have the normal
  * get_block functionality. This is most of the block device filesystems.
@@ -3272,7 +3317,7 @@ int bh_submit_read(struct buffer_head *bh)
 EXPORT_SYMBOL(bh_submit_read);
 
 static void
-init_buffer_head(struct kmem_cache *cachep, void *data)
+init_buffer_head(void *data)
 {
        struct buffer_head *bh = data;
 
index f58e41d3ba485d97bbf57726e7087d5ec6db1d63..6bb440b257b01337e21434d9ef2b8e3d0f5aeb1d 100644 (file)
@@ -400,7 +400,7 @@ asn1_oid_decode(struct asn1_ctx *ctx,
        size = eoc - ctx->pointer + 1;
 
        /* first subid actually encodes first two subids */
-       if (size < 2 || size > ULONG_MAX/sizeof(unsigned long))
+       if (size < 2 || size > UINT_MAX/sizeof(unsigned long))
                return 0;
 
        *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
@@ -494,7 +494,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                /*      remember to free obj->oid */
                rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
                if (rc) {
-                       if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
+                       if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
                                rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
                                if (rc) {
                                        rc = compare_oid(oid, oidlen,
index cc950f69e51ea5b2e5a13135258151e4560c9b2f..688a2d42153f53417efd8938a229ffbd9fcf2a92 100644 (file)
@@ -107,9 +107,7 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
 #endif /* CONFIG_CIFS_DEBUG2 */
 
 #ifdef CONFIG_PROC_FS
-static int
-cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
-                    int count, int *eof, void *data)
+static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
 {
        struct list_head *tmp;
        struct list_head *tmp1;
@@ -117,23 +115,13 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
        struct cifsSesInfo *ses;
        struct cifsTconInfo *tcon;
        int i;
-       int length = 0;
-       char *original_buf = buf;
 
-       *beginBuffer = buf + offset;
-
-       length =
-           sprintf(buf,
+       seq_puts(m,
                    "Display Internal CIFS Data Structures for Debugging\n"
                    "---------------------------------------------------\n");
-       buf += length;
-       length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION);
-       buf += length;
-       length = sprintf(buf,
-               "Active VFS Requests: %d\n", GlobalTotalActiveXid);
-       buf += length;
-       length = sprintf(buf, "Servers:");
-       buf += length;
+       seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
+       seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
+       seq_printf(m, "Servers:");
 
        i = 0;
        read_lock(&GlobalSMBSeslock);
@@ -142,11 +130,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
                ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
                if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
                   (ses->serverNOS == NULL)) {
-                       buf += sprintf(buf, "\nentry for %s not fully "
+                       seq_printf(m, "\nentry for %s not fully "
                                        "displayed\n\t", ses->serverName);
                } else {
-                       length =
-                           sprintf(buf,
+                       seq_printf(m,
                                    "\n%d) Name: %s  Domain: %s Mounts: %d OS:"
                                    " %s  \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
                                    " session status: %d\t",
@@ -154,10 +141,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
                                atomic_read(&ses->inUse),
                                ses->serverOS, ses->serverNOS,
                                ses->capabilities, ses->status);
-                       buf += length;
                }
                if (ses->server) {
-                       buf += sprintf(buf, "TCP status: %d\n\tLocal Users To "
+                       seq_printf(m, "TCP status: %d\n\tLocal Users To "
                                    "Server: %d SecMode: 0x%x Req On Wire: %d",
                                ses->server->tcpStatus,
                                atomic_read(&ses->server->socketUseCount),
@@ -165,13 +151,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
                                atomic_read(&ses->server->inFlight));
 
 #ifdef CONFIG_CIFS_STATS2
-                       buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
+                       seq_printf(m, " In Send: %d In MaxReq Wait: %d",
                                atomic_read(&ses->server->inSend),
                                atomic_read(&ses->server->num_waiters));
 #endif
 
-                       length = sprintf(buf, "\nMIDs:\n");
-                       buf += length;
+                       seq_puts(m, "\nMIDs:\n");
 
                        spin_lock(&GlobalMid_Lock);
                        list_for_each(tmp1, &ses->server->pending_mid_q) {
@@ -179,7 +164,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
                                        mid_q_entry,
                                        qhead);
                                if (mid_entry) {
-                                       length = sprintf(buf,
+                                       seq_printf(m,
                                                        "State: %d com: %d pid:"
                                                        " %d tsk: %p mid %d\n",
                                                        mid_entry->midState,
@@ -187,7 +172,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
                                                        mid_entry->pid,
                                                        mid_entry->tsk,
                                                        mid_entry->mid);
-                                       buf += length;
                                }
                        }
                        spin_unlock(&GlobalMid_Lock);
@@ -195,11 +179,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
 
        }
        read_unlock(&GlobalSMBSeslock);
-       sprintf(buf, "\n");
-       buf++;
+       seq_putc(m, '\n');
 
-       length = sprintf(buf, "Shares:");
-       buf += length;
+       seq_puts(m, "Shares:");
 
        i = 0;
        read_lock(&GlobalSMBSeslock);
@@ -208,62 +190,52 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
                i++;
                tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
                dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
-               length = sprintf(buf, "\n%d) %s Uses: %d ", i,
+               seq_printf(m, "\n%d) %s Uses: %d ", i,
                                 tcon->treeName, atomic_read(&tcon->useCount));
-               buf += length;
                if (tcon->nativeFileSystem) {
-                       length = sprintf(buf, "Type: %s ",
+                       seq_printf(m, "Type: %s ",
                                         tcon->nativeFileSystem);
-                       buf += length;
                }
-               length = sprintf(buf, "DevInfo: 0x%x Attributes: 0x%x"
+               seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
                                 "\nPathComponentMax: %d Status: %d",
                            le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
                            le32_to_cpu(tcon->fsAttrInfo.Attributes),
                            le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
                            tcon->tidStatus);
-               buf += length;
                if (dev_type == FILE_DEVICE_DISK)
-                       length = sprintf(buf, " type: DISK ");
+                       seq_puts(m, " type: DISK ");
                else if (dev_type == FILE_DEVICE_CD_ROM)
-                       length = sprintf(buf, " type: CDROM ");
+                       seq_puts(m, " type: CDROM ");
                else
-                       length =
-                           sprintf(buf, " type: %d ", dev_type);
-               buf += length;
-               if (tcon->tidStatus == CifsNeedReconnect) {
-                       buf += sprintf(buf, "\tDISCONNECTED ");
-                       length += 14;
-               }
+                       seq_printf(m, " type: %d ", dev_type);
+
+               if (tcon->tidStatus == CifsNeedReconnect)
+                       seq_puts(m, "\tDISCONNECTED ");
        }
        read_unlock(&GlobalSMBSeslock);
 
-       length = sprintf(buf, "\n");
-       buf += length;
+       seq_putc(m, '\n');
 
        /* BB add code to dump additional info such as TCP session info now */
-       /* Now calculate total size of returned data */
-       length = buf - original_buf;
-
-       if (offset + count >= length)
-               *eof = 1;
-       if (length < offset) {
-               *eof = 1;
-               return 0;
-       } else {
-               length = length - offset;
-       }
-       if (length > count)
-               length = count;
+       return 0;
+}
 
-       return length;
+static int cifs_debug_data_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cifs_debug_data_proc_show, NULL);
 }
 
-#ifdef CONFIG_CIFS_STATS
+static const struct file_operations cifs_debug_data_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cifs_debug_data_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 
-static int
-cifs_stats_write(struct file *file, const char __user *buffer,
-                unsigned long count, void *data)
+#ifdef CONFIG_CIFS_STATS
+static ssize_t cifs_stats_proc_write(struct file *file,
+               const char __user *buffer, size_t count, loff_t *ppos)
 {
        char c;
        int rc;
@@ -307,236 +279,132 @@ cifs_stats_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static int
-cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
-                 int count, int *eof, void *data)
+static int cifs_stats_proc_show(struct seq_file *m, void *v)
 {
-       int item_length, i, length;
+       int i;
        struct list_head *tmp;
        struct cifsTconInfo *tcon;
 
-       *beginBuffer = buf + offset;
-
-       length = sprintf(buf,
+       seq_printf(m,
                        "Resources in use\nCIFS Session: %d\n",
                        sesInfoAllocCount.counter);
-       buf += length;
-       item_length =
-               sprintf(buf, "Share (unique mount targets): %d\n",
+       seq_printf(m, "Share (unique mount targets): %d\n",
                        tconInfoAllocCount.counter);
-       length += item_length;
-       buf += item_length;
-       item_length =
-               sprintf(buf, "SMB Request/Response Buffer: %d Pool size: %d\n",
+       seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n",
                        bufAllocCount.counter,
                        cifs_min_rcv + tcpSesAllocCount.counter);
-       length += item_length;
-       buf += item_length;
-       item_length =
-               sprintf(buf, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
+       seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
                        smBufAllocCount.counter, cifs_min_small);
-       length += item_length;
-       buf += item_length;
 #ifdef CONFIG_CIFS_STATS2
-       item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
+       seq_printf(m, "Total Large %d Small %d Allocations\n",
                                atomic_read(&totBufAllocCount),
                                atomic_read(&totSmBufAllocCount));
-       length += item_length;
-       buf += item_length;
 #endif /* CONFIG_CIFS_STATS2 */
 
-       item_length =
-               sprintf(buf, "Operations (MIDs): %d\n",
-                       midCount.counter);
-       length += item_length;
-       buf += item_length;
-       item_length = sprintf(buf,
+       seq_printf(m, "Operations (MIDs): %d\n", midCount.counter);
+       seq_printf(m,
                "\n%d session %d share reconnects\n",
                tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
-       length += item_length;
-       buf += item_length;
 
-       item_length = sprintf(buf,
+       seq_printf(m,
                "Total vfs operations: %d maximum at one time: %d\n",
                GlobalCurrentXid, GlobalMaxActiveXid);
-       length += item_length;
-       buf += item_length;
 
        i = 0;
        read_lock(&GlobalSMBSeslock);
        list_for_each(tmp, &GlobalTreeConnectionList) {
                i++;
                tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
-               item_length = sprintf(buf, "\n%d) %s", i, tcon->treeName);
-               buf += item_length;
-               length += item_length;
-               if (tcon->tidStatus == CifsNeedReconnect) {
-                       buf += sprintf(buf, "\tDISCONNECTED ");
-                       length += 14;
-               }
-               item_length = sprintf(buf, "\nSMBs: %d Oplock Breaks: %d",
+               seq_printf(m, "\n%d) %s", i, tcon->treeName);
+               if (tcon->tidStatus == CifsNeedReconnect)
+                       seq_puts(m, "\tDISCONNECTED ");
+               seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
                        atomic_read(&tcon->num_smbs_sent),
                        atomic_read(&tcon->num_oplock_brks));
-               buf += item_length;
-               length += item_length;
-               item_length = sprintf(buf, "\nReads:  %d Bytes: %lld",
+               seq_printf(m, "\nReads:  %d Bytes: %lld",
                        atomic_read(&tcon->num_reads),
                        (long long)(tcon->bytes_read));
-               buf += item_length;
-               length += item_length;
-               item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
+               seq_printf(m, "\nWrites: %d Bytes: %lld",
                        atomic_read(&tcon->num_writes),
                        (long long)(tcon->bytes_written));
-               buf += item_length;
-               length += item_length;
-               item_length = sprintf(buf,
+               seq_printf(m,
                        "\nLocks: %d HardLinks: %d Symlinks: %d",
                        atomic_read(&tcon->num_locks),
                        atomic_read(&tcon->num_hardlinks),
                        atomic_read(&tcon->num_symlinks));
-               buf += item_length;
-               length += item_length;
 
-               item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
+               seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d",
                        atomic_read(&tcon->num_opens),
                        atomic_read(&tcon->num_closes),
                        atomic_read(&tcon->num_deletes));
-               buf += item_length;
-               length += item_length;
-               item_length = sprintf(buf, "\nMkdirs: %d Rmdirs: %d",
+               seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
                        atomic_read(&tcon->num_mkdirs),
                        atomic_read(&tcon->num_rmdirs));
-               buf += item_length;
-               length += item_length;
-               item_length = sprintf(buf, "\nRenames: %d T2 Renames %d",
+               seq_printf(m, "\nRenames: %d T2 Renames %d",
                        atomic_read(&tcon->num_renames),
                        atomic_read(&tcon->num_t2renames));
-               buf += item_length;
-               length += item_length;
-               item_length = sprintf(buf, "\nFindFirst: %d FNext %d FClose %d",
+               seq_printf(m, "\nFindFirst: %d FNext %d FClose %d",
                        atomic_read(&tcon->num_ffirst),
                        atomic_read(&tcon->num_fnext),
                        atomic_read(&tcon->num_fclose));
-               buf += item_length;
-               length += item_length;
        }
        read_unlock(&GlobalSMBSeslock);
 
-       buf += sprintf(buf, "\n");
-       length++;
-
-       if (offset + count >= length)
-               *eof = 1;
-       if (length < offset) {
-               *eof = 1;
-               return 0;
-       } else {
-               length = length - offset;
-       }
-       if (length > count)
-               length = count;
+       seq_putc(m, '\n');
+       return 0;
+}
 
-       return length;
+static int cifs_stats_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cifs_stats_proc_show, NULL);
 }
+
+static const struct file_operations cifs_stats_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cifs_stats_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = cifs_stats_proc_write,
+};
 #endif /* STATS */
 
 static struct proc_dir_entry *proc_fs_cifs;
-read_proc_t cifs_txanchor_read;
-static read_proc_t cifsFYI_read;
-static write_proc_t cifsFYI_write;
-static read_proc_t oplockEnabled_read;
-static write_proc_t oplockEnabled_write;
-static read_proc_t lookupFlag_read;
-static write_proc_t lookupFlag_write;
-static read_proc_t traceSMB_read;
-static write_proc_t traceSMB_write;
-static read_proc_t multiuser_mount_read;
-static write_proc_t multiuser_mount_write;
-static read_proc_t security_flags_read;
-static write_proc_t security_flags_write;
-/* static read_proc_t ntlmv2_enabled_read;
-static write_proc_t ntlmv2_enabled_write;
-static read_proc_t packet_signing_enabled_read;
-static write_proc_t packet_signing_enabled_write;*/
-static read_proc_t experimEnabled_read;
-static write_proc_t experimEnabled_write;
-static read_proc_t linuxExtensionsEnabled_read;
-static write_proc_t linuxExtensionsEnabled_write;
+static const struct file_operations cifsFYI_proc_fops;
+static const struct file_operations cifs_oplock_proc_fops;
+static const struct file_operations cifs_lookup_cache_proc_fops;
+static const struct file_operations traceSMB_proc_fops;
+static const struct file_operations cifs_multiuser_mount_proc_fops;
+static const struct file_operations cifs_security_flags_proc_fops;
+static const struct file_operations cifs_experimental_proc_fops;
+static const struct file_operations cifs_linux_ext_proc_fops;
 
 void
 cifs_proc_init(void)
 {
-       struct proc_dir_entry *pde;
-
        proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
        if (proc_fs_cifs == NULL)
                return;
 
        proc_fs_cifs->owner = THIS_MODULE;
-       create_proc_read_entry("DebugData", 0, proc_fs_cifs,
-                               cifs_debug_data_read, NULL);
+       proc_create("DebugData", 0, proc_fs_cifs, &cifs_debug_data_proc_fops);
 
 #ifdef CONFIG_CIFS_STATS
-       pde = create_proc_read_entry("Stats", 0, proc_fs_cifs,
-                               cifs_stats_read, NULL);
-       if (pde)
-               pde->write_proc = cifs_stats_write;
+       proc_create("Stats", 0, proc_fs_cifs, &cifs_stats_proc_fops);
 #endif /* STATS */
-       pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
-                               cifsFYI_read, NULL);
-       if (pde)
-               pde->write_proc = cifsFYI_write;
-
-       pde =
-           create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
-                               traceSMB_read, NULL);
-       if (pde)
-               pde->write_proc = traceSMB_write;
-
-       pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
-                               oplockEnabled_read, NULL);
-       if (pde)
-               pde->write_proc = oplockEnabled_write;
-
-       pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
-                               experimEnabled_read, NULL);
-       if (pde)
-               pde->write_proc = experimEnabled_write;
-
-       pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
-                               linuxExtensionsEnabled_read, NULL);
-       if (pde)
-               pde->write_proc = linuxExtensionsEnabled_write;
-
-       pde =
-           create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
-                               multiuser_mount_read, NULL);
-       if (pde)
-               pde->write_proc = multiuser_mount_write;
-
-       pde =
-           create_proc_read_entry("SecurityFlags", 0, proc_fs_cifs,
-                               security_flags_read, NULL);
-       if (pde)
-               pde->write_proc = security_flags_write;
-
-       pde =
-       create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
-                               lookupFlag_read, NULL);
-       if (pde)
-               pde->write_proc = lookupFlag_write;
-
-/*     pde =
-           create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
-                               ntlmv2_enabled_read, NULL);
-       if (pde)
-               pde->write_proc = ntlmv2_enabled_write;
-
-       pde =
-           create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
-                               packet_signing_enabled_read, NULL);
-       if (pde)
-               pde->write_proc = packet_signing_enabled_write;*/
+       proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops);
+       proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops);
+       proc_create("OplockEnabled", 0, proc_fs_cifs, &cifs_oplock_proc_fops);
+       proc_create("Experimental", 0, proc_fs_cifs,
+                   &cifs_experimental_proc_fops);
+       proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs,
+                   &cifs_linux_ext_proc_fops);
+       proc_create("MultiuserMount", 0, proc_fs_cifs,
+                   &cifs_multiuser_mount_proc_fops);
+       proc_create("SecurityFlags", 0, proc_fs_cifs,
+                   &cifs_security_flags_proc_fops);
+       proc_create("LookupCacheEnabled", 0, proc_fs_cifs,
+                   &cifs_lookup_cache_proc_fops);
 }
 
 void
@@ -553,39 +421,26 @@ cifs_proc_clean(void)
 #endif
        remove_proc_entry("MultiuserMount", proc_fs_cifs);
        remove_proc_entry("OplockEnabled", proc_fs_cifs);
-/*     remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
        remove_proc_entry("SecurityFlags", proc_fs_cifs);
-/*     remove_proc_entry("PacketSigningEnabled", proc_fs_cifs); */
        remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
        remove_proc_entry("Experimental", proc_fs_cifs);
        remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
        remove_proc_entry("fs/cifs", NULL);
 }
 
-static int
-cifsFYI_read(char *page, char **start, off_t off, int count,
-            int *eof, void *data)
+static int cifsFYI_proc_show(struct seq_file *m, void *v)
 {
-       int len;
-
-       len = sprintf(page, "%d\n", cifsFYI);
-
-       len -= off;
-       *start = page + off;
-
-       if (len > count)
-               len = count;
-       else
-               *eof = 1;
-
-       if (len < 0)
-               len = 0;
+       seq_printf(m, "%d\n", cifsFYI);
+       return 0;
+}
 
-       return len;
+static int cifsFYI_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cifsFYI_proc_show, NULL);
 }
-static int
-cifsFYI_write(struct file *file, const char __user *buffer,
-             unsigned long count, void *data)
+
+static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
+               size_t count, loff_t *ppos)
 {
        char c;
        int rc;
@@ -603,30 +458,28 @@ cifsFYI_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static int
-oplockEnabled_read(char *page, char **start, off_t off,
-                  int count, int *eof, void *data)
-{
-       int len;
-
-       len = sprintf(page, "%d\n", oplockEnabled);
-
-       len -= off;
-       *start = page + off;
-
-       if (len > count)
-               len = count;
-       else
-               *eof = 1;
+static const struct file_operations cifsFYI_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cifsFYI_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = cifsFYI_proc_write,
+};
 
-       if (len < 0)
-               len = 0;
+static int cifs_oplock_proc_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "%d\n", oplockEnabled);
+       return 0;
+}
 
-       return len;
+static int cifs_oplock_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cifs_oplock_proc_show, NULL);
 }
-static int
-oplockEnabled_write(struct file *file, const char __user *buffer,
-                   unsigned long count, void *data)
+
+static ssize_t cifs_oplock_proc_write(struct file *file,
+               const char __user *buffer, size_t count, loff_t *ppos)
 {
        char c;
        int rc;
@@ -642,30 +495,28 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static int
-experimEnabled_read(char *page, char **start, off_t off,
-                   int count, int *eof, void *data)
-{
-       int len;
-
-       len = sprintf(page, "%d\n", experimEnabled);
-
-       len -= off;
-       *start = page + off;
+static const struct file_operations cifs_oplock_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cifs_oplock_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = cifs_oplock_proc_write,
+};
 
-       if (len > count)
-               len = count;
-       else
-               *eof = 1;
-
-       if (len < 0)
-               len = 0;
+static int cifs_experimental_proc_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "%d\n", experimEnabled);
+       return 0;
+}
 
-       return len;
+static int cifs_experimental_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cifs_experimental_proc_show, NULL);
 }
-static int
-experimEnabled_write(struct file *file, const char __user *buffer,
-                    unsigned long count, void *data)
+
+static ssize_t cifs_experimental_proc_write(struct file *file,
+               const char __user *buffer, size_t count, loff_t *ppos)
 {
        char c;
        int rc;
@@ -683,29 +534,28 @@ experimEnabled_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static int
-linuxExtensionsEnabled_read(char *page, char **start, off_t off,
-                           int count, int *eof, void *data)
-{
-       int len;
-
-       len = sprintf(page, "%d\n", linuxExtEnabled);
-       len -= off;
-       *start = page + off;
+static const struct file_operations cifs_experimental_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cifs_experimental_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = cifs_experimental_proc_write,
+};
 
-       if (len > count)
-               len = count;
-       else
-               *eof = 1;
-
-       if (len < 0)
-               len = 0;
+static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "%d\n", linuxExtEnabled);
+       return 0;
+}
 
-       return len;
+static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cifs_linux_ext_proc_show, NULL);
 }
-static int
-linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
-                            unsigned long count, void *data)
+
+static ssize_t cifs_linux_ext_proc_write(struct file *file,
+               const char __user *buffer, size_t count, loff_t *ppos)
 {
        char c;
        int rc;
@@ -721,31 +571,28 @@ linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
        return count;
 }
 
+static const struct file_operations cifs_linux_ext_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cifs_linux_ext_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = cifs_linux_ext_proc_write,
+};
 
-static int
-lookupFlag_read(char *page, char **start, off_t off,
-               int count, int *eof, void *data)
+static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v)
 {
-       int len;
-
-       len = sprintf(page, "%d\n", lookupCacheEnabled);
-
-       len -= off;
-       *start = page + off;
-
-       if (len > count)
-               len = count;
-       else
-               *eof = 1;
-
-       if (len < 0)
-               len = 0;
+       seq_printf(m, "%d\n", lookupCacheEnabled);
+       return 0;
+}
 
-       return len;
+static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cifs_lookup_cache_proc_show, NULL);
 }
-static int
-lookupFlag_write(struct file *file, const char __user *buffer,
-                   unsigned long count, void *data)
+
+static ssize_t cifs_lookup_cache_proc_write(struct file *file,
+               const char __user *buffer, size_t count, loff_t *ppos)
 {
        char c;
        int rc;
@@ -760,30 +607,29 @@ lookupFlag_write(struct file *file, const char __user *buffer,
 
        return count;
 }
-static int
-traceSMB_read(char *page, char **start, off_t off, int count,
-             int *eof, void *data)
-{
-       int len;
-
-       len = sprintf(page, "%d\n", traceSMB);
-
-       len -= off;
-       *start = page + off;
 
-       if (len > count)
-               len = count;
-       else
-               *eof = 1;
+static const struct file_operations cifs_lookup_cache_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cifs_lookup_cache_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = cifs_lookup_cache_proc_write,
+};
 
-       if (len < 0)
-               len = 0;
+static int traceSMB_proc_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "%d\n", traceSMB);
+       return 0;
+}
 
-       return len;
+static int traceSMB_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, traceSMB_proc_show, NULL);
 }
-static int
-traceSMB_write(struct file *file, const char __user *buffer,
-              unsigned long count, void *data)
+
+static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
+               size_t count, loff_t *ppos)
 {
        char c;
        int rc;
@@ -799,30 +645,28 @@ traceSMB_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static int
-multiuser_mount_read(char *page, char **start, off_t off,
-                    int count, int *eof, void *data)
-{
-       int len;
-
-       len = sprintf(page, "%d\n", multiuser_mount);
-
-       len -= off;
-       *start = page + off;
+static const struct file_operations traceSMB_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = traceSMB_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = traceSMB_proc_write,
+};
 
-       if (len > count)
-               len = count;
-       else
-               *eof = 1;
-
-       if (len < 0)
-               len = 0;
+static int cifs_multiuser_mount_proc_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "%d\n", multiuser_mount);
+       return 0;
+}
 
-       return len;
+static int cifs_multiuser_mount_proc_open(struct inode *inode, struct file *fh)
+{
+       return single_open(fh, cifs_multiuser_mount_proc_show, NULL);
 }
-static int
-multiuser_mount_write(struct file *file, const char __user *buffer,
-                     unsigned long count, void *data)
+
+static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
+               const char __user *buffer, size_t count, loff_t *ppos)
 {
        char c;
        int rc;
@@ -838,30 +682,28 @@ multiuser_mount_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static int
-security_flags_read(char *page, char **start, off_t off,
-                      int count, int *eof, void *data)
-{
-       int len;
-
-       len = sprintf(page, "0x%x\n", extended_security);
-
-       len -= off;
-       *start = page + off;
+static const struct file_operations cifs_multiuser_mount_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cifs_multiuser_mount_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = cifs_multiuser_mount_proc_write,
+};
 
-       if (len > count)
-               len = count;
-       else
-               *eof = 1;
-
-       if (len < 0)
-               len = 0;
+static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "0x%x\n", extended_security);
+       return 0;
+}
 
-       return len;
+static int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cifs_security_flags_proc_show, NULL);
 }
-static int
-security_flags_write(struct file *file, const char __user *buffer,
-                       unsigned long count, void *data)
+
+static ssize_t cifs_security_flags_proc_write(struct file *file,
+               const char __user *buffer, size_t count, loff_t *ppos)
 {
        unsigned int flags;
        char flags_string[12];
@@ -917,6 +759,15 @@ security_flags_write(struct file *file, const char __user *buffer,
        /* BB should we turn on MAY flags for other MUST options? */
        return count;
 }
+
+static const struct file_operations cifs_security_flags_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cifs_security_flags_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = cifs_security_flags_proc_write,
+};
 #else
 inline void cifs_proc_init(void)
 {
index 0e9fc2ba90ee23998c33e1125b6186c8f8150ac5..57ecdc83c26f3852440e67957ca031577cba8543 100644 (file)
@@ -56,7 +56,7 @@ int match_sid(struct cifs_sid *ctsid)
        struct cifs_sid *cwsid;
 
        if (!ctsid)
-               return (-1);
+               return -1;
 
        for (i = 0; i < NUM_WK_SIDS; ++i) {
                cwsid = &(wksidarr[i].cifssid);
@@ -87,11 +87,11 @@ int match_sid(struct cifs_sid *ctsid)
                }
 
                cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
-               return (0); /* sids compare/match */
+               return 0; /* sids compare/match */
        }
 
        cFYI(1, ("No matching sid"));
-       return (-1);
+       return -1;
 }
 
 /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
@@ -102,16 +102,16 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
        int num_subauth, num_sat, num_saw;
 
        if ((!ctsid) || (!cwsid))
-               return (0);
+               return 0;
 
        /* compare the revision */
        if (ctsid->revision != cwsid->revision)
-               return (0);
+               return 0;
 
        /* compare all of the six auth values */
        for (i = 0; i < 6; ++i) {
                if (ctsid->authority[i] != cwsid->authority[i])
-                       return (0);
+                       return 0;
        }
 
        /* compare all of the subauth values if any */
@@ -121,11 +121,11 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
        if (num_subauth) {
                for (i = 0; i < num_subauth; ++i) {
                        if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
-                               return (0);
+                               return 0;
                }
        }
 
-       return (1); /* sids compare/match */
+       return 1; /* sids compare/match */
 }
 
 
@@ -169,8 +169,7 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd,
        for (i = 0; i < 6; i++)
                ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
        for (i = 0; i < 5; i++)
-               ngroup_sid_ptr->sub_auth[i] =
-                               cpu_to_le32(group_sid_ptr->sub_auth[i]);
+               ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
 
        return;
 }
@@ -285,7 +284,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
        size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
        pntace->size = cpu_to_le16(size);
 
-       return (size);
+       return size;
 }
 
 
@@ -426,7 +425,7 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
        pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
        pndacl->num_aces = cpu_to_le32(3);
 
-       return (0);
+       return 0;
 }
 
 
@@ -510,7 +509,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
                        sizeof(struct cifs_sid)); */
 
 
-       return (0);
+       return 0;
 }
 
 
@@ -527,7 +526,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
        struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
 
        if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL))
-               return (-EIO);
+               return -EIO;
 
        owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->osidoffset));
@@ -550,7 +549,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
        /* copy security descriptor control portion and owner and group sid */
        copy_sec_desc(pntsd, pnntsd, sidsoffset);
 
-       return (rc);
+       return rc;
 }
 
 
@@ -629,11 +628,11 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
        cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
 
        if (!inode)
-               return (rc);
+               return rc;
 
        sb = inode->i_sb;
        if (sb == NULL)
-               return (rc);
+               return rc;
 
        cifs_sb = CIFS_SB(sb);
        xid = GetXid();
@@ -652,7 +651,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
                if (rc != 0) {
                        cERROR(1, ("Unable to open file to set ACL"));
                        FreeXid(xid);
-                       return (rc);
+                       return rc;
                }
        }
 
@@ -665,7 +664,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
 
        FreeXid(xid);
 
-       return (rc);
+       return rc;
 }
 
 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
@@ -715,7 +714,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
                if (!pnntsd) {
                        cERROR(1, ("Unable to allocate security descriptor"));
                        kfree(pntsd);
-                       return (-ENOMEM);
+                       return -ENOMEM;
                }
 
                rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
@@ -732,6 +731,6 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
                kfree(pntsd);
        }
 
-       return (rc);
+       return rc;
 }
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
index 4ff8939c6cc7b51543170ab8c28d4a54d450f483..83fd40dc1ef0ffc3d6f1136f6966b90155481e98 100644 (file)
@@ -310,9 +310,8 @@ void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key)
        utf8 and other multibyte codepages each need their own strupper
        function since a byte at a time will ont work. */
 
-       for (i = 0; i < CIFS_ENCPWD_SIZE; i++) {
+       for (i = 0; i < CIFS_ENCPWD_SIZE; i++)
                password_with_pad[i] = toupper(password_with_pad[i]);
-       }
 
        SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key);
        /* clear password before we return/free memory */
index 22857c639df55d59e13bd1ae01d70ee3153312a0..1ec7076f7b241b7a86d182043db5debf36fdd977 100644 (file)
@@ -267,7 +267,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
        return 0;
 }
 
-static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd)
+static int cifs_permission(struct inode *inode, int mask)
 {
        struct cifs_sb_info *cifs_sb;
 
@@ -766,7 +766,7 @@ const struct file_operations cifs_dir_ops = {
 };
 
 static void
-cifs_init_once(struct kmem_cache *cachep, void *inode)
+cifs_init_once(void *inode)
 {
        struct cifsInodeInfo *cifsi = inode;
 
index 9cfcf326ead3e058025b772c0debed32fe28bbe9..7e1cf262effe7b5afb0640ce7822ebf4d0d5c15e 100644 (file)
@@ -27,7 +27,7 @@
 #define MAX_SES_INFO 2
 #define MAX_TCON_INFO 4
 
-#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
+#define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1)
 #define MAX_SERVER_SIZE 15
 #define MAX_SHARE_SIZE  64     /* used to be 20, this should still be enough */
 #define MAX_USERNAME_SIZE 32   /* 32 is to allow for 15 char names + null
@@ -537,8 +537,8 @@ require use of the stronger protocol */
 #endif /* WEAK_PW_HASH */
 #define   CIFSSEC_MUST_SEAL    0x40040 /* not supported yet */
 
-#define   CIFSSEC_DEF  CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
-#define   CIFSSEC_MAX  CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
+#define   CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2)
+#define   CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2)
 #define   CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5)
 /*
  *****************************************************************
index 0f327c224da384a6724ea31c9f52731863680410..409abce1273246374560f8753baf5638b0d75884 100644 (file)
@@ -31,7 +31,7 @@
 #else
 #define CIFS_PROT   0
 #endif
-#define POSIX_PROT  CIFS_PROT+1
+#define POSIX_PROT  (CIFS_PROT+1)
 #define BAD_PROT 0xFFFF
 
 /* SMB command codes */
 #define CREATE_COMPLETE_IF_OPLK 0x00000100     /* should be zero */
 #define CREATE_NO_EA_KNOWLEDGE  0x00000200
 #define CREATE_EIGHT_DOT_THREE  0x00000400     /* doc says this is obsolete
-                                                "open for recovery" flag should
+                                                "open for recovery" flag should
                                                 be zero in any case */
 #define CREATE_OPEN_FOR_RECOVERY 0x00000400
 #define CREATE_RANDOM_ACCESS   0x00000800
@@ -414,8 +414,8 @@ struct smb_hdr {
        __u8 WordCount;
 } __attribute__((packed));
 /* given a pointer to an smb_hdr retrieve the value of byte count */
-#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
-#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
+#define BCC(smb_var) (*(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
+#define BCC_LE(smb_var) (*(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
 /* given a pointer to an smb_hdr retrieve the pointer to the byte area */
 #define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2)
 
index 4511b708f0f312d57677e2947276c2063f142446..c621ffa2ca90632173d83b59b4eb203dadbc496c 100644 (file)
@@ -686,11 +686,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                                                 SecurityBlob,
                                                 count - 16,
                                                 &server->secType);
-                       if (rc == 1) {
+                       if (rc == 1)
                                rc = 0;
-                       } else {
+                       else
                                rc = -EINVAL;
-                       }
                }
        } else
                server->capabilities &= ~CAP_EXTENDED_SECURITY;
@@ -3914,7 +3913,10 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
        bool is_unicode;
        struct dfs_referral_level_3 *ref;
 
-       is_unicode = pSMBr->hdr.Flags2 & SMBFLG2_UNICODE;
+       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+               is_unicode = true;
+       else
+               is_unicode = false;
        *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
 
        if (*num_of_nodes < 1) {
index e8fa46c7cff21f82f245e41cbd2cda8f7336d4c7..b51d5777cde695f308c85a2387a56b743ef1820c 100644 (file)
@@ -455,7 +455,7 @@ incomplete_rcv:
                /* Note that FC 1001 length is big endian on the wire,
                but we convert it here so it is always manipulated
                as host byte order */
-               pdu_length = ntohl(smb_buffer->smb_buf_length);
+               pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length);
                smb_buffer->smb_buf_length = pdu_length;
 
                cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
@@ -1461,6 +1461,39 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
        return rc;
 }
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+static struct lock_class_key cifs_key[2];
+static struct lock_class_key cifs_slock_key[2];
+
+static inline void
+cifs_reclassify_socket4(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+       BUG_ON(sock_owned_by_user(sk));
+       sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
+               &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
+}
+
+static inline void
+cifs_reclassify_socket6(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+       BUG_ON(sock_owned_by_user(sk));
+       sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
+               &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
+}
+#else
+static inline void
+cifs_reclassify_socket4(struct socket *sock)
+{
+}
+
+static inline void
+cifs_reclassify_socket6(struct socket *sock)
+{
+}
+#endif
+
 /* See RFC1001 section 14 on representation of Netbios names */
 static void rfc1002mangle(char *target, char *source, unsigned int length)
 {
@@ -1495,6 +1528,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
                /* BB other socket options to set KEEPALIVE, NODELAY? */
                        cFYI(1, ("Socket created"));
                        (*csocket)->sk->sk_allocation = GFP_NOFS;
+                       cifs_reclassify_socket4(*csocket);
                }
        }
 
@@ -1627,6 +1661,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
                /* BB other socket options to set KEEPALIVE, NODELAY? */
                         cFYI(1, ("ipv6 Socket created"));
                        (*csocket)->sk->sk_allocation = GFP_NOFS;
+                       cifs_reclassify_socket6(*csocket);
                }
        }
 
index 2e904bd111c8f5996045302fe66bfe99c5753bf9..46e54d39461da2182dd2eaf5d2c8aea05f9f4ed3 100644 (file)
@@ -1413,6 +1413,82 @@ out_busy:
        return -ETXTBSY;
 }
 
+static int
+cifs_set_file_size(struct inode *inode, struct iattr *attrs,
+                  int xid, char *full_path)
+{
+       int rc;
+       struct cifsFileInfo *open_file;
+       struct cifsInodeInfo *cifsInode = CIFS_I(inode);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct cifsTconInfo *pTcon = cifs_sb->tcon;
+
+       /*
+        * To avoid spurious oplock breaks from server, in the case of
+        * inodes that we already have open, avoid doing path based
+        * setting of file size if we can do it by handle.
+        * This keeps our caching token (oplock) and avoids timeouts
+        * when the local oplock break takes longer to flush
+        * writebehind data than the SMB timeout for the SetPathInfo
+        * request would allow
+        */
+       open_file = find_writable_file(cifsInode);
+       if (open_file) {
+               __u16 nfid = open_file->netfid;
+               __u32 npid = open_file->pid;
+               rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
+                                       npid, false);
+               atomic_dec(&open_file->wrtPending);
+               cFYI(1, ("SetFSize for attrs rc = %d", rc));
+               if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
+                       unsigned int bytes_written;
+                       rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size,
+                                         &bytes_written, NULL, NULL, 1);
+                       cFYI(1, ("Wrt seteof rc %d", rc));
+               }
+       } else
+               rc = -EINVAL;
+
+       if (rc != 0) {
+               /* Set file size by pathname rather than by handle
+                  either because no valid, writeable file handle for
+                  it was found or because there was an error setting
+                  it by handle */
+               rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,
+                                  false, cifs_sb->local_nls,
+                                  cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
+               cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
+               if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
+                       __u16 netfid;
+                       int oplock = 0;
+
+                       rc = SMBLegacyOpen(xid, pTcon, full_path,
+                               FILE_OPEN, GENERIC_WRITE,
+                               CREATE_NOT_DIR, &netfid, &oplock, NULL,
+                               cifs_sb->local_nls,
+                               cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
+                       if (rc == 0) {
+                               unsigned int bytes_written;
+                               rc = CIFSSMBWrite(xid, pTcon, netfid, 0,
+                                                 attrs->ia_size,
+                                                 &bytes_written, NULL,
+                                                 NULL, 1);
+                               cFYI(1, ("wrt seteof rc %d", rc));
+                               CIFSSMBClose(xid, pTcon, netfid);
+                       }
+               }
+       }
+
+       if (rc == 0) {
+               rc = cifs_vmtruncate(inode, attrs->ia_size);
+               cifs_truncate_page(inode->i_mapping, inode->i_size);
+       }
+
+       return rc;
+}
+
 int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 {
        int xid;
@@ -1420,7 +1496,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
        struct cifsTconInfo *pTcon;
        char *full_path = NULL;
        int rc = -EACCES;
-       struct cifsFileInfo *open_file = NULL;
        FILE_BASIC_INFO time_buf;
        bool set_time = false;
        bool set_dosattr = false;
@@ -1472,78 +1547,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
        }
 
        if (attrs->ia_valid & ATTR_SIZE) {
-               /* To avoid spurious oplock breaks from server, in the case of
-                  inodes that we already have open, avoid doing path based
-                  setting of file size if we can do it by handle.
-                  This keeps our caching token (oplock) and avoids timeouts
-                  when the local oplock break takes longer to flush
-                  writebehind data than the SMB timeout for the SetPathInfo
-                  request would allow */
-
-               open_file = find_writable_file(cifsInode);
-               if (open_file) {
-                       __u16 nfid = open_file->netfid;
-                       __u32 npid = open_file->pid;
-                       rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
-                                               nfid, npid, false);
-                       atomic_dec(&open_file->wrtPending);
-                       cFYI(1, ("SetFSize for attrs rc = %d", rc));
-                       if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
-                               unsigned int bytes_written;
-                               rc = CIFSSMBWrite(xid, pTcon,
-                                                 nfid, 0, attrs->ia_size,
-                                                 &bytes_written, NULL, NULL,
-                                                 1 /* 45 seconds */);
-                               cFYI(1, ("Wrt seteof rc %d", rc));
-                       }
-               } else
-                       rc = -EINVAL;
-
-               if (rc != 0) {
-                       /* Set file size by pathname rather than by handle
-                          either because no valid, writeable file handle for
-                          it was found or because there was an error setting
-                          it by handle */
-                       rc = CIFSSMBSetEOF(xid, pTcon, full_path,
-                                          attrs->ia_size, false,
-                                          cifs_sb->local_nls,
-                                          cifs_sb->mnt_cifs_flags &
-                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
-                       cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
-                       if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
-                               __u16 netfid;
-                               int oplock = 0;
-
-                               rc = SMBLegacyOpen(xid, pTcon, full_path,
-                                       FILE_OPEN, GENERIC_WRITE,
-                                       CREATE_NOT_DIR, &netfid, &oplock,
-                                       NULL, cifs_sb->local_nls,
-                                       cifs_sb->mnt_cifs_flags &
-                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
-                               if (rc == 0) {
-                                       unsigned int bytes_written;
-                                       rc = CIFSSMBWrite(xid, pTcon,
-                                                       netfid, 0,
-                                                       attrs->ia_size,
-                                                       &bytes_written, NULL,
-                                                       NULL, 1 /* 45 sec */);
-                                       cFYI(1, ("wrt seteof rc %d", rc));
-                                       CIFSSMBClose(xid, pTcon, netfid);
-                               }
-
-                       }
-               }
-
-               /* Server is ok setting allocation size implicitly - no need
-                  to call:
-               CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, true,
-                        cifs_sb->local_nls);
-                  */
-
-               if (rc == 0) {
-                       rc = cifs_vmtruncate(inode, attrs->ia_size);
-                       cifs_truncate_page(inode->i_mapping, inode->i_size);
-               } else
+               rc = cifs_set_file_size(inode, attrs, xid, full_path);
+               if (rc != 0)
                        goto cifs_setattr_exit;
        }
 
index 83f30695488303a785d24f02870fcfff612dd7e7..5f40ed3473f572ec59646ec33aa4978926d50548 100644 (file)
@@ -690,6 +690,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
                        else
                                cifs_buf_release(cifsFile->srch_inf.
                                                ntwrk_buf_start);
+                       cifsFile->srch_inf.ntwrk_buf_start = NULL;
                }
                rc = initiate_cifs_search(xid, file);
                if (rc) {
index e1c854890f9400b9467419ce9e625084391d9853..bf4a3fd3c8e33a910f0ab7ae638a4b66d06f08e5 100644 (file)
@@ -28,11 +28,9 @@ int coda_fake_statfs;
 char * coda_f2s(struct CodaFid *f)
 {
        static char s[60];
-#ifdef CONFIG_CODA_FS_OLD_API
-       sprintf(s, "(%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2]);
-#else
+
        sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]);
-#endif
+
        return s;
 }
 
index 3d2580e00a3e272e0cfe04103c98466e2daa15e7..c5916228243c1516b2d62e6b06cea208523a09ac 100644 (file)
@@ -137,9 +137,11 @@ exit:
 }
 
 
-int coda_permission(struct inode *inode, int mask, struct nameidata *nd)
+int coda_permission(struct inode *inode, int mask)
 {
         int error = 0;
+
+       mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
  
        if (!mask)
                return 0; 
index 2f58dfc70083536004ea5f1d8945be4650c27992..830f51abb97138d20d8dc07c8bc9ffb5e325659e 100644 (file)
@@ -58,7 +58,7 @@ static void coda_destroy_inode(struct inode *inode)
        kmem_cache_free(coda_inode_cachep, ITOC(inode));
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct coda_inode_info *ei = (struct coda_inode_info *) foo;
 
index c21a1f552a63bf0ca7ef5d09905a326036f0e844..c51365422aa8da4311133c3b0ff773421efbc723 100644 (file)
@@ -24,8 +24,7 @@
 #include <linux/coda_psdev.h>
 
 /* pioctl ops */
-static int coda_ioctl_permission(struct inode *inode, int mask,
-                                struct nameidata *nd);
+static int coda_ioctl_permission(struct inode *inode, int mask);
 static int coda_pioctl(struct inode * inode, struct file * filp, 
                        unsigned int cmd, unsigned long user_data);
 
@@ -42,8 +41,7 @@ const struct file_operations coda_ioctl_operations = {
 };
 
 /* the coda pioctl inode ops */
-static int coda_ioctl_permission(struct inode *inode, int mask,
-                                struct nameidata *nd)
+static int coda_ioctl_permission(struct inode *inode, int mask)
 {
         return 0;
 }
@@ -51,7 +49,7 @@ static int coda_ioctl_permission(struct inode *inode, int mask,
 static int coda_pioctl(struct inode * inode, struct file * filp, 
                        unsigned int cmd, unsigned long user_data)
 {
-       struct nameidata nd;
+       struct path path;
         int error;
        struct PioctlData data;
         struct inode *target_inode = NULL;
@@ -66,21 +64,21 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
          * Look up the pathname. Note that the pathname is in 
          * user memory, and namei takes care of this
          */
-        if ( data.follow ) {
-                error = user_path_walk(data.path, &nd);
+        if (data.follow) {
+                error = user_path(data.path, &path);
        } else {
-               error = user_path_walk_link(data.path, &nd);
+               error = user_lpath(data.path, &path);
        }
                
        if ( error ) {
                return error;
         } else {
-               target_inode = nd.path.dentry->d_inode;
+               target_inode = path.dentry->d_inode;
        }
        
        /* return if it is not a Coda inode */
        if ( target_inode->i_sb != inode->i_sb ) {
-               path_put(&nd.path);
+               path_put(&path);
                return  -EINVAL;
        }
 
@@ -89,7 +87,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
 
        error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
 
-       path_put(&nd.path);
+       path_put(&path);
         return error;
 }
 
index 40c36f7352a609a061cabdd1704e8074c0e0ee2e..0d9b80ec689ccc0741fee358d92f26b34f1bc4c9 100644 (file)
@@ -378,11 +378,7 @@ MODULE_AUTHOR("Jan Harkes, Peter J. Braam");
 MODULE_DESCRIPTION("Coda Distributed File System VFS interface");
 MODULE_ALIAS_CHARDEV_MAJOR(CODA_PSDEV_MAJOR);
 MODULE_LICENSE("GPL");
-#ifdef CONFIG_CODA_FS_OLD_API
-MODULE_VERSION("5.3.21");
-#else
 MODULE_VERSION("6.6");
-#endif
 
 static int __init init_coda(void)
 {
index 359e531094ddddb74a88de2dbb74e11dde27d528..ce432bca95d1f875db17233560d7d7f8cf2dbbfa 100644 (file)
@@ -52,12 +52,8 @@ static void *alloc_upcall(int opcode, int size)
         inp->ih.opcode = opcode;
        inp->ih.pid = current->pid;
        inp->ih.pgid = task_pgrp_nr(current);
-#ifdef CONFIG_CODA_FS_OLD_API
-       memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
-       inp->ih.cred.cr_fsuid = current->fsuid;
-#else
        inp->ih.uid = current->fsuid;
-#endif
+
        return (void*)inp;
 }
 
@@ -166,20 +162,11 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
        union inputArgs *inp;
        union outputArgs *outp;
        int insize, outsize, error;
-#ifdef CONFIG_CODA_FS_OLD_API
-       struct coda_cred cred = { 0, };
-       cred.cr_fsuid = uid;
-#endif
        
        insize = SIZE(release);
        UPARG(CODA_CLOSE);
        
-#ifdef CONFIG_CODA_FS_OLD_API
-       memcpy(&(inp->ih.cred), &cred, sizeof(cred));
-#else
        inp->ih.uid = uid;
-#endif
-       
         inp->coda_close.VFid = *fid;
         inp->coda_close.flags = flags;
 
index ed43e17a5dc68ad6663d28bc5abef135492c2e52..c9d1472e65c5a78288cd6c85c8c16f9bcd190a4c 100644 (file)
@@ -197,8 +197,8 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
 {
        
        if (sizeof ubuf->f_blocks == 4) {
-               if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) &
-                   0xffffffff00000000ULL)
+               if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
+                    kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
                        return -EOVERFLOW;
                /* f_files and f_ffree may be -1; it's okay
                 * to stuff that into 32 bits */
@@ -234,18 +234,18 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
  * The following statfs calls are copies of code from fs/open.c and
  * should be checked against those from time to time
  */
-asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs __user *buf)
+asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (!error) {
                struct kstatfs tmp;
-               error = vfs_statfs(nd.path.dentry, &tmp);
+               error = vfs_statfs(path.dentry, &tmp);
                if (!error)
                        error = put_compat_statfs(buf, &tmp);
-               path_put(&nd.path);
+               path_put(&path);
        }
        return error;
 }
@@ -271,8 +271,8 @@ out:
 static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
 {
        if (sizeof ubuf->f_blocks == 4) {
-               if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) &
-                   0xffffffff00000000ULL)
+               if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
+                    kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
                        return -EOVERFLOW;
                /* f_files and f_ffree may be -1; it's okay
                 * to stuff that into 32 bits */
@@ -299,21 +299,21 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
        return 0;
 }
 
-asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf)
+asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
        if (sz != sizeof(*buf))
                return -EINVAL;
 
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (!error) {
                struct kstatfs tmp;
-               error = vfs_statfs(nd.path.dentry, &tmp);
+               error = vfs_statfs(path.dentry, &tmp);
                if (!error)
                        error = put_compat_statfs64(buf, &tmp);
-               path_put(&nd.path);
+               path_put(&path);
        }
        return error;
 }
@@ -2131,9 +2131,9 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
 
 #ifdef CONFIG_SIGNALFD
 
-asmlinkage long compat_sys_signalfd(int ufd,
-                                   const compat_sigset_t __user *sigmask,
-                                   compat_size_t sigsetsize)
+asmlinkage long compat_sys_signalfd4(int ufd,
+                                    const compat_sigset_t __user *sigmask,
+                                    compat_size_t sigsetsize, int flags)
 {
        compat_sigset_t ss32;
        sigset_t tmp;
@@ -2148,9 +2148,15 @@ asmlinkage long compat_sys_signalfd(int ufd,
        if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
                return -EFAULT;
 
-       return sys_signalfd(ufd, ksigmask, sizeof(sigset_t));
+       return sys_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
 }
 
+asmlinkage long compat_sys_signalfd(int ufd,
+                                   const compat_sigset_t __user *sigmask,
+                                   compat_size_t sigsetsize)
+{
+       return compat_sys_signalfd4(ufd, sigmask, sigsetsize, 0);
+}
 #endif /* CONFIG_SIGNALFD */
 
 #ifdef CONFIG_TIMERFD
index 7b3a03c7c6a9dc5699663c044108d0323b0cc036..5235c67e7594141b289f008a77ee447de5faf8c3 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/raid/md.h>
 #include <linux/kd.h>
-#include <linux/dirent.h>
 #include <linux/route.h>
 #include <linux/in6.h>
 #include <linux/ipv6_route.h>
@@ -2297,8 +2296,6 @@ COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
 COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
 COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
 COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOSUBVER)
-COMPATIBLE_IOCTL(AUTOFS_IOC_ASKREGHOST)
-COMPATIBLE_IOCTL(AUTOFS_IOC_TOGGLEREGHOST)
 COMPATIBLE_IOCTL(AUTOFS_IOC_ASKUMOUNT)
 /* Raw devices */
 COMPATIBLE_IOCTL(RAW_SETBIND)
index 6068c25b393ca21f5faf8c9ca1fdf8d6051fc836..f2584d22cb45e9a46cde2fb3f8c376a47273b39a 100644 (file)
@@ -61,7 +61,6 @@ static struct kmem_cache *dentry_cache __read_mostly;
 static unsigned int d_hash_mask __read_mostly;
 static unsigned int d_hash_shift __read_mostly;
 static struct hlist_head *dentry_hashtable __read_mostly;
-static LIST_HEAD(dentry_unused);
 
 /* Statistics gathering. */
 struct dentry_stat_t dentry_stat = {
@@ -96,14 +95,6 @@ static void d_free(struct dentry *dentry)
                call_rcu(&dentry->d_u.d_rcu, d_callback);
 }
 
-static void dentry_lru_remove(struct dentry *dentry)
-{
-       if (!list_empty(&dentry->d_lru)) {
-               list_del_init(&dentry->d_lru);
-               dentry_stat.nr_unused--;
-       }
-}
-
 /*
  * Release the dentry's inode, using the filesystem
  * d_iput() operation if defined.
@@ -130,6 +121,41 @@ static void dentry_iput(struct dentry * dentry)
        }
 }
 
+/*
+ * dentry_lru_(add|add_tail|del|del_init) must be called with dcache_lock held.
+ */
+static void dentry_lru_add(struct dentry *dentry)
+{
+       list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
+       dentry->d_sb->s_nr_dentry_unused++;
+       dentry_stat.nr_unused++;
+}
+
+static void dentry_lru_add_tail(struct dentry *dentry)
+{
+       list_add_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
+       dentry->d_sb->s_nr_dentry_unused++;
+       dentry_stat.nr_unused++;
+}
+
+static void dentry_lru_del(struct dentry *dentry)
+{
+       if (!list_empty(&dentry->d_lru)) {
+               list_del(&dentry->d_lru);
+               dentry->d_sb->s_nr_dentry_unused--;
+               dentry_stat.nr_unused--;
+       }
+}
+
+static void dentry_lru_del_init(struct dentry *dentry)
+{
+       if (likely(!list_empty(&dentry->d_lru))) {
+               list_del_init(&dentry->d_lru);
+               dentry->d_sb->s_nr_dentry_unused--;
+               dentry_stat.nr_unused--;
+       }
+}
+
 /**
  * d_kill - kill dentry and return parent
  * @dentry: dentry to kill
@@ -212,8 +238,7 @@ repeat:
                goto kill_it;
        if (list_empty(&dentry->d_lru)) {
                dentry->d_flags |= DCACHE_REFERENCED;
-               list_add(&dentry->d_lru, &dentry_unused);
-               dentry_stat.nr_unused++;
+               dentry_lru_add(dentry);
        }
        spin_unlock(&dentry->d_lock);
        spin_unlock(&dcache_lock);
@@ -222,7 +247,8 @@ repeat:
 unhash_it:
        __d_drop(dentry);
 kill_it:
-       dentry_lru_remove(dentry);
+       /* if dentry was on the d_lru list delete it from there */
+       dentry_lru_del(dentry);
        dentry = d_kill(dentry);
        if (dentry)
                goto repeat;
@@ -290,7 +316,7 @@ int d_invalidate(struct dentry * dentry)
 static inline struct dentry * __dget_locked(struct dentry *dentry)
 {
        atomic_inc(&dentry->d_count);
-       dentry_lru_remove(dentry);
+       dentry_lru_del_init(dentry);
        return dentry;
 }
 
@@ -406,133 +432,168 @@ static void prune_one_dentry(struct dentry * dentry)
 
                if (dentry->d_op && dentry->d_op->d_delete)
                        dentry->d_op->d_delete(dentry);
-               dentry_lru_remove(dentry);
+               dentry_lru_del_init(dentry);
                __d_drop(dentry);
                dentry = d_kill(dentry);
                spin_lock(&dcache_lock);
        }
 }
 
-/**
- * prune_dcache - shrink the dcache
- * @count: number of entries to try and free
- * @sb: if given, ignore dentries for other superblocks
- *         which are being unmounted.
- *
- * Shrink the dcache. This is done when we need
- * more memory, or simply when we need to unmount
- * something (at which point we need to unuse
- * all dentries).
- *
- * This function may fail to free any resources if
- * all the dentries are in use.
+/*
+ * Shrink the dentry LRU on a given superblock.
+ * @sb   : superblock to shrink dentry LRU.
+ * @count: If count is NULL, we prune all dentries on superblock.
+ * @flags: If flags is non-zero, we need to do special processing based on
+ * which flags are set. This means we don't need to maintain multiple
+ * similar copies of this loop.
  */
-static void prune_dcache(int count, struct super_block *sb)
+static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags)
 {
-       spin_lock(&dcache_lock);
-       for (; count ; count--) {
-               struct dentry *dentry;
-               struct list_head *tmp;
-               struct rw_semaphore *s_umount;
-
-               cond_resched_lock(&dcache_lock);
+       LIST_HEAD(referenced);
+       LIST_HEAD(tmp);
+       struct dentry *dentry;
+       int cnt = 0;
 
-               tmp = dentry_unused.prev;
-               if (sb) {
-                       /* Try to find a dentry for this sb, but don't try
-                        * too hard, if they aren't near the tail they will
-                        * be moved down again soon
+       BUG_ON(!sb);
+       BUG_ON((flags & DCACHE_REFERENCED) && count == NULL);
+       spin_lock(&dcache_lock);
+       if (count != NULL)
+               /* called from prune_dcache() and shrink_dcache_parent() */
+               cnt = *count;
+restart:
+       if (count == NULL)
+               list_splice_init(&sb->s_dentry_lru, &tmp);
+       else {
+               while (!list_empty(&sb->s_dentry_lru)) {
+                       dentry = list_entry(sb->s_dentry_lru.prev,
+                                       struct dentry, d_lru);
+                       BUG_ON(dentry->d_sb != sb);
+
+                       spin_lock(&dentry->d_lock);
+                       /*
+                        * If we are honouring the DCACHE_REFERENCED flag and
+                        * the dentry has this flag set, don't free it. Clear
+                        * the flag and put it back on the LRU.
                         */
-                       int skip = count;
-                       while (skip && tmp != &dentry_unused &&
-                           list_entry(tmp, struct dentry, d_lru)->d_sb != sb) {
-                               skip--;
-                               tmp = tmp->prev;
+                       if ((flags & DCACHE_REFERENCED)
+                               && (dentry->d_flags & DCACHE_REFERENCED)) {
+                               dentry->d_flags &= ~DCACHE_REFERENCED;
+                               list_move_tail(&dentry->d_lru, &referenced);
+                               spin_unlock(&dentry->d_lock);
+                       } else {
+                               list_move_tail(&dentry->d_lru, &tmp);
+                               spin_unlock(&dentry->d_lock);
+                               cnt--;
+                               if (!cnt)
+                                       break;
                        }
+                       cond_resched_lock(&dcache_lock);
                }
-               if (tmp == &dentry_unused)
-                       break;
-               list_del_init(tmp);
-               prefetch(dentry_unused.prev);
-               dentry_stat.nr_unused--;
-               dentry = list_entry(tmp, struct dentry, d_lru);
-
-               spin_lock(&dentry->d_lock);
+       }
+       while (!list_empty(&tmp)) {
+               dentry = list_entry(tmp.prev, struct dentry, d_lru);
+               dentry_lru_del_init(dentry);
+               spin_lock(&dentry->d_lock);
                /*
                 * We found an inuse dentry which was not removed from
-                * dentry_unused because of laziness during lookup.  Do not free
-                * it - just keep it off the dentry_unused list.
+                * the LRU because of laziness during lookup.  Do not free
+                * it - just keep it off the LRU list.
                 */
-               if (atomic_read(&dentry->d_count)) {
-                       spin_unlock(&dentry->d_lock);
+               if (atomic_read(&dentry->d_count)) {
+                       spin_unlock(&dentry->d_lock);
                        continue;
                }
-               /* If the dentry was recently referenced, don't free it. */
-               if (dentry->d_flags & DCACHE_REFERENCED) {
-                       dentry->d_flags &= ~DCACHE_REFERENCED;
-                       list_add(&dentry->d_lru, &dentry_unused);
-                       dentry_stat.nr_unused++;
-                       spin_unlock(&dentry->d_lock);
+               prune_one_dentry(dentry);
+               /* dentry->d_lock was dropped in prune_one_dentry() */
+               cond_resched_lock(&dcache_lock);
+       }
+       if (count == NULL && !list_empty(&sb->s_dentry_lru))
+               goto restart;
+       if (count != NULL)
+               *count = cnt;
+       if (!list_empty(&referenced))
+               list_splice(&referenced, &sb->s_dentry_lru);
+       spin_unlock(&dcache_lock);
+}
+
+/**
+ * prune_dcache - shrink the dcache
+ * @count: number of entries to try to free
+ *
+ * Shrink the dcache. This is done when we need more memory, or simply when we
+ * need to unmount something (at which point we need to unuse all dentries).
+ *
+ * This function may fail to free any resources if all the dentries are in use.
+ */
+static void prune_dcache(int count)
+{
+       struct super_block *sb;
+       int w_count;
+       int unused = dentry_stat.nr_unused;
+       int prune_ratio;
+       int pruned;
+
+       if (unused == 0 || count == 0)
+               return;
+       spin_lock(&dcache_lock);
+restart:
+       if (count >= unused)
+               prune_ratio = 1;
+       else
+               prune_ratio = unused / count;
+       spin_lock(&sb_lock);
+       list_for_each_entry(sb, &super_blocks, s_list) {
+               if (sb->s_nr_dentry_unused == 0)
                        continue;
-               }
-               /*
-                * If the dentry is not DCACHED_REFERENCED, it is time
-                * to remove it from the dcache, provided the super block is
-                * NULL (which means we are trying to reclaim memory)
-                * or this dentry belongs to the same super block that
-                * we want to shrink.
-                */
-               /*
-                * If this dentry is for "my" filesystem, then I can prune it
-                * without taking the s_umount lock (I already hold it).
+               sb->s_count++;
+               /* Now, we reclaim unused dentrins with fairness.
+                * We reclaim them same percentage from each superblock.
+                * We calculate number of dentries to scan on this sb
+                * as follows, but the implementation is arranged to avoid
+                * overflows:
+                * number of dentries to scan on this sb =
+                * count * (number of dentries on this sb /
+                * number of dentries in the machine)
                 */
-               if (sb && dentry->d_sb == sb) {
-                       prune_one_dentry(dentry);
-                       continue;
-               }
+               spin_unlock(&sb_lock);
+               if (prune_ratio != 1)
+                       w_count = (sb->s_nr_dentry_unused / prune_ratio) + 1;
+               else
+                       w_count = sb->s_nr_dentry_unused;
+               pruned = w_count;
                /*
-                * ...otherwise we need to be sure this filesystem isn't being
-                * unmounted, otherwise we could race with
-                * generic_shutdown_super(), and end up holding a reference to
-                * an inode while the filesystem is unmounted.
-                * So we try to get s_umount, and make sure s_root isn't NULL.
-                * (Take a local copy of s_umount to avoid a use-after-free of
-                * `dentry').
+                * We need to be sure this filesystem isn't being unmounted,
+                * otherwise we could race with generic_shutdown_super(), and
+                * end up holding a reference to an inode while the filesystem
+                * is unmounted.  So we try to get s_umount, and make sure
+                * s_root isn't NULL.
                 */
-               s_umount = &dentry->d_sb->s_umount;
-               if (down_read_trylock(s_umount)) {
-                       if (dentry->d_sb->s_root != NULL) {
-                               prune_one_dentry(dentry);
-                               up_read(s_umount);
-                               continue;
+               if (down_read_trylock(&sb->s_umount)) {
+                       if ((sb->s_root != NULL) &&
+                           (!list_empty(&sb->s_dentry_lru))) {
+                               spin_unlock(&dcache_lock);
+                               __shrink_dcache_sb(sb, &w_count,
+                                               DCACHE_REFERENCED);
+                               pruned -= w_count;
+                               spin_lock(&dcache_lock);
                        }
-                       up_read(s_umount);
+                       up_read(&sb->s_umount);
                }
-               spin_unlock(&dentry->d_lock);
+               spin_lock(&sb_lock);
+               count -= pruned;
                /*
-                * Insert dentry at the head of the list as inserting at the
-                * tail leads to a cycle.
+                * restart only when sb is no longer on the list and
+                * we have more work to do.
                 */
-               list_add(&dentry->d_lru, &dentry_unused);
-               dentry_stat.nr_unused++;
+               if (__put_super_and_need_restart(sb) && count > 0) {
+                       spin_unlock(&sb_lock);
+                       goto restart;
+               }
        }
+       spin_unlock(&sb_lock);
        spin_unlock(&dcache_lock);
 }
 
-/*
- * Shrink the dcache for the specified super block.
- * This allows us to unmount a device without disturbing
- * the dcache for the other devices.
- *
- * This implementation makes just two traversals of the
- * unused list.  On the first pass we move the selected
- * dentries to the most recent end, and on the second
- * pass we free them.  The second pass must restart after
- * each dput(), but since the target dentries are all at
- * the end, it's really just a single traversal.
- */
-
 /**
  * shrink_dcache_sb - shrink dcache for a superblock
  * @sb: superblock
@@ -541,44 +602,9 @@ static void prune_dcache(int count, struct super_block *sb)
  * is used to free the dcache before unmounting a file
  * system
  */
-
 void shrink_dcache_sb(struct super_block * sb)
 {
-       struct list_head *tmp, *next;
-       struct dentry *dentry;
-
-       /*
-        * Pass one ... move the dentries for the specified
-        * superblock to the most recent end of the unused list.
-        */
-       spin_lock(&dcache_lock);
-       list_for_each_prev_safe(tmp, next, &dentry_unused) {
-               dentry = list_entry(tmp, struct dentry, d_lru);
-               if (dentry->d_sb != sb)
-                       continue;
-               list_move_tail(tmp, &dentry_unused);
-       }
-
-       /*
-        * Pass two ... free the dentries for this superblock.
-        */
-repeat:
-       list_for_each_prev_safe(tmp, next, &dentry_unused) {
-               dentry = list_entry(tmp, struct dentry, d_lru);
-               if (dentry->d_sb != sb)
-                       continue;
-               dentry_stat.nr_unused--;
-               list_del_init(tmp);
-               spin_lock(&dentry->d_lock);
-               if (atomic_read(&dentry->d_count)) {
-                       spin_unlock(&dentry->d_lock);
-                       continue;
-               }
-               prune_one_dentry(dentry);
-               cond_resched_lock(&dcache_lock);
-               goto repeat;
-       }
-       spin_unlock(&dcache_lock);
+       __shrink_dcache_sb(sb, NULL, 0);
 }
 
 /*
@@ -595,7 +621,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
 
        /* detach this root from the system */
        spin_lock(&dcache_lock);
-       dentry_lru_remove(dentry);
+       dentry_lru_del_init(dentry);
        __d_drop(dentry);
        spin_unlock(&dcache_lock);
 
@@ -609,7 +635,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                        spin_lock(&dcache_lock);
                        list_for_each_entry(loop, &dentry->d_subdirs,
                                            d_u.d_child) {
-                               dentry_lru_remove(loop);
+                               dentry_lru_del_init(loop);
                                __d_drop(loop);
                                cond_resched_lock(&dcache_lock);
                        }
@@ -791,14 +817,13 @@ resume:
                struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
                next = tmp->next;
 
-               dentry_lru_remove(dentry);
+               dentry_lru_del_init(dentry);
                /* 
                 * move only zero ref count dentries to the end 
                 * of the unused list for prune_dcache
                 */
                if (!atomic_read(&dentry->d_count)) {
-                       list_add_tail(&dentry->d_lru, &dentry_unused);
-                       dentry_stat.nr_unused++;
+                       dentry_lru_add_tail(dentry);
                        found++;
                }
 
@@ -840,10 +865,11 @@ out:
  
 void shrink_dcache_parent(struct dentry * parent)
 {
+       struct super_block *sb = parent->d_sb;
        int found;
 
        while ((found = select_parent(parent)) != 0)
-               prune_dcache(found, parent->d_sb);
+               __shrink_dcache_sb(sb, &found, 0);
 }
 
 /*
@@ -863,7 +889,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask)
        if (nr) {
                if (!(gfp_mask & __GFP_FS))
                        return -1;
-               prune_dcache(nr, NULL);
+               prune_dcache(nr);
        }
        return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
@@ -1215,7 +1241,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
  * rcu_read_lock() and rcu_read_unlock() are used to disable preemption while
  * lookup is going on.
  *
- * dentry_unused list is not updated even if lookup finds the required dentry
+ * The dentry unused LRU is not updated even if lookup finds the required dentry
  * in there. It is updated in places such as prune_dcache, shrink_dcache_sb,
  * select_parent and __dget_locked. This laziness saves lookup from dcache_lock
  * acquisition.
index 9e81addbd6ea7293ad3d2578d20bfeaf92cf8354..9606ee848fd81c98ca9fc2cc496e0452140c9205 100644 (file)
@@ -150,17 +150,11 @@ static int dio_refill_pages(struct dio *dio)
        int nr_pages;
 
        nr_pages = min(dio->total_pages - dio->curr_page, DIO_PAGES);
-       down_read(&current->mm->mmap_sem);
-       ret = get_user_pages(
-               current,                        /* Task for fault acounting */
-               current->mm,                    /* whose pages? */
+       ret = get_user_pages_fast(
                dio->curr_user_address,         /* Where from? */
                nr_pages,                       /* How many pages? */
                dio->rw == READ,                /* Write to memory? */
-               0,                              /* force (?) */
-               &dio->pages[0],
-               NULL);                          /* vmas */
-       up_read(&current->mm->mmap_sem);
+               &dio->pages[0]);                /* Put results here */
 
        if (ret < 0 && dio->blocks_available && (dio->rw & WRITE)) {
                struct page *page = ZERO_PAGE(0);
index 2d3d1027ce2bbdfbc30fef5631b1ce378deaf05e..724ddac91538040d058abfc9888f4188143f83a7 100644 (file)
@@ -363,6 +363,7 @@ static int search_rsb_list(struct list_head *head, char *name, int len,
                if (len == r->res_length && !memcmp(name, r->res_name, len))
                        goto found;
        }
+       *r_ret = NULL;
        return -EBADR;
 
  found:
@@ -1782,7 +1783,8 @@ static void grant_pending_locks(struct dlm_rsb *r)
 
        list_for_each_entry_safe(lkb, s, &r->res_grantqueue, lkb_statequeue) {
                if (lkb->lkb_bastfn && lock_requires_bast(lkb, high, cw)) {
-                       if (cw && high == DLM_LOCK_PR)
+                       if (cw && high == DLM_LOCK_PR &&
+                           lkb->lkb_grmode == DLM_LOCK_PR)
                                queue_bast(r, lkb, DLM_LOCK_CW);
                        else
                                queue_bast(r, lkb, high);
index 637018c891eff7110620ba3aff2ff9f5e573ec8d..3962262f991a32a415db104fd191679834c537a9 100644 (file)
@@ -891,8 +891,10 @@ static void tcp_connect_to_sock(struct connection *con)
                goto out_err;
 
        memset(&saddr, 0, sizeof(saddr));
-       if (dlm_nodeid_to_addr(con->nodeid, &saddr))
+       if (dlm_nodeid_to_addr(con->nodeid, &saddr)) {
+               sock_release(sock);
                goto out_err;
+       }
 
        sock->sk->sk_user_data = con;
        con->rx_action = receive_from_sock;
index 78878c5781cadc0d13846d8af6a993039d8b39e6..eba87ff3177b6070284ee3eea402fd34c610c657 100644 (file)
@@ -116,7 +116,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
        if (xop->callback == NULL)
                wait_event(recv_wq, (op->done != 0));
        else {
-               rv = -EINPROGRESS;
+               rv = FILE_LOCK_DEFERRED;
                goto out;
        }
 
index f976f303c196284e2426167611325772c84d4cde..929e48ae7591199cc0e6e4c80eb4516c939bfd60 100644 (file)
@@ -539,7 +539,7 @@ static ssize_t device_write(struct file *file, const char __user *buf,
 
        /* do we really need this? can a write happen after a close? */
        if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
-           test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
+           (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags)))
                return -EINVAL;
 
        sigfillset(&allsigs);
index 5ac77da19959f9f15792d16669d0b4110674cc3e..1346eebe74ce973e1b81edd788a58442089329af 100644 (file)
@@ -562,6 +562,8 @@ static struct shrinker dqcache_shrinker = {
  */
 static void dqput(struct dquot *dquot)
 {
+       int ret;
+
        if (!dquot)
                return;
 #ifdef __DQUOT_PARANOIA
@@ -594,7 +596,19 @@ we_slept:
        if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_dirty(dquot)) {
                spin_unlock(&dq_list_lock);
                /* Commit dquot before releasing */
-               dquot->dq_sb->dq_op->write_dquot(dquot);
+               ret = dquot->dq_sb->dq_op->write_dquot(dquot);
+               if (ret < 0) {
+                       printk(KERN_ERR "VFS: cannot write quota structure on "
+                               "device %s (error %d). Quota may get out of "
+                               "sync!\n", dquot->dq_sb->s_id, ret);
+                       /*
+                        * We clear dirty bit anyway, so that we avoid
+                        * infinite loop here
+                        */
+                       spin_lock(&dq_list_lock);
+                       clear_dquot_dirty(dquot);
+                       spin_unlock(&dq_list_lock);
+               }
                goto we_slept;
        }
        /* Clear flag in case dquot was inactive (something bad happened) */
@@ -875,7 +889,10 @@ static void print_warning(struct dquot *dquot, const int warntype)
        char *msg = NULL;
        struct tty_struct *tty;
 
-       if (!need_print_warning(dquot))
+       if (warntype == QUOTA_NL_IHARDBELOW ||
+           warntype == QUOTA_NL_ISOFTBELOW ||
+           warntype == QUOTA_NL_BHARDBELOW ||
+           warntype == QUOTA_NL_BSOFTBELOW || !need_print_warning(dquot))
                return;
 
        mutex_lock(&tty_mutex);
@@ -1083,6 +1100,35 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
        return QUOTA_OK;
 }
 
+static int info_idq_free(struct dquot *dquot, ulong inodes)
+{
+       if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
+           dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit)
+               return QUOTA_NL_NOWARN;
+
+       if (dquot->dq_dqb.dqb_curinodes - inodes <= dquot->dq_dqb.dqb_isoftlimit)
+               return QUOTA_NL_ISOFTBELOW;
+       if (dquot->dq_dqb.dqb_curinodes >= dquot->dq_dqb.dqb_ihardlimit &&
+           dquot->dq_dqb.dqb_curinodes - inodes < dquot->dq_dqb.dqb_ihardlimit)
+               return QUOTA_NL_IHARDBELOW;
+       return QUOTA_NL_NOWARN;
+}
+
+static int info_bdq_free(struct dquot *dquot, qsize_t space)
+{
+       if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
+           toqb(dquot->dq_dqb.dqb_curspace) <= dquot->dq_dqb.dqb_bsoftlimit)
+               return QUOTA_NL_NOWARN;
+
+       if (toqb(dquot->dq_dqb.dqb_curspace - space) <=
+           dquot->dq_dqb.dqb_bsoftlimit)
+               return QUOTA_NL_BSOFTBELOW;
+       if (toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bhardlimit &&
+           toqb(dquot->dq_dqb.dqb_curspace - space) <
+                                               dquot->dq_dqb.dqb_bhardlimit)
+               return QUOTA_NL_BHARDBELOW;
+       return QUOTA_NL_NOWARN;
+}
 /*
  *     Initialize quota pointers in inode
  *     Transaction must be started at entry
@@ -1139,6 +1185,28 @@ int dquot_drop(struct inode *inode)
        return 0;
 }
 
+/* Wrapper to remove references to quota structures from inode */
+void vfs_dq_drop(struct inode *inode)
+{
+       /* Here we can get arbitrary inode from clear_inode() so we have
+        * to be careful. OTOH we don't need locking as quota operations
+        * are allowed to change only at mount time */
+       if (!IS_NOQUOTA(inode) && inode->i_sb && inode->i_sb->dq_op
+           && inode->i_sb->dq_op->drop) {
+               int cnt;
+               /* Test before calling to rule out calls from proc and such
+                 * where we are not allowed to block. Note that this is
+                * actually reliable test even without the lock - the caller
+                * must assure that nobody can come after the DQUOT_DROP and
+                * add quota pointers back anyway */
+               for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+                       if (inode->i_dquot[cnt] != NODQUOT)
+                               break;
+               if (cnt < MAXQUOTAS)
+                       inode->i_sb->dq_op->drop(inode);
+       }
+}
+
 /*
  * Following four functions update i_blocks+i_bytes fields and
  * quota information (together with appropriate checks)
@@ -1248,6 +1316,7 @@ warn_put_all:
 int dquot_free_space(struct inode *inode, qsize_t number)
 {
        unsigned int cnt;
+       char warntype[MAXQUOTAS];
 
        /* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
@@ -1256,6 +1325,7 @@ out_sub:
                inode_sub_bytes(inode, number);
                return QUOTA_OK;
        }
+
        down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        /* Now recheck reliably when holding dqptr_sem */
        if (IS_NOQUOTA(inode)) {
@@ -1266,6 +1336,7 @@ out_sub:
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (inode->i_dquot[cnt] == NODQUOT)
                        continue;
+               warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number);
                dquot_decr_space(inode->i_dquot[cnt], number);
        }
        inode_sub_bytes(inode, number);
@@ -1274,6 +1345,7 @@ out_sub:
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
                if (inode->i_dquot[cnt])
                        mark_dquot_dirty(inode->i_dquot[cnt]);
+       flush_warnings(inode->i_dquot, warntype);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        return QUOTA_OK;
 }
@@ -1284,11 +1356,13 @@ out_sub:
 int dquot_free_inode(const struct inode *inode, unsigned long number)
 {
        unsigned int cnt;
+       char warntype[MAXQUOTAS];
 
        /* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
        if (IS_NOQUOTA(inode))
                return QUOTA_OK;
+
        down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        /* Now recheck reliably when holding dqptr_sem */
        if (IS_NOQUOTA(inode)) {
@@ -1299,6 +1373,7 @@ int dquot_free_inode(const struct inode *inode, unsigned long number)
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (inode->i_dquot[cnt] == NODQUOT)
                        continue;
+               warntype[cnt] = info_idq_free(inode->i_dquot[cnt], number);
                dquot_decr_inodes(inode->i_dquot[cnt], number);
        }
        spin_unlock(&dq_data_lock);
@@ -1306,6 +1381,7 @@ int dquot_free_inode(const struct inode *inode, unsigned long number)
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
                if (inode->i_dquot[cnt])
                        mark_dquot_dirty(inode->i_dquot[cnt]);
+       flush_warnings(inode->i_dquot, warntype);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        return QUOTA_OK;
 }
@@ -1323,7 +1399,8 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
        struct dquot *transfer_to[MAXQUOTAS];
        int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid,
            chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid;
-       char warntype[MAXQUOTAS];
+       char warntype_to[MAXQUOTAS];
+       char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS];
 
        /* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
@@ -1332,7 +1409,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
        /* Clear the arrays */
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                transfer_to[cnt] = transfer_from[cnt] = NODQUOT;
-               warntype[cnt] = QUOTA_NL_NOWARN;
+               warntype_to[cnt] = QUOTA_NL_NOWARN;
        }
        down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
        /* Now recheck reliably when holding dqptr_sem */
@@ -1364,8 +1441,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
                if (transfer_to[cnt] == NODQUOT)
                        continue;
                transfer_from[cnt] = inode->i_dquot[cnt];
-               if (check_idq(transfer_to[cnt], 1, warntype+cnt) == NO_QUOTA ||
-                   check_bdq(transfer_to[cnt], space, 0, warntype+cnt) == NO_QUOTA)
+               if (check_idq(transfer_to[cnt], 1, warntype_to + cnt) ==
+                   NO_QUOTA || check_bdq(transfer_to[cnt], space, 0,
+                   warntype_to + cnt) == NO_QUOTA)
                        goto warn_put_all;
        }
 
@@ -1381,6 +1459,10 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
 
                /* Due to IO error we might not have transfer_from[] structure */
                if (transfer_from[cnt]) {
+                       warntype_from_inodes[cnt] =
+                               info_idq_free(transfer_from[cnt], 1);
+                       warntype_from_space[cnt] =
+                               info_bdq_free(transfer_from[cnt], space);
                        dquot_decr_inodes(transfer_from[cnt], 1);
                        dquot_decr_space(transfer_from[cnt], space);
                }
@@ -1400,7 +1482,9 @@ warn_put_all:
                if (transfer_to[cnt])
                        mark_dquot_dirty(transfer_to[cnt]);
        }
-       flush_warnings(transfer_to, warntype);
+       flush_warnings(transfer_to, warntype_to);
+       flush_warnings(transfer_from, warntype_from_inodes);
+       flush_warnings(transfer_from, warntype_from_space);
        
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (ret == QUOTA_OK && transfer_from[cnt] != NODQUOT)
@@ -1412,6 +1496,18 @@ warn_put_all:
        return ret;
 }
 
+/* Wrapper for transferring ownership of an inode */
+int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
+{
+       if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) {
+               vfs_dq_init(inode);
+               if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA)
+                       return 1;
+       }
+       return 0;
+}
+
+
 /*
  * Write info of quota file to disk
  */
@@ -1752,6 +1848,22 @@ out:
        return error;
 }
 
+/* Wrapper to turn on quotas when remounting rw */
+int vfs_dq_quota_on_remount(struct super_block *sb)
+{
+       int cnt;
+       int ret = 0, err;
+
+       if (!sb->s_qcop || !sb->s_qcop->quota_on)
+               return -ENOSYS;
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               err = sb->s_qcop->quota_on(sb, cnt, 0, NULL, 1);
+               if (err < 0 && !ret)
+                       ret = err;
+       }
+       return ret;
+}
+
 /* Generic routine for getting common part of quota structure */
 static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
 {
@@ -2087,8 +2199,11 @@ EXPORT_SYMBOL(dquot_release);
 EXPORT_SYMBOL(dquot_mark_dquot_dirty);
 EXPORT_SYMBOL(dquot_initialize);
 EXPORT_SYMBOL(dquot_drop);
+EXPORT_SYMBOL(vfs_dq_drop);
 EXPORT_SYMBOL(dquot_alloc_space);
 EXPORT_SYMBOL(dquot_alloc_inode);
 EXPORT_SYMBOL(dquot_free_space);
 EXPORT_SYMBOL(dquot_free_inode);
 EXPORT_SYMBOL(dquot_transfer);
+EXPORT_SYMBOL(vfs_dq_transfer);
+EXPORT_SYMBOL(vfs_dq_quota_on_remount);
index 1e34a7fd4884391b5bec9a3de93bc4dfb86d7d2b..b4755a85996e9d6be9597fb92c05d668ff88713c 100644 (file)
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
 
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o miscdev.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o miscdev.o kthread.o debug.o
index e2832bc7869a2ed357ff85763f4ed811af29592e..06db79d05c1262a8de76fc9dcb820b910b464163 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/crypto.h>
 #include <linux/file.h>
 #include <linux/scatterlist.h>
+#include <asm/unaligned.h>
 #include "ecryptfs_kernel.h"
 
 static int
@@ -474,8 +475,8 @@ int ecryptfs_encrypt_page(struct page *page)
 {
        struct inode *ecryptfs_inode;
        struct ecryptfs_crypt_stat *crypt_stat;
-       char *enc_extent_virt = NULL;
-       struct page *enc_extent_page;
+       char *enc_extent_virt;
+       struct page *enc_extent_page = NULL;
        loff_t extent_offset;
        int rc = 0;
 
@@ -491,14 +492,14 @@ int ecryptfs_encrypt_page(struct page *page)
                               page->index);
                goto out;
        }
-       enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
-       if (!enc_extent_virt) {
+       enc_extent_page = alloc_page(GFP_USER);
+       if (!enc_extent_page) {
                rc = -ENOMEM;
                ecryptfs_printk(KERN_ERR, "Error allocating memory for "
                                "encrypted extent\n");
                goto out;
        }
-       enc_extent_page = virt_to_page(enc_extent_virt);
+       enc_extent_virt = kmap(enc_extent_page);
        for (extent_offset = 0;
             extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
             extent_offset++) {
@@ -526,7 +527,10 @@ int ecryptfs_encrypt_page(struct page *page)
                }
        }
 out:
-       kfree(enc_extent_virt);
+       if (enc_extent_page) {
+               kunmap(enc_extent_page);
+               __free_page(enc_extent_page);
+       }
        return rc;
 }
 
@@ -608,8 +612,8 @@ int ecryptfs_decrypt_page(struct page *page)
 {
        struct inode *ecryptfs_inode;
        struct ecryptfs_crypt_stat *crypt_stat;
-       char *enc_extent_virt = NULL;
-       struct page *enc_extent_page;
+       char *enc_extent_virt;
+       struct page *enc_extent_page = NULL;
        unsigned long extent_offset;
        int rc = 0;
 
@@ -626,14 +630,14 @@ int ecryptfs_decrypt_page(struct page *page)
                               page->index);
                goto out;
        }
-       enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
-       if (!enc_extent_virt) {
+       enc_extent_page = alloc_page(GFP_USER);
+       if (!enc_extent_page) {
                rc = -ENOMEM;
                ecryptfs_printk(KERN_ERR, "Error allocating memory for "
                                "encrypted extent\n");
                goto out;
        }
-       enc_extent_page = virt_to_page(enc_extent_virt);
+       enc_extent_virt = kmap(enc_extent_page);
        for (extent_offset = 0;
             extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
             extent_offset++) {
@@ -661,7 +665,10 @@ int ecryptfs_decrypt_page(struct page *page)
                }
        }
 out:
-       kfree(enc_extent_virt);
+       if (enc_extent_page) {
+               kunmap(enc_extent_page);
+               __free_page(enc_extent_page);
+       }
        return rc;
 }
 
@@ -1032,10 +1039,8 @@ static int contains_ecryptfs_marker(char *data)
 {
        u32 m_1, m_2;
 
-       memcpy(&m_1, data, 4);
-       m_1 = be32_to_cpu(m_1);
-       memcpy(&m_2, (data + 4), 4);
-       m_2 = be32_to_cpu(m_2);
+       m_1 = get_unaligned_be32(data);
+       m_2 = get_unaligned_be32(data + 4);
        if ((m_1 ^ MAGIC_ECRYPTFS_MARKER) == m_2)
                return 1;
        ecryptfs_printk(KERN_DEBUG, "m_1 = [0x%.8x]; m_2 = [0x%.8x]; "
@@ -1073,8 +1078,7 @@ static int ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat,
        int i;
        u32 flags;
 
-       memcpy(&flags, page_virt, 4);
-       flags = be32_to_cpu(flags);
+       flags = get_unaligned_be32(page_virt);
        for (i = 0; i < ((sizeof(ecryptfs_flag_map)
                          / sizeof(struct ecryptfs_flag_map_elem))); i++)
                if (flags & ecryptfs_flag_map[i].file_flag) {
@@ -1100,11 +1104,9 @@ static void write_ecryptfs_marker(char *page_virt, size_t *written)
 
        get_random_bytes(&m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));
        m_2 = (m_1 ^ MAGIC_ECRYPTFS_MARKER);
-       m_1 = cpu_to_be32(m_1);
-       memcpy(page_virt, &m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));
-       m_2 = cpu_to_be32(m_2);
-       memcpy(page_virt + (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2), &m_2,
-              (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));
+       put_unaligned_be32(m_1, page_virt);
+       page_virt += (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2);
+       put_unaligned_be32(m_2, page_virt);
        (*written) = MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
 }
 
@@ -1121,8 +1123,7 @@ write_ecryptfs_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat,
                        flags |= ecryptfs_flag_map[i].file_flag;
        /* Version is in top 8 bits of the 32-bit flag vector */
        flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000);
-       flags = cpu_to_be32(flags);
-       memcpy(page_virt, &flags, 4);
+       put_unaligned_be32(flags, page_virt);
        (*written) = 4;
 }
 
@@ -1238,11 +1239,9 @@ ecryptfs_write_header_metadata(char *virt,
        num_header_extents_at_front =
                (u16)(crypt_stat->num_header_bytes_at_front
                      / crypt_stat->extent_size);
-       header_extent_size = cpu_to_be32(header_extent_size);
-       memcpy(virt, &header_extent_size, 4);
+       put_unaligned_be32(header_extent_size, virt);
        virt += 4;
-       num_header_extents_at_front = cpu_to_be16(num_header_extents_at_front);
-       memcpy(virt, &num_header_extents_at_front, 2);
+       put_unaligned_be16(num_header_extents_at_front, virt);
        (*written) = 6;
 }
 
@@ -1410,15 +1409,13 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
        u32 header_extent_size;
        u16 num_header_extents_at_front;
 
-       memcpy(&header_extent_size, virt, sizeof(u32));
-       header_extent_size = be32_to_cpu(header_extent_size);
-       virt += sizeof(u32);
-       memcpy(&num_header_extents_at_front, virt, sizeof(u16));
-       num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front);
+       header_extent_size = get_unaligned_be32(virt);
+       virt += sizeof(__be32);
+       num_header_extents_at_front = get_unaligned_be16(virt);
        crypt_stat->num_header_bytes_at_front =
                (((size_t)num_header_extents_at_front
                  * (size_t)header_extent_size));
-       (*bytes_read) = (sizeof(u32) + sizeof(u16));
+       (*bytes_read) = (sizeof(__be32) + sizeof(__be16));
        if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
            && (crypt_stat->num_header_bytes_at_front
                < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
index c15c25745e05d4ff5cac6e2595e6039858dff693..b73fb752c5f8e9294ce232f4459efa26a79feed4 100644 (file)
@@ -559,10 +559,25 @@ extern struct kmem_cache *ecryptfs_key_record_cache;
 extern struct kmem_cache *ecryptfs_key_sig_cache;
 extern struct kmem_cache *ecryptfs_global_auth_tok_cache;
 extern struct kmem_cache *ecryptfs_key_tfm_cache;
+extern struct kmem_cache *ecryptfs_open_req_cache;
 
+struct ecryptfs_open_req {
+#define ECRYPTFS_REQ_PROCESSED 0x00000001
+#define ECRYPTFS_REQ_DROPPED   0x00000002
+#define ECRYPTFS_REQ_ZOMBIE    0x00000004
+       u32 flags;
+       struct file **lower_file;
+       struct dentry *lower_dentry;
+       struct vfsmount *lower_mnt;
+       wait_queue_head_t wait;
+       struct mutex mux;
+       struct list_head kthread_ctl_list;
+};
+
+#define ECRYPTFS_INTERPOSE_FLAG_D_ADD                 0x00000001
 int ecryptfs_interpose(struct dentry *hidden_dentry,
                       struct dentry *this_dentry, struct super_block *sb,
-                      int flag);
+                      u32 flags);
 int ecryptfs_fill_zeros(struct file *file, loff_t new_length);
 int ecryptfs_decode_filename(struct ecryptfs_crypt_stat *crypt_stat,
                             const char *name, int length,
@@ -690,5 +705,11 @@ void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx);
 int
 ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid,
                      struct user_namespace *user_ns, struct pid *pid);
+int ecryptfs_init_kthread(void);
+void ecryptfs_destroy_kthread(void);
+int ecryptfs_privileged_open(struct file **lower_file,
+                            struct dentry *lower_dentry,
+                            struct vfsmount *lower_mnt);
+int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
index 24749bf0668f0c8d82a887e2b857c347a86a40f5..9244d653743ec02c6d279071095f76c08c834dd6 100644 (file)
@@ -192,6 +192,23 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                                      | ECRYPTFS_ENCRYPTED);
        }
        mutex_unlock(&crypt_stat->cs_mutex);
+       if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY)
+           && !(file->f_flags & O_RDONLY)) {
+               rc = -EPERM;
+               printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
+                      "file must hence be opened RO\n", __func__);
+               goto out;
+       }
+       if (!ecryptfs_inode_to_private(inode)->lower_file) {
+               rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+               if (rc) {
+                       printk(KERN_ERR "%s: Error attempting to initialize "
+                              "the persistent file for the dentry with name "
+                              "[%s]; rc = [%d]\n", __func__,
+                              ecryptfs_dentry->d_name.name, rc);
+                       goto out;
+               }
+       }
        ecryptfs_set_file_lower(
                file, ecryptfs_inode_to_private(inode)->lower_file);
        if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
index c92cc1c00aae9a845911011f091480d9cbe4ffca..89209f00f9c74ecc752ed944f26ecff6e2f5c974 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/mount.h>
 #include <linux/crypto.h>
 #include <linux/fs_stack.h>
+#include <asm/unaligned.h>
 #include "ecryptfs_kernel.h"
 
 static struct dentry *lock_parent(struct dentry *dentry)
@@ -188,6 +189,16 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
                                "context; rc = [%d]\n", rc);
                goto out;
        }
+       if (!ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->lower_file) {
+               rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+               if (rc) {
+                       printk(KERN_ERR "%s: Error attempting to initialize "
+                              "the persistent file for the dentry with name "
+                              "[%s]; rc = [%d]\n", __func__,
+                              ecryptfs_dentry->d_name.name, rc);
+                       goto out;
+               }
+       }
        rc = ecryptfs_write_metadata(ecryptfs_dentry);
        if (rc) {
                printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
@@ -307,10 +318,11 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
                d_add(dentry, NULL);
                goto out;
        }
-       rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 1);
+       rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb,
+                               ECRYPTFS_INTERPOSE_FLAG_D_ADD);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error interposing\n");
-               goto out_dput;
+               goto out;
        }
        if (S_ISDIR(lower_inode->i_mode)) {
                ecryptfs_printk(KERN_DEBUG, "Is a directory; returning\n");
@@ -336,11 +348,21 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
                rc = -ENOMEM;
                ecryptfs_printk(KERN_ERR,
                                "Cannot ecryptfs_kmalloc a page\n");
-               goto out_dput;
+               goto out;
        }
        crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
        if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
                ecryptfs_set_default_sizes(crypt_stat);
+       if (!ecryptfs_inode_to_private(dentry->d_inode)->lower_file) {
+               rc = ecryptfs_init_persistent_file(dentry);
+               if (rc) {
+                       printk(KERN_ERR "%s: Error attempting to initialize "
+                              "the persistent file for the dentry with name "
+                              "[%s]; rc = [%d]\n", __func__,
+                              dentry->d_name.name, rc);
+                       goto out;
+               }
+       }
        rc = ecryptfs_read_and_validate_header_region(page_virt,
                                                      dentry->d_inode);
        if (rc) {
@@ -364,8 +386,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
                else
                        file_size = i_size_read(lower_dentry->d_inode);
        } else {
-               memcpy(&file_size, page_virt, sizeof(file_size));
-               file_size = be64_to_cpu(file_size);
+               file_size = get_unaligned_be64(page_virt);
        }
        i_size_write(dentry->d_inode, (loff_t)file_size);
        kmem_cache_free(ecryptfs_header_cache_2, page_virt);
@@ -444,7 +465,6 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
        int rc;
        struct dentry *lower_dentry;
        struct dentry *lower_dir_dentry;
-       umode_t mode;
        char *encoded_symname;
        int encoded_symlen;
        struct ecryptfs_crypt_stat *crypt_stat = NULL;
@@ -452,7 +472,6 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        dget(lower_dentry);
        lower_dir_dentry = lock_parent(lower_dentry);
-       mode = S_IALLUGO;
        encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
                                                  strlen(symname),
                                                  &encoded_symname);
@@ -461,7 +480,7 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
                goto out_lock;
        }
        rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
-                        encoded_symname, mode);
+                        encoded_symname);
        kfree(encoded_symname);
        if (rc || !lower_dentry->d_inode)
                goto out_lock;
@@ -809,22 +828,9 @@ out:
 }
 
 static int
-ecryptfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+ecryptfs_permission(struct inode *inode, int mask)
 {
-       int rc;
-
-        if (nd) {
-               struct vfsmount *vfsmnt_save = nd->path.mnt;
-               struct dentry *dentry_save = nd->path.dentry;
-
-               nd->path.mnt = ecryptfs_dentry_to_lower_mnt(nd->path.dentry);
-               nd->path.dentry = ecryptfs_dentry_to_lower(nd->path.dentry);
-               rc = permission(ecryptfs_inode_to_lower(inode), mask, nd);
-               nd->path.mnt = vfsmnt_save;
-               nd->path.dentry = dentry_save;
-        } else
-               rc = permission(ecryptfs_inode_to_lower(inode), mask, NULL);
-        return rc;
+       return inode_permission(ecryptfs_inode_to_lower(inode), mask);
 }
 
 /**
index e82b457180be78706e4b829c4dec0ea15db82178..f5b76a331b9c743a3679ae69022f288c60b0f229 100644 (file)
@@ -44,15 +44,15 @@ static int process_request_key_err(long err_code)
        int rc = 0;
 
        switch (err_code) {
-       case ENOKEY:
+       case -ENOKEY:
                ecryptfs_printk(KERN_WARNING, "No key\n");
                rc = -ENOENT;
                break;
-       case EKEYEXPIRED:
+       case -EKEYEXPIRED:
                ecryptfs_printk(KERN_WARNING, "Key expired\n");
                rc = -ETIME;
                break;
-       case EKEYREVOKED:
+       case -EKEYREVOKED:
                ecryptfs_printk(KERN_WARNING, "Key revoked\n");
                rc = -EINVAL;
                break;
@@ -963,8 +963,7 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
        if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) {
                printk(KERN_ERR "Could not find key with description: [%s]\n",
                       sig);
-               process_request_key_err(PTR_ERR(*auth_tok_key));
-               rc = -EINVAL;
+               rc = process_request_key_err(PTR_ERR(*auth_tok_key));
                goto out;
        }
        (*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key);
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
new file mode 100644 (file)
index 0000000..c440c6b
--- /dev/null
@@ -0,0 +1,203 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2008 International Business Machines Corp.
+ *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the 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/kthread.h>
+#include <linux/freezer.h>
+#include <linux/wait.h>
+#include <linux/mount.h>
+#include "ecryptfs_kernel.h"
+
+struct kmem_cache *ecryptfs_open_req_cache;
+
+static struct ecryptfs_kthread_ctl {
+#define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
+       u32 flags;
+       struct mutex mux;
+       struct list_head req_list;
+       wait_queue_head_t wait;
+} ecryptfs_kthread_ctl;
+
+static struct task_struct *ecryptfs_kthread;
+
+/**
+ * ecryptfs_threadfn
+ * @ignored: ignored
+ *
+ * The eCryptfs kernel thread that has the responsibility of getting
+ * the lower persistent file with RW permissions.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int ecryptfs_threadfn(void *ignored)
+{
+       set_freezable();
+       while (1)  {
+               struct ecryptfs_open_req *req;
+
+               wait_event_freezable(
+                       ecryptfs_kthread_ctl.wait,
+                       (!list_empty(&ecryptfs_kthread_ctl.req_list)
+                        || kthread_should_stop()));
+               mutex_lock(&ecryptfs_kthread_ctl.mux);
+               if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
+                       mutex_unlock(&ecryptfs_kthread_ctl.mux);
+                       goto out;
+               }
+               while (!list_empty(&ecryptfs_kthread_ctl.req_list)) {
+                       req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
+                                              struct ecryptfs_open_req,
+                                              kthread_ctl_list);
+                       mutex_lock(&req->mux);
+                       list_del(&req->kthread_ctl_list);
+                       if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) {
+                               dget(req->lower_dentry);
+                               mntget(req->lower_mnt);
+                               (*req->lower_file) = dentry_open(
+                                       req->lower_dentry, req->lower_mnt,
+                                       (O_RDWR | O_LARGEFILE));
+                               req->flags |= ECRYPTFS_REQ_PROCESSED;
+                       }
+                       wake_up(&req->wait);
+                       mutex_unlock(&req->mux);
+               }
+               mutex_unlock(&ecryptfs_kthread_ctl.mux);
+       }
+out:
+       return 0;
+}
+
+int ecryptfs_init_kthread(void)
+{
+       int rc = 0;
+
+       mutex_init(&ecryptfs_kthread_ctl.mux);
+       init_waitqueue_head(&ecryptfs_kthread_ctl.wait);
+       INIT_LIST_HEAD(&ecryptfs_kthread_ctl.req_list);
+       ecryptfs_kthread = kthread_run(&ecryptfs_threadfn, NULL,
+                                      "ecryptfs-kthread");
+       if (IS_ERR(ecryptfs_kthread)) {
+               rc = PTR_ERR(ecryptfs_kthread);
+               printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]"
+                      "\n", __func__, rc);
+       }
+       return rc;
+}
+
+void ecryptfs_destroy_kthread(void)
+{
+       struct ecryptfs_open_req *req;
+
+       mutex_lock(&ecryptfs_kthread_ctl.mux);
+       ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
+       list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list,
+                           kthread_ctl_list) {
+               mutex_lock(&req->mux);
+               req->flags |= ECRYPTFS_REQ_ZOMBIE;
+               wake_up(&req->wait);
+               mutex_unlock(&req->mux);
+       }
+       mutex_unlock(&ecryptfs_kthread_ctl.mux);
+       kthread_stop(ecryptfs_kthread);
+       wake_up(&ecryptfs_kthread_ctl.wait);
+}
+
+/**
+ * ecryptfs_privileged_open
+ * @lower_file: Result of dentry_open by root on lower dentry
+ * @lower_dentry: Lower dentry for file to open
+ * @lower_mnt: Lower vfsmount for file to open
+ *
+ * This function gets a r/w file opened againt the lower dentry.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_privileged_open(struct file **lower_file,
+                            struct dentry *lower_dentry,
+                            struct vfsmount *lower_mnt)
+{
+       struct ecryptfs_open_req *req;
+       int rc = 0;
+
+       /* Corresponding dput() and mntput() are done when the
+        * persistent file is fput() when the eCryptfs inode is
+        * destroyed. */
+       dget(lower_dentry);
+       mntget(lower_mnt);
+       (*lower_file) = dentry_open(lower_dentry, lower_mnt,
+                                   (O_RDWR | O_LARGEFILE));
+       if (!IS_ERR(*lower_file))
+               goto out;
+       req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
+       if (!req) {
+               rc = -ENOMEM;
+               goto out;
+       }
+       mutex_init(&req->mux);
+       req->lower_file = lower_file;
+       req->lower_dentry = lower_dentry;
+       req->lower_mnt = lower_mnt;
+       init_waitqueue_head(&req->wait);
+       req->flags = 0;
+       mutex_lock(&ecryptfs_kthread_ctl.mux);
+       if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
+               rc = -EIO;
+               mutex_unlock(&ecryptfs_kthread_ctl.mux);
+               printk(KERN_ERR "%s: We are in the middle of shutting down; "
+                      "aborting privileged request to open lower file\n",
+                       __func__);
+               goto out_free;
+       }
+       list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
+       mutex_unlock(&ecryptfs_kthread_ctl.mux);
+       wake_up(&ecryptfs_kthread_ctl.wait);
+       wait_event(req->wait, (req->flags != 0));
+       mutex_lock(&req->mux);
+       BUG_ON(req->flags == 0);
+       if (req->flags & ECRYPTFS_REQ_DROPPED
+           || req->flags & ECRYPTFS_REQ_ZOMBIE) {
+               rc = -EIO;
+               printk(KERN_WARNING "%s: Privileged open request dropped\n",
+                      __func__);
+               goto out_unlock;
+       }
+       if (IS_ERR(*req->lower_file)) {
+               rc = PTR_ERR(*req->lower_file);
+               dget(lower_dentry);
+               mntget(lower_mnt);
+               (*lower_file) = dentry_open(lower_dentry, lower_mnt,
+                                           (O_RDONLY | O_LARGEFILE));
+               if (IS_ERR(*lower_file)) {
+                       rc = PTR_ERR(*req->lower_file);
+                       (*lower_file) = NULL;
+                       printk(KERN_WARNING "%s: Error attempting privileged "
+                              "open of lower file with either RW or RO "
+                              "perms; rc = [%d]. Giving up.\n",
+                              __func__, rc);
+               }
+       }
+out_unlock:
+       mutex_unlock(&req->mux);
+out_free:
+       kmem_cache_free(ecryptfs_open_req_cache, req);
+out:
+       return rc;
+}
index d603631601ebdd364d619b18efdcbafec8b4ac91..448dfd597b5f5d696a480bd33148873317598b84 100644 (file)
@@ -117,7 +117,7 @@ void __ecryptfs_printk(const char *fmt, ...)
  *
  * Returns zero on success; non-zero otherwise
  */
-static int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
+int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
 {
        struct ecryptfs_inode_info *inode_info =
                ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
@@ -130,26 +130,12 @@ static int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
                        ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
 
                lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
-               /* Corresponding dput() and mntput() are done when the
-                * persistent file is fput() when the eCryptfs inode
-                * is destroyed. */
-               dget(lower_dentry);
-               mntget(lower_mnt);
-               inode_info->lower_file = dentry_open(lower_dentry,
-                                                    lower_mnt,
-                                                    (O_RDWR | O_LARGEFILE));
-               if (IS_ERR(inode_info->lower_file)) {
-                       dget(lower_dentry);
-                       mntget(lower_mnt);
-                       inode_info->lower_file = dentry_open(lower_dentry,
-                                                            lower_mnt,
-                                                            (O_RDONLY
-                                                             | O_LARGEFILE));
-               }
-               if (IS_ERR(inode_info->lower_file)) {
+               rc = ecryptfs_privileged_open(&inode_info->lower_file,
+                                                    lower_dentry, lower_mnt);
+               if (rc || IS_ERR(inode_info->lower_file)) {
                        printk(KERN_ERR "Error opening lower persistent file "
-                              "for lower_dentry [0x%p] and lower_mnt [0x%p]\n",
-                              lower_dentry, lower_mnt);
+                              "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
+                              "rc = [%d]\n", lower_dentry, lower_mnt, rc);
                        rc = PTR_ERR(inode_info->lower_file);
                        inode_info->lower_file = NULL;
                }
@@ -163,14 +149,14 @@ static int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
  * @lower_dentry: Existing dentry in the lower filesystem
  * @dentry: ecryptfs' dentry
  * @sb: ecryptfs's super_block
- * @flag: If set to true, then d_add is called, else d_instantiate is called
+ * @flags: flags to govern behavior of interpose procedure
  *
  * Interposes upper and lower dentries.
  *
  * Returns zero on success; non-zero otherwise
  */
 int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
-                      struct super_block *sb, int flag)
+                      struct super_block *sb, u32 flags)
 {
        struct inode *lower_inode;
        struct inode *inode;
@@ -207,7 +193,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
                init_special_inode(inode, lower_inode->i_mode,
                                   lower_inode->i_rdev);
        dentry->d_op = &ecryptfs_dops;
-       if (flag)
+       if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD)
                d_add(dentry, inode);
        else
                d_instantiate(dentry, inode);
@@ -215,13 +201,6 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
        /* This size will be overwritten for real files w/ headers and
         * other metadata */
        fsstack_copy_inode_size(inode, lower_inode);
-       rc = ecryptfs_init_persistent_file(dentry);
-       if (rc) {
-               printk(KERN_ERR "%s: Error attempting to initialize the "
-                      "persistent file for the dentry with name [%s]; "
-                      "rc = [%d]\n", __func__, dentry->d_name.name, rc);
-               goto out;
-       }
 out:
        return rc;
 }
@@ -262,10 +241,11 @@ static int ecryptfs_init_global_auth_toks(
                               "session keyring for sig specified in mount "
                               "option: [%s]\n", global_auth_tok->sig);
                        global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID;
-                       rc = 0;
+                       goto out;
                } else
                        global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID;
        }
+out:
        return rc;
 }
 
@@ -314,7 +294,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
        char *cipher_name_dst;
        char *cipher_name_src;
        char *cipher_key_bytes_src;
-       int cipher_name_len;
 
        if (!options) {
                rc = -EINVAL;
@@ -395,17 +374,12 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
                goto out;
        }
        if (!cipher_name_set) {
-               cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER);
-               if (unlikely(cipher_name_len
-                            >= ECRYPTFS_MAX_CIPHER_NAME_SIZE)) {
-                       rc = -EINVAL;
-                       BUG();
-                       goto out;
-               }
-               memcpy(mount_crypt_stat->global_default_cipher_name,
-                      ECRYPTFS_DEFAULT_CIPHER, cipher_name_len);
-               mount_crypt_stat->global_default_cipher_name[cipher_name_len]
-                   = '\0';
+               int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER);
+
+               BUG_ON(cipher_name_len >= ECRYPTFS_MAX_CIPHER_NAME_SIZE);
+
+               strcpy(mount_crypt_stat->global_default_cipher_name,
+                      ECRYPTFS_DEFAULT_CIPHER);
        }
        if (!cipher_key_bytes_set) {
                mount_crypt_stat->global_default_cipher_key_size = 0;
@@ -430,7 +404,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
                printk(KERN_WARNING "One or more global auth toks could not "
                       "properly register; rc = [%d]\n", rc);
        }
-       rc = 0;
 out:
        return rc;
 }
@@ -605,7 +578,7 @@ static struct file_system_type ecryptfs_fs_type = {
  * Initializes the ecryptfs_inode_info_cache when it is created
  */
 static void
-inode_info_init_once(struct kmem_cache *cachep, void *vptr)
+inode_info_init_once(void *vptr)
 {
        struct ecryptfs_inode_info *ei = (struct ecryptfs_inode_info *)vptr;
 
@@ -616,7 +589,7 @@ static struct ecryptfs_cache_info {
        struct kmem_cache **cache;
        const char *name;
        size_t size;
-       void (*ctor)(struct kmem_cache *cache, void *obj);
+       void (*ctor)(void *obj);
 } ecryptfs_cache_infos[] = {
        {
                .cache = &ecryptfs_auth_tok_list_item_cache,
@@ -679,6 +652,11 @@ static struct ecryptfs_cache_info {
                .name = "ecryptfs_key_tfm_cache",
                .size = sizeof(struct ecryptfs_key_tfm),
        },
+       {
+               .cache = &ecryptfs_open_req_cache,
+               .name = "ecryptfs_open_req_cache",
+               .size = sizeof(struct ecryptfs_open_req),
+       },
 };
 
 static void ecryptfs_free_kmem_caches(void)
@@ -795,11 +773,17 @@ static int __init ecryptfs_init(void)
                printk(KERN_ERR "sysfs registration failed\n");
                goto out_unregister_filesystem;
        }
+       rc = ecryptfs_init_kthread();
+       if (rc) {
+               printk(KERN_ERR "%s: kthread initialization failed; "
+                      "rc = [%d]\n", __func__, rc);
+               goto out_do_sysfs_unregistration;
+       }
        rc = ecryptfs_init_messaging(ecryptfs_transport);
        if (rc) {
-               ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
+               printk(KERN_ERR "Failure occured while attempting to "
                                "initialize the eCryptfs netlink socket\n");
-               goto out_do_sysfs_unregistration;
+               goto out_destroy_kthread;
        }
        rc = ecryptfs_init_crypto();
        if (rc) {
@@ -814,6 +798,8 @@ static int __init ecryptfs_init(void)
        goto out;
 out_release_messaging:
        ecryptfs_release_messaging(ecryptfs_transport);
+out_destroy_kthread:
+       ecryptfs_destroy_kthread();
 out_do_sysfs_unregistration:
        do_sysfs_unregistration();
 out_unregister_filesystem:
@@ -833,6 +819,7 @@ static void __exit ecryptfs_exit(void)
                printk(KERN_ERR "Failure whilst attempting to destroy crypto; "
                       "rc = [%d]\n", rc);
        ecryptfs_release_messaging(ecryptfs_transport);
+       ecryptfs_destroy_kthread();
        do_sysfs_unregistration();
        unregister_filesystem(&ecryptfs_fs_type);
        ecryptfs_free_kmem_caches();
index 09a4522f65e6c26311bd896b515b20faf516a025..b484792a0996c0623b08f054f86c06214da47b3f 100644 (file)
@@ -357,46 +357,6 @@ out_unlock_daemon:
        return rc;
 }
 
-/**
- * ecryptfs_miscdev_helo
- * @euid: effective user id of miscdevess sending helo packet
- * @user_ns: The namespace in which @euid applies
- * @pid: miscdevess id of miscdevess sending helo packet
- *
- * Returns zero on success; non-zero otherwise
- */
-static int ecryptfs_miscdev_helo(uid_t euid, struct user_namespace *user_ns,
-                                struct pid *pid)
-{
-       int rc;
-
-       rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_MISCDEV, euid, user_ns,
-                                  pid);
-       if (rc)
-               printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
-       return rc;
-}
-
-/**
- * ecryptfs_miscdev_quit
- * @euid: effective user id of miscdevess sending quit packet
- * @user_ns: The namespace in which @euid applies
- * @pid: miscdevess id of miscdevess sending quit packet
- *
- * Returns zero on success; non-zero otherwise
- */
-static int ecryptfs_miscdev_quit(uid_t euid, struct user_namespace *user_ns,
-                                struct pid *pid)
-{
-       int rc;
-
-       rc = ecryptfs_process_quit(euid, user_ns, pid);
-       if (rc)
-               printk(KERN_WARNING
-                      "Error processing QUIT message; rc = [%d]\n", rc);
-       return rc;
-}
-
 /**
  * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon
  * @data: Bytes comprising struct ecryptfs_message
@@ -512,26 +472,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
                               __func__, rc);
                break;
        case ECRYPTFS_MSG_HELO:
-               rc = ecryptfs_miscdev_helo(current->euid,
-                                          current->nsproxy->user_ns,
-                                          task_pid(current));
-               if (rc) {
-                       printk(KERN_ERR "%s: Error attempting to process "
-                              "helo from pid [0x%p]; rc = [%d]\n", __func__,
-                              task_pid(current), rc);
-                       goto out_free;
-               }
-               break;
        case ECRYPTFS_MSG_QUIT:
-               rc = ecryptfs_miscdev_quit(current->euid,
-                                          current->nsproxy->user_ns,
-                                          task_pid(current));
-               if (rc) {
-                       printk(KERN_ERR "%s: Error attempting to process "
-                              "quit from pid [0x%p]; rc = [%d]\n", __func__,
-                              task_pid(current), rc);
-                       goto out_free;
-               }
                break;
        default:
                ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
index 2b6fe1e6e8ba38d85f5e6b16e63bd8d55804a35a..245c2dc02d5cfa96d1fe60818ae849555ef5e991 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/file.h>
 #include <linux/crypto.h>
 #include <linux/scatterlist.h>
+#include <asm/unaligned.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -372,7 +373,6 @@ out:
  */
 static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
 {
-       u64 file_size;
        char *file_size_virt;
        int rc;
 
@@ -381,9 +381,7 @@ static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
                rc = -ENOMEM;
                goto out;
        }
-       file_size = (u64)i_size_read(ecryptfs_inode);
-       file_size = cpu_to_be64(file_size);
-       memcpy(file_size_virt, &file_size, sizeof(u64));
+       put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt);
        rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
                                  sizeof(u64));
        kfree(file_size_virt);
@@ -403,7 +401,6 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
        struct dentry *lower_dentry =
                ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry;
        struct inode *lower_inode = lower_dentry->d_inode;
-       u64 file_size;
        int rc;
 
        if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
@@ -424,9 +421,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
                                           xattr_virt, PAGE_CACHE_SIZE);
        if (size < 0)
                size = 8;
-       file_size = (u64)i_size_read(ecryptfs_inode);
-       file_size = cpu_to_be64(file_size);
-       memcpy(xattr_virt, &file_size, sizeof(u64));
+       put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
        rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
                                         xattr_virt, size, 0);
        mutex_unlock(&lower_inode->i_mutex);
index d733531b55e2653bff6d49bef4a7f62dafb0340c..567b134fa1f156f1c886e488771fbcb06ab61089 100644 (file)
@@ -70,7 +70,7 @@ static void efs_destroy_inode(struct inode *inode)
        kmem_cache_free(efs_inode_cachep, INODE_INFO(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct efs_inode_info *ei = (struct efs_inode_info *) foo;
 
index 343942deeec138b1925e7815d0ac819e41f1214e..08bf558d04080ffe0a3ced77a5660d4af4e1182f 100644 (file)
@@ -198,11 +198,18 @@ struct file *eventfd_fget(int fd)
        return file;
 }
 
-asmlinkage long sys_eventfd(unsigned int count)
+asmlinkage long sys_eventfd2(unsigned int count, int flags)
 {
        int fd;
        struct eventfd_ctx *ctx;
 
+       /* Check the EFD_* constants for consistency.  */
+       BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC);
+       BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK);
+
+       if (flags & ~(EFD_CLOEXEC | EFD_NONBLOCK))
+               return -EINVAL;
+
        ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
@@ -214,9 +221,15 @@ asmlinkage long sys_eventfd(unsigned int count)
         * When we call this, the initialization must be complete, since
         * anon_inode_getfd() will install the fd.
         */
-       fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx);
+       fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx,
+                             flags & (O_CLOEXEC | O_NONBLOCK));
        if (fd < 0)
                kfree(ctx);
        return fd;
 }
 
+asmlinkage long sys_eventfd(unsigned int count)
+{
+       return sys_eventfd2(count, 0);
+}
+
index 990c01d2d66bcce64a1c2a993cd6cc01ea5951d5..0c87474f7917776d92fb1427c93f118535ef624f 100644 (file)
@@ -1046,20 +1046,25 @@ retry:
  * RB tree. With the current implementation, the "size" parameter is ignored
  * (besides sanity checks).
  */
-asmlinkage long sys_epoll_create(int size)
+asmlinkage long sys_epoll_create1(int flags)
 {
        int error, fd = -1;
        struct eventpoll *ep;
 
+       /* Check the EPOLL_* constant for consistency.  */
+       BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC);
+
+       if (flags & ~EPOLL_CLOEXEC)
+               return -EINVAL;
+
        DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
-                    current, size));
+                    current, flags));
 
        /*
-        * Sanity check on the size parameter, and create the internal data
-        * structure ( "struct eventpoll" ).
+        * Create the internal data structure ( "struct eventpoll" ).
         */
-       error = -EINVAL;
-       if (size <= 0 || (error = ep_alloc(&ep)) < 0) {
+       error = ep_alloc(&ep);
+       if (error < 0) {
                fd = error;
                goto error_return;
        }
@@ -1068,17 +1073,26 @@ asmlinkage long sys_epoll_create(int size)
         * Creates all the items needed to setup an eventpoll file. That is,
         * a file structure and a free file descriptor.
         */
-       fd = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep);
+       fd = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
+                             flags & O_CLOEXEC);
        if (fd < 0)
                ep_free(ep);
 
 error_return:
        DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
-                    current, size, fd));
+                    current, flags, fd));
 
        return fd;
 }
 
+asmlinkage long sys_epoll_create(int size)
+{
+       if (size < 0)
+               return -EINVAL;
+
+       return sys_epoll_create1(0);
+}
+
 /*
  * The following function implements the controller interface for
  * the eventpoll file that enables the insertion/removal/change of
index fd9234379e8d2816965ff924ace687160ff0c365..32993beecbe91a10670cc4f5a9a72a5faf813c56 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
 #include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/fdtable.h>
-#include <linux/mman.h>
+#include <linux/mm.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/smp_lock.h>
+#include <linux/swap.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/pagemap.h>
 #include <linux/key.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
-#include <linux/swap.h>
 #include <linux/utsname.h>
 #include <linux/pid_namespace.h>
 #include <linux/module.h>
 #include <linux/namei.h>
 #include <linux/proc_fs.h>
-#include <linux/ptrace.h>
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
-#include <linux/rmap.h>
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
 #include <linux/audit.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -108,11 +107,17 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
  */
 asmlinkage long sys_uselib(const char __user * library)
 {
-       struct file * file;
+       struct file *file;
        struct nameidata nd;
-       int error;
-
-       error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
+       char *tmp = getname(library);
+       int error = PTR_ERR(tmp);
+
+       if (!IS_ERR(tmp)) {
+               error = path_lookup_open(AT_FDCWD, tmp,
+                                        LOOKUP_FOLLOW, &nd,
+                                        FMODE_READ|FMODE_EXEC);
+               putname(tmp);
+       }
        if (error)
                goto out;
 
@@ -120,7 +125,11 @@ asmlinkage long sys_uselib(const char __user * library)
        if (!S_ISREG(nd.path.dentry->d_inode->i_mode))
                goto exit;
 
-       error = vfs_permission(&nd, MAY_READ | MAY_EXEC);
+       error = -EACCES;
+       if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
+               goto exit;
+
+       error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN);
        if (error)
                goto exit;
 
@@ -541,7 +550,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
                /*
                 * when the old and new regions overlap clear from new_end.
                 */
-               free_pgd_range(&tlb, new_end, old_end, new_end,
+               free_pgd_range(tlb, new_end, old_end, new_end,
                        vma->vm_next ? vma->vm_next->vm_start : 0);
        } else {
                /*
@@ -550,7 +559,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
                 * have constraints on va-space that make this illegal (IA64) -
                 * for the others its just a little faster.
                 */
-               free_pgd_range(&tlb, old_start, old_end, new_end,
+               free_pgd_range(tlb, old_start, old_end, new_end,
                        vma->vm_next ? vma->vm_next->vm_start : 0);
        }
        tlb_finish_mmu(tlb, new_end, old_end);
@@ -658,38 +667,43 @@ EXPORT_SYMBOL(setup_arg_pages);
 struct file *open_exec(const char *name)
 {
        struct nameidata nd;
-       int err;
        struct file *file;
+       int err;
 
-       err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
-       file = ERR_PTR(err);
-
-       if (!err) {
-               struct inode *inode = nd.path.dentry->d_inode;
-               file = ERR_PTR(-EACCES);
-               if (S_ISREG(inode->i_mode)) {
-                       int err = vfs_permission(&nd, MAY_EXEC);
-                       file = ERR_PTR(err);
-                       if (!err) {
-                               file = nameidata_to_filp(&nd,
-                                                       O_RDONLY|O_LARGEFILE);
-                               if (!IS_ERR(file)) {
-                                       err = deny_write_access(file);
-                                       if (err) {
-                                               fput(file);
-                                               file = ERR_PTR(err);
-                                       }
-                               }
-out:
-                               return file;
-                       }
-               }
-               release_open_intent(&nd);
-               path_put(&nd.path);
+       err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd,
+                               FMODE_READ|FMODE_EXEC);
+       if (err)
+               goto out;
+
+       err = -EACCES;
+       if (!S_ISREG(nd.path.dentry->d_inode->i_mode))
+               goto out_path_put;
+
+       if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
+               goto out_path_put;
+
+       err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN);
+       if (err)
+               goto out_path_put;
+
+       file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
+       if (IS_ERR(file))
+               return file;
+
+       err = deny_write_access(file);
+       if (err) {
+               fput(file);
+               goto out;
        }
-       goto out;
-}
 
+       return file;
+
+ out_path_put:
+       release_open_intent(&nd);
+       path_put(&nd.path);
+ out:
+       return ERR_PTR(err);
+}
 EXPORT_SYMBOL(open_exec);
 
 int kernel_read(struct file *file, unsigned long offset,
@@ -724,12 +738,10 @@ static int exec_mmap(struct mm_struct *mm)
                 * Make sure that if there is a core dump in progress
                 * for the old mm, we get out and die instead of going
                 * through with the exec.  We must hold mmap_sem around
-                * checking core_waiters and changing tsk->mm.  The
-                * core-inducing thread will increment core_waiters for
-                * each thread whose ->mm == old_mm.
+                * checking core_state and changing tsk->mm.
                 */
                down_read(&old_mm->mmap_sem);
-               if (unlikely(old_mm->core_waiters)) {
+               if (unlikely(old_mm->core_state)) {
                        up_read(&old_mm->mmap_sem);
                        return -EINTR;
                }
@@ -1075,13 +1087,8 @@ EXPORT_SYMBOL(prepare_binprm);
 
 static int unsafe_exec(struct task_struct *p)
 {
-       int unsafe = 0;
-       if (p->ptrace & PT_PTRACED) {
-               if (p->ptrace & PT_PTRACE_CAP)
-                       unsafe |= LSM_UNSAFE_PTRACE_CAP;
-               else
-                       unsafe |= LSM_UNSAFE_PTRACE;
-       }
+       int unsafe = tracehook_unsafe_exec(p);
+
        if (atomic_read(&p->fs->count) > 1 ||
            atomic_read(&p->files->count) > 1 ||
            atomic_read(&p->sighand->count) > 1)
@@ -1218,6 +1225,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                        read_unlock(&binfmt_lock);
                        retval = fn(bprm, regs);
                        if (retval >= 0) {
+                               tracehook_report_exec(fmt, bprm, regs);
                                put_binfmt(fmt);
                                allow_write_access(bprm->file);
                                if (bprm->file)
@@ -1328,6 +1336,7 @@ int do_execve(char * filename,
        if (retval < 0)
                goto out;
 
+       current->flags &= ~PF_KTHREAD;
        retval = search_binary_handler(bprm,regs);
        if (retval >= 0) {
                /* execve success */
@@ -1382,17 +1391,14 @@ EXPORT_SYMBOL(set_binfmt);
  * name into corename, which must have space for at least
  * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
  */
-static int format_corename(char *corename, const char *pattern, long signr)
+static int format_corename(char *corename, int nr_threads, long signr)
 {
-       const char *pat_ptr = pattern;
+       const char *pat_ptr = core_pattern;
+       int ispipe = (*pat_ptr == '|');
        char *out_ptr = corename;
        char *const out_end = corename + CORENAME_MAX_SIZE;
        int rc;
        int pid_in_pattern = 0;
-       int ispipe = 0;
-
-       if (*pattern == '|')
-               ispipe = 1;
 
        /* Repeat as long as we have more pattern to process and more output
           space */
@@ -1493,7 +1499,7 @@ static int format_corename(char *corename, const char *pattern, long signr)
         * and core_uses_pid is set, then .%pid will be appended to
         * the filename. Do not do this for piped commands. */
        if (!ispipe && !pid_in_pattern
-            && (core_uses_pid || atomic_read(&current->mm->mm_users) != 1)) {
+           && (core_uses_pid || nr_threads)) {
                rc = snprintf(out_ptr, out_end - out_ptr,
                              ".%d", task_tgid_vnr(current));
                if (rc > out_end - out_ptr)
@@ -1505,9 +1511,10 @@ out:
        return ispipe;
 }
 
-static void zap_process(struct task_struct *start)
+static int zap_process(struct task_struct *start)
 {
        struct task_struct *t;
+       int nr = 0;
 
        start->signal->flags = SIGNAL_GROUP_EXIT;
        start->signal->group_stop_count = 0;
@@ -1515,72 +1522,99 @@ static void zap_process(struct task_struct *start)
        t = start;
        do {
                if (t != current && t->mm) {
-                       t->mm->core_waiters++;
                        sigaddset(&t->pending.signal, SIGKILL);
                        signal_wake_up(t, 1);
+                       nr++;
                }
-       } while ((t = next_thread(t)) != start);
+       } while_each_thread(start, t);
+
+       return nr;
 }
 
 static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
-                               int exit_code)
+                               struct core_state *core_state, int exit_code)
 {
        struct task_struct *g, *p;
        unsigned long flags;
-       int err = -EAGAIN;
+       int nr = -EAGAIN;
 
        spin_lock_irq(&tsk->sighand->siglock);
        if (!signal_group_exit(tsk->signal)) {
+               mm->core_state = core_state;
                tsk->signal->group_exit_code = exit_code;
-               zap_process(tsk);
-               err = 0;
+               nr = zap_process(tsk);
        }
        spin_unlock_irq(&tsk->sighand->siglock);
-       if (err)
-               return err;
+       if (unlikely(nr < 0))
+               return nr;
 
-       if (atomic_read(&mm->mm_users) == mm->core_waiters + 1)
+       if (atomic_read(&mm->mm_users) == nr + 1)
                goto done;
-
+       /*
+        * We should find and kill all tasks which use this mm, and we should
+        * count them correctly into ->nr_threads. We don't take tasklist
+        * lock, but this is safe wrt:
+        *
+        * fork:
+        *      None of sub-threads can fork after zap_process(leader). All
+        *      processes which were created before this point should be
+        *      visible to zap_threads() because copy_process() adds the new
+        *      process to the tail of init_task.tasks list, and lock/unlock
+        *      of ->siglock provides a memory barrier.
+        *
+        * do_exit:
+        *      The caller holds mm->mmap_sem. This means that the task which
+        *      uses this mm can't pass exit_mm(), so it can't exit or clear
+        *      its ->mm.
+        *
+        * de_thread:
+        *      It does list_replace_rcu(&leader->tasks, &current->tasks),
+        *      we must see either old or new leader, this does not matter.
+        *      However, it can change p->sighand, so lock_task_sighand(p)
+        *      must be used. Since p->mm != NULL and we hold ->mmap_sem
+        *      it can't fail.
+        *
+        *      Note also that "g" can be the old leader with ->mm == NULL
+        *      and already unhashed and thus removed from ->thread_group.
+        *      This is OK, __unhash_process()->list_del_rcu() does not
+        *      clear the ->next pointer, we will find the new leader via
+        *      next_thread().
+        */
        rcu_read_lock();
        for_each_process(g) {
                if (g == tsk->group_leader)
                        continue;
-
+               if (g->flags & PF_KTHREAD)
+                       continue;
                p = g;
                do {
                        if (p->mm) {
-                               if (p->mm == mm) {
-                                       /*
-                                        * p->sighand can't disappear, but
-                                        * may be changed by de_thread()
-                                        */
+                               if (unlikely(p->mm == mm)) {
                                        lock_task_sighand(p, &flags);
-                                       zap_process(p);
+                                       nr += zap_process(p);
                                        unlock_task_sighand(p, &flags);
                                }
                                break;
                        }
-               } while ((p = next_thread(p)) != g);
+               } while_each_thread(g, p);
        }
        rcu_read_unlock();
 done:
-       return mm->core_waiters;
+       atomic_set(&core_state->nr_threads, nr);
+       return nr;
 }
 
-static int coredump_wait(int exit_code)
+static int coredump_wait(int exit_code, struct core_state *core_state)
 {
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->mm;
-       struct completion startup_done;
        struct completion *vfork_done;
        int core_waiters;
 
-       init_completion(&mm->core_done);
-       init_completion(&startup_done);
-       mm->core_startup_done = &startup_done;
-
-       core_waiters = zap_threads(tsk, mm, exit_code);
+       init_completion(&core_state->startup);
+       core_state->dumper.task = tsk;
+       core_state->dumper.next = NULL;
+       core_waiters = zap_threads(tsk, mm, core_state, exit_code);
        up_write(&mm->mmap_sem);
 
        if (unlikely(core_waiters < 0))
@@ -1597,12 +1631,32 @@ static int coredump_wait(int exit_code)
        }
 
        if (core_waiters)
-               wait_for_completion(&startup_done);
+               wait_for_completion(&core_state->startup);
 fail:
-       BUG_ON(mm->core_waiters);
        return core_waiters;
 }
 
+static void coredump_finish(struct mm_struct *mm)
+{
+       struct core_thread *curr, *next;
+       struct task_struct *task;
+
+       next = mm->core_state->dumper.next;
+       while ((curr = next) != NULL) {
+               next = curr->next;
+               task = curr->task;
+               /*
+                * see exit_mm(), curr->task must not see
+                * ->task == NULL before we read ->next.
+                */
+               smp_mb();
+               curr->task = NULL;
+               wake_up_process(task);
+       }
+
+       mm->core_state = NULL;
+}
+
 /*
  * set_dumpable converts traditional three-value dumpable to two flags and
  * stores them into mm->flags.  It modifies lower two bits of mm->flags, but
@@ -1654,6 +1708,7 @@ int get_dumpable(struct mm_struct *mm)
 
 int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 {
+       struct core_state core_state;
        char corename[CORENAME_MAX_SIZE + 1];
        struct mm_struct *mm = current->mm;
        struct linux_binfmt * binfmt;
@@ -1677,7 +1732,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
        /*
         * If another thread got here first, or we are not dumpable, bail out.
         */
-       if (mm->core_waiters || !get_dumpable(mm)) {
+       if (mm->core_state || !get_dumpable(mm)) {
                up_write(&mm->mmap_sem);
                goto fail;
        }
@@ -1692,7 +1747,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
                current->fsuid = 0;     /* Dump root private */
        }
 
-       retval = coredump_wait(exit_code);
+       retval = coredump_wait(exit_code, &core_state);
        if (retval < 0)
                goto fail;
 
@@ -1707,7 +1762,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
         * uses lock_kernel()
         */
        lock_kernel();
-       ispipe = format_corename(corename, core_pattern, signr);
+       ispipe = format_corename(corename, retval, signr);
        unlock_kernel();
        /*
         * Don't bother to check the RLIMIT_CORE value if core_pattern points
@@ -1786,7 +1841,7 @@ fail_unlock:
                argv_free(helper_argv);
 
        current->fsuid = fsuid;
-       complete_all(&mm->core_done);
+       coredump_finish(mm);
 fail:
        return retval;
 }
index e58669e1b87c6bab0e0a0ac8677713b5b2f3fbb8..ae8c4f850b27d0e83e28e684a07637a992abbe69 100644 (file)
@@ -294,7 +294,7 @@ ext2_check_acl(struct inode *inode, int mask)
 }
 
 int
-ext2_permission(struct inode *inode, int mask, struct nameidata *nd)
+ext2_permission(struct inode *inode, int mask)
 {
        return generic_permission(inode, mask, ext2_check_acl);
 }
index 0bde85bafe386eb47187919a8409e0231b4f5298..b42cf578554b5fd10ec8c290ea3fca3af05f9020 100644 (file)
@@ -58,7 +58,7 @@ static inline int ext2_acl_count(size_t size)
 #define EXT2_ACL_NOT_CACHED ((void *)-1)
 
 /* acl.c */
-extern int ext2_permission (struct inode *, int, struct nameidata *);
+extern int ext2_permission (struct inode *, int);
 extern int ext2_acl_chmod (struct inode *);
 extern int ext2_init_acl (struct inode *, struct inode *);
 
index 384fc0d1dd743b080c0fc1fa7f887663d8ed8d8e..991d6dfeb51f078bfe746e6dede400e7e2525817 100644 (file)
@@ -791,6 +791,7 @@ const struct address_space_operations ext2_aops = {
        .direct_IO              = ext2_direct_IO,
        .writepages             = ext2_writepages,
        .migratepage            = buffer_migrate_page,
+       .is_partially_uptodate  = block_is_partially_uptodate,
 };
 
 const struct address_space_operations ext2_aops_xip = {
index ef50cbc792db94668b9d7deecc22c50076511fe4..fd88c7b43e66b3c7e5eec0594a95eb455fdebae4 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/seq_file.h>
 #include <linux/mount.h>
 #include <linux/log2.h>
+#include <linux/quotaops.h>
 #include <asm/uaccess.h>
 #include "ext2.h"
 #include "xattr.h"
@@ -158,7 +159,7 @@ static void ext2_destroy_inode(struct inode *inode)
        kmem_cache_free(ext2_inode_cachep, EXT2_I(inode));
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct ext2_inode_info *ei = (struct ext2_inode_info *) foo;
 
index eaa23d2d5213ae7dcfa70875ebddf40cc7774ce4..70c0dbdcdcb75447cb73602151c2166e0805bb57 100644 (file)
@@ -14,7 +14,7 @@ static size_t
 ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size,
                         const char *name, size_t name_len)
 {
-       const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
+       const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
 
        if (list && total_len <= list_size) {
index 83ee149f353db383d657e01a5feb8cd0fac82655..e8219f8eae9f293bff015a07c1dd11cccc00febf 100644 (file)
 #include <linux/ext2_fs.h>
 #include "xattr.h"
 
-#define XATTR_TRUSTED_PREFIX "trusted."
-
 static size_t
 ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
                        const char *name, size_t name_len)
 {
-       const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
+       const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
 
        if (!capable(CAP_SYS_ADMIN))
index f383e7c3a7b5bd18b8ca0bd43026c12ed689ce41..92495d28c62f0b43da553efba59e482d16d388bc 100644 (file)
 #include "ext2.h"
 #include "xattr.h"
 
-#define XATTR_USER_PREFIX "user."
-
 static size_t
 ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size,
                     const char *name, size_t name_len)
 {
-       const size_t prefix_len = sizeof(XATTR_USER_PREFIX)-1;
+       const size_t prefix_len = XATTR_USER_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
 
        if (!test_opt(inode->i_sb, XATTR_USER))
index a754d1848173af1b0d5e899d29c0a914211a134a..b60bb241880c86f50420e13411dc19b1148e1a51 100644 (file)
@@ -299,7 +299,7 @@ ext3_check_acl(struct inode *inode, int mask)
 }
 
 int
-ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
+ext3_permission(struct inode *inode, int mask)
 {
        return generic_permission(inode, mask, ext3_check_acl);
 }
index 0d1e6279cbfd5799a11f27f774fbcdaf8bd397fb..42da16b8cac0a82d1bdd06a18c178308068e8d08 100644 (file)
@@ -58,7 +58,7 @@ static inline int ext3_acl_count(size_t size)
 #define EXT3_ACL_NOT_CACHED ((void *)-1)
 
 /* acl.c */
-extern int ext3_permission (struct inode *, int, struct nameidata *);
+extern int ext3_permission (struct inode *, int);
 extern int ext3_acl_chmod (struct inode *);
 extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
 
index 8ca3bfd7242743dba5d05f5afd06e3cdb549718d..2eea96ec78ed218f4fbe14b8e4c1b169e1dfe1ac 100644 (file)
@@ -272,7 +272,7 @@ static void free_rb_tree_fname(struct rb_root *root)
 
        while (n) {
                /* Do the node's children first */
-               if ((n)->rb_left) {
+               if (n->rb_left) {
                        n = n->rb_left;
                        continue;
                }
@@ -301,24 +301,18 @@ static void free_rb_tree_fname(struct rb_root *root)
                        parent->rb_right = NULL;
                n = parent;
        }
-       root->rb_node = NULL;
 }
 
 
-static struct dir_private_info *create_dir_info(loff_t pos)
+static struct dir_private_info *ext3_htree_create_dir_info(loff_t pos)
 {
        struct dir_private_info *p;
 
-       p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL);
+       p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL);
        if (!p)
                return NULL;
-       p->root.rb_node = NULL;
-       p->curr_node = NULL;
-       p->extra_fname = NULL;
-       p->last_pos = 0;
        p->curr_hash = pos2maj_hash(pos);
        p->curr_minor_hash = pos2min_hash(pos);
-       p->next_hash = 0;
        return p;
 }
 
@@ -433,7 +427,7 @@ static int ext3_dx_readdir(struct file * filp,
        int     ret;
 
        if (!info) {
-               info = create_dir_info(filp->f_pos);
+               info = ext3_htree_create_dir_info(filp->f_pos);
                if (!info)
                        return -ENOMEM;
                filp->private_data = info;
index 77126821b2e9de219c0e1f36caea9c263e6f7c2f..47b678d73e7a53d28ef1d0d35eae758bd87e54d7 100644 (file)
@@ -669,6 +669,14 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino)
        if (IS_ERR(inode))
                goto iget_failed;
 
+       /*
+        * If the orphans has i_nlinks > 0 then it should be able to be
+        * truncated, otherwise it won't be removed from the orphan list
+        * during processing and an infinite loop will result.
+        */
+       if (inode->i_nlink && !ext3_can_truncate(inode))
+               goto bad_orphan;
+
        if (NEXT_ORPHAN(inode) > max_ino)
                goto bad_orphan;
        brelse(bitmap_bh);
@@ -690,6 +698,7 @@ bad_orphan:
                printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
                       NEXT_ORPHAN(inode));
                printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
+               printk(KERN_NOTICE "i_nlink=%u\n", inode->i_nlink);
                /* Avoid freeing blocks if we got a bad deleted inode */
                if (inode->i_nlink == 0)
                        inode->i_blocks = 0;
index 6ae4ecf3ce40b646da679ba6b2a1ecb6149e7e00..507d8689b111662b403c874e2c269417635f5555 100644 (file)
@@ -1767,44 +1767,47 @@ static int ext3_journalled_set_page_dirty(struct page *page)
 }
 
 static const struct address_space_operations ext3_ordered_aops = {
-       .readpage       = ext3_readpage,
-       .readpages      = ext3_readpages,
-       .writepage      = ext3_ordered_writepage,
-       .sync_page      = block_sync_page,
-       .write_begin    = ext3_write_begin,
-       .write_end      = ext3_ordered_write_end,
-       .bmap           = ext3_bmap,
-       .invalidatepage = ext3_invalidatepage,
-       .releasepage    = ext3_releasepage,
-       .direct_IO      = ext3_direct_IO,
-       .migratepage    = buffer_migrate_page,
+       .readpage               = ext3_readpage,
+       .readpages              = ext3_readpages,
+       .writepage              = ext3_ordered_writepage,
+       .sync_page              = block_sync_page,
+       .write_begin            = ext3_write_begin,
+       .write_end              = ext3_ordered_write_end,
+       .bmap                   = ext3_bmap,
+       .invalidatepage         = ext3_invalidatepage,
+       .releasepage            = ext3_releasepage,
+       .direct_IO              = ext3_direct_IO,
+       .migratepage            = buffer_migrate_page,
+       .is_partially_uptodate  = block_is_partially_uptodate,
 };
 
 static const struct address_space_operations ext3_writeback_aops = {
-       .readpage       = ext3_readpage,
-       .readpages      = ext3_readpages,
-       .writepage      = ext3_writeback_writepage,
-       .sync_page      = block_sync_page,
-       .write_begin    = ext3_write_begin,
-       .write_end      = ext3_writeback_write_end,
-       .bmap           = ext3_bmap,
-       .invalidatepage = ext3_invalidatepage,
-       .releasepage    = ext3_releasepage,
-       .direct_IO      = ext3_direct_IO,
-       .migratepage    = buffer_migrate_page,
+       .readpage               = ext3_readpage,
+       .readpages              = ext3_readpages,
+       .writepage              = ext3_writeback_writepage,
+       .sync_page              = block_sync_page,
+       .write_begin            = ext3_write_begin,
+       .write_end              = ext3_writeback_write_end,
+       .bmap                   = ext3_bmap,
+       .invalidatepage         = ext3_invalidatepage,
+       .releasepage            = ext3_releasepage,
+       .direct_IO              = ext3_direct_IO,
+       .migratepage            = buffer_migrate_page,
+       .is_partially_uptodate  = block_is_partially_uptodate,
 };
 
 static const struct address_space_operations ext3_journalled_aops = {
-       .readpage       = ext3_readpage,
-       .readpages      = ext3_readpages,
-       .writepage      = ext3_journalled_writepage,
-       .sync_page      = block_sync_page,
-       .write_begin    = ext3_write_begin,
-       .write_end      = ext3_journalled_write_end,
-       .set_page_dirty = ext3_journalled_set_page_dirty,
-       .bmap           = ext3_bmap,
-       .invalidatepage = ext3_invalidatepage,
-       .releasepage    = ext3_releasepage,
+       .readpage               = ext3_readpage,
+       .readpages              = ext3_readpages,
+       .writepage              = ext3_journalled_writepage,
+       .sync_page              = block_sync_page,
+       .write_begin            = ext3_write_begin,
+       .write_end              = ext3_journalled_write_end,
+       .set_page_dirty         = ext3_journalled_set_page_dirty,
+       .bmap                   = ext3_bmap,
+       .invalidatepage         = ext3_invalidatepage,
+       .releasepage            = ext3_releasepage,
+       .is_partially_uptodate  = block_is_partially_uptodate,
 };
 
 void ext3_set_aops(struct inode *inode)
@@ -2127,7 +2130,21 @@ static void ext3_free_data(handle_t *handle, struct inode *inode,
 
        if (this_bh) {
                BUFFER_TRACE(this_bh, "call ext3_journal_dirty_metadata");
-               ext3_journal_dirty_metadata(handle, this_bh);
+
+               /*
+                * The buffer head should have an attached journal head at this
+                * point. However, if the data is corrupted and an indirect
+                * block pointed to itself, it would have been detached when
+                * the block was cleared. Check for this instead of OOPSing.
+                */
+               if (bh2jh(this_bh))
+                       ext3_journal_dirty_metadata(handle, this_bh);
+               else
+                       ext3_error(inode->i_sb, "ext3_free_data",
+                                  "circular indirect block detected, "
+                                  "inode=%lu, block=%llu",
+                                  inode->i_ino,
+                                  (unsigned long long)this_bh->b_blocknr);
        }
 }
 
@@ -2253,6 +2270,19 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
        }
 }
 
+int ext3_can_truncate(struct inode *inode)
+{
+       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+               return 0;
+       if (S_ISREG(inode->i_mode))
+               return 1;
+       if (S_ISDIR(inode->i_mode))
+               return 1;
+       if (S_ISLNK(inode->i_mode))
+               return !ext3_inode_is_fast_symlink(inode);
+       return 0;
+}
+
 /*
  * ext3_truncate()
  *
@@ -2297,12 +2327,7 @@ void ext3_truncate(struct inode *inode)
        unsigned blocksize = inode->i_sb->s_blocksize;
        struct page *page;
 
-       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-           S_ISLNK(inode->i_mode)))
-               return;
-       if (ext3_inode_is_fast_symlink(inode))
-               return;
-       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+       if (!ext3_can_truncate(inode))
                return;
 
        /*
@@ -2513,6 +2538,16 @@ static int __ext3_get_inode_loc(struct inode *inode,
        }
        if (!buffer_uptodate(bh)) {
                lock_buffer(bh);
+
+               /*
+                * If the buffer has the write error flag, we have failed
+                * to write out another inode in the same block.  In this
+                * case, we don't have to read the block because we may
+                * read the old inode data successfully.
+                */
+               if (buffer_write_io_error(bh) && !buffer_uptodate(bh))
+                       set_buffer_uptodate(bh);
+
                if (buffer_uptodate(bh)) {
                        /* someone brought it uptodate while we waited */
                        unlock_buffer(bh);
index 0b8cf80154f1a5c912a1b2d6cae18ccebea591c1..de13e919cd8106fac1012c162699cc5604da90f4 100644 (file)
@@ -240,13 +240,13 @@ static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
 {
        unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) -
                EXT3_DIR_REC_LEN(2) - infosize;
-       return 0? 20: entry_space / sizeof(struct dx_entry);
+       return entry_space / sizeof(struct dx_entry);
 }
 
 static inline unsigned dx_node_limit (struct inode *dir)
 {
        unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0);
-       return 0? 22: entry_space / sizeof(struct dx_entry);
+       return entry_space / sizeof(struct dx_entry);
 }
 
 /*
@@ -991,19 +991,21 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
                de = (struct ext3_dir_entry_2 *) bh->b_data;
                top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize -
                                       EXT3_DIR_REC_LEN(0));
-               for (; de < top; de = ext3_next_entry(de))
-               if (ext3_match (namelen, name, de)) {
-                       if (!ext3_check_dir_entry("ext3_find_entry",
-                                                 dir, de, bh,
-                                 (block<<EXT3_BLOCK_SIZE_BITS(sb))
-                                         +((char *)de - bh->b_data))) {
-                               brelse (bh);
+               for (; de < top; de = ext3_next_entry(de)) {
+                       int off = (block << EXT3_BLOCK_SIZE_BITS(sb))
+                                 + ((char *) de - bh->b_data);
+
+                       if (!ext3_check_dir_entry(__func__, dir, de, bh, off)) {
+                               brelse(bh);
                                *err = ERR_BAD_DX_DIR;
                                goto errout;
                        }
-                       *res_dir = de;
-                       dx_release (frames);
-                       return bh;
+
+                       if (ext3_match(namelen, name, de)) {
+                               *res_dir = de;
+                               dx_release(frames);
+                               return bh;
+                       }
                }
                brelse (bh);
                /* Check to see if we should continue to search */
index 2845425077e857c85ac7413a9613786d0dd0ac25..8ddced38467483a5fded626a73d4e1d62d9d12a1 100644 (file)
@@ -472,7 +472,7 @@ static void ext3_destroy_inode(struct inode *inode)
        kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct ext3_inode_info *ei = (struct ext3_inode_info *) foo;
 
@@ -842,7 +842,7 @@ static int parse_options (char *options, struct super_block *sb,
        int data_opt = 0;
        int option;
 #ifdef CONFIG_QUOTA
-       int qtype;
+       int qtype, qfmt;
        char *qname;
 #endif
 
@@ -1018,9 +1018,11 @@ static int parse_options (char *options, struct super_block *sb,
                case Opt_grpjquota:
                        qtype = GRPQUOTA;
 set_qf_name:
-                       if (sb_any_quota_enabled(sb)) {
+                       if ((sb_any_quota_enabled(sb) ||
+                            sb_any_quota_suspended(sb)) &&
+                           !sbi->s_qf_names[qtype]) {
                                printk(KERN_ERR
-                                       "EXT3-fs: Cannot change journalled "
+                                       "EXT3-fs: Cannot change journaled "
                                        "quota options when quota turned on.\n");
                                return 0;
                        }
@@ -1056,9 +1058,11 @@ set_qf_name:
                case Opt_offgrpjquota:
                        qtype = GRPQUOTA;
 clear_qf_name:
-                       if (sb_any_quota_enabled(sb)) {
+                       if ((sb_any_quota_enabled(sb) ||
+                            sb_any_quota_suspended(sb)) &&
+                           sbi->s_qf_names[qtype]) {
                                printk(KERN_ERR "EXT3-fs: Cannot change "
-                                       "journalled quota options when "
+                                       "journaled quota options when "
                                        "quota turned on.\n");
                                return 0;
                        }
@@ -1069,10 +1073,20 @@ clear_qf_name:
                        sbi->s_qf_names[qtype] = NULL;
                        break;
                case Opt_jqfmt_vfsold:
-                       sbi->s_jquota_fmt = QFMT_VFS_OLD;
-                       break;
+                       qfmt = QFMT_VFS_OLD;
+                       goto set_qf_format;
                case Opt_jqfmt_vfsv0:
-                       sbi->s_jquota_fmt = QFMT_VFS_V0;
+                       qfmt = QFMT_VFS_V0;
+set_qf_format:
+                       if ((sb_any_quota_enabled(sb) ||
+                            sb_any_quota_suspended(sb)) &&
+                           sbi->s_jquota_fmt != qfmt) {
+                               printk(KERN_ERR "EXT3-fs: Cannot change "
+                                       "journaled quota options when "
+                                       "quota turned on.\n");
+                               return 0;
+                       }
+                       sbi->s_jquota_fmt = qfmt;
                        break;
                case Opt_quota:
                case Opt_usrquota:
@@ -1084,7 +1098,8 @@ clear_qf_name:
                        set_opt(sbi->s_mount_opt, GRPQUOTA);
                        break;
                case Opt_noquota:
-                       if (sb_any_quota_enabled(sb)) {
+                       if (sb_any_quota_enabled(sb) ||
+                           sb_any_quota_suspended(sb)) {
                                printk(KERN_ERR "EXT3-fs: Cannot change quota "
                                        "options when quota turned on.\n");
                                return 0;
@@ -1169,14 +1184,14 @@ clear_qf_name:
                }
 
                if (!sbi->s_jquota_fmt) {
-                       printk(KERN_ERR "EXT3-fs: journalled quota format "
+                       printk(KERN_ERR "EXT3-fs: journaled quota format "
                                        "not specified.\n");
                        return 0;
                }
        } else {
                if (sbi->s_jquota_fmt) {
-                       printk(KERN_ERR "EXT3-fs: journalled quota format "
-                                       "specified with no journalling "
+                       printk(KERN_ERR "EXT3-fs: journaled quota format "
+                                       "specified with no journaling "
                                        "enabled.\n");
                        return 0;
                }
@@ -1370,7 +1385,7 @@ static void ext3_orphan_cleanup (struct super_block * sb,
                        int ret = ext3_quota_on_mount(sb, i);
                        if (ret < 0)
                                printk(KERN_ERR
-                                       "EXT3-fs: Cannot turn on journalled "
+                                       "EXT3-fs: Cannot turn on journaled "
                                        "quota: error %d\n", ret);
                }
        }
@@ -2712,7 +2727,7 @@ static int ext3_release_dquot(struct dquot *dquot)
 
 static int ext3_mark_dquot_dirty(struct dquot *dquot)
 {
-       /* Are we journalling quotas? */
+       /* Are we journaling quotas? */
        if (EXT3_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
            EXT3_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
                dquot_mark_dquot_dirty(dquot);
@@ -2759,23 +2774,42 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
 
        if (!test_opt(sb, QUOTA))
                return -EINVAL;
-       /* Not journalling quota or remount? */
-       if ((!EXT3_SB(sb)->s_qf_names[USRQUOTA] &&
-           !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) || remount)
+       /* When remounting, no checks are needed and in fact, path is NULL */
+       if (remount)
                return vfs_quota_on(sb, type, format_id, path, remount);
+
        err = path_lookup(path, LOOKUP_FOLLOW, &nd);
        if (err)
                return err;
+
        /* Quotafile not on the same filesystem? */
        if (nd.path.mnt->mnt_sb != sb) {
                path_put(&nd.path);
                return -EXDEV;
        }
-       /* Quotafile not in fs root? */
-       if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
-               printk(KERN_WARNING
-                       "EXT3-fs: Quota file not on filesystem root. "
-                       "Journalled quota will not work.\n");
+       /* Journaling quota? */
+       if (EXT3_SB(sb)->s_qf_names[type]) {
+               /* Quotafile not of fs root? */
+               if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+                       printk(KERN_WARNING
+                               "EXT3-fs: Quota file not on filesystem root. "
+                               "Journaled quota will not work.\n");
+       }
+
+       /*
+        * When we journal data on quota file, we have to flush journal to see
+        * all updates to the file when we bypass pagecache...
+        */
+       if (ext3_should_journal_data(nd.path.dentry->d_inode)) {
+               /*
+                * We don't need to lock updates but journal_flush() could
+                * otherwise be livelocked...
+                */
+               journal_lock_updates(EXT3_SB(sb)->s_journal);
+               journal_flush(EXT3_SB(sb)->s_journal);
+               journal_unlock_updates(EXT3_SB(sb)->s_journal);
+       }
+
        path_put(&nd.path);
        return vfs_quota_on(sb, type, format_id, path, remount);
 }
index 821efaf2b94e55b7556903d2835493c5ec5a9252..37b81097bdf2a147b6bd2e7720e9ae8efe8170a7 100644 (file)
@@ -15,7 +15,7 @@ static size_t
 ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
                         const char *name, size_t name_len)
 {
-       const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
+       const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
 
 
index 0327497a55ce0a58baa9ce2d855cd7ecad762625..c7c41a410c4bfed2761ade463b9c34957f4bf5f5 100644 (file)
 #include <linux/ext3_fs.h>
 #include "xattr.h"
 
-#define XATTR_TRUSTED_PREFIX "trusted."
-
 static size_t
 ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
                        const char *name, size_t name_len)
 {
-       const size_t prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
+       const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
 
        if (!capable(CAP_SYS_ADMIN))
index 1abd8f92c4402a86a992e10e8e3261fd635eea10..430fe63b31b397d37370758ac119eeb2139469bd 100644 (file)
 #include <linux/ext3_fs.h>
 #include "xattr.h"
 
-#define XATTR_USER_PREFIX "user."
-
 static size_t
 ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
                     const char *name, size_t name_len)
 {
-       const size_t prefix_len = sizeof(XATTR_USER_PREFIX)-1;
+       const size_t prefix_len = XATTR_USER_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
 
        if (!test_opt(inode->i_sb, XATTR_USER))
index 3c8dab880d91f1bb38247d44d605f2bc3943a90e..c7d04e165446dfc5391930b24ce2a1d3280e71d1 100644 (file)
@@ -299,7 +299,7 @@ ext4_check_acl(struct inode *inode, int mask)
 }
 
 int
-ext4_permission(struct inode *inode, int mask, struct nameidata *nd)
+ext4_permission(struct inode *inode, int mask)
 {
        return generic_permission(inode, mask, ext4_check_acl);
 }
index 26a5c1abf147bf9690f091baba133ec5eab7cf00..cd2b855a07d669988f817f6e7415088b8dcefed6 100644 (file)
@@ -58,7 +58,7 @@ static inline int ext4_acl_count(size_t size)
 #define EXT4_ACL_NOT_CACHED ((void *)-1)
 
 /* acl.c */
-extern int ext4_permission (struct inode *, int, struct nameidata *);
+extern int ext4_permission (struct inode *, int);
 extern int ext4_acl_chmod (struct inode *);
 extern int ext4_init_acl (handle_t *, struct inode *, struct inode *);
 
index 8ca2763df091051fea3e02ae7bba35a1e82e21d9..9843b046c2358974bff4bea0449583c688c27358 100644 (file)
@@ -2806,59 +2806,63 @@ static int ext4_journalled_set_page_dirty(struct page *page)
 }
 
 static const struct address_space_operations ext4_ordered_aops = {
-       .readpage       = ext4_readpage,
-       .readpages      = ext4_readpages,
-       .writepage      = ext4_normal_writepage,
-       .sync_page      = block_sync_page,
-       .write_begin    = ext4_write_begin,
-       .write_end      = ext4_ordered_write_end,
-       .bmap           = ext4_bmap,
-       .invalidatepage = ext4_invalidatepage,
-       .releasepage    = ext4_releasepage,
-       .direct_IO      = ext4_direct_IO,
-       .migratepage    = buffer_migrate_page,
+       .readpage               = ext4_readpage,
+       .readpages              = ext4_readpages,
+       .writepage              = ext4_normal_writepage,
+       .sync_page              = block_sync_page,
+       .write_begin            = ext4_write_begin,
+       .write_end              = ext4_ordered_write_end,
+       .bmap                   = ext4_bmap,
+       .invalidatepage         = ext4_invalidatepage,
+       .releasepage            = ext4_releasepage,
+       .direct_IO              = ext4_direct_IO,
+       .migratepage            = buffer_migrate_page,
+       .is_partially_uptodate  = block_is_partially_uptodate,
 };
 
 static const struct address_space_operations ext4_writeback_aops = {
-       .readpage       = ext4_readpage,
-       .readpages      = ext4_readpages,
-       .writepage      = ext4_normal_writepage,
-       .sync_page      = block_sync_page,
-       .write_begin    = ext4_write_begin,
-       .write_end      = ext4_writeback_write_end,
-       .bmap           = ext4_bmap,
-       .invalidatepage = ext4_invalidatepage,
-       .releasepage    = ext4_releasepage,
-       .direct_IO      = ext4_direct_IO,
-       .migratepage    = buffer_migrate_page,
+       .readpage               = ext4_readpage,
+       .readpages              = ext4_readpages,
+       .writepage              = ext4_normal_writepage,
+       .sync_page              = block_sync_page,
+       .write_begin            = ext4_write_begin,
+       .write_end              = ext4_writeback_write_end,
+       .bmap                   = ext4_bmap,
+       .invalidatepage         = ext4_invalidatepage,
+       .releasepage            = ext4_releasepage,
+       .direct_IO              = ext4_direct_IO,
+       .migratepage            = buffer_migrate_page,
+       .is_partially_uptodate  = block_is_partially_uptodate,
 };
 
 static const struct address_space_operations ext4_journalled_aops = {
-       .readpage       = ext4_readpage,
-       .readpages      = ext4_readpages,
-       .writepage      = ext4_journalled_writepage,
-       .sync_page      = block_sync_page,
-       .write_begin    = ext4_write_begin,
-       .write_end      = ext4_journalled_write_end,
-       .set_page_dirty = ext4_journalled_set_page_dirty,
-       .bmap           = ext4_bmap,
-       .invalidatepage = ext4_invalidatepage,
-       .releasepage    = ext4_releasepage,
+       .readpage               = ext4_readpage,
+       .readpages              = ext4_readpages,
+       .writepage              = ext4_journalled_writepage,
+       .sync_page              = block_sync_page,
+       .write_begin            = ext4_write_begin,
+       .write_end              = ext4_journalled_write_end,
+       .set_page_dirty         = ext4_journalled_set_page_dirty,
+       .bmap                   = ext4_bmap,
+       .invalidatepage         = ext4_invalidatepage,
+       .releasepage            = ext4_releasepage,
+       .is_partially_uptodate  = block_is_partially_uptodate,
 };
 
 static const struct address_space_operations ext4_da_aops = {
-       .readpage       = ext4_readpage,
-       .readpages      = ext4_readpages,
-       .writepage      = ext4_da_writepage,
-       .writepages     = ext4_da_writepages,
-       .sync_page      = block_sync_page,
-       .write_begin    = ext4_da_write_begin,
-       .write_end      = ext4_da_write_end,
-       .bmap           = ext4_bmap,
-       .invalidatepage = ext4_da_invalidatepage,
-       .releasepage    = ext4_releasepage,
-       .direct_IO      = ext4_direct_IO,
-       .migratepage    = buffer_migrate_page,
+       .readpage               = ext4_readpage,
+       .readpages              = ext4_readpages,
+       .writepage              = ext4_da_writepage,
+       .writepages             = ext4_da_writepages,
+       .sync_page              = block_sync_page,
+       .write_begin            = ext4_da_write_begin,
+       .write_end              = ext4_da_write_end,
+       .bmap                   = ext4_bmap,
+       .invalidatepage         = ext4_da_invalidatepage,
+       .releasepage            = ext4_releasepage,
+       .direct_IO              = ext4_direct_IO,
+       .migratepage            = buffer_migrate_page,
+       .is_partially_uptodate  = block_is_partially_uptodate,
 };
 
 void ext4_set_aops(struct inode *inode)
index 1cb371dcd609aae5f115cf236acd4d0c66956efb..b5479b1dff14b7513b077ddc2c920ceffc67b76d 100644 (file)
@@ -595,7 +595,7 @@ static void ext4_destroy_inode(struct inode *inode)
        kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
 
index 3a9ecac8d61f081e295655822d311dc27f51f02f..3222f51c41cf0a88637760f2f45729ef1f6a31c4 100644 (file)
@@ -36,7 +36,7 @@ static inline int fat_max_cache(struct inode *inode)
 
 static struct kmem_cache *fat_cache_cachep;
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct fat_cache *cache = (struct fat_cache *)foo;
 
index 34541d06e6263b1817d96ee4d640f2cc8aa35eb7..cd4a0162e10d6dea7507507cf25a13fd93d93f04 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/msdos_fs.h>
-#include <linux/dirent.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/compat.h>
@@ -124,10 +123,11 @@ static inline int fat_get_entry(struct inode *dir, loff_t *pos,
  * but ignore that right now.
  * Ahem... Stack smashing in ring 0 isn't fun. Fixed.
  */
-static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int len,
+static int uni16_to_x8(unsigned char *ascii, const wchar_t *uni, int len,
                       int uni_xlate, struct nls_table *nls)
 {
-       wchar_t *ip, ec;
+       const wchar_t *ip;
+       wchar_t ec;
        unsigned char *op, nc;
        int charlen;
        int k;
@@ -167,6 +167,16 @@ static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int len,
        return (op - ascii);
 }
 
+static inline int fat_uni_to_x8(struct msdos_sb_info *sbi, const wchar_t *uni,
+                               unsigned char *buf, int size)
+{
+       if (sbi->options.utf8)
+               return utf8_wcstombs(buf, uni, size);
+       else
+               return uni16_to_x8(buf, uni, size, sbi->options.unicode_xlate,
+                                  sbi->nls_io);
+}
+
 static inline int
 fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
 {
@@ -227,6 +237,19 @@ fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size,
        return len;
 }
 
+static inline int fat_name_match(struct msdos_sb_info *sbi,
+                                const unsigned char *a, int a_len,
+                                const unsigned char *b, int b_len)
+{
+       if (a_len != b_len)
+               return 0;
+
+       if (sbi->options.name_check != 's')
+               return !nls_strnicmp(sbi->nls_io, a, b, a_len);
+       else
+               return !memcmp(a, b, a_len);
+}
+
 enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, };
 
 /**
@@ -301,6 +324,19 @@ parse_long:
        return 0;
 }
 
+/*
+ * Maximum buffer size of short name.
+ * [(MSDOS_NAME + '.') * max one char + nul]
+ * For msdos style, ['.' (hidden) + MSDOS_NAME + '.' + nul]
+ */
+#define FAT_MAX_SHORT_SIZE     ((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1)
+/*
+ * Maximum buffer size of unicode chars from slots.
+ * [(max longname slots * 13 (size in a slot) + nul) * sizeof(wchar_t)]
+ */
+#define FAT_MAX_UNI_CHARS      ((MSDOS_SLOTS - 1) * 13 + 1)
+#define FAT_MAX_UNI_SIZE       (FAT_MAX_UNI_CHARS * sizeof(wchar_t))
+
 /*
  * Return values: negative -> error, 0 -> not found, positive -> found,
  * value is the total amount of slots, including the shortname entry.
@@ -312,29 +348,20 @@ int fat_search_long(struct inode *inode, const unsigned char *name,
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
        struct buffer_head *bh = NULL;
        struct msdos_dir_entry *de;
-       struct nls_table *nls_io = sbi->nls_io;
        struct nls_table *nls_disk = sbi->nls_disk;
-       wchar_t bufuname[14];
        unsigned char nr_slots;
-       int xlate_len;
+       wchar_t bufuname[14];
        wchar_t *unicode = NULL;
        unsigned char work[MSDOS_NAME];
-       unsigned char *bufname = NULL;
-       int uni_xlate = sbi->options.unicode_xlate;
-       int utf8 = sbi->options.utf8;
-       int anycase = (sbi->options.name_check != 's');
+       unsigned char bufname[FAT_MAX_SHORT_SIZE];
        unsigned short opt_shortname = sbi->options.shortname;
        loff_t cpos = 0;
-       int chl, i, j, last_u, err;
-
-       bufname = __getname();
-       if (!bufname)
-               return -ENOMEM;
+       int chl, i, j, last_u, err, len;
 
        err = -ENOENT;
-       while(1) {
+       while (1) {
                if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
-                       goto EODir;
+                       goto end_of_dir;
 parse_record:
                nr_slots = 0;
                if (de->name[0] == DELETED_FLAG)
@@ -353,7 +380,7 @@ parse_record:
                        else if (status == PARSE_NOT_LONGNAME)
                                goto parse_record;
                        else if (status == PARSE_EOF)
-                               goto EODir;
+                               goto end_of_dir;
                }
 
                memcpy(work, de->name, sizeof(de->name));
@@ -394,30 +421,24 @@ parse_record:
                if (!last_u)
                        continue;
 
+               /* Compare shortname */
                bufuname[last_u] = 0x0000;
-               xlate_len = utf8
-                       ?utf8_wcstombs(bufname, bufuname, PATH_MAX)
-                       :uni16_to_x8(bufname, bufuname, PATH_MAX, uni_xlate, nls_io);
-               if (xlate_len == name_len)
-                       if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
-                           (anycase && !nls_strnicmp(nls_io, name, bufname,
-                                                               xlate_len)))
-                               goto Found;
+               len = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname));
+               if (fat_name_match(sbi, name, name_len, bufname, len))
+                       goto found;
 
                if (nr_slots) {
-                       xlate_len = utf8
-                               ?utf8_wcstombs(bufname, unicode, PATH_MAX)
-                               :uni16_to_x8(bufname, unicode, PATH_MAX, uni_xlate, nls_io);
-                       if (xlate_len != name_len)
-                               continue;
-                       if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
-                           (anycase && !nls_strnicmp(nls_io, name, bufname,
-                                                               xlate_len)))
-                               goto Found;
+                       void *longname = unicode + FAT_MAX_UNI_CHARS;
+                       int size = PATH_MAX - FAT_MAX_UNI_SIZE;
+
+                       /* Compare longname */
+                       len = fat_uni_to_x8(sbi, unicode, longname, size);
+                       if (fat_name_match(sbi, name, name_len, longname, len))
+                               goto found;
                }
        }
 
-Found:
+found:
        nr_slots++;     /* include the de */
        sinfo->slot_off = cpos - nr_slots * sizeof(*de);
        sinfo->nr_slots = nr_slots;
@@ -425,9 +446,7 @@ Found:
        sinfo->bh = bh;
        sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
        err = 0;
-EODir:
-       if (bufname)
-               __putname(bufname);
+end_of_dir:
        if (unicode)
                __putname(unicode);
 
@@ -453,23 +472,20 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
        struct buffer_head *bh;
        struct msdos_dir_entry *de;
-       struct nls_table *nls_io = sbi->nls_io;
        struct nls_table *nls_disk = sbi->nls_disk;
-       unsigned char long_slots;
-       const char *fill_name;
-       int fill_len;
+       unsigned char nr_slots;
        wchar_t bufuname[14];
        wchar_t *unicode = NULL;
-       unsigned char c, work[MSDOS_NAME], bufname[56], *ptname = bufname;
-       unsigned long lpos, dummy, *furrfu = &lpos;
-       int uni_xlate = sbi->options.unicode_xlate;
+       unsigned char c, work[MSDOS_NAME];
+       unsigned char bufname[FAT_MAX_SHORT_SIZE], *ptname = bufname;
+       unsigned short opt_shortname = sbi->options.shortname;
        int isvfat = sbi->options.isvfat;
-       int utf8 = sbi->options.utf8;
        int nocase = sbi->options.nocase;
-       unsigned short opt_shortname = sbi->options.shortname;
+       const char *fill_name = NULL;
        unsigned long inum;
-       int chi, chl, i, i2, j, last, last_u, dotoffset = 0;
+       unsigned long lpos, dummy, *furrfu = &lpos;
        loff_t cpos;
+       int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len = 0;
        int ret = 0;
 
        lock_super(sb);
@@ -489,43 +505,58 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
                        cpos = 0;
                }
        }
-       if (cpos & (sizeof(struct msdos_dir_entry)-1)) {
+       if (cpos & (sizeof(struct msdos_dir_entry) - 1)) {
                ret = -ENOENT;
                goto out;
        }
 
        bh = NULL;
-GetNew:
+get_new:
        if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
-               goto EODir;
+               goto end_of_dir;
 parse_record:
-       long_slots = 0;
-       /* Check for long filename entry */
-       if (isvfat) {
+       nr_slots = 0;
+       /*
+        * Check for long filename entry, but if short_only, we don't
+        * need to parse long filename.
+        */
+       if (isvfat && !short_only) {
                if (de->name[0] == DELETED_FLAG)
-                       goto RecEnd;
+                       goto record_end;
                if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
-                       goto RecEnd;
+                       goto record_end;
                if (de->attr != ATTR_EXT && IS_FREE(de->name))
-                       goto RecEnd;
+                       goto record_end;
        } else {
                if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name))
-                       goto RecEnd;
+                       goto record_end;
        }
 
        if (isvfat && de->attr == ATTR_EXT) {
                int status = fat_parse_long(inode, &cpos, &bh, &de,
-                                           &unicode, &long_slots);
+                                           &unicode, &nr_slots);
                if (status < 0) {
                        filp->f_pos = cpos;
                        ret = status;
                        goto out;
                } else if (status == PARSE_INVALID)
-                       goto RecEnd;
+                       goto record_end;
                else if (status == PARSE_NOT_LONGNAME)
                        goto parse_record;
                else if (status == PARSE_EOF)
-                       goto EODir;
+                       goto end_of_dir;
+
+               if (nr_slots) {
+                       void *longname = unicode + FAT_MAX_UNI_CHARS;
+                       int size = PATH_MAX - FAT_MAX_UNI_SIZE;
+                       int len = fat_uni_to_x8(sbi, unicode, longname, size);
+
+                       fill_name = longname;
+                       fill_len = len;
+                       /* !both && !short_only, so we don't need shortname. */
+                       if (!both)
+                               goto start_filldir;
+               }
        }
 
        if (sbi->options.dotsOK) {
@@ -587,12 +618,32 @@ parse_record:
                }
        }
        if (!last)
-               goto RecEnd;
+               goto record_end;
 
        i = last + dotoffset;
        j = last_u;
 
-       lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry);
+       if (isvfat) {
+               bufuname[j] = 0x0000;
+               i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname));
+       }
+       if (nr_slots) {
+               /* hack for fat_ioctl_filldir() */
+               struct fat_ioctl_filldir_callback *p = dirent;
+
+               p->longname = fill_name;
+               p->long_len = fill_len;
+               p->shortname = bufname;
+               p->short_len = i;
+               fill_name = NULL;
+               fill_len = 0;
+       } else {
+               fill_name = bufname;
+               fill_len = i;
+       }
+
+start_filldir:
+       lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry);
        if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME))
                inum = inode->i_ino;
        else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
@@ -607,49 +658,17 @@ parse_record:
                        inum = iunique(sb, MSDOS_ROOT_INO);
        }
 
-       if (isvfat) {
-               bufuname[j] = 0x0000;
-               i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname))
-                        : uni16_to_x8(bufname, bufuname, sizeof(bufname), uni_xlate, nls_io);
-       }
-
-       fill_name = bufname;
-       fill_len = i;
-       if (!short_only && long_slots) {
-               /* convert the unicode long name. 261 is maximum size
-                * of unicode buffer. (13 * slots + nul) */
-               void *longname = unicode + 261;
-               int buf_size = PATH_MAX - (261 * sizeof(unicode[0]));
-               int long_len = utf8
-                       ? utf8_wcstombs(longname, unicode, buf_size)
-                       : uni16_to_x8(longname, unicode, buf_size, uni_xlate, nls_io);
-
-               if (!both) {
-                       fill_name = longname;
-                       fill_len = long_len;
-               } else {
-                       /* hack for fat_ioctl_filldir() */
-                       struct fat_ioctl_filldir_callback *p = dirent;
-
-                       p->longname = longname;
-                       p->long_len = long_len;
-                       p->shortname = bufname;
-                       p->short_len = i;
-                       fill_name = NULL;
-                       fill_len = 0;
-               }
-       }
        if (filldir(dirent, fill_name, fill_len, *furrfu, inum,
                    (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
-               goto FillFailed;
+               goto fill_failed;
 
-RecEnd:
+record_end:
        furrfu = &lpos;
        filp->f_pos = cpos;
-       goto GetNew;
-EODir:
+       goto get_new;
+end_of_dir:
        filp->f_pos = cpos;
-FillFailed:
+fill_failed:
        brelse(bh);
        if (unicode)
                __putname(unicode);
@@ -715,7 +734,7 @@ efault:                                                                        \
        return -EFAULT;                                                    \
 }
 
-FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, dirent)
+FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)
 
 static int fat_ioctl_readdir(struct inode *inode, struct file *filp,
                             void __user *dirent, filldir_t filldir,
@@ -741,7 +760,7 @@ static int fat_ioctl_readdir(struct inode *inode, struct file *filp,
 static int fat_dir_ioctl(struct inode *inode, struct file *filp,
                         unsigned int cmd, unsigned long arg)
 {
-       struct dirent __user *d1 = (struct dirent __user *)arg;
+       struct __fat_dirent __user *d1 = (struct __fat_dirent __user *)arg;
        int short_only, both;
 
        switch (cmd) {
@@ -757,7 +776,7 @@ static int fat_dir_ioctl(struct inode *inode, struct file *filp,
                return fat_generic_ioctl(inode, filp, cmd, arg);
        }
 
-       if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2])))
+       if (!access_ok(VERIFY_WRITE, d1, sizeof(struct __fat_dirent[2])))
                return -EFAULT;
        /*
         * Yes, we don't need this put_user() absolutely. However old
@@ -1082,7 +1101,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
                goto error_free;
        }
 
-       fat_date_unix2dos(ts->tv_sec, &time, &date);
+       fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
 
        de = (struct msdos_dir_entry *)bhs[0]->b_data;
        /* filling the new directory slots ("." and ".." entries) */
index c672df4036e94cc59aed3c1c59b4fdeb8882fe7a..8707a8cfa02cdd8454056ed320ee49a4604c84f8 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
 #include <linux/blkdev.h>
+#include <linux/fsnotify.h>
+#include <linux/security.h>
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg)
@@ -64,6 +66,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
 
                /* Equivalent to a chmod() */
                ia.ia_valid = ATTR_MODE | ATTR_CTIME;
+               ia.ia_ctime = current_fs_time(inode->i_sb);
                if (is_dir) {
                        ia.ia_mode = MSDOS_MKMODE(attr,
                                S_IRWXUGO & ~sbi->options.fs_dmask)
@@ -90,11 +93,21 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
                        }
                }
 
+               /*
+                * The security check is questionable...  We single
+                * out the RO attribute for checking by the security
+                * module, just because it maps to a file mode.
+                */
+               err = security_inode_setattr(filp->f_path.dentry, &ia);
+               if (err)
+                       goto up;
+
                /* This MUST be done before doing anything irreversible... */
-               err = notify_change(filp->f_path.dentry, &ia);
+               err = fat_setattr(filp->f_path.dentry, &ia);
                if (err)
                        goto up;
 
+               fsnotify_change(filp->f_path.dentry, ia.ia_valid);
                if (sbi->options.sys_immutable) {
                        if (attr & ATTR_SYS)
                                inode->i_flags |= S_IMMUTABLE;
index 46a4508ffd2eba5cbf10be8122d60f721883f934..6d266d793e2caba12ef6b65501ab1db116c50574 100644 (file)
@@ -382,17 +382,20 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
        inode->i_mtime.tv_sec =
-               date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date));
+               date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date),
+                             sbi->options.tz_utc);
        inode->i_mtime.tv_nsec = 0;
        if (sbi->options.isvfat) {
                int secs = de->ctime_cs / 100;
                int csecs = de->ctime_cs % 100;
                inode->i_ctime.tv_sec  =
                        date_dos2unix(le16_to_cpu(de->ctime),
-                                     le16_to_cpu(de->cdate)) + secs;
+                                     le16_to_cpu(de->cdate),
+                                     sbi->options.tz_utc) + secs;
                inode->i_ctime.tv_nsec = csecs * 10000000;
                inode->i_atime.tv_sec =
-                       date_dos2unix(0, le16_to_cpu(de->adate));
+                       date_dos2unix(0, le16_to_cpu(de->adate),
+                                     sbi->options.tz_utc);
                inode->i_atime.tv_nsec = 0;
        } else
                inode->i_ctime = inode->i_atime = inode->i_mtime;
@@ -495,7 +498,7 @@ static void fat_destroy_inode(struct inode *inode)
        kmem_cache_free(fat_inode_cachep, MSDOS_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct msdos_inode_info *ei = (struct msdos_inode_info *)foo;
 
@@ -591,11 +594,14 @@ retry:
        raw_entry->attr = fat_attr(inode);
        raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
        raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
-       fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
+       fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time,
+                         &raw_entry->date, sbi->options.tz_utc);
        if (sbi->options.isvfat) {
                __le16 atime;
-               fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
-               fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate);
+               fat_date_unix2dos(inode->i_ctime.tv_sec, &raw_entry->ctime,
+                                 &raw_entry->cdate, sbi->options.tz_utc);
+               fat_date_unix2dos(inode->i_atime.tv_sec, &atime,
+                                 &raw_entry->adate, sbi->options.tz_utc);
                raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 +
                        inode->i_ctime.tv_nsec / 10000000;
        }
@@ -836,6 +842,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
        }
        if (sbi->options.flush)
                seq_puts(m, ",flush");
+       if (opts->tz_utc)
+               seq_puts(m, ",tz=UTC");
 
        return 0;
 }
@@ -848,7 +856,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_flush, Opt_err,
+       Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_err,
 };
 
 static match_table_t fat_tokens = {
@@ -883,6 +891,7 @@ static match_table_t fat_tokens = {
        {Opt_obsolate, "cvf_options=%100s"},
        {Opt_obsolate, "posix"},
        {Opt_flush, "flush"},
+       {Opt_tz_utc, "tz=UTC"},
        {Opt_err, NULL},
 };
 static match_table_t msdos_tokens = {
@@ -947,10 +956,11 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
        opts->utf8 = opts->unicode_xlate = 0;
        opts->numtail = 1;
        opts->usefree = opts->nocase = 0;
+       opts->tz_utc = 0;
        *debug = 0;
 
        if (!options)
-               return 0;
+               goto out;
 
        while ((p = strsep(&options, ",")) != NULL) {
                int token;
@@ -1036,6 +1046,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                case Opt_flush:
                        opts->flush = 1;
                        break;
+               case Opt_tz_utc:
+                       opts->tz_utc = 1;
+                       break;
 
                /* msdos specific */
                case Opt_dots:
@@ -1104,10 +1117,13 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                        return -EINVAL;
                }
        }
+
+out:
        /* UTF-8 doesn't provide FAT semantics */
        if (!strcmp(opts->iocharset, "utf8")) {
                printk(KERN_ERR "FAT: utf8 is not a recommended IO charset"
-                      " for FAT filesystems, filesystem will be case sensitive!\n");
+                      " for FAT filesystems, filesystem will be "
+                      "case sensitive!\n");
        }
 
        /* If user doesn't specify allow_utime, it's initialized from dmask. */
index 61f23511eacf41ec34649a84f1cc7e601ff61a68..79fb98ad36d4d2e2913c26bb5ab5b56358594eea 100644 (file)
@@ -142,7 +142,7 @@ static int day_n[] = {
 };
 
 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
-int date_dos2unix(unsigned short time, unsigned short date)
+int date_dos2unix(unsigned short time, unsigned short date, int tz_utc)
 {
        int month, year, secs;
 
@@ -156,16 +156,18 @@ int date_dos2unix(unsigned short time, unsigned short date)
            ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
            month < 2 ? 1 : 0)+3653);
                        /* days since 1.1.70 plus 80's leap day */
-       secs += sys_tz.tz_minuteswest*60;
+       if (!tz_utc)
+               secs += sys_tz.tz_minuteswest*60;
        return secs;
 }
 
 /* Convert linear UNIX date to a MS-DOS time/date pair. */
-void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
+void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int tz_utc)
 {
        int day, year, nl_day, month;
 
-       unix_date -= sys_tz.tz_minuteswest*60;
+       if (!tz_utc)
+               unix_date -= sys_tz.tz_minuteswest*60;
 
        /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
        if (unix_date < 315532800)
index 330a7d7825915f591fa89ca74d8e63fa4efe07f4..61d625136813648c3ced7aa4c6daf344d6700e43 100644 (file)
@@ -64,11 +64,6 @@ static int locate_fd(unsigned int orig_start, int cloexec)
        struct fdtable *fdt;
 
        spin_lock(&files->file_lock);
-
-       error = -EINVAL;
-       if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
-               goto out;
-
 repeat:
        fdt = files_fdtable(files);
        /*
@@ -83,10 +78,6 @@ repeat:
        if (start < fdt->max_fds)
                newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
                                           fdt->max_fds, start);
-       
-       error = -EMFILE;
-       if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
-               goto out;
 
        error = expand_files(files, newfd);
        if (error < 0)
@@ -125,27 +116,30 @@ static int dupfd(struct file *file, unsigned int start, int cloexec)
        return fd;
 }
 
-asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
+asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
 {
        int err = -EBADF;
        struct file * file, *tofree;
        struct files_struct * files = current->files;
        struct fdtable *fdt;
 
+       if ((flags & ~O_CLOEXEC) != 0)
+               return -EINVAL;
+
+       if (unlikely(oldfd == newfd))
+               return -EINVAL;
+
        spin_lock(&files->file_lock);
        if (!(file = fcheck(oldfd)))
                goto out_unlock;
-       err = newfd;
-       if (newfd == oldfd)
-               goto out_unlock;
-       err = -EBADF;
-       if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
-               goto out_unlock;
        get_file(file);                 /* We are now finished with oldfd */
 
        err = expand_files(files, newfd);
-       if (err < 0)
+       if (unlikely(err < 0)) {
+               if (err == -EMFILE)
+                       err = -EBADF;
                goto out_fput;
+       }
 
        /* To avoid races with open() and dup(), we will mark the fd as
         * in-use in the open-file bitmap throughout the entire dup2()
@@ -163,7 +157,10 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
 
        rcu_assign_pointer(fdt->fd[newfd], file);
        FD_SET(newfd, fdt->open_fds);
-       FD_CLR(newfd, fdt->close_on_exec);
+       if (flags & O_CLOEXEC)
+               FD_SET(newfd, fdt->close_on_exec);
+       else
+               FD_CLR(newfd, fdt->close_on_exec);
        spin_unlock(&files->file_lock);
 
        if (tofree)
@@ -181,6 +178,19 @@ out_fput:
        goto out;
 }
 
+asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
+{
+       if (unlikely(newfd == oldfd)) { /* corner case */
+               struct files_struct *files = current->files;
+               rcu_read_lock();
+               if (!fcheck_files(files, oldfd))
+                       oldfd = -EBADF;
+               rcu_read_unlock();
+               return oldfd;
+       }
+       return sys_dup3(oldfd, newfd, 0);
+}
+
 asmlinkage long sys_dup(unsigned int fildes)
 {
        int ret = -EBADF;
@@ -310,6 +320,8 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
        switch (cmd) {
        case F_DUPFD:
        case F_DUPFD_CLOEXEC:
+               if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+                       break;
                get_file(filp);
                err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC);
                break;
index 9785e36f81e730e24dd9f1312e2c38f5e35929a4..987bf94114957beca2250a221778f3f93c20d6d2 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -57,7 +57,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
         *  POSIX.1 says that O_NONBLOCK means return with the FIFO
         *  opened, even when there is no process writing the FIFO.
         */
-               filp->f_op = &read_fifo_fops;
+               filp->f_op = &read_pipefifo_fops;
                pipe->r_counter++;
                if (pipe->readers++ == 0)
                        wake_up_partner(inode);
@@ -86,7 +86,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
                if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
                        goto err;
 
-               filp->f_op = &write_fifo_fops;
+               filp->f_op = &write_pipefifo_fops;
                pipe->w_counter++;
                if (!pipe->writers++)
                        wake_up_partner(inode);
@@ -105,7 +105,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
         *  This implementation will NEVER block on a O_RDWR open, since
         *  the process can at least talk to itself.
         */
-               filp->f_op = &rdwr_fifo_fops;
+               filp->f_op = &rdwr_pipefifo_fops;
 
                pipe->readers++;
                pipe->writers++;
@@ -151,5 +151,5 @@ err_nocleanup:
  * depending on the access mode of the file...
  */
 const struct file_operations def_fifo_fops = {
-       .open           = fifo_open,    /* will set read or write pipe_fops */
+       .open           = fifo_open,    /* will set read_ or write_pipefifo_fops */
 };
index 7b3887e054d0bcb5e0e187c8e1e42691c4fadcd0..d8773b19fe47fd23d6bbec2149679b123a79c139 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -250,9 +250,18 @@ int expand_files(struct files_struct *files, int nr)
        struct fdtable *fdt;
 
        fdt = files_fdtable(files);
+
+       /*
+        * N.B. For clone tasks sharing a files structure, this test
+        * will limit the total number of files that can be opened.
+        */
+       if (nr >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+               return -EMFILE;
+
        /* Do we need to expand? */
        if (nr < fdt->max_fds)
                return 0;
+
        /* Can we expand? */
        if (nr >= sysctl_nr_open)
                return -EMFILE;
index 83084225b4c3b3195520d5a7a441360046d6f230..f45a4493f9e71b5afe52640f453a33bce0603c70 100644 (file)
@@ -120,7 +120,7 @@ struct file *get_empty_filp(void)
 
        tsk = current;
        INIT_LIST_HEAD(&f->f_u.fu_list);
-       atomic_set(&f->f_count, 1);
+       atomic_long_set(&f->f_count, 1);
        rwlock_init(&f->f_owner.lock);
        f->f_uid = tsk->fsuid;
        f->f_gid = tsk->fsgid;
@@ -219,7 +219,7 @@ EXPORT_SYMBOL(init_file);
 
 void fput(struct file *file)
 {
-       if (atomic_dec_and_test(&file->f_count))
+       if (atomic_long_dec_and_test(&file->f_count))
                __fput(file);
 }
 
@@ -294,7 +294,7 @@ struct file *fget(unsigned int fd)
        rcu_read_lock();
        file = fcheck_files(files, fd);
        if (file) {
-               if (!atomic_inc_not_zero(&file->f_count)) {
+               if (!atomic_long_inc_not_zero(&file->f_count)) {
                        /* File object ref couldn't be taken */
                        rcu_read_unlock();
                        return NULL;
@@ -326,7 +326,7 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
                rcu_read_lock();
                file = fcheck_files(files, fd);
                if (file) {
-                       if (atomic_inc_not_zero(&file->f_count))
+                       if (atomic_long_inc_not_zero(&file->f_count))
                                *fput_needed = 1;
                        else
                                /* Didn't get the reference, someone's freed */
@@ -341,7 +341,7 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
 
 void put_filp(struct file *file)
 {
-       if (atomic_dec_and_test(&file->f_count)) {
+       if (atomic_long_dec_and_test(&file->f_count)) {
                security_file_free(file);
                file_kill(file);
                file_free(file);
index 2060bf06b90625cf920aa08f87da07bd286a193f..fd03330cadeb135979c5229eb861c89155df8de9 100644 (file)
@@ -97,7 +97,7 @@ void fuse_invalidate_attr(struct inode *inode)
  * timeout is unknown (unlink, rmdir, rename and in some cases
  * lookup)
  */
-static void fuse_invalidate_entry_cache(struct dentry *entry)
+void fuse_invalidate_entry_cache(struct dentry *entry)
 {
        fuse_dentry_settime(entry, 0);
 }
@@ -112,18 +112,16 @@ static void fuse_invalidate_entry(struct dentry *entry)
        fuse_invalidate_entry_cache(entry);
 }
 
-static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
-                            struct dentry *entry,
+static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
+                            u64 nodeid, struct qstr *name,
                             struct fuse_entry_out *outarg)
 {
-       struct fuse_conn *fc = get_fuse_conn(dir);
-
        memset(outarg, 0, sizeof(struct fuse_entry_out));
        req->in.h.opcode = FUSE_LOOKUP;
-       req->in.h.nodeid = get_node_id(dir);
+       req->in.h.nodeid = nodeid;
        req->in.numargs = 1;
-       req->in.args[0].size = entry->d_name.len + 1;
-       req->in.args[0].value = entry->d_name.name;
+       req->in.args[0].size = name->len + 1;
+       req->in.args[0].value = name->name;
        req->out.numargs = 1;
        if (fc->minor < 9)
                req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
@@ -189,7 +187,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
                attr_version = fuse_get_attr_version(fc);
 
                parent = dget_parent(entry);
-               fuse_lookup_init(req, parent->d_inode, entry, &outarg);
+               fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
+                                &entry->d_name, &outarg);
                request_send(fc, req);
                dput(parent);
                err = req->out.h.error;
@@ -225,7 +224,7 @@ static int invalid_nodeid(u64 nodeid)
        return !nodeid || nodeid == FUSE_ROOT_ID;
 }
 
-static struct dentry_operations fuse_dentry_operations = {
+struct dentry_operations fuse_dentry_operations = {
        .d_revalidate   = fuse_dentry_revalidate,
 };
 
@@ -239,85 +238,127 @@ int fuse_valid_type(int m)
  * Add a directory inode to a dentry, ensuring that no other dentry
  * refers to this inode.  Called with fc->inst_mutex.
  */
-static int fuse_d_add_directory(struct dentry *entry, struct inode *inode)
+static struct dentry *fuse_d_add_directory(struct dentry *entry,
+                                          struct inode *inode)
 {
        struct dentry *alias = d_find_alias(inode);
-       if (alias) {
+       if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
                /* This tries to shrink the subtree below alias */
                fuse_invalidate_entry(alias);
                dput(alias);
                if (!list_empty(&inode->i_dentry))
-                       return -EBUSY;
+                       return ERR_PTR(-EBUSY);
+       } else {
+               dput(alias);
        }
-       d_add(entry, inode);
-       return 0;
+       return d_splice_alias(inode, entry);
 }
 
-static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
-                                 struct nameidata *nd)
+int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
+                    struct fuse_entry_out *outarg, struct inode **inode)
 {
-       int err;
-       struct fuse_entry_out outarg;
-       struct inode *inode = NULL;
-       struct fuse_conn *fc = get_fuse_conn(dir);
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
        struct fuse_req *req;
        struct fuse_req *forget_req;
        u64 attr_version;
+       int err;
 
-       if (entry->d_name.len > FUSE_NAME_MAX)
-               return ERR_PTR(-ENAMETOOLONG);
+       *inode = NULL;
+       err = -ENAMETOOLONG;
+       if (name->len > FUSE_NAME_MAX)
+               goto out;
 
        req = fuse_get_req(fc);
+       err = PTR_ERR(req);
        if (IS_ERR(req))
-               return ERR_CAST(req);
+               goto out;
 
        forget_req = fuse_get_req(fc);
+       err = PTR_ERR(forget_req);
        if (IS_ERR(forget_req)) {
                fuse_put_request(fc, req);
-               return ERR_CAST(forget_req);
+               goto out;
        }
 
        attr_version = fuse_get_attr_version(fc);
 
-       fuse_lookup_init(req, dir, entry, &outarg);
+       fuse_lookup_init(fc, req, nodeid, name, outarg);
        request_send(fc, req);
        err = req->out.h.error;
        fuse_put_request(fc, req);
        /* Zero nodeid is same as -ENOENT, but with valid timeout */
-       if (!err && outarg.nodeid &&
-           (invalid_nodeid(outarg.nodeid) ||
-            !fuse_valid_type(outarg.attr.mode)))
-               err = -EIO;
-       if (!err && outarg.nodeid) {
-               inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
-                                 &outarg.attr, entry_attr_timeout(&outarg),
-                                 attr_version);
-               if (!inode) {
-                       fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
-                       return ERR_PTR(-ENOMEM);
-               }
+       if (err || !outarg->nodeid)
+               goto out_put_forget;
+
+       err = -EIO;
+       if (!outarg->nodeid)
+               goto out_put_forget;
+       if (!fuse_valid_type(outarg->attr.mode))
+               goto out_put_forget;
+
+       *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
+                          &outarg->attr, entry_attr_timeout(outarg),
+                          attr_version);
+       err = -ENOMEM;
+       if (!*inode) {
+               fuse_send_forget(fc, forget_req, outarg->nodeid, 1);
+               goto out;
        }
+       err = 0;
+
+ out_put_forget:
        fuse_put_request(fc, forget_req);
-       if (err && err != -ENOENT)
-               return ERR_PTR(err);
+ out:
+       return err;
+}
+
+static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
+                                 struct nameidata *nd)
+{
+       int err;
+       struct fuse_entry_out outarg;
+       struct inode *inode;
+       struct dentry *newent;
+       struct fuse_conn *fc = get_fuse_conn(dir);
+       bool outarg_valid = true;
+
+       err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
+                              &outarg, &inode);
+       if (err == -ENOENT) {
+               outarg_valid = false;
+               err = 0;
+       }
+       if (err)
+               goto out_err;
+
+       err = -EIO;
+       if (inode && get_node_id(inode) == FUSE_ROOT_ID)
+               goto out_iput;
 
        if (inode && S_ISDIR(inode->i_mode)) {
                mutex_lock(&fc->inst_mutex);
-               err = fuse_d_add_directory(entry, inode);
+               newent = fuse_d_add_directory(entry, inode);
                mutex_unlock(&fc->inst_mutex);
-               if (err) {
-                       iput(inode);
-                       return ERR_PTR(err);
-               }
-       } else
-               d_add(entry, inode);
+               err = PTR_ERR(newent);
+               if (IS_ERR(newent))
+                       goto out_iput;
+       } else {
+               newent = d_splice_alias(inode, entry);
+       }
 
+       entry = newent ? newent : entry;
        entry->d_op = &fuse_dentry_operations;
-       if (!err)
+       if (outarg_valid)
                fuse_change_entry_timeout(entry, &outarg);
        else
                fuse_invalidate_entry_cache(entry);
-       return NULL;
+
+       return newent;
+
+ out_iput:
+       iput(inode);
+ out_err:
+       return ERR_PTR(err);
 }
 
 /*
@@ -857,7 +898,7 @@ static int fuse_access(struct inode *inode, int mask)
                return PTR_ERR(req);
 
        memset(&inarg, 0, sizeof(inarg));
-       inarg.mask = mask;
+       inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
        req->in.h.opcode = FUSE_ACCESS;
        req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
@@ -886,7 +927,7 @@ static int fuse_access(struct inode *inode, int mask)
  * access request is sent.  Execute permission is still checked
  * locally based on file mode.
  */
-static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
+static int fuse_permission(struct inode *inode, int mask)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        bool refreshed = false;
@@ -921,7 +962,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
                   exist.  So if permissions are revoked this won't be
                   noticed immediately, only after the attribute
                   timeout has expired */
-       } else if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) {
+       } else if (mask & MAY_ACCESS) {
                err = fuse_access(inode, mask);
        } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
                if (!(inode->i_mode & S_IXUGO)) {
index 8092f0d9fd1fa590ac87f7f0ec7a79331760acb6..2bada6bbc317dbeab3887fbcd26ed9fe630b6148 100644 (file)
@@ -893,7 +893,7 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        if (count == 0)
                goto out;
 
-       err = remove_suid(file->f_path.dentry);
+       err = file_remove_suid(file);
        if (err)
                goto out;
 
@@ -1341,6 +1341,11 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
        pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
        int err;
 
+       if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
+               /* NLM needs asynchronous locks, which we don't support yet */
+               return -ENOLCK;
+       }
+
        /* Unlock on close is handled by the flush method */
        if (fl->fl_flags & FL_CLOSE)
                return 0;
@@ -1365,7 +1370,9 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
        struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
 
-       if (cmd == F_GETLK) {
+       if (cmd == F_CANCELLK) {
+               err = 0;
+       } else if (cmd == F_GETLK) {
                if (fc->no_lock) {
                        posix_test_lock(file, fl);
                        err = 0;
@@ -1373,7 +1380,7 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
                        err = fuse_getlk(file, fl);
        } else {
                if (fc->no_lock)
-                       err = posix_lock_file_wait(file, fl);
+                       err = posix_lock_file(file, fl, NULL);
                else
                        err = fuse_setlk(file, fl, 0);
        }
index bae948657c4fdfd268e86912c6b4fa6c1f944851..3a876076bdd1392c93b6a838af53eef104f8461d 100644 (file)
@@ -363,6 +363,9 @@ struct fuse_conn {
        /** Do not send separate SETATTR request before open(O_TRUNC)  */
        unsigned atomic_o_trunc : 1;
 
+       /** Filesystem supports NFS exporting.  Only set in INIT */
+       unsigned export_support : 1;
+
        /*
         * The following bitfields are only for optimization purposes
         * and hence races in setting them will not cause malfunction
@@ -464,6 +467,8 @@ static inline u64 get_node_id(struct inode *inode)
 /** Device operations */
 extern const struct file_operations fuse_dev_operations;
 
+extern struct dentry_operations fuse_dentry_operations;
+
 /**
  * Get a filled in inode
  */
@@ -471,6 +476,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
                        int generation, struct fuse_attr *attr,
                        u64 attr_valid, u64 attr_version);
 
+int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
+                    struct fuse_entry_out *outarg, struct inode **inode);
+
 /**
  * Send FORGET command
  */
@@ -604,6 +612,8 @@ void fuse_abort_conn(struct fuse_conn *fc);
  */
 void fuse_invalidate_attr(struct inode *inode);
 
+void fuse_invalidate_entry_cache(struct dentry *entry);
+
 /**
  * Acquire reference to fuse_conn
  */
index 3141690558c8aa6029128f7c2d8a5b9fc742696d..d2249f174e207b109e30eaea1701591d0db4631d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/statfs.h>
 #include <linux/random.h>
 #include <linux/sched.h>
+#include <linux/exportfs.h>
 
 MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
 MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -552,6 +553,174 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
        return fuse_iget(sb, 1, 0, &attr, 0, 0);
 }
 
+struct fuse_inode_handle
+{
+       u64 nodeid;
+       u32 generation;
+};
+
+static struct dentry *fuse_get_dentry(struct super_block *sb,
+                                     struct fuse_inode_handle *handle)
+{
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
+       struct inode *inode;
+       struct dentry *entry;
+       int err = -ESTALE;
+
+       if (handle->nodeid == 0)
+               goto out_err;
+
+       inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid);
+       if (!inode) {
+               struct fuse_entry_out outarg;
+               struct qstr name;
+
+               if (!fc->export_support)
+                       goto out_err;
+
+               name.len = 1;
+               name.name = ".";
+               err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg,
+                                      &inode);
+               if (err && err != -ENOENT)
+                       goto out_err;
+               if (err || !inode) {
+                       err = -ESTALE;
+                       goto out_err;
+               }
+               err = -EIO;
+               if (get_node_id(inode) != handle->nodeid)
+                       goto out_iput;
+       }
+       err = -ESTALE;
+       if (inode->i_generation != handle->generation)
+               goto out_iput;
+
+       entry = d_alloc_anon(inode);
+       err = -ENOMEM;
+       if (!entry)
+               goto out_iput;
+
+       if (get_node_id(inode) != FUSE_ROOT_ID) {
+               entry->d_op = &fuse_dentry_operations;
+               fuse_invalidate_entry_cache(entry);
+       }
+
+       return entry;
+
+ out_iput:
+       iput(inode);
+ out_err:
+       return ERR_PTR(err);
+}
+
+static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
+                          int connectable)
+{
+       struct inode *inode = dentry->d_inode;
+       bool encode_parent = connectable && !S_ISDIR(inode->i_mode);
+       int len = encode_parent ? 6 : 3;
+       u64 nodeid;
+       u32 generation;
+
+       if (*max_len < len)
+               return  255;
+
+       nodeid = get_fuse_inode(inode)->nodeid;
+       generation = inode->i_generation;
+
+       fh[0] = (u32)(nodeid >> 32);
+       fh[1] = (u32)(nodeid & 0xffffffff);
+       fh[2] = generation;
+
+       if (encode_parent) {
+               struct inode *parent;
+
+               spin_lock(&dentry->d_lock);
+               parent = dentry->d_parent->d_inode;
+               nodeid = get_fuse_inode(parent)->nodeid;
+               generation = parent->i_generation;
+               spin_unlock(&dentry->d_lock);
+
+               fh[3] = (u32)(nodeid >> 32);
+               fh[4] = (u32)(nodeid & 0xffffffff);
+               fh[5] = generation;
+       }
+
+       *max_len = len;
+       return encode_parent ? 0x82 : 0x81;
+}
+
+static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
+               struct fid *fid, int fh_len, int fh_type)
+{
+       struct fuse_inode_handle handle;
+
+       if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3)
+               return NULL;
+
+       handle.nodeid = (u64) fid->raw[0] << 32;
+       handle.nodeid |= (u64) fid->raw[1];
+       handle.generation = fid->raw[2];
+       return fuse_get_dentry(sb, &handle);
+}
+
+static struct dentry *fuse_fh_to_parent(struct super_block *sb,
+               struct fid *fid, int fh_len, int fh_type)
+{
+       struct fuse_inode_handle parent;
+
+       if (fh_type != 0x82 || fh_len < 6)
+               return NULL;
+
+       parent.nodeid = (u64) fid->raw[3] << 32;
+       parent.nodeid |= (u64) fid->raw[4];
+       parent.generation = fid->raw[5];
+       return fuse_get_dentry(sb, &parent);
+}
+
+static struct dentry *fuse_get_parent(struct dentry *child)
+{
+       struct inode *child_inode = child->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(child_inode);
+       struct inode *inode;
+       struct dentry *parent;
+       struct fuse_entry_out outarg;
+       struct qstr name;
+       int err;
+
+       if (!fc->export_support)
+               return ERR_PTR(-ESTALE);
+
+       name.len = 2;
+       name.name = "..";
+       err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode),
+                              &name, &outarg, &inode);
+       if (err && err != -ENOENT)
+               return ERR_PTR(err);
+       if (err || !inode)
+               return ERR_PTR(-ESTALE);
+
+       parent = d_alloc_anon(inode);
+       if (!parent) {
+               iput(inode);
+               return ERR_PTR(-ENOMEM);
+       }
+       if (get_node_id(inode) != FUSE_ROOT_ID) {
+               parent->d_op = &fuse_dentry_operations;
+               fuse_invalidate_entry_cache(parent);
+       }
+
+       return parent;
+}
+
+static const struct export_operations fuse_export_operations = {
+       .fh_to_dentry   = fuse_fh_to_dentry,
+       .fh_to_parent   = fuse_fh_to_parent,
+       .encode_fh      = fuse_encode_fh,
+       .get_parent     = fuse_get_parent,
+};
+
 static const struct super_operations fuse_super_operations = {
        .alloc_inode    = fuse_alloc_inode,
        .destroy_inode  = fuse_destroy_inode,
@@ -581,6 +750,11 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                                fc->no_lock = 1;
                        if (arg->flags & FUSE_ATOMIC_O_TRUNC)
                                fc->atomic_o_trunc = 1;
+                       if (arg->minor >= 9) {
+                               /* LOOKUP has dependency on proto version */
+                               if (arg->flags & FUSE_EXPORT_SUPPORT)
+                                       fc->export_support = 1;
+                       }
                        if (arg->flags & FUSE_BIG_WRITES)
                                fc->big_writes = 1;
                } else {
@@ -607,7 +781,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
        arg->minor = FUSE_KERNEL_MINOR_VERSION;
        arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
        arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
-               FUSE_BIG_WRITES;
+               FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES;
        req->in.h.opcode = FUSE_INIT;
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(*arg);
@@ -652,6 +826,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_magic = FUSE_SUPER_MAGIC;
        sb->s_op = &fuse_super_operations;
        sb->s_maxbytes = MAX_LFS_FILESIZE;
+       sb->s_export_op = &fuse_export_operations;
 
        file = fget(d.fd);
        if (!file)
@@ -781,7 +956,7 @@ static inline void unregister_fuseblk(void)
 }
 #endif
 
-static void fuse_inode_init_once(struct kmem_cache *cachep, void *foo)
+static void fuse_inode_init_once(void *foo)
 {
        struct inode * inode = foo;
 
index 6da0ab355b8a6e6672ae256ae881289b72c9edb0..8b0806a3294863392c914aa262b2a4cb08f4c98e 100644 (file)
@@ -448,7 +448,7 @@ struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
        struct qstr qstr;
        struct inode *inode;
        gfs2_str2qstr(&qstr, name);
-       inode = gfs2_lookupi(dip, &qstr, 1, NULL);
+       inode = gfs2_lookupi(dip, &qstr, 1);
        /* gfs2_lookupi has inconsistent callers: vfs
         * related routines expect NULL for no entry found,
         * gfs2_lookup_simple callers expect ENOENT
@@ -477,7 +477,7 @@ struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
  */
 
 struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
-                          int is_root, struct nameidata *nd)
+                          int is_root)
 {
        struct super_block *sb = dir->i_sb;
        struct gfs2_inode *dip = GFS2_I(dir);
@@ -1173,7 +1173,7 @@ int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
                        break;
                }
 
-               tmp = gfs2_lookupi(dir, &dotdot, 1, NULL);
+               tmp = gfs2_lookupi(dir, &dotdot, 1);
                if (IS_ERR(tmp)) {
                        error = PTR_ERR(tmp);
                        break;
index 6074c2506f75b3fced5934ff64e159b06b45b409..58f9607d6a8675694769b978bd93f17e56da47dc 100644 (file)
@@ -83,7 +83,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip);
 int gfs2_dinode_dealloc(struct gfs2_inode *inode);
 int gfs2_change_nlink(struct gfs2_inode *ip, int diff);
 struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
-                          int is_root, struct nameidata *nd);
+                          int is_root);
 struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
                           unsigned int mode, dev_t dev);
 int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
index bcc668d0fadd0a2d078efa861cbd4942d527914e..bb2cc303ac2921f2fc16675dbdb50e8abadc3f65 100644 (file)
@@ -24,7 +24,7 @@
 #include "util.h"
 #include "glock.h"
 
-static void gfs2_init_inode_once(struct kmem_cache *cachep, void *foo)
+static void gfs2_init_inode_once(void *foo)
 {
        struct gfs2_inode *ip = foo;
 
@@ -33,7 +33,7 @@ static void gfs2_init_inode_once(struct kmem_cache *cachep, void *foo)
        ip->i_alloc = NULL;
 }
 
-static void gfs2_init_glock_once(struct kmem_cache *cachep, void *foo)
+static void gfs2_init_glock_once(void *foo)
 {
        struct gfs2_glock *gl = foo;
 
index 990d9f4bc463588df8f24e94f9439f4750e8f951..9cda8536530cb04d40a3a1e85ccc128c1f3baba1 100644 (file)
@@ -134,7 +134,7 @@ static struct dentry *gfs2_get_parent(struct dentry *child)
        struct dentry *dentry;
 
        gfs2_str2qstr(&dotdot, "..");
-       inode = gfs2_lookupi(child->d_inode, &dotdot, 1, NULL);
+       inode = gfs2_lookupi(child->d_inode, &dotdot, 1);
 
        if (!inode)
                return ERR_PTR(-ENOENT);
index 1e252dfc52940c745dea61137afc386dbe183cd7..e2c62f73a7783db388f8da70fee51874cf9e4879 100644 (file)
@@ -74,7 +74,7 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
                        return PTR_ERR(inode);
                }
 
-               inode = gfs2_lookupi(dir, &dentry->d_name, 0, nd);
+               inode = gfs2_lookupi(dir, &dentry->d_name, 0);
                if (inode) {
                        if (!IS_ERR(inode)) {
                                gfs2_holder_uninit(ghs);
@@ -109,7 +109,7 @@ static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
 
        dentry->d_op = &gfs2_dops;
 
-       inode = gfs2_lookupi(dir, &dentry->d_name, 0, nd);
+       inode = gfs2_lookupi(dir, &dentry->d_name, 0);
        if (inode && IS_ERR(inode))
                return ERR_CAST(inode);
 
@@ -915,12 +915,6 @@ int gfs2_permission(struct inode *inode, int mask)
        return error;
 }
 
-static int gfs2_iop_permission(struct inode *inode, int mask,
-                              struct nameidata *nd)
-{
-       return gfs2_permission(inode, mask);
-}
-
 static int setattr_size(struct inode *inode, struct iattr *attr)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
@@ -1150,7 +1144,7 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
 }
 
 const struct inode_operations gfs2_file_iops = {
-       .permission = gfs2_iop_permission,
+       .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
        .setxattr = gfs2_setxattr,
@@ -1169,7 +1163,7 @@ const struct inode_operations gfs2_dir_iops = {
        .rmdir = gfs2_rmdir,
        .mknod = gfs2_mknod,
        .rename = gfs2_rename,
-       .permission = gfs2_iop_permission,
+       .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
        .setxattr = gfs2_setxattr,
@@ -1181,7 +1175,7 @@ const struct inode_operations gfs2_dir_iops = {
 const struct inode_operations gfs2_symlink_iops = {
        .readlink = gfs2_readlink,
        .follow_link = gfs2_follow_link,
-       .permission = gfs2_iop_permission,
+       .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
        .setxattr = gfs2_setxattr,
index 63a8a902d9db16029898c8d1caf74e5a198aac48..ca831991cbc2d8a9cd0e82ee1ec6dc8f839d2d13 100644 (file)
@@ -389,7 +389,7 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
                        break;
 
                INIT_LIST_HEAD(&jd->extent_list);
-               jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1, NULL);
+               jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1);
                if (!jd->jd_inode || IS_ERR(jd->jd_inode)) {
                        if (!jd->jd_inode)
                                error = -ENOENT;
index 24e75798ddf014c747d9537dfe475b0e5326c884..c6e97366e8ac3f362d0f08d63d0234d837e14103 100644 (file)
@@ -145,7 +145,7 @@ u32 hfs_vbm_search_free(struct super_block *sb, u32 goal, u32 *num_bits)
        if (!*num_bits)
                return 0;
 
-       down(&HFS_SB(sb)->bitmap_lock);
+       mutex_lock(&HFS_SB(sb)->bitmap_lock);
        bitmap = HFS_SB(sb)->bitmap;
 
        pos = hfs_find_set_zero_bits(bitmap, HFS_SB(sb)->fs_ablocks, goal, num_bits);
@@ -162,7 +162,7 @@ u32 hfs_vbm_search_free(struct super_block *sb, u32 goal, u32 *num_bits)
        HFS_SB(sb)->free_ablocks -= *num_bits;
        hfs_bitmap_dirty(sb);
 out:
-       up(&HFS_SB(sb)->bitmap_lock);
+       mutex_unlock(&HFS_SB(sb)->bitmap_lock);
        return pos;
 }
 
@@ -205,7 +205,7 @@ int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count)
        if ((start + count) > HFS_SB(sb)->fs_ablocks)
                return -2;
 
-       down(&HFS_SB(sb)->bitmap_lock);
+       mutex_lock(&HFS_SB(sb)->bitmap_lock);
        /* bitmap is always on a 32-bit boundary */
        curr = HFS_SB(sb)->bitmap + (start / 32);
        len = count;
@@ -236,7 +236,7 @@ int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count)
        }
 out:
        HFS_SB(sb)->free_ablocks += len;
-       up(&HFS_SB(sb)->bitmap_lock);
+       mutex_unlock(&HFS_SB(sb)->bitmap_lock);
        hfs_bitmap_dirty(sb);
 
        return 0;
index f6621a785202b9f3d26f562bd7402cfbedb589a9..9b9d6395bad36127b04a67b8048d149e2bc89d3a 100644 (file)
@@ -40,7 +40,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
        {
        struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
        HFS_I(tree->inode)->flags = 0;
-       init_MUTEX(&HFS_I(tree->inode)->extents_lock);
+       mutex_init(&HFS_I(tree->inode)->extents_lock);
        switch (id) {
        case HFS_EXT_CNID:
                hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize,
index c176f67ba0a5488c116d283b444dc66f0844fa6d..2c16316d291794a875b5afc36908829cfe1f5ce5 100644 (file)
@@ -343,16 +343,16 @@ int hfs_get_block(struct inode *inode, sector_t block,
                goto done;
        }
 
-       down(&HFS_I(inode)->extents_lock);
+       mutex_lock(&HFS_I(inode)->extents_lock);
        res = hfs_ext_read_extent(inode, ablock);
        if (!res)
                dblock = hfs_ext_find_block(HFS_I(inode)->cached_extents,
                                            ablock - HFS_I(inode)->cached_start);
        else {
-               up(&HFS_I(inode)->extents_lock);
+               mutex_unlock(&HFS_I(inode)->extents_lock);
                return -EIO;
        }
-       up(&HFS_I(inode)->extents_lock);
+       mutex_unlock(&HFS_I(inode)->extents_lock);
 
 done:
        map_bh(bh_result, sb, HFS_SB(sb)->fs_start +
@@ -375,7 +375,7 @@ int hfs_extend_file(struct inode *inode)
        u32 start, len, goal;
        int res;
 
-       down(&HFS_I(inode)->extents_lock);
+       mutex_lock(&HFS_I(inode)->extents_lock);
        if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks)
                goal = hfs_ext_lastblock(HFS_I(inode)->first_extents);
        else {
@@ -425,7 +425,7 @@ int hfs_extend_file(struct inode *inode)
                        goto insert_extent;
        }
 out:
-       up(&HFS_I(inode)->extents_lock);
+       mutex_unlock(&HFS_I(inode)->extents_lock);
        if (!res) {
                HFS_I(inode)->alloc_blocks += len;
                mark_inode_dirty(inode);
@@ -487,7 +487,7 @@ void hfs_file_truncate(struct inode *inode)
        if (blk_cnt == alloc_cnt)
                goto out;
 
-       down(&HFS_I(inode)->extents_lock);
+       mutex_lock(&HFS_I(inode)->extents_lock);
        hfs_find_init(HFS_SB(sb)->ext_tree, &fd);
        while (1) {
                if (alloc_cnt == HFS_I(inode)->first_blocks) {
@@ -514,7 +514,7 @@ void hfs_file_truncate(struct inode *inode)
                hfs_brec_remove(&fd);
        }
        hfs_find_exit(&fd);
-       up(&HFS_I(inode)->extents_lock);
+       mutex_unlock(&HFS_I(inode)->extents_lock);
 
        HFS_I(inode)->alloc_blocks = blk_cnt;
 out:
index 147374b6f67525871efd8f7abb8320bd838a3be4..9955232fdf8c977abae64e327ca250468ee74654 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <linux/mutex.h>
 #include <linux/buffer_head.h>
 #include <linux/fs.h>
 
@@ -53,7 +54,7 @@ struct hfs_inode_info {
        struct list_head open_dir_list;
        struct inode *rsrc_inode;
 
-       struct semaphore extents_lock;
+       struct mutex extents_lock;
 
        u16 alloc_blocks, clump_blocks;
        sector_t fs_blocks;
@@ -139,7 +140,7 @@ struct hfs_sb_info {
 
        struct nls_table *nls_io, *nls_disk;
 
-       struct semaphore bitmap_lock;
+       struct mutex bitmap_lock;
 
        unsigned long flags;
 
index 97f8446c4ff415e8646a868ecce82d6ef77c20eb..7e19835efa2ea91675980a18e963281a02d46bb8 100644 (file)
@@ -150,7 +150,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
        if (!inode)
                return NULL;
 
-       init_MUTEX(&HFS_I(inode)->extents_lock);
+       mutex_init(&HFS_I(inode)->extents_lock);
        INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
        hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
        inode->i_ino = HFS_SB(sb)->next_id++;
@@ -281,7 +281,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
 
        HFS_I(inode)->flags = 0;
        HFS_I(inode)->rsrc_inode = NULL;
-       init_MUTEX(&HFS_I(inode)->extents_lock);
+       mutex_init(&HFS_I(inode)->extents_lock);
        INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
 
        /* Initialize the inode */
@@ -511,8 +511,7 @@ void hfs_clear_inode(struct inode *inode)
        }
 }
 
-static int hfs_permission(struct inode *inode, int mask,
-                         struct nameidata *nd)
+static int hfs_permission(struct inode *inode, int mask)
 {
        if (S_ISREG(inode->i_mode) && mask & MAY_EXEC)
                return 0;
@@ -523,8 +522,6 @@ static int hfs_file_open(struct inode *inode, struct file *file)
 {
        if (HFS_IS_RSRC(inode))
                inode = HFS_I(inode)->rsrc_inode;
-       if (atomic_read(&file->f_count) != 1)
-               return 0;
        atomic_inc(&HFS_I(inode)->opencnt);
        return 0;
 }
@@ -535,8 +532,6 @@ static int hfs_file_release(struct inode *inode, struct file *file)
 
        if (HFS_IS_RSRC(inode))
                inode = HFS_I(inode)->rsrc_inode;
-       if (atomic_read(&file->f_count) != 0)
-               return 0;
        if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) {
                mutex_lock(&inode->i_mutex);
                hfs_file_truncate(inode);
index 8cf67974adf60ad79f1b88da04ba4d4fb71f3b68..4abb1047c68992806125c1ad003e91a9f0cdbd41 100644 (file)
@@ -372,7 +372,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_op = &hfs_super_operations;
        sb->s_flags |= MS_NODIRATIME;
-       init_MUTEX(&sbi->bitmap_lock);
+       mutex_init(&sbi->bitmap_lock);
 
        res = hfs_mdb_get(sb);
        if (res) {
@@ -432,7 +432,7 @@ static struct file_system_type hfs_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-static void hfs_init_once(struct kmem_cache *cachep, void *p)
+static void hfs_init_once(void *p)
 {
        struct hfs_inode_info *i = p;
 
index 12e899cd78866543edb5bfe6510ce113ced5d721..fec8f61227ffb28792a7b94f30417f003d786882 100644 (file)
@@ -199,16 +199,16 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
                goto done;
        }
 
-       down(&HFSPLUS_I(inode).extents_lock);
+       mutex_lock(&HFSPLUS_I(inode).extents_lock);
        res = hfsplus_ext_read_extent(inode, ablock);
        if (!res) {
                dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock -
                                             HFSPLUS_I(inode).cached_start);
        } else {
-               up(&HFSPLUS_I(inode).extents_lock);
+               mutex_unlock(&HFSPLUS_I(inode).extents_lock);
                return -EIO;
        }
-       up(&HFSPLUS_I(inode).extents_lock);
+       mutex_unlock(&HFSPLUS_I(inode).extents_lock);
 
 done:
        dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock);
@@ -355,7 +355,7 @@ int hfsplus_file_extend(struct inode *inode)
                return -ENOSPC;
        }
 
-       down(&HFSPLUS_I(inode).extents_lock);
+       mutex_lock(&HFSPLUS_I(inode).extents_lock);
        if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks)
                goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents);
        else {
@@ -408,7 +408,7 @@ int hfsplus_file_extend(struct inode *inode)
                        goto insert_extent;
        }
 out:
-       up(&HFSPLUS_I(inode).extents_lock);
+       mutex_unlock(&HFSPLUS_I(inode).extents_lock);
        if (!res) {
                HFSPLUS_I(inode).alloc_blocks += len;
                mark_inode_dirty(inode);
@@ -465,7 +465,7 @@ void hfsplus_file_truncate(struct inode *inode)
        if (blk_cnt == alloc_cnt)
                goto out;
 
-       down(&HFSPLUS_I(inode).extents_lock);
+       mutex_lock(&HFSPLUS_I(inode).extents_lock);
        hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
        while (1) {
                if (alloc_cnt == HFSPLUS_I(inode).first_blocks) {
@@ -492,7 +492,7 @@ void hfsplus_file_truncate(struct inode *inode)
                hfs_brec_remove(&fd);
        }
        hfs_find_exit(&fd);
-       up(&HFSPLUS_I(inode).extents_lock);
+       mutex_unlock(&HFSPLUS_I(inode).extents_lock);
 
        HFSPLUS_I(inode).alloc_blocks = blk_cnt;
 out:
index 9e59537b43d56ef0ca178acce4ec900b7d50fcff..f027a905225fc5f7a5c2dfe8b5d1e0764ec96c80 100644 (file)
@@ -11,6 +11,7 @@
 #define _LINUX_HFSPLUS_FS_H
 
 #include <linux/fs.h>
+#include <linux/mutex.h>
 #include <linux/buffer_head.h>
 #include "hfsplus_raw.h"
 
@@ -154,7 +155,7 @@ struct hfsplus_sb_info {
 
 
 struct hfsplus_inode_info {
-       struct semaphore extents_lock;
+       struct mutex extents_lock;
        u32 clump_blocks, alloc_blocks;
        sector_t fs_blocks;
        /* Allocation extents from catalog record or volume header */
index 67e1c8b467c496565359331e79ca7c706166a30d..b085d64a2b672580e328be86af33475e87544f6e 100644 (file)
@@ -163,7 +163,7 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
 
        inode->i_ino = dir->i_ino;
        INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
-       init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+       mutex_init(&HFSPLUS_I(inode).extents_lock);
        HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC;
 
        hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
@@ -238,7 +238,7 @@ static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
        perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev);
 }
 
-static int hfsplus_permission(struct inode *inode, int mask, struct nameidata *nd)
+static int hfsplus_permission(struct inode *inode, int mask)
 {
        /* MAY_EXEC is also used for lookup, if no x bit is set allow lookup,
         * open_exec has the same test, so it's still not executable, if a x bit
@@ -254,8 +254,6 @@ static int hfsplus_file_open(struct inode *inode, struct file *file)
 {
        if (HFSPLUS_IS_RSRC(inode))
                inode = HFSPLUS_I(inode).rsrc_inode;
-       if (atomic_read(&file->f_count) != 1)
-               return 0;
        atomic_inc(&HFSPLUS_I(inode).opencnt);
        return 0;
 }
@@ -266,8 +264,6 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
 
        if (HFSPLUS_IS_RSRC(inode))
                inode = HFSPLUS_I(inode).rsrc_inode;
-       if (atomic_read(&file->f_count) != 0)
-               return 0;
        if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) {
                mutex_lock(&inode->i_mutex);
                hfsplus_file_truncate(inode);
@@ -316,7 +312,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
        inode->i_nlink = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
        INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
-       init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+       mutex_init(&HFSPLUS_I(inode).extents_lock);
        atomic_set(&HFSPLUS_I(inode).opencnt, 0);
        HFSPLUS_I(inode).flags = 0;
        memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec));
index ce97a54518d81d8b904c7a01c336133516547eb3..e834e578c93f8f475f0194831a214e8eb4534138 100644 (file)
@@ -34,7 +34,7 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
                return inode;
 
        INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
-       init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+       mutex_init(&HFSPLUS_I(inode).extents_lock);
        HFSPLUS_I(inode).flags = 0;
        HFSPLUS_I(inode).rsrc_inode = NULL;
        atomic_set(&HFSPLUS_I(inode).opencnt, 0);
@@ -485,7 +485,7 @@ static struct file_system_type hfsplus_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-static void hfsplus_init_once(struct kmem_cache *cachep, void *p)
+static void hfsplus_init_once(void *p)
 {
        struct hfsplus_inode_info *i = p;
 
index 5222345ddccf6525a13cd74fe801da1bde50a304..d6ecabf4d231f2a9aa9f1cf5b5e1c061ea28cf6c 100644 (file)
@@ -822,7 +822,7 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,
        return err;
 }
 
-int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
+int hostfs_permission(struct inode *ino, int desired)
 {
        char *name;
        int r = 0, w = 0, x = 0, err;
index d256559b4104c5ff90370a6d6690e40935c6f1b8..d9c59a775449ee9abfc27e24ed898ce17d05251a 100644 (file)
@@ -415,7 +415,7 @@ again:
                d_drop(dentry);
                spin_lock(&dentry->d_lock);
                if (atomic_read(&dentry->d_count) > 1 ||
-                   permission(inode, MAY_WRITE, NULL) ||
+                   generic_permission(inode, MAY_WRITE, NULL) ||
                    !S_ISREG(inode->i_mode) ||
                    get_write_access(inode)) {
                        spin_unlock(&dentry->d_lock);
index f63a699ec659c076263a221c72414f1cdc111a5b..b8ae9c90ada0e9a7c9fbd9a93a6d5ddb8d8eb276 100644 (file)
@@ -173,7 +173,7 @@ static void hpfs_destroy_inode(struct inode *inode)
        kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo;
 
index 65077aa90f0a74ea405d25ff5796fe3ef3442be1..2b3d1828db99a2a68a3e5fef961f0f6740cf04c8 100644 (file)
@@ -655,20 +655,13 @@ static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
        return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd);
 }
 
-int hppfs_permission(struct inode *inode, int mask, struct nameidata *nd)
-{
-       return generic_permission(inode, mask, NULL);
-}
-
 static const struct inode_operations hppfs_dir_iops = {
        .lookup         = hppfs_lookup,
-       .permission     = hppfs_permission,
 };
 
 static const struct inode_operations hppfs_link_iops = {
        .readlink       = hppfs_readlink,
        .follow_link    = hppfs_follow_link,
-       .permission     = hppfs_permission,
 };
 
 static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
index aeabf80f81a5d38561768ea95d1b544605e5dcc4..3f58923fb39bc11c284980c3e53a6d70de3d9a0d 100644 (file)
@@ -53,6 +53,7 @@ int sysctl_hugetlb_shm_group;
 enum {
        Opt_size, Opt_nr_inodes,
        Opt_mode, Opt_uid, Opt_gid,
+       Opt_pagesize,
        Opt_err,
 };
 
@@ -62,6 +63,7 @@ static match_table_t tokens = {
        {Opt_mode,      "mode=%o"},
        {Opt_uid,       "uid=%u"},
        {Opt_gid,       "gid=%u"},
+       {Opt_pagesize,  "pagesize=%s"},
        {Opt_err,       NULL},
 };
 
@@ -80,6 +82,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
        struct inode *inode = file->f_path.dentry->d_inode;
        loff_t len, vma_len;
        int ret;
+       struct hstate *h = hstate_file(file);
 
        /*
         * vma address alignment (but not the pgoff alignment) has
@@ -92,7 +95,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
        vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
        vma->vm_ops = &hugetlb_vm_ops;
 
-       if (vma->vm_pgoff & ~(HPAGE_MASK >> PAGE_SHIFT))
+       if (vma->vm_pgoff & ~(huge_page_mask(h) >> PAGE_SHIFT))
                return -EINVAL;
 
        vma_len = (loff_t)(vma->vm_end - vma->vm_start);
@@ -103,9 +106,9 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
        ret = -ENOMEM;
        len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
 
-       if (vma->vm_flags & VM_MAYSHARE &&
-           hugetlb_reserve_pages(inode, vma->vm_pgoff >> (HPAGE_SHIFT-PAGE_SHIFT),
-                                 len >> HPAGE_SHIFT))
+       if (hugetlb_reserve_pages(inode,
+                               vma->vm_pgoff >> huge_page_order(h),
+                               len >> huge_page_shift(h), vma))
                goto out;
 
        ret = 0;
@@ -130,20 +133,21 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        unsigned long start_addr;
+       struct hstate *h = hstate_file(file);
 
-       if (len & ~HPAGE_MASK)
+       if (len & ~huge_page_mask(h))
                return -EINVAL;
        if (len > TASK_SIZE)
                return -ENOMEM;
 
        if (flags & MAP_FIXED) {
-               if (prepare_hugepage_range(addr, len))
+               if (prepare_hugepage_range(file, addr, len))
                        return -EINVAL;
                return addr;
        }
 
        if (addr) {
-               addr = ALIGN(addr, HPAGE_SIZE);
+               addr = ALIGN(addr, huge_page_size(h));
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
                    (!vma || addr + len <= vma->vm_start))
@@ -156,7 +160,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                start_addr = TASK_UNMAPPED_BASE;
 
 full_search:
-       addr = ALIGN(start_addr, HPAGE_SIZE);
+       addr = ALIGN(start_addr, huge_page_size(h));
 
        for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
                /* At this point:  (!vma || addr < vma->vm_end). */
@@ -174,7 +178,7 @@ full_search:
 
                if (!vma || addr + len <= vma->vm_start)
                        return addr;
-               addr = ALIGN(vma->vm_end, HPAGE_SIZE);
+               addr = ALIGN(vma->vm_end, huge_page_size(h));
        }
 }
 #endif
@@ -225,10 +229,11 @@ hugetlbfs_read_actor(struct page *page, unsigned long offset,
 static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
                              size_t len, loff_t *ppos)
 {
+       struct hstate *h = hstate_file(filp);
        struct address_space *mapping = filp->f_mapping;
        struct inode *inode = mapping->host;
-       unsigned long index = *ppos >> HPAGE_SHIFT;
-       unsigned long offset = *ppos & ~HPAGE_MASK;
+       unsigned long index = *ppos >> huge_page_shift(h);
+       unsigned long offset = *ppos & ~huge_page_mask(h);
        unsigned long end_index;
        loff_t isize;
        ssize_t retval = 0;
@@ -243,17 +248,17 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
        if (!isize)
                goto out;
 
-       end_index = (isize - 1) >> HPAGE_SHIFT;
+       end_index = (isize - 1) >> huge_page_shift(h);
        for (;;) {
                struct page *page;
-               int nr, ret;
+               unsigned long nr, ret;
 
                /* nr is the maximum number of bytes to copy from this page */
-               nr = HPAGE_SIZE;
+               nr = huge_page_size(h);
                if (index >= end_index) {
                        if (index > end_index)
                                goto out;
-                       nr = ((isize - 1) & ~HPAGE_MASK) + 1;
+                       nr = ((isize - 1) & ~huge_page_mask(h)) + 1;
                        if (nr <= offset) {
                                goto out;
                        }
@@ -287,8 +292,8 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
                offset += ret;
                retval += ret;
                len -= ret;
-               index += offset >> HPAGE_SHIFT;
-               offset &= ~HPAGE_MASK;
+               index += offset >> huge_page_shift(h);
+               offset &= ~huge_page_mask(h);
 
                if (page)
                        page_cache_release(page);
@@ -298,7 +303,7 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
                        break;
        }
 out:
-       *ppos = ((loff_t)index << HPAGE_SHIFT) + offset;
+       *ppos = ((loff_t)index << huge_page_shift(h)) + offset;
        mutex_unlock(&inode->i_mutex);
        return retval;
 }
@@ -339,8 +344,9 @@ static void truncate_huge_page(struct page *page)
 
 static void truncate_hugepages(struct inode *inode, loff_t lstart)
 {
+       struct hstate *h = hstate_inode(inode);
        struct address_space *mapping = &inode->i_data;
-       const pgoff_t start = lstart >> HPAGE_SHIFT;
+       const pgoff_t start = lstart >> huge_page_shift(h);
        struct pagevec pvec;
        pgoff_t next;
        int i, freed = 0;
@@ -441,7 +447,7 @@ hugetlb_vmtruncate_list(struct prio_tree_root *root, pgoff_t pgoff)
                        v_offset = 0;
 
                __unmap_hugepage_range(vma,
-                               vma->vm_start + v_offset, vma->vm_end);
+                               vma->vm_start + v_offset, vma->vm_end, NULL);
        }
 }
 
@@ -449,8 +455,9 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
 {
        pgoff_t pgoff;
        struct address_space *mapping = inode->i_mapping;
+       struct hstate *h = hstate_inode(inode);
 
-       BUG_ON(offset & ~HPAGE_MASK);
+       BUG_ON(offset & ~huge_page_mask(h));
        pgoff = offset >> PAGE_SHIFT;
 
        i_size_write(inode, offset);
@@ -465,6 +472,7 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
 static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
+       struct hstate *h = hstate_inode(inode);
        int error;
        unsigned int ia_valid = attr->ia_valid;
 
@@ -476,7 +484,7 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
 
        if (ia_valid & ATTR_SIZE) {
                error = -EINVAL;
-               if (!(attr->ia_size & ~HPAGE_MASK))
+               if (!(attr->ia_size & ~huge_page_mask(h)))
                        error = hugetlb_vmtruncate(inode, attr->ia_size);
                if (error)
                        goto out;
@@ -610,9 +618,10 @@ static int hugetlbfs_set_page_dirty(struct page *page)
 static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
+       struct hstate *h = hstate_inode(dentry->d_inode);
 
        buf->f_type = HUGETLBFS_MAGIC;
-       buf->f_bsize = HPAGE_SIZE;
+       buf->f_bsize = huge_page_size(h);
        if (sbinfo) {
                spin_lock(&sbinfo->stat_lock);
                /* If no limits set, just report 0 for max/free/used
@@ -696,7 +705,7 @@ static const struct address_space_operations hugetlbfs_aops = {
 };
 
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo;
 
@@ -743,6 +752,8 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
        char *p, *rest;
        substring_t args[MAX_OPT_ARGS];
        int option;
+       unsigned long long size = 0;
+       enum { NO_SIZE, SIZE_STD, SIZE_PERCENT } setsize = NO_SIZE;
 
        if (!options)
                return 0;
@@ -773,17 +784,13 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
                        break;
 
                case Opt_size: {
-                       unsigned long long size;
                        /* memparse() will accept a K/M/G without a digit */
                        if (!isdigit(*args[0].from))
                                goto bad_val;
                        size = memparse(args[0].from, &rest);
-                       if (*rest == '%') {
-                               size <<= HPAGE_SHIFT;
-                               size *= max_huge_pages;
-                               do_div(size, 100);
-                       }
-                       pconfig->nr_blocks = (size >> HPAGE_SHIFT);
+                       setsize = SIZE_STD;
+                       if (*rest == '%')
+                               setsize = SIZE_PERCENT;
                        break;
                }
 
@@ -794,6 +801,19 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
                        pconfig->nr_inodes = memparse(args[0].from, &rest);
                        break;
 
+               case Opt_pagesize: {
+                       unsigned long ps;
+                       ps = memparse(args[0].from, &rest);
+                       pconfig->hstate = size_to_hstate(ps);
+                       if (!pconfig->hstate) {
+                               printk(KERN_ERR
+                               "hugetlbfs: Unsupported page size %lu MB\n",
+                                       ps >> 20);
+                               return -EINVAL;
+                       }
+                       break;
+               }
+
                default:
                        printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
                                 p);
@@ -801,6 +821,18 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
                        break;
                }
        }
+
+       /* Do size after hstate is set up */
+       if (setsize > NO_SIZE) {
+               struct hstate *h = pconfig->hstate;
+               if (setsize == SIZE_PERCENT) {
+                       size <<= huge_page_shift(h);
+                       size *= h->max_huge_pages;
+                       do_div(size, 100);
+               }
+               pconfig->nr_blocks = (size >> huge_page_shift(h));
+       }
+
        return 0;
 
 bad_val:
@@ -825,6 +857,7 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
        config.uid = current->fsuid;
        config.gid = current->fsgid;
        config.mode = 0755;
+       config.hstate = &default_hstate;
        ret = hugetlbfs_parse_options(data, &config);
        if (ret)
                return ret;
@@ -833,14 +866,15 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbinfo)
                return -ENOMEM;
        sb->s_fs_info = sbinfo;
+       sbinfo->hstate = config.hstate;
        spin_lock_init(&sbinfo->stat_lock);
        sbinfo->max_blocks = config.nr_blocks;
        sbinfo->free_blocks = config.nr_blocks;
        sbinfo->max_inodes = config.nr_inodes;
        sbinfo->free_inodes = config.nr_inodes;
        sb->s_maxbytes = MAX_LFS_FILESIZE;
-       sb->s_blocksize = HPAGE_SIZE;
-       sb->s_blocksize_bits = HPAGE_SHIFT;
+       sb->s_blocksize = huge_page_size(config.hstate);
+       sb->s_blocksize_bits = huge_page_shift(config.hstate);
        sb->s_magic = HUGETLBFS_MAGIC;
        sb->s_op = &hugetlbfs_ops;
        sb->s_time_gran = 1;
@@ -942,7 +976,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
                goto out_dentry;
 
        error = -ENOMEM;
-       if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT))
+       if (hugetlb_reserve_pages(inode, 0,
+                       size >> huge_page_shift(hstate_inode(inode)), NULL))
                goto out_inode;
 
        d_instantiate(dentry, inode);
index c36d9480335c6fc8a099aa1551910b0ce55a539f..b6726f6445303fd745ce5faab01aa2d8b924e90e 100644 (file)
@@ -209,7 +209,7 @@ void inode_init_once(struct inode *inode)
        INIT_LIST_HEAD(&inode->i_dentry);
        INIT_LIST_HEAD(&inode->i_devices);
        INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
-       rwlock_init(&inode->i_data.tree_lock);
+       spin_lock_init(&inode->i_data.tree_lock);
        spin_lock_init(&inode->i_data.i_mmap_lock);
        INIT_LIST_HEAD(&inode->i_data.private_list);
        spin_lock_init(&inode->i_data.private_lock);
@@ -224,7 +224,7 @@ void inode_init_once(struct inode *inode)
 
 EXPORT_SYMBOL(inode_init_once);
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct inode * inode = (struct inode *) foo;
 
index 6676c06bb7c16935b3a7fbc4615836f1dfb256fb..60249429a2530d11e6d5037e148d9a3c4fd00799 100644 (file)
@@ -354,20 +354,20 @@ static void inotify_dev_event_dequeue(struct inotify_device *dev)
 }
 
 /*
- * find_inode - resolve a user-given path to a specific inode and return a nd
+ * find_inode - resolve a user-given path to a specific inode
  */
-static int find_inode(const char __user *dirname, struct nameidata *nd,
+static int find_inode(const char __user *dirname, struct path *path,
                      unsigned flags)
 {
        int error;
 
-       error = __user_walk(dirname, flags, nd);
+       error = user_path_at(AT_FDCWD, dirname, flags, path);
        if (error)
                return error;
        /* you can only watch an inode if you have read permissions on it */
-       error = vfs_permission(nd, MAY_READ);
+       error = inode_permission(path->dentry->d_inode, MAY_READ);
        if (error)
-               path_put(&nd->path);
+               path_put(path);
        return error;
 }
 
@@ -566,7 +566,7 @@ static const struct inotify_operations inotify_user_ops = {
        .destroy_watch  = free_inotify_user_watch,
 };
 
-asmlinkage long sys_inotify_init(void)
+asmlinkage long sys_inotify_init1(int flags)
 {
        struct inotify_device *dev;
        struct inotify_handle *ih;
@@ -574,7 +574,14 @@ asmlinkage long sys_inotify_init(void)
        struct file *filp;
        int fd, ret;
 
-       fd = get_unused_fd();
+       /* Check the IN_* constants for consistency.  */
+       BUILD_BUG_ON(IN_CLOEXEC != O_CLOEXEC);
+       BUILD_BUG_ON(IN_NONBLOCK != O_NONBLOCK);
+
+       if (flags & ~(IN_CLOEXEC | IN_NONBLOCK))
+               return -EINVAL;
+
+       fd = get_unused_fd_flags(flags & O_CLOEXEC);
        if (fd < 0)
                return fd;
 
@@ -610,7 +617,7 @@ asmlinkage long sys_inotify_init(void)
        filp->f_path.dentry = dget(inotify_mnt->mnt_root);
        filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
        filp->f_mode = FMODE_READ;
-       filp->f_flags = O_RDONLY;
+       filp->f_flags = O_RDONLY | (flags & O_NONBLOCK);
        filp->private_data = dev;
 
        INIT_LIST_HEAD(&dev->events);
@@ -638,11 +645,16 @@ out_put_fd:
        return ret;
 }
 
-asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
+asmlinkage long sys_inotify_init(void)
+{
+       return sys_inotify_init1(0);
+}
+
+asmlinkage long sys_inotify_add_watch(int fd, const char __user *pathname, u32 mask)
 {
        struct inode *inode;
        struct inotify_device *dev;
-       struct nameidata nd;
+       struct path path;
        struct file *filp;
        int ret, fput_needed;
        unsigned flags = 0;
@@ -662,12 +674,12 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
        if (mask & IN_ONLYDIR)
                flags |= LOOKUP_DIRECTORY;
 
-       ret = find_inode(path, &nd, flags);
+       ret = find_inode(pathname, &path, flags);
        if (unlikely(ret))
                goto fput_and_out;
 
-       /* inode held in place by reference to nd; dev by fget on fd */
-       inode = nd.path.dentry->d_inode;
+       /* inode held in place by reference to path; dev by fget on fd */
+       inode = path.dentry->d_inode;
        dev = filp->private_data;
 
        mutex_lock(&dev->up_mutex);
@@ -676,7 +688,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
                ret = create_watch(dev, inode, mask);
        mutex_unlock(&dev->up_mutex);
 
-       path_put(&nd.path);
+       path_put(&path);
 fput_and_out:
        fput_light(filp, fput_needed);
        return ret;
index 044a254d526b86e38ca0ca925540468ce06e19f1..26948a6033b69a71d82ba0b281c5efd7aa7dcec4 100644 (file)
@@ -73,7 +73,7 @@ static void isofs_destroy_inode(struct inode *inode)
        kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct iso_inode_info *ei = foo;
 
index 6bd48f0a7047d7560f06492dfe57e53141be6a17..c2fb2dd0131f36cf2bcb3e1ad342a2c64cbd8422 100644 (file)
@@ -209,6 +209,11 @@ repeat:
 
        while (rs.len > 2) { /* There may be one byte for padding somewhere */
                rr = (struct rock_ridge *)rs.chr;
+               /*
+                * Ignore rock ridge info if rr->len is out of range, but
+                * don't return -EIO because that would make the file
+                * invisible.
+                */
                if (rr->len < 3)
                        goto out;       /* Something got screwed up here */
                sig = isonum_721(rs.chr);
@@ -216,8 +221,12 @@ repeat:
                        goto eio;
                rs.chr += rr->len;
                rs.len -= rr->len;
+               /*
+                * As above, just ignore the rock ridge info if rr->len
+                * is bogus.
+                */
                if (rs.len < 0)
-                       goto eio;       /* corrupted isofs */
+                       goto out;       /* Something got screwed up here */
 
                switch (sig) {
                case SIG('R', 'R'):
@@ -307,6 +316,11 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de,
 repeat:
        while (rs.len > 2) { /* There may be one byte for padding somewhere */
                rr = (struct rock_ridge *)rs.chr;
+               /*
+                * Ignore rock ridge info if rr->len is out of range, but
+                * don't return -EIO because that would make the file
+                * invisible.
+                */
                if (rr->len < 3)
                        goto out;       /* Something got screwed up here */
                sig = isonum_721(rs.chr);
@@ -314,8 +328,12 @@ repeat:
                        goto eio;
                rs.chr += rr->len;
                rs.len -= rr->len;
+               /*
+                * As above, just ignore the rock ridge info if rr->len
+                * is bogus.
+                */
                if (rs.len < 0)
-                       goto eio;       /* corrupted isofs */
+                       goto out;       /* Something got screwed up here */
 
                switch (sig) {
 #ifndef CONFIG_ZISOFS          /* No flag for SF or ZF */
index 5a8ca61498caf36cbb818fddc00eafbca2642f03..2eccbfaa1d48186934de93b8391e360fc77ede6d 100644 (file)
@@ -36,7 +36,7 @@ static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
 
 /*
  * When an ext3-ordered file is truncated, it is possible that many pages are
- * not sucessfully freed, because they are attached to a committing transaction.
+ * not successfully freed, because they are attached to a committing transaction.
  * After the transaction commits, these pages are left on the LRU, with no
  * ->mapping, and with attached buffers.  These pages are trivially reclaimable
  * by the VM, but their apparent absence upsets the VM accounting, and it makes
@@ -45,8 +45,8 @@ static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
  * So here, we have a buffer which has just come off the forget list.  Look to
  * see if we can strip all buffers from the backing page.
  *
- * Called under lock_journal(), and possibly under journal_datalist_lock.  The
- * caller provided us with a ref against the buffer, and we drop that here.
+ * Called under journal->j_list_lock.  The caller provided us with a ref
+ * against the buffer, and we drop that here.
  */
 static void release_buffer_page(struct buffer_head *bh)
 {
@@ -77,6 +77,19 @@ nope:
        __brelse(bh);
 }
 
+/*
+ * Decrement reference counter for data buffer. If it has been marked
+ * 'BH_Freed', release it and the page to which it belongs if possible.
+ */
+static void release_data_buffer(struct buffer_head *bh)
+{
+       if (buffer_freed(bh)) {
+               clear_buffer_freed(bh);
+               release_buffer_page(bh);
+       } else
+               put_bh(bh);
+}
+
 /*
  * Try to acquire jbd_lock_bh_state() against the buffer, when j_list_lock is
  * held.  For ranking reasons we must trylock.  If we lose, schedule away and
@@ -172,7 +185,7 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs)
 /*
  *  Submit all the data buffers to disk
  */
-static void journal_submit_data_buffers(journal_t *journal,
+static int journal_submit_data_buffers(journal_t *journal,
                                transaction_t *commit_transaction)
 {
        struct journal_head *jh;
@@ -180,6 +193,7 @@ static void journal_submit_data_buffers(journal_t *journal,
        int locked;
        int bufs = 0;
        struct buffer_head **wbuf = journal->j_wbuf;
+       int err = 0;
 
        /*
         * Whenever we unlock the journal and sleep, things can get added
@@ -231,7 +245,7 @@ write_out_data:
                        if (locked)
                                unlock_buffer(bh);
                        BUFFER_TRACE(bh, "already cleaned up");
-                       put_bh(bh);
+                       release_data_buffer(bh);
                        continue;
                }
                if (locked && test_clear_buffer_dirty(bh)) {
@@ -253,15 +267,17 @@ write_out_data:
                        put_bh(bh);
                } else {
                        BUFFER_TRACE(bh, "writeout complete: unfile");
+                       if (unlikely(!buffer_uptodate(bh)))
+                               err = -EIO;
                        __journal_unfile_buffer(jh);
                        jbd_unlock_bh_state(bh);
                        if (locked)
                                unlock_buffer(bh);
                        journal_remove_journal_head(bh);
-                       /* Once for our safety reference, once for
+                       /* One for our safety reference, other for
                         * journal_remove_journal_head() */
                        put_bh(bh);
-                       put_bh(bh);
+                       release_data_buffer(bh);
                }
 
                if (need_resched() || spin_needbreak(&journal->j_list_lock)) {
@@ -271,6 +287,8 @@ write_out_data:
        }
        spin_unlock(&journal->j_list_lock);
        journal_do_submit_data(wbuf, bufs);
+
+       return err;
 }
 
 /*
@@ -410,8 +428,7 @@ void journal_commit_transaction(journal_t *journal)
         * Now start flushing things to disk, in the order they appear
         * on the transaction lists.  Data blocks go first.
         */
-       err = 0;
-       journal_submit_data_buffers(journal, commit_transaction);
+       err = journal_submit_data_buffers(journal, commit_transaction);
 
        /*
         * Wait for all previously submitted IO to complete.
@@ -426,10 +443,21 @@ void journal_commit_transaction(journal_t *journal)
                if (buffer_locked(bh)) {
                        spin_unlock(&journal->j_list_lock);
                        wait_on_buffer(bh);
-                       if (unlikely(!buffer_uptodate(bh)))
-                               err = -EIO;
                        spin_lock(&journal->j_list_lock);
                }
+               if (unlikely(!buffer_uptodate(bh))) {
+                       if (TestSetPageLocked(bh->b_page)) {
+                               spin_unlock(&journal->j_list_lock);
+                               lock_page(bh->b_page);
+                               spin_lock(&journal->j_list_lock);
+                       }
+                       if (bh->b_page->mapping)
+                               set_bit(AS_EIO, &bh->b_page->mapping->flags);
+
+                       unlock_page(bh->b_page);
+                       SetPageError(bh->b_page);
+                       err = -EIO;
+               }
                if (!inverted_lock(journal, bh)) {
                        put_bh(bh);
                        spin_lock(&journal->j_list_lock);
@@ -443,17 +471,21 @@ void journal_commit_transaction(journal_t *journal)
                } else {
                        jbd_unlock_bh_state(bh);
                }
-               put_bh(bh);
+               release_data_buffer(bh);
                cond_resched_lock(&journal->j_list_lock);
        }
        spin_unlock(&journal->j_list_lock);
 
-       if (err)
-               journal_abort(journal, err);
+       if (err) {
+               char b[BDEVNAME_SIZE];
 
-       journal_write_revoke_records(journal, commit_transaction);
+               printk(KERN_WARNING
+                       "JBD: Detected IO errors while flushing file data "
+                       "on %s\n", bdevname(journal->j_fs_dev, b));
+               err = 0;
+       }
 
-       jbd_debug(3, "JBD: commit phase 2\n");
+       journal_write_revoke_records(journal, commit_transaction);
 
        /*
         * If we found any dirty or locked buffers, then we should have
index b99c3b3654c49ee33f86bc8883319a55f11a9711..aa7143a8349bdd0fcb841e70a252d8d9047777bf 100644 (file)
@@ -68,7 +68,6 @@ EXPORT_SYMBOL(journal_set_features);
 EXPORT_SYMBOL(journal_create);
 EXPORT_SYMBOL(journal_load);
 EXPORT_SYMBOL(journal_destroy);
-EXPORT_SYMBOL(journal_update_superblock);
 EXPORT_SYMBOL(journal_abort);
 EXPORT_SYMBOL(journal_errno);
 EXPORT_SYMBOL(journal_ack_err);
@@ -1636,9 +1635,10 @@ static int journal_init_journal_head_cache(void)
 
 static void journal_destroy_journal_head_cache(void)
 {
-       J_ASSERT(journal_head_cache != NULL);
-       kmem_cache_destroy(journal_head_cache);
-       journal_head_cache = NULL;
+       if (journal_head_cache) {
+               kmem_cache_destroy(journal_head_cache);
+               journal_head_cache = NULL;
+       }
 }
 
 /*
index 1bb43e987f4b4ff4f0e37a2d578d34c1642cf6c0..c7bd649bbbdcfe032c46c52ed235bfda7a5e40e9 100644 (file)
@@ -166,138 +166,123 @@ static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
        return NULL;
 }
 
+void journal_destroy_revoke_caches(void)
+{
+       if (revoke_record_cache) {
+               kmem_cache_destroy(revoke_record_cache);
+               revoke_record_cache = NULL;
+       }
+       if (revoke_table_cache) {
+               kmem_cache_destroy(revoke_table_cache);
+               revoke_table_cache = NULL;
+       }
+}
+
 int __init journal_init_revoke_caches(void)
 {
+       J_ASSERT(!revoke_record_cache);
+       J_ASSERT(!revoke_table_cache);
+
        revoke_record_cache = kmem_cache_create("revoke_record",
                                           sizeof(struct jbd_revoke_record_s),
                                           0,
                                           SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
                                           NULL);
        if (!revoke_record_cache)
-               return -ENOMEM;
+               goto record_cache_failure;
 
        revoke_table_cache = kmem_cache_create("revoke_table",
                                           sizeof(struct jbd_revoke_table_s),
                                           0, SLAB_TEMPORARY, NULL);
-       if (!revoke_table_cache) {
-               kmem_cache_destroy(revoke_record_cache);
-               revoke_record_cache = NULL;
-               return -ENOMEM;
-       }
+       if (!revoke_table_cache)
+               goto table_cache_failure;
+
        return 0;
-}
 
-void journal_destroy_revoke_caches(void)
-{
-       kmem_cache_destroy(revoke_record_cache);
-       revoke_record_cache = NULL;
-       kmem_cache_destroy(revoke_table_cache);
-       revoke_table_cache = NULL;
+table_cache_failure:
+       journal_destroy_revoke_caches();
+record_cache_failure:
+       return -ENOMEM;
 }
 
-/* Initialise the revoke table for a given journal to a given size. */
-
-int journal_init_revoke(journal_t *journal, int hash_size)
+static struct jbd_revoke_table_s *journal_init_revoke_table(int hash_size)
 {
-       int shift, tmp;
+       int shift = 0;
+       int tmp = hash_size;
+       struct jbd_revoke_table_s *table;
 
-       J_ASSERT (journal->j_revoke_table[0] == NULL);
+       table = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
+       if (!table)
+               goto out;
 
-       shift = 0;
-       tmp = hash_size;
        while((tmp >>= 1UL) != 0UL)
                shift++;
 
-       journal->j_revoke_table[0] = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
-       if (!journal->j_revoke_table[0])
-               return -ENOMEM;
-       journal->j_revoke = journal->j_revoke_table[0];
-
-       /* Check that the hash_size is a power of two */
-       J_ASSERT(is_power_of_2(hash_size));
-
-       journal->j_revoke->hash_size = hash_size;
-
-       journal->j_revoke->hash_shift = shift;
-
-       journal->j_revoke->hash_table =
+       table->hash_size = hash_size;
+       table->hash_shift = shift;
+       table->hash_table =
                kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
-       if (!journal->j_revoke->hash_table) {
-               kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]);
-               journal->j_revoke = NULL;
-               return -ENOMEM;
+       if (!table->hash_table) {
+               kmem_cache_free(revoke_table_cache, table);
+               table = NULL;
+               goto out;
        }
 
        for (tmp = 0; tmp < hash_size; tmp++)
-               INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+               INIT_LIST_HEAD(&table->hash_table[tmp]);
 
-       journal->j_revoke_table[1] = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
-       if (!journal->j_revoke_table[1]) {
-               kfree(journal->j_revoke_table[0]->hash_table);
-               kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]);
-               return -ENOMEM;
+out:
+       return table;
+}
+
+static void journal_destroy_revoke_table(struct jbd_revoke_table_s *table)
+{
+       int i;
+       struct list_head *hash_list;
+
+       for (i = 0; i < table->hash_size; i++) {
+               hash_list = &table->hash_table[i];
+               J_ASSERT(list_empty(hash_list));
        }
 
-       journal->j_revoke = journal->j_revoke_table[1];
+       kfree(table->hash_table);
+       kmem_cache_free(revoke_table_cache, table);
+}
 
-       /* Check that the hash_size is a power of two */
+/* Initialise the revoke table for a given journal to a given size. */
+int journal_init_revoke(journal_t *journal, int hash_size)
+{
+       J_ASSERT(journal->j_revoke_table[0] == NULL);
        J_ASSERT(is_power_of_2(hash_size));
 
-       journal->j_revoke->hash_size = hash_size;
+       journal->j_revoke_table[0] = journal_init_revoke_table(hash_size);
+       if (!journal->j_revoke_table[0])
+               goto fail0;
 
-       journal->j_revoke->hash_shift = shift;
+       journal->j_revoke_table[1] = journal_init_revoke_table(hash_size);
+       if (!journal->j_revoke_table[1])
+               goto fail1;
 
-       journal->j_revoke->hash_table =
-               kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
-       if (!journal->j_revoke->hash_table) {
-               kfree(journal->j_revoke_table[0]->hash_table);
-               kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]);
-               kmem_cache_free(revoke_table_cache, journal->j_revoke_table[1]);
-               journal->j_revoke = NULL;
-               return -ENOMEM;
-       }
-
-       for (tmp = 0; tmp < hash_size; tmp++)
-               INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+       journal->j_revoke = journal->j_revoke_table[1];
 
        spin_lock_init(&journal->j_revoke_lock);
 
        return 0;
-}
 
-/* Destoy a journal's revoke table.  The table must already be empty! */
+fail1:
+       journal_destroy_revoke_table(journal->j_revoke_table[0]);
+fail0:
+       return -ENOMEM;
+}
 
+/* Destroy a journal's revoke table.  The table must already be empty! */
 void journal_destroy_revoke(journal_t *journal)
 {
-       struct jbd_revoke_table_s *table;
-       struct list_head *hash_list;
-       int i;
-
-       table = journal->j_revoke_table[0];
-       if (!table)
-               return;
-
-       for (i=0; i<table->hash_size; i++) {
-               hash_list = &table->hash_table[i];
-               J_ASSERT (list_empty(hash_list));
-       }
-
-       kfree(table->hash_table);
-       kmem_cache_free(revoke_table_cache, table);
-       journal->j_revoke = NULL;
-
-       table = journal->j_revoke_table[1];
-       if (!table)
-               return;
-
-       for (i=0; i<table->hash_size; i++) {
-               hash_list = &table->hash_table[i];
-               J_ASSERT (list_empty(hash_list));
-       }
-
-       kfree(table->hash_table);
-       kmem_cache_free(revoke_table_cache, table);
        journal->j_revoke = NULL;
+       if (journal->j_revoke_table[0])
+               journal_destroy_revoke_table(journal->j_revoke_table[0]);
+       if (journal->j_revoke_table[1])
+               journal_destroy_revoke_table(journal->j_revoke_table[1]);
 }
 
 
index 67ff2024c23c7d21950407ce8dfea088a090f1c4..8dee32007500e3200451b9334b849f2362611cc7 100644 (file)
@@ -1648,12 +1648,42 @@ out:
        return;
 }
 
+/*
+ * journal_try_to_free_buffers() could race with journal_commit_transaction()
+ * The latter might still hold the a count on buffers when inspecting
+ * them on t_syncdata_list or t_locked_list.
+ *
+ * journal_try_to_free_buffers() will call this function to
+ * wait for the current transaction to finish syncing data buffers, before
+ * tryinf to free that buffer.
+ *
+ * Called with journal->j_state_lock held.
+ */
+static void journal_wait_for_transaction_sync_data(journal_t *journal)
+{
+       transaction_t *transaction = NULL;
+       tid_t tid;
+
+       spin_lock(&journal->j_state_lock);
+       transaction = journal->j_committing_transaction;
+
+       if (!transaction) {
+               spin_unlock(&journal->j_state_lock);
+               return;
+       }
+
+       tid = transaction->t_tid;
+       spin_unlock(&journal->j_state_lock);
+       log_wait_commit(journal, tid);
+}
 
 /**
  * int journal_try_to_free_buffers() - try to free page buffers.
  * @journal: journal for operation
  * @page: to try and free
- * @unused_gfp_mask: unused
+ * @gfp_mask: we use the mask to detect how hard should we try to release
+ * buffers. If __GFP_WAIT and __GFP_FS is set, we wait for commit code to
+ * release the buffers.
  *
  *
  * For all the buffers on this page,
@@ -1682,9 +1712,11 @@ out:
  * journal_try_to_free_buffer() is changing its state.  But that
  * cannot happen because we never reallocate freed data as metadata
  * while the data is part of a transaction.  Yes?
+ *
+ * Return 0 on failure, 1 on success
  */
 int journal_try_to_free_buffers(journal_t *journal,
-                               struct page *page, gfp_t unused_gfp_mask)
+                               struct page *page, gfp_t gfp_mask)
 {
        struct buffer_head *head;
        struct buffer_head *bh;
@@ -1713,7 +1745,28 @@ int journal_try_to_free_buffers(journal_t *journal,
                if (buffer_jbd(bh))
                        goto busy;
        } while ((bh = bh->b_this_page) != head);
+
        ret = try_to_free_buffers(page);
+
+       /*
+        * There are a number of places where journal_try_to_free_buffers()
+        * could race with journal_commit_transaction(), the later still
+        * holds the reference to the buffers to free while processing them.
+        * try_to_free_buffers() failed to free those buffers. Some of the
+        * caller of releasepage() request page buffers to be dropped, otherwise
+        * treat the fail-to-free as errors (such as generic_file_direct_IO())
+        *
+        * So, if the caller of try_to_release_page() wants the synchronous
+        * behaviour(i.e make sure buffers are dropped upon return),
+        * let's wait for the current transaction to finish flush of
+        * dirty data buffers, then try to free those buffers again,
+        * with the journal locked.
+        */
+       if (ret == 0 && (gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_FS)) {
+               journal_wait_for_transaction_sync_data(journal);
+               ret = try_to_free_buffers(page);
+       }
+
 busy:
        return ret;
 }
index 4c80404a9abae4b61e075135bb62441450596b11..d98713777a1b62f2aa12f659dd872616d2dbeb4a 100644 (file)
@@ -314,7 +314,7 @@ static int jffs2_check_acl(struct inode *inode, int mask)
        return -EAGAIN;
 }
 
-int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd)
+int jffs2_permission(struct inode *inode, int mask)
 {
        return generic_permission(inode, mask, jffs2_check_acl);
 }
index 0bb7f003fd80bb8b64909fedf420c3af327198c9..8ca058aed3840fa5f8c13c5b733127c473899739 100644 (file)
@@ -28,7 +28,7 @@ struct jffs2_acl_header {
 
 #define JFFS2_ACL_NOT_CACHED ((void *)-1)
 
-extern int jffs2_permission(struct inode *, int, struct nameidata *);
+extern int jffs2_permission(struct inode *, int);
 extern int jffs2_acl_chmod(struct inode *);
 extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *);
 extern int jffs2_init_acl_post(struct inode *);
index c0c141f6fde11c5e9367698494471e2462f181a3..cd219ef552543cdc98d0a392f95cd6dc1c3ec4fd 100644 (file)
@@ -38,7 +38,7 @@ const struct file_operations jffs2_dir_operations =
 {
        .read =         generic_read_dir,
        .readdir =      jffs2_readdir,
-       .ioctl =        jffs2_ioctl,
+       .unlocked_ioctl=jffs2_ioctl,
        .fsync =        jffs2_fsync
 };
 
index 5e920343b2c598595f2c068455e17d7d360c5a4f..5a98aa87c8530b169ec0453f977860550df73f38 100644 (file)
@@ -46,7 +46,7 @@ const struct file_operations jffs2_file_operations =
        .aio_read =     generic_file_aio_read,
        .write =        do_sync_write,
        .aio_write =    generic_file_aio_write,
-       .ioctl =        jffs2_ioctl,
+       .unlocked_ioctl=jffs2_ioctl,
        .mmap =         generic_file_readonly_mmap,
        .fsync =        jffs2_fsync,
        .splice_read =  generic_file_splice_read,
index e2177210f62153bec393482eb6f2e2b58b48f0eb..9d41f43e47bb29766bc6b309b7179e4d5cee759f 100644 (file)
@@ -12,8 +12,7 @@
 #include <linux/fs.h>
 #include "nodelist.h"
 
-int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-               unsigned long arg)
+long jffs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        /* Later, this will provide for lsattr.jffs2 and chattr.jffs2, which
           will include compression support etc. */
index 2cc866cf134f18ce26bbecdd9b70c450cc075906..5e194a5c8e29c7166116bb8430d962dc4e029cc0 100644 (file)
@@ -167,7 +167,7 @@ int jffs2_fsync(struct file *, struct dentry *, int);
 int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
 
 /* ioctl.c */
-int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+long jffs2_ioctl(struct file *, unsigned int, unsigned long);
 
 /* symlink.c */
 extern const struct inode_operations jffs2_symlink_inode_operations;
index 7da69eae49e491267699dcd8ca50535f5af15aed..efd401257ed9401bc5e438d5548d6e2e9638ba55 100644 (file)
@@ -44,7 +44,7 @@ static void jffs2_destroy_inode(struct inode *inode)
        kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode));
 }
 
-static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
+static void jffs2_i_init_once(void *foo)
 {
        struct jffs2_inode_info *f = foo;
 
index 4d84bdc882999150a1e9bd7ae829f1aff24b33f2..d3e5c33665deceb13a0af0797a67b282129c3037 100644 (file)
@@ -140,7 +140,7 @@ static int jfs_check_acl(struct inode *inode, int mask)
        return -EAGAIN;
 }
 
-int jfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+int jfs_permission(struct inode *inode, int mask)
 {
        return generic_permission(inode, mask, jfs_check_acl);
 }
index 455fa4292045559ea52202da59ae920dfe8d64ed..88475f10a3899dca4c6fa15eceffbbccb97cdab0 100644 (file)
@@ -20,7 +20,7 @@
 
 #ifdef CONFIG_JFS_POSIX_ACL
 
-int jfs_permission(struct inode *, int, struct nameidata *);
+int jfs_permission(struct inode *, int);
 int jfs_init_acl(tid_t, struct inode *, struct inode *);
 int jfs_setattr(struct dentry *, struct iattr *);
 
index 854ff0ec574f8805a71c09152bf60f9e8bd66053..c350057087dd39db3809992338432ac07120bd16 100644 (file)
@@ -182,7 +182,7 @@ static inline void remove_metapage(struct page *page, struct metapage *mp)
 
 #endif
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct metapage *mp = (struct metapage *)foo;
 
index 0288e6d7936a200e51b585914cf5ae76847b91a3..3630718be395deaada9cfe0c28d11a877fcc31e7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/parser.h>
 #include <linux/completion.h>
 #include <linux/vfs.h>
+#include <linux/quotaops.h>
 #include <linux/mount.h>
 #include <linux/moduleparam.h>
 #include <linux/kthread.h>
@@ -759,7 +760,7 @@ static struct file_system_type jfs_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
 
index 1f6dc518505c90b77e3bed2217f8d8de93f0803a..31668b690e03d4e482a8affb7657a310cffac1c0 100644 (file)
@@ -582,7 +582,15 @@ again:
        }
        if (status < 0)
                goto out_unlock;
-       status = nlm_stat_to_errno(resp->status);
+       /*
+        * EAGAIN doesn't make sense for sleeping locks, and in some
+        * cases NLM_LCK_DENIED is returned for a permanent error.  So
+        * turn it into an ENOLCK.
+        */
+       if (resp->status == nlm_lck_denied && (fl_flags & FL_SLEEP))
+               status = -ENOLCK;
+       else
+               status = nlm_stat_to_errno(resp->status);
 out_unblock:
        nlmclnt_finish_block(block);
 out:
index 821b9acdfb66accf6f2428a1eee2b2fcdcaa1620..cf0d5c2c318d6002330f1bca7965b09e8a047e9d 100644 (file)
@@ -418,8 +418,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
                        goto out;
                case -EAGAIN:
                        ret = nlm_lck_denied;
-                       break;
-               case -EINPROGRESS:
+                       goto out;
+               case FILE_LOCK_DEFERRED:
                        if (wait)
                                break;
                        /* Filesystem lock operation is in progress
@@ -434,10 +434,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
                        goto out;
        }
 
-       ret = nlm_lck_denied;
-       if (!wait)
-               goto out;
-
        ret = nlm_lck_blocked;
 
        /* Append to list of blocked */
@@ -507,7 +503,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
        }
 
        error = vfs_test_lock(file->f_file, &lock->fl);
-       if (error == -EINPROGRESS) {
+       if (error == FILE_LOCK_DEFERRED) {
                ret = nlmsvc_defer_lock_rqst(rqstp, block);
                goto out;
        }
@@ -731,8 +727,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
        switch (error) {
        case 0:
                break;
-       case -EAGAIN:
-       case -EINPROGRESS:
+       case FILE_LOCK_DEFERRED:
                dprintk("lockd: lock still blocked error %d\n", error);
                nlmsvc_insert_block(block, NLM_NEVER);
                nlmsvc_release_block(block);
index dce8c747371c77e618ee387158c37451daf63c97..5eb259e3cd38431e7e52baa5ed6975307ff782b5 100644 (file)
@@ -201,7 +201,7 @@ EXPORT_SYMBOL(locks_init_lock);
  * Initialises the fields of the file lock which are invariant for
  * free file_locks.
  */
-static void init_once(struct kmem_cache *cache, void *foo)
+static void init_once(void *foo)
 {
        struct file_lock *lock = (struct file_lock *) foo;
 
@@ -779,8 +779,10 @@ find_conflict:
                if (!flock_locks_conflict(request, fl))
                        continue;
                error = -EAGAIN;
-               if (request->fl_flags & FL_SLEEP)
-                       locks_insert_block(fl, request);
+               if (!(request->fl_flags & FL_SLEEP))
+                       goto out;
+               error = FILE_LOCK_DEFERRED;
+               locks_insert_block(fl, request);
                goto out;
        }
        if (request->fl_flags & FL_ACCESS)
@@ -836,7 +838,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
                        error = -EDEADLK;
                        if (posix_locks_deadlock(request, fl))
                                goto out;
-                       error = -EAGAIN;
+                       error = FILE_LOCK_DEFERRED;
                        locks_insert_block(fl, request);
                        goto out;
                }
@@ -1035,7 +1037,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
        might_sleep ();
        for (;;) {
                error = posix_lock_file(filp, fl, NULL);
-               if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+               if (error != FILE_LOCK_DEFERRED)
                        break;
                error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
                if (!error)
@@ -1107,9 +1109,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
 
        for (;;) {
                error = __posix_lock_file(inode, &fl, NULL);
-               if (error != -EAGAIN)
-                       break;
-               if (!(fl.fl_flags & FL_SLEEP))
+               if (error != FILE_LOCK_DEFERRED)
                        break;
                error = wait_event_interruptible(fl.fl_wait, !fl.fl_next);
                if (!error) {
@@ -1531,7 +1531,7 @@ int flock_lock_file_wait(struct file *filp, struct file_lock *fl)
        might_sleep();
        for (;;) {
                error = flock_lock_file(filp, fl);
-               if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+               if (error != FILE_LOCK_DEFERRED)
                        break;
                error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
                if (!error)
@@ -1716,17 +1716,17 @@ out:
  * fl_grant is set. Callers expecting ->lock() to return asynchronously
  * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
  * the request is for a blocking lock. When ->lock() does return asynchronously,
- * it must return -EINPROGRESS, and call ->fl_grant() when the lock
+ * it must return FILE_LOCK_DEFERRED, and call ->fl_grant() when the lock
  * request completes.
  * If the request is for non-blocking lock the file system should return
- * -EINPROGRESS then try to get the lock and call the callback routine with
- * the result. If the request timed out the callback routine will return a
+ * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine
+ * with the result. If the request timed out the callback routine will return a
  * nonzero return code and the file system should release the lock. The file
  * system is also responsible to keep a corresponding posix lock when it
  * grants a lock so the VFS can find out which locks are locally held and do
  * the correct lock cleanup when required.
  * The underlying filesystem must not drop the kernel lock or call
- * ->fl_grant() before returning to the caller with a -EINPROGRESS
+ * ->fl_grant() before returning to the caller with a FILE_LOCK_DEFERRED
  * return code.
  */
 int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
@@ -1738,6 +1738,30 @@ int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, str
 }
 EXPORT_SYMBOL_GPL(vfs_lock_file);
 
+static int do_lock_file_wait(struct file *filp, unsigned int cmd,
+                            struct file_lock *fl)
+{
+       int error;
+
+       error = security_file_lock(filp, fl->fl_type);
+       if (error)
+               return error;
+
+       for (;;) {
+               error = vfs_lock_file(filp, cmd, fl, NULL);
+               if (error != FILE_LOCK_DEFERRED)
+                       break;
+               error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
+               if (!error)
+                       continue;
+
+               locks_delete_block(fl);
+               break;
+       }
+
+       return error;
+}
+
 /* Apply the lock described by l to an open file descriptor.
  * This implements both the F_SETLK and F_SETLKW commands of fcntl().
  */
@@ -1795,26 +1819,7 @@ again:
                goto out;
        }
 
-       error = security_file_lock(filp, file_lock->fl_type);
-       if (error)
-               goto out;
-
-       if (filp->f_op && filp->f_op->lock != NULL)
-               error = filp->f_op->lock(filp, cmd, file_lock);
-       else {
-               for (;;) {
-                       error = posix_lock_file(filp, file_lock, NULL);
-                       if (error != -EAGAIN || cmd == F_SETLK)
-                               break;
-                       error = wait_event_interruptible(file_lock->fl_wait,
-                                       !file_lock->fl_next);
-                       if (!error)
-                               continue;
-
-                       locks_delete_block(file_lock);
-                       break;
-               }
-       }
+       error = do_lock_file_wait(filp, cmd, file_lock);
 
        /*
         * Attempt to detect a close/fcntl race and recover by
@@ -1932,26 +1937,7 @@ again:
                goto out;
        }
 
-       error = security_file_lock(filp, file_lock->fl_type);
-       if (error)
-               goto out;
-
-       if (filp->f_op && filp->f_op->lock != NULL)
-               error = filp->f_op->lock(filp, cmd, file_lock);
-       else {
-               for (;;) {
-                       error = posix_lock_file(filp, file_lock, NULL);
-                       if (error != -EAGAIN || cmd == F_SETLK64)
-                               break;
-                       error = wait_event_interruptible(file_lock->fl_wait,
-                                       !file_lock->fl_next);
-                       if (!error)
-                               continue;
-
-                       locks_delete_block(file_lock);
-                       break;
-               }
-       }
+       error = do_lock_file_wait(filp, cmd, file_lock);
 
        /*
         * Attempt to detect a close/fcntl race and recover by
index 84f6242ba6fc7262b2cf90a7d126f5192c6a13d9..d1d1eb84679d03ee19d62f7d4033c42d59ac2495 100644 (file)
@@ -68,7 +68,7 @@ static void minix_destroy_inode(struct inode *inode)
        kmem_cache_free(minix_inode_cachep, minix_i(inode));
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct minix_inode_info *ei = (struct minix_inode_info *) foo;
 
@@ -256,9 +256,6 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
        if (!s->s_root)
                goto out_iput;
 
-       if (!NO_TRUNCATE)
-               s->s_root->d_op = &minix_dentry_operations;
-
        if (!(s->s_flags & MS_RDONLY)) {
                if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
                        ms->s_state &= ~MINIX_VALID_FS;
index 326edfe96108f5eec496d57bd96092ff25b5e366..e6a0b193bea4141567f4462574584c4064a72a26 100644 (file)
@@ -2,11 +2,6 @@
 #include <linux/pagemap.h>
 #include <linux/minix_fs.h>
 
-/*
- * change the define below to 0 if you want names > info->s_namelen chars to be
- * truncated. Else they will be disallowed (ENAMETOOLONG).
- */
-#define NO_TRUNCATE 1
 #define INODE_VERSION(inode)   minix_sb(inode->i_sb)->s_version
 #define MINIX_V1               0x0001          /* original minix fs */
 #define MINIX_V2               0x0002          /* minix V2 fs */
@@ -83,7 +78,6 @@ extern const struct inode_operations minix_file_inode_operations;
 extern const struct inode_operations minix_dir_inode_operations;
 extern const struct file_operations minix_file_operations;
 extern const struct file_operations minix_dir_operations;
-extern struct dentry_operations minix_dentry_operations;
 
 static inline struct minix_sb_info *minix_sb(struct super_block *sb)
 {
index 102241bc9c7965e646585d871f4e1436a0057ccb..32b131cd6121d2599d84ee60af29ceac261453d9 100644 (file)
@@ -18,30 +18,6 @@ static int add_nondir(struct dentry *dentry, struct inode *inode)
        return err;
 }
 
-static int minix_hash(struct dentry *dentry, struct qstr *qstr)
-{
-       unsigned long hash;
-       int i;
-       const unsigned char *name;
-
-       i = minix_sb(dentry->d_inode->i_sb)->s_namelen;
-       if (i >= qstr->len)
-               return 0;
-       /* Truncate the name in place, avoids having to define a compare
-          function. */
-       qstr->len = i;
-       name = qstr->name;
-       hash = init_name_hash();
-       while (i--)
-               hash = partial_name_hash(*name++, hash);
-       qstr->hash = end_name_hash(hash);
-       return 0;
-}
-
-struct dentry_operations minix_dentry_operations = {
-       .d_hash         = minix_hash,
-};
-
 static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
        struct inode * inode = NULL;
index 1f7f2956412ac9527be5867aa5c5bca8ecc81db6..e844b9809d27de0aa1447dec920087b6978b8c7c 100644 (file)
 
 /* Characters that are undesirable in an MS-DOS file name */
 static unsigned char bad_chars[] = "*?<>|\"";
-static unsigned char bad_if_strict_pc[] = "+=,; ";
-/* GEMDOS is less restrictive */
-static unsigned char bad_if_strict_atari[] = " ";
-
-#define bad_if_strict(opts) \
-       ((opts)->atari ? bad_if_strict_atari : bad_if_strict_pc)
+static unsigned char bad_if_strict[] = "+=,; ";
 
 /***** Formats an MS-DOS file name. Rejects invalid names. */
 static int msdos_format_name(const unsigned char *name, int len,
@@ -40,21 +35,20 @@ static int msdos_format_name(const unsigned char *name, int len,
                        /* Get rid of dot - test for it elsewhere */
                        name++;
                        len--;
-               } else if (!opts->atari)
+               } else
                        return -EINVAL;
        }
        /*
-        * disallow names that _really_ start with a dot for MS-DOS,
-        * GEMDOS does not care
+        * disallow names that _really_ start with a dot
         */
-       space = !opts->atari;
+       space = 1;
        c = 0;
        for (walk = res; len && walk - res < 8; walk++) {
                c = *name++;
                len--;
                if (opts->name_check != 'r' && strchr(bad_chars, c))
                        return -EINVAL;
-               if (opts->name_check == 's' && strchr(bad_if_strict(opts), c))
+               if (opts->name_check == 's' && strchr(bad_if_strict, c))
                        return -EINVAL;
                if (c >= 'A' && c <= 'Z' && opts->name_check == 's')
                        return -EINVAL;
@@ -94,7 +88,7 @@ static int msdos_format_name(const unsigned char *name, int len,
                        if (opts->name_check != 'r' && strchr(bad_chars, c))
                                return -EINVAL;
                        if (opts->name_check == 's' &&
-                           strchr(bad_if_strict(opts), c))
+                           strchr(bad_if_strict, c))
                                return -EINVAL;
                        if (c < ' ' || c == ':' || c == '\\')
                                return -EINVAL;
@@ -243,6 +237,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
                           int is_dir, int is_hid, int cluster,
                           struct timespec *ts, struct fat_slot_info *sinfo)
 {
+       struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
        struct msdos_dir_entry de;
        __le16 time, date;
        int err;
@@ -252,7 +247,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
        if (is_hid)
                de.attr |= ATTR_HIDDEN;
        de.lcase = 0;
-       fat_date_unix2dos(ts->tv_sec, &time, &date);
+       fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
        de.cdate = de.adate = 0;
        de.ctime = 0;
        de.ctime_cs = 0;
index 01e67dddcc3d2033a2038c37f9f791ba0921a781..a7b0a0b8012873dd1c8db6fe79c45b459096af41 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/file.h>
 #include <linux/fcntl.h>
 #include <linux/device_cgroup.h>
-#include <asm/namei.h>
 #include <asm/uaccess.h>
 
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
@@ -185,6 +184,8 @@ int generic_permission(struct inode *inode, int mask,
 {
        umode_t                 mode = inode->i_mode;
 
+       mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
+
        if (current->fsuid == inode->i_uid)
                mode >>= 6;
        else {
@@ -203,7 +204,7 @@ int generic_permission(struct inode *inode, int mask,
        /*
         * If the DACs are ok we don't need any capability check.
         */
-       if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
+       if ((mask & ~mode) == 0)
                return 0;
 
  check_capabilities:
@@ -226,13 +227,9 @@ int generic_permission(struct inode *inode, int mask,
        return -EACCES;
 }
 
-int permission(struct inode *inode, int mask, struct nameidata *nd)
+int inode_permission(struct inode *inode, int mask)
 {
-       int retval, submask;
-       struct vfsmount *mnt = NULL;
-
-       if (nd)
-               mnt = nd->path.mnt;
+       int retval;
 
        if (mask & MAY_WRITE) {
                umode_t mode = inode->i_mode;
@@ -251,19 +248,9 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
                        return -EACCES;
        }
 
-       if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
-               /*
-                * MAY_EXEC on regular files is denied if the fs is mounted
-                * with the "noexec" flag.
-                */
-               if (mnt && (mnt->mnt_flags & MNT_NOEXEC))
-                       return -EACCES;
-       }
-
        /* Ordinary permission routines do not understand MAY_APPEND. */
-       submask = mask & ~MAY_APPEND;
        if (inode->i_op && inode->i_op->permission) {
-               retval = inode->i_op->permission(inode, submask, nd);
+               retval = inode->i_op->permission(inode, mask);
                if (!retval) {
                        /*
                         * Exec permission on a regular file is denied if none
@@ -277,7 +264,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
                                return -EACCES;
                }
        } else {
-               retval = generic_permission(inode, submask, NULL);
+               retval = generic_permission(inode, mask, NULL);
        }
        if (retval)
                return retval;
@@ -286,7 +273,8 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
        if (retval)
                return retval;
 
-       return security_inode_permission(inode, mask, nd);
+       return security_inode_permission(inode,
+                       mask & (MAY_READ|MAY_WRITE|MAY_EXEC));
 }
 
 /**
@@ -301,7 +289,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
  */
 int vfs_permission(struct nameidata *nd, int mask)
 {
-       return permission(nd->path.dentry->d_inode, mask, nd);
+       return inode_permission(nd->path.dentry->d_inode, mask);
 }
 
 /**
@@ -318,7 +306,7 @@ int vfs_permission(struct nameidata *nd, int mask)
  */
 int file_permission(struct file *file, int mask)
 {
-       return permission(file->f_path.dentry->d_inode, mask, NULL);
+       return inode_permission(file->f_path.dentry->d_inode, mask);
 }
 
 /*
@@ -459,8 +447,7 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
  * short-cut DAC fails, then call permission() to do more
  * complete permission check.
  */
-static int exec_permission_lite(struct inode *inode,
-                                      struct nameidata *nd)
+static int exec_permission_lite(struct inode *inode)
 {
        umode_t mode = inode->i_mode;
 
@@ -486,7 +473,7 @@ static int exec_permission_lite(struct inode *inode,
 
        return -EACCES;
 ok:
-       return security_inode_permission(inode, MAY_EXEC, nd);
+       return security_inode_permission(inode, MAY_EXEC);
 }
 
 /*
@@ -519,7 +506,14 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
         */
        result = d_lookup(parent, name);
        if (!result) {
-               struct dentry * dentry = d_alloc(parent, name);
+               struct dentry *dentry;
+
+               /* Don't create child dentry for a dead directory. */
+               result = ERR_PTR(-ENOENT);
+               if (IS_DEADDIR(dir))
+                       goto out_unlock;
+
+               dentry = d_alloc(parent, name);
                result = ERR_PTR(-ENOMEM);
                if (dentry) {
                        result = dir->i_op->lookup(dir, dentry, nd);
@@ -528,6 +522,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
                        else
                                result = dentry;
                }
+out_unlock:
                mutex_unlock(&dir->i_mutex);
                return result;
        }
@@ -545,27 +540,16 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
        return result;
 }
 
-static int __emul_lookup_dentry(const char *, struct nameidata *);
-
 /* SMP-safe */
-static __always_inline int
+static __always_inline void
 walk_init_root(const char *name, struct nameidata *nd)
 {
        struct fs_struct *fs = current->fs;
 
        read_lock(&fs->lock);
-       if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) {
-               nd->path = fs->altroot;
-               path_get(&fs->altroot);
-               read_unlock(&fs->lock);
-               if (__emul_lookup_dentry(name,nd))
-                       return 0;
-               read_lock(&fs->lock);
-       }
        nd->path = fs->root;
        path_get(&fs->root);
        read_unlock(&fs->lock);
-       return 1;
 }
 
 /*
@@ -606,12 +590,9 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l
 
        if (*link == '/') {
                path_put(&nd->path);
-               if (!walk_init_root(link, nd))
-                       /* weird __emul_prefix() stuff did it */
-                       goto out;
+               walk_init_root(link, nd);
        }
        res = link_path_walk(link, nd);
-out:
        if (nd->depth || res || nd->last_type!=LAST_NORM)
                return res;
        /*
@@ -889,7 +870,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
                unsigned int c;
 
                nd->flags |= LOOKUP_CONTINUE;
-               err = exec_permission_lite(inode, nd);
+               err = exec_permission_lite(inode);
                if (err == -EAGAIN)
                        err = vfs_permission(nd, MAY_EXEC);
                if (err)
@@ -1060,67 +1041,6 @@ static int path_walk(const char *name, struct nameidata *nd)
        return link_path_walk(name, nd);
 }
 
-/* 
- * SMP-safe: Returns 1 and nd will have valid dentry and mnt, if
- * everything is done. Returns 0 and drops input nd, if lookup failed;
- */
-static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
-{
-       if (path_walk(name, nd))
-               return 0;               /* something went wrong... */
-
-       if (!nd->path.dentry->d_inode ||
-           S_ISDIR(nd->path.dentry->d_inode->i_mode)) {
-               struct path old_path = nd->path;
-               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:
-                */
-               nd->last_type = LAST_ROOT;
-               read_lock(&fs->lock);
-               nd->path = fs->root;
-               path_get(&fs->root);
-               read_unlock(&fs->lock);
-               if (path_walk(name, nd) == 0) {
-                       if (nd->path.dentry->d_inode) {
-                               path_put(&old_path);
-                               return 1;
-                       }
-                       path_put(&nd->path);
-               }
-               nd->path = old_path;
-               nd->last = last;
-               nd->last_type = last_type;
-       }
-       return 1;
-}
-
-void set_fs_altroot(void)
-{
-       char *emul = __emul_prefix();
-       struct nameidata nd;
-       struct path path = {}, old_path;
-       int err;
-       struct fs_struct *fs = current->fs;
-
-       if (!emul)
-               goto set_it;
-       err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd);
-       if (!err)
-               path = nd.path;
-set_it:
-       write_lock(&fs->lock);
-       old_path = fs->altroot;
-       fs->altroot = path;
-       write_unlock(&fs->lock);
-       if (old_path.dentry)
-               path_put(&old_path);
-}
-
 /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
 static int do_path_lookup(int dfd, const char *name,
                                unsigned int flags, struct nameidata *nd)
@@ -1136,14 +1056,6 @@ static int do_path_lookup(int dfd, const char *name,
 
        if (*name=='/') {
                read_lock(&fs->lock);
-               if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) {
-                       nd->path = fs->altroot;
-                       path_get(&fs->altroot);
-                       read_unlock(&fs->lock);
-                       if (__emul_lookup_dentry(name,nd))
-                               goto out; /* found in altroot */
-                       read_lock(&fs->lock);
-               }
                nd->path = fs->root;
                path_get(&fs->root);
                read_unlock(&fs->lock);
@@ -1177,7 +1089,6 @@ static int do_path_lookup(int dfd, const char *name,
        }
 
        retval = path_walk(name, nd);
-out:
        if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
                                nd->path.dentry->d_inode))
                audit_inode(name, nd->path.dentry);
@@ -1282,19 +1193,6 @@ static int path_lookup_create(int dfd, const char *name,
                        nd, open_flags, create_mode);
 }
 
-int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
-               struct nameidata *nd, int open_flags)
-{
-       char *tmp = getname(name);
-       int err = PTR_ERR(tmp);
-
-       if (!IS_ERR(tmp)) {
-               err = __path_lookup_intent_open(AT_FDCWD, tmp, lookup_flags, nd, open_flags, 0);
-               putname(tmp);
-       }
-       return err;
-}
-
 static struct dentry *__lookup_hash(struct qstr *name,
                struct dentry *base, struct nameidata *nd)
 {
@@ -1317,7 +1215,14 @@ static struct dentry *__lookup_hash(struct qstr *name,
 
        dentry = cached_lookup(base, name, nd);
        if (!dentry) {
-               struct dentry *new = d_alloc(base, name);
+               struct dentry *new;
+
+               /* Don't create child dentry for a dead directory. */
+               dentry = ERR_PTR(-ENOENT);
+               if (IS_DEADDIR(inode))
+                       goto out;
+
+               new = d_alloc(base, name);
                dentry = ERR_PTR(-ENOMEM);
                if (!new)
                        goto out;
@@ -1340,7 +1245,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
 {
        int err;
 
-       err = permission(nd->path.dentry->d_inode, MAY_EXEC, nd);
+       err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC);
        if (err)
                return ERR_PTR(err);
        return __lookup_hash(&nd->last, nd->path.dentry, nd);
@@ -1388,7 +1293,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
        if (err)
                return ERR_PTR(err);
 
-       err = permission(base->d_inode, MAY_EXEC, NULL);
+       err = inode_permission(base->d_inode, MAY_EXEC);
        if (err)
                return ERR_PTR(err);
        return __lookup_hash(&this, base, NULL);
@@ -1416,22 +1321,40 @@ struct dentry *lookup_one_noperm(const char *name, struct dentry *base)
        return __lookup_hash(&this, base, NULL);
 }
 
-int __user_walk_fd(int dfd, const char __user *name, unsigned flags,
-                           struct nameidata *nd)
+int user_path_at(int dfd, const char __user *name, unsigned flags,
+                struct path *path)
 {
+       struct nameidata nd;
        char *tmp = getname(name);
        int err = PTR_ERR(tmp);
-
        if (!IS_ERR(tmp)) {
-               err = do_path_lookup(dfd, tmp, flags, nd);
+
+               BUG_ON(flags & LOOKUP_PARENT);
+
+               err = do_path_lookup(dfd, tmp, flags, &nd);
                putname(tmp);
+               if (!err)
+                       *path = nd.path;
        }
        return err;
 }
 
-int __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
+static int user_path_parent(int dfd, const char __user *path,
+                       struct nameidata *nd, char **name)
 {
-       return __user_walk_fd(AT_FDCWD, name, flags, nd);
+       char *s = getname(path);
+       int error;
+
+       if (IS_ERR(s))
+               return PTR_ERR(s);
+
+       error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd);
+       if (error)
+               putname(s);
+       else
+               *name = s;
+
+       return error;
 }
 
 /*
@@ -1478,7 +1401,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
        BUG_ON(victim->d_parent->d_inode != dir);
        audit_inode_child(victim->d_name.name, victim, dir);
 
-       error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
+       error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
        if (error)
                return error;
        if (IS_APPEND(dir))
@@ -1515,7 +1438,7 @@ static inline int may_create(struct inode *dir, struct dentry *child,
                return -EEXIST;
        if (IS_DEADDIR(dir))
                return -ENOENT;
-       return permission(dir,MAY_WRITE | MAY_EXEC, nd);
+       return inode_permission(dir, MAY_WRITE | MAY_EXEC);
 }
 
 /* 
@@ -1755,7 +1678,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
        int will_write;
        int flag = open_to_namei_flags(open_flag);
 
-       acc_mode = ACC_MODE(flag);
+       acc_mode = MAY_OPEN | ACC_MODE(flag);
 
        /* O_TRUNC implies we need access checks for write permissions */
        if (flag & O_TRUNC)
@@ -2071,20 +1994,18 @@ static int may_mknod(mode_t mode)
 asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
                                unsigned dev)
 {
-       int error = 0;
-       char * tmp;
-       struct dentry * dentry;
+       int error;
+       char *tmp;
+       struct dentry *dentry;
        struct nameidata nd;
 
        if (S_ISDIR(mode))
                return -EPERM;
-       tmp = getname(filename);
-       if (IS_ERR(tmp))
-               return PTR_ERR(tmp);
 
-       error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+       error = user_path_parent(dfd, filename, &nd, &tmp);
        if (error)
-               goto out;
+               return error;
+
        dentry = lookup_create(&nd, 0);
        if (IS_ERR(dentry)) {
                error = PTR_ERR(dentry);
@@ -2116,7 +2037,6 @@ out_dput:
 out_unlock:
        mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
        path_put(&nd.path);
-out:
        putname(tmp);
 
        return error;
@@ -2156,14 +2076,10 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
        struct dentry *dentry;
        struct nameidata nd;
 
-       tmp = getname(pathname);
-       error = PTR_ERR(tmp);
-       if (IS_ERR(tmp))
+       error = user_path_parent(dfd, pathname, &nd, &tmp);
+       if (error)
                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))
@@ -2181,7 +2097,6 @@ out_dput:
 out_unlock:
        mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
        path_put(&nd.path);
-out:
        putname(tmp);
 out_err:
        return error;
@@ -2259,13 +2174,9 @@ static long do_rmdir(int dfd, const char __user *pathname)
        struct dentry *dentry;
        struct nameidata nd;
 
-       name = getname(pathname);
-       if(IS_ERR(name))
-               return PTR_ERR(name);
-
-       error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
+       error = user_path_parent(dfd, pathname, &nd, &name);
        if (error)
-               goto exit;
+               return error;
 
        switch(nd.last_type) {
                case LAST_DOTDOT:
@@ -2294,7 +2205,6 @@ exit2:
        mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
 exit1:
        path_put(&nd.path);
-exit:
        putname(name);
        return error;
 }
@@ -2343,19 +2253,16 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
  */
 static long do_unlinkat(int dfd, const char __user *pathname)
 {
-       int error = 0;
-       char * name;
+       int error;
+       char *name;
        struct dentry *dentry;
        struct nameidata nd;
        struct inode *inode = NULL;
 
-       name = getname(pathname);
-       if(IS_ERR(name))
-               return PTR_ERR(name);
-
-       error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
+       error = user_path_parent(dfd, pathname, &nd, &name);
        if (error)
-               goto exit;
+               return error;
+
        error = -EISDIR;
        if (nd.last_type != LAST_NORM)
                goto exit1;
@@ -2382,7 +2289,6 @@ static long do_unlinkat(int dfd, const char __user *pathname)
                iput(inode);    /* truncate the inode here */
 exit1:
        path_put(&nd.path);
-exit:
        putname(name);
        return error;
 
@@ -2408,7 +2314,7 @@ asmlinkage long sys_unlink(const char __user *pathname)
        return do_unlinkat(AT_FDCWD, pathname);
 }
 
-int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
+int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
 {
        int error = may_create(dir, dentry, NULL);
 
@@ -2432,23 +2338,20 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i
 asmlinkage long sys_symlinkat(const char __user *oldname,
                              int newdfd, const char __user *newname)
 {
-       int error = 0;
-       char * from;
-       char * to;
+       int error;
+       char *from;
+       char *to;
        struct dentry *dentry;
        struct nameidata nd;
 
        from = getname(oldname);
-       if(IS_ERR(from))
+       if (IS_ERR(from))
                return PTR_ERR(from);
-       to = getname(newname);
-       error = PTR_ERR(to);
-       if (IS_ERR(to))
-               goto out_putname;
 
-       error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+       error = user_path_parent(newdfd, newname, &nd, &to);
        if (error)
-               goto out;
+               goto out_putname;
+
        dentry = lookup_create(&nd, 0);
        error = PTR_ERR(dentry);
        if (IS_ERR(dentry))
@@ -2457,14 +2360,13 @@ asmlinkage long sys_symlinkat(const char __user *oldname,
        error = mnt_want_write(nd.path.mnt);
        if (error)
                goto out_dput;
-       error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO);
+       error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
        mnt_drop_write(nd.path.mnt);
 out_dput:
        dput(dentry);
 out_unlock:
        mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
        path_put(&nd.path);
-out:
        putname(to);
 out_putname:
        putname(from);
@@ -2498,19 +2400,19 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
                return -EPERM;
        if (!dir->i_op || !dir->i_op->link)
                return -EPERM;
-       if (S_ISDIR(old_dentry->d_inode->i_mode))
+       if (S_ISDIR(inode->i_mode))
                return -EPERM;
 
        error = security_inode_link(old_dentry, dir, new_dentry);
        if (error)
                return error;
 
-       mutex_lock(&old_dentry->d_inode->i_mutex);
+       mutex_lock(&inode->i_mutex);
        DQUOT_INIT(dir);
        error = dir->i_op->link(old_dentry, dir, new_dentry);
-       mutex_unlock(&old_dentry->d_inode->i_mutex);
+       mutex_unlock(&inode->i_mutex);
        if (!error)
-               fsnotify_link(dir, old_dentry->d_inode, new_dentry);
+               fsnotify_link(dir, inode, new_dentry);
        return error;
 }
 
@@ -2528,27 +2430,25 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
                           int flags)
 {
        struct dentry *new_dentry;
-       struct nameidata nd, old_nd;
+       struct nameidata nd;
+       struct path old_path;
        int error;
-       char * to;
+       char *to;
 
        if ((flags & ~AT_SYMLINK_FOLLOW) != 0)
                return -EINVAL;
 
-       to = getname(newname);
-       if (IS_ERR(to))
-               return PTR_ERR(to);
-
-       error = __user_walk_fd(olddfd, oldname,
-                              flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
-                              &old_nd);
+       error = user_path_at(olddfd, oldname,
+                            flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
+                            &old_path);
        if (error)
-               goto exit;
-       error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+               return error;
+
+       error = user_path_parent(newdfd, newname, &nd, &to);
        if (error)
                goto out;
        error = -EXDEV;
-       if (old_nd.path.mnt != nd.path.mnt)
+       if (old_path.mnt != nd.path.mnt)
                goto out_release;
        new_dentry = lookup_create(&nd, 0);
        error = PTR_ERR(new_dentry);
@@ -2557,7 +2457,7 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
        error = mnt_want_write(nd.path.mnt);
        if (error)
                goto out_dput;
-       error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry);
+       error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
        mnt_drop_write(nd.path.mnt);
 out_dput:
        dput(new_dentry);
@@ -2565,10 +2465,9 @@ out_unlock:
        mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
 out_release:
        path_put(&nd.path);
-out:
-       path_put(&old_nd.path);
-exit:
        putname(to);
+out:
+       path_put(&old_path);
 
        return error;
 }
@@ -2621,7 +2520,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
         * we'll need to flip '..'.
         */
        if (new_dir != old_dir) {
-               error = permission(old_dentry->d_inode, MAY_WRITE, NULL);
+               error = inode_permission(old_dentry->d_inode, MAY_WRITE);
                if (error)
                        return error;
        }
@@ -2724,20 +2623,22 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        return error;
 }
 
-static int do_rename(int olddfd, const char *oldname,
-                       int newdfd, const char *newname)
+asmlinkage long sys_renameat(int olddfd, const char __user *oldname,
+                            int newdfd, const char __user *newname)
 {
-       int error = 0;
-       struct dentry * old_dir, * new_dir;
-       struct dentry * old_dentry, *new_dentry;
-       struct dentry * trap;
+       struct dentry *old_dir, *new_dir;
+       struct dentry *old_dentry, *new_dentry;
+       struct dentry *trap;
        struct nameidata oldnd, newnd;
+       char *from;
+       char *to;
+       int error;
 
-       error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd);
+       error = user_path_parent(olddfd, oldname, &oldnd, &from);
        if (error)
                goto exit;
 
-       error = do_path_lookup(newdfd, newname, LOOKUP_PARENT, &newnd);
+       error = user_path_parent(newdfd, newname, &newnd, &to);
        if (error)
                goto exit1;
 
@@ -2799,29 +2700,11 @@ exit3:
        unlock_rename(new_dir, old_dir);
 exit2:
        path_put(&newnd.path);
+       putname(to);
 exit1:
        path_put(&oldnd.path);
-exit:
-       return error;
-}
-
-asmlinkage long sys_renameat(int olddfd, const char __user *oldname,
-                            int newdfd, const char __user *newname)
-{
-       int error;
-       char * from;
-       char * to;
-
-       from = getname(oldname);
-       if(IS_ERR(from))
-               return PTR_ERR(from);
-       to = getname(newname);
-       error = PTR_ERR(to);
-       if (!IS_ERR(to)) {
-               error = do_rename(olddfd, from, newdfd, to);
-               putname(to);
-       }
        putname(from);
+exit:
        return error;
 }
 
@@ -2959,8 +2842,7 @@ const struct inode_operations page_symlink_inode_operations = {
        .put_link       = page_put_link,
 };
 
-EXPORT_SYMBOL(__user_walk);
-EXPORT_SYMBOL(__user_walk_fd);
+EXPORT_SYMBOL(user_path_at);
 EXPORT_SYMBOL(follow_down);
 EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
@@ -2975,7 +2857,7 @@ EXPORT_SYMBOL(page_symlink);
 EXPORT_SYMBOL(page_symlink_inode_operations);
 EXPORT_SYMBOL(path_lookup);
 EXPORT_SYMBOL(vfs_path_lookup);
-EXPORT_SYMBOL(permission);
+EXPORT_SYMBOL(inode_permission);
 EXPORT_SYMBOL(vfs_permission);
 EXPORT_SYMBOL(file_permission);
 EXPORT_SYMBOL(unlock_rename);
index 4f6f7635b59c93c0c2a86a8deff1f59c567de9f5..411728c0c8bb2b0ee1248d95106c32c1ad4ef36b 100644 (file)
@@ -112,9 +112,13 @@ struct vfsmount *alloc_vfsmnt(const char *name)
                int err;
 
                err = mnt_alloc_id(mnt);
-               if (err) {
-                       kmem_cache_free(mnt_cache, mnt);
-                       return NULL;
+               if (err)
+                       goto out_free_cache;
+
+               if (name) {
+                       mnt->mnt_devname = kstrdup(name, GFP_KERNEL);
+                       if (!mnt->mnt_devname)
+                               goto out_free_id;
                }
 
                atomic_set(&mnt->mnt_count, 1);
@@ -127,16 +131,14 @@ struct vfsmount *alloc_vfsmnt(const char *name)
                INIT_LIST_HEAD(&mnt->mnt_slave_list);
                INIT_LIST_HEAD(&mnt->mnt_slave);
                atomic_set(&mnt->__mnt_writers, 0);
-               if (name) {
-                       int size = strlen(name) + 1;
-                       char *newname = kmalloc(size, GFP_KERNEL);
-                       if (newname) {
-                               memcpy(newname, name, size);
-                               mnt->mnt_devname = newname;
-                       }
-               }
        }
        return mnt;
+
+out_free_id:
+       mnt_free_id(mnt);
+out_free_cache:
+       kmem_cache_free(mnt_cache, mnt);
+       return NULL;
 }
 
 /*
@@ -309,10 +311,9 @@ static void handle_write_count_underflow(struct vfsmount *mnt)
         */
        if ((atomic_read(&mnt->__mnt_writers) < 0) &&
            !(mnt->mnt_flags & MNT_IMBALANCED_WRITE_COUNT)) {
-               printk(KERN_DEBUG "leak detected on mount(%p) writers "
+               WARN(1, KERN_DEBUG "leak detected on mount(%p) writers "
                                "count: %d\n",
                        mnt, atomic_read(&mnt->__mnt_writers));
-               WARN_ON(1);
                /* use the flag to keep the dmesg spam down */
                mnt->mnt_flags |= MNT_IMBALANCED_WRITE_COUNT;
        }
@@ -1129,27 +1130,27 @@ static int do_umount(struct vfsmount *mnt, int flags)
 
 asmlinkage long sys_umount(char __user * name, int flags)
 {
-       struct nameidata nd;
+       struct path path;
        int retval;
 
-       retval = __user_walk(name, LOOKUP_FOLLOW, &nd);
+       retval = user_path(name, &path);
        if (retval)
                goto out;
        retval = -EINVAL;
-       if (nd.path.dentry != nd.path.mnt->mnt_root)
+       if (path.dentry != path.mnt->mnt_root)
                goto dput_and_out;
-       if (!check_mnt(nd.path.mnt))
+       if (!check_mnt(path.mnt))
                goto dput_and_out;
 
        retval = -EPERM;
        if (!capable(CAP_SYS_ADMIN))
                goto dput_and_out;
 
-       retval = do_umount(nd.path.mnt, flags);
+       retval = do_umount(path.mnt, flags);
 dput_and_out:
        /* we mustn't call path_put() as that would clear mnt_expiry_mark */
-       dput(nd.path.dentry);
-       mntput_no_expire(nd.path.mnt);
+       dput(path.dentry);
+       mntput_no_expire(path.mnt);
 out:
        return retval;
 }
@@ -1973,7 +1974,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
                struct fs_struct *fs)
 {
        struct mnt_namespace *new_ns;
-       struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
+       struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
        struct vfsmount *p, *q;
 
        new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
@@ -2016,10 +2017,6 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
                                pwdmnt = p;
                                fs->pwd.mnt = mntget(q);
                        }
-                       if (p == fs->altroot.mnt) {
-                               altrootmnt = p;
-                               fs->altroot.mnt = mntget(q);
-                       }
                }
                p = next_mnt(p, mnt_ns->root);
                q = next_mnt(q, new_ns->root);
@@ -2030,8 +2027,6 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
                mntput(rootmnt);
        if (pwdmnt)
                mntput(pwdmnt);
-       if (altrootmnt)
-               mntput(altrootmnt);
 
        return new_ns;
 }
@@ -2184,28 +2179,26 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
                               const char __user * put_old)
 {
        struct vfsmount *tmp;
-       struct nameidata new_nd, old_nd;
-       struct path parent_path, root_parent, root;
+       struct path new, old, parent_path, root_parent, root;
        int error;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
-                           &new_nd);
+       error = user_path_dir(new_root, &new);
        if (error)
                goto out0;
        error = -EINVAL;
-       if (!check_mnt(new_nd.path.mnt))
+       if (!check_mnt(new.mnt))
                goto out1;
 
-       error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd);
+       error = user_path_dir(put_old, &old);
        if (error)
                goto out1;
 
-       error = security_sb_pivotroot(&old_nd.path, &new_nd.path);
+       error = security_sb_pivotroot(&old, &new);
        if (error) {
-               path_put(&old_nd.path);
+               path_put(&old);
                goto out1;
        }
 
@@ -2214,69 +2207,69 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
        path_get(&current->fs->root);
        read_unlock(&current->fs->lock);
        down_write(&namespace_sem);
-       mutex_lock(&old_nd.path.dentry->d_inode->i_mutex);
+       mutex_lock(&old.dentry->d_inode->i_mutex);
        error = -EINVAL;
-       if (IS_MNT_SHARED(old_nd.path.mnt) ||
-               IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) ||
+       if (IS_MNT_SHARED(old.mnt) ||
+               IS_MNT_SHARED(new.mnt->mnt_parent) ||
                IS_MNT_SHARED(root.mnt->mnt_parent))
                goto out2;
        if (!check_mnt(root.mnt))
                goto out2;
        error = -ENOENT;
-       if (IS_DEADDIR(new_nd.path.dentry->d_inode))
+       if (IS_DEADDIR(new.dentry->d_inode))
                goto out2;
-       if (d_unhashed(new_nd.path.dentry) && !IS_ROOT(new_nd.path.dentry))
+       if (d_unhashed(new.dentry) && !IS_ROOT(new.dentry))
                goto out2;
-       if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry))
+       if (d_unhashed(old.dentry) && !IS_ROOT(old.dentry))
                goto out2;
        error = -EBUSY;
-       if (new_nd.path.mnt == root.mnt ||
-           old_nd.path.mnt == root.mnt)
+       if (new.mnt == root.mnt ||
+           old.mnt == root.mnt)
                goto out2; /* loop, on the same file system  */
        error = -EINVAL;
        if (root.mnt->mnt_root != root.dentry)
                goto out2; /* not a mountpoint */
        if (root.mnt->mnt_parent == root.mnt)
                goto out2; /* not attached */
-       if (new_nd.path.mnt->mnt_root != new_nd.path.dentry)
+       if (new.mnt->mnt_root != new.dentry)
                goto out2; /* not a mountpoint */
-       if (new_nd.path.mnt->mnt_parent == new_nd.path.mnt)
+       if (new.mnt->mnt_parent == new.mnt)
                goto out2; /* not attached */
        /* make sure we can reach put_old from new_root */
-       tmp = old_nd.path.mnt;
+       tmp = old.mnt;
        spin_lock(&vfsmount_lock);
-       if (tmp != new_nd.path.mnt) {
+       if (tmp != new.mnt) {
                for (;;) {
                        if (tmp->mnt_parent == tmp)
                                goto out3; /* already mounted on put_old */
-                       if (tmp->mnt_parent == new_nd.path.mnt)
+                       if (tmp->mnt_parent == new.mnt)
                                break;
                        tmp = tmp->mnt_parent;
                }
-               if (!is_subdir(tmp->mnt_mountpoint, new_nd.path.dentry))
+               if (!is_subdir(tmp->mnt_mountpoint, new.dentry))
                        goto out3;
-       } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry))
+       } else if (!is_subdir(old.dentry, new.dentry))
                goto out3;
-       detach_mnt(new_nd.path.mnt, &parent_path);
+       detach_mnt(new.mnt, &parent_path);
        detach_mnt(root.mnt, &root_parent);
        /* mount old root on put_old */
-       attach_mnt(root.mnt, &old_nd.path);
+       attach_mnt(root.mnt, &old);
        /* mount new_root on / */
-       attach_mnt(new_nd.path.mnt, &root_parent);
+       attach_mnt(new.mnt, &root_parent);
        touch_mnt_namespace(current->nsproxy->mnt_ns);
        spin_unlock(&vfsmount_lock);
-       chroot_fs_refs(&root, &new_nd.path);
-       security_sb_post_pivotroot(&root, &new_nd.path);
+       chroot_fs_refs(&root, &new);
+       security_sb_post_pivotroot(&root, &new);
        error = 0;
        path_put(&root_parent);
        path_put(&parent_path);
 out2:
-       mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex);
+       mutex_unlock(&old.dentry->d_inode->i_mutex);
        up_write(&namespace_sem);
        path_put(&root);
-       path_put(&old_nd.path);
+       path_put(&old);
 out1:
-       path_put(&new_nd.path);
+       path_put(&new);
 out0:
        return error;
 out3:
index 011ef0b6d2d48eb9fcc391fc9180ceb4d34d4f6a..07e9715b865887042b899299effe1c4f37a7e106 100644 (file)
@@ -266,7 +266,7 @@ leave_me:;
 
 
 static int
-__ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
+__ncp_lookup_validate(struct dentry *dentry)
 {
        struct ncp_server *server;
        struct dentry *parent;
@@ -340,7 +340,7 @@ ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
 {
        int res;
        lock_kernel();
-       res = __ncp_lookup_validate(dentry, nd);
+       res = __ncp_lookup_validate(dentry);
        unlock_kernel();
        return res;
 }
index 2e5ab1204dece88feb8f1709cf37323ff459658c..d642f0e5b3653059f0d2c319a5e930f17170b0ed 100644 (file)
@@ -64,7 +64,7 @@ static void ncp_destroy_inode(struct inode *inode)
        kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
 
index 28a238dab23a2a16919ef58706a431447bcc8f5b..74f92b717f783ca1974094beabb879ea1adde0cc 100644 (file)
@@ -1884,7 +1884,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
                return status;
        nfs_access_add_cache(inode, &cache);
 out:
-       if ((cache.mask & mask) == mask)
+       if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
                return 0;
        return -EACCES;
 }
@@ -1907,17 +1907,17 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
        return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
 }
 
-int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+int nfs_permission(struct inode *inode, int mask)
 {
        struct rpc_cred *cred;
        int res = 0;
 
        nfs_inc_stats(inode, NFSIOS_VFSACCESS);
 
-       if (mask == 0)
+       if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
                goto out;
        /* Is this sys_access() ? */
-       if (nd != NULL && (nd->flags & LOOKUP_ACCESS))
+       if (mask & MAY_ACCESS)
                goto force_lookup;
 
        switch (inode->i_mode & S_IFMT) {
@@ -1926,8 +1926,7 @@ int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
                case S_IFREG:
                        /* NFSv4 has atomic_open... */
                        if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN)
-                                       && nd != NULL
-                                       && (nd->flags & LOOKUP_OPEN))
+                                       && (mask & MAY_OPEN))
                                goto out;
                        break;
                case S_IFDIR:
index df23f987da6beeb006496ece538f20765599acb7..52daefa2f5210ef44a34a6ba0779e791453ba81d 100644 (file)
@@ -1242,7 +1242,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
 #endif
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct nfs_inode *nfsi = (struct nfs_inode *) foo;
 
index 46763d1cd3976bca27f4d5dca5d3dd9e36d3453b..8478fc25daee196383f3e40a34999795be41585e 100644 (file)
@@ -127,7 +127,7 @@ enum {
        Opt_err
 };
 
-static match_table_t __initdata tokens = {
+static match_table_t __initconst tokens = {
        {Opt_port, "port=%u"},
        {Opt_rsize, "rsize=%u"},
        {Opt_wsize, "wsize=%u"},
index 1b94e3650f5cb343d241d372d0d03d85ed42528d..9abcd2b329f7357b0af65065613e996b643e1747 100644 (file)
@@ -1718,9 +1718,9 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
         * ones were explicitly specified. Fall back to legacy behavior and
         * just return success.
         */
-       if ((nfsvers == 4 && options4->version == 1) ||
-           (nfsvers <= 3 && options->version >= 1 &&
-            options->version <= 6))
+       if ((nfsvers == 4 && (!options4 || options4->version == 1)) ||
+           (nfsvers <= 3 && (!options || (options->version >= 1 &&
+                                          options->version <= 6))))
                return 0;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
index 3adf8b266461fbf3562d7876ed57f50de2f974df..f089e5839d7deefe50bc351f98eff7d45fdfd453 100644 (file)
@@ -95,10 +95,11 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
 static void nfs_async_unlink_release(void *calldata)
 {
        struct nfs_unlinkdata   *data = calldata;
+       struct super_block *sb = data->dir->i_sb;
 
        nfs_dec_sillycount(data->dir);
-       nfs_sb_deactive(NFS_SERVER(data->dir));
        nfs_free_unlinkdata(data);
+       nfs_sb_deactive(NFS_SB(sb));
 }
 
 static const struct rpc_call_ops nfs_unlink_ops = {
index 6b6225ac4926f8364762ed5c74bda3a5681235b7..15c6faeec77c118a77b11c50287a6a43828bd9a2 100644 (file)
 
 #define NFSDDBG_FACILITY               NFSDDBG_LOCKD
 
+#ifdef CONFIG_LOCKD_V4
+#define nlm_stale_fh   nlm4_stale_fh
+#define nlm_failed     nlm4_failed
+#else
+#define nlm_stale_fh   nlm_lck_denied_nolocks
+#define nlm_failed     nlm_lck_denied_nolocks
+#endif
 /*
  * Note: we hold the dentry use count while the file is open.
  */
@@ -47,12 +54,10 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
                return 0;
        case nfserr_dropit:
                return nlm_drop_reply;
-#ifdef CONFIG_LOCKD_V4
        case nfserr_stale:
-               return nlm4_stale_fh;
-#endif
+               return nlm_stale_fh;
        default:
-               return nlm_lck_denied;
+               return nlm_failed;
        }
 }
 
index 1955a2702e60a473cad46549d2e58298c5c767c7..c53e65f8f3a2b460d6c01424094b29c8082843a4 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/namei.h>
 #include <linux/fcntl.h>
 #include <linux/net.h>
 #include <linux/in.h>
index f45451eb1e383b6bb1a353c5c7a2ed2e2c9d0468..ea37c96f04454e7f1513ca1222aa4eba86f98fb0 100644 (file)
@@ -51,7 +51,7 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry)
                /* make sure parents give x permission to user */
                int err;
                parent = dget_parent(tdentry);
-               err = permission(parent->d_inode, MAY_EXEC, NULL);
+               err = inode_permission(parent->d_inode, MAY_EXEC);
                if (err < 0) {
                        dput(parent);
                        break;
index 0f4481e0502d132b624e952f3c2cbad50163c4ab..18060bed5267451c005345ef19f5a270ee5143aa 100644 (file)
@@ -1516,7 +1516,6 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
        struct dentry   *dentry, *dnew;
        __be32          err, cerr;
        int             host_err;
-       umode_t         mode;
 
        err = nfserr_noent;
        if (!flen || !plen)
@@ -1535,11 +1534,6 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
        if (IS_ERR(dnew))
                goto out_nfserr;
 
-       mode = S_IALLUGO;
-       /* Only the MODE ATTRibute is even vaguely meaningful */
-       if (iap && (iap->ia_valid & ATTR_MODE))
-               mode = iap->ia_mode & S_IALLUGO;
-
        host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
        if (host_err)
                goto out_nfserr;
@@ -1551,11 +1545,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
                else {
                        strncpy(path_alloced, path, plen);
                        path_alloced[plen] = 0;
-                       host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode);
+                       host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced);
                        kfree(path_alloced);
                }
        } else
-               host_err = vfs_symlink(dentry->d_inode, dnew, path, mode);
+               host_err = vfs_symlink(dentry->d_inode, dnew, path);
 
        if (!host_err) {
                if (EX_ISSYNC(fhp->fh_export))
@@ -1959,12 +1953,12 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
                return 0;
 
        /* This assumes  NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */
-       err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
+       err = inode_permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC));
 
        /* Allow read access to binaries even when mode 111 */
        if (err == -EACCES && S_ISREG(inode->i_mode) &&
            acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE))
-               err = permission(inode, MAY_EXEC, NULL);
+               err = inode_permission(inode, MAY_EXEC);
 
        return err? nfserrno(err) : 0;
 }
index 3c5550cd11d67b53a5d3ef6ff49dd6d4312f9d4c..d020866d42320dddd0ed6a8b9a9d31e572a42cab 100644 (file)
@@ -2118,7 +2118,7 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
                goto out;
        if (!count)
                goto out;
-       err = remove_suid(file->f_path.dentry);
+       err = file_remove_suid(file);
        if (err)
                goto out;
        file_update_time(file);
index 3e76f3b216bc2add33b2d3298f7bbe40233e3232..4a46743b5077a5e98e59d8f2b0205a4bc20e75a5 100644 (file)
@@ -3080,7 +3080,7 @@ struct kmem_cache *ntfs_inode_cache;
 struct kmem_cache *ntfs_big_inode_cache;
 
 /* Init once constructor for the inode slab cache. */
-static void ntfs_big_inode_init_once(struct kmem_cache *cachep, void *foo)
+static void ntfs_big_inode_init_once(void *foo)
 {
        ntfs_inode *ni = (ntfs_inode *)foo;
 
index e48aba698b775a895d32c87b254dc54fe5b2006f..533a789c3ef8e01872bb44e7a7d989c70e0e0f06 100644 (file)
@@ -267,8 +267,7 @@ static ssize_t dlmfs_file_write(struct file *filp,
        return writelen;
 }
 
-static void dlmfs_init_once(struct kmem_cache *cachep,
-                           void *foo)
+static void dlmfs_init_once(void *foo)
 {
        struct dlmfs_inode_private *ip =
                (struct dlmfs_inode_private *) foo;
index e8514e8b6ce8977eb3f75d3a64a7b8f33f96726a..be2dd95d3a1dc0c916229ad4deb643ed0ee841b0 100644 (file)
@@ -1176,7 +1176,7 @@ bail:
        return err;
 }
 
-int ocfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
+int ocfs2_permission(struct inode *inode, int mask)
 {
        int ret;
 
index 048ddcaf5c80e9b2bb76b1e06d3f6ddb340856c8..1e27b4d017ea49401ec43445a29d62bcd6b219ce 100644 (file)
@@ -62,8 +62,7 @@ int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
 int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
                  struct kstat *stat);
-int ocfs2_permission(struct inode *inode, int mask,
-                    struct nameidata *nd);
+int ocfs2_permission(struct inode *inode, int mask);
 
 int ocfs2_should_update_atime(struct inode *inode,
                              struct vfsmount *vfsmnt);
index ccecfe5094fa914407d5de8e8292b837a167784f..2560b33889aad8380b77f35ba4f21af7220459ac 100644 (file)
@@ -1118,7 +1118,7 @@ bail:
        return status;
 }
 
-static void ocfs2_inode_init_once(struct kmem_cache *cachep, void *data)
+static void ocfs2_inode_init_once(void *data)
 {
        struct ocfs2_inode_info *oi = data;
 
diff --git a/fs/omfs/Makefile b/fs/omfs/Makefile
new file mode 100644 (file)
index 0000000..8b82b63
--- /dev/null
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_OMFS_FS) += omfs.o
+
+omfs-y := bitmap.o dir.o file.o inode.o
diff --git a/fs/omfs/bitmap.c b/fs/omfs/bitmap.c
new file mode 100644 (file)
index 0000000..dc75f22
--- /dev/null
@@ -0,0 +1,192 @@
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <asm/div64.h>
+#include "omfs.h"
+
+unsigned long omfs_count_free(struct super_block *sb)
+{
+       unsigned int i;
+       unsigned long sum = 0;
+       struct omfs_sb_info *sbi = OMFS_SB(sb);
+       int nbits = sb->s_blocksize * 8;
+
+       for (i = 0; i < sbi->s_imap_size; i++)
+               sum += nbits - bitmap_weight(sbi->s_imap[i], nbits);
+
+       return sum;
+}
+
+/*
+ *  Counts the run of zero bits starting at bit up to max.
+ *  It handles the case where a run might spill over a buffer.
+ *  Called with bitmap lock.
+ */
+static int count_run(unsigned long **addr, int nbits,
+               int addrlen, int bit, int max)
+{
+       int count = 0;
+       int x;
+
+       for (; addrlen > 0; addrlen--, addr++) {
+               x = find_next_bit(*addr, nbits, bit);
+               count += x - bit;
+
+               if (x < nbits || count > max)
+                       return min(count, max);
+
+               bit = 0;
+       }
+       return min(count, max);
+}
+
+/*
+ * Sets or clears the run of count bits starting with bit.
+ * Called with bitmap lock.
+ */
+static int set_run(struct super_block *sb, int map,
+               int nbits, int bit, int count, int set)
+{
+       int i;
+       int err;
+       struct buffer_head *bh;
+       struct omfs_sb_info *sbi = OMFS_SB(sb);
+
+       err = -ENOMEM;
+       bh = sb_bread(sb, clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
+       if (!bh)
+               goto out;
+
+       for (i = 0; i < count; i++, bit++) {
+               if (bit >= nbits) {
+                       bit = 0;
+                       map++;
+
+                       mark_buffer_dirty(bh);
+                       brelse(bh);
+                       bh = sb_bread(sb,
+                               clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
+                       if (!bh)
+                               goto out;
+               }
+               if (set) {
+                       set_bit(bit, sbi->s_imap[map]);
+                       set_bit(bit, (long *) bh->b_data);
+               } else {
+                       clear_bit(bit, sbi->s_imap[map]);
+                       clear_bit(bit, (long *) bh->b_data);
+               }
+       }
+       mark_buffer_dirty(bh);
+       brelse(bh);
+       err = 0;
+out:
+       return err;
+}
+
+/*
+ * Tries to allocate exactly one block.  Returns true if sucessful.
+ */
+int omfs_allocate_block(struct super_block *sb, u64 block)
+{
+       struct buffer_head *bh;
+       struct omfs_sb_info *sbi = OMFS_SB(sb);
+       int bits_per_entry = 8 * sb->s_blocksize;
+       int map, bit;
+       int ret = 0;
+       u64 tmp;
+
+       tmp = block;
+       bit = do_div(tmp, bits_per_entry);
+       map = tmp;
+
+       mutex_lock(&sbi->s_bitmap_lock);
+       if (map >= sbi->s_imap_size || test_and_set_bit(bit, sbi->s_imap[map]))
+               goto out;
+
+       if (sbi->s_bitmap_ino > 0) {
+               bh = sb_bread(sb, clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
+               if (!bh)
+                       goto out;
+
+               set_bit(bit, (long *) bh->b_data);
+               mark_buffer_dirty(bh);
+               brelse(bh);
+       }
+       ret = 1;
+out:
+       mutex_unlock(&sbi->s_bitmap_lock);
+       return ret;
+}
+
+
+/*
+ *  Tries to allocate a set of blocks. The request size depends on the
+ *  type: for inodes, we must allocate sbi->s_mirrors blocks, and for file
+ *  blocks, we try to allocate sbi->s_clustersize, but can always get away
+ *  with just one block.
+ */
+int omfs_allocate_range(struct super_block *sb,
+                       int min_request,
+                       int max_request,
+                       u64 *return_block,
+                       int *return_size)
+{
+       struct omfs_sb_info *sbi = OMFS_SB(sb);
+       int bits_per_entry = 8 * sb->s_blocksize;
+       int ret = 0;
+       int i, run, bit;
+
+       mutex_lock(&sbi->s_bitmap_lock);
+       for (i = 0; i < sbi->s_imap_size; i++) {
+               bit = 0;
+               while (bit < bits_per_entry) {
+                       bit = find_next_zero_bit(sbi->s_imap[i], bits_per_entry,
+                               bit);
+
+                       if (bit == bits_per_entry)
+                               break;
+
+                       run = count_run(&sbi->s_imap[i], bits_per_entry,
+                               sbi->s_imap_size-i, bit, max_request);
+
+                       if (run >= min_request)
+                               goto found;
+                       bit += run;
+               }
+       }
+       ret = -ENOSPC;
+       goto out;
+
+found:
+       *return_block = i * bits_per_entry + bit;
+       *return_size = run;
+       ret = set_run(sb, i, bits_per_entry, bit, run, 1);
+
+out:
+       mutex_unlock(&sbi->s_bitmap_lock);
+       return ret;
+}
+
+/*
+ * Clears count bits starting at a given block.
+ */
+int omfs_clear_range(struct super_block *sb, u64 block, int count)
+{
+       struct omfs_sb_info *sbi = OMFS_SB(sb);
+       int bits_per_entry = 8 * sb->s_blocksize;
+       u64 tmp;
+       int map, bit, ret;
+
+       tmp = block;
+       bit = do_div(tmp, bits_per_entry);
+       map = tmp;
+
+       if (map >= sbi->s_imap_size)
+               return 0;
+
+       mutex_lock(&sbi->s_bitmap_lock);
+       ret = set_run(sb, map, bits_per_entry, bit, count, 0);
+       mutex_unlock(&sbi->s_bitmap_lock);
+       return ret;
+}
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c
new file mode 100644 (file)
index 0000000..05a5bc3
--- /dev/null
@@ -0,0 +1,504 @@
+/*
+ * OMFS (as used by RIO Karma) directory operations.
+ * Copyright (C) 2005 Bob Copeland <me@bobcopeland.com>
+ * Released under GPL v2.
+ */
+
+#include <linux/fs.h>
+#include <linux/ctype.h>
+#include <linux/buffer_head.h>
+#include "omfs.h"
+
+static int omfs_hash(const char *name, int namelen, int mod)
+{
+       int i, hash = 0;
+       for (i = 0; i < namelen; i++)
+               hash ^= tolower(name[i]) << (i % 24);
+       return hash % mod;
+}
+
+/*
+ * Finds the bucket for a given name and reads the containing block;
+ * *ofs is set to the offset of the first list entry.
+ */
+static struct buffer_head *omfs_get_bucket(struct inode *dir,
+               const char *name, int namelen, int *ofs)
+{
+       int nbuckets = (dir->i_size - OMFS_DIR_START)/8;
+       int block = clus_to_blk(OMFS_SB(dir->i_sb), dir->i_ino);
+       int bucket = omfs_hash(name, namelen, nbuckets);
+
+       *ofs = OMFS_DIR_START + bucket * 8;
+       return sb_bread(dir->i_sb, block);
+}
+
+static struct buffer_head *omfs_scan_list(struct inode *dir, u64 block,
+                               const char *name, int namelen,
+                               u64 *prev_block)
+{
+       struct buffer_head *bh;
+       struct omfs_inode *oi;
+       int err = -ENOENT;
+       *prev_block = ~0;
+
+       while (block != ~0) {
+               bh = sb_bread(dir->i_sb,
+                       clus_to_blk(OMFS_SB(dir->i_sb), block));
+               if (!bh) {
+                       err = -EIO;
+                       goto err;
+               }
+
+               oi = (struct omfs_inode *) bh->b_data;
+               if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, block)) {
+                       brelse(bh);
+                       goto err;
+               }
+
+               if (strncmp(oi->i_name, name, namelen) == 0)
+                       return bh;
+
+               *prev_block = block;
+               block = be64_to_cpu(oi->i_sibling);
+               brelse(bh);
+       }
+err:
+       return ERR_PTR(err);
+}
+
+static struct buffer_head *omfs_find_entry(struct inode *dir,
+                                          const char *name, int namelen)
+{
+       struct buffer_head *bh;
+       int ofs;
+       u64 block, dummy;
+
+       bh = omfs_get_bucket(dir, name, namelen, &ofs);
+       if (!bh)
+               return ERR_PTR(-EIO);
+
+       block = be64_to_cpu(*((__be64 *) &bh->b_data[ofs]));
+       brelse(bh);
+
+       return omfs_scan_list(dir, block, name, namelen, &dummy);
+}
+
+int omfs_make_empty(struct inode *inode, struct super_block *sb)
+{
+       struct omfs_sb_info *sbi = OMFS_SB(sb);
+       int block = clus_to_blk(sbi, inode->i_ino);
+       struct buffer_head *bh;
+       struct omfs_inode *oi;
+
+       bh = sb_bread(sb, block);
+       if (!bh)
+               return -ENOMEM;
+
+       memset(bh->b_data, 0, sizeof(struct omfs_inode));
+
+       if (inode->i_mode & S_IFDIR) {
+               memset(&bh->b_data[OMFS_DIR_START], 0xff,
+                       sbi->s_sys_blocksize - OMFS_DIR_START);
+       } else
+               omfs_make_empty_table(bh, OMFS_EXTENT_START);
+
+       oi = (struct omfs_inode *) bh->b_data;
+       oi->i_head.h_self = cpu_to_be64(inode->i_ino);
+       oi->i_sibling = ~0ULL;
+
+       mark_buffer_dirty(bh);
+       brelse(bh);
+       return 0;
+}
+
+static int omfs_add_link(struct dentry *dentry, struct inode *inode)
+{
+       struct inode *dir = dentry->d_parent->d_inode;
+       const char *name = dentry->d_name.name;
+       int namelen = dentry->d_name.len;
+       struct omfs_inode *oi;
+       struct buffer_head *bh;
+       u64 block;
+       __be64 *entry;
+       int ofs;
+
+       /* just prepend to head of queue in proper bucket */
+       bh = omfs_get_bucket(dir, name, namelen, &ofs);
+       if (!bh)
+               goto out;
+
+       entry = (__be64 *) &bh->b_data[ofs];
+       block = be64_to_cpu(*entry);
+       *entry = cpu_to_be64(inode->i_ino);
+       mark_buffer_dirty(bh);
+       brelse(bh);
+
+       /* now set the sibling and parent pointers on the new inode */
+       bh = sb_bread(dir->i_sb, clus_to_blk(OMFS_SB(dir->i_sb), inode->i_ino));
+       if (!bh)
+               goto out;
+
+       oi = (struct omfs_inode *) bh->b_data;
+       memcpy(oi->i_name, name, namelen);
+       memset(oi->i_name + namelen, 0, OMFS_NAMELEN - namelen);
+       oi->i_sibling = cpu_to_be64(block);
+       oi->i_parent = cpu_to_be64(dir->i_ino);
+       mark_buffer_dirty(bh);
+       brelse(bh);
+
+       dir->i_ctime = CURRENT_TIME_SEC;
+
+       /* mark affected inodes dirty to rebuild checksums */
+       mark_inode_dirty(dir);
+       mark_inode_dirty(inode);
+       return 0;
+out:
+       return -ENOMEM;
+}
+
+static int omfs_delete_entry(struct dentry *dentry)
+{
+       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dirty;
+       const char *name = dentry->d_name.name;
+       int namelen = dentry->d_name.len;
+       struct omfs_inode *oi;
+       struct buffer_head *bh, *bh2;
+       __be64 *entry, next;
+       u64 block, prev;
+       int ofs;
+       int err = -ENOMEM;
+
+       /* delete the proper node in the bucket's linked list */
+       bh = omfs_get_bucket(dir, name, namelen, &ofs);
+       if (!bh)
+               goto out;
+
+       entry = (__be64 *) &bh->b_data[ofs];
+       block = be64_to_cpu(*entry);
+
+       bh2 = omfs_scan_list(dir, block, name, namelen, &prev);
+       if (IS_ERR(bh2)) {
+               err = PTR_ERR(bh2);
+               goto out_free_bh;
+       }
+
+       oi = (struct omfs_inode *) bh2->b_data;
+       next = oi->i_sibling;
+       brelse(bh2);
+
+       if (prev != ~0) {
+               /* found in middle of list, get list ptr */
+               brelse(bh);
+               bh = sb_bread(dir->i_sb,
+                       clus_to_blk(OMFS_SB(dir->i_sb), prev));
+               if (!bh)
+                       goto out;
+
+               oi = (struct omfs_inode *) bh->b_data;
+               entry = &oi->i_sibling;
+       }
+
+       *entry = next;
+       mark_buffer_dirty(bh);
+
+       if (prev != ~0) {
+               dirty = omfs_iget(dir->i_sb, prev);
+               if (!IS_ERR(dirty)) {
+                       mark_inode_dirty(dirty);
+                       iput(dirty);
+               }
+       }
+
+       err = 0;
+out_free_bh:
+       brelse(bh);
+out:
+       return err;
+}
+
+static int omfs_dir_is_empty(struct inode *inode)
+{
+       int nbuckets = (inode->i_size - OMFS_DIR_START) / 8;
+       struct buffer_head *bh;
+       u64 *ptr;
+       int i;
+
+       bh = sb_bread(inode->i_sb, clus_to_blk(OMFS_SB(inode->i_sb),
+                       inode->i_ino));
+
+       if (!bh)
+               return 0;
+
+       ptr = (u64 *) &bh->b_data[OMFS_DIR_START];
+
+       for (i = 0; i < nbuckets; i++, ptr++)
+               if (*ptr != ~0)
+                       break;
+
+       brelse(bh);
+       return *ptr != ~0;
+}
+
+static int omfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+       int ret;
+       struct inode *inode = dentry->d_inode;
+
+       ret = omfs_delete_entry(dentry);
+       if (ret)
+               goto end_unlink;
+
+       inode_dec_link_count(inode);
+       mark_inode_dirty(dir);
+
+end_unlink:
+       return ret;
+}
+
+static int omfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+       int err = -ENOTEMPTY;
+       struct inode *inode = dentry->d_inode;
+
+       if (omfs_dir_is_empty(inode)) {
+               err = omfs_unlink(dir, dentry);
+               if (!err)
+                       inode_dec_link_count(inode);
+       }
+       return err;
+}
+
+static int omfs_add_node(struct inode *dir, struct dentry *dentry, int mode)
+{
+       int err;
+       struct inode *inode = omfs_new_inode(dir, mode);
+
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
+
+       err = omfs_make_empty(inode, dir->i_sb);
+       if (err)
+               goto out_free_inode;
+
+       err = omfs_add_link(dentry, inode);
+       if (err)
+               goto out_free_inode;
+
+       d_instantiate(dentry, inode);
+       return 0;
+
+out_free_inode:
+       iput(inode);
+       return err;
+}
+
+static int omfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+       return omfs_add_node(dir, dentry, mode | S_IFDIR);
+}
+
+static int omfs_create(struct inode *dir, struct dentry *dentry, int mode,
+               struct nameidata *nd)
+{
+       return omfs_add_node(dir, dentry, mode | S_IFREG);
+}
+
+static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry,
+                                 struct nameidata *nd)
+{
+       struct buffer_head *bh;
+       struct inode *inode = NULL;
+
+       if (dentry->d_name.len > OMFS_NAMELEN)
+               return ERR_PTR(-ENAMETOOLONG);
+
+       bh = omfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
+       if (!IS_ERR(bh)) {
+               struct omfs_inode *oi = (struct omfs_inode *)bh->b_data;
+               ino_t ino = be64_to_cpu(oi->i_head.h_self);
+               brelse(bh);
+               inode = omfs_iget(dir->i_sb, ino);
+               if (IS_ERR(inode))
+                       return ERR_CAST(inode);
+       }
+       d_add(dentry, inode);
+       return NULL;
+}
+
+/* sanity check block's self pointer */
+int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header,
+       u64 fsblock)
+{
+       int is_bad;
+       u64 ino = be64_to_cpu(header->h_self);
+       is_bad = ((ino != fsblock) || (ino < sbi->s_root_ino) ||
+               (ino > sbi->s_num_blocks));
+
+       if (is_bad)
+               printk(KERN_WARNING "omfs: bad hash chain detected\n");
+
+       return is_bad;
+}
+
+static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir,
+               u64 fsblock, int hindex)
+{
+       struct inode *dir = filp->f_dentry->d_inode;
+       struct buffer_head *bh;
+       struct omfs_inode *oi;
+       u64 self;
+       int res = 0;
+       unsigned char d_type;
+
+       /* follow chain in this bucket */
+       while (fsblock != ~0) {
+               bh = sb_bread(dir->i_sb, clus_to_blk(OMFS_SB(dir->i_sb),
+                               fsblock));
+               if (!bh)
+                       goto out;
+
+               oi = (struct omfs_inode *) bh->b_data;
+               if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) {
+                       brelse(bh);
+                       goto out;
+               }
+
+               self = fsblock;
+               fsblock = be64_to_cpu(oi->i_sibling);
+
+               /* skip visited nodes */
+               if (hindex) {
+                       hindex--;
+                       brelse(bh);
+                       continue;
+               }
+
+               d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG;
+
+               res = filldir(dirent, oi->i_name, strnlen(oi->i_name,
+                       OMFS_NAMELEN), filp->f_pos, self, d_type);
+               if (res == 0)
+                       filp->f_pos++;
+               brelse(bh);
+       }
+out:
+       return res;
+}
+
+static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+               struct inode *new_dir, struct dentry *new_dentry)
+{
+       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = old_dentry->d_inode;
+       struct buffer_head *bh;
+       int is_dir;
+       int err;
+
+       is_dir = S_ISDIR(old_inode->i_mode);
+
+       if (new_inode) {
+               /* overwriting existing file/dir */
+               err = -ENOTEMPTY;
+               if (is_dir && !omfs_dir_is_empty(new_inode))
+                       goto out;
+
+               err = -ENOENT;
+               bh = omfs_find_entry(new_dir, new_dentry->d_name.name,
+                       new_dentry->d_name.len);
+               if (IS_ERR(bh))
+                       goto out;
+               brelse(bh);
+
+               err = omfs_unlink(new_dir, new_dentry);
+               if (err)
+                       goto out;
+       }
+
+       /* since omfs locates files by name, we need to unlink _before_
+        * adding the new link or we won't find the old one */
+       inode_inc_link_count(old_inode);
+       err = omfs_unlink(old_dir, old_dentry);
+       if (err) {
+               inode_dec_link_count(old_inode);
+               goto out;
+       }
+
+       err = omfs_add_link(new_dentry, old_inode);
+       if (err)
+               goto out;
+
+       old_inode->i_ctime = CURRENT_TIME_SEC;
+out:
+       return err;
+}
+
+static int omfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+       struct inode *dir = filp->f_dentry->d_inode;
+       struct buffer_head *bh;
+       loff_t offset, res;
+       unsigned int hchain, hindex;
+       int nbuckets;
+       u64 fsblock;
+       int ret = -EINVAL;
+
+       if (filp->f_pos >> 32)
+               goto success;
+
+       switch ((unsigned long) filp->f_pos) {
+       case 0:
+               if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
+                       goto success;
+               filp->f_pos++;
+               /* fall through */
+       case 1:
+               if (filldir(dirent, "..", 2, 1,
+                   parent_ino(filp->f_dentry), DT_DIR) < 0)
+                       goto success;
+               filp->f_pos = 1 << 20;
+               /* fall through */
+       }
+
+       nbuckets = (dir->i_size - OMFS_DIR_START) / 8;
+
+       /* high 12 bits store bucket + 1 and low 20 bits store hash index */
+       hchain = (filp->f_pos >> 20) - 1;
+       hindex = filp->f_pos & 0xfffff;
+
+       bh = sb_bread(dir->i_sb, clus_to_blk(OMFS_SB(dir->i_sb), dir->i_ino));
+       if (!bh)
+               goto out;
+
+       offset = OMFS_DIR_START + hchain * 8;
+
+       for (; hchain < nbuckets; hchain++, offset += 8) {
+               fsblock = be64_to_cpu(*((__be64 *) &bh->b_data[offset]));
+
+               res = omfs_fill_chain(filp, dirent, filldir, fsblock, hindex);
+               hindex = 0;
+               if (res < 0)
+                       break;
+
+               filp->f_pos = (hchain+2) << 20;
+       }
+       brelse(bh);
+success:
+       ret = 0;
+out:
+       return ret;
+}
+
+struct inode_operations omfs_dir_inops = {
+       .lookup = omfs_lookup,
+       .mkdir = omfs_mkdir,
+       .rename = omfs_rename,
+       .create = omfs_create,
+       .unlink = omfs_unlink,
+       .rmdir = omfs_rmdir,
+};
+
+struct file_operations omfs_dir_operations = {
+       .read = generic_read_dir,
+       .readdir = omfs_readdir,
+};
diff --git a/fs/omfs/file.c b/fs/omfs/file.c
new file mode 100644 (file)
index 0000000..66e01fa
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * OMFS (as used by RIO Karma) file operations.
+ * Copyright (C) 2005 Bob Copeland <me@bobcopeland.com>
+ * Released under GPL v2.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/mpage.h>
+#include "omfs.h"
+
+static int omfs_sync_file(struct file *file, struct dentry *dentry,
+               int datasync)
+{
+       struct inode *inode = dentry->d_inode;
+       int err;
+
+       err = sync_mapping_buffers(inode->i_mapping);
+       if (!(inode->i_state & I_DIRTY))
+               return err;
+       if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+               return err;
+       err |= omfs_sync_inode(inode);
+       return err ? -EIO : 0;
+}
+
+void omfs_make_empty_table(struct buffer_head *bh, int offset)
+{
+       struct omfs_extent *oe = (struct omfs_extent *) &bh->b_data[offset];
+
+       oe->e_next = ~0ULL;
+       oe->e_extent_count = cpu_to_be32(1),
+       oe->e_fill = cpu_to_be32(0x22),
+       oe->e_entry.e_cluster = ~0ULL;
+       oe->e_entry.e_blocks = ~0ULL;
+}
+
+int omfs_shrink_inode(struct inode *inode)
+{
+       struct omfs_sb_info *sbi = OMFS_SB(inode->i_sb);
+       struct omfs_extent *oe;
+       struct omfs_extent_entry *entry;
+       struct buffer_head *bh;
+       u64 next, last;
+       u32 extent_count;
+       int ret;
+
+       /* traverse extent table, freeing each entry that is greater
+        * than inode->i_size;
+        */
+       next = inode->i_ino;
+
+       /* only support truncate -> 0 for now */
+       ret = -EIO;
+       if (inode->i_size != 0)
+               goto out;
+
+       bh = sb_bread(inode->i_sb, clus_to_blk(sbi, next));
+       if (!bh)
+               goto out;
+
+       oe = (struct omfs_extent *)(&bh->b_data[OMFS_EXTENT_START]);
+
+       for (;;) {
+
+               if (omfs_is_bad(sbi, (struct omfs_header *) bh->b_data, next)) {
+                       brelse(bh);
+                       goto out;
+               }
+
+               extent_count = be32_to_cpu(oe->e_extent_count);
+               last = next;
+               next = be64_to_cpu(oe->e_next);
+               entry = &oe->e_entry;
+
+               /* ignore last entry as it is the terminator */
+               for (; extent_count > 1; extent_count--) {
+                       u64 start, count;
+                       start = be64_to_cpu(entry->e_cluster);
+                       count = be64_to_cpu(entry->e_blocks);
+
+                       omfs_clear_range(inode->i_sb, start, (int) count);
+                       entry++;
+               }
+               omfs_make_empty_table(bh, (char *) oe - bh->b_data);
+               mark_buffer_dirty(bh);
+               brelse(bh);
+
+               if (last != inode->i_ino)
+                       omfs_clear_range(inode->i_sb, last, sbi->s_mirrors);
+
+               if (next == ~0)
+                       break;
+
+               bh = sb_bread(inode->i_sb, clus_to_blk(sbi, next));
+               if (!bh)
+                       goto out;
+               oe = (struct omfs_extent *) (&bh->b_data[OMFS_EXTENT_CONT]);
+       }
+       ret = 0;
+out:
+       return ret;
+}
+
+static void omfs_truncate(struct inode *inode)
+{
+       omfs_shrink_inode(inode);
+       mark_inode_dirty(inode);
+}
+
+/*
+ * Add new blocks to the current extent, or create new entries/continuations
+ * as necessary.
+ */
+static int omfs_grow_extent(struct inode *inode, struct omfs_extent *oe,
+                       u64 *ret_block)
+{
+       struct omfs_extent_entry *terminator;
+       struct omfs_extent_entry *entry = &oe->e_entry;
+       struct omfs_sb_info *sbi = OMFS_SB(inode->i_sb);
+       u32 extent_count = be32_to_cpu(oe->e_extent_count);
+       u64 new_block = 0;
+       u32 max_count;
+       int new_count;
+       int ret = 0;
+
+       /* reached the end of the extent table with no blocks mapped.
+        * there are three possibilities for adding: grow last extent,
+        * add a new extent to the current extent table, and add a
+        * continuation inode.  in last two cases need an allocator for
+        * sbi->s_cluster_size
+        */
+
+       /* TODO: handle holes */
+
+       /* should always have a terminator */
+       if (extent_count < 1)
+               return -EIO;
+
+       /* trivially grow current extent, if next block is not taken */
+       terminator = entry + extent_count - 1;
+       if (extent_count > 1) {
+               entry = terminator-1;
+               new_block = be64_to_cpu(entry->e_cluster) +
+                       be64_to_cpu(entry->e_blocks);
+
+               if (omfs_allocate_block(inode->i_sb, new_block)) {
+                       entry->e_blocks =
+                               cpu_to_be64(be64_to_cpu(entry->e_blocks) + 1);
+                       terminator->e_blocks = ~(cpu_to_be64(
+                               be64_to_cpu(~terminator->e_blocks) + 1));
+                       goto out;
+               }
+       }
+       max_count = (sbi->s_sys_blocksize - OMFS_EXTENT_START -
+               sizeof(struct omfs_extent)) /
+               sizeof(struct omfs_extent_entry) + 1;
+
+       /* TODO: add a continuation block here */
+       if (be32_to_cpu(oe->e_extent_count) > max_count-1)
+               return -EIO;
+
+       /* try to allocate a new cluster */
+       ret = omfs_allocate_range(inode->i_sb, 1, sbi->s_clustersize,
+               &new_block, &new_count);
+       if (ret)
+               goto out_fail;
+
+       /* copy terminator down an entry */
+       entry = terminator;
+       terminator++;
+       memcpy(terminator, entry, sizeof(struct omfs_extent_entry));
+
+       entry->e_cluster = cpu_to_be64(new_block);
+       entry->e_blocks = cpu_to_be64((u64) new_count);
+
+       terminator->e_blocks = ~(cpu_to_be64(
+               be64_to_cpu(~terminator->e_blocks) + (u64) new_count));
+
+       /* write in new entry */
+       oe->e_extent_count = cpu_to_be32(1 + be32_to_cpu(oe->e_extent_count));
+
+out:
+       *ret_block = new_block;
+out_fail:
+       return ret;
+}
+
+/*
+ * Scans across the directory table for a given file block number.
+ * If block not found, return 0.
+ */
+static sector_t find_block(struct inode *inode, struct omfs_extent_entry *ent,
+                       sector_t block, int count, int *left)
+{
+       /* count > 1 because of terminator */
+       sector_t searched = 0;
+       for (; count > 1; count--) {
+               int numblocks = clus_to_blk(OMFS_SB(inode->i_sb),
+                       be64_to_cpu(ent->e_blocks));
+
+               if (block >= searched  &&
+                   block < searched + numblocks) {
+                       /*
+                        * found it at cluster + (block - searched)
+                        * numblocks - (block - searched) is remainder
+                        */
+                       *left = numblocks - (block - searched);
+                       return clus_to_blk(OMFS_SB(inode->i_sb),
+                               be64_to_cpu(ent->e_cluster)) +
+                               block - searched;
+               }
+               searched += numblocks;
+               ent++;
+       }
+       return 0;
+}
+
+static int omfs_get_block(struct inode *inode, sector_t block,
+                         struct buffer_head *bh_result, int create)
+{
+       struct buffer_head *bh;
+       sector_t next, offset;
+       int ret;
+       u64 new_block;
+       int extent_count;
+       struct omfs_extent *oe;
+       struct omfs_extent_entry *entry;
+       struct omfs_sb_info *sbi = OMFS_SB(inode->i_sb);
+       int max_blocks = bh_result->b_size >> inode->i_blkbits;
+       int remain;
+
+       ret = -EIO;
+       bh = sb_bread(inode->i_sb, clus_to_blk(sbi, inode->i_ino));
+       if (!bh)
+               goto out;
+
+       oe = (struct omfs_extent *)(&bh->b_data[OMFS_EXTENT_START]);
+       next = inode->i_ino;
+
+       for (;;) {
+
+               if (omfs_is_bad(sbi, (struct omfs_header *) bh->b_data, next))
+                       goto out_brelse;
+
+               extent_count = be32_to_cpu(oe->e_extent_count);
+               next = be64_to_cpu(oe->e_next);
+               entry = &oe->e_entry;
+
+               offset = find_block(inode, entry, block, extent_count, &remain);
+               if (offset > 0) {
+                       ret = 0;
+                       map_bh(bh_result, inode->i_sb, offset);
+                       if (remain > max_blocks)
+                               remain = max_blocks;
+                       bh_result->b_size = (remain << inode->i_blkbits);
+                       goto out_brelse;
+               }
+               if (next == ~0)
+                       break;
+
+               brelse(bh);
+               bh = sb_bread(inode->i_sb, clus_to_blk(sbi, next));
+               if (!bh)
+                       goto out;
+               oe = (struct omfs_extent *) (&bh->b_data[OMFS_EXTENT_CONT]);
+       }
+       if (create) {
+               ret = omfs_grow_extent(inode, oe, &new_block);
+               if (ret == 0) {
+                       mark_buffer_dirty(bh);
+                       mark_inode_dirty(inode);
+                       map_bh(bh_result, inode->i_sb,
+                                       clus_to_blk(sbi, new_block));
+               }
+       }
+out_brelse:
+       brelse(bh);
+out:
+       return ret;
+}
+
+static int omfs_readpage(struct file *file, struct page *page)
+{
+       return block_read_full_page(page, omfs_get_block);
+}
+
+static int omfs_readpages(struct file *file, struct address_space *mapping,
+               struct list_head *pages, unsigned nr_pages)
+{
+       return mpage_readpages(mapping, pages, nr_pages, omfs_get_block);
+}
+
+static int omfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+       return block_write_full_page(page, omfs_get_block, wbc);
+}
+
+static int
+omfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
+{
+       return mpage_writepages(mapping, wbc, omfs_get_block);
+}
+
+static int omfs_write_begin(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned flags,
+                       struct page **pagep, void **fsdata)
+{
+       *pagep = NULL;
+       return block_write_begin(file, mapping, pos, len, flags,
+                               pagep, fsdata, omfs_get_block);
+}
+
+static sector_t omfs_bmap(struct address_space *mapping, sector_t block)
+{
+       return generic_block_bmap(mapping, block, omfs_get_block);
+}
+
+struct file_operations omfs_file_operations = {
+       .llseek = generic_file_llseek,
+       .read = do_sync_read,
+       .write = do_sync_write,
+       .aio_read = generic_file_aio_read,
+       .aio_write = generic_file_aio_write,
+       .mmap = generic_file_mmap,
+       .fsync = omfs_sync_file,
+       .splice_read = generic_file_splice_read,
+};
+
+struct inode_operations omfs_file_inops = {
+       .truncate = omfs_truncate
+};
+
+struct address_space_operations omfs_aops = {
+       .readpage = omfs_readpage,
+       .readpages = omfs_readpages,
+       .writepage = omfs_writepage,
+       .writepages = omfs_writepages,
+       .sync_page = block_sync_page,
+       .write_begin = omfs_write_begin,
+       .write_end = generic_write_end,
+       .bmap = omfs_bmap,
+};
+
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
new file mode 100644 (file)
index 0000000..d865f55
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * Optimized MPEG FS - inode and super operations.
+ * Copyright (C) 2006 Bob Copeland <me@bobcopeland.com>
+ * Released under GPL v2.
+ */
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/vfs.h>
+#include <linux/parser.h>
+#include <linux/buffer_head.h>
+#include <linux/vmalloc.h>
+#include <linux/crc-itu-t.h>
+#include "omfs.h"
+
+MODULE_AUTHOR("Bob Copeland <me@bobcopeland.com>");
+MODULE_DESCRIPTION("OMFS (ReplayTV/Karma) Filesystem for Linux");
+MODULE_LICENSE("GPL");
+
+struct inode *omfs_new_inode(struct inode *dir, int mode)
+{
+       struct inode *inode;
+       u64 new_block;
+       int err;
+       int len;
+       struct omfs_sb_info *sbi = OMFS_SB(dir->i_sb);
+
+       inode = new_inode(dir->i_sb);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+
+       err = omfs_allocate_range(dir->i_sb, sbi->s_mirrors, sbi->s_mirrors,
+                       &new_block, &len);
+       if (err)
+               goto fail;
+
+       inode->i_ino = new_block;
+       inode->i_mode = mode;
+       inode->i_uid = current->fsuid;
+       inode->i_gid = current->fsgid;
+       inode->i_blocks = 0;
+       inode->i_mapping->a_ops = &omfs_aops;
+
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       switch (mode & S_IFMT) {
+       case S_IFDIR:
+               inode->i_op = &omfs_dir_inops;
+               inode->i_fop = &omfs_dir_operations;
+               inode->i_size = sbi->s_sys_blocksize;
+               inc_nlink(inode);
+               break;
+       case S_IFREG:
+               inode->i_op = &omfs_file_inops;
+               inode->i_fop = &omfs_file_operations;
+               inode->i_size = 0;
+               break;
+       }
+
+       insert_inode_hash(inode);
+       mark_inode_dirty(inode);
+       return inode;
+fail:
+       make_bad_inode(inode);
+       iput(inode);
+       return ERR_PTR(err);
+}
+
+/*
+ * Update the header checksums for a dirty inode based on its contents.
+ * Caller is expected to hold the buffer head underlying oi and mark it
+ * dirty.
+ */
+static void omfs_update_checksums(struct omfs_inode *oi)
+{
+       int xor, i, ofs = 0, count;
+       u16 crc = 0;
+       unsigned char *ptr = (unsigned char *) oi;
+
+       count = be32_to_cpu(oi->i_head.h_body_size);
+       ofs = sizeof(struct omfs_header);
+
+       crc = crc_itu_t(crc, ptr + ofs, count);
+       oi->i_head.h_crc = cpu_to_be16(crc);
+
+       xor = ptr[0];
+       for (i = 1; i < OMFS_XOR_COUNT; i++)
+               xor ^= ptr[i];
+
+       oi->i_head.h_check_xor = xor;
+}
+
+static int omfs_write_inode(struct inode *inode, int wait)
+{
+       struct omfs_inode *oi;
+       struct omfs_sb_info *sbi = OMFS_SB(inode->i_sb);
+       struct buffer_head *bh, *bh2;
+       unsigned int block;
+       u64 ctime;
+       int i;
+       int ret = -EIO;
+       int sync_failed = 0;
+
+       /* get current inode since we may have written sibling ptrs etc. */
+       block = clus_to_blk(sbi, inode->i_ino);
+       bh = sb_bread(inode->i_sb, block);
+       if (!bh)
+               goto out;
+
+       oi = (struct omfs_inode *) bh->b_data;
+
+       oi->i_head.h_self = cpu_to_be64(inode->i_ino);
+       if (S_ISDIR(inode->i_mode))
+               oi->i_type = OMFS_DIR;
+       else if (S_ISREG(inode->i_mode))
+               oi->i_type = OMFS_FILE;
+       else {
+               printk(KERN_WARNING "omfs: unknown file type: %d\n",
+                       inode->i_mode);
+               goto out_brelse;
+       }
+
+       oi->i_head.h_body_size = cpu_to_be32(sbi->s_sys_blocksize -
+               sizeof(struct omfs_header));
+       oi->i_head.h_version = 1;
+       oi->i_head.h_type = OMFS_INODE_NORMAL;
+       oi->i_head.h_magic = OMFS_IMAGIC;
+       oi->i_size = cpu_to_be64(inode->i_size);
+
+       ctime = inode->i_ctime.tv_sec * 1000LL +
+               ((inode->i_ctime.tv_nsec + 999)/1000);
+       oi->i_ctime = cpu_to_be64(ctime);
+
+       omfs_update_checksums(oi);
+
+       mark_buffer_dirty(bh);
+       if (wait) {
+               sync_dirty_buffer(bh);
+               if (buffer_req(bh) && !buffer_uptodate(bh))
+                       sync_failed = 1;
+       }
+
+       /* if mirroring writes, copy to next fsblock */
+       for (i = 1; i < sbi->s_mirrors; i++) {
+               bh2 = sb_bread(inode->i_sb, block + i *
+                       (sbi->s_blocksize / sbi->s_sys_blocksize));
+               if (!bh2)
+                       goto out_brelse;
+
+               memcpy(bh2->b_data, bh->b_data, bh->b_size);
+               mark_buffer_dirty(bh2);
+               if (wait) {
+                       sync_dirty_buffer(bh2);
+                       if (buffer_req(bh2) && !buffer_uptodate(bh2))
+                               sync_failed = 1;
+               }
+               brelse(bh2);
+       }
+       ret = (sync_failed) ? -EIO : 0;
+out_brelse:
+       brelse(bh);
+out:
+       return ret;
+}
+
+int omfs_sync_inode(struct inode *inode)
+{
+       return omfs_write_inode(inode, 1);
+}
+
+/*
+ * called when an entry is deleted, need to clear the bits in the
+ * bitmaps.
+ */
+static void omfs_delete_inode(struct inode *inode)
+{
+       truncate_inode_pages(&inode->i_data, 0);
+
+       if (S_ISREG(inode->i_mode)) {
+               inode->i_size = 0;
+               omfs_shrink_inode(inode);
+       }
+
+       omfs_clear_range(inode->i_sb, inode->i_ino, 2);
+       clear_inode(inode);
+}
+
+struct inode *omfs_iget(struct super_block *sb, ino_t ino)
+{
+       struct omfs_sb_info *sbi = OMFS_SB(sb);
+       struct omfs_inode *oi;
+       struct buffer_head *bh;
+       unsigned int block;
+       u64 ctime;
+       unsigned long nsecs;
+       struct inode *inode;
+
+       inode = iget_locked(sb, ino);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+       if (!(inode->i_state & I_NEW))
+               return inode;
+
+       block = clus_to_blk(sbi, ino);
+       bh = sb_bread(inode->i_sb, block);
+       if (!bh)
+               goto iget_failed;
+
+       oi = (struct omfs_inode *)bh->b_data;
+
+       /* check self */
+       if (ino != be64_to_cpu(oi->i_head.h_self))
+               goto fail_bh;
+
+       inode->i_uid = sbi->s_uid;
+       inode->i_gid = sbi->s_gid;
+
+       ctime = be64_to_cpu(oi->i_ctime);
+       nsecs = do_div(ctime, 1000) * 1000L;
+
+       inode->i_atime.tv_sec = ctime;
+       inode->i_mtime.tv_sec = ctime;
+       inode->i_ctime.tv_sec = ctime;
+       inode->i_atime.tv_nsec = nsecs;
+       inode->i_mtime.tv_nsec = nsecs;
+       inode->i_ctime.tv_nsec = nsecs;
+
+       inode->i_mapping->a_ops = &omfs_aops;
+
+       switch (oi->i_type) {
+       case OMFS_DIR:
+               inode->i_mode = S_IFDIR | (S_IRWXUGO & ~sbi->s_dmask);
+               inode->i_op = &omfs_dir_inops;
+               inode->i_fop = &omfs_dir_operations;
+               inode->i_size = be32_to_cpu(oi->i_head.h_body_size) +
+                       sizeof(struct omfs_header);
+               inc_nlink(inode);
+               break;
+       case OMFS_FILE:
+               inode->i_mode = S_IFREG | (S_IRWXUGO & ~sbi->s_fmask);
+               inode->i_fop = &omfs_file_operations;
+               inode->i_size = be64_to_cpu(oi->i_size);
+               break;
+       }
+       brelse(bh);
+       unlock_new_inode(inode);
+       return inode;
+fail_bh:
+       brelse(bh);
+iget_failed:
+       iget_failed(inode);
+       return ERR_PTR(-EIO);
+}
+
+static void omfs_put_super(struct super_block *sb)
+{
+       struct omfs_sb_info *sbi = OMFS_SB(sb);
+       kfree(sbi->s_imap);
+       kfree(sbi);
+       sb->s_fs_info = NULL;
+}
+
+static int omfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+       struct super_block *s = dentry->d_sb;
+       struct omfs_sb_info *sbi = OMFS_SB(s);
+       buf->f_type = OMFS_MAGIC;
+       buf->f_bsize = sbi->s_blocksize;
+       buf->f_blocks = sbi->s_num_blocks;
+       buf->f_files = sbi->s_num_blocks;
+       buf->f_namelen = OMFS_NAMELEN;
+
+       buf->f_bfree = buf->f_bavail = buf->f_ffree =
+               omfs_count_free(s);
+       return 0;
+}
+
+static struct super_operations omfs_sops = {
+       .write_inode    = omfs_write_inode,
+       .delete_inode   = omfs_delete_inode,
+       .put_super      = omfs_put_super,
+       .statfs         = omfs_statfs,
+       .show_options   = generic_show_options,
+};
+
+/*
+ * For Rio Karma, there is an on-disk free bitmap whose location is
+ * stored in the root block.  For ReplayTV, there is no such free bitmap
+ * so we have to walk the tree.  Both inodes and file data are allocated
+ * from the same map.  This array can be big (300k) so we allocate
+ * in units of the blocksize.
+ */
+static int omfs_get_imap(struct super_block *sb)
+{
+       int bitmap_size;
+       int array_size;
+       int count;
+       struct omfs_sb_info *sbi = OMFS_SB(sb);
+       struct buffer_head *bh;
+       unsigned long **ptr;
+       sector_t block;
+
+       bitmap_size = DIV_ROUND_UP(sbi->s_num_blocks, 8);
+       array_size = DIV_ROUND_UP(bitmap_size, sb->s_blocksize);
+
+       if (sbi->s_bitmap_ino == ~0ULL)
+               goto out;
+
+       sbi->s_imap_size = array_size;
+       sbi->s_imap = kzalloc(array_size * sizeof(unsigned long *), GFP_KERNEL);
+       if (!sbi->s_imap)
+               goto nomem;
+
+       block = clus_to_blk(sbi, sbi->s_bitmap_ino);
+       ptr = sbi->s_imap;
+       for (count = bitmap_size; count > 0; count -= sb->s_blocksize) {
+               bh = sb_bread(sb, block++);
+               if (!bh)
+                       goto nomem_free;
+               *ptr = kmalloc(sb->s_blocksize, GFP_KERNEL);
+               if (!*ptr) {
+                       brelse(bh);
+                       goto nomem_free;
+               }
+               memcpy(*ptr, bh->b_data, sb->s_blocksize);
+               if (count < sb->s_blocksize)
+                       memset((void *)*ptr + count, 0xff,
+                               sb->s_blocksize - count);
+               brelse(bh);
+               ptr++;
+       }
+out:
+       return 0;
+
+nomem_free:
+       for (count = 0; count < array_size; count++)
+               kfree(sbi->s_imap[count]);
+
+       kfree(sbi->s_imap);
+nomem:
+       sbi->s_imap = NULL;
+       sbi->s_imap_size = 0;
+       return -ENOMEM;
+}
+
+enum {
+       Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask
+};
+
+static match_table_t tokens = {
+       {Opt_uid, "uid=%u"},
+       {Opt_gid, "gid=%u"},
+       {Opt_umask, "umask=%o"},
+       {Opt_dmask, "dmask=%o"},
+       {Opt_fmask, "fmask=%o"},
+};
+
+static int parse_options(char *options, struct omfs_sb_info *sbi)
+{
+       char *p;
+       substring_t args[MAX_OPT_ARGS];
+       int option;
+
+       if (!options)
+               return 1;
+
+       while ((p = strsep(&options, ",")) != NULL) {
+               int token;
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case Opt_uid:
+                       if (match_int(&args[0], &option))
+                               return 0;
+                       sbi->s_uid = option;
+                       break;
+               case Opt_gid:
+                       if (match_int(&args[0], &option))
+                               return 0;
+                       sbi->s_gid = option;
+                       break;
+               case Opt_umask:
+                       if (match_octal(&args[0], &option))
+                               return 0;
+                       sbi->s_fmask = sbi->s_dmask = option;
+                       break;
+               case Opt_dmask:
+                       if (match_octal(&args[0], &option))
+                               return 0;
+                       sbi->s_dmask = option;
+                       break;
+               case Opt_fmask:
+                       if (match_octal(&args[0], &option))
+                               return 0;
+                       sbi->s_fmask = option;
+                       break;
+               default:
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+static int omfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+       struct buffer_head *bh, *bh2;
+       struct omfs_super_block *omfs_sb;
+       struct omfs_root_block *omfs_rb;
+       struct omfs_sb_info *sbi;
+       struct inode *root;
+       sector_t start;
+       int ret = -EINVAL;
+
+       save_mount_options(sb, (char *) data);
+
+       sbi = kzalloc(sizeof(struct omfs_sb_info), GFP_KERNEL);
+       if (!sbi)
+               return -ENOMEM;
+
+       sb->s_fs_info = sbi;
+
+       sbi->s_uid = current->uid;
+       sbi->s_gid = current->gid;
+       sbi->s_dmask = sbi->s_fmask = current->fs->umask;
+
+       if (!parse_options((char *) data, sbi))
+               goto end;
+
+       sb->s_maxbytes = 0xffffffff;
+
+       sb_set_blocksize(sb, 0x200);
+
+       bh = sb_bread(sb, 0);
+       if (!bh)
+               goto end;
+
+       omfs_sb = (struct omfs_super_block *)bh->b_data;
+
+       if (omfs_sb->s_magic != cpu_to_be32(OMFS_MAGIC)) {
+               if (!silent)
+                       printk(KERN_ERR "omfs: Invalid superblock (%x)\n",
+                                  omfs_sb->s_magic);
+               goto out_brelse_bh;
+       }
+       sb->s_magic = OMFS_MAGIC;
+
+       sbi->s_num_blocks = be64_to_cpu(omfs_sb->s_num_blocks);
+       sbi->s_blocksize = be32_to_cpu(omfs_sb->s_blocksize);
+       sbi->s_mirrors = be32_to_cpu(omfs_sb->s_mirrors);
+       sbi->s_root_ino = be64_to_cpu(omfs_sb->s_root_block);
+       sbi->s_sys_blocksize = be32_to_cpu(omfs_sb->s_sys_blocksize);
+       mutex_init(&sbi->s_bitmap_lock);
+
+       if (sbi->s_sys_blocksize > PAGE_SIZE) {
+               printk(KERN_ERR "omfs: sysblock size (%d) is out of range\n",
+                       sbi->s_sys_blocksize);
+               goto out_brelse_bh;
+       }
+
+       if (sbi->s_blocksize < sbi->s_sys_blocksize ||
+           sbi->s_blocksize > OMFS_MAX_BLOCK_SIZE) {
+               printk(KERN_ERR "omfs: block size (%d) is out of range\n",
+                       sbi->s_blocksize);
+               goto out_brelse_bh;
+       }
+
+       /*
+        * Use sys_blocksize as the fs block since it is smaller than a
+        * page while the fs blocksize can be larger.
+        */
+       sb_set_blocksize(sb, sbi->s_sys_blocksize);
+
+       /*
+        * ...and the difference goes into a shift.  sys_blocksize is always
+        * a power of two factor of blocksize.
+        */
+       sbi->s_block_shift = get_bitmask_order(sbi->s_blocksize) -
+               get_bitmask_order(sbi->s_sys_blocksize);
+
+       start = clus_to_blk(sbi, be64_to_cpu(omfs_sb->s_root_block));
+       bh2 = sb_bread(sb, start);
+       if (!bh2)
+               goto out_brelse_bh;
+
+       omfs_rb = (struct omfs_root_block *)bh2->b_data;
+
+       sbi->s_bitmap_ino = be64_to_cpu(omfs_rb->r_bitmap);
+       sbi->s_clustersize = be32_to_cpu(omfs_rb->r_clustersize);
+
+       if (sbi->s_num_blocks != be64_to_cpu(omfs_rb->r_num_blocks)) {
+               printk(KERN_ERR "omfs: block count discrepancy between "
+                       "super and root blocks (%llx, %llx)\n",
+                       sbi->s_num_blocks, be64_to_cpu(omfs_rb->r_num_blocks));
+               goto out_brelse_bh2;
+       }
+
+       ret = omfs_get_imap(sb);
+       if (ret)
+               goto out_brelse_bh2;
+
+       sb->s_op = &omfs_sops;
+
+       root = omfs_iget(sb, be64_to_cpu(omfs_rb->r_root_dir));
+       if (IS_ERR(root)) {
+               ret = PTR_ERR(root);
+               goto out_brelse_bh2;
+       }
+
+       sb->s_root = d_alloc_root(root);
+       if (!sb->s_root) {
+               iput(root);
+               goto out_brelse_bh2;
+       }
+       printk(KERN_DEBUG "omfs: Mounted volume %s\n", omfs_rb->r_name);
+
+       ret = 0;
+out_brelse_bh2:
+       brelse(bh2);
+out_brelse_bh:
+       brelse(bh);
+end:
+       return ret;
+}
+
+static int omfs_get_sb(struct file_system_type *fs_type,
+                       int flags, const char *dev_name,
+                       void *data, struct vfsmount *m)
+{
+       return get_sb_bdev(fs_type, flags, dev_name, data, omfs_fill_super, m);
+}
+
+static struct file_system_type omfs_fs_type = {
+       .owner = THIS_MODULE,
+       .name = "omfs",
+       .get_sb = omfs_get_sb,
+       .kill_sb = kill_block_super,
+       .fs_flags = FS_REQUIRES_DEV,
+};
+
+static int __init init_omfs_fs(void)
+{
+       return register_filesystem(&omfs_fs_type);
+}
+
+static void __exit exit_omfs_fs(void)
+{
+       unregister_filesystem(&omfs_fs_type);
+}
+
+module_init(init_omfs_fs);
+module_exit(exit_omfs_fs);
diff --git a/fs/omfs/omfs.h b/fs/omfs/omfs.h
new file mode 100644 (file)
index 0000000..2bc0f06
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _OMFS_H
+#define _OMFS_H
+
+#include <linux/module.h>
+#include <linux/fs.h>
+
+#include "omfs_fs.h"
+
+/* In-memory structures */
+struct omfs_sb_info {
+       u64 s_num_blocks;
+       u64 s_bitmap_ino;
+       u64 s_root_ino;
+       u32 s_blocksize;
+       u32 s_mirrors;
+       u32 s_sys_blocksize;
+       u32 s_clustersize;
+       int s_block_shift;
+       unsigned long **s_imap;
+       int s_imap_size;
+       struct mutex s_bitmap_lock;
+       int s_uid;
+       int s_gid;
+       int s_dmask;
+       int s_fmask;
+};
+
+/* convert a cluster number to a scaled block number */
+static inline sector_t clus_to_blk(struct omfs_sb_info *sbi, sector_t block)
+{
+       return block << sbi->s_block_shift;
+}
+
+static inline struct omfs_sb_info *OMFS_SB(struct super_block *sb)
+{
+       return sb->s_fs_info;
+}
+
+/* bitmap.c */
+extern unsigned long omfs_count_free(struct super_block *sb);
+extern int omfs_allocate_block(struct super_block *sb, u64 block);
+extern int omfs_allocate_range(struct super_block *sb, int min_request,
+                       int max_request, u64 *return_block, int *return_size);
+extern int omfs_clear_range(struct super_block *sb, u64 block, int count);
+
+/* dir.c */
+extern struct file_operations omfs_dir_operations;
+extern struct inode_operations omfs_dir_inops;
+extern int omfs_make_empty(struct inode *inode, struct super_block *sb);
+extern int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header,
+                       u64 fsblock);
+
+/* file.c */
+extern struct file_operations omfs_file_operations;
+extern struct inode_operations omfs_file_inops;
+extern struct address_space_operations omfs_aops;
+extern void omfs_make_empty_table(struct buffer_head *bh, int offset);
+extern int omfs_shrink_inode(struct inode *inode);
+
+/* inode.c */
+extern struct inode *omfs_iget(struct super_block *sb, ino_t inode);
+extern struct inode *omfs_new_inode(struct inode *dir, int mode);
+extern int omfs_reserve_block(struct super_block *sb, sector_t block);
+extern int omfs_find_empty_block(struct super_block *sb, int mode, ino_t *ino);
+extern int omfs_sync_inode(struct inode *inode);
+
+#endif
diff --git a/fs/omfs/omfs_fs.h b/fs/omfs/omfs_fs.h
new file mode 100644 (file)
index 0000000..12cca24
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef _OMFS_FS_H
+#define _OMFS_FS_H
+
+/* OMFS On-disk structures */
+
+#define OMFS_MAGIC 0xC2993D87
+#define OMFS_IMAGIC 0xD2
+
+#define OMFS_DIR 'D'
+#define OMFS_FILE 'F'
+#define OMFS_INODE_NORMAL 'e'
+#define OMFS_INODE_CONTINUATION 'c'
+#define OMFS_INODE_SYSTEM 's'
+#define OMFS_NAMELEN 256
+#define OMFS_DIR_START 0x1b8
+#define OMFS_EXTENT_START 0x1d0
+#define OMFS_EXTENT_CONT 0x40
+#define OMFS_XOR_COUNT 19
+#define OMFS_MAX_BLOCK_SIZE 8192
+
+struct omfs_super_block {
+       char s_fill1[256];
+       __be64 s_root_block;            /* block number of omfs_root_block */
+       __be64 s_num_blocks;            /* total number of FS blocks */
+       __be32 s_magic;                 /* OMFS_MAGIC */
+       __be32 s_blocksize;             /* size of a block */
+       __be32 s_mirrors;               /* # of mirrors of system blocks */
+       __be32 s_sys_blocksize;         /* size of non-data blocks */
+};
+
+struct omfs_header {
+       __be64 h_self;                  /* FS block where this is located */
+       __be32 h_body_size;             /* size of useful data after header */
+       __be16 h_crc;                   /* crc-ccitt of body_size bytes */
+       char h_fill1[2];
+       u8 h_version;                   /* version, always 1 */
+       char h_type;                    /* OMFS_INODE_X */
+       u8 h_magic;                     /* OMFS_IMAGIC */
+       u8 h_check_xor;                 /* XOR of header bytes before this */
+       __be32 h_fill2;
+};
+
+struct omfs_root_block {
+       struct omfs_header r_head;      /* header */
+       __be64 r_fill1;
+       __be64 r_num_blocks;            /* total number of FS blocks */
+       __be64 r_root_dir;              /* block # of root directory */
+       __be64 r_bitmap;                /* block # of free space bitmap */
+       __be32 r_blocksize;             /* size of a block */
+       __be32 r_clustersize;           /* size allocated for data blocks */
+       __be64 r_mirrors;               /* # of mirrors of system blocks */
+       char r_name[OMFS_NAMELEN];      /* partition label */
+};
+
+struct omfs_inode {
+       struct omfs_header i_head;      /* header */
+       __be64 i_parent;                /* parent containing this inode */
+       __be64 i_sibling;               /* next inode in hash bucket */
+       __be64 i_ctime;                 /* ctime, in milliseconds */
+       char i_fill1[35];
+       char i_type;                    /* OMFS_[DIR,FILE] */
+       __be32 i_fill2;
+       char i_fill3[64];
+       char i_name[OMFS_NAMELEN];      /* filename */
+       __be64 i_size;                  /* size of file, in bytes */
+};
+
+struct omfs_extent_entry {
+       __be64 e_cluster;               /* start location of a set of blocks */
+       __be64 e_blocks;                /* number of blocks after e_cluster */
+};
+
+struct omfs_extent {
+       __be64 e_next;                  /* next extent table location */
+       __be32 e_extent_count;          /* total # extents in this table */
+       __be32 e_fill;
+       struct omfs_extent_entry e_entry;       /* start of extent entries */
+};
+
+#endif
index a99ad09c3197a1f60e4332f86520183cffa50bbd..52647be277a2c6bbe7e6ba5a9e0603d07ad33c71 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -64,7 +64,8 @@ static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf)
                memcpy(buf, &st, sizeof(st));
        else {
                if (sizeof buf->f_blocks == 4) {
-                       if ((st.f_blocks | st.f_bfree | st.f_bavail) &
+                       if ((st.f_blocks | st.f_bfree | st.f_bavail |
+                            st.f_bsize | st.f_frsize) &
                            0xffffffff00000000ULL)
                                return -EOVERFLOW;
                        /*
@@ -121,37 +122,37 @@ static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
        return 0;
 }
 
-asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf)
+asmlinkage long sys_statfs(const char __user *pathname, struct statfs __user * buf)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (!error) {
                struct statfs tmp;
-               error = vfs_statfs_native(nd.path.dentry, &tmp);
+               error = vfs_statfs_native(path.dentry, &tmp);
                if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
                        error = -EFAULT;
-               path_put(&nd.path);
+               path_put(&path);
        }
        return error;
 }
 
 
-asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf)
+asmlinkage long sys_statfs64(const char __user *pathname, size_t sz, struct statfs64 __user *buf)
 {
-       struct nameidata nd;
+       struct path path;
        long error;
 
        if (sz != sizeof(*buf))
                return -EINVAL;
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (!error) {
                struct statfs64 tmp;
-               error = vfs_statfs64(nd.path.dentry, &tmp);
+               error = vfs_statfs64(path.dentry, &tmp);
                if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
                        error = -EFAULT;
-               path_put(&nd.path);
+               path_put(&path);
        }
        return error;
 }
@@ -222,20 +223,20 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
        return err;
 }
 
-static long do_sys_truncate(const char __user * path, loff_t length)
+static long do_sys_truncate(const char __user *pathname, loff_t length)
 {
-       struct nameidata nd;
-       struct inode * inode;
+       struct path path;
+       struct inode *inode;
        int error;
 
        error = -EINVAL;
        if (length < 0) /* sorry, but loff_t says... */
                goto out;
 
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (error)
                goto out;
-       inode = nd.path.dentry->d_inode;
+       inode = path.dentry->d_inode;
 
        /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
        error = -EISDIR;
@@ -246,16 +247,16 @@ static long do_sys_truncate(const char __user * path, loff_t length)
        if (!S_ISREG(inode->i_mode))
                goto dput_and_out;
 
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (error)
                goto dput_and_out;
 
-       error = vfs_permission(&nd, MAY_WRITE);
+       error = inode_permission(inode, MAY_WRITE);
        if (error)
                goto mnt_drop_write_and_out;
 
        error = -EPERM;
-       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+       if (IS_APPEND(inode))
                goto mnt_drop_write_and_out;
 
        error = get_write_access(inode);
@@ -273,15 +274,15 @@ static long do_sys_truncate(const char __user * path, loff_t length)
        error = locks_verify_truncate(inode, NULL, length);
        if (!error) {
                DQUOT_INIT(inode);
-               error = do_truncate(nd.path.dentry, length, 0, NULL);
+               error = do_truncate(path.dentry, length, 0, NULL);
        }
 
 put_write_and_out:
        put_write_access(inode);
 mnt_drop_write_and_out:
-       mnt_drop_write(nd.path.mnt);
+       mnt_drop_write(path.mnt);
 dput_and_out:
-       path_put(&nd.path);
+       path_put(&path);
 out:
        return error;
 }
@@ -424,7 +425,8 @@ out:
  */
 asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 {
-       struct nameidata nd;
+       struct path path;
+       struct inode *inode;
        int old_fsuid, old_fsgid;
        kernel_cap_t uninitialized_var(old_cap);  /* !SECURE_NO_SETUID_FIXUP */
        int res;
@@ -447,7 +449,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
                 * FIXME: There is a race here against sys_capset.  The
                 * capabilities can change yet we will restore the old
                 * value below.  We should hold task_capabilities_lock,
-                * but we cannot because user_path_walk can sleep.
+                * but we cannot because user_path_at can sleep.
                 */
 #endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */
                if (current->uid)
@@ -456,14 +458,25 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
                        old_cap = cap_set_effective(current->cap_permitted);
        }
 
-       res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
+       res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
        if (res)
                goto out;
 
-       res = vfs_permission(&nd, mode);
+       inode = path.dentry->d_inode;
+
+       if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
+               /*
+                * MAY_EXEC on regular files is denied if the fs is mounted
+                * with the "noexec" flag.
+                */
+               res = -EACCES;
+               if (path.mnt->mnt_flags & MNT_NOEXEC)
+                       goto out_path_release;
+       }
+
+       res = inode_permission(inode, mode | MAY_ACCESS);
        /* SuS v2 requires we report a read only fs too */
-       if(res || !(mode & S_IWOTH) ||
-          special_file(nd.path.dentry->d_inode->i_mode))
+       if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
                goto out_path_release;
        /*
         * This is a rare case where using __mnt_is_readonly()
@@ -475,11 +488,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
         * inherently racy and know that the fs may change
         * state before we even see this result.
         */
-       if (__mnt_is_readonly(nd.path.mnt))
+       if (__mnt_is_readonly(path.mnt))
                res = -EROFS;
 
 out_path_release:
-       path_put(&nd.path);
+       path_put(&path);
 out:
        current->fsuid = old_fsuid;
        current->fsgid = old_fsgid;
@@ -497,22 +510,21 @@ asmlinkage long sys_access(const char __user *filename, int mode)
 
 asmlinkage long sys_chdir(const char __user * filename)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = __user_walk(filename,
-                           LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd);
+       error = user_path_dir(filename, &path);
        if (error)
                goto out;
 
-       error = vfs_permission(&nd, MAY_EXEC);
+       error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
        if (error)
                goto dput_and_out;
 
-       set_fs_pwd(current->fs, &nd.path);
+       set_fs_pwd(current->fs, &path);
 
 dput_and_out:
-       path_put(&nd.path);
+       path_put(&path);
 out:
        return error;
 }
@@ -534,7 +546,7 @@ asmlinkage long sys_fchdir(unsigned int fd)
        if (!S_ISDIR(inode->i_mode))
                goto out_putf;
 
-       error = file_permission(file, MAY_EXEC);
+       error = inode_permission(inode, MAY_EXEC | MAY_ACCESS);
        if (!error)
                set_fs_pwd(current->fs, &file->f_path);
 out_putf:
@@ -545,14 +557,14 @@ out:
 
 asmlinkage long sys_chroot(const char __user * filename)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
+       error = user_path_dir(filename, &path);
        if (error)
                goto out;
 
-       error = vfs_permission(&nd, MAY_EXEC);
+       error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
        if (error)
                goto dput_and_out;
 
@@ -560,11 +572,10 @@ asmlinkage long sys_chroot(const char __user * filename)
        if (!capable(CAP_SYS_CHROOT))
                goto dput_and_out;
 
-       set_fs_root(current->fs, &nd.path);
-       set_fs_altroot();
+       set_fs_root(current->fs, &path);
        error = 0;
 dput_and_out:
-       path_put(&nd.path);
+       path_put(&path);
 out:
        return error;
 }
@@ -589,9 +600,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
        err = mnt_want_write(file->f_path.mnt);
        if (err)
                goto out_putf;
-       err = -EPERM;
-       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-               goto out_drop_write;
        mutex_lock(&inode->i_mutex);
        if (mode == (mode_t) -1)
                mode = inode->i_mode;
@@ -599,8 +607,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
        err = notify_change(dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
-
-out_drop_write:
        mnt_drop_write(file->f_path.mnt);
 out_putf:
        fput(file);
@@ -611,36 +617,29 @@ out:
 asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
                             mode_t mode)
 {
-       struct nameidata nd;
-       struct inode * inode;
+       struct path path;
+       struct inode *inode;
        int error;
        struct iattr newattrs;
 
-       error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
+       error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
        if (error)
                goto out;
-       inode = nd.path.dentry->d_inode;
+       inode = path.dentry->d_inode;
 
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (error)
                goto dput_and_out;
-
-       error = -EPERM;
-       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-               goto out_drop_write;
-
        mutex_lock(&inode->i_mutex);
        if (mode == (mode_t) -1)
                mode = inode->i_mode;
        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-       error = notify_change(nd.path.dentry, &newattrs);
+       error = notify_change(path.dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
-
-out_drop_write:
-       mnt_drop_write(nd.path.mnt);
+       mnt_drop_write(path.mnt);
 dput_and_out:
-       path_put(&nd.path);
+       path_put(&path);
 out:
        return error;
 }
@@ -652,18 +651,10 @@ asmlinkage long sys_chmod(const char __user *filename, mode_t mode)
 
 static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
 {
-       struct inode * inode;
+       struct inode *inode = dentry->d_inode;
        int error;
        struct iattr newattrs;
 
-       error = -ENOENT;
-       if (!(inode = dentry->d_inode)) {
-               printk(KERN_ERR "chown_common: NULL inode\n");
-               goto out;
-       }
-       error = -EPERM;
-       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-               goto out;
        newattrs.ia_valid =  ATTR_CTIME;
        if (user != (uid_t) -1) {
                newattrs.ia_valid |= ATTR_UID;
@@ -679,25 +670,25 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
        mutex_lock(&inode->i_mutex);
        error = notify_change(dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
-out:
+
        return error;
 }
 
 asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = user_path_walk(filename, &nd);
+       error = user_path(filename, &path);
        if (error)
                goto out;
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (error)
                goto out_release;
-       error = chown_common(nd.path.dentry, user, group);
-       mnt_drop_write(nd.path.mnt);
+       error = chown_common(path.dentry, user, group);
+       mnt_drop_write(path.mnt);
 out_release:
-       path_put(&nd.path);
+       path_put(&path);
 out:
        return error;
 }
@@ -705,7 +696,7 @@ out:
 asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
                             gid_t group, int flag)
 {
-       struct nameidata nd;
+       struct path path;
        int error = -EINVAL;
        int follow;
 
@@ -713,35 +704,35 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
                goto out;
 
        follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
-       error = __user_walk_fd(dfd, filename, follow, &nd);
+       error = user_path_at(dfd, filename, follow, &path);
        if (error)
                goto out;
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (error)
                goto out_release;
-       error = chown_common(nd.path.dentry, user, group);
-       mnt_drop_write(nd.path.mnt);
+       error = chown_common(path.dentry, user, group);
+       mnt_drop_write(path.mnt);
 out_release:
-       path_put(&nd.path);
+       path_put(&path);
 out:
        return error;
 }
 
 asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = user_path_walk_link(filename, &nd);
+       error = user_lpath(filename, &path);
        if (error)
                goto out;
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (error)
                goto out_release;
-       error = chown_common(nd.path.dentry, user, group);
-       mnt_drop_write(nd.path.mnt);
+       error = chown_common(path.dentry, user, group);
+       mnt_drop_write(path.mnt);
 out_release:
-       path_put(&nd.path);
+       path_put(&path);
 out:
        return error;
 }
@@ -981,7 +972,6 @@ int get_unused_fd_flags(int flags)
        int fd, error;
        struct fdtable *fdt;
 
-       error = -EMFILE;
        spin_lock(&files->file_lock);
 
 repeat:
@@ -989,13 +979,6 @@ repeat:
        fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
                                files->next_fd);
 
-       /*
-        * N.B. For clone tasks sharing a files structure, this test
-        * will limit the total number of files that can be opened.
-        */
-       if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
-               goto out;
-
        /* Do we need to expand the fd array or fd set?  */
        error = expand_files(files, fd);
        if (error < 0)
@@ -1006,7 +989,6 @@ repeat:
                 * If we needed to expand the fs array we
                 * might have blocked - try again.
                 */
-               error = -EMFILE;
                goto repeat;
        }
 
index d17b4fd204e1f434558fdc55e78f6be0002a576e..9f5b054f06b932f873327a9c82e5674da54707cf 100644 (file)
@@ -430,7 +430,7 @@ static struct file_system_type openprom_fs_type = {
        .kill_sb        = kill_anon_super,
 };
 
-static void op_inode_init_once(struct kmem_cache * cachep, void *data)
+static void op_inode_init_once(void *data)
 {
        struct op_inode_info *oi = (struct op_inode_info *) data;
 
index efef715135d34e459ce450eb24ca41e4234cf471..7d6b34e201db4a8ba08525f942399eb742a57731 100644 (file)
@@ -344,18 +344,18 @@ static ssize_t whole_disk_show(struct device *dev,
 static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH,
                   whole_disk_show, NULL);
 
-void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags)
+int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags)
 {
        struct hd_struct *p;
        int err;
 
        p = kzalloc(sizeof(*p), GFP_KERNEL);
        if (!p)
-               return;
+               return -ENOMEM;
 
        if (!init_part_stats(p)) {
-               kfree(p);
-               return;
+               err = -ENOMEM;
+               goto out0;
        }
        p->start_sect = start;
        p->nr_sects = len;
@@ -378,15 +378,31 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len,
 
        /* delay uevent until 'holders' subdir is created */
        p->dev.uevent_suppress = 1;
-       device_add(&p->dev);
+       err = device_add(&p->dev);
+       if (err)
+               goto out1;
        partition_sysfs_add_subdir(p);
        p->dev.uevent_suppress = 0;
-       if (flags & ADDPART_FLAG_WHOLEDISK)
+       if (flags & ADDPART_FLAG_WHOLEDISK) {
                err = device_create_file(&p->dev, &dev_attr_whole_disk);
+               if (err)
+                       goto out2;
+       }
 
        /* suppress uevent if the disk supresses it */
        if (!disk->dev.uevent_suppress)
                kobject_uevent(&p->dev.kobj, KOBJ_ADD);
+
+       return 0;
+
+out2:
+       device_del(&p->dev);
+out1:
+       put_device(&p->dev);
+       free_part_stats(p);
+out0:
+       kfree(p);
+       return err;
 }
 
 /* Not exported, helper to add_disk(). */
@@ -483,10 +499,16 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
                if (!size)
                        continue;
                if (from + size > get_capacity(disk)) {
-                       printk(" %s: p%d exceeds device capacity\n",
+                       printk(KERN_ERR " %s: p%d exceeds device capacity\n",
                                disk->disk_name, p);
+                       continue;
+               }
+               res = add_partition(disk, p, from, size, state->parts[p].flags);
+               if (res) {
+                       printk(KERN_ERR " %s: p%d could not be added: %d\n",
+                               disk->disk_name, p, -res);
+                       continue;
                }
-               add_partition(disk, p, from, size, state->parts[p].flags);
 #ifdef CONFIG_BLK_DEV_MD
                if (state->parts[p].flags & ADDPART_FLAG_RAID)
                        md_autodetect_dev(bdev->bd_dev+p);
index e7b07006bc4173c5489c3bb1532f01e0473e4bf1..038a6022152fd15d84fb48b70fab816b971a8f7e 100644 (file)
 #include "check.h"
 #include "efi.h"
 
-#undef EFI_DEBUG
-#ifdef EFI_DEBUG
-#define Dprintk(x...) printk(KERN_DEBUG x)
-#else
-#define Dprintk(x...)
-#endif
-
 /* This allows a kernel command line option 'gpt' to override
  * the test for invalid PMBR.  Not __initdata because reloading
  * the partition tables happens after init too.
@@ -305,10 +298,10 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
 
        /* Check the GUID Partition Table signature */
        if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
-               Dprintk("GUID Partition Table Header signature is wrong:"
-                       "%lld != %lld\n",
-                       (unsigned long long)le64_to_cpu((*gpt)->signature),
-                       (unsigned long long)GPT_HEADER_SIGNATURE);
+               pr_debug("GUID Partition Table Header signature is wrong:"
+                        "%lld != %lld\n",
+                        (unsigned long long)le64_to_cpu((*gpt)->signature),
+                        (unsigned long long)GPT_HEADER_SIGNATURE);
                goto fail;
        }
 
@@ -318,9 +311,8 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
        crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));
 
        if (crc != origcrc) {
-               Dprintk
-                   ("GUID Partition Table Header CRC is wrong: %x != %x\n",
-                    crc, origcrc);
+               pr_debug("GUID Partition Table Header CRC is wrong: %x != %x\n",
+                        crc, origcrc);
                goto fail;
        }
        (*gpt)->header_crc32 = cpu_to_le32(origcrc);
@@ -328,9 +320,9 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
        /* Check that the my_lba entry points to the LBA that contains
         * the GUID Partition Table */
        if (le64_to_cpu((*gpt)->my_lba) != lba) {
-               Dprintk("GPT my_lba incorrect: %lld != %lld\n",
-                       (unsigned long long)le64_to_cpu((*gpt)->my_lba),
-                       (unsigned long long)lba);
+               pr_debug("GPT my_lba incorrect: %lld != %lld\n",
+                        (unsigned long long)le64_to_cpu((*gpt)->my_lba),
+                        (unsigned long long)lba);
                goto fail;
        }
 
@@ -339,15 +331,15 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
         */
        lastlba = last_lba(bdev);
        if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) {
-               Dprintk("GPT: first_usable_lba incorrect: %lld > %lld\n",
-                       (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba),
-                       (unsigned long long)lastlba);
+               pr_debug("GPT: first_usable_lba incorrect: %lld > %lld\n",
+                        (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba),
+                        (unsigned long long)lastlba);
                goto fail;
        }
        if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) {
-               Dprintk("GPT: last_usable_lba incorrect: %lld > %lld\n",
-                       (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
-                       (unsigned long long)lastlba);
+               pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n",
+                        (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
+                        (unsigned long long)lastlba);
                goto fail;
        }
 
@@ -360,7 +352,7 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
                        le32_to_cpu((*gpt)->sizeof_partition_entry));
 
        if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
-               Dprintk("GUID Partitition Entry Array CRC check failed.\n");
+               pr_debug("GUID Partitition Entry Array CRC check failed.\n");
                goto fail_ptes;
        }
 
@@ -616,7 +608,7 @@ efi_partition(struct parsed_partitions *state, struct block_device *bdev)
                return 0;
        }
 
-       Dprintk("GUID Partition Table is valid!  Yea!\n");
+       pr_debug("GUID Partition Table is valid!  Yea!\n");
 
        for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
                if (!is_pte_valid(&ptes[i], last_lba(bdev)))
index 0fdda2e8a4cc916648b035a1f962eaf8744797fa..8652fb99e96256e944295ab35ad3970ccf8b7cb1 100644 (file)
@@ -133,17 +133,17 @@ static bool ldm_parse_privhead(const u8 *data, struct privhead *ph)
        bool is_vista = false;
 
        BUG_ON(!data || !ph);
-       if (MAGIC_PRIVHEAD != BE64(data)) {
+       if (MAGIC_PRIVHEAD != get_unaligned_be64(data)) {
                ldm_error("Cannot find PRIVHEAD structure. LDM database is"
                        " corrupt. Aborting.");
                return false;
        }
-       ph->ver_major = BE16(data + 0x000C);
-       ph->ver_minor = BE16(data + 0x000E);
-       ph->logical_disk_start = BE64(data + 0x011B);
-       ph->logical_disk_size = BE64(data + 0x0123);
-       ph->config_start = BE64(data + 0x012B);
-       ph->config_size = BE64(data + 0x0133);
+       ph->ver_major = get_unaligned_be16(data + 0x000C);
+       ph->ver_minor = get_unaligned_be16(data + 0x000E);
+       ph->logical_disk_start = get_unaligned_be64(data + 0x011B);
+       ph->logical_disk_size = get_unaligned_be64(data + 0x0123);
+       ph->config_start = get_unaligned_be64(data + 0x012B);
+       ph->config_size = get_unaligned_be64(data + 0x0133);
        /* Version 2.11 is Win2k/XP and version 2.12 is Vista. */
        if (ph->ver_major == 2 && ph->ver_minor == 12)
                is_vista = true;
@@ -191,14 +191,14 @@ static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
 {
        BUG_ON (!data || !toc);
 
-       if (MAGIC_TOCBLOCK != BE64 (data)) {
+       if (MAGIC_TOCBLOCK != get_unaligned_be64(data)) {
                ldm_crit ("Cannot find TOCBLOCK, database may be corrupt.");
                return false;
        }
        strncpy (toc->bitmap1_name, data + 0x24, sizeof (toc->bitmap1_name));
        toc->bitmap1_name[sizeof (toc->bitmap1_name) - 1] = 0;
-       toc->bitmap1_start = BE64 (data + 0x2E);
-       toc->bitmap1_size  = BE64 (data + 0x36);
+       toc->bitmap1_start = get_unaligned_be64(data + 0x2E);
+       toc->bitmap1_size  = get_unaligned_be64(data + 0x36);
 
        if (strncmp (toc->bitmap1_name, TOC_BITMAP1,
                        sizeof (toc->bitmap1_name)) != 0) {
@@ -208,8 +208,8 @@ static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
        }
        strncpy (toc->bitmap2_name, data + 0x46, sizeof (toc->bitmap2_name));
        toc->bitmap2_name[sizeof (toc->bitmap2_name) - 1] = 0;
-       toc->bitmap2_start = BE64 (data + 0x50);
-       toc->bitmap2_size  = BE64 (data + 0x58);
+       toc->bitmap2_start = get_unaligned_be64(data + 0x50);
+       toc->bitmap2_size  = get_unaligned_be64(data + 0x58);
        if (strncmp (toc->bitmap2_name, TOC_BITMAP2,
                        sizeof (toc->bitmap2_name)) != 0) {
                ldm_crit ("TOCBLOCK's second bitmap is '%s', should be '%s'.",
@@ -237,22 +237,22 @@ static bool ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
 {
        BUG_ON (!data || !vm);
 
-       if (MAGIC_VMDB != BE32 (data)) {
+       if (MAGIC_VMDB != get_unaligned_be32(data)) {
                ldm_crit ("Cannot find the VMDB, database may be corrupt.");
                return false;
        }
 
-       vm->ver_major = BE16 (data + 0x12);
-       vm->ver_minor = BE16 (data + 0x14);
+       vm->ver_major = get_unaligned_be16(data + 0x12);
+       vm->ver_minor = get_unaligned_be16(data + 0x14);
        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;
        }
 
-       vm->vblk_size     = BE32 (data + 0x08);
-       vm->vblk_offset   = BE32 (data + 0x0C);
-       vm->last_vblk_seq = BE32 (data + 0x04);
+       vm->vblk_size     = get_unaligned_be32(data + 0x08);
+       vm->vblk_offset   = get_unaligned_be32(data + 0x0C);
+       vm->last_vblk_seq = get_unaligned_be32(data + 0x04);
 
        ldm_debug ("Parsed VMDB successfully.");
        return true;
@@ -507,7 +507,7 @@ static bool ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
                goto out;                               /* Already logged */
 
        /* Are there uncommitted transactions? */
-       if (BE16(data + 0x10) != 0x01) {
+       if (get_unaligned_be16(data + 0x10) != 0x01) {
                ldm_crit ("Database is not in a consistent state.  Aborting.");
                goto out;
        }
@@ -802,7 +802,7 @@ static bool ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
                return false;
 
        len += VBLK_SIZE_CMP3;
-       if (len != BE32 (buffer + 0x14))
+       if (len != get_unaligned_be32(buffer + 0x14))
                return false;
 
        comp = &vb->vblk.comp;
@@ -851,7 +851,7 @@ static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb)
                return false;
 
        len += VBLK_SIZE_DGR3;
-       if (len != BE32 (buffer + 0x14))
+       if (len != get_unaligned_be32(buffer + 0x14))
                return false;
 
        dgrp = &vb->vblk.dgrp;
@@ -895,7 +895,7 @@ static bool ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb)
                return false;
 
        len += VBLK_SIZE_DGR4;
-       if (len != BE32 (buffer + 0x14))
+       if (len != get_unaligned_be32(buffer + 0x14))
                return false;
 
        dgrp = &vb->vblk.dgrp;
@@ -931,7 +931,7 @@ static bool ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb)
                return false;
 
        len += VBLK_SIZE_DSK3;
-       if (len != BE32 (buffer + 0x14))
+       if (len != get_unaligned_be32(buffer + 0x14))
                return false;
 
        disk = &vb->vblk.disk;
@@ -968,7 +968,7 @@ static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
                return false;
 
        len += VBLK_SIZE_DSK4;
-       if (len != BE32 (buffer + 0x14))
+       if (len != get_unaligned_be32(buffer + 0x14))
                return false;
 
        disk = &vb->vblk.disk;
@@ -1034,14 +1034,14 @@ static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb)
                return false;
        }
        len += VBLK_SIZE_PRT3;
-       if (len > BE32(buffer + 0x14)) {
+       if (len > get_unaligned_be32(buffer + 0x14)) {
                ldm_error("len %d > BE32(buffer + 0x14) %d", len,
-                               BE32(buffer + 0x14));
+                               get_unaligned_be32(buffer + 0x14));
                return false;
        }
        part = &vb->vblk.part;
-       part->start = BE64(buffer + 0x24 + r_name);
-       part->volume_offset = BE64(buffer + 0x2C + r_name);
+       part->start = get_unaligned_be64(buffer + 0x24 + r_name);
+       part->volume_offset = get_unaligned_be64(buffer + 0x2C + r_name);
        part->size = ldm_get_vnum(buffer + 0x34 + r_name);
        part->parent_id = ldm_get_vnum(buffer + 0x34 + r_size);
        part->disk_id = ldm_get_vnum(buffer + 0x34 + r_parent);
@@ -1139,9 +1139,9 @@ static bool ldm_parse_vol5(const u8 *buffer, int buflen, struct vblk *vb)
                return false;
        }
        len += VBLK_SIZE_VOL5;
-       if (len > BE32(buffer + 0x14)) {
+       if (len > get_unaligned_be32(buffer + 0x14)) {
                ldm_error("len %d > BE32(buffer + 0x14) %d", len,
-                               BE32(buffer + 0x14));
+                               get_unaligned_be32(buffer + 0x14));
                return false;
        }
        volu = &vb->vblk.volu;
@@ -1294,9 +1294,9 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
 
        BUG_ON (!data || !frags);
 
-       group = BE32 (data + 0x08);
-       rec   = BE16 (data + 0x0C);
-       num   = BE16 (data + 0x0E);
+       group = get_unaligned_be32(data + 0x08);
+       rec   = get_unaligned_be16(data + 0x0C);
+       num   = get_unaligned_be16(data + 0x0E);
        if ((num < 1) || (num > 4)) {
                ldm_error ("A VBLK claims to have %d parts.", num);
                return false;
@@ -1425,12 +1425,12 @@ static bool ldm_get_vblks (struct block_device *bdev, unsigned long base,
                }
 
                for (v = 0; v < perbuf; v++, data+=size) {  /* For each vblk */
-                       if (MAGIC_VBLK != BE32 (data)) {
+                       if (MAGIC_VBLK != get_unaligned_be32(data)) {
                                ldm_error ("Expected to find a VBLK.");
                                goto out;
                        }
 
-                       recs = BE16 (data + 0x0E);      /* Number of records */
+                       recs = get_unaligned_be16(data + 0x0E); /* Number of records */
                        if (recs == 1) {
                                if (!ldm_ldmdb_add (data, size, ldb))
                                        goto out;       /* Already logged */
index 80f63b5fdd9fe294db9af77ae8d183e0a9449d3a..30e08e809c1dd7867801357ce71c12ecc028f132 100644 (file)
@@ -98,11 +98,6 @@ struct parsed_partitions;
 #define TOC_BITMAP1            "config"        /* Names of the two defined */
 #define TOC_BITMAP2            "log"           /* bitmaps in the TOCBLOCK. */
 
-/* Most numbers we deal with are big-endian and won't be aligned. */
-#define BE16(x)                        ((u16)be16_to_cpu(get_unaligned((__be16*)(x))))
-#define BE32(x)                        ((u32)be32_to_cpu(get_unaligned((__be32*)(x))))
-#define BE64(x)                        ((u64)be64_to_cpu(get_unaligned((__be64*)(x))))
-
 /* Borrowed from msdos.c */
 #define SYS_IND(p)             (get_unaligned(&(p)->sys_ind))
 
index 700f4e0d9572170a4de51527bc1698768a848afe..fcba6542b8d0132b72be8a93959a60b57c556e38 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -777,45 +777,10 @@ pipe_rdwr_open(struct inode *inode, struct file *filp)
 /*
  * The file_operations structs are not static because they
  * are also used in linux/fs/fifo.c to do operations on FIFOs.
+ *
+ * Pipes reuse fifos' file_operations structs.
  */
-const struct file_operations read_fifo_fops = {
-       .llseek         = no_llseek,
-       .read           = do_sync_read,
-       .aio_read       = pipe_read,
-       .write          = bad_pipe_w,
-       .poll           = pipe_poll,
-       .unlocked_ioctl = pipe_ioctl,
-       .open           = pipe_read_open,
-       .release        = pipe_read_release,
-       .fasync         = pipe_read_fasync,
-};
-
-const struct file_operations write_fifo_fops = {
-       .llseek         = no_llseek,
-       .read           = bad_pipe_r,
-       .write          = do_sync_write,
-       .aio_write      = pipe_write,
-       .poll           = pipe_poll,
-       .unlocked_ioctl = pipe_ioctl,
-       .open           = pipe_write_open,
-       .release        = pipe_write_release,
-       .fasync         = pipe_write_fasync,
-};
-
-const struct file_operations rdwr_fifo_fops = {
-       .llseek         = no_llseek,
-       .read           = do_sync_read,
-       .aio_read       = pipe_read,
-       .write          = do_sync_write,
-       .aio_write      = pipe_write,
-       .poll           = pipe_poll,
-       .unlocked_ioctl = pipe_ioctl,
-       .open           = pipe_rdwr_open,
-       .release        = pipe_rdwr_release,
-       .fasync         = pipe_rdwr_fasync,
-};
-
-static const struct file_operations read_pipe_fops = {
+const struct file_operations read_pipefifo_fops = {
        .llseek         = no_llseek,
        .read           = do_sync_read,
        .aio_read       = pipe_read,
@@ -827,7 +792,7 @@ static const struct file_operations read_pipe_fops = {
        .fasync         = pipe_read_fasync,
 };
 
-static const struct file_operations write_pipe_fops = {
+const struct file_operations write_pipefifo_fops = {
        .llseek         = no_llseek,
        .read           = bad_pipe_r,
        .write          = do_sync_write,
@@ -839,7 +804,7 @@ static const struct file_operations write_pipe_fops = {
        .fasync         = pipe_write_fasync,
 };
 
-static const struct file_operations rdwr_pipe_fops = {
+const struct file_operations rdwr_pipefifo_fops = {
        .llseek         = no_llseek,
        .read           = do_sync_read,
        .aio_read       = pipe_read,
@@ -927,7 +892,7 @@ static struct inode * get_pipe_inode(void)
        inode->i_pipe = pipe;
 
        pipe->readers = pipe->writers = 1;
-       inode->i_fop = &rdwr_pipe_fops;
+       inode->i_fop = &rdwr_pipefifo_fops;
 
        /*
         * Mark the inode dirty from the very beginning,
@@ -950,7 +915,7 @@ fail_inode:
        return NULL;
 }
 
-struct file *create_write_pipe(void)
+struct file *create_write_pipe(int flags)
 {
        int err;
        struct inode *inode;
@@ -978,12 +943,12 @@ struct file *create_write_pipe(void)
        d_instantiate(dentry, inode);
 
        err = -ENFILE;
-       f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipe_fops);
+       f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipefifo_fops);
        if (!f)
                goto err_dentry;
        f->f_mapping = inode->i_mapping;
 
-       f->f_flags = O_WRONLY;
+       f->f_flags = O_WRONLY | (flags & O_NONBLOCK);
        f->f_version = 0;
 
        return f;
@@ -1007,7 +972,7 @@ void free_write_pipe(struct file *f)
        put_filp(f);
 }
 
-struct file *create_read_pipe(struct file *wrf)
+struct file *create_read_pipe(struct file *wrf, int flags)
 {
        struct file *f = get_empty_filp();
        if (!f)
@@ -1019,34 +984,37 @@ struct file *create_read_pipe(struct file *wrf)
        f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
 
        f->f_pos = 0;
-       f->f_flags = O_RDONLY;
-       f->f_op = &read_pipe_fops;
+       f->f_flags = O_RDONLY | (flags & O_NONBLOCK);
+       f->f_op = &read_pipefifo_fops;
        f->f_mode = FMODE_READ;
        f->f_version = 0;
 
        return f;
 }
 
-int do_pipe(int *fd)
+int do_pipe_flags(int *fd, int flags)
 {
        struct file *fw, *fr;
        int error;
        int fdw, fdr;
 
-       fw = create_write_pipe();
+       if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+               return -EINVAL;
+
+       fw = create_write_pipe(flags);
        if (IS_ERR(fw))
                return PTR_ERR(fw);
-       fr = create_read_pipe(fw);
+       fr = create_read_pipe(fw, flags);
        error = PTR_ERR(fr);
        if (IS_ERR(fr))
                goto err_write_pipe;
 
-       error = get_unused_fd();
+       error = get_unused_fd_flags(flags);
        if (error < 0)
                goto err_read_pipe;
        fdr = error;
 
-       error = get_unused_fd();
+       error = get_unused_fd_flags(flags);
        if (error < 0)
                goto err_fdr;
        fdw = error;
@@ -1074,16 +1042,21 @@ int do_pipe(int *fd)
        return error;
 }
 
+int do_pipe(int *fd)
+{
+       return do_pipe_flags(fd, 0);
+}
+
 /*
  * sys_pipe() is the normal C calling standard for creating
  * a pipe. It's not the way Unix traditionally does this, though.
  */
-asmlinkage long __weak sys_pipe(int __user *fildes)
+asmlinkage long __weak sys_pipe2(int __user *fildes, int flags)
 {
        int fd[2];
        int error;
 
-       error = do_pipe(fd);
+       error = do_pipe_flags(fd, flags);
        if (!error) {
                if (copy_to_user(fildes, fd, sizeof(fd))) {
                        sys_close(fd[0]);
@@ -1094,6 +1067,11 @@ asmlinkage long __weak sys_pipe(int __user *fildes)
        return error;
 }
 
+asmlinkage long __weak sys_pipe(int __user *fildes)
+{
+       return sys_pipe2(fildes, 0);
+}
+
 /*
  * pipefs should _never_ be mounted by userland - too much of security hassle,
  * no real gain from having the whole whorehouse mounted. So we don't need
diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig
new file mode 100644 (file)
index 0000000..73cd7a4
--- /dev/null
@@ -0,0 +1,59 @@
+config PROC_FS
+       bool "/proc file system support" if EMBEDDED
+       default y
+       help
+         This is a virtual file system providing information about the status
+         of the system. "Virtual" means that it doesn't take up any space on
+         your hard disk: the files are created on the fly by the kernel when
+         you try to access them. Also, you cannot read the files with older
+         version of the program less: you need to use more or cat.
+
+         It's totally cool; for example, "cat /proc/interrupts" gives
+         information about what the different IRQs are used for at the moment
+         (there is a small number of Interrupt ReQuest lines in your computer
+         that are used by the attached devices to gain the CPU's attention --
+         often a source of trouble if two devices are mistakenly configured
+         to use the same IRQ). The program procinfo to display some
+         information about your system gathered from the /proc file system.
+
+         Before you can use the /proc file system, it has to be mounted,
+         meaning it has to be given a location in the directory hierarchy.
+         That location should be /proc. A command such as "mount -t proc proc
+         /proc" or the equivalent line in /etc/fstab does the job.
+
+         The /proc file system is explained in the file
+         <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage
+         ("man 5 proc").
+
+         This option will enlarge your kernel by about 67 KB. Several
+         programs depend on this, so everyone should say Y here.
+
+config PROC_KCORE
+       bool "/proc/kcore support" if !ARM
+       depends on PROC_FS && MMU
+
+config PROC_VMCORE
+        bool "/proc/vmcore support (EXPERIMENTAL)"
+        depends on PROC_FS && CRASH_DUMP
+       default y
+        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.
index 797d775e0354fca502c8ab439c4e986c8e27d237..0d6eb33597c6627f24586407f7e0a820454b3612 100644 (file)
@@ -80,6 +80,7 @@
 #include <linux/delayacct.h>
 #include <linux/seq_file.h>
 #include <linux/pid_namespace.h>
+#include <linux/tracehook.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -168,8 +169,12 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
        rcu_read_lock();
        ppid = pid_alive(p) ?
                task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
-       tpid = pid_alive(p) && p->ptrace ?
-               task_pid_nr_ns(rcu_dereference(p->parent), ns) : 0;
+       tpid = 0;
+       if (pid_alive(p)) {
+               struct task_struct *tracer = tracehook_tracer_task(p);
+               if (tracer)
+                       tpid = task_pid_nr_ns(tracer, ns);
+       }
        seq_printf(m,
                "State:\t%s\n"
                "Tgid:\t%d\n"
index 58c3e6a8e15e160ec3d6af3aabe6138b666b00b8..01ed610f9b87f6fc0ffe1bfa89f2177e77d07323 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/init.h>
 #include <linux/capability.h>
 #include <linux/file.h>
@@ -69,6 +70,7 @@
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/cgroup.h>
 #include <linux/cpuset.h>
 #include <linux/audit.h>
@@ -231,10 +233,14 @@ static int check_mem_permission(struct task_struct *task)
         * If current is actively ptrace'ing, and would also be
         * permitted to freshly attach with ptrace now, permit it.
         */
-       if (task->parent == current && (task->ptrace & PT_PTRACED) &&
-           task_is_stopped_or_traced(task) &&
-           ptrace_may_access(task, PTRACE_MODE_ATTACH))
-               return 0;
+       if (task_is_stopped_or_traced(task)) {
+               int match;
+               rcu_read_lock();
+               match = (tracehook_tracer_task(task) == current);
+               rcu_read_unlock();
+               if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
+                       return 0;
+       }
 
        /*
         * Noone else is allowed.
@@ -504,6 +510,26 @@ static int proc_pid_limits(struct task_struct *task, char *buffer)
        return count;
 }
 
+#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+static int proc_pid_syscall(struct task_struct *task, char *buffer)
+{
+       long nr;
+       unsigned long args[6], sp, pc;
+
+       if (task_current_syscall(task, &nr, args, 6, &sp, &pc))
+               return sprintf(buffer, "running\n");
+
+       if (nr < 0)
+               return sprintf(buffer, "%ld 0x%lx 0x%lx\n", nr, sp, pc);
+
+       return sprintf(buffer,
+                      "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+                      nr,
+                      args[0], args[1], args[2], args[3], args[4], args[5],
+                      sp, pc);
+}
+#endif /* CONFIG_HAVE_ARCH_TRACEHOOK */
+
 /************************************************************************/
 /*                       Here the fs part begins                        */
 /************************************************************************/
@@ -1834,8 +1860,7 @@ static const struct file_operations proc_fd_operations = {
  * /proc/pid/fd needs a special permission handler so that a process can still
  * access /proc/self/fd after it has executed a setuid().
  */
-static int proc_fd_permission(struct inode *inode, int mask,
-                               struct nameidata *nd)
+static int proc_fd_permission(struct inode *inode, int mask)
 {
        int rv;
 
@@ -2376,29 +2401,44 @@ static int proc_base_fill_cache(struct file *filp, void *dirent,
 }
 
 #ifdef CONFIG_TASK_IO_ACCOUNTING
-static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
+static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
 {
+       struct task_io_accounting acct = task->ioac;
+       unsigned long flags;
+
+       if (whole && lock_task_sighand(task, &flags)) {
+               struct task_struct *t = task;
+
+               task_io_accounting_add(&acct, &task->signal->ioac);
+               while_each_thread(task, t)
+                       task_io_accounting_add(&acct, &t->ioac);
+
+               unlock_task_sighand(task, &flags);
+       }
        return sprintf(buffer,
-#ifdef CONFIG_TASK_XACCT
                        "rchar: %llu\n"
                        "wchar: %llu\n"
                        "syscr: %llu\n"
                        "syscw: %llu\n"
-#endif
                        "read_bytes: %llu\n"
                        "write_bytes: %llu\n"
                        "cancelled_write_bytes: %llu\n",
-#ifdef CONFIG_TASK_XACCT
-                       (unsigned long long)task->rchar,
-                       (unsigned long long)task->wchar,
-                       (unsigned long long)task->syscr,
-                       (unsigned long long)task->syscw,
-#endif
-                       (unsigned long long)task->ioac.read_bytes,
-                       (unsigned long long)task->ioac.write_bytes,
-                       (unsigned long long)task->ioac.cancelled_write_bytes);
+                       acct.rchar, acct.wchar,
+                       acct.syscr, acct.syscw,
+                       acct.read_bytes, acct.write_bytes,
+                       acct.cancelled_write_bytes);
+}
+
+static int proc_tid_io_accounting(struct task_struct *task, char *buffer)
+{
+       return do_io_accounting(task, buffer, 0);
 }
-#endif
+
+static int proc_tgid_io_accounting(struct task_struct *task, char *buffer)
+{
+       return do_io_accounting(task, buffer, 1);
+}
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
 
 /*
  * Thread groups
@@ -2419,6 +2459,9 @@ static const struct pid_entry tgid_base_stuff[] = {
        INF("limits",     S_IRUSR, pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",      S_IRUGO|S_IWUSR, pid_sched),
+#endif
+#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+       INF("syscall",    S_IRUSR, pid_syscall),
 #endif
        INF("cmdline",    S_IRUGO, pid_cmdline),
        ONE("stat",       S_IRUGO, tgid_stat),
@@ -2470,7 +2513,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter),
 #endif
 #ifdef CONFIG_TASK_IO_ACCOUNTING
-       INF("io",       S_IRUGO, pid_io_accounting),
+       INF("io",       S_IRUGO, tgid_io_accounting),
 #endif
 };
 
@@ -2751,6 +2794,9 @@ static const struct pid_entry tid_base_stuff[] = {
        INF("limits",    S_IRUSR, pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",     S_IRUGO|S_IWUSR, pid_sched),
+#endif
+#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+       INF("syscall",   S_IRUSR, pid_syscall),
 #endif
        INF("cmdline",   S_IRUGO, pid_cmdline),
        ONE("stat",      S_IRUGO, tid_stat),
@@ -2797,6 +2843,9 @@ static const struct pid_entry tid_base_stuff[] = {
 #ifdef CONFIG_FAULT_INJECTION
        REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
 #endif
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+       INF("io",       S_IRUGO, tid_io_accounting),
+#endif
 };
 
 static int proc_tid_base_readdir(struct file * filp,
index 43e54e86cefd995aee7fc01d3e32515283472123..cb4096cc3fb7456f96a5a4e30dc1957e0707b10e 100644 (file)
@@ -597,6 +597,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
        ent->pde_users = 0;
        spin_lock_init(&ent->pde_unload_lock);
        ent->pde_unload_completion = NULL;
+       INIT_LIST_HEAD(&ent->pde_openers);
  out:
        return ent;
 }
@@ -789,15 +790,25 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
        spin_unlock(&de->pde_unload_lock);
 
 continue_removing:
+       spin_lock(&de->pde_unload_lock);
+       while (!list_empty(&de->pde_openers)) {
+               struct pde_opener *pdeo;
+
+               pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh);
+               list_del(&pdeo->lh);
+               spin_unlock(&de->pde_unload_lock);
+               pdeo->release(pdeo->inode, pdeo->file);
+               kfree(pdeo);
+               spin_lock(&de->pde_unload_lock);
+       }
+       spin_unlock(&de->pde_unload_lock);
+
        if (S_ISDIR(de->mode))
                parent->nlink--;
        de->nlink = 0;
-       if (de->subdir) {
-               printk(KERN_WARNING "%s: removing non-empty directory "
+       WARN(de->subdir, KERN_WARNING "%s: removing non-empty directory "
                        "'%s/%s', leaking at least '%s'\n", __func__,
                        de->parent->name, de->name, de->subdir->name);
-               WARN_ON(1);
-       }
        if (atomic_dec_and_test(&de->count))
                free_proc_entry(de);
 }
index b08d10017911f43927646943307e26238e4fe7dc..8bb03f056c282ec1c0b4b256c5f4ed4551182f1c 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
+#include <linux/sysctl.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -65,6 +66,8 @@ static void proc_delete_inode(struct inode *inode)
                        module_put(de->owner);
                de_put(de);
        }
+       if (PROC_I(inode)->sysctl)
+               sysctl_head_put(PROC_I(inode)->sysctl);
        clear_inode(inode);
 }
 
@@ -84,6 +87,8 @@ static struct inode *proc_alloc_inode(struct super_block *sb)
        ei->fd = 0;
        ei->op.proc_get_link = NULL;
        ei->pde = NULL;
+       ei->sysctl = NULL;
+       ei->sysctl_entry = NULL;
        inode = &ei->vfs_inode;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        return inode;
@@ -94,7 +99,7 @@ static void proc_destroy_inode(struct inode *inode)
        kmem_cache_free(proc_inode_cachep, PROC_I(inode));
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct proc_inode *ei = (struct proc_inode *) foo;
 
@@ -111,27 +116,25 @@ int __init proc_init_inodecache(void)
        return 0;
 }
 
-static int proc_remount(struct super_block *sb, int *flags, char *data)
-{
-       *flags |= MS_NODIRATIME;
-       return 0;
-}
-
 static const struct super_operations proc_sops = {
        .alloc_inode    = proc_alloc_inode,
        .destroy_inode  = proc_destroy_inode,
        .drop_inode     = generic_delete_inode,
        .delete_inode   = proc_delete_inode,
        .statfs         = simple_statfs,
-       .remount_fs     = proc_remount,
 };
 
-static void pde_users_dec(struct proc_dir_entry *pde)
+static void __pde_users_dec(struct proc_dir_entry *pde)
 {
-       spin_lock(&pde->pde_unload_lock);
        pde->pde_users--;
        if (pde->pde_unload_completion && pde->pde_users == 0)
                complete(pde->pde_unload_completion);
+}
+
+static void pde_users_dec(struct proc_dir_entry *pde)
+{
+       spin_lock(&pde->pde_unload_lock);
+       __pde_users_dec(pde);
        spin_unlock(&pde->pde_unload_lock);
 }
 
@@ -318,36 +321,97 @@ static int proc_reg_open(struct inode *inode, struct file *file)
        struct proc_dir_entry *pde = PDE(inode);
        int rv = 0;
        int (*open)(struct inode *, struct file *);
+       int (*release)(struct inode *, struct file *);
+       struct pde_opener *pdeo;
+
+       /*
+        * What for, you ask? Well, we can have open, rmmod, remove_proc_entry
+        * sequence. ->release won't be called because ->proc_fops will be
+        * cleared. Depending on complexity of ->release, consequences vary.
+        *
+        * We can't wait for mercy when close will be done for real, it's
+        * deadlockable: rmmod foo </proc/foo . So, we're going to do ->release
+        * by hand in remove_proc_entry(). For this, save opener's credentials
+        * for later.
+        */
+       pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL);
+       if (!pdeo)
+               return -ENOMEM;
 
        spin_lock(&pde->pde_unload_lock);
        if (!pde->proc_fops) {
                spin_unlock(&pde->pde_unload_lock);
+               kfree(pdeo);
                return rv;
        }
        pde->pde_users++;
        open = pde->proc_fops->open;
+       release = pde->proc_fops->release;
        spin_unlock(&pde->pde_unload_lock);
 
        if (open)
                rv = open(inode, file);
 
-       pde_users_dec(pde);
+       spin_lock(&pde->pde_unload_lock);
+       if (rv == 0 && release) {
+               /* To know what to release. */
+               pdeo->inode = inode;
+               pdeo->file = file;
+               /* Strictly for "too late" ->release in proc_reg_release(). */
+               pdeo->release = release;
+               list_add(&pdeo->lh, &pde->pde_openers);
+       } else
+               kfree(pdeo);
+       __pde_users_dec(pde);
+       spin_unlock(&pde->pde_unload_lock);
        return rv;
 }
 
+static struct pde_opener *find_pde_opener(struct proc_dir_entry *pde,
+                                       struct inode *inode, struct file *file)
+{
+       struct pde_opener *pdeo;
+
+       list_for_each_entry(pdeo, &pde->pde_openers, lh) {
+               if (pdeo->inode == inode && pdeo->file == file)
+                       return pdeo;
+       }
+       return NULL;
+}
+
 static int proc_reg_release(struct inode *inode, struct file *file)
 {
        struct proc_dir_entry *pde = PDE(inode);
        int rv = 0;
        int (*release)(struct inode *, struct file *);
+       struct pde_opener *pdeo;
 
        spin_lock(&pde->pde_unload_lock);
+       pdeo = find_pde_opener(pde, inode, file);
        if (!pde->proc_fops) {
-               spin_unlock(&pde->pde_unload_lock);
+               /*
+                * Can't simply exit, __fput() will think that everything is OK,
+                * and move on to freeing struct file. remove_proc_entry() will
+                * find slacker in opener's list and will try to do non-trivial
+                * things with struct file. Therefore, remove opener from list.
+                *
+                * But if opener is removed from list, who will ->release it?
+                */
+               if (pdeo) {
+                       list_del(&pdeo->lh);
+                       spin_unlock(&pde->pde_unload_lock);
+                       rv = pdeo->release(inode, file);
+                       kfree(pdeo);
+               } else
+                       spin_unlock(&pde->pde_unload_lock);
                return rv;
        }
        pde->pde_users++;
        release = pde->proc_fops->release;
+       if (pdeo) {
+               list_del(&pdeo->lh);
+               kfree(pdeo);
+       }
        spin_unlock(&pde->pde_unload_lock);
 
        if (release)
index 28cbca8059057e5f1b7729b69743aea11cecc27c..442202314d5322292f87328b3e62b5427b3fa77a 100644 (file)
@@ -63,6 +63,7 @@ extern const struct file_operations proc_smaps_operations;
 extern const struct file_operations proc_clear_refs_operations;
 extern const struct file_operations proc_pagemap_operations;
 extern const struct file_operations proc_net_operations;
+extern const struct file_operations proc_kmsg_operations;
 extern const struct inode_operations proc_net_inode_operations;
 
 void free_proc_entry(struct proc_dir_entry *de);
@@ -88,3 +89,10 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *ino,
                struct dentry *dentry);
 int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
                filldir_t filldir);
+
+struct pde_opener {
+       struct inode *inode;
+       struct file *file;
+       int (*release)(struct inode *, struct file *);
+       struct list_head lh;
+};
index e78c81fcf547981f3aa99c7ebeca831af15e98f5..c2370c76fb711d6c7c32fba6ec34ffac437d7b65 100644 (file)
 
 #define CORE_STR "CORE"
 
+#ifndef ELF_CORE_EFLAGS
+#define ELF_CORE_EFLAGS        0
+#endif
+
 static int open_kcore(struct inode * inode, struct file * filp)
 {
        return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
@@ -164,11 +168,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
        elf->e_entry    = 0;
        elf->e_phoff    = sizeof(struct elfhdr);
        elf->e_shoff    = 0;
-#if defined(CONFIG_H8300)
-       elf->e_flags    = ELF_FLAGS;
-#else
-       elf->e_flags    = 0;
-#endif
+       elf->e_flags    = ELF_CORE_EFLAGS;
        elf->e_ehsize   = sizeof(struct elfhdr);
        elf->e_phentsize= sizeof(struct elf_phdr);
        elf->e_phnum    = nphdr;
index ff3b90b56e9d635546fe71868ffdc473632c5352..9fd5df3f40ce7d0dcc4f78559fdd5eb2c521da4f 100644 (file)
@@ -15,6 +15,8 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
+#include "internal.h"
+
 extern wait_queue_head_t log_wait;
 
 extern int do_syslog(int type, char __user *bug, int count);
index c652d469dc08deeb25b057ca4675d857b9db79bb..ded96986296099a036af1400a1ecdd7f3f71c058 100644 (file)
@@ -232,7 +232,6 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
 #undef K
 }
 
-extern const struct seq_operations fragmentation_op;
 static int fragmentation_open(struct inode *inode, struct file *file)
 {
        (void)inode;
@@ -246,7 +245,6 @@ static const struct file_operations fragmentation_file_operations = {
        .release        = seq_release,
 };
 
-extern const struct seq_operations pagetypeinfo_op;
 static int pagetypeinfo_open(struct inode *inode, struct file *file)
 {
        return seq_open(file, &pagetypeinfo_op);
@@ -259,7 +257,6 @@ static const struct file_operations pagetypeinfo_file_ops = {
        .release        = seq_release,
 };
 
-extern const struct seq_operations zoneinfo_op;
 static int zoneinfo_open(struct inode *inode, struct file *file)
 {
        return seq_open(file, &zoneinfo_op);
@@ -356,7 +353,6 @@ static const struct file_operations proc_devinfo_operations = {
        .release        = seq_release,
 };
 
-extern const struct seq_operations vmstat_op;
 static int vmstat_open(struct inode *inode, struct file *file)
 {
        return seq_open(file, &vmstat_op);
@@ -468,14 +464,25 @@ static const struct file_operations proc_slabstats_operations = {
 #ifdef CONFIG_MMU
 static int vmalloc_open(struct inode *inode, struct file *file)
 {
-       return seq_open(file, &vmalloc_op);
+       unsigned int *ptr = NULL;
+       int ret;
+
+       if (NUMA_BUILD)
+               ptr = kmalloc(nr_node_ids * sizeof(unsigned int), GFP_KERNEL);
+       ret = seq_open(file, &vmalloc_op);
+       if (!ret) {
+               struct seq_file *m = file->private_data;
+               m->private = ptr;
+       } else
+               kfree(ptr);
+       return ret;
 }
 
 static const struct file_operations proc_vmalloc_operations = {
        .open           = vmalloc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = seq_release_private,
 };
 #endif
 
index 5acc001d49f6c72db83216173136701c2169f950..f9a8b892718fc2f1a04ce1d169ba1667378832b5 100644 (file)
 static struct dentry_operations proc_sys_dentry_operations;
 static const struct file_operations proc_sys_file_operations;
 static const struct inode_operations proc_sys_inode_operations;
+static const struct file_operations proc_sys_dir_file_operations;
+static const struct inode_operations proc_sys_dir_operations;
 
-static void proc_sys_refresh_inode(struct inode *inode, struct ctl_table *table)
-{
-       /* Refresh the cached information bits in the inode */
-       if (table) {
-               inode->i_uid = 0;
-               inode->i_gid = 0;
-               inode->i_mode = table->mode;
-               if (table->proc_handler) {
-                       inode->i_mode |= S_IFREG;
-                       inode->i_nlink = 1;
-               } else {
-                       inode->i_mode |= S_IFDIR;
-                       inode->i_nlink = 0;     /* It is too hard to figure out */
-               }
-       }
-}
-
-static struct inode *proc_sys_make_inode(struct inode *dir, struct ctl_table *table)
+static struct inode *proc_sys_make_inode(struct super_block *sb,
+               struct ctl_table_header *head, struct ctl_table *table)
 {
        struct inode *inode;
-       struct proc_inode *dir_ei, *ei;
-       int depth;
+       struct proc_inode *ei;
 
-       inode = new_inode(dir->i_sb);
+       inode = new_inode(sb);
        if (!inode)
                goto out;
 
-       /* A directory is always one deeper than it's parent */
-       dir_ei = PROC_I(dir);
-       depth = dir_ei->fd + 1;
-
+       sysctl_head_get(head);
        ei = PROC_I(inode);
-       ei->fd = depth;
+       ei->sysctl = head;
+       ei->sysctl_entry = table;
+
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-       inode->i_op = &proc_sys_inode_operations;
-       inode->i_fop = &proc_sys_file_operations;
        inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */
-       proc_sys_refresh_inode(inode, table);
+       inode->i_mode = table->mode;
+       if (!table->child) {
+               inode->i_mode |= S_IFREG;
+               inode->i_op = &proc_sys_inode_operations;
+               inode->i_fop = &proc_sys_file_operations;
+       } else {
+               inode->i_mode |= S_IFDIR;
+               inode->i_nlink = 0;
+               inode->i_op = &proc_sys_dir_operations;
+               inode->i_fop = &proc_sys_dir_file_operations;
+       }
 out:
        return inode;
 }
 
-static struct dentry *proc_sys_ancestor(struct dentry *dentry, int depth)
-{
-       for (;;) {
-               struct proc_inode *ei;
-
-               ei = PROC_I(dentry->d_inode);
-               if (ei->fd == depth)
-                       break; /* found */
-
-               dentry = dentry->d_parent;
-       }
-       return dentry;
-}
-
-static struct ctl_table *proc_sys_lookup_table_one(struct ctl_table *table,
-                                                       struct qstr *name)
+static struct ctl_table *find_in_table(struct ctl_table *p, struct qstr *name)
 {
        int len;
-       for ( ; table->ctl_name || table->procname; table++) {
+       for ( ; p->ctl_name || p->procname; p++) {
 
-               if (!table->procname)
+               if (!p->procname)
                        continue;
 
-               len = strlen(table->procname);
+               len = strlen(p->procname);
                if (len != name->len)
                        continue;
 
-               if (memcmp(table->procname, name->name, len) != 0)
+               if (memcmp(p->procname, name->name, len) != 0)
                        continue;
 
                /* I have a match */
-               return table;
+               return p;
        }
        return NULL;
 }
 
-static struct ctl_table *proc_sys_lookup_table(struct dentry *dentry,
-                                               struct ctl_table *table)
+struct ctl_table_header *grab_header(struct inode *inode)
 {
-       struct dentry *ancestor;
-       struct proc_inode *ei;
-       int depth, i;
+       if (PROC_I(inode)->sysctl)
+               return sysctl_head_grab(PROC_I(inode)->sysctl);
+       else
+               return sysctl_head_next(NULL);
+}
 
-       ei = PROC_I(dentry->d_inode);
-       depth = ei->fd;
+static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
+                                       struct nameidata *nd)
+{
+       struct ctl_table_header *head = grab_header(dir);
+       struct ctl_table *table = PROC_I(dir)->sysctl_entry;
+       struct ctl_table_header *h = NULL;
+       struct qstr *name = &dentry->d_name;
+       struct ctl_table *p;
+       struct inode *inode;
+       struct dentry *err = ERR_PTR(-ENOENT);
 
-       if (depth == 0)
-               return table;
+       if (IS_ERR(head))
+               return ERR_CAST(head);
 
-       for (i = 1; table && (i <= depth); i++) {
-               ancestor = proc_sys_ancestor(dentry, i);
-               table = proc_sys_lookup_table_one(table, &ancestor->d_name);
-               if (table)
-                       table = table->child;
+       if (table && !table->child) {
+               WARN_ON(1);
+               goto out;
        }
-       return table;
-
-}
-static struct ctl_table *proc_sys_lookup_entry(struct dentry *dparent,
-                                               struct qstr *name,
-                                               struct ctl_table *table)
-{
-       table = proc_sys_lookup_table(dparent, table);
-       if (table)
-               table = proc_sys_lookup_table_one(table, name);
-       return table;
-}
 
-static struct ctl_table *do_proc_sys_lookup(struct dentry *parent,
-                                               struct qstr *name,
-                                               struct ctl_table_header **ptr)
-{
-       struct ctl_table_header *head;
-       struct ctl_table *table = NULL;
+       table = table ? table->child : head->ctl_table;
 
-       for (head = sysctl_head_next(NULL); head;
-                       head = sysctl_head_next(head)) {
-               table = proc_sys_lookup_entry(parent, name, head->ctl_table);
-               if (table)
-                       break;
+       p = find_in_table(table, name);
+       if (!p) {
+               for (h = sysctl_head_next(NULL); h; h = sysctl_head_next(h)) {
+                       if (h->attached_to != table)
+                               continue;
+                       p = find_in_table(h->attached_by, name);
+                       if (p)
+                               break;
+               }
        }
-       *ptr = head;
-       return table;
-}
-
-static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
-                                       struct nameidata *nd)
-{
-       struct ctl_table_header *head;
-       struct inode *inode;
-       struct dentry *err;
-       struct ctl_table *table;
 
-       err = ERR_PTR(-ENOENT);
-       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
-       if (!table)
+       if (!p)
                goto out;
 
        err = ERR_PTR(-ENOMEM);
-       inode = proc_sys_make_inode(dir, table);
+       inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
+       if (h)
+               sysctl_head_finish(h);
+
        if (!inode)
                goto out;
 
@@ -168,22 +129,14 @@ out:
 static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
                size_t count, loff_t *ppos, int write)
 {
-       struct dentry *dentry = filp->f_dentry;
-       struct ctl_table_header *head;
-       struct ctl_table *table;
+       struct inode *inode = filp->f_path.dentry->d_inode;
+       struct ctl_table_header *head = grab_header(inode);
+       struct ctl_table *table = PROC_I(inode)->sysctl_entry;
        ssize_t error;
        size_t res;
 
-       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
-       /* Has the sysctl entry disappeared on us? */
-       error = -ENOENT;
-       if (!table)
-               goto out;
-
-       /* Has the sysctl entry been replaced by a directory? */
-       error = -EISDIR;
-       if (!table->proc_handler)
-               goto out;
+       if (IS_ERR(head))
+               return PTR_ERR(head);
 
        /*
         * At this point we know that the sysctl was not unregistered
@@ -193,6 +146,11 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
        if (sysctl_perm(head->root, table, write ? MAY_WRITE : MAY_READ))
                goto out;
 
+       /* if that can happen at all, it should be -EINVAL, not -EISDIR */
+       error = -EINVAL;
+       if (!table->proc_handler)
+               goto out;
+
        /* careful: calling conventions are nasty here */
        res = count;
        error = table->proc_handler(table, write, filp, buf, &res, ppos);
@@ -218,82 +176,86 @@ static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
 
 
 static int proc_sys_fill_cache(struct file *filp, void *dirent,
-                               filldir_t filldir, struct ctl_table *table)
+                               filldir_t filldir,
+                               struct ctl_table_header *head,
+                               struct ctl_table *table)
 {
-       struct ctl_table_header *head;
-       struct ctl_table *child_table = NULL;
        struct dentry *child, *dir = filp->f_path.dentry;
        struct inode *inode;
        struct qstr qname;
        ino_t ino = 0;
        unsigned type = DT_UNKNOWN;
-       int ret;
 
        qname.name = table->procname;
        qname.len  = strlen(table->procname);
        qname.hash = full_name_hash(qname.name, qname.len);
 
-       /* Suppress duplicates.
-        * Only fill a directory entry if it is the value that
-        * an ordinary lookup of that name returns.  Hide all
-        * others.
-        *
-        * If we ever cache this translation in the dcache
-        * I should do a dcache lookup first.  But for now
-        * it is just simpler not to.
-        */
-       ret = 0;
-       child_table = do_proc_sys_lookup(dir, &qname, &head);
-       sysctl_head_finish(head);
-       if (child_table != table)
-               return 0;
-
        child = d_lookup(dir, &qname);
        if (!child) {
-               struct dentry *new;
-               new = d_alloc(dir, &qname);
-               if (new) {
-                       inode = proc_sys_make_inode(dir->d_inode, table);
-                       if (!inode)
-                               child = ERR_PTR(-ENOMEM);
-                       else {
-                               new->d_op = &proc_sys_dentry_operations;
-                               d_add(new, inode);
+               child = d_alloc(dir, &qname);
+               if (child) {
+                       inode = proc_sys_make_inode(dir->d_sb, head, table);
+                       if (!inode) {
+                               dput(child);
+                               return -ENOMEM;
+                       else {
+                               child->d_op = &proc_sys_dentry_operations;
+                               d_add(child, inode);
                        }
-                       if (child)
-                               dput(new);
-                       else
-                               child = new;
+               } else {
+                       return -ENOMEM;
                }
        }
-       if (!child || IS_ERR(child) || !child->d_inode)
-               goto end_instantiate;
        inode = child->d_inode;
-       if (inode) {
-               ino  = inode->i_ino;
-               type = inode->i_mode >> 12;
-       }
+       ino  = inode->i_ino;
+       type = inode->i_mode >> 12;
        dput(child);
-end_instantiate:
-       if (!ino)
-               ino= find_inode_number(dir, &qname);
-       if (!ino)
-               ino = 1;
-       return filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type);
+       return !!filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type);
+}
+
+static int scan(struct ctl_table_header *head, ctl_table *table,
+               unsigned long *pos, struct file *file,
+               void *dirent, filldir_t filldir)
+{
+
+       for (; table->ctl_name || table->procname; table++, (*pos)++) {
+               int res;
+
+               /* Can't do anything without a proc name */
+               if (!table->procname)
+                       continue;
+
+               if (*pos < file->f_pos)
+                       continue;
+
+               res = proc_sys_fill_cache(file, dirent, filldir, head, table);
+               if (res)
+                       return res;
+
+               file->f_pos = *pos + 1;
+       }
+       return 0;
 }
 
 static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
-       struct ctl_table_header *head = NULL;
-       struct ctl_table *table;
+       struct ctl_table_header *head = grab_header(inode);
+       struct ctl_table *table = PROC_I(inode)->sysctl_entry;
+       struct ctl_table_header *h = NULL;
        unsigned long pos;
-       int ret;
+       int ret = -EINVAL;
+
+       if (IS_ERR(head))
+               return PTR_ERR(head);
 
-       ret = -ENOTDIR;
-       if (!S_ISDIR(inode->i_mode))
+       if (table && !table->child) {
+               WARN_ON(1);
                goto out;
+       }
+
+       table = table ? table->child : head->ctl_table;
 
        ret = 0;
        /* Avoid a switch here: arm builds fail with missing __cmpdi2 */
@@ -311,30 +273,17 @@ static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir)
        }
        pos = 2;
 
-       /* - Find each instance of the directory
-        * - Read all entries in each instance
-        * - Before returning an entry to user space lookup the entry
-        *   by name and if I find a different entry don't return
-        *   this one because it means it is a buried dup.
-        * For sysctl this should only happen for directory entries.
-        */
-       for (head = sysctl_head_next(NULL); head; head = sysctl_head_next(head)) {
-               table = proc_sys_lookup_table(dentry, head->ctl_table);
+       ret = scan(head, table, &pos, filp, dirent, filldir);
+       if (ret)
+               goto out;
 
-               if (!table)
+       for (h = sysctl_head_next(NULL); h; h = sysctl_head_next(h)) {
+               if (h->attached_to != table)
                        continue;
-
-               for (; table->ctl_name || table->procname; table++, pos++) {
-                       /* Can't do anything without a proc name */
-                       if (!table->procname)
-                               continue;
-
-                       if (pos < filp->f_pos)
-                               continue;
-
-                       if (proc_sys_fill_cache(filp, dirent, filldir, table) < 0)
-                               goto out;
-                       filp->f_pos = pos + 1;
+               ret = scan(h, h->attached_by, &pos, filp, dirent, filldir);
+               if (ret) {
+                       sysctl_head_finish(h);
+                       break;
                }
        }
        ret = 1;
@@ -343,53 +292,24 @@ out:
        return ret;
 }
 
-static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *nd)
+static int proc_sys_permission(struct inode *inode, int mask)
 {
        /*
         * sysctl entries that are not writeable,
         * are _NOT_ writeable, capabilities or not.
         */
-       struct ctl_table_header *head;
-       struct ctl_table *table;
-       struct dentry *dentry;
-       int mode;
-       int depth;
+       struct ctl_table_header *head = grab_header(inode);
+       struct ctl_table *table = PROC_I(inode)->sysctl_entry;
        int error;
 
-       head = NULL;
-       depth = PROC_I(inode)->fd;
-
-       /* First check the cached permissions, in case we don't have
-        * enough information to lookup the sysctl table entry.
-        */
-       error = -EACCES;
-       mode = inode->i_mode;
-
-       if (current->euid == 0)
-               mode >>= 6;
-       else if (in_group_p(0))
-               mode >>= 3;
-
-       if ((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)
-               error = 0;
-
-       /* If we can't get a sysctl table entry the permission
-        * checks on the cached mode will have to be enough.
-        */
-       if (!nd || !depth)
-               goto out;
+       if (IS_ERR(head))
+               return PTR_ERR(head);
 
-       dentry = nd->path.dentry;
-       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+       if (!table) /* global root - r-xr-xr-x */
+               error = mask & MAY_WRITE ? -EACCES : 0;
+       else /* Use the permissions on the sysctl table entry */
+               error = sysctl_perm(head->root, table, mask);
 
-       /* If the entry does not exist deny permission */
-       error = -EACCES;
-       if (!table)
-               goto out;
-
-       /* Use the permissions on the sysctl table entry */
-       error = sysctl_perm(head->root, table, mask);
-out:
        sysctl_head_finish(head);
        return error;
 }
@@ -409,33 +329,70 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
        return error;
 }
 
-/* I'm lazy and don't distinguish between files and directories,
- * until access time.
- */
+static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+       struct inode *inode = dentry->d_inode;
+       struct ctl_table_header *head = grab_header(inode);
+       struct ctl_table *table = PROC_I(inode)->sysctl_entry;
+
+       if (IS_ERR(head))
+               return PTR_ERR(head);
+
+       generic_fillattr(inode, stat);
+       if (table)
+               stat->mode = (stat->mode & S_IFMT) | table->mode;
+
+       sysctl_head_finish(head);
+       return 0;
+}
+
 static const struct file_operations proc_sys_file_operations = {
        .read           = proc_sys_read,
        .write          = proc_sys_write,
+};
+
+static const struct file_operations proc_sys_dir_file_operations = {
        .readdir        = proc_sys_readdir,
 };
 
 static const struct inode_operations proc_sys_inode_operations = {
+       .permission     = proc_sys_permission,
+       .setattr        = proc_sys_setattr,
+       .getattr        = proc_sys_getattr,
+};
+
+static const struct inode_operations proc_sys_dir_operations = {
        .lookup         = proc_sys_lookup,
        .permission     = proc_sys_permission,
        .setattr        = proc_sys_setattr,
+       .getattr        = proc_sys_getattr,
 };
 
 static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-       struct ctl_table_header *head;
-       struct ctl_table *table;
-       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
-       proc_sys_refresh_inode(dentry->d_inode, table);
-       sysctl_head_finish(head);
-       return !!table;
+       return !PROC_I(dentry->d_inode)->sysctl->unregistering;
+}
+
+static int proc_sys_delete(struct dentry *dentry)
+{
+       return !!PROC_I(dentry->d_inode)->sysctl->unregistering;
+}
+
+static int proc_sys_compare(struct dentry *dir, struct qstr *qstr,
+                           struct qstr *name)
+{
+       struct dentry *dentry = container_of(qstr, struct dentry, d_name);
+       if (qstr->len != name->len)
+               return 1;
+       if (memcmp(qstr->name, name->name, name->len))
+               return 1;
+       return !sysctl_is_seen(PROC_I(dentry->d_inode)->sysctl);
 }
 
 static struct dentry_operations proc_sys_dentry_operations = {
        .d_revalidate   = proc_sys_revalidate,
+       .d_delete       = proc_sys_delete,
+       .d_compare      = proc_sys_compare,
 };
 
 static struct proc_dir_entry *proc_sys_root;
@@ -443,8 +400,8 @@ static struct proc_dir_entry *proc_sys_root;
 int proc_sys_init(void)
 {
        proc_sys_root = proc_mkdir("sys", NULL);
-       proc_sys_root->proc_iops = &proc_sys_inode_operations;
-       proc_sys_root->proc_fops = &proc_sys_file_operations;
+       proc_sys_root->proc_iops = &proc_sys_dir_operations;
+       proc_sys_root->proc_fops = &proc_sys_dir_file_operations;
        proc_sys_root->nlink = 0;
        return 0;
 }
index b31ab78052b386380058e0fc9031f39f1fd1db63..2aad1044b84ccf1342578cd66407ef88e406cf1d 100644 (file)
@@ -553,7 +553,7 @@ static void qnx4_destroy_inode(struct inode *inode)
        kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo;
 
index db1cc9f3c7aa3a24be8439c632f77228e5e266ab..7f4386ebc23a26b98f97d5088ecff7c79369fe17 100644 (file)
@@ -186,7 +186,7 @@ static void quota_sync_sb(struct super_block *sb, int type)
 
 void sync_dquots(struct super_block *sb, int type)
 {
-       int cnt, dirty;
+       int cnt;
 
        if (sb) {
                if (sb->s_qcop->quota_sync)
@@ -198,11 +198,17 @@ void sync_dquots(struct super_block *sb, int type)
 restart:
        list_for_each_entry(sb, &super_blocks, s_list) {
                /* This test just improves performance so it needn't be reliable... */
-               for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
-                       if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
-                           && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
-                               dirty = 1;
-               if (!dirty)
+               for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+                       if (type != -1 && type != cnt)
+                               continue;
+                       if (!sb_has_quota_enabled(sb, cnt))
+                               continue;
+                       if (!info_dirty(&sb_dqopt(sb)->info[cnt]) &&
+                           list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list))
+                               continue;
+                       break;
+               }
+               if (cnt == MAXQUOTAS)
                        continue;
                sb->s_count++;
                spin_unlock(&sb_lock);
index a6cf9269105c478e7a88db2ca6b074b8bcc0933d..5ae15b13eeb00217b529b336349736604377c472 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/quota.h>
+#include <linux/quotaops.h>
 #include <linux/dqblk_v1.h>
 #include <linux/quotaio_v1.h>
 #include <linux/kernel.h>
index 234ada90363343ad668eff8213dd0927af7aa6f2..b53827dc02d9081c50e0d0ed0acb971c2ad931b8 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/quotaops.h>
 
 #include <asm/byteorder.h>
 
index e396b2fa4743e66b32d3ea4ad740aa403266fa40..c8f60ee183b5b53d4799116e776f990ba6bf2d93 100644 (file)
 **                     from within kupdate, it will ignore the immediate flag
 */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
 #include <linux/time.h>
 #include <linux/semaphore.h>
-
 #include <linux/vmalloc.h>
 #include <linux/reiserfs_fs.h>
-
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
@@ -54,6 +49,9 @@
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
+#include <linux/uaccess.h>
+
+#include <asm/system.h>
 
 /* gets a struct reiserfs_journal_list * from a list head */
 #define JOURNAL_LIST_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \
@@ -558,13 +556,13 @@ static inline void insert_journal_hash(struct reiserfs_journal_cnode **table,
 static inline void lock_journal(struct super_block *p_s_sb)
 {
        PROC_INFO_INC(p_s_sb, journal.lock_journal);
-       down(&SB_JOURNAL(p_s_sb)->j_lock);
+       mutex_lock(&SB_JOURNAL(p_s_sb)->j_mutex);
 }
 
 /* unlock the current transaction */
 static inline void unlock_journal(struct super_block *p_s_sb)
 {
-       up(&SB_JOURNAL(p_s_sb)->j_lock);
+       mutex_unlock(&SB_JOURNAL(p_s_sb)->j_mutex);
 }
 
 static inline void get_journal_list(struct reiserfs_journal_list *jl)
@@ -1045,9 +1043,9 @@ static int flush_commit_list(struct super_block *s,
        }
 
        /* make sure nobody is trying to flush this one at the same time */
-       down(&jl->j_commit_lock);
+       mutex_lock(&jl->j_commit_mutex);
        if (!journal_list_still_alive(s, trans_id)) {
-               up(&jl->j_commit_lock);
+               mutex_unlock(&jl->j_commit_mutex);
                goto put_jl;
        }
        BUG_ON(jl->j_trans_id == 0);
@@ -1057,7 +1055,7 @@ static int flush_commit_list(struct super_block *s,
                if (flushall) {
                        atomic_set(&(jl->j_older_commits_done), 1);
                }
-               up(&jl->j_commit_lock);
+               mutex_unlock(&jl->j_commit_mutex);
                goto put_jl;
        }
 
@@ -1181,7 +1179,7 @@ static int flush_commit_list(struct super_block *s,
        if (flushall) {
                atomic_set(&(jl->j_older_commits_done), 1);
        }
-       up(&jl->j_commit_lock);
+       mutex_unlock(&jl->j_commit_mutex);
       put_jl:
        put_journal_list(s, jl);
 
@@ -1411,8 +1409,8 @@ static int flush_journal_list(struct super_block *s,
 
        /* if flushall == 0, the lock is already held */
        if (flushall) {
-               down(&journal->j_flush_sem);
-       } else if (!down_trylock(&journal->j_flush_sem)) {
+               mutex_lock(&journal->j_flush_mutex);
+       } else if (mutex_trylock(&journal->j_flush_mutex)) {
                BUG();
        }
 
@@ -1642,7 +1640,7 @@ static int flush_journal_list(struct super_block *s,
        jl->j_state = 0;
        put_journal_list(s, jl);
        if (flushall)
-               up(&journal->j_flush_sem);
+               mutex_unlock(&journal->j_flush_mutex);
        put_fs_excl();
        return err;
 }
@@ -1772,12 +1770,12 @@ static int kupdate_transactions(struct super_block *s,
        struct reiserfs_journal *journal = SB_JOURNAL(s);
        chunk.nr = 0;
 
-       down(&journal->j_flush_sem);
+       mutex_lock(&journal->j_flush_mutex);
        if (!journal_list_still_alive(s, orig_trans_id)) {
                goto done;
        }
 
-       /* we've got j_flush_sem held, nobody is going to delete any
+       /* we've got j_flush_mutex held, nobody is going to delete any
         * of these lists out from underneath us
         */
        while ((num_trans && transactions_flushed < num_trans) ||
@@ -1812,7 +1810,7 @@ static int kupdate_transactions(struct super_block *s,
        }
 
       done:
-       up(&journal->j_flush_sem);
+       mutex_unlock(&journal->j_flush_mutex);
        return ret;
 }
 
@@ -2556,7 +2554,7 @@ static struct reiserfs_journal_list *alloc_journal_list(struct super_block *s)
        INIT_LIST_HEAD(&jl->j_working_list);
        INIT_LIST_HEAD(&jl->j_tail_bh_list);
        INIT_LIST_HEAD(&jl->j_bh_list);
-       sema_init(&jl->j_commit_lock, 1);
+       mutex_init(&jl->j_commit_mutex);
        SB_JOURNAL(s)->j_num_lists++;
        get_journal_list(jl);
        return jl;
@@ -2837,8 +2835,8 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name,
        journal->j_last = NULL;
        journal->j_first = NULL;
        init_waitqueue_head(&(journal->j_join_wait));
-       sema_init(&journal->j_lock, 1);
-       sema_init(&journal->j_flush_sem, 1);
+       mutex_init(&journal->j_mutex);
+       mutex_init(&journal->j_flush_mutex);
 
        journal->j_trans_id = 10;
        journal->j_mount_id = 10;
@@ -4030,7 +4028,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
         * the new transaction is fully setup, and we've already flushed the
         * ordered bh list
         */
-       down(&jl->j_commit_lock);
+       mutex_lock(&jl->j_commit_mutex);
 
        /* save the transaction id in case we need to commit it later */
        commit_trans_id = jl->j_trans_id;
@@ -4196,7 +4194,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
                lock_kernel();
        }
        BUG_ON(!list_empty(&jl->j_tail_bh_list));
-       up(&jl->j_commit_lock);
+       mutex_unlock(&jl->j_commit_mutex);
 
        /* honor the flush wishes from the caller, simple commits can
         ** be done outside the journal lock, they are done below
index 1d40f2bd197081284dce1ff34c6d1f828082304f..879e54d35c2d49400a48b3d748a69c92934acb7a 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
 #include <linux/exportfs.h>
+#include <linux/quotaops.h>
 #include <linux/vfs.h>
 #include <linux/mnt_namespace.h>
 #include <linux/mount.h>
@@ -182,7 +183,7 @@ static int finish_unfinished(struct super_block *s)
                        int ret = reiserfs_quota_on_mount(s, i);
                        if (ret < 0)
                                reiserfs_warning(s,
-                                                "reiserfs: cannot turn on journalled quota: error %d",
+                                                "reiserfs: cannot turn on journaled quota: error %d",
                                                 ret);
                }
        }
@@ -520,7 +521,7 @@ static void reiserfs_destroy_inode(struct inode *inode)
        kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo;
 
@@ -876,7 +877,9 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                                     mount options were selected. */
                                  unsigned long *blocks,        /* strtol-ed from NNN of resize=NNN */
                                  char **jdev_name,
-                                 unsigned int *commit_max_age)
+                                 unsigned int *commit_max_age,
+                                 char **qf_names,
+                                 unsigned int *qfmt)
 {
        int c;
        char *arg = NULL;
@@ -992,9 +995,11 @@ static int reiserfs_parse_options(struct super_block *s, char *options,    /* strin
                if (c == 'u' || c == 'g') {
                        int qtype = c == 'u' ? USRQUOTA : GRPQUOTA;
 
-                       if (sb_any_quota_enabled(s)) {
+                       if ((sb_any_quota_enabled(s) ||
+                            sb_any_quota_suspended(s)) &&
+                           (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) {
                                reiserfs_warning(s,
-                                                "reiserfs_parse_options: cannot change journalled quota options when quota turned on.");
+                                                "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
                                return 0;
                        }
                        if (*arg) {     /* Some filename specified? */
@@ -1011,46 +1016,54 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
                                                         "reiserfs_parse_options: quotafile must be on filesystem root.");
                                        return 0;
                                }
-                               REISERFS_SB(s)->s_qf_names[qtype] =
+                               qf_names[qtype] =
                                    kmalloc(strlen(arg) + 1, GFP_KERNEL);
-                               if (!REISERFS_SB(s)->s_qf_names[qtype]) {
+                               if (!qf_names[qtype]) {
                                        reiserfs_warning(s,
                                                         "reiserfs_parse_options: not enough memory for storing quotafile name.");
                                        return 0;
                                }
-                               strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg);
+                               strcpy(qf_names[qtype], arg);
                                *mount_options |= 1 << REISERFS_QUOTA;
                        } else {
-                               kfree(REISERFS_SB(s)->s_qf_names[qtype]);
-                               REISERFS_SB(s)->s_qf_names[qtype] = NULL;
+                               if (qf_names[qtype] !=
+                                   REISERFS_SB(s)->s_qf_names[qtype])
+                                       kfree(qf_names[qtype]);
+                               qf_names[qtype] = NULL;
                        }
                }
                if (c == 'f') {
                        if (!strcmp(arg, "vfsold"))
-                               REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_OLD;
+                               *qfmt = QFMT_VFS_OLD;
                        else if (!strcmp(arg, "vfsv0"))
-                               REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_V0;
+                               *qfmt = QFMT_VFS_V0;
                        else {
                                reiserfs_warning(s,
                                                 "reiserfs_parse_options: unknown quota format specified.");
                                return 0;
                        }
+                       if ((sb_any_quota_enabled(s) ||
+                            sb_any_quota_suspended(s)) &&
+                           *qfmt != REISERFS_SB(s)->s_jquota_fmt) {
+                               reiserfs_warning(s,
+                                                "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
+                               return 0;
+                       }
                }
 #else
                if (c == 'u' || c == 'g' || c == 'f') {
                        reiserfs_warning(s,
-                                        "reiserfs_parse_options: journalled quota options not supported.");
+                                        "reiserfs_parse_options: journaled quota options not supported.");
                        return 0;
                }
 #endif
        }
 
 #ifdef CONFIG_QUOTA
-       if (!REISERFS_SB(s)->s_jquota_fmt
-           && (REISERFS_SB(s)->s_qf_names[USRQUOTA]
-               || REISERFS_SB(s)->s_qf_names[GRPQUOTA])) {
+       if (!REISERFS_SB(s)->s_jquota_fmt && !*qfmt
+           && (qf_names[USRQUOTA] || qf_names[GRPQUOTA])) {
                reiserfs_warning(s,
-                                "reiserfs_parse_options: journalled quota format not specified.");
+                                "reiserfs_parse_options: journaled quota format not specified.");
                return 0;
        }
        /* This checking is not precise wrt the quota type but for our purposes it is sufficient */
@@ -1130,6 +1143,21 @@ static void handle_attrs(struct super_block *s)
        }
 }
 
+#ifdef CONFIG_QUOTA
+static void handle_quota_files(struct super_block *s, char **qf_names,
+                              unsigned int *qfmt)
+{
+       int i;
+
+       for (i = 0; i < MAXQUOTAS; i++) {
+               if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
+                       kfree(REISERFS_SB(s)->s_qf_names[i]);
+               REISERFS_SB(s)->s_qf_names[i] = qf_names[i];
+       }
+       REISERFS_SB(s)->s_jquota_fmt = *qfmt;
+}
+#endif
+
 static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 {
        struct reiserfs_super_block *rs;
@@ -1141,23 +1169,30 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        struct reiserfs_journal *journal = SB_JOURNAL(s);
        char *new_opts = kstrdup(arg, GFP_KERNEL);
        int err;
+       char *qf_names[MAXQUOTAS];
+       unsigned int qfmt = 0;
 #ifdef CONFIG_QUOTA
        int i;
+
+       memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names));
 #endif
 
        rs = SB_DISK_SUPER_BLOCK(s);
 
        if (!reiserfs_parse_options
-           (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) {
+           (s, arg, &mount_options, &blocks, NULL, &commit_max_age,
+           qf_names, &qfmt)) {
 #ifdef CONFIG_QUOTA
-               for (i = 0; i < MAXQUOTAS; i++) {
-                       kfree(REISERFS_SB(s)->s_qf_names[i]);
-                       REISERFS_SB(s)->s_qf_names[i] = NULL;
-               }
+               for (i = 0; i < MAXQUOTAS; i++)
+                       if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
+                               kfree(qf_names[i]);
 #endif
                err = -EINVAL;
                goto out_err;
        }
+#ifdef CONFIG_QUOTA
+       handle_quota_files(s, qf_names, &qfmt);
+#endif
 
        handle_attrs(s);
 
@@ -1570,6 +1605,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        char *jdev_name;
        struct reiserfs_sb_info *sbi;
        int errval = -EINVAL;
+       char *qf_names[MAXQUOTAS] = {};
+       unsigned int qfmt = 0;
 
        save_mount_options(s, data);
 
@@ -1597,9 +1634,12 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        jdev_name = NULL;
        if (reiserfs_parse_options
            (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
-            &commit_max_age) == 0) {
+            &commit_max_age, qf_names, &qfmt) == 0) {
                goto error;
        }
+#ifdef CONFIG_QUOTA
+       handle_quota_files(s, qf_names, &qfmt);
+#endif
 
        if (blocks) {
                SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option "
@@ -1819,7 +1859,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 
        return (0);
 
-      error:
+error:
        if (jinit_done) {       /* kill the commit thread, free journal ram */
                journal_release_error(NULL, s);
        }
@@ -1830,10 +1870,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 #ifdef CONFIG_QUOTA
        {
                int j;
-               for (j = 0; j < MAXQUOTAS; j++) {
-                       kfree(sbi->s_qf_names[j]);
-                       sbi->s_qf_names[j] = NULL;
-               }
+               for (j = 0; j < MAXQUOTAS; j++)
+                       kfree(qf_names[j]);
        }
 #endif
        kfree(sbi);
@@ -1980,7 +2018,7 @@ static int reiserfs_release_dquot(struct dquot *dquot)
 
 static int reiserfs_mark_dquot_dirty(struct dquot *dquot)
 {
-       /* Are we journalling quotas? */
+       /* Are we journaling quotas? */
        if (REISERFS_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
            REISERFS_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
                dquot_mark_dquot_dirty(dquot);
@@ -2026,6 +2064,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
        int err;
        struct nameidata nd;
        struct inode *inode;
+       struct reiserfs_transaction_handle th;
 
        if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA)))
                return -EINVAL;
@@ -2053,17 +2092,28 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
                }
                mark_inode_dirty(inode);
        }
-       /* Not journalling quota? No more tests needed... */
-       if (!REISERFS_SB(sb)->s_qf_names[USRQUOTA] &&
-           !REISERFS_SB(sb)->s_qf_names[GRPQUOTA]) {
-               path_put(&nd.path);
-               return vfs_quota_on(sb, type, format_id, path, 0);
-       }
-       /* Quotafile not of fs root? */
-       if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
-               reiserfs_warning(sb,
+       /* Journaling quota? */
+       if (REISERFS_SB(sb)->s_qf_names[type]) {
+               /* Quotafile not of fs root? */
+               if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+                       reiserfs_warning(sb,
                                 "reiserfs: Quota file not on filesystem root. "
                                 "Journalled quota will not work.");
+       }
+
+       /*
+        * When we journal data on quota file, we have to flush journal to see
+        * all updates to the file when we bypass pagecache...
+        */
+       if (reiserfs_file_data_log(inode)) {
+               /* Just start temporary transaction and finish it */
+               err = journal_begin(&th, sb, 1);
+               if (err)
+                       return err;
+               err = journal_end_sync(&th, sb, 1);
+               if (err)
+                       return err;
+       }
        path_put(&nd.path);
        return vfs_quota_on(sb, type, format_id, path, 0);
 }
index d7c4935c1034b58d8a5399dcd22d63b2d645cc41..bb3cb5b7cdb2479d1b68b9eb2fa2521e54810490 100644 (file)
@@ -1250,7 +1250,7 @@ static int reiserfs_check_acl(struct inode *inode, int mask)
        return error;
 }
 
-int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+int reiserfs_permission(struct inode *inode, int mask)
 {
        /*
         * We don't do permission checks on the internal objects.
index 5e90a95ad60b5208d22cac6c0722fd1494af3e8a..056008db13775ccf235b6b2b3822f66efe9fb825 100644 (file)
@@ -6,8 +6,6 @@
 #include <linux/reiserfs_xattr.h>
 #include <asm/uaccess.h>
 
-#define XATTR_SECURITY_PREFIX "security."
-
 static int
 security_get(struct inode *inode, const char *name, void *buffer, size_t size)
 {
index 024a938ca60f1a77238703f648f78733f64f8df4..60abe2bb1f980bbb11de6d2b161ea16946bc595a 100644 (file)
@@ -7,8 +7,6 @@
 #include <linux/reiserfs_xattr.h>
 #include <asm/uaccess.h>
 
-#define XATTR_TRUSTED_PREFIX "trusted."
-
 static int
 trusted_get(struct inode *inode, const char *name, void *buffer, size_t size)
 {
index 073f39364b1136dcd9cbb808f5820b3e5581ff58..1384efcb938e078d882587ee9e84e1de10090bb2 100644 (file)
@@ -10,8 +10,6 @@
 # include <linux/reiserfs_acl.h>
 #endif
 
-#define XATTR_USER_PREFIX "user."
-
 static int
 user_get(struct inode *inode, const char *name, void *buffer, size_t size)
 {
index 3f13d491c7c70ba1343a66f87c0df5c3a093b20f..8e51a2aaa9772546c7071ac135383e6068f82f87 100644 (file)
@@ -577,7 +577,7 @@ static void romfs_destroy_inode(struct inode *inode)
        kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct romfs_inode_info *ei = foo;
 
index 619725644c75e4b30d5ba379f9d40a391466efdb..9c39bc7f843137cf167476797554697ce5834da5 100644 (file)
@@ -205,11 +205,19 @@ static const struct file_operations signalfd_fops = {
        .read           = signalfd_read,
 };
 
-asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask)
+asmlinkage long sys_signalfd4(int ufd, sigset_t __user *user_mask,
+                             size_t sizemask, int flags)
 {
        sigset_t sigmask;
        struct signalfd_ctx *ctx;
 
+       /* Check the SFD_* constants for consistency.  */
+       BUILD_BUG_ON(SFD_CLOEXEC != O_CLOEXEC);
+       BUILD_BUG_ON(SFD_NONBLOCK != O_NONBLOCK);
+
+       if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))
+               return -EINVAL;
+
        if (sizemask != sizeof(sigset_t) ||
            copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
                return -EINVAL;
@@ -227,7 +235,8 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
                 * When we call this, the initialization must be complete, since
                 * anon_inode_getfd() will install the fd.
                 */
-               ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx);
+               ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
+                                      flags & (O_CLOEXEC | O_NONBLOCK));
                if (ufd < 0)
                        kfree(ctx);
        } else {
@@ -249,3 +258,9 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
 
        return ufd;
 }
+
+asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask,
+                            size_t sizemask)
+{
+       return sys_signalfd4(ufd, user_mask, sizemask, 0);
+}
index 8182f0542a2176aadc221c40d65dfec7e4bb382e..8c177eb7e3447175158f77aecb28be5e678bd770 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/dirent.h>
 #include <linux/smb_fs.h>
 #include <linux/pagemap.h>
 #include <linux/net.h>
index 2294783320cbd14a1b88cd2822122bed664e42cf..e4f8d51a5553651bd0235b2d4310ac9c44f32fb6 100644 (file)
@@ -408,7 +408,7 @@ smb_file_release(struct inode *inode, struct file * file)
  * privileges, so we need our own check for this.
  */
 static int
-smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
+smb_file_permission(struct inode *inode, int mask)
 {
        int mode = inode->i_mode;
        int error = 0;
@@ -417,7 +417,7 @@ smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
 
        /* Look at user permissions */
        mode >>= 6;
-       if ((mode & 7 & mask) != mask)
+       if (mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC))
                error = -EACCES;
        return error;
 }
index 376ef3ee6ed7b004807e52f61ac077a7e759df1d..3528f40ffb0f0c137dfcd32b6e69a928dee5e400 100644 (file)
@@ -67,7 +67,7 @@ static void smb_destroy_inode(struct inode *inode)
        kmem_cache_free(smb_inode_cachep, SMB_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct smb_inode_info *ei = (struct smb_inode_info *) foo;
 
index d517a27b7f4b7baeefb6048aef46a20d03293b21..ee536e8a649a28710fe89417265fc5bce0a1119d 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/dcache.h>
-#include <linux/dirent.h>
 #include <linux/nls.h>
 #include <linux/smp_lock.h>
 #include <linux/net.h>
index 399442179d89d5821b4caccc488fb0180e4e35c0..b30311ba8af6ff23ee45af51d07655e68c98fad2 100644 (file)
@@ -772,7 +772,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
        ssize_t ret;
        int err;
 
-       err = remove_suid(out->f_path.dentry);
+       err = file_remove_suid(out);
        if (unlikely(err))
                return err;
 
@@ -830,7 +830,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
        ssize_t ret;
 
        inode_double_lock(inode, pipe->inode);
-       ret = remove_suid(out->f_path.dentry);
+       ret = file_remove_suid(out);
        if (likely(!ret))
                ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
        inode_double_unlock(inode, pipe->inode);
@@ -1160,36 +1160,6 @@ static long do_splice(struct file *in, loff_t __user *off_in,
        return -EINVAL;
 }
 
-/*
- * Do a copy-from-user while holding the mmap_semaphore for reading, in a
- * manner safe from deadlocking with simultaneous mmap() (grabbing mmap_sem
- * for writing) and page faulting on the user memory pointed to by src.
- * This assumes that we will very rarely hit the partial != 0 path, or this
- * will not be a win.
- */
-static int copy_from_user_mmap_sem(void *dst, const void __user *src, size_t n)
-{
-       int partial;
-
-       if (!access_ok(VERIFY_READ, src, n))
-               return -EFAULT;
-
-       pagefault_disable();
-       partial = __copy_from_user_inatomic(dst, src, n);
-       pagefault_enable();
-
-       /*
-        * Didn't copy everything, drop the mmap_sem and do a faulting copy
-        */
-       if (unlikely(partial)) {
-               up_read(&current->mm->mmap_sem);
-               partial = copy_from_user(dst, src, n);
-               down_read(&current->mm->mmap_sem);
-       }
-
-       return partial;
-}
-
 /*
  * Map an iov into an array of pages and offset/length tupples. With the
  * partial_page structure, we can map several non-contiguous ranges into
@@ -1203,8 +1173,6 @@ static int get_iovec_page_array(const struct iovec __user *iov,
 {
        int buffers = 0, error = 0;
 
-       down_read(&current->mm->mmap_sem);
-
        while (nr_vecs) {
                unsigned long off, npages;
                struct iovec entry;
@@ -1213,7 +1181,7 @@ static int get_iovec_page_array(const struct iovec __user *iov,
                int i;
 
                error = -EFAULT;
-               if (copy_from_user_mmap_sem(&entry, iov, sizeof(entry)))
+               if (copy_from_user(&entry, iov, sizeof(entry)))
                        break;
 
                base = entry.iov_base;
@@ -1247,9 +1215,8 @@ static int get_iovec_page_array(const struct iovec __user *iov,
                if (npages > PIPE_BUFFERS - buffers)
                        npages = PIPE_BUFFERS - buffers;
 
-               error = get_user_pages(current, current->mm,
-                                      (unsigned long) base, npages, 0, 0,
-                                      &pages[buffers], NULL);
+               error = get_user_pages_fast((unsigned long)base, npages,
+                                       0, &pages[buffers]);
 
                if (unlikely(error <= 0))
                        break;
@@ -1288,8 +1255,6 @@ static int get_iovec_page_array(const struct iovec __user *iov,
                iov++;
        }
 
-       up_read(&current->mm->mmap_sem);
-
        if (buffers)
                return buffers;
 
index 9cf41f719d50d18adf2fca7a6582b0ecfdc506aa..7c46fbeb8b762e0f125a594a6fd27747ff160c55 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -57,13 +57,13 @@ EXPORT_SYMBOL(vfs_getattr);
 
 int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
+       error = user_path_at(dfd, name, LOOKUP_FOLLOW, &path);
        if (!error) {
-               error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat);
-               path_put(&nd.path);
+               error = vfs_getattr(path.mnt, path.dentry, stat);
+               path_put(&path);
        }
        return error;
 }
@@ -77,13 +77,13 @@ EXPORT_SYMBOL(vfs_stat);
 
 int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = __user_walk_fd(dfd, name, 0, &nd);
+       error = user_path_at(dfd, name, 0, &path);
        if (!error) {
-               error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat);
-               path_put(&nd.path);
+               error = vfs_getattr(path.mnt, path.dentry, stat);
+               path_put(&path);
        }
        return error;
 }
@@ -291,29 +291,29 @@ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
        return error;
 }
 
-asmlinkage long sys_readlinkat(int dfd, const char __user *path,
+asmlinkage long sys_readlinkat(int dfd, const char __user *pathname,
                                char __user *buf, int bufsiz)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
        if (bufsiz <= 0)
                return -EINVAL;
 
-       error = __user_walk_fd(dfd, path, 0, &nd);
+       error = user_path_at(dfd, pathname, 0, &path);
        if (!error) {
-               struct inode *inode = nd.path.dentry->d_inode;
+               struct inode *inode = path.dentry->d_inode;
 
                error = -EINVAL;
                if (inode->i_op && inode->i_op->readlink) {
-                       error = security_inode_readlink(nd.path.dentry);
+                       error = security_inode_readlink(path.dentry);
                        if (!error) {
-                               touch_atime(nd.path.mnt, nd.path.dentry);
-                               error = inode->i_op->readlink(nd.path.dentry,
+                               touch_atime(path.mnt, path.dentry);
+                               error = inode->i_op->readlink(path.dentry,
                                                              buf, bufsiz);
                        }
                }
-               path_put(&nd.path);
+               path_put(&path);
        }
        return error;
 }
index 453877c5697be1b927bc8b9654f98f9cad71644b..e931ae9511fef01f5ae98ea477b89f491a73bb00 100644 (file)
@@ -70,6 +70,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
                INIT_LIST_HEAD(&s->s_instances);
                INIT_HLIST_HEAD(&s->s_anon);
                INIT_LIST_HEAD(&s->s_inodes);
+               INIT_LIST_HEAD(&s->s_dentry_lru);
                init_rwsem(&s->s_umount);
                mutex_init(&s->s_lock);
                lockdep_set_class(&s->s_umount, &type->s_umount_key);
index 228e17b5e9ee911c2c2f58b4090e33b96954ff23..2967562d416fb52e54a1af5840d0dc63c0d25cfb 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -139,7 +139,8 @@ asmlinkage long sys_fdatasync(unsigned int fd)
  * before performing the write.
  *
  * SYNC_FILE_RANGE_WRITE: initiate writeout of all those dirty pages in the
- * range which are not presently under writeback.
+ * range which are not presently under writeback. Note that this may block for
+ * significant periods due to exhaustion of disk request structures.
  *
  * SYNC_FILE_RANGE_WAIT_AFTER: wait upon writeout of all pages in the range
  * after performing the write.
index c1a7efb310bf3517ab1bf52bb1312a79a517f2d6..aedaeba82ae5503a41cbd6ee366601ecb67ae31b 100644 (file)
@@ -459,11 +459,8 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
        int ret;
 
        ret = __sysfs_add_one(acxt, sd);
-       if (ret == -EEXIST) {
-               printk(KERN_WARNING "sysfs: duplicate filename '%s' "
+       WARN(ret == -EEXIST, KERN_WARNING "sysfs: duplicate filename '%s' "
                       "can not be created\n", sd->s_name);
-               WARN_ON(1);
-       }
        return ret;
 }
 
index 3f07893ff8968a483f4c5fc45646c80e3535966f..c9e4e5091da14c24b185b67419f3207188150f96 100644 (file)
@@ -337,9 +337,8 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
        if (kobj->ktype && kobj->ktype->sysfs_ops)
                ops = kobj->ktype->sysfs_ops;
        else {
-               printk(KERN_ERR "missing sysfs attribute operations for "
+               WARN(1, KERN_ERR "missing sysfs attribute operations for "
                       "kobject: %s\n", kobject_name(kobj));
-               WARN_ON(1);
                goto err_out;
        }
 
index eeba38417b1d4c5db2a54e381fb68b8441eb7743..fe611949a7f7419f789dbb8b4335b76d03e9fab9 100644 (file)
@@ -134,9 +134,8 @@ void sysfs_remove_group(struct kobject * kobj,
        if (grp->name) {
                sd = sysfs_get_dirent(dir_sd, grp->name);
                if (!sd) {
-                       printk(KERN_WARNING "sysfs group %p not found for "
+                       WARN(!sd, KERN_WARNING "sysfs group %p not found for "
                                "kobject '%s'\n", grp, kobject_name(kobj));
-                       WARN_ON(!sd);
                        return;
                }
        } else
index c5d60de0658f767cf91d13264c002bb9564d028a..df0d435baa48da3088b16cad08d982c329bc1227 100644 (file)
@@ -326,7 +326,7 @@ static void sysv_destroy_inode(struct inode *inode)
        kmem_cache_free(sysv_inode_cachep, SYSV_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *p)
+static void init_once(void *p)
 {
        struct sysv_inode_info *si = (struct sysv_inode_info *)p;
 
index d87d354ec42438a4a0794cf964999eb376053c73..c502c60e4f54ddfe6ac9402c2c550a274485b003 100644 (file)
@@ -184,7 +184,11 @@ asmlinkage long sys_timerfd_create(int clockid, int flags)
        int ufd;
        struct timerfd_ctx *ctx;
 
-       if (flags)
+       /* Check the TFD_* constants for consistency.  */
+       BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC);
+       BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK);
+
+       if (flags & ~(TFD_CLOEXEC | TFD_NONBLOCK))
                return -EINVAL;
        if (clockid != CLOCK_MONOTONIC &&
            clockid != CLOCK_REALTIME)
@@ -198,7 +202,8 @@ asmlinkage long sys_timerfd_create(int clockid, int flags)
        ctx->clockid = clockid;
        hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
 
-       ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx);
+       ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
+                              flags & (O_CLOEXEC | O_NONBLOCK));
        if (ufd < 0)
                kfree(ctx);
 
index 005a3b854d96ad120098f750e0ef17d540a4abe1..8565e586e533bdafae604abfda4d06b369025bb9 100644 (file)
@@ -53,6 +53,7 @@
 
 #include "ubifs.h"
 #include <linux/mount.h>
+#include <linux/namei.h>
 
 static int read_block(struct inode *inode, void *addr, unsigned int block,
                      struct ubifs_data_node *dn)
index 00eb9c68ad03512ef40ebf98acf77e83bbc13345..ca1e2d4e03cc74fa82dbf2eed84f3d2e01aadf98 100644 (file)
@@ -1841,7 +1841,7 @@ static struct file_system_type ubifs_fs_type = {
 /*
  * Inode slab cache constructor.
  */
-static void inode_slab_ctor(struct kmem_cache *cachep, void *obj)
+static void inode_slab_ctor(void *obj)
 {
        struct ubifs_inode *ui = obj;
        inode_init_once(&ui->vfs_inode);
index 44cc702f96cc994919170bbee7621c841347b0ea..5698bbf83bbff90565ad75e46e04d037c457135d 100644 (file)
@@ -148,7 +148,7 @@ static void udf_destroy_inode(struct inode *inode)
        kmem_cache_free(udf_inode_cachep, UDF_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct udf_inode_info *ei = (struct udf_inode_info *)foo;
 
index 85b22b5977fa3d5c1d3eda3874742baf07a7d480..3e30e40aa24d04c454612565ba746f72dabfc652 100644 (file)
@@ -76,6 +76,7 @@
 
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/stat.h>
@@ -1232,7 +1233,7 @@ static int ufs_show_options(struct seq_file *seq, struct vfsmount *vfs)
 {
        struct ufs_sb_info *sbi = UFS_SB(vfs->mnt_sb);
        unsigned mval = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE;
-       struct match_token *tp = tokens;
+       const struct match_token *tp = tokens;
 
        while (tp->token != Opt_onerror_panic && tp->token != mval)
                ++tp;
@@ -1301,7 +1302,7 @@ static void ufs_destroy_inode(struct inode *inode)
        kmem_cache_free(ufs_inode_cachep, UFS_I(inode));
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct ufs_inode_info *ei = (struct ufs_inode_info *) foo;
 
index b6b664e7145ec7e0debea47c041b7c3faa9a0aee..6929e3e91d0579d28c6cd4453554a4c559236736 100644 (file)
@@ -48,66 +48,22 @@ static bool nsec_valid(long nsec)
        return nsec >= 0 && nsec <= 999999999;
 }
 
-/* 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 timespec *times, int flags)
+static int utimes_common(struct path *path, struct timespec *times)
 {
        int error;
-       struct nameidata nd;
-       struct dentry *dentry;
-       struct inode *inode;
        struct iattr newattrs;
-       struct file *f = NULL;
-       struct vfsmount *mnt;
-
-       error = -EINVAL;
-       if (times && (!nsec_valid(times[0].tv_nsec) ||
-                     !nsec_valid(times[1].tv_nsec))) {
-               goto out;
-       }
-
-       if (flags & ~AT_SYMLINK_NOFOLLOW)
-               goto out;
-
-       if (filename == NULL && dfd != AT_FDCWD) {
-               error = -EINVAL;
-               if (flags & AT_SYMLINK_NOFOLLOW)
-                       goto out;
+       struct inode *inode = path->dentry->d_inode;
 
-               error = -EBADF;
-               f = fget(dfd);
-               if (!f)
-                       goto out;
-               dentry = f->f_path.dentry;
-               mnt = f->f_path.mnt;
-       } else {
-               error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
-               if (error)
-                       goto out;
-
-               dentry = nd.path.dentry;
-               mnt = nd.path.mnt;
-       }
-
-       inode = dentry->d_inode;
-
-       error = mnt_want_write(mnt);
+       error = mnt_want_write(path->mnt);
        if (error)
-               goto dput_and_out;
+               goto out;
 
        if (times && times[0].tv_nsec == UTIME_NOW &&
                     times[1].tv_nsec == UTIME_NOW)
                times = NULL;
 
-       /* In most cases, 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 mnt_drop_write_and_out;
-
                if (times[0].tv_nsec == UTIME_OMIT)
                        newattrs.ia_valid &= ~ATTR_ATIME;
                else if (times[0].tv_nsec != UTIME_NOW) {
@@ -123,21 +79,13 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
                        newattrs.ia_mtime.tv_nsec = times[1].tv_nsec;
                        newattrs.ia_valid |= ATTR_MTIME_SET;
                }
-
                /*
-                * For the UTIME_OMIT/UTIME_NOW and UTIME_NOW/UTIME_OMIT
-                * cases, we need to make an extra check that is not done by
-                * inode_change_ok().
+                * Tell inode_change_ok(), that this is an explicit time
+                * update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET
+                * were used.
                 */
-               if (((times[0].tv_nsec == UTIME_NOW &&
-                           times[1].tv_nsec == UTIME_OMIT)
-                    ||
-                    (times[0].tv_nsec == UTIME_OMIT &&
-                           times[1].tv_nsec == UTIME_NOW))
-                   && !is_owner_or_cap(inode))
-                       goto mnt_drop_write_and_out;
+               newattrs.ia_valid |= ATTR_TIMES_SET;
        } else {
-
                /*
                 * If times is NULL (or both times are UTIME_NOW),
                 * then we need to check permissions, because
@@ -148,21 +96,76 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
                        goto mnt_drop_write_and_out;
 
                if (!is_owner_or_cap(inode)) {
-                       error = permission(inode, MAY_WRITE, NULL);
+                       error = inode_permission(inode, MAY_WRITE);
                        if (error)
                                goto mnt_drop_write_and_out;
                }
        }
        mutex_lock(&inode->i_mutex);
-       error = notify_change(dentry, &newattrs);
+       error = notify_change(path->dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
+
 mnt_drop_write_and_out:
-       mnt_drop_write(mnt);
-dput_and_out:
-       if (f)
-               fput(f);
-       else
-               path_put(&nd.path);
+       mnt_drop_write(path->mnt);
+out:
+       return error;
+}
+
+/*
+ * do_utimes - change times on filename or file descriptor
+ * @dfd: open file descriptor, -1 or AT_FDCWD
+ * @filename: path name or NULL
+ * @times: new times or NULL
+ * @flags: zero or more flags (only AT_SYMLINK_NOFOLLOW for the moment)
+ *
+ * If filename is NULL and dfd refers to an open file, then operate on
+ * the file.  Otherwise look up filename, possibly using dfd as a
+ * starting point.
+ *
+ * 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 timespec *times, int flags)
+{
+       int error = -EINVAL;
+
+       if (times && (!nsec_valid(times[0].tv_nsec) ||
+                     !nsec_valid(times[1].tv_nsec))) {
+               goto out;
+       }
+
+       if (flags & ~AT_SYMLINK_NOFOLLOW)
+               goto out;
+
+       if (filename == NULL && dfd != AT_FDCWD) {
+               struct file *file;
+
+               if (flags & AT_SYMLINK_NOFOLLOW)
+                       goto out;
+
+               file = fget(dfd);
+               error = -EBADF;
+               if (!file)
+                       goto out;
+
+               error = utimes_common(&file->f_path, times);
+               fput(file);
+       } else {
+               struct path path;
+               int lookup_flags = 0;
+
+               if (!(flags & AT_SYMLINK_NOFOLLOW))
+                       lookup_flags |= LOOKUP_FOLLOW;
+
+               error = user_path_at(dfd, filename, lookup_flags, &path);
+               if (error)
+                       goto out;
+
+               error = utimes_common(&path, times);
+               path_put(&path);
+       }
+
 out:
        return error;
 }
index b546ba69be8224f79253e75770a93ff2fdb8a621..155c10b4adbd4a0d3e518b7558d07e4501bee11b 100644 (file)
@@ -621,7 +621,7 @@ shortname:
        memcpy(de->name, msdos_name, MSDOS_NAME);
        de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
        de->lcase = lcase;
-       fat_date_unix2dos(ts->tv_sec, &time, &date);
+       fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
        de->time = de->ctime = time;
        de->date = de->cdate = de->adate = date;
        de->ctime_cs = 0;
index 4706a8b1f4959cdf955cc8b625ee5bac3b53ccf7..468377e665314434fd4f5aa6fe407f50a68096fc 100644 (file)
@@ -63,7 +63,7 @@ xattr_permission(struct inode *inode, const char *name, int mask)
                        return -EPERM;
        }
 
-       return permission(inode, mask, NULL);
+       return inode_permission(inode, mask);
 }
 
 int
@@ -252,40 +252,40 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
 }
 
 asmlinkage long
-sys_setxattr(const char __user *path, const char __user *name,
+sys_setxattr(const char __user *pathname, const char __user *name,
             const void __user *value, size_t size, int flags)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (error)
                return error;
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (!error) {
-               error = setxattr(nd.path.dentry, name, value, size, flags);
-               mnt_drop_write(nd.path.mnt);
+               error = setxattr(path.dentry, name, value, size, flags);
+               mnt_drop_write(path.mnt);
        }
-       path_put(&nd.path);
+       path_put(&path);
        return error;
 }
 
 asmlinkage long
-sys_lsetxattr(const char __user *path, const char __user *name,
+sys_lsetxattr(const char __user *pathname, const char __user *name,
              const void __user *value, size_t size, int flags)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = user_path_walk_link(path, &nd);
+       error = user_lpath(pathname, &path);
        if (error)
                return error;
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (!error) {
-               error = setxattr(nd.path.dentry, name, value, size, flags);
-               mnt_drop_write(nd.path.mnt);
+               error = setxattr(path.dentry, name, value, size, flags);
+               mnt_drop_write(path.mnt);
        }
-       path_put(&nd.path);
+       path_put(&path);
        return error;
 }
 
@@ -350,32 +350,32 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
 }
 
 asmlinkage ssize_t
-sys_getxattr(const char __user *path, const char __user *name,
+sys_getxattr(const char __user *pathname, const char __user *name,
             void __user *value, size_t size)
 {
-       struct nameidata nd;
+       struct path path;
        ssize_t error;
 
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (error)
                return error;
-       error = getxattr(nd.path.dentry, name, value, size);
-       path_put(&nd.path);
+       error = getxattr(path.dentry, name, value, size);
+       path_put(&path);
        return error;
 }
 
 asmlinkage ssize_t
-sys_lgetxattr(const char __user *path, const char __user *name, void __user *value,
+sys_lgetxattr(const char __user *pathname, const char __user *name, void __user *value,
              size_t size)
 {
-       struct nameidata nd;
+       struct path path;
        ssize_t error;
 
-       error = user_path_walk_link(path, &nd);
+       error = user_lpath(pathname, &path);
        if (error)
                return error;
-       error = getxattr(nd.path.dentry, name, value, size);
-       path_put(&nd.path);
+       error = getxattr(path.dentry, name, value, size);
+       path_put(&path);
        return error;
 }
 
@@ -425,30 +425,30 @@ listxattr(struct dentry *d, char __user *list, size_t size)
 }
 
 asmlinkage ssize_t
-sys_listxattr(const char __user *path, char __user *list, size_t size)
+sys_listxattr(const char __user *pathname, char __user *list, size_t size)
 {
-       struct nameidata nd;
+       struct path path;
        ssize_t error;
 
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (error)
                return error;
-       error = listxattr(nd.path.dentry, list, size);
-       path_put(&nd.path);
+       error = listxattr(path.dentry, list, size);
+       path_put(&path);
        return error;
 }
 
 asmlinkage ssize_t
-sys_llistxattr(const char __user *path, char __user *list, size_t size)
+sys_llistxattr(const char __user *pathname, char __user *list, size_t size)
 {
-       struct nameidata nd;
+       struct path path;
        ssize_t error;
 
-       error = user_path_walk_link(path, &nd);
+       error = user_lpath(pathname, &path);
        if (error)
                return error;
-       error = listxattr(nd.path.dentry, list, size);
-       path_put(&nd.path);
+       error = listxattr(path.dentry, list, size);
+       path_put(&path);
        return error;
 }
 
@@ -486,38 +486,38 @@ removexattr(struct dentry *d, const char __user *name)
 }
 
 asmlinkage long
-sys_removexattr(const char __user *path, const char __user *name)
+sys_removexattr(const char __user *pathname, const char __user *name)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = user_path_walk(path, &nd);
+       error = user_path(pathname, &path);
        if (error)
                return error;
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (!error) {
-               error = removexattr(nd.path.dentry, name);
-               mnt_drop_write(nd.path.mnt);
+               error = removexattr(path.dentry, name);
+               mnt_drop_write(path.mnt);
        }
-       path_put(&nd.path);
+       path_put(&path);
        return error;
 }
 
 asmlinkage long
-sys_lremovexattr(const char __user *path, const char __user *name)
+sys_lremovexattr(const char __user *pathname, const char __user *name)
 {
-       struct nameidata nd;
+       struct path path;
        int error;
 
-       error = user_path_walk_link(path, &nd);
+       error = user_lpath(pathname, &path);
        if (error)
                return error;
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (!error) {
-               error = removexattr(nd.path.dentry, name);
-               mnt_drop_write(nd.path.mnt);
+               error = removexattr(path.dentry, name);
+               mnt_drop_write(path.mnt);
        }
-       path_put(&nd.path);
+       path_put(&path);
        return error;
 }
 
index 5e9564902976e0f1d76fbfbb0cb4565afcf36def..a20683cf74ddde496cd78dbbeb09988559bfd35d 100644 (file)
@@ -79,7 +79,7 @@ kmem_zone_init(int size, char *zone_name)
 
 static inline kmem_zone_t *
 kmem_zone_init_flags(int size, char *zone_name, unsigned long flags,
-                    void (*construct)(kmem_zone_t *, void *))
+                    void (*construct)(void *))
 {
        return kmem_cache_create(zone_name, size, 0, flags, construct);
 }
index a42ba9d71156f84101e1068a33d4bd05e055bcd9..01939ba2d8dea65c43b04b0754b9df4513e8864e 100644 (file)
@@ -84,17 +84,15 @@ xfs_find_handle(
        switch (cmd) {
        case XFS_IOC_PATH_TO_FSHANDLE:
        case XFS_IOC_PATH_TO_HANDLE: {
-               struct nameidata        nd;
-               int                     error;
-
-               error = user_path_walk_link((const char __user *)hreq.path, &nd);
+               struct path path;
+               int error = user_lpath((const char __user *)hreq.path, &path);
                if (error)
                        return error;
 
-               ASSERT(nd.path.dentry);
-               ASSERT(nd.path.dentry->d_inode);
-               inode = igrab(nd.path.dentry->d_inode);
-               path_put(&nd.path);
+               ASSERT(path.dentry);
+               ASSERT(path.dentry->d_inode);
+               inode = igrab(path.dentry->d_inode);
+               path_put(&path);
                break;
        }
 
index 2bf287ef54897af2651f24b39792404270179a19..5fc61c824bb9bbe1b53cca02ab6b72c427c900db 100644 (file)
@@ -589,8 +589,7 @@ xfs_check_acl(
 STATIC int
 xfs_vn_permission(
        struct inode            *inode,
-       int                     mask,
-       struct nameidata        *nd)
+       int                     mask)
 {
        return generic_permission(inode, mask, xfs_check_acl);
 }
index 5e3b57516ec7293fe8bffe42cc995b9025780b8e..82333b3e118e7d6491589c5ad524b179e4feec96 100644 (file)
@@ -711,7 +711,7 @@ start:
             !capable(CAP_FSETID)) {
                error = xfs_write_clear_setuid(xip);
                if (likely(!error))
-                       error = -remove_suid(file->f_path.dentry);
+                       error = -file_remove_suid(file);
                if (unlikely(error)) {
                        goto out_unlock_internal;
                }
index 742b2c7852c1bc947ae93e3a11dd499cecab8fdb..943381284e2e842245b42137b7516c84220cef86 100644 (file)
@@ -843,7 +843,6 @@ xfs_fs_destroy_inode(
 
 STATIC void
 xfs_fs_inode_init_once(
-       kmem_zone_t             *zonep,
        void                    *vnode)
 {
        inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
index bdca155028ecd343b4ebf0182904dc83f1e61469..d8c3e3cbf41603eb983e5922da3ee796c7fece84 100644 (file)
@@ -1,3 +1,6 @@
+# Top-level Makefile calls into asm-$(ARCH)
+# List only non-arch directories below
+
 header-y += asm-generic/
 header-y += linux/
 header-y += sound/
@@ -5,5 +8,3 @@ header-y += mtd/
 header-y += rdma/
 header-y += video/
 header-y += drm/
-
-header-y += asm-$(ARCH)/
index 1ebbe883f7865576d022280a8da0f979e6a3278d..13a3d9ad92db79f57c2063f60be9302d3525e77c 100644 (file)
@@ -277,6 +277,7 @@ enum acpi_prefered_pm_profiles {
 #define BAF_LEGACY_DEVICES              0x0001
 #define BAF_8042_KEYBOARD_CONTROLLER    0x0002
 #define BAF_MSI_NOT_SUPPORTED           0x0008
+#define BAF_PCIE_ASPM_CONTROL           0x0010
 
 #define FADT2_REVISION_ID               3
 #define FADT2_MINUS_REVISION_ID         2
index db351d1296f4bb13a9dfab082c7ce2dc66969e62..a5801ae02e4be31cb7232626b6f6468a9495244e 100644 (file)
@@ -24,8 +24,8 @@
                pci_unmap_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
 #define dma_supported(dev, mask)                       \
                pci_dma_supported(alpha_gendev_to_pci(dev), mask)
-#define dma_mapping_error(addr)                                \
-               pci_dma_mapping_error(addr)
+#define dma_mapping_error(dev, addr)                           \
+               pci_dma_mapping_error(alpha_gendev_to_pci(dev), addr)
 
 #else  /* no PCI - no IOMMU. */
 
@@ -45,7 +45,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 #define dma_unmap_page(dev, addr, size, dir)   ((void)0)
 #define dma_unmap_sg(dev, sg, nents, dir)      ((void)0)
 
-#define dma_mapping_error(addr)  (0)
+#define dma_mapping_error(dev, addr)  (0)
 
 #endif /* !CONFIG_PCI */
 
diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h
deleted file mode 100644 (file)
index f44129a..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  linux/include/asm-alpha/ide.h
- *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
- */
-
-/*
- *  This file contains the alpha architecture specific IDE code.
- */
-
-#ifndef __ASMalpha_IDE_H
-#define __ASMalpha_IDE_H
-
-#ifdef __KERNEL__
-
-static inline int ide_default_irq(unsigned long base)
-{
-       switch (base) {
-               case 0x1f0: return 14;
-               case 0x170: return 15;
-               case 0x1e8: return 11;
-               case 0x168: return 10;
-               default:
-                       return 0;
-       }
-}
-
-static inline unsigned long ide_default_io_base(int index)
-{
-       switch (index) {
-               case 0: return 0x1f0;
-               case 1: return 0x170;
-               case 2: return 0x1e8;
-               case 3: return 0x168;
-               default:
-                       return 0;
-       }
-}
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASMalpha_IDE_H */
diff --git a/include/asm-alpha/kvm.h b/include/asm-alpha/kvm.h
deleted file mode 100644 (file)
index b9daec4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_ALPHA_H
-#define __LINUX_KVM_ALPHA_H
-
-/* alpha does not support KVM */
-
-#endif
diff --git a/include/asm-alpha/namei.h b/include/asm-alpha/namei.h
deleted file mode 100644 (file)
index 5cc9bb3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $Id: namei.h,v 1.1 1996/12/13 14:48:21 jj Exp $
- * linux/include/asm-alpha/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __ALPHA_NAMEI_H
-#define __ALPHA_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __ALPHA_NAMEI_H */
index 22ff9762d17b63b8379abea371cb816d37dcaae2..0995f9d13417241e283cad83bd4f0729af014c66 100644 (file)
@@ -80,9 +80,6 @@ typedef struct page *pgtable_t;
 
 #endif /* !__ASSEMBLY__ */
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 #define __pa(x)                        ((unsigned long) (x) - PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long) (x) + PAGE_OFFSET))
 #ifndef CONFIG_DISCONTIGMEM
index d31fd49ff79a40fc7d00d22528f9b955739786e9..2a14302c17a337194cf3df0a7d20ae4dfa28273d 100644 (file)
@@ -106,7 +106,7 @@ extern dma_addr_t pci_map_page(struct pci_dev *, struct page *,
 /* Test for pci_map_single or pci_map_page having generated an error.  */
 
 static inline int
-pci_dma_mapping_error(dma_addr_t dma_addr)
+pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr)
 {
        return dma_addr == 0;
 }
diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 08c9793199290fefc36f027da65f7e7e50f9cd43..a1057c2d95e7047e06ab1c9df73392b9f49e8ab6 100644 (file)
@@ -62,4 +62,9 @@
 
 #define SO_MARK                        36
 
+/* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
+ * have to define SOCK_NONBLOCK to a different value here.
+ */
+#define SOCK_NONBLOCK  0x40000000
+
 #endif /* _ASM_SOCKET_H */
index fb3185196298326ee265f2ef87cb148795896a01..15fda434442428660e3d896661ec11c9f134e71e 100644 (file)
@@ -50,10 +50,8 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define current_thread_info()  __current_thread_info
 
 /* Thread information allocation.  */
+#define THREAD_SIZE_ORDER 1
 #define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info(tsk) \
-  ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-arm/arch-at91/at91_ecc.h b/include/asm-arm/arch-at91/at91_ecc.h
deleted file mode 100644 (file)
index 1e5a8ca..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * include/asm-arm/arch-at91/at91_ecc.h
- *
- * Error Corrected Code Controller (ECC) - System peripherals regsters.
- * Based on AT91SAM9260 datasheet revision B.
- *
- * 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 AT91_ECC_H
-#define AT91_ECC_H
-
-#define AT91_ECC_CR            0x00                    /* Control register */
-#define                AT91_ECC_RST            (1 << 0)                /* Reset parity */
-
-#define AT91_ECC_MR            0x04                    /* Mode register */
-#define                AT91_ECC_PAGESIZE       (3 << 0)                /* Page Size */
-#define                        AT91_ECC_PAGESIZE_528           (0)
-#define                        AT91_ECC_PAGESIZE_1056          (1)
-#define                        AT91_ECC_PAGESIZE_2112          (2)
-#define                        AT91_ECC_PAGESIZE_4224          (3)
-
-#define AT91_ECC_SR            0x08                    /* Status register */
-#define                AT91_ECC_RECERR         (1 << 0)                /* Recoverable Error */
-#define                AT91_ECC_ECCERR         (1 << 1)                /* ECC Single Bit Error */
-#define                AT91_ECC_MULERR         (1 << 2)                /* Multiple Errors */
-
-#define AT91_ECC_PR            0x0c                    /* Parity register */
-#define                AT91_ECC_BITADDR        (0xf << 0)              /* Bit Error Address */
-#define                AT91_ECC_WORDADDR       (0xfff << 4)            /* Word Error Address */
-
-#define AT91_ECC_NPR           0x10                    /* NParity register */
-#define                AT91_ECC_NPARITY        (0xffff << 0)           /* NParity */
-
-#endif
index 94de788da76ed55a64b0a1698ff790f322e545cb..48bbd854f57d7690e1f3dbbf34ecf41b65560e4d 100644 (file)
@@ -89,7 +89,7 @@ struct at91_usbh_data {
 extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 
  /* NAND / SmartMedia */
-struct at91_nand_data {
+struct atmel_nand_data {
        u8              enable_pin;     /* chip enable */
        u8              det_pin;        /* card detect */
        u8              rdy_pin;        /* ready/busy */
@@ -98,7 +98,7 @@ struct at91_nand_data {
        u8              bus_width_16;   /* buswidth is 16 bit */
        struct mtd_partition* (*partition_info)(int, int*);
 };
-extern void __init at91_add_device_nand(struct at91_nand_data *data);
+extern void __init at91_add_device_nand(struct atmel_nand_data *data);
 
  /* I2C*/
 extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices);
index 13ec7ed0f501a00e222089efe07a6e9ccd2fbebb..a25d18f2d87a7ba2d4d583c0cc048fd352a6d0d5 100644 (file)
 
 #define PNX4008_IRQ_TYPES \
 {                                           /*IRQ #'s: */         \
-IRQT_LOW,  IRQT_LOW,  IRQT_LOW,  IRQT_HIGH, /*  0, 1, 2, 3 */     \
-IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /*  4, 5, 6, 7 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /*  8, 9,10,11 */     \
-IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 12,13,14,15 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 16,17,18,19 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 20,21,22,23 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 24,25,26,27 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_LOW,  /* 28,29,30,31 */     \
-IRQT_HIGH, IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, /* 32,33,34,35 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_FALLING, IRQT_HIGH, /* 36,37,38,39 */  \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 40,41,42,43 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 44,45,46,47 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_LOW,  /* 48,49,50,51 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 52,53,54,55 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_HIGH, /* 56,57,58,59 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 60,61,62,63 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 64,65,66,67 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 68,69,70,71 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 72,73,74,75 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 76,77,78,79 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 80,81,82,83 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 84,85,86,87 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 88,89,90,91 */     \
-IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 92,93,94,95 */     \
+IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, /*  0, 1, 2, 3 */     \
+IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /*  4, 5, 6, 7 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /*  8, 9,10,11 */     \
+IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 12,13,14,15 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 16,17,18,19 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 20,21,22,23 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 24,25,26,27 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_LOW,  /* 28,29,30,31 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 32,33,34,35 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_LEVEL_HIGH, /* 36,37,38,39 */  \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 40,41,42,43 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 44,45,46,47 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_LOW,  /* 48,49,50,51 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 52,53,54,55 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, /* 56,57,58,59 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 60,61,62,63 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 64,65,66,67 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 68,69,70,71 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 72,73,74,75 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 76,77,78,79 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 80,81,82,83 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 84,85,86,87 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 88,89,90,91 */     \
+IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 92,93,94,95 */     \
 }
 
 /* Start Enable Pin Interrupts - table 58 page 66 */
index b6952534a4e16039775ee1ba60399e548c8e480c..21aa8ac35c1c30df8fe635b9c851ea447afe09ae 100644 (file)
 #define TOUCH_PANEL_IRQ                        IRQ_GPIO(5)
 #define IDE_IRQ                                IRQ_GPIO(21)
 
-#define TOUCH_PANEL_IRQ_EDGE           IRQT_FALLING
+#define TOUCH_PANEL_IRQ_EDGE           IRQ_TYPE_EDGE_FALLING
 
 #define ETHERNET_IRQ                   IRQ_GPIO(4)
-#define ETHERNET_IRQ_EDGE              IRQT_RISING
+#define ETHERNET_IRQ_EDGE              IRQ_TYPE_EDGE_RISING
 
-#define IDE_IRQ_EDGE                   IRQT_RISING
+#define IDE_IRQ_EDGE                   IRQ_TYPE_EDGE_RISING
 
 #define PCMCIA_S0_CD_VALID             IRQ_GPIO(7)
-#define PCMCIA_S0_CD_VALID_EDGE                IRQT_BOTHEDGE
+#define PCMCIA_S0_CD_VALID_EDGE                IRQ_TYPE_EDGE_BOTH
 
 #define PCMCIA_S1_CD_VALID             IRQ_GPIO(8)
-#define PCMCIA_S1_CD_VALID_EDGE                IRQT_BOTHEDGE
+#define PCMCIA_S1_CD_VALID_EDGE                IRQ_TYPE_EDGE_BOTH
 
 #define PCMCIA_S0_RDYINT               IRQ_GPIO(19)
 #define PCMCIA_S1_RDYINT               IRQ_GPIO(22)
index b699d0d7bdb29dd2e01348420f1b8c6b11050554..2e20131790632da57dbe43a1124c82347230a15b 100644 (file)
 /* CPLD's interrupt controller is connected to PCM-027 GPIO 9 */
 #define PCM990_CTRL_INT_IRQ_GPIO       9
 #define PCM990_CTRL_INT_IRQ            IRQ_GPIO(PCM990_CTRL_INT_IRQ_GPIO)
-#define PCM990_CTRL_INT_IRQ_EDGE       IRQT_RISING
+#define PCM990_CTRL_INT_IRQ_EDGE       IRQ_TYPE_EDGE_RISING
 #define PCM990_CTRL_PHYS               PXA_CS1_PHYS    /* 16-Bit */
 #define PCM990_CTRL_BASE               0xea000000
 #define PCM990_CTRL_SIZE               (1*1024*1024)
 
 #define PCM990_CTRL_PWR_IRQ_GPIO       14
 #define PCM990_CTRL_PWR_IRQ            IRQ_GPIO(PCM990_CTRL_PWR_IRQ_GPIO)
-#define PCM990_CTRL_PWR_IRQ_EDGE       IRQT_RISING
+#define PCM990_CTRL_PWR_IRQ_EDGE       IRQ_TYPE_EDGE_RISING
 
 /* visible CPLD (U7) registers */
 #define PCM990_CTRL_REG0       0x0000  /* RESET REGISTER */
  */
 #define PCM990_IDE_IRQ_GPIO    13
 #define PCM990_IDE_IRQ         IRQ_GPIO(PCM990_IDE_IRQ_GPIO)
-#define PCM990_IDE_IRQ_EDGE    IRQT_RISING
+#define PCM990_IDE_IRQ_EDGE    IRQ_TYPE_EDGE_RISING
 #define PCM990_IDE_PLD_PHYS    0x20000000      /* 16 bit wide */
 #define PCM990_IDE_PLD_BASE    0xee000000
 #define PCM990_IDE_PLD_SIZE    (1*1024*1024)
  */
 #define PCM990_CF_IRQ_GPIO     11
 #define PCM990_CF_IRQ          IRQ_GPIO(PCM990_CF_IRQ_GPIO)
-#define PCM990_CF_IRQ_EDGE     IRQT_RISING
+#define PCM990_CF_IRQ_EDGE     IRQ_TYPE_EDGE_RISING
 
 #define PCM990_CF_CD_GPIO      12
 #define PCM990_CF_CD           IRQ_GPIO(PCM990_CF_CD_GPIO)
-#define PCM990_CF_CD_EDGE      IRQT_RISING
+#define PCM990_CF_CD_EDGE      IRQ_TYPE_EDGE_RISING
 
 #define PCM990_CF_PLD_PHYS     0x30000000      /* 16 bit wide */
 #define PCM990_CF_PLD_BASE     0xef000000
  */
 #define PCM990_AC97_IRQ_GPIO   10
 #define PCM990_AC97_IRQ                IRQ_GPIO(PCM990_AC97_IRQ_GPIO)
-#define PCM990_AC97_IRQ_EDGE   IRQT_RISING
+#define PCM990_AC97_IRQ_EDGE   IRQ_TYPE_EDGE_RISING
 
 /*
  * MMC phyCORE
  */
 #define PCM990_MMC0_IRQ_GPIO   9
 #define PCM990_MMC0_IRQ                IRQ_GPIO(PCM990_MMC0_IRQ_GPIO)
-#define PCM990_MMC0_IRQ_EDGE   IRQT_FALLING
+#define PCM990_MMC0_IRQ_EDGE   IRQ_TYPE_EDGE_FALLING
 
 /*
  * USB phyCore
index 840305916b6de86cd35f8bbb02504b7483311265..1b80a4805a604689b49e53090f6630bd251dd9cb 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_ARCH_PXA25X_UDC_H
 
 #ifdef _ASM_ARCH_PXA27X_UDC_H
-#error You can't include both PXA25x and PXA27x UDC support
+#error "You can't include both PXA25x and PXA27x UDC support"
 #endif
 
 #define UDC_RES1       __REG(0x40600004)  /* UDC Undocumented - Reserved1 */
index 352d33860b6383a6584011edb5239b23b3ebcd1b..442169887d3b0d4e810df46059b2c65ca76df64d 100644 (file)
@@ -16,6 +16,7 @@
 struct s3c2410_spi_info {
        unsigned long            pin_cs;        /* simple gpio cs */
        unsigned int             num_cs;        /* total chipselects */
+       int                      bus_num;       /* bus number to use. */
 
        void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
 };
index 1b6355971574a0b2be21a881e4dedb8f45c8d92a..3ca0ecf095e67c9153d845e2cdad49d37093532d 100644 (file)
 #ifndef _INCLUDE_H3600_H_
 #define _INCLUDE_H3600_H_
 
+typedef int __bitwise pm_request_t;
+
+#define PM_SUSPEND     ((__force pm_request_t) 1)      /* enter D1-D3 */
+#define PM_RESUME      ((__force pm_request_t) 2)      /* enter D0 */
+
 /* generalized support for H3xxx series Compaq Pocket PC's */
 #define machine_is_h3xxx() (machine_is_h3100() || machine_is_h3600() || machine_is_h3800())
 
index b14cbda01dc3cce14c715ffef836dde3d1fbabe9..193f6c15f4ddae567dc0b20184b96334e11a71d3 100644 (file)
@@ -61,7 +61,7 @@ ide_init_default_hwifs(void)
 
         /* Enable GPIO as interrupt line */
         GPDR &= ~LART_GPIO_IDE;
-       set_irq_type(LART_IRQ_IDE, IRQT_RISING);
+       set_irq_type(LART_IRQ_IDE, IRQ_TYPE_EDGE_RISING);
 
         /* set PCMCIA interface timing */
         MECR = 0x00060006;
index 5c60bfc1a84ddd92e67a20c0bd82ed194654bfdf..9a1db20e032a07eb744aba50c1c60a28d0a0b381 100644 (file)
@@ -277,9 +277,16 @@ static inline int constant_fls(int x)
  * the clz instruction for much better code efficiency.
  */
 
-#define fls(x) \
+#define __fls(x) \
        ( __builtin_constant_p(x) ? constant_fls(x) : \
          ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }) )
+
+/* Implement fls() in C so that 64-bit args are suitably truncated */
+static inline int fls(int x)
+{
+       return __fls(x);
+}
+
 #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
 #define __ffs(x) (ffs(x) - 1)
 #define ffz(x) __ffs( ~(x) )
index 70b0fe724b62686a3485b66e747b46300117d8ec..e68a1cbcc85209d99fa3a927bb40cb6727690e02 100644 (file)
@@ -424,9 +424,9 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
 }
 
 #define flush_dcache_mmap_lock(mapping) \
-       write_lock_irq(&(mapping)->tree_lock)
+       spin_lock_irq(&(mapping)->tree_lock)
 #define flush_dcache_mmap_unlock(mapping) \
-       write_unlock_irq(&(mapping)->tree_lock)
+       spin_unlock_irq(&(mapping)->tree_lock)
 
 #define flush_icache_user_range(vma,page,addr,len) \
        flush_dcache_page(page)
@@ -459,15 +459,19 @@ static inline void flush_ioremap_region(unsigned long phys, void __iomem *virt,
 #define __cacheid_vivt_asid_tagged_instr(val)  (__cacheid_type_v7(val) ? ((val & (3 << 14)) == (1 << 14)) : 0)
 
 #if defined(CONFIG_CPU_CACHE_VIVT) && !defined(CONFIG_CPU_CACHE_VIPT)
-
+/*
+ * VIVT caches only
+ */
 #define cache_is_vivt()                        1
 #define cache_is_vipt()                        0
 #define cache_is_vipt_nonaliasing()    0
 #define cache_is_vipt_aliasing()       0
 #define icache_is_vivt_asid_tagged()   0
 
-#elif defined(CONFIG_CPU_CACHE_VIPT)
-
+#elif !defined(CONFIG_CPU_CACHE_VIVT) && defined(CONFIG_CPU_CACHE_VIPT)
+/*
+ * VIPT caches only
+ */
 #define cache_is_vivt()                        0
 #define cache_is_vipt()                        1
 #define cache_is_vipt_nonaliasing()                                    \
@@ -489,7 +493,12 @@ static inline void flush_ioremap_region(unsigned long phys, void __iomem *virt,
        })
 
 #else
-
+/*
+ * VIVT or VIPT caches.  Note that this is unreliable since ARM926
+ * and V6 CPUs satisfy the "(val & (15 << 25)) == (14 << 25)" test.
+ * There's no way to tell from the CacheType register what type (!)
+ * the cache is.
+ */
 #define cache_is_vivt()                                                        \
        ({                                                              \
                unsigned int __val = read_cpuid(CPUID_CACHETYPE);       \
index e99406a7bece7264569542b85a72ea8c7d3aaa1e..45329fca1b64e32f18ba9dc711ea8bc89f5d5576 100644 (file)
@@ -7,6 +7,8 @@
 
 #include <linux/scatterlist.h>
 
+#include <asm-generic/dma-coherent.h>
+
 /*
  * DMA-consistent mapping functions.  These allocate/free a region of
  * uncached, unwrite-buffered mapped memory space for use with DMA
@@ -56,7 +58,7 @@ static inline int dma_is_consistent(struct device *dev, dma_addr_t handle)
 /*
  * DMA errors are defined by all-bits-set in the DMA address.
  */
-static inline int dma_mapping_error(dma_addr_t dma_addr)
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return dma_addr == ~0;
 }
index 88f4d231ce4f2579a27cfb9daba5bb824b6c6664..a48019f99d08acd160a2dd098c960dc4c5cdac2a 100644 (file)
 
 #ifdef __KERNEL__
 
-#ifndef MAX_HWIFS
-#define MAX_HWIFS      4
-#endif
-
 #define __ide_mm_insw(port,addr,len)   readsw(port,addr,len)
 #define __ide_mm_insl(port,addr,len)   readsl(port,addr,len)
 #define __ide_mm_outsw(port,addr,len)  writesw(port,addr,len)
index 1b882a255e3515861f9fe58a6112ca747ad54ec3..9cb01907e43bc1eb0ea2c4fce870f853ac221fd2 100644 (file)
 #define NO_IRQ ((unsigned int)(-1))
 #endif
 
-
-/*
- * Migration helpers
- */
-#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING
-#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING
-#define __IRQT_LOWLVL  IRQ_TYPE_LEVEL_LOW
-#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH
-
-#define IRQT_NOEDGE    (0)
-#define IRQT_RISING    (__IRQT_RISEDGE)
-#define IRQT_FALLING   (__IRQT_FALEDGE)
-#define IRQT_BOTHEDGE  (__IRQT_RISEDGE|__IRQT_FALEDGE)
-#define IRQT_LOW       (__IRQT_LOWLVL)
-#define IRQT_HIGH      (__IRQT_HIGHLVL)
-#define IRQT_PROBE     IRQ_TYPE_PROBE
-
 #ifndef __ASSEMBLY__
 struct irqaction;
 extern void migrate_irqs(void);
diff --git a/include/asm-arm/kvm.h b/include/asm-arm/kvm.h
deleted file mode 100644 (file)
index cb3c08c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_ARM_H
-#define __LINUX_KVM_ARM_H
-
-/* arm does not support KVM */
-
-#endif
diff --git a/include/asm-arm/namei.h b/include/asm-arm/namei.h
deleted file mode 100644 (file)
index a402d3b..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 
- * linux/include/asm-arm/namei.h
- *
- * Routines to handle famous /usr/gnemul
- * Derived from the Sparc version of this file
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __ASMARM_NAMEI_H
-#define __ASMARM_NAMEI_H
-
-#define ARM_BSD_EMUL "usr/gnemul/bsd/"
-
-static inline char *__emul_prefix(void)
-{
-       switch (current->personality) {
-       case PER_BSD:
-               return ARM_BSD_EMUL;
-       default:
-               return NULL;
-       }
-}
-
-#endif /* __ASMARM_NAMEI_H */
index a1bcad0604805bc3fbc736bc14c31f80039b6987..ea1cde84f500d96e5dd552b63fc8e0736f593ef2 100644 (file)
@@ -7,6 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
 #ifndef _ASMARM_PAGE_NOMMU_H
 #define _ASMARM_PAGE_NOMMU_H
 
@@ -42,9 +43,6 @@ typedef unsigned long pgprot_t;
 #define __pmd(x)        (x)
 #define __pgprot(x)     (x)
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 extern unsigned long memory_start;
 extern unsigned long memory_end;
 
index 8e05bdb5f12f555f94c66b8ff1c008c3a3a5cb86..7c5fc5582e5dde1cdadbc9d3758a205f7aa5cd61 100644 (file)
@@ -15,9 +15,6 @@
 #define PAGE_SIZE              (1UL << PAGE_SHIFT)
 #define PAGE_MASK              (~(PAGE_SIZE-1))
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 #ifndef __ASSEMBLY__
 
 #ifndef CONFIG_MMU
index 75feb1574a69050845f270f370566ee2b51d1b7b..2d84792f2e12d094095fd2b2b29f1a6cee2c2e3c 100644 (file)
@@ -78,6 +78,14 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
        return root;
 }
 
+/*
+ * Dummy implementation; always return 0.
+ */
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+       return 0;
+}
+
 #endif /* __KERNEL__ */
  
 #endif
index 71211c8b5384a85d76a8b7b03ccf845ac287f0e8..d08a1f2863e472051e3e60327c13b3bfbfcf99d6 100644 (file)
@@ -21,6 +21,7 @@
 */
 
 struct s3c2410_platform_i2c {
+       int             bus_num;        /* bus number to use */
        unsigned int    flags;
        unsigned int    slave_addr;     /* slave address for controller */
        unsigned long   bus_freq;       /* standard bus frequency */
index 7aaa206cb54ef22e8a45d92822b31bc8bda18782..8382b7510f942de6b7d4db7a6e459e9576d64b36 100644 (file)
@@ -139,8 +139,6 @@ static inline int valid_user_regs(struct pt_regs *regs)
        return 0;
 }
 
-#endif /* __KERNEL__ */
-
 #define pc_pointer(v) \
        ((v) & ~PCMASK)
 
@@ -153,10 +151,10 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 #define profile_pc(regs) instruction_pointer(regs)
 #endif
 
-#ifdef __KERNEL__
 #define predicate(x)           ((x) & 0xf0000000)
 #define PREDICATE_ALWAYS       0xe0000000
-#endif
+
+#endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index f5a6647863114ccfe5fa8f88a8bab88ce29b48aa..d4be2d64616087a4ebf3bf2427d399314c6584b3 100644 (file)
@@ -97,19 +97,6 @@ static inline struct thread_info *current_thread_info(void)
        return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
 }
 
-/* thread information allocation */
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) \
-       ((struct thread_info *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, \
-               THREAD_SIZE_ORDER))
-#else
-#define alloc_thread_info(tsk) \
-       ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
-#endif
-
-#define free_thread_info(info) \
-       free_pages((unsigned long)info, THREAD_SIZE_ORDER);
-
 #define thread_saved_pc(tsk)   \
        ((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc)))
 #define thread_saved_fp(tsk)   \
index a3783861cdd269ab80101e1a2acdf162f8fdecef..e60e9076544d08ace7891dbe1d1ffbf31df4f45f 100644 (file)
@@ -82,7 +82,15 @@ struct mci_platform_data;
 struct platform_device *
 at32_add_device_mci(unsigned int id, struct mci_platform_data *data);
 
-struct platform_device *at32_add_device_ac97c(unsigned int id);
+struct ac97c_platform_data {
+       unsigned short dma_rx_periph_id;
+       unsigned short dma_tx_periph_id;
+       unsigned short dma_controller_id;
+       int reset_pin;
+};
+struct platform_device *
+at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data);
+
 struct platform_device *at32_add_device_abdac(unsigned int id);
 struct platform_device *at32_add_device_psif(unsigned int id);
 
@@ -97,4 +105,17 @@ struct platform_device *
 at32_add_device_cf(unsigned int id, unsigned int extint,
                struct cf_platform_data *data);
 
+/* NAND / SmartMedia */
+struct atmel_nand_data {
+       int     enable_pin;     /* chip enable */
+       int     det_pin;        /* card detect */
+       int     rdy_pin;        /* ready/busy */
+       u8      ale;            /* address line number connected to ALE */
+       u8      cle;            /* address line number connected to CLE */
+       u8      bus_width_16;   /* buswidth is 16 bit */
+       struct mtd_partition *(*partition_info)(int size, int *num_partitions);
+};
+struct platform_device *
+at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
+
 #endif /* __ASM_ARCH_BOARD_H */
index 57dc672bab8ed3fb9666c15039fa07260fe80a4c..0399359ab5d80f043b54dfe792baa65c1e2364fa 100644 (file)
@@ -35,7 +35,7 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
 /*
  * dma_map_single can't fail as it is implemented now.
  */
-static inline int dma_mapping_error(dma_addr_t addr)
+static inline int dma_mapping_error(struct device *dev, dma_addr_t addr)
 {
        return 0;
 }
diff --git a/include/asm-avr32/kvm.h b/include/asm-avr32/kvm.h
deleted file mode 100644 (file)
index 8c57770..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_AVR32_H
-#define __LINUX_KVM_AVR32_H
-
-/* avr32 does not support KVM */
-
-#endif
diff --git a/include/asm-avr32/namei.h b/include/asm-avr32/namei.h
deleted file mode 100644 (file)
index f0a26de..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_AVR32_NAMEI_H
-#define __ASM_AVR32_NAMEI_H
-
-/* This dummy routine may be changed to something useful */
-#define __emul_prefix() NULL
-
-#endif /* __ASM_AVR32_NAMEI_H */
index cbbc5ca9728bb94558513df79d18904633b84ca9..f805d1cb11bc199b86055552900630371ee9f562 100644 (file)
@@ -57,9 +57,6 @@ static inline int get_order(unsigned long size)
 
 #endif /* !__ASSEMBLY__ */
 
-/* Align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
 /*
  * The hardware maps the virtual addresses 0x80000000 -> 0x9fffffff
  * permanently to the physical addresses 0x00000000 -> 0x1fffffff when
diff --git a/include/asm-avr32/semaphore.h b/include/asm-avr32/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index df68631b7b27f98f63e579a3a20940a544f84f6a..294b25f9323dda6a4885de1a6b874b4a6a3bb825 100644 (file)
@@ -61,10 +61,6 @@ static inline struct thread_info *current_thread_info(void)
        return (struct thread_info *)addr;
 }
 
-/* thread information allocation */
-#define alloc_thread_info(ti) \
-       ((struct thread_info *) __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
-#define free_thread_info(ti) free_pages((unsigned long)(ti), 1)
 #define get_thread_info(ti) get_task_struct((ti)->task)
 #define put_thread_info(ti) put_task_struct((ti)->task)
 
index 76033831eb35d02c91bf29baef6d4ed15af4dcbc..320aa5e167e95098fca000cb83084266eecc91c9 100644 (file)
@@ -92,16 +92,20 @@ extern void *l1_data_B_sram_alloc(size_t);
 extern void *l1_inst_sram_alloc(size_t);
 extern void *l1_data_sram_alloc(size_t);
 extern void *l1_data_sram_zalloc(size_t);
+extern void *l2_sram_alloc(size_t);
+extern void *l2_sram_zalloc(size_t);
 extern int l1_data_A_sram_free(const void*);
 extern int l1_data_B_sram_free(const void*);
 extern int l1_inst_sram_free(const void*);
 extern int l1_data_sram_free(const void*);
+extern int l2_sram_free(const void *);
 extern int sram_free(const void*);
 
 #define L1_INST_SRAM           0x00000001
 #define L1_DATA_A_SRAM         0x00000002
 #define L1_DATA_B_SRAM         0x00000004
 #define L1_DATA_SRAM           0x00000006
+#define L2_SRAM                        0x00000008
 extern void *sram_alloc_with_lsl(size_t, unsigned long);
 extern int sram_free_with_lsl(const void*);
 
@@ -114,7 +118,9 @@ extern struct file_operations dpmc_fops;
 extern unsigned long _ramstart, _ramend, _rambase;
 extern unsigned long memory_start, memory_end, physical_mem_end;
 extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
-    _ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _ebss_b_l1[];
+       _ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _ebss_b_l1[],
+       _stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[],
+       _ebss_l2[], _l2_lma_start[];
 
 #ifdef CONFIG_MTD_UCLINUX
 extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size;
index c0d5259e315b05f155d3bcc9dd299b5fb0062679..3cd4b522aa3fa1c00f4757501031d3978583d882 100644 (file)
@@ -144,8 +144,16 @@ struct dma_channel {
        void *data;
        unsigned int dma_enable_flag;
        unsigned int loopback_flag;
+#ifdef CONFIG_PM
+       unsigned short saved_peripheral_map;
+#endif
 };
 
+#ifdef CONFIG_PM
+int blackfin_dma_suspend(void);
+void blackfin_dma_resume(void);
+#endif
+
 /*******************************************************************************
 *      DMA API's
 *******************************************************************************/
index 7f34cd384f12abbacab586bfe7417eb059e01c5e..de28e6e018b33a01e0938c0f18119884f3496e59 100644 (file)
@@ -7,63 +7,18 @@
 #ifndef _BLACKFIN_DPMC_H_
 #define _BLACKFIN_DPMC_H_
 
-#define SLEEP_MODE             1
-#define DEEP_SLEEP_MODE                2
-#define ACTIVE_PLL_DISABLED    3
-#define FULLON_MODE            4
-#define ACTIVE_PLL_ENABLED     5
-#define HIBERNATE_MODE         6
-
-#define IOCTL_FULL_ON_MODE     _IO('s', 0xA0)
-#define IOCTL_ACTIVE_MODE      _IO('s', 0xA1)
-#define IOCTL_SLEEP_MODE       _IO('s', 0xA2)
-#define IOCTL_DEEP_SLEEP_MODE  _IO('s', 0xA3)
-#define IOCTL_HIBERNATE_MODE   _IO('s', 0xA4)
-#define IOCTL_CHANGE_FREQUENCY _IOW('s', 0xA5, unsigned long)
-#define IOCTL_CHANGE_VOLTAGE   _IOW('s', 0xA6, unsigned long)
-#define IOCTL_SET_CCLK         _IOW('s', 0xA7, unsigned long)
-#define IOCTL_SET_SCLK         _IOW('s', 0xA8, unsigned long)
-#define IOCTL_GET_PLLSTATUS    _IOW('s', 0xA9, unsigned long)
-#define IOCTL_GET_CORECLOCK    _IOW('s', 0xAA, unsigned long)
-#define IOCTL_GET_SYSTEMCLOCK  _IOW('s', 0xAB, unsigned long)
-#define IOCTL_GET_VCO          _IOW('s', 0xAC, unsigned long)
-#define IOCTL_DISABLE_WDOG_TIMER _IO('s', 0xAD)
-#define IOCTL_UNMASK_WDOG_WAKEUP_EVENT _IO('s',0xAE)
-#define IOCTL_PROGRAM_WDOG_TIMER _IOW('s',0xAF,unsigned long)
-#define IOCTL_CLEAR_WDOG_WAKEUP_EVENT _IO('s',0xB0)
-#define IOCTL_SLEEP_DEEPER_MODE _IO('s',0xB1)
-
-#define DPMC_MINOR             254
-
-#define ON     0
-#define OFF    1
-
 #ifdef __KERNEL__
+#ifndef __ASSEMBLY__
 
-unsigned long calc_volt(void);
-int calc_vlev(int vlt);
-unsigned long change_voltage(unsigned long volt);
-int calc_msel(int vco_hz);
-unsigned long change_frequency(unsigned long vco_mhz);
-int set_pll_div(unsigned short sel, unsigned char flag);
-int get_vco(void);
-unsigned long change_system_clock(unsigned long clock);
-unsigned long change_core_clock(unsigned long clock);
-unsigned long get_pll_status(void);
-void change_baud(int baud);
-void fullon_mode(void);
-void active_mode(void);
 void sleep_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
 void deep_sleep(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
 void hibernate_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
 void sleep_deeper(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
-void program_wdog_timer(unsigned long);
-void unmask_wdog_wakeup_evt(void);
-void clear_wdog_wakeup_evt(void);
-void disable_wdog_timer(void);
+void do_hibernate(int wakeup);
+void set_dram_srfs(void);
+void unset_dram_srfs(void);
 
-extern unsigned long get_cclk(void);
-extern unsigned long get_sclk(void);
+#define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16))
 
 struct bfin_dpmc_platform_data {
        const unsigned int *tuple_tab;
@@ -71,8 +26,33 @@ struct bfin_dpmc_platform_data {
        unsigned short vr_settling_time; /* in us */
 };
 
-#define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16))
+#else
+
+#define PM_PUSH(x) \
+       R0 = [P0 + (x - SRAM_BASE_ADDRESS)];\
+       [--SP] =  R0;\
+
+#define PM_POP(x) \
+       R0 = [SP++];\
+       [P0 + (x - SRAM_BASE_ADDRESS)] = R0;\
+
+#define PM_SYS_PUSH(x) \
+       R0 = [P0 + (x - PLL_CTL)];\
+       [--SP] =  R0;\
+
+#define PM_SYS_POP(x) \
+       R0 = [SP++];\
+       [P0 + (x - PLL_CTL)] = R0;\
+
+#define PM_SYS_PUSH16(x) \
+       R0 = w[P0 + (x - PLL_CTL)];\
+       [--SP] =  R0;\
+
+#define PM_SYS_POP16(x) \
+       R0 = [SP++];\
+       w[P0 + (x - PLL_CTL)] = R0;\
 
+#endif
 #endif /* __KERNEL__ */
 
 #endif /*_BLACKFIN_DPMC_H_*/
index 30303fc8292c3ac820653e83d36f520141d40c91..67a03a8a353e019a28a1c86918ee6367eb978d69 100644 (file)
@@ -15,6 +15,8 @@
 #define EF_BFIN_FDPIC          0x00000002      /* -mfdpic */
 #define EF_BFIN_CODE_IN_L1     0x00000010      /* --code-in-l1 */
 #define EF_BFIN_DATA_IN_L1     0x00000020      /* --data-in-l1 */
+#define EF_BFIN_CODE_IN_L2     0x00000040      /* --code-in-l2 */
+#define EF_BFIN_DATA_IN_L2     0x00000080      /* --data-in-l2 */
 
 typedef unsigned long elf_greg_t;
 
index ff95e9d883427fca797a9f6c84c7b9f21076f1ff..168f1251eb4da96c94a129f5d225fe4a0cf97d66 100644 (file)
@@ -376,8 +376,12 @@ struct gpio_port_t {
 #endif
 
 #ifdef CONFIG_PM
-unsigned int bfin_pm_setup(void);
-void bfin_pm_restore(void);
+
+unsigned int bfin_pm_standby_setup(void);
+void bfin_pm_standby_restore(void);
+
+void bfin_gpio_pm_hibernate_restore(void);
+void bfin_gpio_pm_hibernate_suspend(void);
 
 #ifndef CONFIG_BF54x
 #define PM_WAKE_RISING 0x1
@@ -392,17 +396,8 @@ void gpio_pm_wakeup_free(unsigned gpio);
 
 struct gpio_port_s {
        unsigned short data;
-       unsigned short data_clear;
-       unsigned short data_set;
-       unsigned short toggle;
        unsigned short maska;
-       unsigned short maska_clear;
-       unsigned short maska_set;
-       unsigned short maska_toggle;
        unsigned short maskb;
-       unsigned short maskb_clear;
-       unsigned short maskb_set;
-       unsigned short maskb_toggle;
        unsigned short dir;
        unsigned short polar;
        unsigned short edge;
@@ -411,10 +406,10 @@ struct gpio_port_s {
 
        unsigned short fer;
        unsigned short reserved;
+       unsigned short mux;
 };
 #endif /*CONFIG_BF54x*/
 #endif /*CONFIG_PM*/
-
 /***********************************************************
 *
 * FUNCTIONS: Blackfin GPIO Driver
diff --git a/include/asm-blackfin/ide.h b/include/asm-blackfin/ide.h
deleted file mode 100644 (file)
index 5b88de1..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/****************************************************************************/
-
-/*
- *  linux/include/asm-blackfin/ide.h
- *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
- *  Copyright (C) 2001       Lineo Inc., davidm@snapgear.com
- *  Copyright (C) 2002       Greg Ungerer (gerg@snapgear.com)
- *  Copyright (C) 2002       Yoshinori Sato (ysato@users.sourceforge.jp)
- *  Copyright (C) 2005       Hennerich Michael (hennerich@blackfin.uclinux.org)
- */
-
-/****************************************************************************/
-#ifndef _BLACKFIN_IDE_H
-#define _BLACKFIN_IDE_H
-/****************************************************************************/
-#ifdef __KERNEL__
-/****************************************************************************/
-
-#define MAX_HWIFS      1
-
-#include <asm-generic/ide_iops.h>
-
-/****************************************************************************/
-#endif                         /* __KERNEL__ */
-#endif                         /* _BLACKFIN_IDE_H */
-/****************************************************************************/
diff --git a/include/asm-blackfin/kvm.h b/include/asm-blackfin/kvm.h
deleted file mode 100644 (file)
index e3477d7..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_BLACKFIN_H
-#define __LINUX_KVM_BLACKFIN_H
-
-/* blackfin does not support KVM */
-
-#endif
index 4725268a5adaff7ae02de00541d153c23d910c75..b7b166f4f064d8abe4bee22bb5c566e78e0b683a 100644 (file)
@@ -23,6 +23,8 @@
 #define ANOMALY_05000245 (1)
 /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
 #define ANOMALY_05000265 (1)
+/* New Feature: EMAC TX DMA Word Alignment */
+#define ANOMALY_05000285 (1)
 /* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
 #define ANOMALY_05000312 (1)
 /* Incorrect Access of OTP_STATUS During otp_write() Function */
index 0612d0c9501c59e3ce990c81dc83f681f40f2a6b..cfd8ad4f1f2c33cc34efc32aba570c09eaac42c0 100644 (file)
@@ -118,16 +118,25 @@ static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
 
 #define DRIVER_NAME "bfin_sir"
 
-static void bfin_sir_hw_init(void)
+static int bfin_sir_hw_init(void)
 {
+       int ret = -ENODEV;
 #ifdef CONFIG_BFIN_SIR0
-       peripheral_request(P_UART0_TX, DRIVER_NAME);
-       peripheral_request(P_UART0_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
 
 #ifdef CONFIG_BFIN_SIR1
-       peripheral_request(P_UART1_TX, DRIVER_NAME);
-       peripheral_request(P_UART1_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART1_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART1_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
-       SSYNC();
+       return ret;
 }
index 82134f578f326a0be244f4659782dda429e7a68f..f1a70db70cb84fd180d0a5cd82692fa31a7137cd 100644 (file)
 #define        PHYIE             0x00000001    /* PHY_INT Interrupt Enable                               */
 #define        RXDWA             0x00000002    /* Receive Frame DMA Word Alignment (Odd/Even*)           */
 #define        RXCKS             0x00000004    /* Enable RX Frame TCP/UDP Checksum Computation           */
+#define        TXDWA             0x00000010    /* Transmit Frame DMA Word Alignment (Odd/Even*)          */
 #define        MDCDIV            0x00003F00    /* SCLK:MDC Clock Divisor [MDC=SCLK/(2*(N+1))]            */
 
 #define        SET_MDCDIV(x) (((x)&0x3F)<< 8)   /* Set MDC Clock Divisor                                 */
index 008ca66719e21caac625a016f0948b5a328eaed5..cbe03f4a569853321225678d7b73d29e27c6b2fd 100644 (file)
 #define SDRAM_CL    CL_3
 #endif
 
-#if (CONFIG_MEM_SIZE == 128)
-#define SDRAM_SIZE      EBSZ_128
-#endif
-#if (CONFIG_MEM_SIZE == 64)
-#define SDRAM_SIZE      EBSZ_64
-#endif
-#if (CONFIG_MEM_SIZE == 32)
-#define SDRAM_SIZE      EBSZ_32
-#endif
-#if (CONFIG_MEM_SIZE == 16)
-#define SDRAM_SIZE      EBSZ_16
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 11)
-#define SDRAM_WIDTH     EBCAW_11
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 10)
-#define SDRAM_WIDTH     EBCAW_10
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 9)
-#define SDRAM_WIDTH     EBCAW_9
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 8)
-#define SDRAM_WIDTH     EBCAW_8
-#endif
-
-#define mem_SDBCTL      (SDRAM_WIDTH | SDRAM_SIZE | EBE)
-
 /* Equation from section 17 (p17-46) of BF533 HRM */
 #define mem_SDRRC       (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
 
index cefcf8bb505b1aba5d9f0247e1eb15fe6918b135..9bb87e9e2e9b9fb1dc0901d7a2b3e63a19d0b583 100644 (file)
@@ -110,11 +110,16 @@ static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
 
 #define DRIVER_NAME "bfin_sir"
 
-static void bfin_sir_hw_init(void)
+static int bfin_sir_hw_init(void)
 {
+       int ret = -ENODEV;
 #ifdef CONFIG_BFIN_SIR0
-       peripheral_request(P_UART0_TX, DRIVER_NAME);
-       peripheral_request(P_UART0_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
-       SSYNC();
+       return ret;
 }
index f8f31901fca9984d854eb182840cd757ea2a001f..995c06b2b1ef7f2131c28201897fd293eafbf227 100644 (file)
 #define SDRAM_CL    CL_3
 #endif
 
-#if (CONFIG_MEM_SIZE == 128)
-#define SDRAM_SIZE      EBSZ_128
-#endif
-#if (CONFIG_MEM_SIZE == 64)
-#define SDRAM_SIZE      EBSZ_64
-#endif
-#if (CONFIG_MEM_SIZE == 32)
-#define SDRAM_SIZE      EBSZ_32
-#endif
-#if (CONFIG_MEM_SIZE == 16)
-#define SDRAM_SIZE      EBSZ_16
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 11)
-#define SDRAM_WIDTH     EBCAW_11
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 10)
-#define SDRAM_WIDTH     EBCAW_10
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 9)
-#define SDRAM_WIDTH     EBCAW_9
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 8)
-#define SDRAM_WIDTH     EBCAW_8
-#endif
-
-#define mem_SDBCTL      (SDRAM_WIDTH | SDRAM_SIZE | EBE)
-
 /* Equation from section 17 (p17-46) of BF533 HRM */
 #define mem_SDRRC       (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref)  / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
 
index 0612d0c9501c59e3ce990c81dc83f681f40f2a6b..cfd8ad4f1f2c33cc34efc32aba570c09eaac42c0 100644 (file)
@@ -118,16 +118,25 @@ static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
 
 #define DRIVER_NAME "bfin_sir"
 
-static void bfin_sir_hw_init(void)
+static int bfin_sir_hw_init(void)
 {
+       int ret = -ENODEV;
 #ifdef CONFIG_BFIN_SIR0
-       peripheral_request(P_UART0_TX, DRIVER_NAME);
-       peripheral_request(P_UART0_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
 
 #ifdef CONFIG_BFIN_SIR1
-       peripheral_request(P_UART1_TX, DRIVER_NAME);
-       peripheral_request(P_UART1_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART1_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART1_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
-       SSYNC();
+       return ret;
 }
index 3f455909c418c09521512913c501d195c777f019..abde24c6d3b1f96dde114bfdf3e48d7b823becf6 100644 (file)
 #define        PHYIE           0x00000001      /* PHY_INT Interrupt Enable                                                     */
 #define        RXDWA           0x00000002      /* Receive Frame DMA Word Alignment (Odd/Even*)         */
 #define        RXCKS           0x00000004      /* Enable RX Frame TCP/UDP Checksum Computation         */
+#define        TXDWA           0x00000010      /* Transmit Frame DMA Word Alignment (Odd/Even*)        */
 #define        MDCDIV          0x00003F00      /* SCLK:MDC Clock Divisor [MDC=SCLK/(2*(N+1))]          */
 
 #define        SET_MDCDIV(x)   (((x)&0x3F)<< 8)        /* Set MDC Clock Divisor                                */
index 9ad979d416c65adc87e45a0bdf60d20a47820ceb..f67698f670ca04b6a9aeda4510b6d3e10a3fd21d 100644 (file)
 #define SDRAM_CL    CL_3
 #endif
 
-#if (CONFIG_MEM_SIZE == 128)
-#define SDRAM_SIZE      EBSZ_128
-#endif
-#if (CONFIG_MEM_SIZE == 64)
-#define SDRAM_SIZE      EBSZ_64
-#endif
-#if (CONFIG_MEM_SIZE == 32)
-#define SDRAM_SIZE      EBSZ_32
-#endif
-#if (CONFIG_MEM_SIZE == 16)
-#define SDRAM_SIZE      EBSZ_16
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 11)
-#define SDRAM_WIDTH     EBCAW_11
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 10)
-#define SDRAM_WIDTH     EBCAW_10
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 9)
-#define SDRAM_WIDTH     EBCAW_9
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 8)
-#define SDRAM_WIDTH     EBCAW_8
-#endif
-
-#define mem_SDBCTL      (SDRAM_WIDTH | SDRAM_SIZE | EBE)
-
 /* Equation from section 17 (p17-46) of BF533 HRM */
 #define mem_SDRRC       (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
 
index 5e94271c7e3bd476652981f2391d1b3db90f01c0..c41f9cf00268933c88d55d1cb832695a6036386d 100644 (file)
@@ -124,26 +124,43 @@ struct bfin_sir_self {
 
 #define DRIVER_NAME "bfin_sir"
 
-static void bfin_sir_hw_init(void)
+static int bfin_sir_hw_init(void)
 {
+       int ret = -ENODEV;
 #ifdef CONFIG_BFIN_SIR0
-       peripheral_request(P_UART0_TX, DRIVER_NAME);
-       peripheral_request(P_UART0_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
 
 #ifdef CONFIG_BFIN_SIR1
-       peripheral_request(P_UART1_TX, DRIVER_NAME);
-       peripheral_request(P_UART1_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART1_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART1_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
 
 #ifdef CONFIG_BFIN_SIR2
-       peripheral_request(P_UART2_TX, DRIVER_NAME);
-       peripheral_request(P_UART2_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART2_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART2_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
 
 #ifdef CONFIG_BFIN_SIR3
-       peripheral_request(P_UART3_TX, DRIVER_NAME);
-       peripheral_request(P_UART3_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART3_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART3_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
-       SSYNC();
+       return ret;
 }
index cb8b0f15c9a6b2439b3ea120e0c7c53ef8c66aee..bba82dc75f16be127fabab1d5d96559d4c57044f 100644 (file)
@@ -209,3 +209,11 @@ struct gpio_port_t {
        unsigned short dummy7;
        unsigned int port_mux;
 };
+
+struct gpio_port_s {
+       unsigned short fer;
+       unsigned short data;
+       unsigned short dir;
+       unsigned short inen;
+       unsigned int mux;
+};
index cefcf8bb505b1aba5d9f0247e1eb15fe6918b135..9bb87e9e2e9b9fb1dc0901d7a2b3e63a19d0b583 100644 (file)
@@ -110,11 +110,16 @@ static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
 
 #define DRIVER_NAME "bfin_sir"
 
-static void bfin_sir_hw_init(void)
+static int bfin_sir_hw_init(void)
 {
+       int ret = -ENODEV;
 #ifdef CONFIG_BFIN_SIR0
-       peripheral_request(P_UART0_TX, DRIVER_NAME);
-       peripheral_request(P_UART0_RX, DRIVER_NAME);
+       ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
+       if (ret)
+               return ret;
+       ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
+       if (ret)
+               return ret;
 #endif
-       SSYNC();
+       return ret;
 }
index 439a5895b346d3c0a8b31bd6aa3ff4ccd771bee7..e163260bca18ac94041cd4e3391e814b41a6f806 100644 (file)
 #define SDRAM_CL    CL_3
 #endif
 
-#if (CONFIG_MEM_SIZE == 128)
-#define SDRAM_SIZE      EB0_SZ_128
-#endif
-#if (CONFIG_MEM_SIZE == 64)
-#define SDRAM_SIZE      EB0_SZ_64
-#endif
-#if ( CONFIG_MEM_SIZE == 32)
-#define SDRAM_SIZE      EB0_SZ_32
-#endif
-#if (CONFIG_MEM_SIZE == 16)
-#define SDRAM_SIZE      EB0_SZ_16
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 11)
-#define SDRAM_WIDTH     EB0_CAW_11
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 10)
-#define SDRAM_WIDTH     EB0_CAW_10
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 9)
-#define SDRAM_WIDTH     EB0_CAW_9
-#endif
-#if (CONFIG_MEM_ADD_WIDTH == 8)
-#define SDRAM_WIDTH     EB0_CAW_8
-#endif
-
-#define mem_SDBCTL      (SDRAM_WIDTH | SDRAM_SIZE | EB0_E)
-
 /* Equation from section 17 (p17-46) of BF533 HRM */
 #define mem_SDRRC       (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
 
index 3c7ce1644280568a4c34f68a48924cbcecd62990..e3128df139d68a261419b0f997a9a167d31a6a92 100644 (file)
@@ -6,8 +6,6 @@
 #define Elf_Shdr        Elf32_Shdr
 #define Elf_Sym         Elf32_Sym
 #define Elf_Ehdr        Elf32_Ehdr
-#define FLG_CODE_IN_L1 0x10
-#define FLG_DATA_IN_L1 0x20
 
 struct mod_arch_specific {
        Elf_Shdr        *text_l1;
@@ -15,5 +13,8 @@ struct mod_arch_specific {
        Elf_Shdr        *bss_a_l1;
        Elf_Shdr        *data_b_l1;
        Elf_Shdr        *bss_b_l1;
+       Elf_Shdr        *text_l2;
+       Elf_Shdr        *data_l2;
+       Elf_Shdr        *bss_l2;
 };
 #endif                         /* _ASM_BFIN_MODULE_H */
diff --git a/include/asm-blackfin/namei.h b/include/asm-blackfin/namei.h
deleted file mode 100644 (file)
index 8b89a2d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * linux/include/asm/namei.h
- *
- * Included from linux/fs/namei.c
- *
- * Changes made by Lineo Inc.    May 2001
- */
-
-#ifndef __BFIN_NAMEI_H
-#define __BFIN_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif
index c7db0220fbd6dd74d7a8b97a4bae4fe801fdfc25..344f6a8c1f22a9cebe0a86f38c3955e30c0032a5 100644 (file)
@@ -51,9 +51,6 @@ typedef struct page *pgtable_t;
 #define __pgd(x)       ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 extern unsigned long memory_start;
 extern unsigned long memory_end;
 
index 1c004072461257a2b7ebb2c850858103f30cf620..6f3995b119d8e78658abd9c5ca448deaa2026435 100644 (file)
@@ -112,7 +112,26 @@ unsigned long get_wchan(struct task_struct *p);
 static inline uint32_t __pure bfin_revid(void)
 {
        /* stored in the upper 4 bits */
-       return bfin_read_CHIPID() >> 28;
+       uint32_t revid = bfin_read_CHIPID() >> 28;
+
+#ifdef CONFIG_BF52x
+       /* ANOMALY_05000357
+        * Incorrect Revision Number in DSPID Register
+        */
+       if (revid == 0)
+               switch (bfin_read16(_BOOTROM_GET_DXE_ADDRESS_TWI)) {
+               case 0x0010:
+                       revid = 0;
+                       break;
+               case 0x2796:
+                       revid = 1;
+                       break;
+               default:
+                       revid = 0xFFFF;
+                       break;
+               }
+#endif
+       return revid;
 }
 
 static inline uint32_t __pure bfin_compiled_revid(void)
index b8346cd3a6f609018b7a0aae0db0f11fc0d33802..a45a80e54adcbe75a774df805d881c03a8da7015 100644 (file)
@@ -83,14 +83,14 @@ struct pt_regs {
 #define PTRACE_GETREGS            12
 #define PTRACE_SETREGS            13   /* ptrace signal  */
 
-#ifdef CONFIG_BINFMT_ELF_FDPIC
 #define PTRACE_GETFDPIC           31
 #define PTRACE_GETFDPIC_EXEC      0
 #define PTRACE_GETFDPIC_INTERP    1
-#endif
 
 #define PS_S  (0x0002)
 
+#ifdef __KERNEL__
+
 /* user_mode returns true if only one bit is set in IPEND, other than the
    master interrupt enable.  */
 #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1)))
@@ -98,6 +98,8 @@ struct pt_regs {
 #define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
+#endif  /*  __KERNEL__  */
+
 #endif                         /* __ASSEMBLY__ */
 
 /*
diff --git a/include/asm-blackfin/semaphore.h b/include/asm-blackfin/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index bc2fe5accf20a7f4c55f5b45c640e7e025a29ec1..642769329d12b12fde86d7fb99620a20a98f39ad 100644 (file)
@@ -42,6 +42,7 @@
 /*
  * Size of kernel stack for each process. This must be a power of 2...
  */
+#define THREAD_SIZE_ORDER      1
 #define THREAD_SIZE            8192    /* 2 pages */
 
 #ifndef __ASSEMBLY__
@@ -94,10 +95,6 @@ static inline struct thread_info *current_thread_info(void)
        return (struct thread_info *)((long)ti & ~((long)THREAD_SIZE-1));
 }
 
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-                               __get_free_pages(GFP_KERNEL, 1))
-#define free_thread_info(ti)   free_pages((unsigned long) (ti), 1)
 #endif                         /* __ASSEMBLY__ */
 
 /*
index 60e7e1b73cec6a0e05f33e3b422b4ea3e65f6263..7a192e1290b1a335dd52ff48c001dcc80b3ac63c 100644 (file)
@@ -1,4 +1,3 @@
-header-y += ptrace.h
 header-y += user.h
 header-y += svinto.h
 header-y += sv_addr_ag.h
diff --git a/include/asm-cris/arch-v10/ide.h b/include/asm-cris/arch-v10/ide.h
deleted file mode 100644 (file)
index 5366e62..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  linux/include/asm-cris/ide.h
- *
- *  Copyright (C) 2000, 2001, 2002  Axis Communications AB
- *
- *  Authors:    Bjorn Wesen
- *
- */
-
-/*
- *  This file contains the ETRAX 100LX specific IDE code.
- */
-
-#ifndef __ASMCRIS_IDE_H
-#define __ASMCRIS_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/arch/svinto.h>
-#include <asm/io.h>
-#include <asm-generic/ide_iops.h>
-
-
-/* ETRAX 100 can support 4 IDE busses on the same pins (serialized) */
-
-#define MAX_HWIFS      4
-
-static inline int ide_default_irq(unsigned long base)
-{
-       /* all IDE busses share the same IRQ, number 4.
-        * this has the side-effect that ide-probe.c will cluster our 4 interfaces
-        * together in a hwgroup, and will serialize accesses. this is good, because
-        * we can't access more than one interface at the same time on ETRAX100.
-        */
-       return 4;
-}
-
-static inline unsigned long ide_default_io_base(int index)
-{
-       /* we have no real I/O base address per interface, since all go through the
-        * same register. but in a bitfield in that register, we have the i/f number.
-        * so we can use the io_base to remember that bitfield.
-        */
-       static const unsigned long io_bases[MAX_HWIFS] = {
-               IO_FIELD(R_ATA_CTRL_DATA, sel, 0),
-               IO_FIELD(R_ATA_CTRL_DATA, sel, 1),
-               IO_FIELD(R_ATA_CTRL_DATA, sel, 2),
-               IO_FIELD(R_ATA_CTRL_DATA, sel, 3)
-       };
-       return io_bases[index];
-}
-
-/* this is called once for each interface, to setup the port addresses. data_port is the result
- * of the ide_default_io_base call above. ctrl_port will be 0, but that is don't care for us.
- */
-
-static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq)
-{
-       int i;
-
-       /* fill in ports for ATA addresses 0 to 7 */
-       for (i = 0; i <= 7; i++) {
-               hw->io_ports_array[i] = data_port |
-                       IO_FIELD(R_ATA_CTRL_DATA, addr, i) |
-                       IO_STATE(R_ATA_CTRL_DATA, cs0, active);
-       }
-
-       /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
-       hw->io_ports.ctl_addr = data_port |
-                       IO_FIELD(R_ATA_CTRL_DATA, addr, 6) |
-                       IO_STATE(R_ATA_CTRL_DATA, cs1, active);
-
-       /* whats this for ? */
-       hw->io_ports.irq_addr = 0;
-}
-
-static inline void ide_init_default_hwifs(void)
-{
-       hw_regs_t hw;
-       int index;
-
-       for(index = 0; index < MAX_HWIFS; index++) {
-               ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
-               hw.irq = ide_default_irq(ide_default_io_base(index));
-               ide_register_hw(&hw, NULL);
-       }
-}
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASMCRIS_IDE_H */
index fb14c5ee37f94e342bfb865c35dac478ec024dec..2f464eab3a51cf25764c74939e3736babfe9f844 100644 (file)
@@ -106,10 +106,14 @@ struct switch_stack {
        unsigned long return_ip; /* ip that _resume will return to */
 };
 
+#ifdef __KERNEL__
+
 /* bit 8 is user-mode flag */
 #define user_mode(regs) (((regs)->dccr & 0x100) != 0)
 #define instruction_pointer(regs) ((regs)->irp)
 #define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
+#endif  /*  __KERNEL__  */
+
 #endif
index a0ec545e242ea27e77213c398ba00a3e13bf0e6c..35f2fc4f993e793b1fd29c56300614dd9a263960 100644 (file)
@@ -1,3 +1,2 @@
-header-y += ptrace.h
 header-y += user.h
 header-y += cryptocop.h
diff --git a/include/asm-cris/arch-v32/ide.h b/include/asm-cris/arch-v32/ide.h
deleted file mode 100644 (file)
index fb9c362..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  linux/include/asm-cris/ide.h
- *
- *  Copyright (C) 2000-2004  Axis Communications AB
- *
- *  Authors:    Bjorn Wesen, Mikael Starvik
- *
- */
-
-/*
- *  This file contains the ETRAX FS specific IDE code.
- */
-
-#ifndef __ASMCRIS_IDE_H
-#define __ASMCRIS_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/arch/hwregs/intr_vect.h>
-#include <asm/arch/hwregs/ata_defs.h>
-#include <asm/io.h>
-#include <asm-generic/ide_iops.h>
-
-
-/* ETRAX FS can support 4 IDE busses on the same pins (serialized) */
-
-#define MAX_HWIFS      4
-
-static inline int ide_default_irq(unsigned long base)
-{
-       /* all IDE busses share the same IRQ,
-        * this has the side-effect that ide-probe.c will cluster our 4 interfaces
-        * together in a hwgroup, and will serialize accesses. this is good, because
-        * we can't access more than one interface at the same time on ETRAX100.
-        */
-       return ATA_INTR_VECT;
-}
-
-static inline unsigned long ide_default_io_base(int index)
-{
-       reg_ata_rw_ctrl2 ctrl2 = {.sel = index};
-       /* we have no real I/O base address per interface, since all go through the
-        * same register. but in a bitfield in that register, we have the i/f number.
-        * so we can use the io_base to remember that bitfield.
-        */
-        ctrl2.sel = index;
-
-       return REG_TYPE_CONV(unsigned long, reg_ata_rw_ctrl2, ctrl2);
-}
-
-#define IDE_ARCH_ACK_INTR
-#define ide_ack_intr(hwif)     ((hwif)->ack_intr(hwif))
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASMCRIS_IDE_H */
index 516cc7062d9488786f45d4b36327469d42d6170b..41f4e8662bc2555c6c18f66071a9902577ab1312 100644 (file)
@@ -106,9 +106,13 @@ struct switch_stack {
        unsigned long return_ip; /* ip that _resume will return to */
 };
 
+#ifdef __KERNEL__
+
 #define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0)
 #define instruction_pointer(regs) ((regs)->erp)
 extern void show_regs(struct pt_regs *);
 #define profile_pc(regs) instruction_pointer(regs)
 
+#endif  /*  __KERNEL__  */
+
 #endif
index 01af2de27c5bcf59eceaf758e27253fc303937f4..cf60e3f69f8d6ed9b40556b58e759738b485fb8d 100644 (file)
@@ -26,7 +26,6 @@
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
        memcpy(dst, src, len)
 
-void global_flush_tlb(void); 
 int change_page_attr(struct page *page, int numpages, pgprot_t prot);
 
 #endif /* _CRIS_CACHEFLUSH_H */
index edc8d1bfaae2a6fa303f7dfa1f844fdff7eac812..da8ef8e8f842733751a33985879e07057e6af523 100644 (file)
@@ -14,6 +14,8 @@
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
 #ifdef CONFIG_PCI
+#include <asm-generic/dma-coherent.h>
+
 void *dma_alloc_coherent(struct device *dev, size_t size,
                           dma_addr_t *dma_handle, gfp_t flag);
 
@@ -120,7 +122,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
 }
 
 static inline int
-dma_mapping_error(dma_addr_t dma_addr)
+dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return 0;
 }
diff --git a/include/asm-cris/ide.h b/include/asm-cris/ide.h
deleted file mode 100644 (file)
index a894f66..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm/arch/ide.h>
diff --git a/include/asm-cris/kvm.h b/include/asm-cris/kvm.h
deleted file mode 100644 (file)
index c860f51..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_CRIS_H
-#define __LINUX_KVM_CRIS_H
-
-/* cris does not support KVM */
-
-#endif
diff --git a/include/asm-cris/namei.h b/include/asm-cris/namei.h
deleted file mode 100644 (file)
index 8a3be7a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $Id: namei.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $
- * linux/include/asm-cris/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __CRIS_NAMEI_H
-#define __CRIS_NAMEI_H
-
-/* used to find file-system prefixes for doing emulations
- * see for example asm-sparc/namei.h
- * we don't use it...
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __CRIS_NAMEI_H */
index c45bb1ef397cb3466c2d836f8fc1679ba69d4a9d..d19272ba6b696d659c1e14643e86445c135aeb92 100644 (file)
@@ -60,9 +60,6 @@ typedef struct page *pgtable_t;
 
 #define page_to_phys(page)     __pa((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 #ifndef __ASSEMBLY__
 
 #endif /* __ASSEMBLY__ */
index 1ec69a7ea8365282b226ff9a91dbe36df4600bf8..d910925e3174e4bab4d8267b4dd6d0ac34890ffe 100644 (file)
@@ -4,11 +4,13 @@
 #include <asm/arch/ptrace.h>
 
 #ifdef __KERNEL__
+
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS            12
 #define PTRACE_SETREGS            13
-#endif
 
 #define profile_pc(regs) instruction_pointer(regs)
 
+#endif /* __KERNEL__ */
+
 #endif /* _CRIS_PTRACE_H */
diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 784668ab0fa29dfdb251302f623993c9ceb19d65..7efe1000f99d23e18b0825d7b8f4c7ebc52df53d 100644 (file)
@@ -11,6 +11,8 @@
 
 #ifdef __KERNEL__
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 #include <asm/processor.h>
index bc3f12c5b7e05688a609350735ab44744fa4b6f8..0f8956def738bfbfcb2ba77204a945bde9806979 100644 (file)
@@ -3,4 +3,3 @@ include include/asm-generic/Kbuild.asm
 header-y += registers.h
 
 unifdef-y += termios.h
-unifdef-y += ptrace.h
index 2e8966ca030d46cd4b7514a3a0c4589aeba667b7..b2898877c07b5048fb820fe1b5e1350a53ccf5fe 100644 (file)
@@ -126,7 +126,7 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nele
 }
 
 static inline
-int dma_mapping_error(dma_addr_t dma_addr)
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return 0;
 }
index 8c9a540d434431138deb74ee9f7558b660e9b197..7ebcc56a22291edb6388332d16f84686c1542e61 100644 (file)
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#ifndef MAX_HWIFS
-#define MAX_HWIFS 8
-#endif
-
 /****************************************************************************/
 /*
  * some bits needed for parts of the IDE subsystem to compile
diff --git a/include/asm-frv/kvm.h b/include/asm-frv/kvm.h
deleted file mode 100644 (file)
index 9c8a4f0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_FRV_H
-#define __LINUX_KVM_FRV_H
-
-/* frv does not support KVM */
-
-#endif
diff --git a/include/asm-frv/namei.h b/include/asm-frv/namei.h
deleted file mode 100644 (file)
index 4ea5717..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * include/asm-frv/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __ASM_NAMEI_H
-#define __ASM_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif
-
index c2c1e89e747d248d78c0a7535fe2b4f11740edb7..bd9c220094c74b288a03dc958f91e1b977dcb57c 100644 (file)
@@ -40,9 +40,6 @@ typedef struct page *pgtable_t;
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 #define PTE_MASK       PAGE_MASK
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
 #define devmem_is_allowed(pfn) 1
 
 #define __pa(vaddr)            virt_to_phys((void *) (unsigned long) (vaddr))
diff --git a/include/asm-frv/semaphore.h b/include/asm-frv/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 348b8f1df17eef8593183fe565925d4c1b15467f..b7ac6bf2844c395c3179d733102e13ca0e8001fa 100644 (file)
@@ -82,6 +82,8 @@ register struct thread_info *__current_thread_info asm("gr15");
 
 #define current_thread_info() ({ __current_thread_info; })
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
 #define alloc_thread_info(tsk)                                 \
index 7cd25b8e7c9a4b891fcf00fd60b3985e5d48c59e..1170dc60e638b35a9ee42cf39ba84b3982178a21 100644 (file)
@@ -1,4 +1,6 @@
+ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),)
 header-y  += kvm.h
+endif
 
 ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),)
 unifdef-y += a.out.h
index 2632328d8646840aab41c8e401a1088e922754f2..a3f738cffdb61a0057ffb8a1cd9a012e30b72f24 100644 (file)
@@ -34,9 +34,14 @@ struct bug_entry {
 #ifndef __WARN
 #ifndef __ASSEMBLY__
 extern void warn_on_slowpath(const char *file, const int line);
+extern void warn_slowpath(const char *file, const int line,
+               const char *fmt, ...) __attribute__((format(printf, 3, 4)));
 #define WANT_WARN_ON_SLOWPATH
 #endif
 #define __WARN() warn_on_slowpath(__FILE__, __LINE__)
+#define __WARN_printf(arg...) warn_slowpath(__FILE__, __LINE__, arg)
+#else
+#define __WARN_printf(arg...) __WARN()
 #endif
 
 #ifndef WARN_ON
@@ -48,6 +53,15 @@ extern void warn_on_slowpath(const char *file, const int line);
 })
 #endif
 
+#ifndef WARN
+#define WARN(condition, format...) ({                                          \
+       int __ret_warn_on = !!(condition);                              \
+       if (unlikely(__ret_warn_on))                                    \
+               __WARN_printf(format);                                  \
+       unlikely(__ret_warn_on);                                        \
+})
+#endif
+
 #else /* !CONFIG_BUG */
 #ifndef HAVE_ARCH_BUG
 #define BUG()
@@ -63,6 +77,14 @@ extern void warn_on_slowpath(const char *file, const int line);
        unlikely(__ret_warn_on);                                        \
 })
 #endif
+
+#ifndef WARN
+#define WARN(condition, format...) ({                                  \
+       int __ret_warn_on = !!(condition);                              \
+       unlikely(__ret_warn_on);                                        \
+})
+#endif
+
 #endif
 
 #define WARN_ON_ONCE(condition)        ({                              \
@@ -75,6 +97,9 @@ extern void warn_on_slowpath(const char *file, const int line);
        unlikely(__ret_warn_once);                              \
 })
 
+#define WARN_ON_RATELIMIT(condition, state)                    \
+               WARN_ON((condition) && __ratelimit(state))
+
 #ifdef CONFIG_SMP
 # define WARN_ON_SMP(x)                        WARN_ON(x)
 #else
diff --git a/include/asm-generic/dma-coherent.h b/include/asm-generic/dma-coherent.h
new file mode 100644 (file)
index 0000000..85a3ffa
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef DMA_COHERENT_H
+#define DMA_COHERENT_H
+
+#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
+/*
+ * These two functions are only for dma allocator.
+ * Don't use them in device drivers.
+ */
+int dma_alloc_from_coherent(struct device *dev, ssize_t size,
+                                      dma_addr_t *dma_handle, void **ret);
+int dma_release_from_coherent(struct device *dev, int order, void *vaddr);
+
+/*
+ * Standard interface
+ */
+#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+extern int
+dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+                           dma_addr_t device_addr, size_t size, int flags);
+
+extern void
+dma_release_declared_memory(struct device *dev);
+
+extern void *
+dma_mark_declared_memory_occupied(struct device *dev,
+                                 dma_addr_t device_addr, size_t size);
+#else
+#define dma_alloc_from_coherent(dev, size, handle, ret) (0)
+#define dma_release_from_coherent(dev, order, vaddr) (0)
+#endif
+
+#endif
index e2468f894d2aab0d2e22d1fa87b86ab03160b7cb..82cd0cb1c3fe0100f6a0194491324e11d6deb95b 100644 (file)
@@ -61,7 +61,7 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
 #define dma_sync_sg_for_device dma_sync_sg_for_cpu
 
 extern int
-dma_mapping_error(dma_addr_t dma_addr);
+dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
 
 extern int
 dma_supported(struct device *dev, u64 mask);
index 783ab9944d701234cfd80eeaf34da6ab90af6f04..189486c3f92e3e775d21bf56444e5c6b2d576216 100644 (file)
@@ -144,9 +144,9 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
 }
 
 static inline int
-dma_mapping_error(dma_addr_t dma_addr)
+dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-       return pci_dma_mapping_error(dma_addr);
+       return pci_dma_mapping_error(to_pci_dev(dev), dma_addr);
 }
 
 
index 6be061d09da9d06fc2dabdb520148c028194621b..0f99ad38b012f93ef10ccb5b0f9105b4e7f8daab 100644 (file)
@@ -2,8 +2,9 @@
 #define _ASM_GENERIC_GPIO_H
 
 #include <linux/types.h>
+#include <linux/errno.h>
 
-#ifdef CONFIG_HAVE_GPIO_LIB
+#ifdef CONFIG_GPIOLIB
 
 #include <linux/compiler.h>
 
@@ -13,7 +14,7 @@
  *
  * While the GPIO programming interface defines valid GPIO numbers
  * to be in the range 0..MAX_INT, this library restricts them to the
- * smaller range 0..ARCH_NR_GPIOS.
+ * smaller range 0..ARCH_NR_GPIOS-1.
  */
 
 #ifndef ARCH_NR_GPIOS
@@ -32,6 +33,8 @@ struct module;
 /**
  * struct gpio_chip - abstract a GPIO controller
  * @label: for diagnostics
+ * @dev: optional device providing the GPIOs
+ * @owner: helps prevent removal of modules exporting active GPIOs
  * @direction_input: configures signal "offset" as input, or returns error
  * @get: returns value for signal "offset"; for output signals this
  *     returns either the value actually sensed, or zero
@@ -59,6 +62,7 @@ struct module;
  */
 struct gpio_chip {
        char                    *label;
+       struct device           *dev;
        struct module           *owner;
 
        int                     (*direction_input)(struct gpio_chip *chip,
@@ -74,6 +78,7 @@ struct gpio_chip {
        int                     base;
        u16                     ngpio;
        unsigned                can_sleep:1;
+       unsigned                exported:1;
 };
 
 extern const char *gpiochip_is_requested(struct gpio_chip *chip,
@@ -108,7 +113,18 @@ extern void __gpio_set_value(unsigned gpio, int value);
 extern int __gpio_cansleep(unsigned gpio);
 
 
-#else
+#ifdef CONFIG_GPIO_SYSFS
+
+/*
+ * A sysfs interface can be exported by individual drivers if they want,
+ * but more typically is configured entirely from userspace.
+ */
+extern int gpio_export(unsigned gpio, bool direction_may_change);
+extern void gpio_unexport(unsigned gpio);
+
+#endif /* CONFIG_GPIO_SYSFS */
+
+#else  /* !CONFIG_HAVE_GPIO_LIB */
 
 static inline int gpio_is_valid(int number)
 {
@@ -137,6 +153,20 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
        gpio_set_value(gpio, value);
 }
 
-#endif
+#endif /* !CONFIG_HAVE_GPIO_LIB */
+
+#ifndef CONFIG_GPIO_SYSFS
+
+/* sysfs support is only available with gpiolib, where it's optional */
+
+static inline int gpio_export(unsigned gpio, bool direction_may_change)
+{
+       return -ENOSYS;
+}
+
+static inline void gpio_unexport(unsigned gpio)
+{
+}
+#endif /* CONFIG_GPIO_SYSFS */
 
 #endif /* _ASM_GENERIC_GPIO_H */
index 260948905e4ea5d35f781ffcd08dff5428e6b58d..f9bc9ac29b36edafca055190ca4df361f9152f52 100644 (file)
@@ -26,7 +26,7 @@ typedef unsigned int __u32;
 #ifdef __GNUC__
 __extension__ typedef __signed__ long long __s64;
 __extension__ typedef unsigned long long __u64;
-#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#else
 typedef __signed__ long long __s64;
 typedef unsigned long long __u64;
 #endif
index 25c10e96b2b794099ead8769dad4b5f8146a19ba..37b3706226e74f67e52d80dce326968e05c0655c 100644 (file)
@@ -99,9 +99,9 @@ pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
 }
 
 static inline int
-pci_dma_mapping_error(dma_addr_t dma_addr)
+pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr)
 {
-       return dma_mapping_error(dma_addr);
+       return dma_mapping_error(&pdev->dev, dma_addr);
 }
 
 #endif
index 087325ede76cf31e4a9798664d36913928f058b3..a7cdc48e8b78703156456f8eb2472251e66c8d78 100644 (file)
@@ -5,6 +5,8 @@
 
 #include <asm-generic/pgtable-nopud.h>
 
+struct mm_struct;
+
 #define __PAGETABLE_PMD_FOLDED
 
 /*
@@ -54,7 +56,9 @@ static inline pmd_t * pmd_offset(pud_t * pud, unsigned long address)
  * inside the pud, so has no extra memory associated with it.
  */
 #define pmd_alloc_one(mm, address)             NULL
-#define pmd_free(mm, x)                                do { } while (0)
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+}
 #define __pmd_free_tlb(tlb, x)                 do { } while (0)
 
 #undef  pmd_addr_end
diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h
new file mode 100644 (file)
index 0000000..abcf34c
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * This file is a stub providing documentation for what functions
+ * asm-ARCH/syscall.h files need to define.  Most arch definitions
+ * will be simple inlines.
+ *
+ * All of these functions expect to be called with no locks,
+ * and only when the caller is sure that the task of interest
+ * cannot return to user mode while we are looking at it.
+ */
+
+#ifndef _ASM_SYSCALL_H
+#define _ASM_SYSCALL_H 1
+
+struct task_struct;
+struct pt_regs;
+
+/**
+ * syscall_get_nr - find what system call a task is executing
+ * @task:      task of interest, must be blocked
+ * @regs:      task_pt_regs() of @task
+ *
+ * If @task is executing a system call or is at system call
+ * tracing about to attempt one, returns the system call number.
+ * If @task is not executing a system call, i.e. it's blocked
+ * inside the kernel for a fault or signal, returns -1.
+ *
+ * It's only valid to call this when @task is known to be blocked.
+ */
+long syscall_get_nr(struct task_struct *task, struct pt_regs *regs);
+
+/**
+ * syscall_rollback - roll back registers after an aborted system call
+ * @task:      task of interest, must be in system call exit tracing
+ * @regs:      task_pt_regs() of @task
+ *
+ * It's only valid to call this when @task is stopped for system
+ * call exit tracing (due to TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT),
+ * after tracehook_report_syscall_entry() returned nonzero to prevent
+ * the system call from taking place.
+ *
+ * This rolls back the register state in @regs so it's as if the
+ * system call instruction was a no-op.  The registers containing
+ * the system call number and arguments are as they were before the
+ * system call instruction.  This may not be the same as what the
+ * register state looked like at system call entry tracing.
+ */
+void syscall_rollback(struct task_struct *task, struct pt_regs *regs);
+
+/**
+ * syscall_get_error - check result of traced system call
+ * @task:      task of interest, must be blocked
+ * @regs:      task_pt_regs() of @task
+ *
+ * Returns 0 if the system call succeeded, or -ERRORCODE if it failed.
+ *
+ * It's only valid to call this when @task is stopped for tracing on exit
+ * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ */
+long syscall_get_error(struct task_struct *task, struct pt_regs *regs);
+
+/**
+ * syscall_get_return_value - get the return value of a traced system call
+ * @task:      task of interest, must be blocked
+ * @regs:      task_pt_regs() of @task
+ *
+ * Returns the return value of the successful system call.
+ * This value is meaningless if syscall_get_error() returned nonzero.
+ *
+ * It's only valid to call this when @task is stopped for tracing on exit
+ * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ */
+long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs);
+
+/**
+ * syscall_set_return_value - change the return value of a traced system call
+ * @task:      task of interest, must be blocked
+ * @regs:      task_pt_regs() of @task
+ * @error:     negative error code, or zero to indicate success
+ * @val:       user return value if @error is zero
+ *
+ * This changes the results of the system call that user mode will see.
+ * If @error is zero, the user sees a successful system call with a
+ * return value of @val.  If @error is nonzero, it's a negated errno
+ * code; the user sees a failed system call with this errno code.
+ *
+ * It's only valid to call this when @task is stopped for tracing on exit
+ * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ */
+void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
+                             int error, long val);
+
+/**
+ * syscall_get_arguments - extract system call parameter values
+ * @task:      task of interest, must be blocked
+ * @regs:      task_pt_regs() of @task
+ * @i:         argument index [0,5]
+ * @n:         number of arguments; n+i must be [1,6].
+ * @args:      array filled with argument values
+ *
+ * Fetches @n arguments to the system call starting with the @i'th argument
+ * (from 0 through 5).  Argument @i is stored in @args[0], and so on.
+ * An arch inline version is probably optimal when @i and @n are constants.
+ *
+ * It's only valid to call this when @task is stopped for tracing on
+ * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ * It's invalid to call this with @i + @n > 6; we only support system calls
+ * taking up to 6 arguments.
+ */
+void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+                          unsigned int i, unsigned int n, unsigned long *args);
+
+/**
+ * syscall_set_arguments - change system call parameter value
+ * @task:      task of interest, must be in system call entry tracing
+ * @regs:      task_pt_regs() of @task
+ * @i:         argument index [0,5]
+ * @n:         number of arguments; n+i must be [1,6].
+ * @args:      array of argument values to store
+ *
+ * Changes @n arguments to the system call starting with the @i'th argument.
+ * @n'th argument to @val.  Argument @i gets value @args[0], and so on.
+ * An arch inline version is probably optimal when @i and @n are constants.
+ *
+ * It's only valid to call this when @task is stopped for tracing on
+ * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ * It's invalid to call this with @i + @n > 6; we only support system calls
+ * taking up to 6 arguments.
+ */
+void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
+                          unsigned int i, unsigned int n,
+                          const unsigned long *args);
+
+#endif /* _ASM_SYSCALL_H */
index 729f6b0a60e9d1655cfa5005236c5bf11fb83d5c..6d88a923c945cea5b860bb8dc8051c236740f771 100644 (file)
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT                                                      \
                ALIGN_FUNCTION();                                       \
+               *(.text.hot)                                            \
                *(.text)                                                \
                *(.ref.text)                                            \
                *(.text.init.refok)                                     \
        CPU_KEEP(init.text)                                             \
        CPU_KEEP(exit.text)                                             \
        MEM_KEEP(init.text)                                             \
-       MEM_KEEP(exit.text)
+       MEM_KEEP(exit.text)                                             \
+               *(.text.unlikely)
 
 
 /* sched.text is aling to function alignment to secure we have same
        }
 
 #define INITCALLS                                                      \
+       *(.initcallearly.init)                                          \
+       __early_initcall_end = .;                                       \
        *(.initcall0.init)                                              \
        *(.initcall0s.init)                                             \
        *(.initcall1.init)                                              \
index 26bfc7e641daf339b933c269526b98e984734120..a8b57d1f41286261434957bc408057b487628408 100644 (file)
@@ -26,10 +26,10 @@ typedef unsigned long elf_fpregset_t;
 #define ELF_DATA       ELFDATA2MSB
 #define ELF_ARCH       EM_H8_300
 #if defined(__H8300H__)
-#define ELF_FLAGS       0x810000
+#define ELF_CORE_EFLAGS 0x810000
 #endif
 #if defined(__H8300S__)
-#define ELF_FLAGS       0x820000
+#define ELF_CORE_EFLAGS 0x820000
 #endif
 
 #define ELF_PLAT_INIT(_r)      _r->er1 = 0
diff --git a/include/asm-h8300/ide.h b/include/asm-h8300/ide.h
deleted file mode 100644 (file)
index f8535ce..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/****************************************************************************/
-
-/*
- *  linux/include/asm-h8300/ide.h
- *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
- *  Copyright (C) 2001       Lineo Inc., davidm@snapgear.com
- *  Copyright (C) 2002       Greg Ungerer (gerg@snapgear.com)
- *  Copyright (C) 2002       Yoshinori Sato (ysato@users.sourceforge.jp)
- */
-
-/****************************************************************************/
-#ifndef _H8300_IDE_H
-#define _H8300_IDE_H
-/****************************************************************************/
-#ifdef __KERNEL__
-/****************************************************************************/
-
-#define MAX_HWIFS      1
-
-#include <asm-generic/ide_iops.h>
-
-/****************************************************************************/
-#endif /* __KERNEL__ */
-#endif /* _H8300_IDE_H */
-/****************************************************************************/
diff --git a/include/asm-h8300/keyboard.h b/include/asm-h8300/keyboard.h
deleted file mode 100644 (file)
index 90efbd6..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  linux/include/asm-h8300/keyboard.h
- *  Created 04 Dec 2001 by Khaled Hassounah <khassounah@mediumware.net>
- *  This file contains the Dragonball architecture specific keyboard definitions
- */
-
-#ifndef _H8300_KEYBOARD_H
-#define _H8300_KEYBOARD_H
-
-
-/* dummy i.e. no real keyboard */
-#define kbd_setkeycode(x...)   (-ENOSYS)
-#define kbd_getkeycode(x...)   (-ENOSYS)
-#define kbd_translate(x...)    (0)
-#define kbd_unexpected_up(x...)        (1)
-#define kbd_leds(x...)         do {;} while (0)
-#define kbd_init_hw(x...)      do {;} while (0)
-#define kbd_enable_irq(x...)   do {;} while (0)
-#define kbd_disable_irq(x...)  do {;} while (0)
-
-#endif  /* _H8300_KEYBOARD_H */
-
-
-
diff --git a/include/asm-h8300/kvm.h b/include/asm-h8300/kvm.h
deleted file mode 100644 (file)
index bdbed7b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_H8300_H
-#define __LINUX_KVM_H8300_H
-
-/* h8300 does not support KVM */
-
-#endif
diff --git a/include/asm-h8300/namei.h b/include/asm-h8300/namei.h
deleted file mode 100644 (file)
index ab6f196..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * linux/include/asm-h8300/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __H8300_NAMEI_H
-#define __H8300_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif
index d6a3eaf3b27eebfb53395cbeb9ac50cf492124a1..0b6acf0b03aa823a884cd8a861666ef9b1a75ecd 100644 (file)
@@ -43,9 +43,6 @@ typedef struct page *pgtable_t;
 #define __pgd(x)       ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 extern unsigned long memory_start;
 extern unsigned long memory_end;
 
diff --git a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 27bb95e2944c013d8024b58893d17f3585a39c53..aafd4d322ec3e2e8c6767aac9ea125587ff4b322 100644 (file)
@@ -49,6 +49,7 @@ struct thread_info {
 /*
  * Size of kernel stack for each process. This must be a power of 2...
  */
+#define THREAD_SIZE_ORDER      1
 #define THREAD_SIZE            8192    /* 2 pages */
 
 
@@ -65,10 +66,6 @@ static inline struct thread_info *current_thread_info(void)
        return ti;
 }
 
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-                               __get_free_pages(GFP_KERNEL, 1))
-#define free_thread_info(ti)   free_pages((unsigned long) (ti), 1)
 #endif /* __ASSEMBLY__ */
 
 /*
index f28a9701f1cfe94a9d9d55796513b9364c330fe1..da55c63728e0e3f5d2b269d8c6bcb1607bddee57 100644 (file)
@@ -4,11 +4,12 @@
 #include <asm/page.h>
 
 
-void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
                            unsigned long end, unsigned long floor,
                            unsigned long ceiling);
 
-int prepare_hugepage_range(unsigned long addr, unsigned long len);
+int prepare_hugepage_range(struct file *file,
+                       unsigned long addr, unsigned long len);
 
 static inline int is_hugepage_only_range(struct mm_struct *mm,
                                         unsigned long addr,
diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
deleted file mode 100644 (file)
index 8fa3f8c..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  linux/include/asm-ia64/ide.h
- *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
- */
-
-/*
- *  This file contains the ia64 architecture specific IDE code.
- */
-
-#ifndef __ASM_IA64_IDE_H
-#define __ASM_IA64_IDE_H
-
-#ifdef __KERNEL__
-
-
-#include <linux/irq.h>
-
-static inline int ide_default_irq(unsigned long base)
-{
-       switch (base) {
-             case 0x1f0: return isa_irq_to_vector(14);
-             case 0x170: return isa_irq_to_vector(15);
-             case 0x1e8: return isa_irq_to_vector(11);
-             case 0x168: return isa_irq_to_vector(10);
-             case 0x1e0: return isa_irq_to_vector(8);
-             case 0x160: return isa_irq_to_vector(12);
-             default:
-               return 0;
-       }
-}
-
-static inline unsigned long ide_default_io_base(int index)
-{
-       switch (index) {
-             case 0: return 0x1f0;
-             case 1: return 0x170;
-             case 2: return 0x1e8;
-             case 3: return 0x168;
-             case 4: return 0x1e0;
-             case 5: return 0x160;
-             default:
-               return 0;
-       }
-}
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASM_IA64_IDE_H */
index 0721a5e8271e7ffe2181a487689f155b7b85cb89..a6d50c77b6bfaa467eb5ef51c645348316082316 100644 (file)
@@ -54,7 +54,7 @@ typedef void ia64_mv_dma_sync_single_for_cpu (struct device *, dma_addr_t, size_
 typedef void ia64_mv_dma_sync_sg_for_cpu (struct device *, struct scatterlist *, int, int);
 typedef void ia64_mv_dma_sync_single_for_device (struct device *, dma_addr_t, size_t, int);
 typedef void ia64_mv_dma_sync_sg_for_device (struct device *, struct scatterlist *, int, int);
-typedef int ia64_mv_dma_mapping_error (dma_addr_t dma_addr);
+typedef int ia64_mv_dma_mapping_error(struct device *, dma_addr_t dma_addr);
 typedef int ia64_mv_dma_supported (struct device *, u64);
 
 typedef dma_addr_t ia64_mv_dma_map_single_attrs (struct device *, void *, size_t, int, struct dma_attrs *);
diff --git a/include/asm-ia64/namei.h b/include/asm-ia64/namei.h
deleted file mode 100644 (file)
index 78e7680..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _ASM_IA64_NAMEI_H
-#define _ASM_IA64_NAMEI_H
-
-/*
- * Modified 1998, 1999, 2001
- *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-#include <asm/ptrace.h>
-#include <asm/system.h>
-
-#define EMUL_PREFIX_LINUX_IA32 "/emul/ia32-linux/"
-
-static inline char *
-__emul_prefix (void)
-{
-       switch (current->personality) {
-             case PER_LINUX32:
-               return EMUL_PREFIX_LINUX_IA32;
-             default:
-               return NULL;
-       }
-}
-
-#endif /* _ASM_IA64_NAMEI_H */
index 36f39321b7681a305da85b7be173a4c5c171e0b1..5f271bc712ee92675ab0a04b255aa13ec0daa439 100644 (file)
@@ -40,7 +40,6 @@
 
 #define PAGE_SIZE              (__IA64_UL_CONST(1) << PAGE_SHIFT)
 #define PAGE_MASK              (~(PAGE_SIZE - 1))
-#define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
 
 #define PERCPU_PAGE_SHIFT      16      /* log2() of max. size of per-CPU area */
 #define PERCPU_PAGE_SIZE       (__IA64_UL_CONST(1) << PERCPU_PAGE_SHIFT)
diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 2422ac61658a6bb16f465c26acf8c58df1735c6e..7c60fcdd2efdb6f6f79615b051f18c755c4ff69e 100644 (file)
@@ -54,6 +54,8 @@ struct thread_info {
        },                                      \
 }
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 #ifndef ASM_OFFSETS_C
 /* how to get the thread information struct from C */
 #define current_thread_info()  ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
index e60314716122d38d2b7175fcce9281474cb57d46..d535833aab5e54420a72cd8915f8a87a1dda2fb0 100644 (file)
 #define __NR_timerfd_create            1310
 #define __NR_timerfd_settime           1311
 #define __NR_timerfd_gettime           1312
+#define __NR_signalfd4                 1313
+#define __NR_eventfd2                  1314
+#define __NR_epoll_create1             1315
+#define __NR_dup3                      1316
+#define __NR_pipe2                     1317
+#define __NR_inotify_init1             1318
 
 #ifdef __KERNEL__
 
 
-#define NR_syscalls                    289 /* length of syscall table */
+#define NR_syscalls                    295 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
deleted file mode 100644 (file)
index 1e7f647..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef _ASM_M32R_IDE_H
-#define _ASM_M32R_IDE_H
-
-/*
- *  linux/include/asm-m32r/ide.h
- *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
- */
-
-/*
- *  This file contains the i386 architecture specific IDE code.
- */
-
-#ifdef __KERNEL__
-
-#include <asm/m32r.h>
-
-#ifndef MAX_HWIFS
-# ifdef CONFIG_BLK_DEV_IDEPCI
-#define MAX_HWIFS      10
-# else
-#define MAX_HWIFS      2
-# endif
-#endif
-
-static __inline__ int ide_default_irq(unsigned long base)
-{
-       switch (base) {
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \
-       || defined(CONFIG_PLAT_OPSPUT)
-               case 0x1f0: return PLD_IRQ_CFIREQ;
-               default:
-                       return 0;
-#elif defined(CONFIG_PLAT_MAPPI3)
-               case 0x1f0: return PLD_IRQ_CFIREQ;
-               case 0x170: return PLD_IRQ_IDEIREQ;
-               default:
-                       return 0;
-#else
-               case 0x1f0: return 14;
-               case 0x170: return 15;
-               case 0x1e8: return 11;
-               case 0x168: return 10;
-               case 0x1e0: return 8;
-               case 0x160: return 12;
-               default:
-                       return 0;
-#endif
-       }
-}
-
-static __inline__ unsigned long ide_default_io_base(int index)
-{
-       switch (index) {
-               case 0: return 0x1f0;
-               case 1: return 0x170;
-               case 2: return 0x1e8;
-               case 3: return 0x168;
-               case 4: return 0x1e0;
-               case 5: return 0x160;
-               default:
-                       return 0;
-       }
-}
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_M32R_IDE_H */
diff --git a/include/asm-m32r/kvm.h b/include/asm-m32r/kvm.h
deleted file mode 100644 (file)
index 99a4051..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_M32R_H
-#define __LINUX_KVM_M32R_H
-
-/* m32r does not support KVM */
-
-#endif
diff --git a/include/asm-m32r/namei.h b/include/asm-m32r/namei.h
deleted file mode 100644 (file)
index 210f805..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _ASM_M32R_NAMEI_H
-#define _ASM_M32R_NAMEI_H
-
-/*
- * linux/include/asm-m32r/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* _ASM_M32R_NAMEI_H */
index 8a677f3fca683d658dc41c6306ff6828f9df6390..c9333089fe111e5b0e4878bb4c6cd063d6b9271f 100644 (file)
@@ -41,9 +41,6 @@ typedef struct page *pgtable_t;
 
 #endif /* !__ASSEMBLY__ */
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
 /*
  * This handles the memory map.. We could make this a config
  * option, but too many people screw it up, and too few need
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 1effcd0f5e631502eab4eb005e4393a146b14858..8589d462df27e366863974619b5cf293e0b9213c 100644 (file)
@@ -94,6 +94,8 @@ static inline struct thread_info *current_thread_info(void)
        return ti;
 }
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
 #define alloc_thread_info(tsk)                                 \
index a26cdeb46a575e2a0756ed8c4226fe64a4139a9c..91f7944333d49d6ce2f861036cddf0492ce76b9c 100644 (file)
@@ -84,7 +84,7 @@ static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *s
 {
 }
 
-static inline int dma_mapping_error(dma_addr_t handle)
+static inline int dma_mapping_error(struct device *dev, dma_addr_t handle)
 {
        return 0;
 }
index 4fff408d0150879e8acd517e6ce4aa9743e6ee5d..890bbf7e7758b1f3613479d562b084c99ae19442 100644 (file)
@@ -13,7 +13,7 @@
 #define DVMA_PAGE_SHIFT        13
 #define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT)
 #define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1))
-#define DVMA_PAGE_ALIGN(addr)  (((addr)+DVMA_PAGE_SIZE-1)&DVMA_PAGE_MASK)
+#define DVMA_PAGE_ALIGN(addr)  ALIGN(addr, DVMA_PAGE_SIZE)
 
 extern void dvma_init(void);
 extern int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,
index 909c6dfd3851169dae42ac87613a70fc912ece34..1daf6cbdd9f0de3d9b3ae515dd939e887b7dd1e7 100644 (file)
 #include <asm/macints.h>
 #endif
 
-#ifndef MAX_HWIFS
-#define MAX_HWIFS      4       /* same as the other archs */
-#endif
-
 /*
  * Get rid of defs from io.h - ide has its private and conflicting versions
  * Since so far no single m68k platform uses ISA/PCI I/O space for IDE, we
diff --git a/include/asm-m68k/kvm.h b/include/asm-m68k/kvm.h
deleted file mode 100644 (file)
index 7ed27fc..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_M68K_H
-#define __LINUX_KVM_M68K_H
-
-/* m68k does not support KVM */
-
-#endif
diff --git a/include/asm-m68k/namei.h b/include/asm-m68k/namei.h
deleted file mode 100644 (file)
index f33f243..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * linux/include/asm-m68k/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __M68K_NAMEI_H
-#define __M68K_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif
index 880c2cbff8a681cc8619ef50f5b26cd5fd202433..a34b8bad784703b1597c5e15e5f655e3a05a7a3e 100644 (file)
@@ -103,9 +103,6 @@ typedef struct page *pgtable_t;
 #define __pgd(x)       ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 #endif /* !__ASSEMBLY__ */
 
 #include <asm/page_offset.h>
diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index d635a375248896149ba6a14fcfc7392ca62873f0..abc002798a2b07a9fcb502ab0f93c1c7f502ef50 100644 (file)
@@ -25,13 +25,7 @@ struct thread_info {
 }
 
 /* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */
-#if PAGE_SHIFT == 13 /* 8k machines */
-#define alloc_thread_info(tsk)   ((struct thread_info *)__get_free_pages(GFP_KERNEL,0))
-#define free_thread_info(ti)  free_pages((unsigned long)(ti),0)
-#else /* otherwise assume 4k pages */
-#define alloc_thread_info(tsk)   ((struct thread_info *)__get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti)  free_pages((unsigned long)(ti),1)
-#endif /* PAGE_SHIFT == 13 */
+#define THREAD_SIZE_ORDER (13 - PAGE_SHIFT)
 
 #define init_thread_info       (init_task.thread.info)
 #define init_stack             (init_thread_union.stack)
index c142fbf2f376b0abc4767f5c6c048130d5fcd8f2..6f3685eab44c7f88818451d76599f934661a8785 100644 (file)
 #error only <linux/bitops.h> can be included directly
 #endif
 
+#if defined (__mcfisaaplus__) || defined (__mcfisac__)
+static inline int ffs(unsigned int val)
+{
+        if (!val)
+                return 0;
+
+        asm volatile(
+                        "bitrev %0\n\t"
+                        "ff1 %0\n\t"
+                        : "=d" (val)
+                        : "0" (val)
+                   );
+        val++;
+        return val;
+}
+
+static inline int __ffs(unsigned int val)
+{
+        asm volatile(
+                        "bitrev %0\n\t"
+                        "ff1 %0\n\t"
+                        : "=d" (val)
+                        : "0" (val)
+                   );
+        return val;
+}
+
+#else
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/__ffs.h>
+#endif
+
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/ffz.h>
 
index 8fcde907b0f95d4d4c0431529a3a3f22d9c5a82a..20bb4426b610e7665b08c6a6f34b005fea665d18 100644 (file)
@@ -1,13 +1,27 @@
 #ifndef _M68KNOMMU_BYTEORDER_H
 #define _M68KNOMMU_BYTEORDER_H
 
-#include <asm/types.h>
+#include <linux/types.h>
 
 #if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
 #  define __BYTEORDER_HAS_U64__
 #  define __SWAB_64_THRU_32__
 #endif
 
+#if defined (__mcfisaaplus__) || defined (__mcfisac__)
+static inline __attribute_const__ __u32 ___arch__swab32(__u32 val)
+{
+       asm(
+                       "byterev %0"
+                       : "=d" (val)
+                       : "0" (val)
+          );
+       return val;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#endif
+
 #include <linux/byteorder/big_endian.h>
 
 #endif /* _M68KNOMMU_BYTEORDER_H */
index 36e870b468ef0fa1546890f5b8b05516eab60398..edf5eb6c08d2bbe4fbac29223392215173bb28a4 100644 (file)
@@ -519,25 +519,6 @@ typedef struct scc_enet {
 #define SICR_ENET_CLKRT        ((uint)0x00002c00)
 #endif
 
-#ifdef CONFIG_RPXCLASSIC
-/* Bits in parallel I/O port registers that have to be set/cleared
- * to configure the pins for SCC1 use.
- */
-#define PA_ENET_RXD    ((ushort)0x0001)
-#define PA_ENET_TXD    ((ushort)0x0002)
-#define PA_ENET_TCLK   ((ushort)0x0200)
-#define PA_ENET_RCLK   ((ushort)0x0800)
-#define PB_ENET_TENA   ((uint)0x00001000)
-#define PC_ENET_CLSN   ((ushort)0x0010)
-#define PC_ENET_RENA   ((ushort)0x0020)
-
-/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to
- * SCC1.  Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
- */
-#define SICR_ENET_MASK ((uint)0x000000ff)
-#define SICR_ENET_CLKRT        ((uint)0x0000003d)
-#endif
-
 /* SCC Event register as used by Ethernet.
 */
 #define SCCE_ENET_GRA  ((ushort)0x0080)        /* Graceful stop complete */
diff --git a/include/asm-m68knommu/kvm.h b/include/asm-m68knommu/kvm.h
deleted file mode 100644 (file)
index b49d425..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_M68KNOMMU_H
-#define __LINUX_KVM_M68KNOMMU_H
-
-/* m68knommu does not support KVM */
-
-#endif
diff --git a/include/asm-m68knommu/namei.h b/include/asm-m68knommu/namei.h
deleted file mode 100644 (file)
index 31a85d2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/namei.h>
index 1e82ebb7d6442d755266ac2b452f04964ab52b61..3a1ede4544cba4815e357a23daafbb07189f59f1 100644 (file)
@@ -43,9 +43,6 @@ typedef struct page *pgtable_t;
 #define __pgd(x)       ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 extern unsigned long memory_start;
 extern unsigned long memory_end;
 
index 47258e86e8c4a69e996504d52e34abfcea3524a4..8c9194b98548ffee6b4201b47050cc1ae7e0909b 100644 (file)
@@ -68,10 +68,8 @@ struct switch_stack {
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS            12
 #define PTRACE_SETREGS            13
-#ifdef CONFIG_FPU
 #define PTRACE_GETFPREGS          14
 #define PTRACE_SETFPREGS          15
-#endif
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 64c64432bbb80248c44ddfc34a6cc98beff938e1..40f49de69821df7c98f523bf32800228ace3d339 100644 (file)
@@ -118,6 +118,8 @@ asmlinkage void resume(void);
 #define smp_read_barrier_depends()     do { } while(0)
 #endif
 
+#define read_barrier_depends()  ((void)0)
+
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
 struct __xchg_dummy { unsigned long a[100]; };
@@ -310,4 +312,13 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 #endif
 #define arch_align_stack(x) (x)
 
+
+static inline int irqs_disabled_flags(unsigned long flags)
+{
+       if (flags & 0x0700)
+               return 0;
+       else
+               return 1;
+}
+
 #endif /* _M68KNOMMU_SYSTEM_H */
index 95996d978bedcf0d9adc3dd27e1e99f121b79881..0c9bc095f3f0bc3cae753f788f72786a67b96512 100644 (file)
@@ -71,10 +71,6 @@ static inline struct thread_info *current_thread_info(void)
        return ti;
 }
 
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-                               __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
-#define free_thread_info(ti)   free_pages((unsigned long) (ti), THREAD_SIZE_ORDER)
 #endif /* __ASSEMBLY__ */
 
 #define        PREEMPT_ACTIVE  0x4000000
index 230b3f1b69b1015b3d639691200f97ebad45052e..c64afb40cd0698dce532067e66e70d2a27bbbea9 100644 (file)
@@ -42,7 +42,7 @@ extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
        int nelems, enum dma_data_direction direction);
 extern void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
        int nelems, enum dma_data_direction direction);
-extern int dma_mapping_error(dma_addr_t dma_addr);
+extern int dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
 extern int dma_supported(struct device *dev, u64 mask);
 
 static inline int
diff --git a/include/asm-mips/kvm.h b/include/asm-mips/kvm.h
deleted file mode 100644 (file)
index 093a5b7..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_MIPS_H
-#define __LINUX_KVM_MIPS_H
-
-/* mips does not support KVM */
-
-#endif
index 40e6c489833a06ae628460dfbe11326d2541cc6b..08e1958e9410e40c7078fc0fd10d5cafae9ee06c 100644 (file)
@@ -6,7 +6,6 @@
 #define _AU1550_SPI_H_
 
 struct au1550_spi_info {
-       s16 bus_num;            /* defines which PSC and IRQ to use */
        u32 mainclk_hz;         /* main input clock frequency of PSC */
        u16 num_chipselect;     /* number of chipselects supported */
        void (*activate_cs)(struct au1550_spi_info *spi, int cs, int polarity);
index e6b376bd9d06c1c296395f30db8bb397af5f195a..b4e70208da643bdc2e1e8b2ba8ad2c260064160d 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_GENERIC_GPIO_H
 #define __ASM_MACH_GENERIC_GPIO_H
 
-#ifdef CONFIG_HAVE_GPIO_LIB
+#ifdef CONFIG_GPIOLIB
 #define gpio_get_value __gpio_get_value
 #define gpio_set_value __gpio_set_value
 #define gpio_cansleep  __gpio_cansleep
index 0f6c251f5fec20d6668f1bf102edcc33253f5e6b..73008f7bdc93708281e647889a7e3d6c6be87c41 100644 (file)
 #include <linux/stddef.h>
 #include <asm/processor.h>
 
-#ifndef MAX_HWIFS
-# ifdef CONFIG_BLK_DEV_IDEPCI
-#define MAX_HWIFS      10
-# else
-#define MAX_HWIFS      6
-# endif
-#endif
-
 static __inline__ int ide_probe_legacy(void)
 {
 #ifdef CONFIG_PCI
@@ -56,46 +48,6 @@ found:
 #endif
 }
 
-static __inline__ int ide_default_irq(unsigned long base)
-{
-       switch (base) {
-               case 0x1f0: return 14;
-               case 0x170: return 15;
-               case 0x1e8: return 11;
-               case 0x168: return 10;
-               case 0x1e0: return 8;
-               case 0x160: return 12;
-               default:
-                       return 0;
-       }
-}
-
-static __inline__ unsigned long ide_default_io_base(int index)
-{
-       if (!ide_probe_legacy())
-               return 0;
-       /*
-        *      If PCI is present then it is not safe to poke around
-        *      the other legacy IDE ports. Only 0x1f0 and 0x170 are
-        *      defined compatibility mode ports for PCI. A user can
-        *      override this using ide= but we must default safe.
-        */
-       if (no_pci_devices()) {
-               switch (index) {
-               case 2: return 0x1e8;
-               case 3: return 0x168;
-               case 4: return 0x1e0;
-               case 5: return 0x160;
-               }
-       }
-       switch (index) {
-       case 0: return 0x1f0;
-       case 1: return 0x170;
-       default:
-               return 0;
-       }
-}
-
 /* MIPS port and memory-mapped I/O string operations.  */
 static inline void __ide_flush_prologue(void)
 {
diff --git a/include/asm-mips/namei.h b/include/asm-mips/namei.h
deleted file mode 100644 (file)
index a6605a7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_NAMEI_H
-#define _ASM_NAMEI_H
-
-/*
- * This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* _ASM_NAMEI_H */
index 494f00ba9541f6b3cefb4a43e97d990b244182ef..fe7a88ea066e6a655fc4d9a14408d0e54f8bf1d4 100644 (file)
@@ -137,9 +137,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #endif /* !__ASSEMBLY__ */
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
 /*
  * __pa()/__va() should be used only during mem init.
  */
index 58cbac5a64e4472dd45e17c3cef7426b86dbf243..a1e4453469f9af2e09ed52cd3f2b428b46b0c5da 100644 (file)
@@ -45,7 +45,7 @@ extern unsigned int vced_count, vcei_count;
  * This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE     (PAGE_ALIGN(TASK_SIZE / 3))
+#define TASK_UNMAPPED_BASE     ((TASK_SIZE / 3) & ~(PAGE_SIZE))
 #endif
 
 #ifdef CONFIG_64BIT
diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 63f60254d308741efde979586ccdd9456ac47811..facc2d7a87cafaa7220a842cdce0954f15bdd78c 100644 (file)
@@ -102,6 +102,13 @@ enum sock_type {
 };
 
 #define SOCK_MAX (SOCK_PACKET + 1)
+/* Mask which covers at least up to SOCK_MASK-1.  The
+ *  * remaining bits are used as flags. */
+#define SOCK_TYPE_MASK 0xf
+
+/* Flags for socket, socketpair, paccept */
+#define SOCK_CLOEXEC   O_CLOEXEC
+#define SOCK_NONBLOCK  O_NONBLOCK
 
 #define ARCH_HAS_SOCKET_TYPES 1
 
index b2772df1a1bd6270a84da3e9d2fcfc5d0ae06ab8..bb3060699df29f437facbb5631fd44985ca9e69e 100644 (file)
@@ -82,6 +82,8 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
 #define THREAD_MASK (THREAD_SIZE - 1UL)
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 #ifdef CONFIG_DEBUG_STACK_USAGE
 #define alloc_thread_info(tsk)                                 \
 ({                                                             \
index 7c882fca9ec86cd056aa776782f4d2d8e15c01d0..ccae8f6c6326b17f6224ad1e555999a9c9cd5d5a 100644 (file)
@@ -182,7 +182,7 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 }
 
 static inline
-int dma_mapping_error(dma_addr_t dma_addr)
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return 0;
 }
index dc235121ec422e57b7639503701c449d9fc3dae4..6adcdd92e83d942c171f0307c68b45d6a9834d71 100644 (file)
 #undef SUPPORT_VLB_SYNC
 #define SUPPORT_VLB_SYNC 0
 
-#ifndef MAX_HWIFS
-#define MAX_HWIFS 8
-#endif
-
 /*
  * some bits needed for parts of the IDE subsystem to compile
  */
diff --git a/include/asm-mn10300/kvm.h b/include/asm-mn10300/kvm.h
deleted file mode 100644 (file)
index f6b609f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_MN10300_H
-#define __LINUX_KVM_MN10300_H
-
-/* mn10300 does not support KVM */
-
-#endif
diff --git a/include/asm-mn10300/namei.h b/include/asm-mn10300/namei.h
deleted file mode 100644 (file)
index bd9ce94..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Emulation stuff
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#ifndef _ASM_NAMEI_H
-#define _ASM_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* _ASM_NAMEI_H */
index 124971b9fb9bfc91ca464637406a71e3d4651449..8288e124165b50fbd83f73bec88dd391227a9941 100644 (file)
@@ -61,9 +61,6 @@ typedef struct page *pgtable_t;
 
 #endif /* !__ASSEMBLY__ */
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
 /*
  * This handles the memory map.. We could make this a config
  * option, but too many people screw it up, and too few need
index 205192c52bb5708507a58939f870136e2a1d7c0b..cd9cc5c89cea9f524c5d1b4db02f45daff950231 100644 (file)
@@ -74,15 +74,6 @@ struct pci_dev;
 /* This is always fine. */
 #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.
- */
-#define sg_dma_address(sg)     ((sg)->dma_address)
-#define sg_dma_len(sg)         ((sg)->length)
-
 /* Return the index of the PCI controller for device. */
 static inline int pci_controller_num(struct pci_dev *dev)
 {
index b3684689fcceedc7be4f13f7e020559b07bd4cbe..7b06cc623d8b074a3a23511673e2c170bb033840 100644 (file)
@@ -88,12 +88,16 @@ extern struct pt_regs *__frame; /* current frame pointer */
 /* options set using PTRACE_SETOPTIONS */
 #define PTRACE_O_TRACESYSGOOD     0x00000001
 
-#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#if defined(__KERNEL__)
+
+#if !defined(__ASSEMBLY__)
 #define user_mode(regs)                        (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
 #define instruction_pointer(regs)      ((regs)->pc)
 extern void show_regs(struct pt_regs *);
-#endif
+#endif  /*  !__ASSEMBLY  */
 
 #define profile_pc(regs) ((regs)->pc)
 
+#endif  /*  __KERNEL__  */
+
 #endif /* _ASM_PTRACE_H */
index e29d91dbcf2b99fb82fc6b3ebdf8cbd52324f78c..67535901b9ffaf34e2ac366017313bf6dbd44da8 100644 (file)
@@ -43,4 +43,13 @@ struct scatterlist {
 
 #define ISA_DMA_THRESHOLD (0x00ffffff)
 
+/*
+ * 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.
+ */
+#define sg_dma_address(sg)     ((sg)->dma_address)
+#define sg_dma_len(sg)         ((sg)->length)
+
 #endif /* _ASM_SCATTERLIST_H */
diff --git a/include/asm-mn10300/semaphore.h b/include/asm-mn10300/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index e397e719278544b530dd72a3740e8ce06e65da85..78a3881f3c1250f39eea83dc80a320c826ed650d 100644 (file)
@@ -112,6 +112,8 @@ static inline unsigned long current_stack_pointer(void)
        return sp;
 }
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
 #define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
index 2f1e1b05440a50cf1de278e03c7b698cf09851bb..b7ca6dc7fddc89d484f9a210ff24ea48eaf48d74 100644 (file)
@@ -45,9 +45,9 @@ void flush_cache_mm(struct mm_struct *mm);
 extern void flush_dcache_page(struct page *page);
 
 #define flush_dcache_mmap_lock(mapping) \
-       write_lock_irq(&(mapping)->tree_lock)
+       spin_lock_irq(&(mapping)->tree_lock)
 #define flush_dcache_mmap_unlock(mapping) \
-       write_unlock_irq(&(mapping)->tree_lock)
+       spin_unlock_irq(&(mapping)->tree_lock)
 
 #define flush_icache_page(vma,page)    do {            \
        flush_kernel_dcache_page(page);                 \
index c6c0e9ff6bdea3eeb623893fb2d8d3a078d893f9..53af696f23d2fda10025551686d9ce15e01f1f00 100644 (file)
@@ -248,6 +248,6 @@ void * sba_get_iommu(struct parisc_device *dev);
 #endif
 
 /* At the moment, we panic on error for IOMMU resource exaustion */
-#define dma_mapping_error(x)   0
+#define dma_mapping_error(dev, x)      0
 
 #endif
index db0c944100953a1ce46ab8d7caa00f3a81314317..c246ef75017db7fc048699577c0603121bb19f51 100644 (file)
 
 #ifdef __KERNEL__
 
-#ifndef MAX_HWIFS
-#define MAX_HWIFS      2
-#endif
-
 #define ide_request_irq(irq,hand,flg,dev,id)   request_irq((irq),(hand),(flg),(dev),(id))
 #define ide_free_irq(irq,dev_id)               free_irq((irq), (dev_id))
 #define ide_request_region(from,extent,name)   request_region((from), (extent), (name))
diff --git a/include/asm-parisc/kvm.h b/include/asm-parisc/kvm.h
deleted file mode 100644 (file)
index 00cc458..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_PARISC_H
-#define __LINUX_KVM_PARISC_H
-
-/* parisc does not support KVM */
-
-#endif
diff --git a/include/asm-parisc/namei.h b/include/asm-parisc/namei.h
deleted file mode 100644 (file)
index 8d29b3d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $Id: namei.h,v 1.1 1996/12/13 14:48:21 jj Exp $
- * linux/include/asm-parisc/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __PARISC_NAMEI_H
-#define __PARISC_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __PARISC_NAMEI_H */
index 27d50b85954109d123a8e9118a8799a4eadc5221..c3941f09a87891e79c52f05f182ed84e0f0fc0c9 100644 (file)
@@ -119,10 +119,6 @@ extern int npmem_ranges;
 #define PMD_ENTRY_SIZE (1UL << BITS_PER_PMD_ENTRY)
 #define PTE_ENTRY_SIZE (1UL << BITS_PER_PTE_ENTRY)
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-
 #define LINUX_GATEWAY_SPACE     0
 
 /* This governs the relationship between virtual and physical addresses.
index 93f990e418f1cd989e001bdeeec8b9ae60afe9a3..3e94c5d85ff5715a3d95af8e6444b27ae081a1fd 100644 (file)
@@ -33,7 +33,6 @@ struct pt_regs {
        unsigned long ipsw;     /* CR22 */
 };
 
-#define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
 /*
  * The numbers chosen here are somewhat arbitrary but absolutely MUST
  * not overlap with any of the number assigned in <linux/ptrace.h>.
@@ -43,8 +42,11 @@ struct pt_regs {
  * since we have taken branch traps too)
  */
 #define PTRACE_SINGLEBLOCK     12      /* resume execution until next branch */
+
 #ifdef __KERNEL__
 
+#define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
+
 /* XXX should we use iaoq[1] or iaoq[0] ? */
 #define user_mode(regs)                        (((regs)->iaoq[0] & 3) ? 1 : 0)
 #define user_space(regs)               (((regs)->iasq[1] != 0) ? 1 : 0)
diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 69a7a0d30b025335f927979f1eb14e7750d3c09a..fba402c95ac2d403856e141508453646c3a38b5e 100644 (file)
@@ -54,4 +54,9 @@
 
 #define SO_MARK                        0x401f
 
+/* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
+ * have to define SOCK_NONBLOCK to a different value here.
+ */
+#define SOCK_NONBLOCK   0x40000000
+
 #endif /* _ASM_SOCKET_H */
index 2d9c7500867b599ade220a0a086d8d055057c675..9f812741c3553d41a45e8dada845c7bb57fef86a 100644 (file)
@@ -34,15 +34,11 @@ struct thread_info {
 
 /* thread information allocation */
 
-#define THREAD_ORDER            2
+#define THREAD_SIZE_ORDER            2
 /* Be sure to hunt all references to this down when you change the size of
  * the kernel stack */
-#define THREAD_SIZE             (PAGE_SIZE << THREAD_ORDER)
-#define THREAD_SHIFT            (PAGE_SHIFT + THREAD_ORDER)
-
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-                       __get_free_pages(GFP_KERNEL, THREAD_ORDER))
-#define free_thread_info(ti)    free_pages((unsigned long) (ti), THREAD_ORDER)
+#define THREAD_SIZE             (PAGE_SIZE << THREAD_SIZE_ORDER)
+#define THREAD_SHIFT            (PAGE_SHIFT + THREAD_SIZE_ORDER)
 
 /* how to get the thread information struct from C */
 #define current_thread_info()  ((struct thread_info *)mfctl(30))
index 04ce8f8a2ee7ef1319ed00a8bc5e51de94bbde38..5ab7d7fe198ce091708e9ba25066c3788e859ebb 100644 (file)
@@ -29,7 +29,6 @@ unifdef-y += elf.h
 unifdef-y += nvram.h
 unifdef-y += param.h
 unifdef-y += posix_types.h
-unifdef-y += ptrace.h
 unifdef-y += seccomp.h
 unifdef-y += signal.h
 unifdef-y += spu_info.h
index 2a3e9075a5a0732768ebf71b3bb5abcf600cc588..ef8a248dfd558697a374868bf35f4b8e8d5950d1 100644 (file)
@@ -127,6 +127,8 @@ extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr);
 extern void do_feature_fixups(unsigned long value, void *fixup_start,
                              void *fixup_end);
 
+extern const char *powerpc_base_platform;
+
 #endif /* __ASSEMBLY__ */
 
 /* CPU kernel features */
index 74c549780987ba8e9feb48a299c9455c32cfce93..c7ca45f97dd210e9ef611ba8d4877b6f64067021 100644 (file)
@@ -415,7 +415,7 @@ static inline void dma_sync_sg_for_device(struct device *dev,
                __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
 }
 
-static inline int dma_mapping_error(dma_addr_t dma_addr)
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 #ifdef CONFIG_PPC64
        return (dma_addr == DMA_ERROR_CODE);
index 89664675b469d8af2212b826433c4a6861f3b4e5..80d1f399ee513a944aae0b7366a55d588393fac9 100644 (file)
@@ -217,6 +217,14 @@ typedef elf_vrregset_t elf_fpxregset_t;
 
 #define ELF_PLATFORM   (cur_cpu_spec->platform)
 
+/* While ELF_PLATFORM indicates the ISA supported by the platform, it
+ * may not accurately reflect the underlying behavior of the hardware
+ * (as in the case of running in Power5+ compatibility mode on a
+ * Power6 machine).  ELF_BASE_PLATFORM allows ld.so to load libraries
+ * that are tuned for the real hardware.
+ */
+#define ELF_BASE_PLATFORM (powerpc_base_platform)
+
 #ifdef __powerpc64__
 # define ELF_PLAT_INIT(_r, load_addr)  do {    \
        _r->gpr[2] = load_addr;                 \
index ef328995ba9dd9cd3537aeabbcb8be05f5f1e13c..3a179827528d1b8ad53f998fec23d4fd788c77f1 100644 (file)
@@ -46,6 +46,7 @@
 #define FW_FEATURE_PS3_LV1     ASM_CONST(0x0000000000800000)
 #define FW_FEATURE_BEAT                ASM_CONST(0x0000000001000000)
 #define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0000000002000000)
+#define FW_FEATURE_CMO         ASM_CONST(0x0000000004000000)
 
 #ifndef __ASSEMBLY__
 
@@ -58,7 +59,7 @@ enum {
                FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ |
                FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
                FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE |
-               FW_FEATURE_SPLPAR | FW_FEATURE_LPAR,
+               FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | FW_FEATURE_CMO,
        FW_FEATURE_PSERIES_ALWAYS = 0,
        FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
        FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
index 77ad3a890f30589aae9cfacc2ca1abd1c5a2f6ef..ea04632399d8d25f8cf5e4f4720c28bd7dbbaef9 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/errno.h>
 #include <asm-generic/gpio.h>
 
-#ifdef CONFIG_HAVE_GPIO_LIB
+#ifdef CONFIG_GPIOLIB
 
 /*
  * We don't (yet) implement inlined/rapid versions for on-chip gpios.
@@ -51,6 +51,6 @@ static inline int irq_to_gpio(unsigned int irq)
        return -EINVAL;
 }
 
-#endif /* CONFIG_HAVE_GPIO_LIB */
+#endif /* CONFIG_GPIOLIB */
 
 #endif /* __ASM_POWERPC_GPIO_H */
index be32ff02f4a0a6ac174e176a2e87ec3eecc9c23d..26f0d0ab27a50261f99e5d36e831329d30f0834c 100644 (file)
@@ -7,7 +7,7 @@
 int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
                           unsigned long len);
 
-void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
                            unsigned long end, unsigned long floor,
                            unsigned long ceiling);
 
@@ -21,11 +21,13 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
  * If the arch doesn't supply something else, assume that hugepage
  * size aligned regions are ok without further preparation.
  */
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+                       unsigned long addr, unsigned long len)
 {
-       if (len & ~HPAGE_MASK)
+       struct hstate *h = hstate_file(file);
+       if (len & ~huge_page_mask(h))
                return -EINVAL;
-       if (addr & ~HPAGE_MASK)
+       if (addr & ~huge_page_mask(h))
                return -EINVAL;
        return 0;
 }
index bf6cd7cb996cf9f911d52bfaa20ff150a011684c..fbe2932fa9e9660d0a896dea589d4ac1ad6e17c3 100644 (file)
 #define H_EXACT                        (1UL<<(63-24))  /* Use exact PTE or return H_PTEG_FULL */
 #define H_R_XLATE              (1UL<<(63-25))  /* include a valid logical page num in the pte if the valid bit is set */
 #define H_READ_4               (1UL<<(63-26))  /* Return 4 PTEs */
+#define H_PAGE_STATE_CHANGE    (1UL<<(63-28))
+#define H_PAGE_UNUSED          ((1UL<<(63-29)) | (1UL<<(63-30)))
+#define H_PAGE_SET_UNUSED      (H_PAGE_STATE_CHANGE | H_PAGE_UNUSED)
+#define H_PAGE_SET_LOANED      (H_PAGE_SET_UNUSED | (1UL<<(63-31)))
+#define H_PAGE_SET_ACTIVE      H_PAGE_STATE_CHANGE
 #define H_AVPN                 (1UL<<(63-32))  /* An avpn is provided as a sanity test */
 #define H_ANDCOND              (1UL<<(63-33))
 #define H_ICACHE_INVALIDATE    (1UL<<(63-40))  /* icbi, etc.  (ignored for IO pages) */
 #define H_JOIN                 0x298
 #define H_VASI_STATE            0x2A4
 #define H_ENABLE_CRQ           0x2B0
-#define MAX_HCALL_OPCODE       H_ENABLE_CRQ
+#define H_SET_MPP              0x2D0
+#define H_GET_MPP              0x2D4
+#define MAX_HCALL_OPCODE       H_GET_MPP
 
 #ifndef __ASSEMBLY__
 
@@ -270,6 +277,20 @@ struct hcall_stats {
 };
 #define HCALL_STAT_ARRAY_SIZE  ((MAX_HCALL_OPCODE >> 2) + 1)
 
+struct hvcall_mpp_data {
+       unsigned long entitled_mem;
+       unsigned long mapped_mem;
+       unsigned short group_num;
+       unsigned short pool_num;
+       unsigned char mem_weight;
+       unsigned char unallocated_mem_weight;
+       unsigned long unallocated_entitlement;  /* value in bytes */
+       unsigned long pool_size;
+       signed long loan_request;
+       unsigned long backing_mem;
+};
+
+int h_get_mpp(struct hvcall_mpp_data *);
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */
index 3d90bf7d3d73ed19ae011c20b576f422b07e5868..1aaf27be8741a3ab9f52a3e538376a38978be779 100644 (file)
 #endif
 #include <asm/io.h>
 
-#ifndef MAX_HWIFS
-#ifdef __powerpc64__
-#define MAX_HWIFS      10
-#else
-#define MAX_HWIFS      8
-#endif
-#endif
-
 #define __ide_mm_insw(p, a, c) readsw((void __iomem *)(p), (a), (c))
 #define __ide_mm_insl(p, a, c) readsl((void __iomem *)(p), (a), (c))
 #define __ide_mm_outsw(p, a, c)        writesw((void __iomem *)(p), (a), (c))
@@ -39,16 +31,6 @@ static __inline__ int ide_default_irq(unsigned long base)
        case 0x1f0:     return 14;
        case 0x170:     return 15;
        }
-#endif
-#ifdef CONFIG_PPC_PREP
-       switch (base) {
-       case 0x1f0:     return 13;
-       case 0x170:     return 13;
-       case 0x1e8:     return 11;
-       case 0x168:     return 10;
-       case 0xfff0:    return 14;      /* MCP(N)750 ide0 */
-       case 0xffe0:    return 15;      /* MCP(N)750 ide1 */
-       }
 #endif
        return 0;
 }
@@ -61,14 +43,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
        case 0:         return 0x1f0;
        case 1:         return 0x170;
        }
-#endif
-#ifdef CONFIG_PPC_PREP
-       switch (index) {
-       case 0:         return 0x1f0;
-       case 1:         return 0x170;
-       case 2:         return 0x1e8;
-       case 3:         return 0x168;
-       }
 #endif
        return 0;
 }
index 8b627823f5f91c59af24cc6088deebe361d96f28..77c7fa025e658cd736175f16fc4e2144538cdd19 100644 (file)
@@ -617,7 +617,8 @@ static inline void iosync(void)
  *   and can be hooked by the platform via ppc_md
  *
  * * ioremap_flags allows to specify the page flags as an argument and can
- *   also be hooked by the platform via ppc_md
+ *   also be hooked by the platform via ppc_md. ioremap_prot is the exact
+ *   same thing as ioremap_flags.
  *
  * * ioremap_nocache is identical to ioremap
  *
@@ -639,6 +640,8 @@ extern void __iomem *ioremap(phys_addr_t address, unsigned long size);
 extern void __iomem *ioremap_flags(phys_addr_t address, unsigned long size,
                                   unsigned long flags);
 #define ioremap_nocache(addr, size)    ioremap((addr), (size))
+#define ioremap_prot(addr, size, prot) ioremap_flags((addr), (size), (prot))
+
 extern void iounmap(volatile void __iomem *addr);
 
 extern void __iomem *__ioremap(phys_addr_t, unsigned long size,
index 5a21115228af7947c333eb5c4e4cc230623ba243..a8b068792260a56a5371fcec5845a66a634d0453 100644 (file)
@@ -61,7 +61,8 @@ extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
 
 extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn,
                            u64 asid, u32 flags);
-extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid);
+extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
+                                  gva_t eend, u32 asid);
 extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode);
 
 extern void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu);
index 567ed92cd91ff6f1cf0b7193b990de75ec90ede1..2fe268b10333433ad6b2e40bcf2d90c392c45798 100644 (file)
@@ -125,7 +125,10 @@ struct lppaca {
        // NOTE: This value will ALWAYS be zero for dedicated processors and
        // will NEVER be zero for shared processors (ie, initialized to a 1).
        volatile u32 yield_count;       // PLIC increments each dispatchx00-x03
-       u8      reserved6[124];         // Reserved                     x04-x7F
+       u32 reserved6;
+       volatile u64 cmo_faults;        // CMO page fault count         x08-x0F
+       volatile u64 cmo_fault_time;    // CMO page fault time          x10-x17
+       u8      reserved7[104];         // Reserved                     x18-x7F
 
 //=============================================================================
 // CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data
index 1233d735fd289a5831e7d6a542a0912b9cffcf32..893aafd87fde2b20ce7eda9dee61f30b79c9ec91 100644 (file)
@@ -76,7 +76,7 @@ struct machdep_calls {
         * destroyed as well */
        void            (*hpte_clear_all)(void);
 
-       void            (*tce_build)(struct iommu_table * tbl,
+       int             (*tce_build)(struct iommu_table *tbl,
                                     long index,
                                     long npages,
                                     unsigned long uaddr,
index d1dc16afb1186c4a40f374a0e2f5ba3d89ffff2f..19c7a94034900909bb4952944f17bc99c2483b11 100644 (file)
@@ -194,9 +194,9 @@ extern int mmu_ci_restrictions;
 
 #ifdef CONFIG_HUGETLB_PAGE
 /*
- * The page size index of the huge pages for use by hugetlbfs
+ * The page size indexes of the huge pages for use by hugetlbfs
  */
-extern int mmu_huge_psize;
+extern unsigned int mmu_huge_psizes[MMU_PAGE_COUNT];
 
 #endif /* CONFIG_HUGETLB_PAGE */
 
@@ -281,6 +281,8 @@ extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
                             unsigned long pstart, unsigned long mode,
                             int psize, int ssize);
 extern void set_huge_psize(int psize);
+extern void add_gpage(unsigned long addr, unsigned long page_size,
+                         unsigned long number_of_pages);
 extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
 
 extern void htab_initialize(void);
index 710c5d36efaa08496f1a473633acfdf132b3eba1..8917ed63056593377498abaf721e3f33ecaa3b1e 100644 (file)
 #define MPC52xx_PSC_RXTX_FIFO_ALARM    0x0002
 #define MPC52xx_PSC_RXTX_FIFO_EMPTY    0x0001
 
-/* PSC interrupt mask bits */
+/* PSC interrupt status/mask bits */
 #define MPC52xx_PSC_IMR_TXRDY          0x0100
 #define MPC52xx_PSC_IMR_RXRDY          0x0200
 #define MPC52xx_PSC_IMR_DB             0x0400
+#define MPC52xx_PSC_IMR_TXEMP          0x0800
+#define MPC52xx_PSC_IMR_ORERR          0x1000
 #define MPC52xx_PSC_IMR_IPC            0x8000
 
 /* PSC input port change bit */
 
 #define MPC52xx_PSC_RFNUM_MASK 0x01ff
 
+#define MPC52xx_PSC_SICR_DTS1                  (1 << 29)
+#define MPC52xx_PSC_SICR_SHDR                  (1 << 28)
+#define MPC52xx_PSC_SICR_SIM_MASK              (0xf << 24)
+#define MPC52xx_PSC_SICR_SIM_UART              (0x0 << 24)
+#define MPC52xx_PSC_SICR_SIM_UART_DCD          (0x8 << 24)
+#define MPC52xx_PSC_SICR_SIM_CODEC_8           (0x1 << 24)
+#define MPC52xx_PSC_SICR_SIM_CODEC_16          (0x2 << 24)
+#define MPC52xx_PSC_SICR_SIM_AC97              (0x3 << 24)
+#define MPC52xx_PSC_SICR_SIM_SIR               (0x8 << 24)
+#define MPC52xx_PSC_SICR_SIM_SIR_DCD           (0xc << 24)
+#define MPC52xx_PSC_SICR_SIM_MIR               (0x5 << 24)
+#define MPC52xx_PSC_SICR_SIM_FIR               (0x6 << 24)
+#define MPC52xx_PSC_SICR_SIM_CODEC_24          (0x7 << 24)
+#define MPC52xx_PSC_SICR_SIM_CODEC_32          (0xf << 24)
+#define MPC52xx_PSC_SICR_GENCLK                        (1 << 23)
+#define MPC52xx_PSC_SICR_I2S                   (1 << 22)
+#define MPC52xx_PSC_SICR_CLKPOL                        (1 << 21)
+#define MPC52xx_PSC_SICR_SYNCPOL               (1 << 20)
+#define MPC52xx_PSC_SICR_CELLSLAVE             (1 << 19)
+#define MPC52xx_PSC_SICR_CELL2XCLK             (1 << 18)
+#define MPC52xx_PSC_SICR_ESAI                  (1 << 17)
+#define MPC52xx_PSC_SICR_ENAC97                        (1 << 16)
+#define MPC52xx_PSC_SICR_SPI                   (1 << 15)
+#define MPC52xx_PSC_SICR_MSTR                  (1 << 14)
+#define MPC52xx_PSC_SICR_CPOL                  (1 << 13)
+#define MPC52xx_PSC_SICR_CPHA                  (1 << 12)
+#define MPC52xx_PSC_SICR_USEEOF                        (1 << 11)
+#define MPC52xx_PSC_SICR_DISABLEEOF            (1 << 10)
 
 /* Structure of the hardware registers */
 struct mpc52xx_psc {
@@ -132,8 +162,12 @@ struct mpc52xx_psc {
        u8              reserved5[3];
        u8              ctlr;           /* PSC + 0x1c */
        u8              reserved6[3];
-       u16             ccr;            /* PSC + 0x20 */
-       u8              reserved7[14];
+       /* BitClkDiv field of CCR is byte swapped in
+        * the hardware for mpc5200/b compatibility */
+       u32             ccr;            /* PSC + 0x20 */
+       u32             ac97_slots;     /* PSC + 0x24 */
+       u32             ac97_cmd;       /* PSC + 0x28 */
+       u32             ac97_data;      /* PSC + 0x2c */
        u8              ivr;            /* PSC + 0x30 */
        u8              reserved8[3];
        u8              ip;             /* PSC + 0x34 */
diff --git a/include/asm-powerpc/namei.h b/include/asm-powerpc/namei.h
deleted file mode 100644 (file)
index 6574434..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_POWERPC_NAMEI_H
-#define _ASM_POWERPC_NAMEI_H
-
-#ifdef __KERNEL__
-
-/*
- * Adapted from include/asm-alpha/namei.h
- *
- * Included from fs/namei.c
- */
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_NAMEI_H */
index cffdf0eb0df68068fb0720a8ba9adff870be5fbe..e088545cb3f5ea67b2065f962f89c34f4798ae1a 100644 (file)
@@ -119,9 +119,6 @@ extern phys_addr_t kernstart_addr;
 /* align addr on a size boundary - adjust address up if needed */
 #define _ALIGN(addr,size)     _ALIGN_UP(addr,size)
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       _ALIGN(addr, PAGE_SIZE)
-
 /*
  * Don't compare things with KERNELBASE or PAGE_OFFSET to test for
  * "kernelness", use is_kernel_addr() - it should do what you want.
index 02fd80710e9d67219b95f3a060f7a2ab533183c3..043bfdfe4f7379ed90edc7bf5119e25950e159a8 100644 (file)
@@ -90,6 +90,7 @@ extern unsigned int HPAGE_SHIFT;
 #define HPAGE_SIZE             ((1UL) << HPAGE_SHIFT)
 #define HPAGE_MASK             (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
+#define HUGE_MAX_HSTATE                3
 
 #endif /* __ASSEMBLY__ */
 
index 68980990f62a764f3896cfe95830d412f98cf824..812a1d8f35cbc58f21d9096b3ef00c8678d930f9 100644 (file)
@@ -22,7 +22,7 @@ extern struct kmem_cache *pgtable_cache[];
 #define PUD_CACHE_NUM          1
 #define PMD_CACHE_NUM          1
 #define HUGEPTE_CACHE_NUM      2
-#define PTE_NONCACHE_NUM       3  /* from GFP rather than kmem_cache */
+#define PTE_NONCACHE_NUM       7  /* from GFP rather than kmem_cache */
 
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
@@ -119,7 +119,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
        __free_page(ptepage);
 }
 
-#define PGF_CACHENUM_MASK      0x3
+#define PGF_CACHENUM_MASK      0x7
 
 typedef struct pgtable_free {
        unsigned long val;
index fd2090dc1dce776bae664257911516b932230d26..6b18ba9d2d856fabc31e86dc9d6ebbb300aac63d 100644 (file)
 #define _PAGE_GROUP_IX  0x7000 /* software: HPTE index within group */
 #define _PAGE_F_SECOND  _PAGE_SECONDARY
 #define _PAGE_F_GIX     _PAGE_GROUP_IX
+#define _PAGE_SPECIAL  0x10000 /* software: special page */
+#define __HAVE_ARCH_PTE_SPECIAL
 
 /* PTE flags to conserve for HPTE identification */
 #define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | \
                         _PAGE_SECONDARY | _PAGE_GROUP_IX)
 
+/* There is no 4K PFN hack on 4K pages */
+#define _PAGE_4K_PFN   0
+
 /* PAGE_MASK gives the right answer below, but only by accident */
 /* It should be preserving the high 48 bits and then specifically */
 /* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
index c5007712473f1f11c64525c9ae1014c021767cf2..07b0d8f09cb60ecbad1a963193fa0cfec85a0155 100644 (file)
@@ -70,6 +70,8 @@ static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd)
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
 /* Additional PTE bits (don't change without checking asm in hash_low.S) */
+#define __HAVE_ARCH_PTE_SPECIAL
+#define _PAGE_SPECIAL  0x00000400 /* software: special page */
 #define _PAGE_HPTE_SUB 0x0ffff000 /* combo only: sub pages HPTE bits */
 #define _PAGE_HPTE_SUB0        0x08000000 /* combo only: first sub page */
 #define _PAGE_COMBO    0x10000000 /* this is a combo 4k page */
@@ -138,7 +140,7 @@ static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd)
                 unsigned __split = (psize == MMU_PAGE_4K ||                 \
                                    psize == MMU_PAGE_64K_AP);              \
                 shift = mmu_psize_defs[psize].shift;                        \
-               for (index = 0; va < __end; index++, va += (1 << shift)) {  \
+               for (index = 0; va < __end; index++, va += (1L << shift)) { \
                        if (!__split || __rpte_sub_valid(rpte, index)) do { \
 
 #define pte_iterate_hashed_end() } while(0); } } while(0)
index 3a96d001cb7539866ecdbd00e3e53934979f92b6..6fe39e327047d16814f345402303efb75e9822b7 100644 (file)
@@ -395,6 +395,15 @@ extern int icache_44x_need_flush;
 #ifndef _PAGE_EXEC
 #define _PAGE_EXEC     0
 #endif
+#ifndef _PAGE_ENDIAN
+#define _PAGE_ENDIAN   0
+#endif
+#ifndef _PAGE_COHERENT
+#define _PAGE_COHERENT 0
+#endif
+#ifndef _PAGE_WRITETHRU
+#define _PAGE_WRITETHRU        0
+#endif
 #ifndef _PMD_PRESENT_MASK
 #define _PMD_PRESENT_MASK      _PMD_PRESENT
 #endif
@@ -405,6 +414,12 @@ extern int icache_44x_need_flush;
 
 #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
 
+
+#define PAGE_PROT_BITS __pgprot(_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
+                                _PAGE_WRITETHRU | _PAGE_ENDIAN | \
+                                _PAGE_USER | _PAGE_ACCESSED | \
+                                _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \
+                                _PAGE_EXEC | _PAGE_HWEXEC)
 /*
  * Note: the _PAGE_COHERENT bit automatically gets set in the hardware
  * PTE if CONFIG_SMP is defined (hash_page does this); there is no need
@@ -538,6 +553,10 @@ static inline pte_t pte_mkyoung(pte_t pte) {
        pte_val(pte) |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkspecial(pte_t pte) {
        return pte; }
+static inline unsigned long pte_pgprot(pte_t pte)
+{
+       return __pgprot(pte_val(pte)) & PAGE_PROT_BITS;
+}
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
index ab98a9c80b2883b60957a0a7a69f2758de133687..5fc78c0be302fa60e972fbad50f24bb69114351b 100644 (file)
 #define PAGE_AGP       __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE)
 #define HAVE_PAGE_AGP
 
+#define PAGE_PROT_BITS __pgprot(_PAGE_GUARDED | _PAGE_COHERENT | \
+                                _PAGE_NO_CACHE | _PAGE_WRITETHRU | \
+                                _PAGE_4K_PFN | _PAGE_RW | _PAGE_USER | \
+                                _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_EXEC)
 /* PTEIDX nibble */
 #define _PTEIDX_SECONDARY      0x8
 #define _PTEIDX_GROUP_IX       0x7
@@ -241,7 +245,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
 static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
-static inline int pte_special(pte_t pte) { return 0; }
+static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
 
 static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)   { pte_val(pte) &= ~_PAGE_NO_CACHE; }
@@ -261,7 +265,11 @@ static inline pte_t pte_mkyoung(pte_t pte) {
 static inline pte_t pte_mkhuge(pte_t pte) {
        return pte; }
 static inline pte_t pte_mkspecial(pte_t pte) {
-       return pte; }
+       pte_val(pte) |= _PAGE_SPECIAL; return pte; }
+static inline unsigned long pte_pgprot(pte_t pte)
+{
+       return __pgprot(pte_val(pte)) & PAGE_PROT_BITS;
+}
 
 /* Atomic PTE updates */
 static inline unsigned long pte_update(struct mm_struct *mm,
index d18ffe7bc7c4a498a038f0a96f64c81227ac067b..dbb8ca172e445461a8c61bcad3a994bf62276f96 100644 (file)
@@ -38,6 +38,19 @@ extern void paging_init(void);
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 
 #include <asm-generic/pgtable.h>
+
+
+/*
+ * This gets called at the end of handling a page fault, when
+ * the kernel has put a new PTE into the page table for the process.
+ * We use it to ensure coherency between the i-cache and d-cache
+ * for the page which has just been mapped in.
+ * On machines which use an MMU hash table, we use this to put a
+ * corresponding HPTE into the hash table ahead of time, instead of
+ * waiting for the inevitable extra hash-table miss exception.
+ */
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 3d6e31024e5609217e74d45882fd0d118fd45bb2..734e0754fb9bec39a0d8533d77c30ad1c02d1103 100644 (file)
@@ -84,6 +84,7 @@ struct pt_regs {
 #ifndef __ASSEMBLY__
 
 #define instruction_pointer(regs) ((regs)->nip)
+#define user_stack_pointer(regs) ((regs)->gpr[1])
 #define regs_return_value(regs) ((regs)->gpr[3])
 
 #ifdef CONFIG_SMP
diff --git a/include/asm-powerpc/semaphore.h b/include/asm-powerpc/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index a8c7babf4950ca86b8a04eb2d96aef26241fe022..a7360cdd99eb783b6249c58428ffb744d46007d3 100644 (file)
@@ -122,8 +122,7 @@ typedef struct sigaltstack {
 
 #ifdef __KERNEL__
 struct pt_regs;
-extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
-extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
+extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags);
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 #endif /* __KERNEL__ */
 
index 416d4c288ceadca055b6d5c5be33f83b7e71c3a6..4d28e1e4521b8c39992d327a4d0699d8f0df4ba2 100644 (file)
@@ -62,6 +62,8 @@ extern int smp_hw_index[];
 #endif
 
 DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+extern int cpu_to_core_id(int cpu);
 
 /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
  *
diff --git a/include/asm-powerpc/syscall.h b/include/asm-powerpc/syscall.h
new file mode 100644 (file)
index 0000000..efa7f0b
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * See asm-generic/syscall.h for descriptions of what we must do here.
+ */
+
+#ifndef _ASM_SYSCALL_H
+#define _ASM_SYSCALL_H 1
+
+#include <linux/sched.h>
+
+static inline long syscall_get_nr(struct task_struct *task,
+                                 struct pt_regs *regs)
+{
+       return TRAP(regs) == 0xc00 ? regs->gpr[0] : -1L;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+                                   struct pt_regs *regs)
+{
+       regs->gpr[3] = regs->orig_gpr3;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+                                    struct pt_regs *regs)
+{
+       return (regs->ccr & 0x1000) ? -regs->gpr[3] : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+                                           struct pt_regs *regs)
+{
+       return regs->gpr[3];
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+                                           struct pt_regs *regs,
+                                           int error, long val)
+{
+       if (error) {
+               regs->ccr |= 0x1000L;
+               regs->gpr[3] = -error;
+       } else {
+               regs->ccr &= ~0x1000L;
+               regs->gpr[3] = val;
+       }
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned int i, unsigned int n,
+                                        unsigned long *args)
+{
+       BUG_ON(i + n > 6);
+#ifdef CONFIG_PPC64
+       if (test_tsk_thread_flag(task, TIF_32BIT)) {
+               /*
+                * Zero-extend 32-bit argument values.  The high bits are
+                * garbage ignored by the actual syscall dispatch.
+                */
+               while (n-- > 0)
+                       args[n] = (u32) regs->gpr[3 + i + n];
+               return;
+       }
+#endif
+       memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0]));
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned int i, unsigned int n,
+                                        const unsigned long *args)
+{
+       BUG_ON(i + n > 6);
+       memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0]));
+}
+
+#endif /* _ASM_SYSCALL_H */
index 2b8a458f990a8b73e72ac2da42322812f9094bba..eb8eb400c664c3dc6d38fb14637752bb5454e0da 100644 (file)
@@ -31,6 +31,7 @@ asmlinkage int sys_vfork(unsigned long p1, unsigned long p2,
                unsigned long p3, unsigned long p4, unsigned long p5,
                unsigned long p6, struct pt_regs *regs);
 asmlinkage long sys_pipe(int __user *fildes);
+asmlinkage long sys_pipe2(int __user *fildes, int flags);
 asmlinkage long sys_rt_sigaction(int sig,
                const struct sigaction __user *act,
                struct sigaction __user *oact, size_t sigsetsize);
index ae7085c65692136cf7affb8cfdc25dcec8151431..e084272ed1c26f4d5dc985c254f9550093041875 100644 (file)
@@ -316,3 +316,9 @@ COMPAT_SYS(fallocate)
 SYSCALL(subpage_prot)
 COMPAT_SYS_SPU(timerfd_settime)
 COMPAT_SYS_SPU(timerfd_gettime)
+COMPAT_SYS_SPU(signalfd4)
+SYSCALL_SPU(eventfd2)
+SYSCALL_SPU(epoll_create1)
+SYSCALL_SPU(dup3)
+SYSCALL_SPU(pipe2)
+SYSCALL(inotify_init1)
index e6e25e2364ebf87d6012a977d3e5b0d66382820b..d6648c1433221972a6730392236dc8c3c63fe614 100644 (file)
@@ -110,6 +110,8 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
 extern int set_dabr(unsigned long dabr);
+extern void do_dabr(struct pt_regs *regs, unsigned long address,
+                   unsigned long error_code);
 extern void print_backtrace(unsigned long *);
 extern void show_regs(struct pt_regs * regs);
 extern void flush_instruction_cache(void);
index b705c2a7651a929a42780163d6bd303a412f998b..9665a26a253aaef0c118b644ec6635f96b84a83f 100644 (file)
@@ -66,20 +66,12 @@ struct thread_info {
 
 #if THREAD_SHIFT >= PAGE_SHIFT
 
-#define THREAD_ORDER   (THREAD_SHIFT - PAGE_SHIFT)
-
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) \
-       ((struct thread_info *)__get_free_pages(GFP_KERNEL | \
-               __GFP_ZERO, THREAD_ORDER))
-#else
-#define alloc_thread_info(tsk) \
-       ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_ORDER))
-#endif
-#define free_thread_info(ti)   free_pages((unsigned long)ti, THREAD_ORDER)
+#define THREAD_SIZE_ORDER      (THREAD_SHIFT - PAGE_SHIFT)
 
 #else /* THREAD_SHIFT < PAGE_SHIFT */
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
 extern void free_thread_info(struct thread_info *ti);
 
@@ -116,6 +108,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SECCOMP            10      /* secure computing */
 #define TIF_RESTOREALL         11      /* Restore all regs (implies NOERROR) */
 #define TIF_NOERROR            12      /* Force successful syscall return */
+#define TIF_NOTIFY_RESUME      13      /* callback before returning to user */
 #define TIF_FREEZE             14      /* Freezing for suspend */
 #define TIF_RUNLATCH           15      /* Is the runlatch enabled? */
 #define TIF_ABI_PENDING                16      /* 32/64 bit switch needed */
@@ -133,12 +126,14 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_RESTOREALL                (1<<TIF_RESTOREALL)
 #define _TIF_NOERROR           (1<<TIF_NOERROR)
+#define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_FREEZE            (1<<TIF_FREEZE)
 #define _TIF_RUNLATCH          (1<<TIF_RUNLATCH)
 #define _TIF_ABI_PENDING       (1<<TIF_ABI_PENDING)
 #define _TIF_SYSCALL_T_OR_A    (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
-#define _TIF_USER_WORK_MASK    (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
+#define _TIF_USER_WORK_MASK    (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+                                _TIF_NOTIFY_RESUME)
 #define _TIF_PERSYSCALL_MASK   (_TIF_RESTOREALL|_TIF_NOERROR)
 
 /* Bits in local_flags */
index 5c91081476441277c968d0f55067442d4cd20640..361cd5c7a32b428107b6815ae2240fce19de99e1 100644 (file)
@@ -162,16 +162,5 @@ extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
 
 #endif
 
-/*
- * This gets called at the end of handling a page fault, when
- * the kernel has put a new PTE into the page table for the process.
- * We use it to ensure coherency between the i-cache and d-cache
- * for the page which has just been mapped in.
- * On machines which use an MMU hash table, we use this to put a
- * corresponding HPTE into the hash table ahead of time, instead of
- * waiting for the inevitable extra hash-table miss exception.
- */
-extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
-
 #endif /*__KERNEL__ */
 #endif /* _ASM_POWERPC_TLBFLUSH_H */
index 100c6fbfc587058d889b657e61e2b180ae1b2e13..c32da6f9799957a1ce3439b8f9e269bd887621f2 100644 (file)
@@ -108,6 +108,8 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev,
 #include <asm/smp.h>
 
 #define topology_thread_siblings(cpu)  (per_cpu(cpu_sibling_map, cpu))
+#define topology_core_siblings(cpu)    (per_cpu(cpu_core_map, cpu))
+#define topology_core_id(cpu)          (cpu_to_core_id(cpu))
 #endif
 #endif
 
index ce91bb662063401f054b34fbbdd09aee73241673..e07d0c76ed779793280480b50032d0ffefe04c54 100644 (file)
 #define __NR_subpage_prot      310
 #define __NR_timerfd_settime   311
 #define __NR_timerfd_gettime   312
+#define __NR_signalfd4         313
+#define __NR_eventfd2          314
+#define __NR_epoll_create1     315
+#define __NR_dup3              316
+#define __NR_pipe2             317
+#define __NR_inotify_init1     318
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls          313
+#define __NR_syscalls          319
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index 56512a968dab9075666ac15a9437bd3c1a25529c..0a290a19594645b41ac386a21576459705756b7a 100644 (file)
 #define VIO_IRQ_DISABLE                0UL
 #define VIO_IRQ_ENABLE         1UL
 
+/*
+ * VIO CMO minimum entitlement for all devices and spare entitlement
+ */
+#define VIO_CMO_MIN_ENT 1562624
+
 struct iommu_table;
 
-/*
- * The vio_dev structure is used to describe virtual I/O devices.
+/**
+ * vio_dev - This structure is used to describe virtual I/O devices.
+ *
+ * @desired: set from return of driver's get_desired_dma() function
+ * @entitled: bytes of IO data that has been reserved for this device.
+ * @allocated: bytes of IO data currently in use by the device.
+ * @allocs_failed: number of DMA failures due to insufficient entitlement.
  */
 struct vio_dev {
        const char *name;
        const char *type;
        uint32_t unit_address;
        unsigned int irq;
+       struct {
+               size_t desired;
+               size_t entitled;
+               size_t allocated;
+               atomic_t allocs_failed;
+       } cmo;
        struct device dev;
 };
 
@@ -56,12 +72,19 @@ struct vio_driver {
        const struct vio_device_id *id_table;
        int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
        int (*remove)(struct vio_dev *dev);
+       /* A driver must have a get_desired_dma() function to
+        * be loaded in a CMO environment if it uses DMA.
+        */
+       unsigned long (*get_desired_dma)(struct vio_dev *dev);
        struct device_driver driver;
 };
 
 extern int vio_register_driver(struct vio_driver *drv);
 extern void vio_unregister_driver(struct vio_driver *drv);
 
+extern int vio_cmo_entitlement_update(size_t);
+extern void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired);
+
 extern void __devinit vio_unregister_device(struct vio_dev *dev);
 
 struct device_node;
index bb5e9edb9825391bcb152efe3ed79c27b8d5623f..63a23415fba6b2ed4a80d68630f8b240eba9e64b 100644 (file)
@@ -7,7 +7,6 @@ header-y += tape390.h
 header-y += ucontext.h
 header-y += vtoc.h
 header-y += zcrypt.h
-header-y += kvm.h
 header-y += chsc.h
 
 unifdef-y += cmb.h
index 600a776f8f75121fb378ddda4e0aa82427ff7f14..670a1d1745d271e6e89a8246e6432c0c281b3d94 100644 (file)
@@ -22,7 +22,8 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
  * If the arch doesn't supply something else, assume that hugepage
  * size aligned regions are ok without further preparation.
  */
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+                       unsigned long addr, unsigned long len)
 {
        if (len & ~HPAGE_MASK)
                return -EINVAL;
index 3234dd5b3511275521f8f22b3e4f808b432eb257..3c55e4107dcc1864f232aff79d7e8d6b726ca084 100644 (file)
@@ -111,7 +111,7 @@ struct kvm_vcpu_stat {
        u32 exit_validity;
        u32 exit_instruction;
        u32 instruction_lctl;
-       u32 instruction_lctg;
+       u32 instruction_lctlg;
        u32 exit_program_interruption;
        u32 exit_instr_and_program;
        u32 deliver_emergency_signal;
@@ -231,5 +231,5 @@ struct kvm_arch{
        struct kvm_s390_float_interrupt float_int;
 };
 
-extern int sie64a(struct kvm_s390_sie_block *, __u64 *);
+extern int sie64a(struct kvm_s390_sie_block *, unsigned long *);
 #endif
index 5c871a990c2933f03029934440195b939d0e3dce..146100224defc9ffbf30280b724f67a2d7cdbc54 100644 (file)
@@ -50,4 +50,14 @@ struct kvm_vqconfig {
 #define KVM_S390_VIRTIO_RESET          1
 #define KVM_S390_VIRTIO_SET_STATUS     2
 
+#ifdef __KERNEL__
+/* early virtio console setup */
+#ifdef CONFIG_VIRTIO_CONSOLE
+extern void s390_virtio_console_init(void);
+#else
+static inline void s390_virtio_console_init(void)
+{
+}
+#endif /* CONFIG_VIRTIO_CONSOLE */
+#endif /* __KERNEL__ */
 #endif
diff --git a/include/asm-s390/namei.h b/include/asm-s390/namei.h
deleted file mode 100644 (file)
index 3e286bd..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  include/asm-s390/namei.h
- *
- *  S390 version
- *
- *  Derived from "include/asm-i386/namei.h"
- *
- *  Included from linux/fs/namei.c
- */
-
-#ifndef __S390_NAMEI_H
-#define __S390_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __S390_NAMEI_H */
index 12fd9c4f0f154fe86baaed66c71103d24b15f65a..991ba939408c5f9c6b1f9bcdfbc159e715f13554 100644 (file)
@@ -138,9 +138,6 @@ void arch_alloc_page(struct page *page, int order);
 
 #endif /* !__ASSEMBLY__ */
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)        (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 #define __PAGE_OFFSET           0x0UL
 #define PAGE_OFFSET             0x0UL
 #define __pa(x)                 (unsigned long)(x)
diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 99bbed99a3b2d288d17a7154c174dd7de514c390..91a8f93ad355fcfd2e69a710bbc9efb2bba685f0 100644 (file)
@@ -78,10 +78,7 @@ static inline struct thread_info *current_thread_info(void)
        return (struct thread_info *)((*(unsigned long *) __LC_KERNEL_STACK)-THREAD_SIZE);
 }
 
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-       __get_free_pages(GFP_KERNEL,THREAD_ORDER))
-#define free_thread_info(ti) free_pages((unsigned long) (ti),THREAD_ORDER)
+#define THREAD_SIZE_ORDER THREAD_ORDER
 
 #endif
 
index b550a27a7042c85bc856a39b0eec86dcba0ca9a8..720dfab7b15e5b5605714a3511436fd27103e6d9 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/list.h>
 #include <linux/seq_file.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 
 struct clk;
 
@@ -30,6 +31,7 @@ struct clk {
 
        unsigned long           rate;
        unsigned long           flags;
+       unsigned long           arch_flags;
 };
 
 #define CLK_ALWAYS_ENABLED     (1 << 0)
@@ -41,14 +43,27 @@ void arch_init_clk_ops(struct clk_ops **, int type);
 /* arch/sh/kernel/cpu/clock.c */
 int clk_init(void);
 
-int __clk_enable(struct clk *);
-void __clk_disable(struct clk *);
-
 void clk_recalc_rate(struct clk *);
 
 int clk_register(struct clk *);
 void clk_unregister(struct clk *);
 
+static inline int clk_always_enable(const char *id)
+{
+       struct clk *clk;
+       int ret;
+
+       clk = clk_get(NULL, id);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       ret = clk_enable(clk);
+       if (ret)
+               clk_put(clk);
+
+       return ret;
+}
+
 /* the exported API, in addition to clk_set_rate */
 /**
  * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter
index 5fd5c89ef86a8c859429d257f31bc488dfdc47cf..065306d376eb694f59309d4f699ab84478c1b976 100644 (file)
@@ -30,7 +30,6 @@ void flush_dcache_page(struct page *pg);
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
 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);
 
index da46e67ae26d422449e31f51c28b9ce43b3a8eaf..c23af81c2e701805a0656b84ec459181f2c5b8ca 100644 (file)
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7722) || \
     defined(CONFIG_CPU_SUBTYPE_SH7723) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7343) || \
     defined(CONFIG_CPU_SUBTYPE_SH7366)
 #define FRQCR                  0xa4150000
 #define VCLKCR                 0xa4150004
 #define SCLKACR                        0xa4150008
 #define SCLKBCR                        0xa415000c
 #define IrDACLKCR              0xa4150010
+#define MSTPCR0                        0xa4150030
+#define MSTPCR1                        0xa4150034
+#define MSTPCR2                        0xa4150038
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
       defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define        FRQCR                   0xffc80000
index d8f9872b0e2dc3587a9e658adc957f093b7906fb..efd511d0803ad4002fcb73f8a04af39aa51eede3 100644 (file)
@@ -5,3 +5,8 @@
  */
 #include <asm-generic/device.h>
 
+struct platform_device;
+/* allocate contiguous memory chunk and fill in struct resource */
+int platform_resource_setup_memory(struct platform_device *pdev,
+                                  char *name, unsigned long memsize);
+
index 22cc419389fe6b54717f2c13ed8814fa87703ef1..627315ecdb520de2c0f8688a18934fe05c93121f 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/scatterlist.h>
 #include <asm/cacheflush.h>
 #include <asm/io.h>
+#include <asm-generic/dma-coherent.h>
 
 extern struct bus_type pci_bus_type;
 
@@ -171,7 +172,7 @@ static inline int dma_get_cache_alignment(void)
        return L1_CACHE_BYTES;
 }
 
-static inline int dma_mapping_error(dma_addr_t dma_addr)
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return dma_addr == 0;
 }
index 05092da1aa59bdae4c74a5f8903b0cf2fb3e4825..f01449a8d378c498197150df82abf6ab8b439b09 100644 (file)
@@ -1,10 +1,15 @@
 #ifndef __ASM_SH_ELF_H
 #define __ASM_SH_ELF_H
 
+#include <linux/utsname.h>
 #include <asm/auxvec.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
+/* ELF header e_flags defines */
+#define EF_SH_PIC              0x100   /* -fpic */
+#define EF_SH_FDPIC            0x8000  /* -mfdpic */
+
 /* SH (particularly SHcompact) relocation types  */
 #define        R_SH_NONE               0
 #define        R_SH_DIR32              1
 #define        R_SH_RELATIVE           165
 #define        R_SH_GOTOFF             166
 #define        R_SH_GOTPC              167
+
+/* FDPIC relocs */
+#define R_SH_GOT20             70
+#define R_SH_GOTOFF20          71
+#define R_SH_GOTFUNCDESC       72
+#define R_SH_GOTFUNCDESC20     73
+#define R_SH_GOTOFFFUNCDESC    74
+#define R_SH_GOTOFFFUNCDESC20  75
+#define R_SH_FUNCDESC          76
+#define R_SH_FUNCDESC_VALUE    77
+
+#if 0 /* XXX - later .. */
+#define R_SH_GOT20             198
+#define R_SH_GOTOFF20          199
+#define R_SH_GOTFUNCDESC       200
+#define R_SH_GOTFUNCDESC20     201
+#define R_SH_GOTOFFFUNCDESC    202
+#define R_SH_GOTOFFFUNCDESC20  203
+#define R_SH_FUNCDESC          204
+#define R_SH_FUNCDESC_VALUE    205
+#endif
+
 /* SHmedia relocs */
 #define R_SH_IMM_LOW16         246
 #define R_SH_IMM_LOW16_PCREL   247
@@ -77,9 +104,12 @@ typedef struct user_fpu_struct elf_fpregset_t;
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(x) ( (x)->e_machine == EM_SH )
+#define elf_check_arch(x)              ((x)->e_machine == EM_SH)
+#define elf_check_fdpic(x)             ((x)->e_flags & EF_SH_FDPIC)
+#define elf_check_const_displacement(x)        ((x)->e_flags & EF_SH_PIC)
 
 #define USE_ELF_CORE_DUMP
+#define ELF_FDPIC_CORE_EFLAGS  EF_SH_FDPIC
 #define ELF_EXEC_PAGESIZE      PAGE_SIZE
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
@@ -136,6 +166,27 @@ typedef struct user_fpu_struct elf_fpregset_t;
        _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \
        _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; \
        _r->sr = SR_FD; } while (0)
+
+#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr,      \
+                           _dynamic_addr)                              \
+do {                                                                   \
+       _r->regs[0]     = 0;                                            \
+       _r->regs[1]     = 0;                                            \
+       _r->regs[2]     = 0;                                            \
+       _r->regs[3]     = 0;                                            \
+       _r->regs[4]     = 0;                                            \
+       _r->regs[5]     = 0;                                            \
+       _r->regs[6]     = 0;                                            \
+       _r->regs[7]     = 0;                                            \
+       _r->regs[8]     = _exec_map_addr;                               \
+       _r->regs[9]     = _interp_map_addr;                             \
+       _r->regs[10]    = _dynamic_addr;                                \
+       _r->regs[11]    = 0;                                            \
+       _r->regs[12]    = 0;                                            \
+       _r->regs[13]    = 0;                                            \
+       _r->regs[14]    = 0;                                            \
+       _r->sr          = SR_FD;                                        \
+} while (0)
 #endif
 
 #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
index 02402303d89b50111de303715a1560c2d6fdcea9..967068fb79ac483959ccd13436e1c14601133308 100644 (file)
@@ -14,7 +14,8 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
  * If the arch doesn't supply something else, assume that hugepage
  * size aligned regions are ok without further preparation.
  */
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+                       unsigned long addr, unsigned long len)
 {
        if (len & ~HPAGE_MASK)
                return -EINVAL;
@@ -26,7 +27,7 @@ static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
 static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) {
 }
 
-static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
                                          unsigned long addr, unsigned long end,
                                          unsigned long floor,
                                          unsigned long ceiling)
index 7438d1e21bc9b91feb4186d00ef996acb6dd50b6..d557b00111bfb280a19880ae39d4afe779c7976e 100644 (file)
@@ -79,7 +79,7 @@ struct intc_desc {
        struct intc_sense_reg *sense_regs;
        unsigned int nr_sense_regs;
        char *name;
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
        struct intc_mask_reg *ack_regs;
        unsigned int nr_ack_regs;
 #endif
@@ -95,7 +95,7 @@ struct intc_desc symbol __initdata = {                                        \
        chipname,                                                       \
 }
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 #define DECLARE_INTC_DESC_ACK(symbol, chipname, vectors, groups,       \
        mask_regs, prio_regs, sense_regs, ack_regs)                     \
 struct intc_desc symbol __initdata = {                                 \
diff --git a/include/asm-sh/ide.h b/include/asm-sh/ide.h
deleted file mode 100644 (file)
index 58e0bdd..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  linux/include/asm-sh/ide.h
- *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
- */
-
-/*
- *  This file contains the i386 architecture specific IDE code.
- *  In future, SuperH code.
- */
-
-#ifndef __ASM_SH_IDE_H
-#define __ASM_SH_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASM_SH_IDE_H */
diff --git a/include/asm-sh/kvm.h b/include/asm-sh/kvm.h
deleted file mode 100644 (file)
index 6af51db..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_SH_H
-#define __LINUX_KVM_SH_H
-
-/* sh does not support KVM */
-
-#endif
index 2329363afdc3a426cb1f01bf4a7bd06c691a36ac..10016e0f4a4e7c0986d5cef42441d566f2d5c432 100644 (file)
 #include <asm/addrspace.h>
 
 /* GPIO */
-#define MSTPCR0 0xa4150030
-#define MSTPCR1 0xa4150034
-#define MSTPCR2 0xa4150038
-
 #define PORT_PACR 0xa4050100
 #define PORT_PDCR 0xa4050106
 #define PORT_PECR 0xa4050108
 #define PORT_PLCR 0xa4050114
 #define PORT_PMCR 0xa4050116
 #define PORT_PRCR 0xa405011c
+#define PORT_PTCR 0xa4050140
+#define PORT_PUCR 0xa4050142
+#define PORT_PVCR 0xa4050144
 #define PORT_PWCR 0xa4050146
 #define PORT_PXCR 0xa4050148
 #define PORT_PYCR 0xa405014a
 #define PORT_PZCR 0xa405014c
 #define PORT_PADR 0xa4050120
+#define PORT_PHDR 0xa405012e
+#define PORT_PTDR 0xa4050160
 #define PORT_PWDR 0xa4050166
 
 #define PORT_HIZCRA 0xa4050158
@@ -48,6 +49,7 @@
 #define PORT_PSELB 0xa4050150
 #define PORT_PSELC 0xa4050152
 #define PORT_PSELD 0xa4050154
+#define PORT_PSELE 0xa4050156
 
 #define PORT_HIZCRA 0xa4050158
 #define PORT_HIZCRB 0xa405015a
@@ -55,4 +57,9 @@
 
 #define BSC_CS6ABCR 0xfec1001c
 
+#include <asm/sh_mobile_lcdc.h>
+
+int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle,
+                        struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+
 #endif /* __ASM_SH_MIGOR_H */
index eb0358c097d01a3c236b83400e03aa2ac5b757b7..fdcb93bc6d11d3126093409580f9243e7d1b1e8a 100644 (file)
@@ -12,6 +12,10 @@ typedef struct {
        struct vm_list_struct   *vmlist;
        unsigned long           end_brk;
 #endif
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+       unsigned long           exec_fdpic_loadmap;
+       unsigned long           interp_fdpic_loadmap;
+#endif
 } mm_context_t;
 
 /*
index 87e812f68bb06d11c83b5ecca25b72d5cb35366b..8589a50febd0ff5166e63da243c78ffe54ed9c1f 100644 (file)
@@ -27,8 +27,9 @@
 /* ASID is 8-bit value, so it can't be 0x100 */
 #define MMU_NO_ASID                    0x100
 
-#ifdef CONFIG_MMU
 #define asid_cache(cpu)                (cpu_data[cpu].asid_cache)
+
+#ifdef CONFIG_MMU
 #define cpu_context(cpu, mm)   ((mm)->context.id[cpu])
 
 #define cpu_asid(cpu, mm)      \
diff --git a/include/asm-sh/namei.h b/include/asm-sh/namei.h
deleted file mode 100644 (file)
index 338a5d9..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $Id: namei.h,v 1.3 2000/07/04 06:24:49 gniibe Exp $
- * linux/include/asm-sh/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __ASM_SH_NAMEI_H
-#define __ASM_SH_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __ASM_SH_NAMEI_H */
index 304c30b5d9472b0eee5b1d167d5c5d4cd485e881..77fb8bf02e4e846b8dfcb969cac079e3009e768a 100644 (file)
@@ -12,6 +12,8 @@
 # define PAGE_SHIFT    12
 #elif defined(CONFIG_PAGE_SIZE_8KB)
 # define PAGE_SHIFT    13
+#elif defined(CONFIG_PAGE_SIZE_16KB)
+# define PAGE_SHIFT    14
 #elif defined(CONFIG_PAGE_SIZE_64KB)
 # define PAGE_SHIFT    16
 #else
@@ -22,9 +24,6 @@
 #define PAGE_MASK      (~(PAGE_SIZE-1))
 #define PTE_MASK       PAGE_MASK
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 #if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
 #define HPAGE_SHIFT    16
 #elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K)
index cbc731d35c25a1a96f8cef4bef6daa7f2563ccdb..72ea209195bd1103443b6548b7f1f8d483616e21 100644 (file)
 #define _PAGE_FLAGS_HARDWARE_MASK      (PHYS_ADDR_MASK & ~(_PAGE_CLEAR_FLAGS))
 
 /* Hardware flags, page size encoding */
-#if defined(CONFIG_X2TLB)
+#if !defined(CONFIG_MMU)
+# define _PAGE_FLAGS_HARD      0ULL
+#elif defined(CONFIG_X2TLB)
 # if defined(CONFIG_PAGE_SIZE_4KB)
 #  define _PAGE_FLAGS_HARD     _PAGE_EXT(_PAGE_EXT_ESZ0)
 # elif defined(CONFIG_PAGE_SIZE_8KB)
index b7c7ce80f03e110007c75e2a1b32e4b2d2379cda..15d9f92ca383c38c35e001d27828c33d77aff09f 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_SH_PROCESSOR_H
 
 #include <asm/cpu-features.h>
+#include <asm/segment.h>
 
 #ifndef __ASSEMBLY__
 /*
index c09305d6a9d94b2ceabbcf5f8984ceb0fc06af93..c6583f2670715fc3e12f396bc2b17c1d4100c508 100644 (file)
@@ -28,6 +28,7 @@
 
 struct sh_cpuinfo {
        unsigned int type;
+       int cut_major, cut_minor;
        unsigned long loops_per_jiffy;
        unsigned long asid_cache;
 
@@ -113,10 +114,6 @@ 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;
 
index 88a2edf8fa5d000e1070443b736b0accfb3e77b7..fc7fc685ba2790a7c2b1fb97afb3737dfaa1d378 100644 (file)
@@ -166,10 +166,6 @@ struct thread_struct {
        union sh_fpu_union fpu;
 };
 
-typedef struct {
-       unsigned long seg;
-} mm_segment_t;
-
 #define INIT_MMAP \
 { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
 
index 8d6c92b3e770992630b93232bd61135f3c01ae05..643ab5a7cf3b87d466b43e15f4d59cb9b9b077b9 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) 1999, 2000  Niibe Yutaka
  *
  */
-#if defined(__SH5__) || defined(CONFIG_SUPERH64)
+#if defined(__SH5__)
 struct pt_regs {
        unsigned long long pc;
        unsigned long long sr;
@@ -87,6 +87,11 @@ struct pt_dspregs {
        unsigned long   mod;
 };
 
+#define PTRACE_GETFDPIC                31      /* get the ELF fdpic loadmap address */
+
+#define PTRACE_GETFDPIC_EXEC   0       /* [addr] request the executable loadmap */
+#define PTRACE_GETFDPIC_INTERP 1       /* [addr] request the interpreter loadmap */
+
 #define        PTRACE_GETDSPREGS       55
 #define        PTRACE_SETDSPREGS       56
 #endif
index bd2596c014a9d9e77cec4a1f942a27534b7b24e6..eb23000e1bbee1526410891891423fa3919fa259 100644 (file)
 #define IRQ_CFCARD     7
 #endif
 
+/* SH Ether support (SH7710/SH7712) */
+/* Base address */
+#define SH_ETH0_BASE 0xA7000000
+#define SH_ETH1_BASE 0xA7000400
+/* PHY ID */
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+# define PHY_ID 0x00
+#elif defined(CONFIG_CPU_SUBTYPE_SH7712)
+# define PHY_ID 0x01
+#endif
+/* Ether IRQ */
+#define SH_ETH0_IRQ    80
+#define SH_ETH1_IRQ    81
+#define SH_TSU_IRQ     82
+
+void init_se_IRQ(void);
+
 #define __IO_PREFIX    se
 #include <asm/io_generic.h>
 
index e7914a54aa96f285b30d1882b9e93f128ac85f96..98458460e632e58dec0f98f79bbf9d0e8df7fab8 100644 (file)
 #define PA_LCD1                0xb8000000
 #define PA_LCD2                0xb8800000
 
+#define PORT_PACR      0xA4050100
+#define PORT_PBCR      0xA4050102
+#define PORT_PCCR      0xA4050104
+#define PORT_PDCR      0xA4050106
+#define PORT_PECR      0xA4050108
+#define PORT_PFCR      0xA405010A
+#define PORT_PGCR      0xA405010C
+#define PORT_PHCR      0xA405010E
+#define PORT_PJCR      0xA4050110
+#define PORT_PKCR      0xA4050112
+#define PORT_PLCR      0xA4050114
+#define PORT_PMCR      0xA4050116
+#define PORT_PNCR      0xA4050118
+#define PORT_PQCR      0xA405011A
+#define PORT_PRCR      0xA405011C
+#define PORT_PSCR      0xA405011E
+#define PORT_PTCR      0xA4050140
+#define PORT_PUCR      0xA4050142
+#define PORT_PVCR      0xA4050144
+#define PORT_PWCR      0xA4050146
+#define PORT_PYCR      0xA4050148
+#define PORT_PZCR      0xA405014A
+
+#define PORT_PSELA     0xA405014C
+#define PORT_PSELB     0xA405014E
+#define PORT_PSELC     0xA4050150
+#define PORT_PSELD     0xA4050152
+#define PORT_PSELE     0xA4050154
+
+#define PORT_HIZCRA    0xA4050156
+#define PORT_HIZCRB    0xA4050158
+#define PORT_HIZCRC    0xA405015C
+
+#define PORT_DRVCR     0xA4050180
+
+#define PORT_PADR      0xA4050120
+#define PORT_PBDR      0xA4050122
+#define PORT_PCDR      0xA4050124
+#define PORT_PDDR      0xA4050126
+#define PORT_PEDR      0xA4050128
+#define PORT_PFDR      0xA405012A
+#define PORT_PGDR      0xA405012C
+#define PORT_PHDR      0xA405012E
+#define PORT_PJDR      0xA4050130
+#define PORT_PKDR      0xA4050132
+#define PORT_PLDR      0xA4050134
+#define PORT_PMDR      0xA4050136
+#define PORT_PNDR      0xA4050138
+#define PORT_PQDR      0xA405013A
+#define PORT_PRDR      0xA405013C
+#define PORT_PTDR      0xA4050160
+#define PORT_PUDR      0xA4050162
+#define PORT_PVDR      0xA4050164
+#define PORT_PWDR      0xA4050166
+#define PORT_PYDR      0xA4050168
+
+#define FPGA_IN                0xb1400000
+#define FPGA_OUT       0xb1400002
+
 #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 IRQ0_IRQ        32
+#define IRQ1_IRQ        33
+#define IRQ4_IRQ        36
+#define IRQ5_IRQ        37
+
+#define SE7343_FPGA_IRQ_MRSHPC0        0
+#define SE7343_FPGA_IRQ_MRSHPC1        1
+#define SE7343_FPGA_IRQ_MRSHPC2        2
+#define SE7343_FPGA_IRQ_MRSHPC3        3
+#define SE7343_FPGA_IRQ_SMC    6       /* EXT_IRQ2 */
+#define SE7343_FPGA_IRQ_USB    8
 
-#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 SE7343_FPGA_IRQ_NR     11
+#define SE7343_FPGA_IRQ_BASE   120
 
-#define USB_IRQ0       (EXT_IRQ3 + 1)
-#define USB_IRQ1       (USB_IRQ0 + 1)
+#define MRSHPC_IRQ3            (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC3)
+#define MRSHPC_IRQ2            (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC2)
+#define MRSHPC_IRQ1            (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC1)
+#define MRSHPC_IRQ0            (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC0)
+#define SMC_IRQ                (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_SMC)
+#define USB_IRQ                (SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_USB)
 
-#define UART_IRQ0      (USB_IRQ1 + 1)
-#define UART_IRQ1      (UART_IRQ0 + 1)
+/* arch/sh/boards/se/7343/irq.c */
+void init_7343se_IRQ(void);
 
 #endif  /* __ASM_SH_HITACHI_SE7343_H */
index 3690fe5857a4714d38f6cc1592cd820369bab01b..e971d9a82f4a760606954949d9ab81c1eb6dd7a6 100644 (file)
 
 #define PA_LAN         (PA_AREA6_IO + 0)               /* SMC LAN91C111 */
 /* GPIO */
-#define MSTPCR0         0xA4150030UL
-#define MSTPCR1         0xA4150034UL
-#define MSTPCR2         0xA4150038UL
-
 #define FPGA_IN         0xb1840000UL
 #define FPGA_OUT        0xb1840004UL
 
index e417eab4c7d77aedf7b82c9d96bd07045fef6820..5e2725f4ac4901dd6be34c567417bfc06e327824 100644 (file)
@@ -1,6 +1,34 @@
 #ifndef __ASM_SH_SEGMENT_H
 #define __ASM_SH_SEGMENT_H
 
-/* Only here because we have some old header files that expect it.. */
+#ifndef __ASSEMBLY__
 
+typedef struct {
+       unsigned long seg;
+} mm_segment_t;
+
+#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+#define KERNEL_DS      MAKE_MM_SEG(0xFFFFFFFFUL)
+#ifdef CONFIG_MMU
+#define USER_DS                MAKE_MM_SEG(PAGE_OFFSET)
+#else
+#define USER_DS                KERNEL_DS
+#endif
+
+#define segment_eq(a,b)        ((a).seg == (b).seg)
+
+#define get_ds()       (KERNEL_DS)
+
+#define get_fs()       (current_thread_info()->addr_limit)
+#define set_fs(x)      (current_thread_info()->addr_limit = (x))
+
+#endif /* __ASSEMBLY__ */
 #endif /* __ASM_SH_SEGMENT_H */
diff --git a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-sh/sh7760fb.h b/include/asm-sh/sh7760fb.h
new file mode 100644 (file)
index 0000000..8767f61
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * sh7760fb.h -- platform data for SH7760/SH7763 LCDC framebuffer driver.
+ *
+ * (c) 2006-2008 MSC Vertriebsges.m.b.H.,
+ *                     Manuel Lauss <mano@roarinelk.homelinux.net>
+ * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
+ */
+
+#ifndef _ASM_SH_SH7760FB_H
+#define _ASM_SH_SH7760FB_H
+
+/*
+ * some bits of the colormap registers should be written as zero.
+ * create a mask for that.
+ */
+#define SH7760FB_PALETTE_MASK 0x00f8fcf8
+
+/* The LCDC dma engine always sets bits 27-26 to 1: this is Area3 */
+#define SH7760FB_DMA_MASK 0x0C000000
+
+/* palette */
+#define LDPR(x) (((x) << 2))
+
+/* framebuffer registers and bits */
+#define LDICKR 0x400
+#define LDMTR 0x402
+/* see sh7760fb.h for LDMTR bits */
+#define LDDFR 0x404
+#define LDDFR_PABD (1 << 8)
+#define LDDFR_COLOR_MASK 0x7F
+#define LDSMR 0x406
+#define LDSMR_ROT (1 << 13)
+#define LDSARU 0x408
+#define LDSARL 0x40c
+#define LDLAOR 0x410
+#define LDPALCR 0x412
+#define LDPALCR_PALS (1 << 4)
+#define LDPALCR_PALEN (1 << 0)
+#define LDHCNR 0x414
+#define LDHSYNR 0x416
+#define LDVDLNR 0x418
+#define LDVTLNR 0x41a
+#define LDVSYNR 0x41c
+#define LDACLNR 0x41e
+#define LDINTR 0x420
+#define LDPMMR 0x424
+#define LDPSPR 0x426
+#define LDCNTR 0x428
+#define LDCNTR_DON (1 << 0)
+#define LDCNTR_DON2 (1 << 4)
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7763
+# define LDLIRNR       0x440
+/* LDINTR bit */
+# define LDINTR_MINTEN (1 << 15)
+# define LDINTR_FINTEN (1 << 14)
+# define LDINTR_VSINTEN (1 << 13)
+# define LDINTR_VEINTEN (1 << 12)
+# define LDINTR_MINTS (1 << 11)
+# define LDINTR_FINTS (1 << 10)
+# define LDINTR_VSINTS (1 << 9)
+# define LDINTR_VEINTS (1 << 8)
+# define VINT_START (LDINTR_VSINTEN)
+# define VINT_CHECK (LDINTR_VSINTS)
+#else
+/* LDINTR bit */
+# define LDINTR_VINTSEL (1 << 12)
+# define LDINTR_VINTE (1 << 8)
+# define LDINTR_VINTS (1 << 0)
+# define VINT_START (LDINTR_VINTSEL)
+# define VINT_CHECK (LDINTR_VINTS)
+#endif
+
+/* HSYNC polarity inversion */
+#define LDMTR_FLMPOL (1 << 15)
+
+/* VSYNC polarity inversion */
+#define LDMTR_CL1POL (1 << 14)
+
+/* DISPLAY-ENABLE polarity inversion */
+#define LDMTR_DISPEN_LOWACT (1 << 13)
+
+/* DISPLAY DATA BUS polarity inversion */
+#define LDMTR_DPOL_LOWACT (1 << 12)
+
+/* AC modulation signal enable */
+#define LDMTR_MCNT (1 << 10)
+
+/* Disable output of HSYNC during VSYNC period */
+#define LDMTR_CL1CNT (1 << 9)
+
+/* Disable output of VSYNC during VSYNC period */
+#define LDMTR_CL2CNT (1 << 8)
+
+/* Display types supported by the LCDC */
+#define LDMTR_STN_MONO_4       0x00
+#define LDMTR_STN_MONO_8       0x01
+#define LDMTR_STN_COLOR_4      0x08
+#define LDMTR_STN_COLOR_8      0x09
+#define LDMTR_STN_COLOR_12     0x0A
+#define LDMTR_STN_COLOR_16     0x0B
+#define LDMTR_DSTN_MONO_8      0x11
+#define LDMTR_DSTN_MONO_16     0x13
+#define LDMTR_DSTN_COLOR_8     0x19
+#define LDMTR_DSTN_COLOR_12    0x1A
+#define LDMTR_DSTN_COLOR_16    0x1B
+#define LDMTR_TFT_COLOR_16     0x2B
+
+/* framebuffer color layout */
+#define LDDFR_1BPP_MONO 0x00
+#define LDDFR_2BPP_MONO 0x01
+#define LDDFR_4BPP_MONO 0x02
+#define LDDFR_6BPP_MONO 0x04
+#define LDDFR_4BPP 0x0A
+#define LDDFR_8BPP 0x0C
+#define LDDFR_16BPP_RGB555 0x1D
+#define LDDFR_16BPP_RGB565 0x2D
+
+/* LCDC Pixclock sources */
+#define LCDC_CLKSRC_BUSCLOCK 0
+#define LCDC_CLKSRC_PERIPHERAL 1
+#define LCDC_CLKSRC_EXTERNAL 2
+
+#define LDICKR_CLKSRC(x) \
+       (((x) & 3) << 12)
+
+/* LCDC pixclock input divider. Set to 1 at a minimum! */
+#define LDICKR_CLKDIV(x) \
+       ((x) & 0x1f)
+
+struct sh7760fb_platdata {
+
+       /* Set this member to a valid fb_videmode for the display you
+        * wish to use.  The following members must be initialized:
+        * xres, yres, hsync_len, vsync_len, sync,
+        * {left,right,upper,lower}_margin.
+        * The driver uses the above members to calculate register values
+        * and memory requirements. Other members are ignored but may
+        * be used by other framebuffer layer components.
+        */
+       struct fb_videomode *def_mode;
+
+       /* LDMTR includes display type and signal polarity.  The
+        * HSYNC/VSYNC polarities are derived from the fb_var_screeninfo
+        * data above; however the polarities of the following signals
+        * must be encoded in the ldmtr member:
+        * Display Enable signal (default high-active)  DISPEN_LOWACT
+        * Display Data signals (default high-active)   DPOL_LOWACT
+        * AC Modulation signal (default off)           MCNT
+        * Hsync-During-Vsync suppression (default off) CL1CNT
+        * Vsync-during-vsync suppression (default off) CL2CNT
+        * NOTE: also set a display type!
+        * (one of LDMTR_{STN,DSTN,TFT}_{MONO,COLOR}_{4,8,12,16})
+        */
+       u16 ldmtr;
+
+       /* LDDFR controls framebuffer image format (depth, organization)
+        * Use ONE of the LDDFR_?BPP_* macros!
+        */
+       u16 lddfr;
+
+       /* LDPMMR and LDPSPR control the timing of the power signals
+        * for the display. Please read the SH7760 Hardware Manual,
+        * Chapters 30.3.17, 30.3.18 and 30.4.6!
+        */
+       u16 ldpmmr;
+       u16 ldpspr;
+
+       /* LDACLNR contains the line numbers after which the AC modulation
+        * signal is to toggle. Set to ZERO for TFTs or displays which
+        * do not need it. (Chapter 30.3.15 in SH7760 Hardware Manual).
+        */
+       u16 ldaclnr;
+
+       /* LDICKR contains information on pixelclock source and config.
+        * Please use the LDICKR_CLKSRC() and LDICKR_CLKDIV() macros.
+        * minimal value for CLKDIV() must be 1!.
+        */
+       u16 ldickr;
+
+       /* set this member to 1 if you wish to use the LCDC's hardware
+        * rotation function.  This is limited to displays <= 320x200
+        * pixels resolution!
+        */
+       int rotate;             /* set to 1 to rotate 90 CCW */
+
+       /* set this to 1 to suppress vsync irq use. */
+       int novsync;
+
+       /* blanking hook for platform. Set this if your platform can do
+        * more than the LCDC in terms of blanking (e.g. disable clock
+        * generator / backlight power supply / etc.
+        */
+       void (*blank) (int);
+};
+
+#endif /* _ASM_SH_SH7760FB_H */
diff --git a/include/asm-sh/sh7763rdp.h b/include/asm-sh/sh7763rdp.h
new file mode 100644 (file)
index 0000000..8750cc8
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __ASM_SH_SH7763RDP_H
+#define __ASM_SH_SH7763RDP_H
+
+/*
+ * linux/include/asm-sh/sh7763drp.h
+ *
+ * Copyright (C) 2008 Renesas Solutions
+ * Copyright (C) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.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 <asm/addrspace.h>
+
+/* clock control */
+#define MSTPCR1 0xFFC80038
+
+/* PORT */
+#define PORT_PSEL0     0xFFEF0070
+#define PORT_PSEL1     0xFFEF0072
+#define PORT_PSEL2     0xFFEF0074
+#define PORT_PSEL3     0xFFEF0076
+#define PORT_PSEL4     0xFFEF0078
+
+#define PORT_PACR      0xFFEF0000
+#define PORT_PCCR      0xFFEF0004
+#define PORT_PFCR      0xFFEF000A
+#define PORT_PGCR      0xFFEF000C
+#define PORT_PHCR      0xFFEF000E
+#define PORT_PICR      0xFFEF0010
+#define PORT_PJCR      0xFFEF0012
+#define PORT_PKCR      0xFFEF0014
+#define PORT_PLCR      0xFFEF0016
+#define PORT_PMCR      0xFFEF0018
+#define PORT_PNCR      0xFFEF001A
+
+/* FPGA */
+#define CPLD_BOARD_ID_ERV_REG  0xB1000000
+#define CPLD_CPLD_CMD_REG              0xB1000006
+
+/*
+ * USB SH7763RDP board can use Host only.
+ */
+#define USB_USBHSC     0xFFEC80f0
+
+/* arch/sh/boards/renesas/sh7763rdp/irq.c */
+void init_sh7763rdp_IRQ(void);
+int sh7763rdp_irq_demux(int irq);
+#define __IO_PREFIX    sh7763rdp
+#include <asm/io_generic.h>
+
+#endif /* __ASM_SH_SH7763RDP_H */
diff --git a/include/asm-sh/sh7785lcr.h b/include/asm-sh/sh7785lcr.h
new file mode 100644 (file)
index 0000000..1ce27d5
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __ASM_SH_RENESAS_SH7785LCR_H
+#define __ASM_SH_RENESAS_SH7785LCR_H
+
+/*
+ * This board has 2 physical memory maps.
+ * It can be changed with DIP switch(S2-5).
+ *
+ * phys address                        | S2-5 = OFF    | S2-5 = ON
+ * -----------------------------+---------------+---------------
+ * 0x00000000 - 0x03ffffff(CS0)        | NOR Flash     | NOR Flash
+ * 0x04000000 - 0x05ffffff(CS1)        | PLD           | PLD
+ * 0x06000000 - 0x07ffffff(CS1)        | reserved      | I2C
+ * 0x08000000 - 0x0bffffff(CS2)        | USB           | DDR SDRAM
+ * 0x0c000000 - 0x0fffffff(CS3)        | SD            | DDR SDRAM
+ * 0x10000000 - 0x13ffffff(CS4)        | SM107         | SM107
+ * 0x14000000 - 0x17ffffff(CS5)        | I2C           | USB
+ * 0x18000000 - 0x1bffffff(CS6)        | reserved      | SD
+ * 0x40000000 - 0x5fffffff     | DDR SDRAM     | (cannot use)
+ *
+ */
+
+#define NOR_FLASH_ADDR         0x00000000
+#define NOR_FLASH_SIZE         0x04000000
+
+#define PLD_BASE_ADDR          0x04000000
+#define PLD_PCICR              (PLD_BASE_ADDR + 0x00)
+#define PLD_LCD_BK_CONTR       (PLD_BASE_ADDR + 0x02)
+#define PLD_LOCALCR            (PLD_BASE_ADDR + 0x04)
+#define PLD_POFCR              (PLD_BASE_ADDR + 0x06)
+#define PLD_LEDCR              (PLD_BASE_ADDR + 0x08)
+#define PLD_SWSR               (PLD_BASE_ADDR + 0x0a)
+#define PLD_VERSR              (PLD_BASE_ADDR + 0x0c)
+#define PLD_MMSR               (PLD_BASE_ADDR + 0x0e)
+
+#define SM107_MEM_ADDR         0x10000000
+#define SM107_MEM_SIZE         0x00e00000
+#define SM107_REG_ADDR         0x13e00000
+#define SM107_REG_SIZE         0x00200000
+
+#if defined(CONFIG_SH_SH7785LCR_29BIT_PHYSMAPS)
+#define R8A66597_ADDR          0x14000000      /* USB */
+#define CG200_ADDR             0x18000000      /* SD */
+#define PCA9564_ADDR           0x06000000      /* I2C */
+#else
+#define R8A66597_ADDR          0x08000000
+#define CG200_ADDR             0x0c000000
+#define PCA9564_ADDR           0x14000000
+#endif
+
+#define R8A66597_SIZE          0x00000100
+#define CG200_SIZE             0x00010000
+#define PCA9564_SIZE           0x00000100
+
+#endif  /* __ASM_SH_RENESAS_SH7785LCR_H */
+
diff --git a/include/asm-sh/sh_mobile_lcdc.h b/include/asm-sh/sh_mobile_lcdc.h
new file mode 100644 (file)
index 0000000..2767772
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __ASM_SH_MOBILE_LCDC_H__
+#define __ASM_SH_MOBILE_LCDC_H__
+
+#include <linux/fb.h>
+
+enum { RGB8,   /* 24bpp, 8:8:8 */
+       RGB9,   /* 18bpp, 9:9 */
+       RGB12A, /* 24bpp, 12:12 */
+       RGB12B, /* 12bpp */
+       RGB16,  /* 16bpp */
+       RGB18,  /* 18bpp */
+       RGB24,  /* 24bpp */
+       SYS8A,  /* 24bpp, 8:8:8 */
+       SYS8B,  /* 18bpp, 8:8:2 */
+       SYS8C,  /* 18bpp, 2:8:8 */
+       SYS8D,  /* 16bpp, 8:8 */
+       SYS9,   /* 18bpp, 9:9 */
+       SYS12,  /* 24bpp, 12:12 */
+       SYS16A, /* 16bpp */
+       SYS16B, /* 18bpp, 16:2 */
+       SYS16C, /* 18bpp, 2:16 */
+       SYS18,  /* 18bpp */
+       SYS24 };/* 24bpp */
+
+enum { LCDC_CHAN_DISABLED = 0,
+       LCDC_CHAN_MAINLCD,
+       LCDC_CHAN_SUBLCD };
+
+enum { LCDC_CLK_BUS, LCDC_CLK_PERIPHERAL, LCDC_CLK_EXTERNAL };
+
+struct sh_mobile_lcdc_sys_bus_cfg {
+       unsigned long ldmt2r;
+       unsigned long ldmt3r;
+};
+
+struct sh_mobile_lcdc_sys_bus_ops {
+       void (*write_index)(void *handle, unsigned long data);
+       void (*write_data)(void *handle, unsigned long data);
+       unsigned long (*read_data)(void *handle);
+};
+
+struct sh_mobile_lcdc_board_cfg {
+       void *board_data;
+       int (*setup_sys)(void *board_data, void *sys_ops_handle,
+                        struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+       void (*display_on)(void *board_data);
+       void (*display_off)(void *board_data);
+};
+
+struct sh_mobile_lcdc_chan_cfg {
+       int chan;
+       int bpp;
+       int interface_type; /* selects RGBn or SYSn I/F, see above */
+       int clock_divider;
+       struct fb_videomode lcd_cfg;
+       struct sh_mobile_lcdc_board_cfg board_cfg;
+       struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
+};
+
+struct sh_mobile_lcdc_info {
+       unsigned long lddckr;
+       int clock_source;
+       struct sh_mobile_lcdc_chan_cfg ch[2];
+};
+
+#endif /* __ASM_SH_MOBILE_LCDC_H__ */
index e65b6b822cb3722731cf5d4d5bb21673050ac9bb..056d68cd21080e36b4e4a1ad56952751592b8a12 100644 (file)
@@ -148,14 +148,6 @@ extern unsigned long cached_to_uncached;
 
 extern struct dentry *sh_debugfs_root;
 
-/* XXX
- * disable hlt during certain critical i/o operations
- */
-#define HAVE_DISABLE_HLT
-void disable_hlt(void);
-void enable_hlt(void);
-
-void default_idle(void);
 void per_cpu_trap_init(void);
 
 asmlinkage void break_point_trap(void);
index c50e5d35fe84fefe26978011966a5d39f3d2ac7b..eeb4c747119eb2fab268ba854a63b22b9eeb8948 100644 (file)
@@ -38,6 +38,8 @@ struct thread_info {
 #define THREAD_SIZE_ORDER      (1)
 #elif defined(CONFIG_PAGE_SIZE_8KB)
 #define THREAD_SIZE_ORDER      (1)
+#elif defined(CONFIG_PAGE_SIZE_16KB)
+#define THREAD_SIZE_ORDER      (0)
 #elif defined(CONFIG_PAGE_SIZE_64KB)
 #define THREAD_SIZE_ORDER      (0)
 #else
@@ -92,6 +94,8 @@ static inline struct thread_info *current_thread_info(void)
        return ti;
 }
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
 #define alloc_thread_info(ti)  kzalloc(THREAD_SIZE, GFP_KERNEL)
index 701ba84c7049305dd1e763efe671bfbf15ed9439..327f7eb8976aeba1c04068f0c4570867131072b3 100644 (file)
@@ -40,6 +40,5 @@ struct sys_timer *get_sys_timer(void);
 /* arch/sh/kernel/time.c */
 void handle_timer_tick(void);
 extern unsigned long sh_hpt_frequency;
-extern struct clocksource clocksource_sh;
 
 #endif /* __ASM_SH_TIMER_H */
index b3440c305b5d844cf58312e0654c3d515798d761..45c2c9b2993d7ad3b33720966e4a07ddb98d85c2 100644 (file)
 #ifndef __ASM_SH_UACCESS_H
 #define __ASM_SH_UACCESS_H
 
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/segment.h>
+
+#define VERIFY_READ    0
+#define VERIFY_WRITE   1
+
+#define __addr_ok(addr) \
+       ((unsigned long __force)(addr) < current_thread_info()->addr_limit.seg)
+
+/*
+ * __access_ok: Check if address with size is OK or not.
+ *
+ * Uhhuh, this needs 33-bit arithmetic. We have a carry..
+ *
+ * sum := addr + size;  carry? --> flag = true;
+ * if (sum >= addr_limit) flag = true;
+ */
+#define __access_ok(addr, size)                \
+       (__addr_ok((addr) + (size)))
+#define access_ok(type, addr, size)    \
+       (__chk_user_ptr(addr),          \
+        __access_ok((unsigned long __force)(addr), (size)))
+
+/*
+ * Uh, these should become the main single-value transfer routines ...
+ * They automatically use the right size if we just have the right
+ * pointer type ...
+ *
+ * As SuperH uses the same address space for kernel and user data, we
+ * can just do these as direct assignments.
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr)                __put_user_check((x), (ptr), sizeof(*(ptr)))
+#define get_user(x,ptr)                __get_user_check((x), (ptr), sizeof(*(ptr)))
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the user has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x,ptr)      __put_user_nocheck((x), (ptr), sizeof(*(ptr)))
+#define __get_user(x,ptr)      __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct __user *)(x))
+
+#define __get_user_nocheck(x,ptr,size)                         \
+({                                                             \
+       long __gu_err;                                          \
+       unsigned long __gu_val;                                 \
+       const __typeof__(*(ptr)) __user *__gu_addr = (ptr);     \
+       __chk_user_ptr(ptr);                                    \
+       __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
+       (x) = (__typeof__(*(ptr)))__gu_val;                     \
+       __gu_err;                                               \
+})
+
+#define __get_user_check(x,ptr,size)                                   \
+({                                                                     \
+       long __gu_err = -EFAULT;                                        \
+       unsigned long __gu_val = 0;                                     \
+       const __typeof__(*(ptr)) *__gu_addr = (ptr);                    \
+       if (likely(access_ok(VERIFY_READ, __gu_addr, (size))))          \
+               __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
+       (x) = (__typeof__(*(ptr)))__gu_val;                             \
+       __gu_err;                                                       \
+})
+
+#define __put_user_nocheck(x,ptr,size)                         \
+({                                                             \
+       long __pu_err;                                          \
+       __typeof__(*(ptr)) __user *__pu_addr = (ptr);           \
+       __chk_user_ptr(ptr);                                    \
+       __put_user_size((x), __pu_addr, (size), __pu_err);      \
+       __pu_err;                                               \
+})
+
+#define __put_user_check(x,ptr,size)                           \
+({                                                             \
+       long __pu_err = -EFAULT;                                \
+       __typeof__(*(ptr)) __user *__pu_addr = (ptr);           \
+       if (likely(access_ok(VERIFY_WRITE, __pu_addr, size)))   \
+               __put_user_size((x), __pu_addr, (size),         \
+                               __pu_err);                      \
+       __pu_err;                                               \
+})
+
 #ifdef CONFIG_SUPERH32
 # include "uaccess_32.h"
 #else
 # include "uaccess_64.h"
 #endif
 
+/* Generic arbitrary sized copy.  */
+/* Return the number of bytes NOT copied */
+__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
+
+static __always_inline unsigned long
+__copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+       return __copy_user(to, (__force void *)from, n);
+}
+
+static __always_inline unsigned long __must_check
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+       return __copy_user((__force void *)to, from, n);
+}
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+/*
+ * Clear the area and return remaining number of bytes
+ * (on failure.  Usually it's 0.)
+ */
+__kernel_size_t __clear_user(void *addr, __kernel_size_t size);
+
+#define clear_user(addr,n)                                             \
+({                                                                     \
+       void __user * __cl_addr = (addr);                               \
+       unsigned long __cl_size = (n);                                  \
+                                                                       \
+       if (__cl_size && access_ok(VERIFY_WRITE,                        \
+               ((unsigned long)(__cl_addr)), __cl_size))               \
+               __cl_size = __clear_user(__cl_addr, __cl_size);         \
+                                                                       \
+       __cl_size;                                                      \
+})
+
+/**
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+#define strncpy_from_user(dest,src,count)                              \
+({                                                                     \
+       unsigned long __sfu_src = (unsigned long)(src);                 \
+       int __sfu_count = (int)(count);                                 \
+       long __sfu_res = -EFAULT;                                       \
+                                                                       \
+       if (__access_ok(__sfu_src, __sfu_count))                        \
+               __sfu_res = __strncpy_from_user((unsigned long)(dest),  \
+                               __sfu_src, __sfu_count);                \
+                                                                       \
+       __sfu_res;                                                      \
+})
+
 static inline unsigned long
 copy_from_user(void *to, const void __user *from, unsigned long n)
 {
@@ -31,4 +190,67 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
        return __copy_size;
 }
 
+/**
+ * strnlen_user: - Get the size of a string in user space.
+ * @s: The string to measure.
+ * @n: The maximum valid length
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
+static inline long strnlen_user(const char __user *s, long n)
+{
+       if (!__addr_ok(s))
+               return 0;
+       else
+               return __strnlen_user(s, n);
+}
+
+/**
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ *
+ * If there is a limit on the length of a valid string, you may wish to
+ * consider using strnlen_user() instead.
+ */
+#define strlen_user(str)       strnlen_user(str, ~0UL >> 1)
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+struct exception_table_entry {
+       unsigned long insn, fixup;
+};
+
+#if defined(CONFIG_SUPERH64) && defined(CONFIG_MMU)
+#define ARCH_HAS_SEARCH_EXTABLE
+#endif
+
+int fixup_exception(struct pt_regs *regs);
+/* Returns 0 if exception not found and fixup.unit otherwise.  */
+unsigned long search_exception_table(unsigned long addr);
+const struct exception_table_entry *search_exception_tables(unsigned long addr);
+
+
 #endif /* __ASM_SH_UACCESS_H */
index 1e41fda74bd38a0ae459ba884b598b9ed78425ce..892fd6dea9dbb355c432b63ecd699bb9ffb6ae57 100644 (file)
@@ -1,9 +1,8 @@
-/* $Id: uaccess.h,v 1.11 2003/10/13 07:21:20 lethal Exp $
- *
+/*
  * User space memory access functions
  *
  * Copyright (C) 1999, 2002  Niibe Yutaka
- * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2003 - 2008  Paul Mundt
  *
  *  Based on:
  *     MIPS implementation version 1.15 by
 #ifndef __ASM_SH_UACCESS_32_H
 #define __ASM_SH_UACCESS_32_H
 
-#include <linux/errno.h>
-#include <linux/sched.h>
-
-#define VERIFY_READ    0
-#define VERIFY_WRITE   1
-
-/*
- * The fs value determines whether argument validity checking should be
- * performed or not.  If get_fs() == USER_DS, checking is performed, with
- * get_fs() == KERNEL_DS, checking is bypassed.
- *
- * For historical reasons (Data Segment Register?), these macros are misnamed.
- */
-
-#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-
-#define KERNEL_DS      MAKE_MM_SEG(0xFFFFFFFFUL)
-#define USER_DS                MAKE_MM_SEG(PAGE_OFFSET)
-
-#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;
-}
-
-static inline void set_fs(mm_segment_t s)
-{
-}
-
-/*
- * __access_ok: Check if address with size is OK or not.
- *
- * If we don't have an MMU (or if its disabled) the only thing we really have
- * to look out for is if the address resides somewhere outside of what
- * available RAM we have.
- */
-static inline int __access_ok(unsigned long addr, unsigned long size)
-{
-       return 1;
-}
-#else /* CONFIG_MMU */
-#define __addr_ok(addr) \
-       ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
-
-#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.
- *
- * Uhhuh, this needs 33-bit arithmetic. We have a carry..
- *
- * sum := addr + size;  carry? --> flag = true;
- * if (sum >= addr_limit) flag = true;
- */
-static inline int __access_ok(unsigned long addr, unsigned long size)
-{
-       unsigned long flag, sum;
-
-       __asm__("clrt\n\t"
-               "addc   %3, %1\n\t"
-               "movt   %0\n\t"
-               "cmp/hi %4, %1\n\t"
-               "rotcl  %0"
-               :"=&r" (flag), "=r" (sum)
-               :"1" (addr), "r" (size),
-                "r" (current_thread_info()->addr_limit.seg)
-               :"t");
-       return flag == 0;
-}
-#endif /* CONFIG_MMU */
-
-#define access_ok(type, addr, size)    \
-       (__chk_user_ptr(addr),          \
-        __access_ok((unsigned long __force)(addr), (size)))
-
-/*
- * Uh, these should become the main single-value transfer routines ...
- * They automatically use the right size if we just have the right
- * pointer type ...
- *
- * As SuperH uses the same address space for kernel and user data, we
- * can just do these as direct assignments.
- *
- * Careful to not
- * (a) re-use the arguments for side effects (sizeof is ok)
- * (b) require any knowledge of processes at this stage
- */
-#define put_user(x,ptr)                __put_user_check((x), (ptr), sizeof(*(ptr)))
-#define get_user(x,ptr)                __get_user_check((x), (ptr), sizeof(*(ptr)))
-
-/*
- * The "__xxx" versions do not do address space checking, useful when
- * doing multiple accesses to the same area (the user has to do the
- * checks by hand with "access_ok()")
- */
-#define __put_user(x,ptr)      __put_user_nocheck((x), (ptr), sizeof(*(ptr)))
-#define __get_user(x,ptr)      __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
-
-struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct __user *)(x))
-
 #define __get_user_size(x,ptr,size,retval)                     \
 do {                                                           \
        retval = 0;                                             \
@@ -141,28 +31,7 @@ do {                                                                \
        }                                                       \
 } while (0)
 
-#define __get_user_nocheck(x,ptr,size)                         \
-({                                                             \
-       long __gu_err;                                          \
-       unsigned long __gu_val;                                 \
-       const __typeof__(*(ptr)) __user *__gu_addr = (ptr);     \
-       __chk_user_ptr(ptr);                                    \
-       __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
-       (x) = (__typeof__(*(ptr)))__gu_val;                     \
-       __gu_err;                                               \
-})
-
-#define __get_user_check(x,ptr,size)                                   \
-({                                                                     \
-       long __gu_err = -EFAULT;                                        \
-       unsigned long __gu_val = 0;                                     \
-       const __typeof__(*(ptr)) *__gu_addr = (ptr);                    \
-       if (likely(access_ok(VERIFY_READ, __gu_addr, (size))))          \
-               __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
-       (x) = (__typeof__(*(ptr)))__gu_val;                             \
-       __gu_err;                                                       \
-})
-
+#ifdef CONFIG_MMU
 #define __get_user_asm(x, addr, err, insn) \
 ({ \
 __asm__ __volatile__( \
@@ -183,6 +52,16 @@ __asm__ __volatile__( \
        ".previous" \
        :"=&r" (err), "=&r" (x) \
        :"m" (__m(addr)), "i" (-EFAULT), "0" (err)); })
+#else
+#define __get_user_asm(x, addr, err, insn)             \
+do {                                                   \
+       __asm__ __volatile__ (                          \
+               "mov." insn "   %1, %0\n\t"             \
+               : "=&r" (x)                             \
+               : "m" (__m(addr))                       \
+       );                                              \
+} while (0)
+#endif /* CONFIG_MMU */
 
 extern void __get_user_unknown(void);
 
@@ -197,7 +76,8 @@ do {                                                 \
                __put_user_asm(x, ptr, retval, "w");    \
                break;                                  \
        case 4:                                         \
-               __put_user_asm(x, ptr, retval, "l");    \
+               __put_user_asm((u32)x, ptr,             \
+                              retval, "l");            \
                break;                                  \
        case 8:                                         \
                __put_user_u64(x, ptr, retval);         \
@@ -207,45 +87,41 @@ do {                                                       \
        }                                               \
 } while (0)
 
-#define __put_user_nocheck(x,ptr,size)                         \
-({                                                             \
-       long __pu_err;                                          \
-       __typeof__(*(ptr)) __user *__pu_addr = (ptr);           \
-       __chk_user_ptr(ptr);                                    \
-       __put_user_size((x), __pu_addr, (size), __pu_err);      \
-       __pu_err;                                               \
-})
-
-#define __put_user_check(x,ptr,size)                           \
-({                                                             \
-       long __pu_err = -EFAULT;                                \
-       __typeof__(*(ptr)) __user *__pu_addr = (ptr);           \
-       if (likely(access_ok(VERIFY_WRITE, __pu_addr, size)))   \
-               __put_user_size((x), __pu_addr, (size),         \
-                               __pu_err);                      \
-       __pu_err;                                               \
-})
-
-#define __put_user_asm(x, addr, err, insn) \
-({ \
-__asm__ __volatile__( \
-       "1:\n\t" \
-       "mov." insn "   %1, %2\n\t" \
-       "2:\n" \
-       ".section       .fixup,\"ax\"\n" \
-       "3:\n\t" \
-       "mov.l  4f, %0\n\t" \
-       "jmp    @%0\n\t" \
-       " mov   %3, %0\n\t" \
-       ".balign        4\n" \
-       "4:     .long   2b\n\t" \
-       ".previous\n" \
-       ".section       __ex_table,\"a\"\n\t" \
-       ".long  1b, 3b\n\t" \
-       ".previous" \
-       :"=&r" (err) \
-       :"r" (x), "m" (__m(addr)), "i" (-EFAULT), "0" (err)     \
-        :"memory"); })
+#ifdef CONFIG_MMU
+#define __put_user_asm(x, addr, err, insn)                     \
+do {                                                           \
+       __asm__ __volatile__ (                                  \
+               "1:\n\t"                                        \
+               "mov." insn "   %1, %2\n\t"                     \
+               "2:\n"                                          \
+               ".section       .fixup,\"ax\"\n"                \
+               "3:\n\t"                                        \
+               "mov.l  4f, %0\n\t"                             \
+               "jmp    @%0\n\t"                                \
+               " mov   %3, %0\n\t"                             \
+               ".balign        4\n"                            \
+               "4:     .long   2b\n\t"                         \
+               ".previous\n"                                   \
+               ".section       __ex_table,\"a\"\n\t"           \
+               ".long  1b, 3b\n\t"                             \
+               ".previous"                                     \
+               : "=&r" (err)                                   \
+               : "r" (x), "m" (__m(addr)), "i" (-EFAULT),      \
+                 "0" (err)                                     \
+               : "memory"                                      \
+       );                                                      \
+} while (0)
+#else
+#define __put_user_asm(x, addr, err, insn)             \
+do {                                                   \
+       __asm__ __volatile__ (                          \
+               "mov." insn "   %0, %1\n\t"             \
+               : /* no outputs */                      \
+               : "r" (x), "m" (__m(addr))              \
+               : "memory"                              \
+       );                                              \
+} while (0)
+#endif /* CONFIG_MMU */
 
 #if defined(CONFIG_CPU_LITTLE_ENDIAN)
 #define __put_user_u64(val,addr,retval) \
@@ -295,40 +171,7 @@ __asm__ __volatile__( \
 
 extern void __put_user_unknown(void);
 
-/* Generic arbitrary sized copy.  */
-/* Return the number of bytes NOT copied */
-__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
-
-
-static __always_inline unsigned long
-__copy_from_user(void *to, const void __user *from, unsigned long n)
-{
-       return __copy_user(to, (__force void *)from, n);
-}
-
-static __always_inline unsigned long __must_check
-__copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-       return __copy_user((__force void *)to, from, n);
-}
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-/*
- * Clear the area and return remaining number of bytes
- * (on failure.  Usually it's 0.)
- */
-extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
-
-#define clear_user(addr,n) ({ \
-void * __cl_addr = (addr); \
-unsigned long __cl_size = (n); \
-if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \
-__cl_size = __clear_user(__cl_addr, __cl_size); \
-__cl_size; })
-
-static __inline__ int
+static inline int
 __strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count)
 {
        __kernel_size_t res;
@@ -367,37 +210,11 @@ __strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __coun
        return res;
 }
 
-/**
- * strncpy_from_user: - Copy a NUL terminated string from userspace.
- * @dst:   Destination address, in kernel space.  This buffer must be at
- *         least @count bytes long.
- * @src:   Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-#define strncpy_from_user(dest,src,count) ({ \
-unsigned long __sfu_src = (unsigned long) (src); \
-int __sfu_count = (int) (count); \
-long __sfu_res = -EFAULT; \
-if(__access_ok(__sfu_src, __sfu_count)) { \
-__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
-} __sfu_res; })
-
 /*
  * Return the size of a string (including the ending 0 even when we have
  * exceeded the maximum string length).
  */
-static __inline__ long __strnlen_user(const char __user *__s, long __n)
+static inline long __strnlen_user(const char __user *__s, long __n)
 {
        unsigned long res;
        unsigned long __dummy;
@@ -429,61 +246,4 @@ static __inline__ long __strnlen_user(const char __user *__s, long __n)
        return res;
 }
 
-/**
- * strnlen_user: - Get the size of a string in user space.
- * @s: The string to measure.
- * @n: The maximum valid length
- *
- * Context: User context only.  This function may sleep.
- *
- * Get the size of a NUL-terminated string in user space.
- *
- * Returns the size of the string INCLUDING the terminating NUL.
- * On exception, returns 0.
- * If the string is too long, returns a value greater than @n.
- */
-static __inline__ long strnlen_user(const char __user *s, long n)
-{
-       if (!__addr_ok(s))
-               return 0;
-       else
-               return __strnlen_user(s, n);
-}
-
-/**
- * strlen_user: - Get the size of a string in user space.
- * @str: The string to measure.
- *
- * Context: User context only.  This function may sleep.
- *
- * Get the size of a NUL-terminated string in user space.
- *
- * Returns the size of the string INCLUDING the terminating NUL.
- * On exception, returns 0.
- *
- * If there is a limit on the length of a valid string, you may wish to
- * consider using strnlen_user() instead.
- */
-#define strlen_user(str)       strnlen_user(str, ~0UL >> 1)
-
-/*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue.  No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
- *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path.  This means when everything is well,
- * we don't even have to jump over them.  Further, they do not intrude
- * on our cache or tlb entries.
- */
-
-struct exception_table_entry
-{
-       unsigned long insn, fixup;
-};
-
-extern int fixup_exception(struct pt_regs *regs);
-
 #endif /* __ASM_SH_UACCESS_32_H */
index a9b68d094844eb7a93556edf8e7c0016d380f46c..81b3d515fcb36920938de61b13412a0d75e95fe4 100644 (file)
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-#include <linux/errno.h>
-#include <linux/sched.h>
-
-#define VERIFY_READ    0
-#define VERIFY_WRITE   1
-
-/*
- * The fs value determines whether argument validity checking should be
- * performed or not.  If get_fs() == USER_DS, checking is performed, with
- * get_fs() == KERNEL_DS, checking is bypassed.
- *
- * For historical reasons (Data Segment Register?), these macros are misnamed.
- */
-
-#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-
-#define KERNEL_DS      MAKE_MM_SEG(0xFFFFFFFF)
-#define USER_DS                MAKE_MM_SEG(0x80000000)
-
-#define get_ds()       (KERNEL_DS)
-#define get_fs()        (current_thread_info()->addr_limit)
-#define set_fs(x)       (current_thread_info()->addr_limit=(x))
-
-#define segment_eq(a,b)        ((a).seg == (b).seg)
-
-#define __addr_ok(addr) ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
-
-/*
- * Uhhuh, this needs 33-bit arithmetic. We have a carry..
- *
- * sum := addr + size;  carry? --> flag = true;
- * if (sum >= addr_limit) flag = true;
- */
-#define __range_ok(addr,size) (((unsigned long) (addr) + (size) < (current_thread_info()->addr_limit.seg)) ? 0 : 1)
-
-#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
-#define __access_ok(addr,size) (__range_ok(addr,size) == 0)
-
-/*
- * Uh, these should become the main single-value transfer routines ...
- * They automatically use the right size if we just have the right
- * pointer type ...
- *
- * As MIPS uses the same address space for kernel and user data, we
- * can just do these as direct assignments.
- *
- * Careful to not
- * (a) re-use the arguments for side effects (sizeof is ok)
- * (b) require any knowledge of processes at this stage
- */
-#define put_user(x,ptr)        __put_user_check((x),(ptr),sizeof(*(ptr)))
-#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)))
-
-/*
- * The "__xxx" versions do not do address space checking, useful when
- * doing multiple accesses to the same area (the user has to do the
- * checks by hand with "access_ok()")
- */
-#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
-#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
-
-/*
- * The "xxx_ret" versions return constant specified in third argument, if
- * something bad happens. These macros can be optimized for the
- * case of just returning from the function xxx_ret is used.
- */
-
-#define put_user_ret(x,ptr,ret) ({ \
-if (put_user(x,ptr)) return ret; })
-
-#define get_user_ret(x,ptr,ret) ({ \
-if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ \
-if (__put_user(x,ptr)) return ret; })
-
-#define __get_user_ret(x,ptr,ret) ({ \
-if (__get_user(x,ptr)) return ret; })
-
-struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
 
 #define __get_user_size(x,ptr,size,retval)                     \
 do {                                                           \
@@ -124,26 +43,6 @@ do {                                                                \
        }                                                       \
 } while (0)
 
-#define __get_user_nocheck(x,ptr,size)                         \
-({                                                             \
-       long __gu_err, __gu_val;                                \
-       __get_user_size((void *)&__gu_val, (long)(ptr),         \
-                       (size), __gu_err);                      \
-       (x) = (__typeof__(*(ptr)))__gu_val;                     \
-       __gu_err;                                               \
-})
-
-#define __get_user_check(x,ptr,size)                           \
-({                                                             \
-       long __gu_addr = (long)(ptr);                           \
-       long __gu_err = -EFAULT, __gu_val;                      \
-       if (__access_ok(__gu_addr, (size)))                     \
-               __get_user_size((void *)&__gu_val, __gu_addr,   \
-                               (size), __gu_err);              \
-       (x) = (__typeof__(*(ptr))) __gu_val;                    \
-       __gu_err;                                               \
-})
-
 extern long __get_user_asm_b(void *, long);
 extern long __get_user_asm_w(void *, long);
 extern long __get_user_asm_l(void *, long);
@@ -171,115 +70,10 @@ do {                                                              \
        }                                                       \
 } while (0)
 
-#define __put_user_nocheck(x,ptr,size)                         \
-({                                                             \
-       long __pu_err;                                          \
-       __typeof__(*(ptr)) __pu_val = (x);                      \
-       __put_user_size((void *)&__pu_val, (long)(ptr), (size), __pu_err); \
-       __pu_err;                                               \
-})
-
-#define __put_user_check(x,ptr,size)                           \
-({                                                             \
-       long __pu_err = -EFAULT;                                \
-       long __pu_addr = (long)(ptr);                           \
-       __typeof__(*(ptr)) __pu_val = (x);                      \
-                                                               \
-       if (__access_ok(__pu_addr, (size)))                     \
-               __put_user_size((void *)&__pu_val, __pu_addr, (size), __pu_err);\
-       __pu_err;                                               \
-})
-
 extern long __put_user_asm_b(void *, long);
 extern long __put_user_asm_w(void *, long);
 extern long __put_user_asm_l(void *, long);
 extern long __put_user_asm_q(void *, long);
 extern void __put_user_unknown(void);
 
-\f
-/* Generic arbitrary sized copy.  */
-/* Return the number of bytes NOT copied */
-/* XXX: should be such that: 4byte and the rest. */
-extern __kernel_size_t __copy_user(void *__to, const void *__from, __kernel_size_t __n);
-
-#define copy_to_user_ret(to,from,n,retval) ({ \
-if (copy_to_user(to,from,n)) \
-       return retval; \
-})
-
-#define __copy_to_user(to,from,n)              \
-       __copy_user((void *)(to),               \
-                   (void *)(from), n)
-
-#define __copy_to_user_ret(to,from,n,retval) ({ \
-if (__copy_to_user(to,from,n)) \
-       return retval; \
-})
-
-#define copy_from_user_ret(to,from,n,retval) ({ \
-if (copy_from_user(to,from,n)) \
-       return retval; \
-})
-
-#define __copy_from_user(to,from,n)            \
-       __copy_user((void *)(to),               \
-                   (void *)(from), n)
-
-#define __copy_from_user_ret(to,from,n,retval) ({ \
-if (__copy_from_user(to,from,n)) \
-       return retval; \
-})
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-/* XXX: Not sure it works well..
-   should be such that: 4byte clear and the rest. */
-extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
-
-#define clear_user(addr,n) ({ \
-void * __cl_addr = (addr); \
-unsigned long __cl_size = (n); \
-if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \
-__cl_size = __clear_user(__cl_addr, __cl_size); \
-__cl_size; })
-
-extern int __strncpy_from_user(unsigned long __dest, unsigned long __src, int __count);
-
-#define strncpy_from_user(dest,src,count) ({ \
-unsigned long __sfu_src = (unsigned long) (src); \
-int __sfu_count = (int) (count); \
-long __sfu_res = -EFAULT; \
-if(__access_ok(__sfu_src, __sfu_count)) { \
-__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
-} __sfu_res; })
-
-#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
-
-/*
- * Return the size of a string (including the ending 0!)
- */
-extern long __strnlen_user(const char *__s, long __n);
-
-static inline long strnlen_user(const char *s, long n)
-{
-       if (!__addr_ok(s))
-               return 0;
-       else
-               return __strnlen_user(s, n);
-}
-
-struct exception_table_entry
-{
-       unsigned long insn, fixup;
-};
-
-#ifdef CONFIG_MMU
-#define ARCH_HAS_SEARCH_EXTABLE
-#endif
-
-/* Returns 0 if exception not found and fixup.unit otherwise.  */
-extern unsigned long search_exception_table(unsigned long addr);
-extern const struct exception_table_entry *search_exception_tables (unsigned long addr);
-
 #endif /* __ASM_SH_UACCESS_64_H */
index 4b21f369c28cfac51532d3e1a82c7d860c883893..65be656ead7d037a03476ce335b6aec7d90049bd 100644 (file)
@@ -1,5 +1,13 @@
-#ifdef CONFIG_SUPERH32
-# include "unistd_32.h"
+#ifdef __KERNEL__
+# ifdef CONFIG_SUPERH32
+#  include "unistd_32.h"
+# else
+#  include "unistd_64.h"
+# endif
 #else
-# include "unistd_64.h"
+# ifdef __SH5__
+#  include "unistd_64.h"
+# else
+#  include "unistd_32.h"
+# endif
 #endif
index 0b07212ec659f9839baad36c4a31c207584dcc21..d52c000cf9243fdaaa42e75eeea16a6f3b9b457e 100644 (file)
 #define __NR_fallocate         324
 #define __NR_timerfd_settime   325
 #define __NR_timerfd_gettime   326
+#define __NR_signalfd4         327
+#define __NR_eventfd2          328
+#define __NR_epoll_create1     329
+#define __NR_dup3              330
+#define __NR_pipe2             331
+#define __NR_inotify_init1     332
 
-#define NR_syscalls 327
+#define NR_syscalls 333
 
 #ifdef __KERNEL__
 
index 9d21eab52427e260159f46c44094a91c1c27f328..7c54e91753c14c8ccbc6d7ea7e623679c9604044 100644 (file)
 #define __NR_fallocate         352
 #define __NR_timerfd_settime   353
 #define __NR_timerfd_gettime   354
+#define __NR_signalfd4         355
+#define __NR_eventfd2          356
+#define __NR_epoll_create1     357
+#define __NR_dup3              358
+#define __NR_pipe2             359
+#define __NR_inotify_init1     360
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 353
+#define NR_syscalls 361
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff --git a/include/asm-sparc/Kbuild b/include/asm-sparc/Kbuild
deleted file mode 100644 (file)
index 6cdaf9d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# dummy file to avoid breaking make headers_install
diff --git a/include/asm-sparc/kvm.h b/include/asm-sparc/kvm.h
deleted file mode 100644 (file)
index 2e5478d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_SPARC_H
-#define __LINUX_KVM_SPARC_H
-
-/* sparc does not support KVM */
-
-#endif
diff --git a/include/asm-sparc/namei.h b/include/asm-sparc/namei.h
deleted file mode 100644 (file)
index eff944b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef ___ASM_SPARC_NAMEI_H
-#define ___ASM_SPARC_NAMEI_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/namei_64.h>
-#else
-#include <asm-sparc/namei_32.h>
-#endif
-#endif
diff --git a/include/asm-sparc/namei_32.h b/include/asm-sparc/namei_32.h
deleted file mode 100644 (file)
index 0646102..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * linux/include/asm-sparc/namei.h
- *
- * Routines to handle famous /usr/gnemul/s*.
- * Included from linux/fs/namei.c
- */
-
-#ifndef __SPARC_NAMEI_H
-#define __SPARC_NAMEI_H
-
-#define __emul_prefix() NULL
-
-#endif /* __SPARC_NAMEI_H */
diff --git a/include/asm-sparc/namei_64.h b/include/asm-sparc/namei_64.h
deleted file mode 100644 (file)
index cbc1b4c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * linux/include/asm-sparc64/namei.h
- *
- * Routines to handle famous /usr/gnemul/s*.
- * Included from linux/fs/namei.c
- */
-
-#ifndef __SPARC64_NAMEI_H
-#define __SPARC64_NAMEI_H
-
-#define __emul_prefix() NULL
-
-#endif /* __SPARC64_NAMEI_H */
diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-sparc64/Kbuild b/include/asm-sparc64/Kbuild
deleted file mode 100644 (file)
index 6cdaf9d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# dummy file to avoid breaking make headers_install
diff --git a/include/asm-sparc64/agp.h b/include/asm-sparc64/agp.h
deleted file mode 100644 (file)
index eb8d4b3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/agp.h>
diff --git a/include/asm-sparc64/apb.h b/include/asm-sparc64/apb.h
deleted file mode 100644 (file)
index 5e236ca..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/apb.h>
diff --git a/include/asm-sparc64/asi.h b/include/asm-sparc64/asi.h
deleted file mode 100644 (file)
index 9b7110c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/asi.h>
diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h
deleted file mode 100644 (file)
index f512682..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/atomic.h>
diff --git a/include/asm-sparc64/auxio.h b/include/asm-sparc64/auxio.h
deleted file mode 100644 (file)
index 46c9042..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/auxio.h>
diff --git a/include/asm-sparc64/auxvec.h b/include/asm-sparc64/auxvec.h
deleted file mode 100644 (file)
index 1f45c67..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/auxvec.h>
diff --git a/include/asm-sparc64/backoff.h b/include/asm-sparc64/backoff.h
deleted file mode 100644 (file)
index 8ee26d9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/backoff.h>
diff --git a/include/asm-sparc64/bbc.h b/include/asm-sparc64/bbc.h
deleted file mode 100644 (file)
index 06e8b63..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/bbc.h>
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
deleted file mode 100644 (file)
index 2044043..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/bitops.h>
diff --git a/include/asm-sparc64/bpp.h b/include/asm-sparc64/bpp.h
deleted file mode 100644 (file)
index 514eee2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/bpp.h>
diff --git a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h
deleted file mode 100644 (file)
index 3433737..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/bug.h>
diff --git a/include/asm-sparc64/bugs.h b/include/asm-sparc64/bugs.h
deleted file mode 100644 (file)
index 04ae9e2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/bugs.h>
diff --git a/include/asm-sparc64/byteorder.h b/include/asm-sparc64/byteorder.h
deleted file mode 100644 (file)
index f672855..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/byteorder.h>
diff --git a/include/asm-sparc64/cache.h b/include/asm-sparc64/cache.h
deleted file mode 100644 (file)
index fa9de5c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/cache.h>
diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h
deleted file mode 100644 (file)
index cf5b6b3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/cacheflush.h>
diff --git a/include/asm-sparc64/chafsr.h b/include/asm-sparc64/chafsr.h
deleted file mode 100644 (file)
index aaab975..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/chafsr.h>
diff --git a/include/asm-sparc64/checksum.h b/include/asm-sparc64/checksum.h
deleted file mode 100644 (file)
index c3966c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/checksum.h>
diff --git a/include/asm-sparc64/chmctrl.h b/include/asm-sparc64/chmctrl.h
deleted file mode 100644 (file)
index eb757b4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/chmctrl.h>
diff --git a/include/asm-sparc64/cmt.h b/include/asm-sparc64/cmt.h
deleted file mode 100644 (file)
index b19b445..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/cmt.h>
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
deleted file mode 100644 (file)
index 8c155d2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/compat.h>
diff --git a/include/asm-sparc64/compat_signal.h b/include/asm-sparc64/compat_signal.h
deleted file mode 100644 (file)
index 7187dcc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/compat_signal.h>
diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
deleted file mode 100644 (file)
index 3220e13..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/cpudata.h>
diff --git a/include/asm-sparc64/cputime.h b/include/asm-sparc64/cputime.h
deleted file mode 100644 (file)
index 435f37a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/cputime.h>
diff --git a/include/asm-sparc64/current.h b/include/asm-sparc64/current.h
deleted file mode 100644 (file)
index a7904a7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/current.h>
diff --git a/include/asm-sparc64/dcr.h b/include/asm-sparc64/dcr.h
deleted file mode 100644 (file)
index d67613b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/dcr.h>
diff --git a/include/asm-sparc64/dcu.h b/include/asm-sparc64/dcu.h
deleted file mode 100644 (file)
index 28853f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/dcu.h>
diff --git a/include/asm-sparc64/delay.h b/include/asm-sparc64/delay.h
deleted file mode 100644 (file)
index 33dc558..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/delay.h>
diff --git a/include/asm-sparc64/device.h b/include/asm-sparc64/device.h
deleted file mode 100644 (file)
index 4145c47..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/device.h>
diff --git a/include/asm-sparc64/display7seg.h b/include/asm-sparc64/display7seg.h
deleted file mode 100644 (file)
index e74f046..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/display7seg.h>
diff --git a/include/asm-sparc64/div64.h b/include/asm-sparc64/div64.h
deleted file mode 100644 (file)
index 928c94f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/div64.h>
diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h
deleted file mode 100644 (file)
index 380b7b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/dma-mapping.h>
diff --git a/include/asm-sparc64/dma.h b/include/asm-sparc64/dma.h
deleted file mode 100644 (file)
index 2e36248..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/dma.h>
diff --git a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h
deleted file mode 100644 (file)
index d7d4761..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/ebus.h>
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
deleted file mode 100644 (file)
index f256d94..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/elf.h>
diff --git a/include/asm-sparc64/emergency-restart.h b/include/asm-sparc64/emergency-restart.h
deleted file mode 100644 (file)
index 2cac7b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/emergency-restart.h>
diff --git a/include/asm-sparc64/envctrl.h b/include/asm-sparc64/envctrl.h
deleted file mode 100644 (file)
index a2cc0ca..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/envctrl.h>
diff --git a/include/asm-sparc64/errno.h b/include/asm-sparc64/errno.h
deleted file mode 100644 (file)
index 9701fe0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/errno.h>
diff --git a/include/asm-sparc64/estate.h b/include/asm-sparc64/estate.h
deleted file mode 100644 (file)
index bedd0ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/estate.h>
diff --git a/include/asm-sparc64/fb.h b/include/asm-sparc64/fb.h
deleted file mode 100644 (file)
index 1c2ac58..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/fb.h>
diff --git a/include/asm-sparc64/fbio.h b/include/asm-sparc64/fbio.h
deleted file mode 100644 (file)
index c17edf8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/fbio.h>
diff --git a/include/asm-sparc64/fcntl.h b/include/asm-sparc64/fcntl.h
deleted file mode 100644 (file)
index 8b1beae..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/fcntl.h>
diff --git a/include/asm-sparc64/fhc.h b/include/asm-sparc64/fhc.h
deleted file mode 100644 (file)
index 73eb04c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/fhc.h>
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
deleted file mode 100644 (file)
index 2148781..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/floppy.h>
diff --git a/include/asm-sparc64/fpumacro.h b/include/asm-sparc64/fpumacro.h
deleted file mode 100644 (file)
index 30d6d0f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/fpumacro.h>
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h
deleted file mode 100644 (file)
index 1ceb0bb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/futex.h>
diff --git a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h
deleted file mode 100644 (file)
index 63dca3d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/hardirq.h>
diff --git a/include/asm-sparc64/head.h b/include/asm-sparc64/head.h
deleted file mode 100644 (file)
index 2254c09..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/head.h>
diff --git a/include/asm-sparc64/hugetlb.h b/include/asm-sparc64/hugetlb.h
deleted file mode 100644 (file)
index 21d8f0a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/hugetlb.h>
diff --git a/include/asm-sparc64/hvtramp.h b/include/asm-sparc64/hvtramp.h
deleted file mode 100644 (file)
index fb46bfe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/hvtramp.h>
diff --git a/include/asm-sparc64/hw_irq.h b/include/asm-sparc64/hw_irq.h
deleted file mode 100644 (file)
index 16920a2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/hw_irq.h>
diff --git a/include/asm-sparc64/hypervisor.h b/include/asm-sparc64/hypervisor.h
deleted file mode 100644 (file)
index fe7e51a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/hypervisor.h>
diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
deleted file mode 100644 (file)
index 7125317..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/ide.h>
diff --git a/include/asm-sparc64/idprom.h b/include/asm-sparc64/idprom.h
deleted file mode 100644 (file)
index c22f9c3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/idprom.h>
diff --git a/include/asm-sparc64/intr_queue.h b/include/asm-sparc64/intr_queue.h
deleted file mode 100644 (file)
index f722501..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/intr_queue.h>
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
deleted file mode 100644 (file)
index 25ff258..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/io.h>
diff --git a/include/asm-sparc64/ioctl.h b/include/asm-sparc64/ioctl.h
deleted file mode 100644 (file)
index 18fc562..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/ioctl.h>
diff --git a/include/asm-sparc64/ioctls.h b/include/asm-sparc64/ioctls.h
deleted file mode 100644 (file)
index dcd5540..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/ioctls.h>
diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h
deleted file mode 100644 (file)
index 76252bb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/iommu.h>
diff --git a/include/asm-sparc64/ipcbuf.h b/include/asm-sparc64/ipcbuf.h
deleted file mode 100644 (file)
index 41dfaf1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/ipcbuf.h>
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
deleted file mode 100644 (file)
index b2102e6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/irq.h>
diff --git a/include/asm-sparc64/irq_regs.h b/include/asm-sparc64/irq_regs.h
deleted file mode 100644 (file)
index 1e2b8a1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/irq_regs.h>
diff --git a/include/asm-sparc64/irqflags.h b/include/asm-sparc64/irqflags.h
deleted file mode 100644 (file)
index 27b091f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/irqflags.h>
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
deleted file mode 100644 (file)
index 78cfd5d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/kdebug.h>
diff --git a/include/asm-sparc64/kgdb.h b/include/asm-sparc64/kgdb.h
deleted file mode 100644 (file)
index aa6532f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/kgdb.h>
diff --git a/include/asm-sparc64/kmap_types.h b/include/asm-sparc64/kmap_types.h
deleted file mode 100644 (file)
index 276530c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/kmap_types.h>
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
deleted file mode 100644 (file)
index c55e43e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/kprobes.h>
diff --git a/include/asm-sparc64/kvm.h b/include/asm-sparc64/kvm.h
deleted file mode 100644 (file)
index 53564ad..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/kvm.h>
diff --git a/include/asm-sparc64/ldc.h b/include/asm-sparc64/ldc.h
deleted file mode 100644 (file)
index 40f3f23..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/ldc.h>
diff --git a/include/asm-sparc64/linkage.h b/include/asm-sparc64/linkage.h
deleted file mode 100644 (file)
index 3ea4fd1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/linkage.h>
diff --git a/include/asm-sparc64/lmb.h b/include/asm-sparc64/lmb.h
deleted file mode 100644 (file)
index 3d04981..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/lmb.h>
diff --git a/include/asm-sparc64/local.h b/include/asm-sparc64/local.h
deleted file mode 100644 (file)
index c11c530..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff --git a/include/asm-sparc64/lsu.h b/include/asm-sparc64/lsu.h
deleted file mode 100644 (file)
index 4e3d8b1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/lsu.h>
diff --git a/include/asm-sparc64/mc146818rtc.h b/include/asm-sparc64/mc146818rtc.h
deleted file mode 100644 (file)
index 97842e6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/mc146818rtc.h>
diff --git a/include/asm-sparc64/mdesc.h b/include/asm-sparc64/mdesc.h
deleted file mode 100644 (file)
index 165a193..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/mdesc.h>
diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h
deleted file mode 100644 (file)
index 17ddb17..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/mman.h>
diff --git a/include/asm-sparc64/mmu.h b/include/asm-sparc64/mmu.h
deleted file mode 100644 (file)
index e677a64..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/mmu.h>
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
deleted file mode 100644 (file)
index 877fee9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/mmu_context.h>
diff --git a/include/asm-sparc64/mmzone.h b/include/asm-sparc64/mmzone.h
deleted file mode 100644 (file)
index 43a710f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/mmzone.h>
diff --git a/include/asm-sparc64/module.h b/include/asm-sparc64/module.h
deleted file mode 100644 (file)
index a9606db..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/module.h>
diff --git a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h
deleted file mode 100644 (file)
index 95a752f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/mostek.h>
diff --git a/include/asm-sparc64/msgbuf.h b/include/asm-sparc64/msgbuf.h
deleted file mode 100644 (file)
index 5b33cc9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/msgbuf.h>
diff --git a/include/asm-sparc64/mutex.h b/include/asm-sparc64/mutex.h
deleted file mode 100644 (file)
index c0c0f8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/mutex.h>
diff --git a/include/asm-sparc64/namei.h b/include/asm-sparc64/namei.h
deleted file mode 100644 (file)
index 1344a91..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/namei.h>
diff --git a/include/asm-sparc64/ns87303.h b/include/asm-sparc64/ns87303.h
deleted file mode 100644 (file)
index 5f369d4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/ns87303.h>
diff --git a/include/asm-sparc64/of_device.h b/include/asm-sparc64/of_device.h
deleted file mode 100644 (file)
index a769fdb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/of_device.h>
diff --git a/include/asm-sparc64/of_platform.h b/include/asm-sparc64/of_platform.h
deleted file mode 100644 (file)
index f7c427b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/of_platform.h>
diff --git a/include/asm-sparc64/openprom.h b/include/asm-sparc64/openprom.h
deleted file mode 100644 (file)
index acf4b23..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/openprom.h>
diff --git a/include/asm-sparc64/openpromio.h b/include/asm-sparc64/openpromio.h
deleted file mode 100644 (file)
index 122fabd..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/openpromio.h>
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
deleted file mode 100644 (file)
index d93e44e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/oplib.h>
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
deleted file mode 100644 (file)
index f46c1fb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/page.h>
diff --git a/include/asm-sparc64/param.h b/include/asm-sparc64/param.h
deleted file mode 100644 (file)
index 40c6dc1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/param.h>
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
deleted file mode 100644 (file)
index b4e4ca8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/parport.h>
diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
deleted file mode 100644 (file)
index da54c4d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/pci.h>
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
deleted file mode 100644 (file)
index 292729b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/percpu.h>
diff --git a/include/asm-sparc64/perfctr.h b/include/asm-sparc64/perfctr.h
deleted file mode 100644 (file)
index 52073a9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/perfctr.h>
diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
deleted file mode 100644 (file)
index bec3164..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/pgalloc.h>
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
deleted file mode 100644 (file)
index 9decbd9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/pgtable.h>
diff --git a/include/asm-sparc64/pil.h b/include/asm-sparc64/pil.h
deleted file mode 100644 (file)
index d805f33..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/pil.h>
diff --git a/include/asm-sparc64/poll.h b/include/asm-sparc64/poll.h
deleted file mode 100644 (file)
index 8e2f31b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/poll.h>
diff --git a/include/asm-sparc64/posix_types.h b/include/asm-sparc64/posix_types.h
deleted file mode 100644 (file)
index 8cee992..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/posix_types.h>
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
deleted file mode 100644 (file)
index 21de6cc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/processor.h>
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h
deleted file mode 100644 (file)
index 5fa166e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/prom.h>
diff --git a/include/asm-sparc64/psrcompat.h b/include/asm-sparc64/psrcompat.h
deleted file mode 100644 (file)
index 587846f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/psrcompat.h>
diff --git a/include/asm-sparc64/pstate.h b/include/asm-sparc64/pstate.h
deleted file mode 100644 (file)
index 3ccf0be..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/pstate.h>
diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
deleted file mode 100644 (file)
index 1a55b9f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/ptrace.h>
diff --git a/include/asm-sparc64/reboot.h b/include/asm-sparc64/reboot.h
deleted file mode 100644 (file)
index 0d72eb8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/reboot.h>
diff --git a/include/asm-sparc64/reg.h b/include/asm-sparc64/reg.h
deleted file mode 100644 (file)
index 495bab2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/reg.h>
diff --git a/include/asm-sparc64/resource.h b/include/asm-sparc64/resource.h
deleted file mode 100644 (file)
index 46e3bc0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/resource.h>
diff --git a/include/asm-sparc64/rtc.h b/include/asm-sparc64/rtc.h
deleted file mode 100644 (file)
index e49a968..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/rtc.h>
diff --git a/include/asm-sparc64/rwsem-const.h b/include/asm-sparc64/rwsem-const.h
deleted file mode 100644 (file)
index 2a1de31..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/rwsem-const.h>
diff --git a/include/asm-sparc64/rwsem.h b/include/asm-sparc64/rwsem.h
deleted file mode 100644 (file)
index 6943c56..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/rwsem.h>
diff --git a/include/asm-sparc64/sbus.h b/include/asm-sparc64/sbus.h
deleted file mode 100644 (file)
index 0cab0e8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sbus.h>
diff --git a/include/asm-sparc64/scatterlist.h b/include/asm-sparc64/scatterlist.h
deleted file mode 100644 (file)
index b7fef95..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/scatterlist.h>
diff --git a/include/asm-sparc64/scratchpad.h b/include/asm-sparc64/scratchpad.h
deleted file mode 100644 (file)
index 23675f6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/scratchpad.h>
diff --git a/include/asm-sparc64/seccomp.h b/include/asm-sparc64/seccomp.h
deleted file mode 100644 (file)
index f22f02a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/seccomp.h>
diff --git a/include/asm-sparc64/sections.h b/include/asm-sparc64/sections.h
deleted file mode 100644 (file)
index 721496f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sections.h>
diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h
deleted file mode 100644 (file)
index 39362af..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/semaphore.h>
diff --git a/include/asm-sparc64/sembuf.h b/include/asm-sparc64/sembuf.h
deleted file mode 100644 (file)
index c55b952..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sembuf.h>
diff --git a/include/asm-sparc64/setup.h b/include/asm-sparc64/setup.h
deleted file mode 100644 (file)
index 7143d06..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/setup.h>
diff --git a/include/asm-sparc64/sfafsr.h b/include/asm-sparc64/sfafsr.h
deleted file mode 100644 (file)
index 8036fc3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sfafsr.h>
diff --git a/include/asm-sparc64/sfp-machine.h b/include/asm-sparc64/sfp-machine.h
deleted file mode 100644 (file)
index 7bbc4fe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sfp-machine.h>
diff --git a/include/asm-sparc64/shmbuf.h b/include/asm-sparc64/shmbuf.h
deleted file mode 100644 (file)
index 0c54a2d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/shmbuf.h>
diff --git a/include/asm-sparc64/shmparam.h b/include/asm-sparc64/shmparam.h
deleted file mode 100644 (file)
index 5fa3a9b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/shmparam.h>
diff --git a/include/asm-sparc64/sigcontext.h b/include/asm-sparc64/sigcontext.h
deleted file mode 100644 (file)
index 5b16dcc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sigcontext.h>
diff --git a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
deleted file mode 100644 (file)
index 8ffd6eb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/siginfo.h>
diff --git a/include/asm-sparc64/signal.h b/include/asm-sparc64/signal.h
deleted file mode 100644 (file)
index 79705e5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/signal.h>
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
deleted file mode 100644 (file)
index 5095a2c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/smp.h>
diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
deleted file mode 100644 (file)
index 13e0d5d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/socket.h>
diff --git a/include/asm-sparc64/sockios.h b/include/asm-sparc64/sockios.h
deleted file mode 100644 (file)
index 2cb4b64..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sockios.h>
diff --git a/include/asm-sparc64/sparsemem.h b/include/asm-sparc64/sparsemem.h
deleted file mode 100644 (file)
index e681f22..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sparsemem.h>
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
deleted file mode 100644 (file)
index 0115b81..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/spinlock.h>
diff --git a/include/asm-sparc64/spinlock_types.h b/include/asm-sparc64/spinlock_types.h
deleted file mode 100644 (file)
index 48d81c8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/spinlock_types.h>
diff --git a/include/asm-sparc64/spitfire.h b/include/asm-sparc64/spitfire.h
deleted file mode 100644 (file)
index 4430d2f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/spitfire.h>
diff --git a/include/asm-sparc64/sstate.h b/include/asm-sparc64/sstate.h
deleted file mode 100644 (file)
index 97720ce..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sstate.h>
diff --git a/include/asm-sparc64/stacktrace.h b/include/asm-sparc64/stacktrace.h
deleted file mode 100644 (file)
index adc9b92..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/stacktrace.h>
diff --git a/include/asm-sparc64/starfire.h b/include/asm-sparc64/starfire.h
deleted file mode 100644 (file)
index db97daa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/starfire.h>
diff --git a/include/asm-sparc64/stat.h b/include/asm-sparc64/stat.h
deleted file mode 100644 (file)
index b108a86..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/stat.h>
diff --git a/include/asm-sparc64/statfs.h b/include/asm-sparc64/statfs.h
deleted file mode 100644 (file)
index 5503d6a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/statfs.h>
diff --git a/include/asm-sparc64/string.h b/include/asm-sparc64/string.h
deleted file mode 100644 (file)
index 5018cd8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/string.h>
diff --git a/include/asm-sparc64/sunbpp.h b/include/asm-sparc64/sunbpp.h
deleted file mode 100644 (file)
index 9632be2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/sunbpp.h>
diff --git a/include/asm-sparc64/syscalls.h b/include/asm-sparc64/syscalls.h
deleted file mode 100644 (file)
index 3477b16..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/syscalls.h>
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
deleted file mode 100644 (file)
index be2603c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/system.h>
diff --git a/include/asm-sparc64/termbits.h b/include/asm-sparc64/termbits.h
deleted file mode 100644 (file)
index e03f975..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/termbits.h>
diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
deleted file mode 100644 (file)
index 940495e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/termios.h>
diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
deleted file mode 100644 (file)
index 92bed79..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/thread_info.h>
diff --git a/include/asm-sparc64/timer.h b/include/asm-sparc64/timer.h
deleted file mode 100644 (file)
index 88026d8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/timer.h>
diff --git a/include/asm-sparc64/timex.h b/include/asm-sparc64/timex.h
deleted file mode 100644 (file)
index 8dd59ee..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/timex.h>
diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
deleted file mode 100644 (file)
index ae92fce..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/tlb.h>
diff --git a/include/asm-sparc64/tlbflush.h b/include/asm-sparc64/tlbflush.h
deleted file mode 100644 (file)
index a43979a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/tlbflush.h>
diff --git a/include/asm-sparc64/topology.h b/include/asm-sparc64/topology.h
deleted file mode 100644 (file)
index 46999b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/topology.h>
diff --git a/include/asm-sparc64/tsb.h b/include/asm-sparc64/tsb.h
deleted file mode 100644 (file)
index 3677a30..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/tsb.h>
diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
deleted file mode 100644 (file)
index a550f1b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/ttable.h>
diff --git a/include/asm-sparc64/types.h b/include/asm-sparc64/types.h
deleted file mode 100644 (file)
index cfbfad5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/types.h>
diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
deleted file mode 100644 (file)
index 2872d22..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/uaccess.h>
diff --git a/include/asm-sparc64/uctx.h b/include/asm-sparc64/uctx.h
deleted file mode 100644 (file)
index 9e1b579..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/uctx.h>
diff --git a/include/asm-sparc64/unaligned.h b/include/asm-sparc64/unaligned.h
deleted file mode 100644 (file)
index 19fbf95..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/unaligned.h>
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
deleted file mode 100644 (file)
index ad86e0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/unistd.h>
diff --git a/include/asm-sparc64/upa.h b/include/asm-sparc64/upa.h
deleted file mode 100644 (file)
index aab7293..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/upa.h>
diff --git a/include/asm-sparc64/user.h b/include/asm-sparc64/user.h
deleted file mode 100644 (file)
index 29fc6e9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/user.h>
diff --git a/include/asm-sparc64/utrap.h b/include/asm-sparc64/utrap.h
deleted file mode 100644 (file)
index b030a41..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/utrap.h>
diff --git a/include/asm-sparc64/vga.h b/include/asm-sparc64/vga.h
deleted file mode 100644 (file)
index fbf4d58..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/vga.h>
diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h
deleted file mode 100644 (file)
index 299b26a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/vio.h>
diff --git a/include/asm-sparc64/visasm.h b/include/asm-sparc64/visasm.h
deleted file mode 100644 (file)
index 837a122..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/visasm.h>
diff --git a/include/asm-sparc64/watchdog.h b/include/asm-sparc64/watchdog.h
deleted file mode 100644 (file)
index b0f2857..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/watchdog.h>
diff --git a/include/asm-sparc64/xor.h b/include/asm-sparc64/xor.h
deleted file mode 100644 (file)
index ef187cc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/xor.h>
diff --git a/include/asm-um/kvm.h b/include/asm-um/kvm.h
deleted file mode 100644 (file)
index 66aa770..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_UM_H
-#define __LINUX_KVM_UM_H
-
-/* um does not support KVM */
-
-#endif
diff --git a/include/asm-um/namei.h b/include/asm-um/namei.h
deleted file mode 100644 (file)
index 002984d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_NAMEI_H
-#define __UM_NAMEI_H
-
-#include "asm/arch/namei.h"
-
-#endif
index 916e1a61999f4b414b94e31db9b928c09ef69aff..a6df1f13d732ddaf7d487fdcb5eabf20a14f6c93 100644 (file)
@@ -92,9 +92,6 @@ typedef struct page *pgtable_t;
 #define __pgd(x) ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
 extern unsigned long uml_physmem;
 
 #define PAGE_OFFSET (uml_physmem)
@@ -118,9 +115,6 @@ extern unsigned long uml_physmem;
 #define pfn_valid(pfn) ((pfn) < max_mapnr)
 #define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
 
-extern struct page *arch_validate(struct page *page, gfp_t mask, int order);
-#define HAVE_ARCH_VALIDATE
-
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
index 6aefcd32fc615d91723baad3adfe51734cd60070..315749705ea1b91fccf261ba1161eb785cff9701 100644 (file)
@@ -47,9 +47,6 @@ extern int set_fpregs(struct user_i387_struct __user *buf,
 
 extern void show_regs(struct pt_regs *regs);
 
-extern void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
-                        int error_code);
-
 extern int arch_copy_tls(struct task_struct *new);
 extern void clear_flushed_tls(struct task_struct *task);
 
diff --git a/include/asm-um/semaphore.h b/include/asm-um/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index 356b83e2c22edf07c357e91c46469ad762968fb2..e07e72846c7a339544e859d4295eba4452891197 100644 (file)
@@ -53,21 +53,7 @@ static inline struct thread_info *current_thread_info(void)
        return ti;
 }
 
-#ifdef CONFIG_DEBUG_STACK_USAGE
-
-#define alloc_thread_info(tsk) \
-       ((struct thread_info *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, \
-                                                CONFIG_KERNEL_STACK_ORDER))
-#else
-
-/* thread information allocation */
-#define alloc_thread_info(tsk) \
-       ((struct thread_info *) __get_free_pages(GFP_KERNEL, \
-                                                CONFIG_KERNEL_STACK_ORDER))
-#endif
-
-#define free_thread_info(ti) \
-       free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
+#define THREAD_SIZE_ORDER CONFIG_KERNEL_STACK_ORDER
 
 #endif
 
diff --git a/include/asm-v850/Kbuild b/include/asm-v850/Kbuild
deleted file mode 100644 (file)
index c68e168..0000000
+++ /dev/null
@@ -1 +0,0 @@
-include include/asm-generic/Kbuild.asm
diff --git a/include/asm-v850/a.out.h b/include/asm-v850/a.out.h
deleted file mode 100644 (file)
index e9439a0..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __V850_A_OUT_H__
-#define __V850_A_OUT_H__
-
-struct exec
-{
-  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
-  unsigned a_text;             /* length of text, in bytes */
-  unsigned a_data;             /* length of data, in bytes */
-  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
-  unsigned a_syms;             /* length of symbol table data in file, in bytes */
-  unsigned a_entry;            /* start address */
-  unsigned a_trsize;           /* length of relocation info for text, in bytes */
-  unsigned a_drsize;           /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-
-#endif /* __V850_A_OUT_H__ */
diff --git a/include/asm-v850/anna.h b/include/asm-v850/anna.h
deleted file mode 100644 (file)
index cd5eaee..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * include/asm-v850/anna.h -- Anna V850E2 evaluation cpu chip/board
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_ANNA_H__
-#define __V850_ANNA_H__
-
-#include <asm/v850e2.h>                /* Based on V850E2 core.  */
-
-
-#define CPU_MODEL      "v850e2/anna"
-#define CPU_MODEL_LONG "NEC V850E2/Anna"
-#define PLATFORM       "anna"
-#define PLATFORM_LONG  "NEC/Midas lab V850E2/Anna evaluation board"
-
-#define CPU_CLOCK_FREQ 200000000 /*  200MHz */
-#define SYS_CLOCK_FREQ  33300000 /* 33.3MHz */
-
-
-/* 1MB of static RAM.  This memory is mirrored 64 times.  */
-#define SRAM_ADDR      0x04000000
-#define SRAM_SIZE      0x00100000 /* 1MB */
-/* 64MB of DRAM.  */
-#define SDRAM_ADDR     0x08000000      
-#define SDRAM_SIZE     0x04000000 /* 64MB */
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET    SRAM_ADDR
-
-/* We use on-chip RAM, for a few miscellaneous variables that must be
-   accessible using a load instruction relative to R0.  The Anna chip has
-   128K of `dLB' ram nominally located at 0xFFF00000, but it's mirrored
-   every 128K, so we can use the `last mirror' (except for the portion at
-   the top which is overridden by I/O space).  In addition, the early
-   sample chip we're using has lots of memory errors in the dLB ram, so we
-   use a specially chosen location that has at least 20 bytes of contiguous
-   valid memory (xxxF0020 - xxxF003F).  */
-#define R0_RAM_ADDR                    0xFFFF8020
-
-
-/* Anna specific control registers.  */
-#define ANNA_ILBEN_ADDR                        0xFFFFF7F2
-#define ANNA_ILBEN                     (*(volatile u16 *)ANNA_ILBEN_ADDR)
-
-
-/* I/O port P0-P3. */
-/* Direct I/O.  Bits 0-7 are pins Pn0-Pn7.  */
-#define ANNA_PORT_IO_ADDR(n)           (0xFFFFF400 + (n) * 2)
-#define ANNA_PORT_IO(n)                        (*(volatile u8 *)ANNA_PORT_IO_ADDR(n))
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define ANNA_PORT_PM_ADDR(n)           (0xFFFFF410 + (n) * 2)
-#define ANNA_PORT_PM(n)                        (*(volatile u8 *)ANNA_PORT_PM_ADDR(n))
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace).  */
-#define IRQ_INTP(n)    (n)     /* Pnnn (pin) interrupts 0-15 */
-#define IRQ_INTP_NUM   16
-#define IRQ_INTOV(n)   (0x10 + (n)) /* 0-2 */
-#define IRQ_INTOV_NUM  2
-#define IRQ_INTCCC(n)  (0x12 + (n))
-#define IRQ_INTCCC_NUM 4
-#define IRQ_INTCMD(n)  (0x16 + (n)) /* interval timer interrupts 0-5 */
-#define IRQ_INTCMD_NUM 6
-#define IRQ_INTDMA(n)  (0x1C + (n)) /* DMA interrupts 0-3 */
-#define IRQ_INTDMA_NUM 4
-#define IRQ_INTDMXER   0x20
-#define IRQ_INTSRE(n)  (0x21 + (n)*3) /* UART 0-1 reception error */
-#define IRQ_INTSRE_NUM 2
-#define IRQ_INTSR(n)   (0x22 + (n)*3) /* UART 0-1 reception completion */
-#define IRQ_INTSR_NUM  2
-#define IRQ_INTST(n)   (0x23 + (n)*3) /* UART 0-1 transmission completion */
-#define IRQ_INTST_NUM  2
-
-#define NUM_CPU_IRQS   64
-
-#ifndef __ASSEMBLY__
-/* Initialize chip interrupts.  */
-extern void anna_init_irqs (void);
-#endif
-
-
-/* Anna UART details (basically the same as the V850E/MA1, but 2 channels).  */
-#define V850E_UART_NUM_CHANNELS                2
-#define V850E_UART_BASE_FREQ           (SYS_CLOCK_FREQ / 2)
-#define V850E_UART_CHIP_NAME           "V850E2/NA85E2A"
-
-/* This is the UART channel that's actually connected on the board.  */
-#define V850E_UART_CONSOLE_CHANNEL     1
-
-/* This is a function that gets called before configuring the UART.  */
-#define V850E_UART_PRE_CONFIGURE       anna_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void anna_uart_pre_configure (unsigned chan,
-                                    unsigned cflags, unsigned baud);
-#endif
-
-/* This board supports RTS/CTS for the on-chip UART, but only for channel 1. */
-
-/* CTS for UART channel 1 is pin P37 (bit 7 of port 3).  */
-#define V850E_UART_CTS(chan)   ((chan) == 1 ? !(ANNA_PORT_IO(3) & 0x80) : 1)
-/* RTS for UART channel 1 is pin P07 (bit 7 of port 0).  */
-#define V850E_UART_SET_RTS(chan, val)                                        \
-   do {                                                                              \
-          if (chan == 1) {                                                   \
-                  unsigned old = ANNA_PORT_IO(0);                            \
-                  if (val)                                                   \
-                          ANNA_PORT_IO(0) = old & ~0x80;                     \
-                  else                                                       \
-                          ANNA_PORT_IO(0) = old | 0x80;                      \
-          }                                                                  \
-   } while (0)
-
-
-/* Timer C details.  */
-#define V850E_TIMER_C_BASE_ADDR                0xFFFFF600
-
-/* Timer D details (the Anna actually has 5 of these; should change later). */
-#define V850E_TIMER_D_BASE_ADDR                0xFFFFF540
-#define V850E_TIMER_D_TMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_CMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x2)
-#define V850E_TIMER_D_TMCD_BASE_ADDR   (V850E_TIMER_D_BASE_ADDR + 0x4)
-
-#define V850E_TIMER_D_BASE_FREQ                SYS_CLOCK_FREQ
-#define V850E_TIMER_D_TMCD_CS_MIN      1 /* min 2^1 divider */
-
-
-#endif /* __V850_ANNA_H__ */
diff --git a/include/asm-v850/as85ep1.h b/include/asm-v850/as85ep1.h
deleted file mode 100644 (file)
index 5a5ca90..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * include/asm-v850/as85ep1.h -- AS85EP1 evaluation CPU chip/board
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_AS85EP1_H__
-#define __V850_AS85EP1_H__
-
-#include <asm/v850e.h>
-
-
-#define CPU_MODEL      "as85ep1"
-#define CPU_MODEL_LONG "NEC V850E/AS85EP1"
-#define PLATFORM       "AS85EP1"
-#define PLATFORM_LONG  "NEC V850E/AS85EP1 evaluation board"
-
-#define CPU_CLOCK_FREQ 96000000 /*  96MHz */
-#define SYS_CLOCK_FREQ CPU_CLOCK_FREQ
-
-
-/* 1MB of static RAM.  */
-#define SRAM_ADDR      0x00400000
-#define SRAM_SIZE      0x00100000 /* 1MB */
-/* About 58MB of DRAM.  This can actually be at one of two positions,
-   determined by jump JP3; we have to use the first position because the
-   second is partially out of processor instruction addressing range
-   (though in the second position there's actually 64MB available).  */
-#define SDRAM_ADDR     0x00600000
-#define SDRAM_SIZE     0x039F8000 /* approx 58MB */
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET    SRAM_ADDR
-
-/* We use on-chip RAM, for a few miscellaneous variables that must be
-   accessible using a load instruction relative to R0.  The AS85EP1 chip
-   16K of internal RAM located slightly before I/O space.  */
-#define R0_RAM_ADDR    0xFFFF8000
-
-
-/* AS85EP1 specific control registers.  */
-#define AS85EP1_CSC_ADDR(n)    (0xFFFFF060 + (n) * 2)
-#define AS85EP1_CSC(n)         (*(volatile u16 *)AS85EP1_CSC_ADDR(n))
-#define AS85EP1_BSC_ADDR       0xFFFFF066
-#define AS85EP1_BSC            (*(volatile u16 *)AS85EP1_BSC_ADDR)
-#define AS85EP1_BCT_ADDR(n)    (0xFFFFF480 + (n) * 2)
-#define AS85EP1_BCT(n)         (*(volatile u16 *)AS85EP1_BCT_ADDR(n))
-#define AS85EP1_DWC_ADDR(n)    (0xFFFFF484 + (n) * 2)
-#define AS85EP1_DWC(n)         (*(volatile u16 *)AS85EP1_DWC_ADDR(n))
-#define AS85EP1_BCC_ADDR       0xFFFFF488
-#define AS85EP1_BCC            (*(volatile u16 *)AS85EP1_BCC_ADDR)
-#define AS85EP1_ASC_ADDR       0xFFFFF48A
-#define AS85EP1_ASC            (*(volatile u16 *)AS85EP1_ASC_ADDR)
-#define AS85EP1_BCP_ADDR       0xFFFFF48C
-#define AS85EP1_BCP            (*(volatile u16 *)AS85EP1_BCP_ADDR)
-#define AS85EP1_LBS_ADDR       0xFFFFF48E
-#define AS85EP1_LBS            (*(volatile u16 *)AS85EP1_LBS_ADDR)
-#define AS85EP1_BMC_ADDR       0xFFFFF498
-#define AS85EP1_BMC            (*(volatile u16 *)AS85EP1_BMC_ADDR)
-#define AS85EP1_PRC_ADDR       0xFFFFF49A
-#define AS85EP1_PRC            (*(volatile u16 *)AS85EP1_PRC_ADDR)
-#define AS85EP1_SCR_ADDR(n)    (0xFFFFF4A0 + (n) * 4)
-#define AS85EP1_SCR(n)         (*(volatile u16 *)AS85EP1_SCR_ADDR(n))
-#define AS85EP1_RFS_ADDR(n)    (0xFFFFF4A2 + (n) * 4)
-#define AS85EP1_RFS(n)         (*(volatile u16 *)AS85EP1_RFS_ADDR(n))
-#define AS85EP1_IRAMM_ADDR     0xFFFFF80A
-#define AS85EP1_IRAMM          (*(volatile u8 *)AS85EP1_IRAMM_ADDR)
-
-
-
-/* I/O port P0-P13. */
-/* Direct I/O.  Bits 0-7 are pins Pn0-Pn7.  */
-#define AS85EP1_PORT_IO_ADDR(n)        (0xFFFFF400 + (n) * 2)
-#define AS85EP1_PORT_IO(n)     (*(volatile u8 *)AS85EP1_PORT_IO_ADDR(n))
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define AS85EP1_PORT_PM_ADDR(n)        (0xFFFFF420 + (n) * 2)
-#define AS85EP1_PORT_PM(n)     (*(volatile u8 *)AS85EP1_PORT_PM_ADDR(n))
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
-#define AS85EP1_PORT_PMC_ADDR(n) (0xFFFFF440 + (n) * 2)
-#define AS85EP1_PORT_PMC(n)    (*(volatile u8 *)AS85EP1_PORT_PMC_ADDR(n))
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace).  */
-#define IRQ_INTCCC(n)  (0x0C + (n))
-#define IRQ_INTCCC_NUM 8
-#define IRQ_INTCMD(n)  (0x14 + (n)) /* interval timer interrupts 0-5 */
-#define IRQ_INTCMD_NUM 6
-#define IRQ_INTSRE(n)  (0x1E + (n)*3) /* UART 0-1 reception error */
-#define IRQ_INTSRE_NUM 2
-#define IRQ_INTSR(n)   (0x1F + (n)*3) /* UART 0-1 reception completion */
-#define IRQ_INTSR_NUM  2
-#define IRQ_INTST(n)   (0x20 + (n)*3) /* UART 0-1 transmission completion */
-#define IRQ_INTST_NUM  2
-
-#define NUM_CPU_IRQS   64
-
-#ifndef __ASSEMBLY__
-/* Initialize chip interrupts.  */
-extern void as85ep1_init_irqs (void);
-#endif
-
-
-/* AS85EP1 UART details (basically the same as the V850E/MA1, but 2 channels).  */
-#define V850E_UART_NUM_CHANNELS                2
-#define V850E_UART_BASE_FREQ           (SYS_CLOCK_FREQ / 4)
-#define V850E_UART_CHIP_NAME           "V850E/NA85E"
-
-/* This is a function that gets called before configuring the UART.  */
-#define V850E_UART_PRE_CONFIGURE       as85ep1_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void as85ep1_uart_pre_configure (unsigned chan,
-                                       unsigned cflags, unsigned baud);
-#endif
-
-/* This board supports RTS/CTS for the on-chip UART, but only for channel 1. */
-
-/* CTS for UART channel 1 is pin P54 (bit 4 of port 5).  */
-#define V850E_UART_CTS(chan)   ((chan) == 1 ? !(AS85EP1_PORT_IO(5) & 0x10) : 1)
-/* RTS for UART channel 1 is pin P53 (bit 3 of port 5).  */
-#define V850E_UART_SET_RTS(chan, val)                                        \
-   do {                                                                              \
-          if (chan == 1) {                                                   \
-                  unsigned old = AS85EP1_PORT_IO(5);                         \
-                  if (val)                                                   \
-                          AS85EP1_PORT_IO(5) = old & ~0x8;                   \
-                  else                                                       \
-                          AS85EP1_PORT_IO(5) = old | 0x8;                    \
-          }                                                                  \
-   } while (0)
-
-
-/* Timer C details.  */
-#define V850E_TIMER_C_BASE_ADDR                0xFFFFF600
-
-/* Timer D details (the AS85EP1 actually has 5 of these; should change later). */
-#define V850E_TIMER_D_BASE_ADDR                0xFFFFF540
-#define V850E_TIMER_D_TMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_CMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x2)
-#define V850E_TIMER_D_TMCD_BASE_ADDR   (V850E_TIMER_D_BASE_ADDR + 0x4)
-
-#define V850E_TIMER_D_BASE_FREQ                SYS_CLOCK_FREQ
-#define V850E_TIMER_D_TMCD_CS_MIN      2 /* min 2^2 divider */
-
-
-#endif /* __V850_AS85EP1_H__ */
diff --git a/include/asm-v850/asm.h b/include/asm-v850/asm.h
deleted file mode 100644 (file)
index bf1e785..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * include/asm-v850/asm.h -- Macros for writing assembly code
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#define G_ENTRY(name)                                                        \
-   .balign 4;                                                                \
-   .globl name;                                                                      \
-   .type  name,@function;                                                    \
-   name
-#define G_DATA(name)                                                         \
-   .globl name;                                                                      \
-   .type  name,@object;                                                              \
-   name
-#define END(name)                                                            \
-   .size  name,.-name
-
-#define L_ENTRY(name)                                                        \
-   .balign 4;                                                                \
-   .type  name,@function;                                                    \
-   name
-#define L_DATA(name)                                                         \
-   .type  name,@object;                                                              \
-   name
diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h
deleted file mode 100644 (file)
index e4e57de..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * include/asm-v850/atomic.h -- Atomic operations
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_ATOMIC_H__
-#define __V850_ATOMIC_H__
-
-
-#include <asm/system.h>
-
-#ifdef CONFIG_SMP
-#error SMP not supported
-#endif
-
-typedef struct { int counter; } atomic_t;
-
-#define ATOMIC_INIT(i) { (i) }
-
-#ifdef __KERNEL__
-
-#define atomic_read(v)         ((v)->counter)
-#define atomic_set(v,i)                (((v)->counter) = (i))
-
-static inline int atomic_add_return (int i, volatile atomic_t *v)
-{
-       unsigned long flags;
-       int res;
-
-       local_irq_save (flags);
-       res = v->counter + i;
-       v->counter = res;
-       local_irq_restore (flags);
-
-       return res;
-}
-
-static __inline__ int atomic_sub_return (int i, volatile atomic_t *v)
-{
-       unsigned long flags;
-       int res;
-
-       local_irq_save (flags);
-       res = v->counter - i;
-       v->counter = res;
-       local_irq_restore (flags);
-
-       return res;
-}
-
-static __inline__ void atomic_clear_mask (unsigned long mask, unsigned long *addr)
-{
-       unsigned long flags;
-
-       local_irq_save (flags);
-       *addr &= ~mask;
-       local_irq_restore (flags);
-}
-
-#endif
-
-#define atomic_add(i, v)       atomic_add_return ((i), (v))
-#define atomic_sub(i, v)       atomic_sub_return ((i), (v))
-
-#define atomic_dec_return(v)   atomic_sub_return (1, (v))
-#define atomic_inc_return(v)   atomic_add_return (1, (v))
-#define atomic_inc(v)          atomic_inc_return (v)
-#define atomic_dec(v)          atomic_dec_return (v)
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-
-#define atomic_sub_and_test(i,v)       (atomic_sub_return ((i), (v)) == 0)
-#define atomic_dec_and_test(v)         (atomic_sub_return (1, (v)) == 0)
-#define atomic_add_negative(i,v)       (atomic_add_return ((i), (v)) < 0)
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
-       int ret;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       ret = v->counter;
-       if (likely(ret == old))
-               v->counter = new;
-       local_irq_restore(flags);
-
-       return ret;
-}
-
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
-{
-       int ret;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       ret = v->counter;
-       if (ret != u)
-               v->counter += a;
-       local_irq_restore(flags);
-
-       return ret != u;
-}
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-/* Atomic operations are already serializing on ARM */
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec()     barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc()     barrier()
-
-#include <asm-generic/atomic.h>
-#endif /* __V850_ATOMIC_H__ */
diff --git a/include/asm-v850/auxvec.h b/include/asm-v850/auxvec.h
deleted file mode 100644 (file)
index f493232..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __V850_AUXVEC_H__
-#define __V850_AUXVEC_H__
-
-#endif /* __V850_AUXVEC_H__ */
diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h
deleted file mode 100644 (file)
index f82f5b4..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * include/asm-v850/bitops.h -- Bit operations
- *
- *  Copyright (C) 2001,02,03,04,05  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03,04,05  Miles Bader <miles@gnu.org>
- *  Copyright (C) 1992  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.
- */
-
-#ifndef __V850_BITOPS_H__
-#define __V850_BITOPS_H__
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-#include <linux/compiler.h>    /* unlikely  */
-#include <asm/byteorder.h>     /* swab32 */
-#include <asm/system.h>                /* interrupt enable/disable */
-
-
-#ifdef __KERNEL__
-
-#include <asm-generic/bitops/ffz.h>
-
-/*
- * The __ functions are not atomic
- */
-
-/* In the following constant-bit-op macros, a "g" constraint is used when
-   we really need an integer ("i" constraint).  This is to avoid
-   warnings/errors from the compiler in the case where the associated
-   operand _isn't_ an integer, and shouldn't produce bogus assembly because
-   use of that form is protected by a guard statement that checks for
-   constants, and should otherwise be removed by the optimizer.  This
-   _usually_ works -- however, __builtin_constant_p returns true for a
-   variable with a known constant value too, and unfortunately gcc will
-   happily put the variable in a register and use the register for the "g"
-   constraint'd asm operand.  To avoid the latter problem, we add a
-   constant offset to the operand and subtract it back in the asm code;
-   forcing gcc to do arithmetic on the value is usually enough to get it
-   to use a real constant value.  This is horrible, and ultimately
-   unreliable too, but it seems to work for now (hopefully gcc will offer
-   us more control in the future, so we can do a better job).  */
-
-#define __const_bit_op(op, nr, addr)                                   \
-  ({ __asm__ (op " (%0 - 0x123), %1"                                   \
-             :: "g" (((nr) & 0x7) + 0x123),                            \
-                "m" (*((char *)(addr) + ((nr) >> 3)))                  \
-             : "memory"); })
-#define __var_bit_op(op, nr, addr)                                     \
-  ({ int __nr = (nr);                                                  \
-     __asm__ (op " %0, [%1]"                                           \
-             :: "r" (__nr & 0x7),                                      \
-                "r" ((char *)(addr) + (__nr >> 3))                     \
-             : "memory"); })
-#define __bit_op(op, nr, addr)                                         \
-  ((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF)            \
-   ? __const_bit_op (op, nr, addr)                                     \
-   : __var_bit_op (op, nr, addr))
-
-#define __set_bit(nr, addr)            __bit_op ("set1", nr, addr)
-#define __clear_bit(nr, addr)          __bit_op ("clr1", nr, addr)
-#define __change_bit(nr, addr)         __bit_op ("not1", nr, addr)
-
-/* The bit instructions used by `non-atomic' variants are actually atomic.  */
-#define set_bit __set_bit
-#define clear_bit __clear_bit
-#define change_bit __change_bit
-
-
-#define __const_tns_bit_op(op, nr, addr)                                     \
-  ({ int __tns_res;                                                          \
-     __asm__ __volatile__ (                                                  \
-            "tst1 (%1 - 0x123), %2; setf nz, %0; " op " (%1 - 0x123), %2"    \
-            : "=&r" (__tns_res)                                              \
-            : "g" (((nr) & 0x7) + 0x123),                                    \
-              "m" (*((char *)(addr) + ((nr) >> 3)))                          \
-            : "memory");                                                     \
-     __tns_res;                                                                      \
-  })
-#define __var_tns_bit_op(op, nr, addr)                                       \
-  ({ int __nr = (nr);                                                        \
-     int __tns_res;                                                          \
-     __asm__ __volatile__ (                                                  \
-            "tst1 %1, [%2]; setf nz, %0; " op " %1, [%2]"                    \
-             : "=&r" (__tns_res)                                             \
-             : "r" (__nr & 0x7),                                             \
-               "r" ((char *)(addr) + (__nr >> 3))                            \
-             : "memory");                                                    \
-     __tns_res;                                                                      \
-  })
-#define __tns_bit_op(op, nr, addr)                                     \
-  ((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF)            \
-   ? __const_tns_bit_op (op, nr, addr)                                 \
-   : __var_tns_bit_op (op, nr, addr))
-#define __tns_atomic_bit_op(op, nr, addr)                              \
-  ({ int __tns_atomic_res, __tns_atomic_flags;                         \
-     local_irq_save (__tns_atomic_flags);                              \
-     __tns_atomic_res = __tns_bit_op (op, nr, addr);                   \
-     local_irq_restore (__tns_atomic_flags);                           \
-     __tns_atomic_res;                                                 \
-  })
-
-#define __test_and_set_bit(nr, addr)   __tns_bit_op ("set1", nr, addr)
-#define test_and_set_bit(nr, addr)     __tns_atomic_bit_op ("set1", nr, addr)
-
-#define __test_and_clear_bit(nr, addr) __tns_bit_op ("clr1", nr, addr)
-#define test_and_clear_bit(nr, addr)   __tns_atomic_bit_op ("clr1", nr, addr)
-
-#define __test_and_change_bit(nr, addr)        __tns_bit_op ("not1", nr, addr)
-#define test_and_change_bit(nr, addr)  __tns_atomic_bit_op ("not1", nr, addr)
-
-
-#define __const_test_bit(nr, addr)                                           \
-  ({ int __test_bit_res;                                                     \
-     __asm__ __volatile__ ("tst1 (%1 - 0x123), %2; setf nz, %0"                      \
-                          : "=r" (__test_bit_res)                            \
-                          : "g" (((nr) & 0x7) + 0x123),                      \
-                            "m" (*((const char *)(addr) + ((nr) >> 3))));    \
-     __test_bit_res;                                                         \
-  })
-static inline int __test_bit (int nr, const void *addr)
-{
-       int res;
-       __asm__ __volatile__ ("tst1 %1, [%2]; setf nz, %0"
-                             : "=r" (res)
-                             : "r" (nr & 0x7), "r" (addr + (nr >> 3)));
-       return res;
-}
-#define test_bit(nr,addr)                                              \
-  ((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF)            \
-   ? __const_test_bit ((nr), (addr))                                   \
-   : __test_bit ((nr), (addr)))
-
-
-/* clear_bit doesn't provide any barrier for the compiler.  */
-#define smp_mb__before_clear_bit()     barrier ()
-#define smp_mb__after_clear_bit()      barrier ()
-
-#include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/fls.h>
-#include <asm-generic/bitops/fls64.h>
-#include <asm-generic/bitops/__ffs.h>
-#include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
-
-#include <asm-generic/bitops/ext2-non-atomic.h>
-#define ext2_set_bit_atomic(l,n,a)      test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a)    test_and_clear_bit(n,a)
-
-#include <asm-generic/bitops/minix.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_BITOPS_H__ */
diff --git a/include/asm-v850/bug.h b/include/asm-v850/bug.h
deleted file mode 100644 (file)
index b0ed2d3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * include/asm-v850/bug.h -- Bug reporting
- *
- *  Copyright (C) 2003  NEC Electronics Corporation
- *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_BUG_H__
-#define __V850_BUG_H__
-
-#ifdef CONFIG_BUG
-extern void __bug (void) __attribute__ ((noreturn));
-#define BUG()          __bug()
-#define HAVE_ARCH_BUG
-#endif
-
-#include <asm-generic/bug.h>
-
-#endif /* __V850_BUG_H__ */
diff --git a/include/asm-v850/bugs.h b/include/asm-v850/bugs.h
deleted file mode 100644 (file)
index 71110a6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  include/asm-v850e/bugs.h
- *
- *  Copyright (C) 1994  Linus Torvalds
- */
-
-/*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- *     void check_bugs(void);
- */
-
-static void check_bugs(void)
-{
-}
diff --git a/include/asm-v850/byteorder.h b/include/asm-v850/byteorder.h
deleted file mode 100644 (file)
index a6f0753..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * include/asm-v850/byteorder.h -- Endian id and conversion ops
- *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_BYTEORDER_H__
-#define __V850_BYTEORDER_H__
-
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-#ifdef __GNUC__
-
-static __inline__ __attribute_const__ __u32 ___arch__swab32 (__u32 word)
-{
-       __u32 res;
-       __asm__ ("bsw %1, %0" : "=r" (res) : "r" (word));
-       return res;
-}
-
-static __inline__ __attribute_const__ __u16 ___arch__swab16 (__u16 half_word)
-{
-       __u16 res;
-       __asm__ ("bsh %1, %0" : "=r" (res) : "r" (half_word));
-       return res;
-}
-
-#define __arch__swab32(x) ___arch__swab32(x)
-#define __arch__swab16(x) ___arch__swab16(x)
-
-#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#  define __BYTEORDER_HAS_U64__
-#  define __SWAB_64_THRU_32__
-#endif
-
-#endif /* __GNUC__ */
-
-#include <linux/byteorder/little_endian.h>
-
-#endif /* __V850_BYTEORDER_H__ */
diff --git a/include/asm-v850/cache.h b/include/asm-v850/cache.h
deleted file mode 100644 (file)
index 8832c7e..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-v850/cache.h -- Cache operations
- *
- *  Copyright (C) 2001,05  NEC Corporation
- *  Copyright (C) 2001,05  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CACHE_H__
-#define __V850_CACHE_H__
-
-/* All cache operations are machine-dependent.  */
-#include <asm/machdep.h>
-
-#ifndef L1_CACHE_BYTES
-/* This processor has no cache, so just choose an arbitrary value.  */
-#define L1_CACHE_BYTES         16
-#define L1_CACHE_SHIFT         4
-#endif
-
-#endif /* __V850_CACHE_H__ */
diff --git a/include/asm-v850/cacheflush.h b/include/asm-v850/cacheflush.h
deleted file mode 100644 (file)
index 9ece05a..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * include/asm-v850/cacheflush.h
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CACHEFLUSH_H__
-#define __V850_CACHEFLUSH_H__
-
-/* Somebody depends on this; sigh...  */
-#include <linux/mm.h>
-
-#include <asm/machdep.h>
-
-
-/* The following are all used by the kernel in ways that only affect
-   systems with MMUs, so we don't need them.  */
-#define flush_cache_all()                      ((void)0)
-#define flush_cache_mm(mm)                     ((void)0)
-#define flush_cache_dup_mm(mm)                 ((void)0)
-#define flush_cache_range(vma, start, end)     ((void)0)
-#define flush_cache_page(vma, vmaddr, pfn)     ((void)0)
-#define flush_dcache_page(page)                        ((void)0)
-#define flush_dcache_mmap_lock(mapping)                ((void)0)
-#define flush_dcache_mmap_unlock(mapping)      ((void)0)
-#define flush_cache_vmap(start, end)           ((void)0)
-#define flush_cache_vunmap(start, end)         ((void)0)
-
-#ifdef CONFIG_NO_CACHE
-
-/* Some systems have no cache at all, in which case we don't need these
-   either.  */
-#define flush_icache()                         ((void)0)
-#define flush_icache_range(start, end)         ((void)0)
-#define flush_icache_page(vma,pg)              ((void)0)
-#define flush_icache_user_range(vma,pg,adr,len)        ((void)0)
-#define flush_cache_sigtramp(vaddr)            ((void)0)
-
-#else /* !CONFIG_NO_CACHE */
-
-struct page;
-struct mm_struct;
-struct vm_area_struct;
-
-/* Otherwise, somebody had better define them.  */
-extern void flush_icache (void);
-extern void flush_icache_range (unsigned long start, unsigned long end);
-extern void flush_icache_page (struct vm_area_struct *vma, struct page *page);
-extern void flush_icache_user_range (struct vm_area_struct *vma,
-                                    struct page *page,
-                                    unsigned long adr, int len);
-extern void flush_cache_sigtramp (unsigned long addr);
-
-#endif /* CONFIG_NO_CACHE */
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-       memcpy(dst, src, len)
-
-#endif /* __V850_CACHEFLUSH_H__ */
diff --git a/include/asm-v850/checksum.h b/include/asm-v850/checksum.h
deleted file mode 100644 (file)
index d1dddd9..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * include/asm-v850/checksum.h -- Checksum ops
- *
- *  Copyright (C) 2001,2005  NEC Corporation
- *  Copyright (C) 2001,2005  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CHECKSUM_H__
-#define __V850_CHECKSUM_H__
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-extern __wsum csum_partial_copy_nocheck(const void *src,
-                                  void *dst, int len, __wsum sum);
-
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-extern __wsum csum_partial_copy_from_user (const void *src,
-                                            void *dst,
-                                            int len, __wsum sum,
-                                            int *csum_err);
-
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-/*
- *     Fold a partial checksum
- */
-static inline __sum16 csum_fold (__wsum sum)
-{
-       unsigned int result;
-       /*
-                               %0              %1
-             hsw %1, %0        H     L         L     H
-             add %1, %0        H     L         H+L+C H+L
-       */
-       asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum));
-       return (__force __sum16)(~result >> 16);
-}
-
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __wsum
-csum_tcpudp_nofold (__be32 saddr, __be32 daddr,
-                   unsigned short len,
-                   unsigned short proto, __wsum sum)
-{
-       int __carry;
-       __asm__ ("add %2, %0;"
-                "setf c, %1;"
-                "add %1, %0;"
-                "add %3, %0;"
-                "setf c, %1;"
-                "add %1, %0;"
-                "add %4, %0;"
-                "setf c, %1;"
-                "add %1, %0"
-                : "=&r" (sum), "=&r" (__carry)
-                : "r" (daddr), "r" (saddr),
-                "r" ((len + proto) << 8),
-                "0" (sum));
-       return sum;
-}
-
-static inline __sum16
-csum_tcpudp_magic (__be32 saddr, __be32 daddr,
-                  unsigned short len,
-                  unsigned short proto, __wsum sum)
-{
-       return csum_fold (csum_tcpudp_nofold (saddr, daddr, len, proto, sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-
-#endif /* __V850_CHECKSUM_H__ */
diff --git a/include/asm-v850/clinkage.h b/include/asm-v850/clinkage.h
deleted file mode 100644 (file)
index c389691..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-v850/clinkage.h -- Macros to reflect C symbol-naming conventions
- *
- *  Copyright (C) 2001,02  NEC Corporatione
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CLINKAGE_H__
-#define __V850_CLINKAGE_H__
-
-#include <asm/macrology.h>
-#include <asm/asm.h>
-
-#define C_SYMBOL_NAME(name)    macrology_paste(_, name)
-#define C_SYMBOL_STRING(name)  macrology_stringify(C_SYMBOL_NAME(name))
-#define C_ENTRY(name)          G_ENTRY(C_SYMBOL_NAME(name))
-#define C_DATA(name)           G_DATA(C_SYMBOL_NAME(name))
-#define C_END(name)            END(C_SYMBOL_NAME(name))
-
-#endif /* __V850_CLINKAGE_H__ */
diff --git a/include/asm-v850/cputime.h b/include/asm-v850/cputime.h
deleted file mode 100644 (file)
index 7c799c3..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_CPUTIME_H
-#define __V850_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __V850_CPUTIME_H */
diff --git a/include/asm-v850/current.h b/include/asm-v850/current.h
deleted file mode 100644 (file)
index 30aae56..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * include/asm-v850/current.h -- Current task
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CURRENT_H__
-#define __V850_CURRENT_H__
-
-#ifndef __ASSEMBLY__ /* <linux/thread_info.h> is not asm-safe.  */
-#include <linux/thread_info.h>
-#endif
-
-#include <asm/macrology.h>
-
-
-/* Register used to hold the current task pointer while in the kernel.
-   Any `call clobbered' register without a special meaning should be OK,
-   but check asm/v850/kernel/entry.S to be sure.  */
-#define CURRENT_TASK_REGNUM    16
-#define CURRENT_TASK           macrology_paste (r, CURRENT_TASK_REGNUM)
-
-
-#ifdef __ASSEMBLY__
-
-/* Put a pointer to the current task structure into REG.  */
-#define GET_CURRENT_TASK(reg)                                          \
-       GET_CURRENT_THREAD(reg);                                        \
-       ld.w    TI_TASK[reg], reg
-
-#else /* !__ASSEMBLY__ */
-
-/* A pointer to the current task.  */
-register struct task_struct *current                                   \
-   __asm__ (macrology_stringify (CURRENT_TASK));
-
-#endif /* __ASSEMBLY__ */
-
-
-#endif /* _V850_CURRENT_H */
diff --git a/include/asm-v850/delay.h b/include/asm-v850/delay.h
deleted file mode 100644 (file)
index 6d028e6..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * include/asm-v850/delay.h -- Delay routines, using a pre-computed
- *     "loops_per_second" value
- *
- *  Copyright (C) 2001,03  NEC Corporation
- *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
- *  Copyright (C) 1994 Hamish Macdonald
- *
- * 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 __V850_DELAY_H__
-#define __V850_DELAY_H__
-
-#include <asm/param.h>
-
-static inline void __delay(unsigned long loops)
-{
-       if (loops)
-               __asm__ __volatile__ ("1: add -1, %0; bnz 1b"
-                                     : "=r" (loops) : "0" (loops));
-}
-
-/*
- * Use only for very small delays ( < 1 msec).  Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays.  This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)  
- */
-
-extern unsigned long loops_per_jiffy;
-
-static inline void udelay(unsigned long usecs)
-{
-       register unsigned long full_loops, part_loops;
-
-       full_loops = ((usecs * HZ) / 1000000) * loops_per_jiffy;
-       usecs %= (1000000 / HZ);
-       part_loops = (usecs * HZ * loops_per_jiffy) / 1000000;
-
-       __delay(full_loops + part_loops);
-}
-
-#endif /* __V850_DELAY_H__ */
diff --git a/include/asm-v850/device.h b/include/asm-v850/device.h
deleted file mode 100644 (file)
index d8f9872..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/include/asm-v850/div64.h b/include/asm-v850/div64.h
deleted file mode 100644 (file)
index 6cd978c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/include/asm-v850/dma-mapping.h b/include/asm-v850/dma-mapping.h
deleted file mode 100644 (file)
index 1cc42c6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __V850_DMA_MAPPING_H__
-#define __V850_DMA_MAPPING_H__
-
-
-#ifdef CONFIG_PCI
-#include <asm-generic/dma-mapping.h>
-#else
-#include <asm-generic/dma-mapping-broken.h>
-#endif
-
-#endif /* __V850_DMA_MAPPING_H__ */
diff --git a/include/asm-v850/dma.h b/include/asm-v850/dma.h
deleted file mode 100644 (file)
index 2369849..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef __V850_DMA_H__
-#define __V850_DMA_H__
-
-/* What should this be?  */
-#define MAX_DMA_ADDRESS        0xFFFFFFFF
-
-/* reserve a DMA channel */
-extern int request_dma (unsigned int dmanr, const char * device_id);
-/* release it again */
-extern void free_dma (unsigned int dmanr);
-
-#ifdef CONFIG_PCI
-extern int isa_dma_bridge_buggy;
-#else
-#define isa_dma_bridge_buggy    (0)
-#endif
-
-#endif /* __V850_DMA_H__ */
diff --git a/include/asm-v850/elf.h b/include/asm-v850/elf.h
deleted file mode 100644 (file)
index 28f5b17..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef __V850_ELF_H__
-#define __V850_ELF_H__
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/user.h>
-#include <asm/byteorder.h>
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_fpu_struct elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x)  \
-  ((x)->e_machine == EM_V850 || (x)->e_machine == EM_CYGNUS_V850)
-
-
-/* v850 relocation types.  */
-#define R_V850_NONE            0
-#define R_V850_9_PCREL         1
-#define R_V850_22_PCREL                2
-#define R_V850_HI16_S          3
-#define R_V850_HI16            4
-#define R_V850_LO16            5
-#define R_V850_32              6
-#define R_V850_16              7
-#define R_V850_8               8
-#define R_V850_SDA_16_16_OFFSET        9       /* For ld.b, st.b, set1, clr1,
-                                          not1, tst1, movea, movhi */
-#define R_V850_SDA_15_16_OFFSET        10      /* For ld.w, ld.h, ld.hu, st.w, st.h */
-#define R_V850_ZDA_16_16_OFFSET        11      /* For ld.b, st.b, set1, clr1,
-                                          not1, tst1, movea, movhi */
-#define R_V850_ZDA_15_16_OFFSET        12      /* For ld.w, ld.h, ld.hu, st.w, st.h */
-#define R_V850_TDA_6_8_OFFSET  13      /* For sst.w, sld.w */
-#define R_V850_TDA_7_8_OFFSET  14      /* For sst.h, sld.h */
-#define R_V850_TDA_7_7_OFFSET  15      /* For sst.b, sld.b */
-#define R_V850_TDA_16_16_OFFSET        16      /* For set1, clr1, not1, tst1,
-                                          movea, movhi */
-#define R_V850_NUM             17
-
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS      ELFCLASS32
-#ifdef __LITTLE_ENDIAN__
-#define ELF_DATA       ELFDATA2LSB
-#else
-#define ELF_DATA       ELFDATA2MSB
-#endif
-#define ELF_ARCH       EM_V850
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE      4096
-
-
-#define ELF_CORE_COPY_REGS(_dest,_regs)                                \
-       memcpy((char *) &_dest, (char *) _regs,                 \
-              sizeof(struct pt_regs));
-
-/* This yields a mask that user programs can use to figure out what
-   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)
-
-/* This yields a string that ld.so will use to load implementation
-   specific libraries for optimization.  This is more specific in
-   intent than poking at uname or /proc/cpuinfo.
-
-   For the moment, we have only optimizations for the Intel generations,
-   but that could change... */
-
-#define ELF_PLATFORM  (NULL)
-
-#define ELF_PLAT_INIT(_r, load_addr)                                         \
-  do {                                                                       \
-        _r->gpr[0] =  _r->gpr[1] =  _r->gpr[2] =  _r->gpr[3] =               \
-        _r->gpr[4] =  _r->gpr[5] =  _r->gpr[6] =  _r->gpr[7] =               \
-        _r->gpr[8] =  _r->gpr[9] = _r->gpr[10] = _r->gpr[11] =               \
-       _r->gpr[12] = _r->gpr[13] = _r->gpr[14] = _r->gpr[15] =               \
-       _r->gpr[16] = _r->gpr[17] = _r->gpr[18] = _r->gpr[19] =               \
-       _r->gpr[20] = _r->gpr[21] = _r->gpr[22] = _r->gpr[23] =               \
-       _r->gpr[24] = _r->gpr[25] = _r->gpr[26] = _r->gpr[27] =               \
-       _r->gpr[28] = _r->gpr[29] = _r->gpr[30] = _r->gpr[31] =               \
-       0;                                                                    \
-  } while (0)
-
-#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
-
-#endif /* __V850_ELF_H__ */
diff --git a/include/asm-v850/emergency-restart.h b/include/asm-v850/emergency-restart.h
deleted file mode 100644 (file)
index 108d8c4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/include/asm-v850/entry.h b/include/asm-v850/entry.h
deleted file mode 100644 (file)
index d9df8ac..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * include/asm-v850/entry.h -- Definitions used by low-level trap handlers
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_ENTRY_H__
-#define __V850_ENTRY_H__
-
-
-#include <asm/ptrace.h>
-#include <asm/machdep.h>
-
-
-/* These are special variables using by the kernel trap/interrupt code
-   to save registers in, at a time when there are no spare registers we
-   can use to do so, and we can't depend on the value of the stack
-   pointer.  This means that they must be within a signed 16-bit
-   displacement of 0x00000000.  */
-
-#define KERNEL_VAR_SPACE_ADDR  R0_RAM_ADDR
-
-#ifdef __ASSEMBLY__
-#define KERNEL_VAR(addr)       addr[r0]
-#else
-#define KERNEL_VAR(addr)       (*(volatile unsigned long *)(addr))
-#endif
-
-/* Kernel stack pointer, 4 bytes.  */
-#define KSP_ADDR               (KERNEL_VAR_SPACE_ADDR +  0)
-#define KSP                    KERNEL_VAR (KSP_ADDR)
-/* 1 if in kernel-mode, 0 if in user mode, 1 byte.  */
-#define KM_ADDR                (KERNEL_VAR_SPACE_ADDR +  4)
-#define KM                     KERNEL_VAR (KM_ADDR)
-/* Temporary storage for interrupt handlers, 4 bytes.  */
-#define INT_SCRATCH_ADDR       (KERNEL_VAR_SPACE_ADDR +  8)
-#define INT_SCRATCH            KERNEL_VAR (INT_SCRATCH_ADDR)
-/* Where the stack-pointer is saved when jumping to various sorts of
-   interrupt handlers.  ENTRY_SP is used by everything except NMIs,
-   which have their own location.  Higher-priority NMIs can clobber the
-   value written by a lower priority NMI, since they can't be disabled,
-   but that's OK, because only NMI0 (the lowest-priority one) is allowed
-   to return.  */
-#define ENTRY_SP_ADDR          (KERNEL_VAR_SPACE_ADDR + 12)
-#define ENTRY_SP               KERNEL_VAR (ENTRY_SP_ADDR)
-#define NMI_ENTRY_SP_ADDR      (KERNEL_VAR_SPACE_ADDR + 16)
-#define NMI_ENTRY_SP           KERNEL_VAR (NMI_ENTRY_SP_ADDR)
-
-#ifdef CONFIG_RESET_GUARD
-/* Used to detect unexpected resets (since the v850 has no MMU, any call
-   through a null pointer will jump to the reset vector).  We detect
-   such resets by checking for a magic value, RESET_GUARD_ACTIVE, in
-   this location.  Properly resetting the machine stores zero there, so
-   it shouldn't trigger the guard; the power-on value is uncertain, but
-   it's unlikely to be RESET_GUARD_ACTIVE.  */
-#define RESET_GUARD_ADDR       (KERNEL_VAR_SPACE_ADDR + 28)
-#define RESET_GUARD            KERNEL_VAR (RESET_GUARD_ADDR)
-#define RESET_GUARD_ACTIVE     0xFAB4BEEF
-#endif /* CONFIG_RESET_GUARD */
-
-#ifdef CONFIG_V850E_HIGHRES_TIMER
-#define HIGHRES_TIMER_SLOW_TICKS_ADDR (KERNEL_VAR_SPACE_ADDR + 32)
-#define HIGHRES_TIMER_SLOW_TICKS     KERNEL_VAR (HIGHRES_TIMER_SLOW_TICKS_ADDR)
-#endif /* CONFIG_V850E_HIGHRES_TIMER */
-
-#ifndef __ASSEMBLY__
-
-#ifdef CONFIG_RESET_GUARD
-/* Turn off reset guard, so that resetting the machine works normally.
-   This should be called in the various machine_halt, etc., functions.  */
-static inline void disable_reset_guard (void)
-{
-       RESET_GUARD = 0;
-}
-#endif /* CONFIG_RESET_GUARD */
-
-#endif /* !__ASSEMBLY__ */
-
-
-/* A `state save frame' is a struct pt_regs preceded by some extra space
-   suitable for a function call stack frame.  */
-
-/* Amount of room on the stack reserved for arguments and to satisfy the
-   C calling conventions, in addition to the space used by the struct
-   pt_regs that actually holds saved values.  */
-#define STATE_SAVE_ARG_SPACE   (6*4) /* Up to six arguments.  */
-
-
-#ifdef __ASSEMBLY__
-
-/* The size of a state save frame.  */
-#define STATE_SAVE_SIZE                (PT_SIZE + STATE_SAVE_ARG_SPACE)
-
-#else /* !__ASSEMBLY__ */
-
-/* The size of a state save frame.  */
-#define STATE_SAVE_SIZE               (sizeof (struct pt_regs) + STATE_SAVE_ARG_SPACE)
-
-#endif /* __ASSEMBLY__ */
-
-
-/* Offset of the struct pt_regs in a state save frame.  */
-#define STATE_SAVE_PT_OFFSET   STATE_SAVE_ARG_SPACE
-
-
-#endif /* __V850_ENTRY_H__ */
diff --git a/include/asm-v850/errno.h b/include/asm-v850/errno.h
deleted file mode 100644 (file)
index 31c91df..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_ERRNO_H__
-#define __V850_ERRNO_H__
-
-#include <asm-generic/errno.h>
-
-#endif /* __V850_ERRNO_H__ */
diff --git a/include/asm-v850/fb.h b/include/asm-v850/fb.h
deleted file mode 100644 (file)
index c7df380..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-#include <linux/fb.h>
-
-#define fb_pgprotect(...) do {} while (0)
-
-static inline int fb_is_primary_device(struct fb_info *info)
-{
-       return 0;
-}
-
-#endif /* _ASM_FB_H_ */
diff --git a/include/asm-v850/fcntl.h b/include/asm-v850/fcntl.h
deleted file mode 100644 (file)
index 3af4d56..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __V850_FCNTL_H__
-#define __V850_FCNTL_H__
-
-#define O_DIRECTORY    040000  /* must be a directory */
-#define O_NOFOLLOW     0100000 /* don't follow links */
-#define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE    0400000
-
-#include <asm-generic/fcntl.h>
-
-#endif /* __V850_FCNTL_H__ */
diff --git a/include/asm-v850/flat.h b/include/asm-v850/flat.h
deleted file mode 100644 (file)
index 17f0ea5..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * include/asm-v850/flat.h -- uClinux flat-format executables
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_FLAT_H__
-#define __V850_FLAT_H__
-
-/* The amount by which a relocation can exceed the program image limits
-   without being regarded as an error.  On the v850, the relocations of
-   some base-pointers can be offset by 0x8000 (to allow better usage of the
-   space offered by 16-bit signed offsets -- in most cases the offsets used
-   with such a base-pointer will be negative).  */
-
-#define        flat_reloc_valid(reloc, size)   ((reloc) <= (size + 0x8000))
-
-#define        flat_stack_align(sp)            /* nothing needed */
-#define        flat_argvp_envp_on_stack()      0
-#define        flat_old_ram_flag(flags)        (flags)
-#define        flat_set_persistent(relval, p)  0
-
-/* We store the type of relocation in the top 4 bits of the `relval.' */
-
-/* Convert a relocation entry into an address.  */
-static inline unsigned long
-flat_get_relocate_addr (unsigned long relval)
-{
-       return relval & 0x0fffffff; /* Mask out top 4-bits */
-}
-
-#define flat_v850_get_reloc_type(relval) ((relval) >> 28)
-
-#define FLAT_V850_R_32         0 /* Normal 32-bit reloc */
-#define FLAT_V850_R_HI16S_LO15 1 /* High 16-bits + signed 15-bit low field */
-#define FLAT_V850_R_HI16S_LO16 2 /* High 16-bits + signed 16-bit low field */
-
-/* Extract the address to be relocated from the symbol reference at RP;
-   RELVAL is the raw relocation-table entry from which RP is derived.
-   For the v850, RP should always be half-word aligned.  */
-static inline unsigned long flat_get_addr_from_rp (unsigned long *rp,
-                                                  unsigned long relval,
-                                                  unsigned long flags,
-                                                  unsigned long *persistent)
-{
-       short *srp = (short *)rp;
-
-       switch (flat_v850_get_reloc_type (relval))
-       {
-       case FLAT_V850_R_32:
-               /* Simple 32-bit address.  */
-               return srp[0] | (srp[1] << 16);
-
-       case FLAT_V850_R_HI16S_LO16:
-               /* The high and low halves of the address are in the 16
-                  bits at RP, and the 2nd word of the 32-bit instruction
-                  following that, respectively.  The low half is _signed_
-                  so we have to sign-extend it and add it to the upper
-                  half instead of simply or-ing them together.
-
-                  Unlike most relocated address, this one is stored in
-                  native (little-endian) byte-order to avoid problems with
-                  trashing the low-order bit, so we have to convert to
-                  network-byte-order before returning, as that's what the
-                  caller expects.  */
-               return htonl ((srp[0] << 16) + srp[2]);
-
-       case FLAT_V850_R_HI16S_LO15:
-               /* The high and low halves of the address are in the 16
-                  bits at RP, and the upper 15 bits of the 2nd word of the
-                  32-bit instruction following that, respectively.  The
-                  low half is _signed_ so we have to sign-extend it and
-                  add it to the upper half instead of simply or-ing them
-                  together.  The lowest bit is always zero.
-
-                  Unlike most relocated address, this one is stored in
-                  native (little-endian) byte-order to avoid problems with
-                  trashing the low-order bit, so we have to convert to
-                  network-byte-order before returning, as that's what the
-                  caller expects.  */
-               return htonl ((srp[0] << 16) + (srp[2] & ~0x1));
-
-       default:
-               return ~0;      /* bogus value */
-       }
-}
-
-/* Insert the address ADDR into the symbol reference at RP;
-   RELVAL is the raw relocation-table entry from which RP is derived.
-   For the v850, RP should always be half-word aligned.  */
-static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr,
-                                       unsigned long relval)
-{
-       short *srp = (short *)rp;
-
-       switch (flat_v850_get_reloc_type (relval)) {
-       case FLAT_V850_R_32:
-               /* Simple 32-bit address.  */
-               srp[0] = addr & 0xFFFF;
-               srp[1] = (addr >> 16);
-               break;
-
-       case FLAT_V850_R_HI16S_LO16:
-               /* The high and low halves of the address are in the 16
-                  bits at RP, and the 2nd word of the 32-bit instruction
-                  following that, respectively.  The low half is _signed_
-                  so we must carry its sign bit to the upper half before
-                  writing the upper half.  */
-               srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
-               srp[2] = addr & 0xFFFF;
-               break;
-
-       case FLAT_V850_R_HI16S_LO15:
-               /* The high and low halves of the address are in the 16
-                  bits at RP, and the upper 15 bits of the 2nd word of the
-                  32-bit instruction following that, respectively.  The
-                  low half is _signed_ so we must carry its sign bit to
-                  the upper half before writing the upper half.  The
-                  lowest bit we preserve from the existing instruction.  */
-               srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
-               srp[2] = (addr & 0xFFFE) | (srp[2] & 0x1);
-               break;
-       }
-}
-
-#endif /* __V850_FLAT_H__ */
diff --git a/include/asm-v850/fpga85e2c.h b/include/asm-v850/fpga85e2c.h
deleted file mode 100644 (file)
index 23aae66..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * include/asm-v850/fpga85e2c.h -- Machine-dependent defs for
- *     FPGA implementation of V850E2/NA85E2C
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_FPGA85E2C_H__
-#define __V850_FPGA85E2C_H__
-
-#include <asm/v850e2.h>
-#include <asm/clinkage.h>
-
-
-#define CPU_MODEL      "v850e2/fpga85e2c"
-#define CPU_MODEL_LONG "NEC V850E2/NA85E2C"
-#define PLATFORM       "fpga85e2c"
-#define PLATFORM_LONG  "NA85E2C FPGA implementation"
-
-
-/* `external ram'.  */
-#define ERAM_ADDR              0
-#define ERAM_SIZE              0x00100000 /* 1MB */
-
-
-/* FPGA specific control registers.  */
-
-/* Writing a non-zero value to FLGREG(0) will signal the controlling CPU
-   to stop execution.  */
-#define FLGREG_ADDR(n)         (0xFFE80100 + 2*(n))
-#define FLGREG(n)              (*(volatile unsigned char *)FLGREG_ADDR (n))
-#define FLGREG_NUM             2
-
-#define CSDEV_ADDR(n)          (0xFFE80110 + 2*(n))
-#define CSDEV(n)               (*(volatile unsigned char *)CSDEV_ADDR (n))
-
-
-/* Timer interrupts 0-3, interrupt at intervals from CLK/4096 to CLK/16384.  */
-#define IRQ_RPU(n)             (60 + (n))
-#define IRQ_RPU_NUM            4
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS           64
-
-
-/* General-purpose timer.  */
-/* control/status register (can only be read/written via bit insns) */
-#define RPU_GTMC_ADDR          0xFFFFFB00
-#define RPU_GTMC               (*(volatile unsigned char *)RPU_GTMC_ADDR)
-#define RPU_GTMC_CE_BIT                7 /* clock enable (control) */
-#define RPU_GTMC_OV_BIT                6 /* overflow (status) */
-#define RPU_GTMC_CLK_BIT       1 /* 0 = .5 MHz CLK, 1 = 1 Mhz (control) */
-/* 32-bit count (8 least-significant bits are always zero).  */
-#define RPU_GTM_ADDR           0xFFFFFB28
-#define RPU_GTM                        (*(volatile unsigned long *)RPU_GTMC_ADDR)
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET            ERAM_ADDR /* minimum allocatable address */
-
-
-/* For <asm/entry.h> */
-/* `R0 RAM', used for a few miscellaneous variables that must be accessible
-   using a load instruction relative to R0.  The FPGA implementation
-   actually has no on-chip RAM, so we use part of main ram just after the
-   interrupt vectors.  */
-#ifdef __ASSEMBLY__
-#define R0_RAM_ADDR            lo(C_SYMBOL_NAME(_r0_ram))
-#else
-extern char _r0_ram;
-#define R0_RAM_ADDR            ((unsigned long)&_r0_ram);
-#endif
-
-
-#endif /* __V850_FPGA85E2C_H__ */
diff --git a/include/asm-v850/futex.h b/include/asm-v850/futex.h
deleted file mode 100644 (file)
index 6a332a9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif
diff --git a/include/asm-v850/gbus_int.h b/include/asm-v850/gbus_int.h
deleted file mode 100644 (file)
index 0c4bce7..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * include/asm-v850/gbus_int.h -- Midas labs GBUS interrupt support
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_GBUS_INT_H__
-#define __V850_GBUS_INT_H__
-
-
-/* The GBUS interrupt interface has 32 interrupts shared among 4
-   processor interrupts.  The 32 GBUS interrupts are divided into two
-   sets of 16 each, for allocating among control registers, etc (there
-   are two of each control register, with bits 0-15 controlling an
-   interrupt each).  */
-
-/* The GBUS interrupts themselves.  */
-#define IRQ_GBUS_INT(n)                (GBUS_INT_BASE_IRQ + (n))
-#define IRQ_GBUS_INT_NUM       32
-
-/* Control registers.  */
-#define GBUS_INT_STATUS_ADDR(w)        (GBUS_INT_BASE_ADDR + (w)*0x40)
-#define GBUS_INT_STATUS(w)     (*(volatile u16 *)GBUS_INT_STATUS_ADDR(w))
-#define GBUS_INT_CLEAR_ADDR(w) (GBUS_INT_BASE_ADDR + 0x10 + (w)*0x40)
-#define GBUS_INT_CLEAR(w)      (*(volatile u16 *)GBUS_INT_CLEAR_ADDR(w))
-#define GBUS_INT_EDGE_ADDR(w)  (GBUS_INT_BASE_ADDR + 0x20 + (w)*0x40)
-#define GBUS_INT_EDGE(w)       (*(volatile u16 *)GBUS_INT_EDGE_ADDR(w))
-#define GBUS_INT_POLARITY_ADDR(w)      (GBUS_INT_BASE_ADDR + 0x30 + (w)*0x40)
-#define GBUS_INT_POLARITY(w)   (*(volatile u16 *)GBUS_INT_POLARITY_ADDR(w))
-/* This allows enabling interrupt bits in word W for interrupt GINTn.  */
-#define GBUS_INT_ENABLE_ADDR(w, n) \
-   (GBUS_INT_BASE_ADDR + 0x100 + (w)*0x10 + (n)*0x20)
-#define GBUS_INT_ENABLE(w, n)  (*(volatile u16 *)GBUS_INT_ENABLE_ADDR(w, n))
-
-/* Mapping between kernel interrupt numbers and hardware control regs/bits.  */
-#define GBUS_INT_BITS_PER_WORD 16
-#define GBUS_INT_NUM_WORDS     (IRQ_GBUS_INT_NUM / GBUS_INT_BITS_PER_WORD)
-#define GBUS_INT_IRQ_WORD(irq) (((irq) - GBUS_INT_BASE_IRQ) >> 4)
-#define GBUS_INT_IRQ_BIT(irq)  (((irq) - GBUS_INT_BASE_IRQ) & 0xF)
-#define GBUS_INT_IRQ_MASK(irq) (1 << GBUS_INT_IRQ_BIT(irq))
-
-
-/* Possible priorities for GBUS interrupts.  */
-#define GBUS_INT_PRIORITY_HIGH         2
-#define GBUS_INT_PRIORITY_MEDIUM       4
-#define GBUS_INT_PRIORITY_LOW          6
-
-
-#ifndef __ASSEMBLY__
-
-/* Enable interrupt handling for interrupt IRQ.  */
-extern void gbus_int_enable_irq (unsigned irq);
-/* Disable interrupt handling for interrupt IRQ.  Note that any
-   interrupts received while disabled will be delivered once the
-   interrupt is enabled again, unless they are explicitly cleared using
-   `gbus_int_clear_pending_irq'.  */
-extern void gbus_int_disable_irq (unsigned irq);
-/* Return true if interrupt handling for interrupt IRQ is enabled.  */
-extern int gbus_int_irq_enabled (unsigned irq);
-/* Disable all GBUS irqs.  */
-extern void gbus_int_disable_irqs (void);
-/* Clear any pending interrupts for IRQ.  */
-extern void gbus_int_clear_pending_irq (unsigned irq);
-/* Return true if interrupt IRQ is pending (but disabled).  */
-extern int gbus_int_irq_pending (unsigned irq);
-
-
-struct gbus_int_irq_init {
-       const char *name;       /* name of interrupt type */
-
-       /* Range of kernel irq numbers for this type:
-          BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM  */
-       unsigned base, num, interval;
-
-       unsigned priority;      /* interrupt priority to assign */
-};
-struct hw_interrupt_type;      /* fwd decl */
-
-/* Initialize HW_IRQ_TYPES for GBUS irqs described in array
-   INITS (which is terminated by an entry with the name field == 0).  */
-extern void gbus_int_init_irq_types (struct gbus_int_irq_init *inits,
-                                    struct hw_interrupt_type *hw_irq_types);
-
-/* Initialize GBUS interrupts.  */
-extern void gbus_int_init_irqs (void);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_GBUS_INT_H__ */
diff --git a/include/asm-v850/hardirq.h b/include/asm-v850/hardirq.h
deleted file mode 100644 (file)
index 04e2012..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __V850_HARDIRQ_H__
-#define __V850_HARDIRQ_H__
-
-#include <linux/threads.h>
-#include <linux/cache.h>
-
-#include <asm/irq.h>
-
-typedef struct {
-       unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-
-#define HARDIRQ_BITS   8
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-void ack_bad_irq(unsigned int irq);
-
-#endif /* __V850_HARDIRQ_H__ */
diff --git a/include/asm-v850/highres_timer.h b/include/asm-v850/highres_timer.h
deleted file mode 100644 (file)
index 486fb49..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * include/asm-v850/highres_timer.h -- High resolution timing routines
- *
- *  Copyright (C) 2001,03  NEC Electronics Corporation
- *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_HIGHRES_TIMER_H__
-#define __V850_HIGHRES_TIMER_H__
-
-#ifndef __ASSEMBLY__
-#include <linux/time.h>
-#endif
-
-#include <asm/entry.h>
-
-
-/* Frequency of the `slow ticks' (one tick each time the fast-tick
-   counter overflows).  */
-#define HIGHRES_TIMER_SLOW_TICK_RATE   25
-
-/* Which timer in the V850E `Timer D' we use.  */
-#define HIGHRES_TIMER_TIMER_D_UNIT     3
-
-
-#ifndef __ASSEMBLY__
-
-extern void highres_timer_start (void), highres_timer_stop (void);
-extern void highres_timer_reset (void);
-extern void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks);
-extern void highres_timer_ticks_to_timeval (u32 slow_ticks, u32 fast_ticks,
-                                           struct timeval *tv);
-extern void highres_timer_read (struct timeval *tv);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_HIGHRES_TIMER_H__ */
diff --git a/include/asm-v850/hw_irq.h b/include/asm-v850/hw_irq.h
deleted file mode 100644 (file)
index 043e94b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __V850_HW_IRQ_H__
-#define __V850_HW_IRQ_H__
-
-#endif /* __V850_HW_IRQ_H__ */
diff --git a/include/asm-v850/io.h b/include/asm-v850/io.h
deleted file mode 100644 (file)
index cdad251..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * include/asm-v850/io.h -- Misc I/O operations
- *
- *  Copyright (C) 2001,02,03,04,05  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03,04,05  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_IO_H__
-#define __V850_IO_H__
-
-#define IO_SPACE_LIMIT 0xFFFFFFFF
-
-#define readb(addr) \
-  ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
-#define readw(addr) \
-  ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
-#define readl(addr) \
-  ({ unsigned long __v = (*(volatile unsigned long *) (addr)); __v; })
-
-#define readb_relaxed(a) readb(a)
-#define readw_relaxed(a) readw(a)
-#define readl_relaxed(a) readl(a)
-
-#define writeb(val, addr) \
-  (void)((*(volatile unsigned char *) (addr)) = (val))
-#define writew(val, addr) \
-  (void)((*(volatile unsigned short *) (addr)) = (val))
-#define writel(val, addr) \
-  (void)((*(volatile unsigned int *) (addr)) = (val))
-
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-
-#define inb(addr)      readb (addr)
-#define inw(addr)      readw (addr)
-#define inl(addr)      readl (addr)
-#define outb(x, addr)  ((void) writeb (x, addr))
-#define outw(x, addr)  ((void) writew (x, addr))
-#define outl(x, addr)  ((void) writel (x, addr))
-
-#define inb_p(port)            inb((port))
-#define outb_p(val, port)      outb((val), (port))
-#define inw_p(port)            inw((port))
-#define outw_p(val, port)      outw((val), (port))
-#define inl_p(port)            inl((port))
-#define outl_p(val, port)      outl((val), (port))
-
-static inline void insb (unsigned long port, void *dst, unsigned long count)
-{
-       unsigned char *p = dst;
-       while (count--)
-               *p++ = inb (port);
-}
-static inline void insw (unsigned long port, void *dst, unsigned long count)
-{
-       unsigned short *p = dst;
-       while (count--)
-               *p++ = inw (port);
-}
-static inline void insl (unsigned long port, void *dst, unsigned long count)
-{
-       unsigned long *p = dst;
-       while (count--)
-               *p++ = inl (port);
-}
-
-static inline void
-outsb (unsigned long port, const void *src, unsigned long count)
-{
-       const unsigned char *p = src;
-       while (count--)
-               outb (*p++, port);
-}
-static inline void
-outsw (unsigned long port, const void *src, unsigned long count)
-{
-       const unsigned short *p = src;
-       while (count--)
-               outw (*p++, port);
-}
-static inline void
-outsl (unsigned long port, const void *src, unsigned long count)
-{
-       const unsigned long *p = src;
-       while (count--)
-               outl (*p++, port);
-}
-
-
-/* Some places try to pass in an loff_t for PHYSADDR (?!), so we cast it to
-   long before casting it to a pointer to avoid compiler warnings.  */
-#define ioremap(physaddr, size)        ((void __iomem *)(unsigned long)(physaddr))
-#define iounmap(addr)          ((void)0)
-
-#define ioremap_nocache(physaddr, size)                ioremap (physaddr, size)
-#define ioremap_writethrough(physaddr, size)   ioremap (physaddr, size)
-#define ioremap_fullcache(physaddr, size)      ioremap (physaddr, size)
-
-#define ioread8(addr)          readb (addr)
-#define ioread16(addr)         readw (addr)
-#define ioread32(addr)         readl (addr)
-#define iowrite8(val, addr)    writeb (val, addr)
-#define iowrite16(val, addr)   writew (val, addr)
-#define iowrite32(val, addr)   writel (val, addr)
-
-#define mmiowb()
-
-#define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
-#if 0
-/* This is really stupid; don't define it.  */
-#define page_to_bus(page)       page_to_phys (page)
-#endif
-
-/* Conversion between virtual and physical mappings.  */
-#define phys_to_virt(addr)     ((void *)__phys_to_virt (addr))
-#define virt_to_phys(addr)     ((unsigned long)__virt_to_phys (addr))
-
-#define memcpy_fromio(dst, src, len) memcpy (dst, (void *)src, len)
-#define memcpy_toio(dst, src, len) memcpy ((void *)dst, src, len)
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)   __va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p)  p
-
-#endif /* __V850_IO_H__ */
diff --git a/include/asm-v850/ioctl.h b/include/asm-v850/ioctl.h
deleted file mode 100644 (file)
index b279fe0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/include/asm-v850/ioctls.h b/include/asm-v850/ioctls.h
deleted file mode 100644 (file)
index 5313abd..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef __V850_IOCTLS_H__
-#define __V850_IOCTLS_H__
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#define TCSETSF2       _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
-
-#define FIONCLEX       0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX                0x5451
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
-#define FIOQSIZE       0x545E
-
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
-
-#endif /* __V850_IOCTLS_H__ */
diff --git a/include/asm-v850/ipcbuf.h b/include/asm-v850/ipcbuf.h
deleted file mode 100644 (file)
index d8cbe98..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __V850E_IPCBUF_H__
-#define __V850E_IPCBUF_H__
-
-/*
- * The user_ipc_perm structure for v850e architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode_t and seq
- * - 2 miscellaneous 32-bit values
- */
-
-struct ipc64_perm
-{
-       __kernel_key_t          key;
-       __kernel_uid32_t        uid;
-       __kernel_gid32_t        gid;
-       __kernel_uid32_t        cuid;
-       __kernel_gid32_t        cgid;
-       __kernel_mode_t         mode;
-       unsigned short          __pad1;
-       unsigned short          seq;
-       unsigned short          __pad2;
-       unsigned long           __unused1;
-       unsigned long           __unused2;
-};
-
-#endif /* __V850E_IPCBUF_H__ */
diff --git a/include/asm-v850/irq.h b/include/asm-v850/irq.h
deleted file mode 100644 (file)
index 7d0d4cd..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * include/asm-v850/irq.h -- Machine interrupt handling
- *
- *  Copyright (C) 2001,02,04  NEC Electronics Corporation
- *  Copyright (C) 2001,02,04  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_IRQ_H__
-#define __V850_IRQ_H__
-
-#include <asm/machdep.h>
-
-/* Default NUM_MACH_IRQS.  */
-#ifndef NUM_MACH_IRQS
-#define NUM_MACH_IRQS  NUM_CPU_IRQS
-#endif
-
-/* NMIs have IRQ numbers from FIRST_NMI to FIRST_NMI+NUM_NMIS-1.  */
-#define FIRST_NMI      NUM_MACH_IRQS
-#define IRQ_NMI(n)     (FIRST_NMI + (n))
-/* v850 processors have 3 non-maskable interrupts.  */
-#define NUM_NMIS       3
-
-/* Includes both maskable and non-maskable irqs.  */
-#define NR_IRQS                (NUM_MACH_IRQS + NUM_NMIS)
-
-
-#ifndef __ASSEMBLY__
-
-struct pt_regs;
-struct hw_interrupt_type;
-struct irqaction;
-
-#define irq_canonicalize(irq)  (irq)
-
-/* Initialize irq handling for IRQs.
-   BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL
-   to IRQ_TYPE.  An IRQ_TYPE of 0 means to use a generic interrupt type.  */
-extern void
-init_irq_handlers (int base_irq, int num, int interval,
-                  struct hw_interrupt_type *irq_type);
-
-/* Handle interrupt IRQ.  REGS are the registers at the time of ther
-   interrupt.  */
-extern unsigned int handle_irq (int irq, struct pt_regs *regs);
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __V850_IRQ_H__ */
diff --git a/include/asm-v850/irq_regs.h b/include/asm-v850/irq_regs.h
deleted file mode 100644 (file)
index 3dd9c0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/include/asm-v850/kdebug.h b/include/asm-v850/kdebug.h
deleted file mode 100644 (file)
index 6ece1b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/include/asm-v850/kmap_types.h b/include/asm-v850/kmap_types.h
deleted file mode 100644 (file)
index 3288976..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __V850_KMAP_TYPES_H__
-#define __V850_KMAP_TYPES_H__
-
-enum km_type {
-       KM_BOUNCE_READ,
-       KM_SKB_SUNRPC_DATA,
-       KM_SKB_DATA_SOFTIRQ,
-       KM_USER0,
-       KM_USER1,
-       KM_BIO_SRC_IRQ,
-       KM_BIO_DST_IRQ,
-       KM_PTE0,
-       KM_PTE1,
-       KM_IRQ0,
-       KM_IRQ1,
-       KM_TYPE_NR
-};
-
-#endif /* __V850_KMAP_TYPES_H__ */
diff --git a/include/asm-v850/kvm.h b/include/asm-v850/kvm.h
deleted file mode 100644 (file)
index 3f729b7..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_V850_H
-#define __LINUX_KVM_V850_H
-
-/* v850 does not support KVM */
-
-#endif
diff --git a/include/asm-v850/linkage.h b/include/asm-v850/linkage.h
deleted file mode 100644 (file)
index b6185d3..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ASM_LINKAGE_H
-#define __ASM_LINKAGE_H
-
-#ifdef __ASSEMBLY__
-#include <asm/asm.h>
-#endif
-
-#endif
diff --git a/include/asm-v850/local.h b/include/asm-v850/local.h
deleted file mode 100644 (file)
index 705148a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_LOCAL_H__
-#define __V850_LOCAL_H__
-
-#include <asm-generic/local.h>
-
-#endif /* __V850_LOCAL_H__ */
diff --git a/include/asm-v850/ma.h b/include/asm-v850/ma.h
deleted file mode 100644 (file)
index 89e6647..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * include/asm-v850/ma.h -- V850E/MA series of cpu chips
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MA_H__
-#define __V850_MA_H__
-
-/* The MA series uses the V850E cpu core.  */
-#include <asm/v850e.h>
-
-
-/* For <asm/entry.h> */
-/* We use on-chip RAM, for a few miscellaneous variables that must be
-   accessible using a load instruction relative to R0.  The amount
-   varies between chip models, but there's always at least 4K, and it
-   should always start at FFFFC000.  */
-#define R0_RAM_ADDR                    0xFFFFC000
-
-
-/* MA series UART details.  */
-#define V850E_UART_BASE_FREQ           CPU_CLOCK_FREQ
-
-/* This is a function that gets called before configuring the UART.  */
-#define V850E_UART_PRE_CONFIGURE       ma_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void ma_uart_pre_configure (unsigned chan,
-                                  unsigned cflags, unsigned baud);
-#endif
-
-
-/* MA series timer C details.  */
-#define V850E_TIMER_C_BASE_ADDR                0xFFFFF600
-
-
-/* MA series timer D details.  */
-#define V850E_TIMER_D_BASE_ADDR                0xFFFFF540
-#define V850E_TIMER_D_TMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_CMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x2)
-#define V850E_TIMER_D_TMCD_BASE_ADDR   (V850E_TIMER_D_BASE_ADDR + 0x4)
-
-#define V850E_TIMER_D_BASE_FREQ                CPU_CLOCK_FREQ
-
-
-/* Port 0 */
-/* Direct I/O.  Bits 0-7 are pins P00-P07.  */
-#define MA_PORT0_IO_ADDR               0xFFFFF400
-#define MA_PORT0_IO                    (*(volatile u8 *)MA_PORT0_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define MA_PORT0_PM_ADDR               0xFFFFF420
-#define MA_PORT0_PM                    (*(volatile u8 *)MA_PORT0_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
-#define MA_PORT0_PMC_ADDR              0xFFFFF440
-#define MA_PORT0_PMC                   (*(volatile u8 *)MA_PORT0_PMC_ADDR)
-/* Port function control (for P04-P07, 0 = IRQ, 1 = DMARQ).  */
-#define MA_PORT0_PFC_ADDR              0xFFFFF460
-#define MA_PORT0_PFC                   (*(volatile u8 *)MA_PORT0_PFC_ADDR)
-
-/* Port 1 */
-/* Direct I/O.  Bits 0-3 are pins P10-P13.  */
-#define MA_PORT1_IO_ADDR               0xFFFFF402
-#define MA_PORT1_IO                    (*(volatile u8 *)MA_PORT1_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define MA_PORT1_PM_ADDR               0xFFFFF420
-#define MA_PORT1_PM                    (*(volatile u8 *)MA_PORT1_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
-#define MA_PORT1_PMC_ADDR              0xFFFFF442
-#define MA_PORT1_PMC                   (*(volatile u8 *)MA_PORT1_PMC_ADDR)
-
-/* Port 4 */
-/* Direct I/O.  Bits 0-5 are pins P40-P45.  */
-#define MA_PORT4_IO_ADDR               0xFFFFF408
-#define MA_PORT4_IO                    (*(volatile u8 *)MA_PORT4_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define MA_PORT4_PM_ADDR               0xFFFFF428
-#define MA_PORT4_PM                    (*(volatile u8 *)MA_PORT4_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
-#define MA_PORT4_PMC_ADDR              0xFFFFF448
-#define MA_PORT4_PMC                   (*(volatile u8 *)MA_PORT4_PMC_ADDR)
-/* Port function control (for serial interfaces, 0 = CSI, 1 = UART).  */
-#define MA_PORT4_PFC_ADDR              0xFFFFF468
-#define MA_PORT4_PFC                   (*(volatile u8 *)MA_PORT4_PFC_ADDR)
-
-
-#ifndef __ASSEMBLY__
-
-/* Initialize MA chip interrupts.  */
-extern void ma_init_irqs (void);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_MA_H__ */
diff --git a/include/asm-v850/ma1.h b/include/asm-v850/ma1.h
deleted file mode 100644 (file)
index ede1f1d..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * include/asm-v850/ma1.h -- V850E/MA1 cpu chip
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MA1_H__
-#define __V850_MA1_H__
-
-/* Inherit more generic details from MA series.  */
-#include <asm/ma.h>
-
-
-#define CPU_MODEL      "v850e/ma1"
-#define CPU_MODEL_LONG "NEC V850E/MA1"
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace).  */
-#define IRQ_INTOV(n)   (n)     /* 0-3 */
-#define IRQ_INTOV_NUM  4
-#define IRQ_INTP(n)    (0x4  + (n)) /* Pnnn (pin) interrupts */
-#define IRQ_INTP_NUM   24
-#define IRQ_INTCMD(n)  (0x1c + (n)) /* interval timer interrupts 0-3 */
-#define IRQ_INTCMD_NUM 4
-#define IRQ_INTDMA(n)  (0x20 + (n)) /* DMA interrupts 0-3 */
-#define IRQ_INTDMA_NUM 4
-#define IRQ_INTCSI(n)  (0x24 + (n)*4)/* CSI 0-2 transmit/receive completion */
-#define IRQ_INTCSI_NUM 3
-#define IRQ_INTSER(n)  (0x25 + (n)*4) /* UART 0-2 reception error */
-#define IRQ_INTSER_NUM 3
-#define IRQ_INTSR(n)   (0x26 + (n)*4) /* UART 0-2 reception completion */
-#define IRQ_INTSR_NUM  3
-#define IRQ_INTST(n)   (0x27 + (n)*4) /* UART 0-2 transmission completion */
-#define IRQ_INTST_NUM  3
-
-#define NUM_CPU_IRQS   0x30
-
-
-/* The MA1 has a UART with 3 channels.  */
-#define V850E_UART_NUM_CHANNELS        3
-
-
-#endif /* __V850_MA1_H__ */
diff --git a/include/asm-v850/machdep.h b/include/asm-v850/machdep.h
deleted file mode 100644 (file)
index f1e3b8b..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * include/asm-v850/machdep.h -- Machine-dependent definitions
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MACHDEP_H__
-#define __V850_MACHDEP_H__
-
-
-/* chips */
-#ifdef CONFIG_V850E_MA1
-#include <asm/ma1.h>
-#endif
-#ifdef CONFIG_V850E_ME2
-#include <asm/me2.h>
-#endif
-#ifdef CONFIG_V850E_TEG
-#include <asm/teg.h>
-#endif
-
-/* These are both chips _and_ platforms, so put them in the middle... */
-#ifdef CONFIG_V850E2_ANNA
-#include <asm/anna.h>
-#endif
-#ifdef CONFIG_V850E_AS85EP1
-#include <asm/as85ep1.h>
-#endif
-
-/* platforms */
-#ifdef CONFIG_RTE_CB_MA1
-#include <asm/rte_ma1_cb.h>
-#endif
-#ifdef CONFIG_RTE_CB_ME2
-#include <asm/rte_me2_cb.h>
-#endif
-#ifdef CONFIG_RTE_CB_NB85E
-#include <asm/rte_nb85e_cb.h>
-#endif
-#ifdef CONFIG_V850E_SIM
-#include <asm/sim.h>
-#endif
-#ifdef CONFIG_V850E2_SIM85E2C
-#include <asm/sim85e2c.h>
-#endif
-#ifdef CONFIG_V850E2_SIM85E2S
-#include <asm/sim85e2s.h>
-#endif
-#ifdef CONFIG_V850E2_FPGA85E2C
-#include <asm/fpga85e2c.h>
-#endif
-
-#endif /* __V850_MACHDEP_H__ */
diff --git a/include/asm-v850/macrology.h b/include/asm-v850/macrology.h
deleted file mode 100644 (file)
index 37abf87..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * include/asm-v850/macrology.h -- Various useful CPP macros
- *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#define macrology_paste(arg1, arg2)    macrology_paste_1(arg1, arg2)
-#define macrology_paste_1(arg1, arg2)  arg1 ## arg2
-#define macrology_stringify(sym)       macrology_stringify_1(sym)
-#define macrology_stringify_1(sym)     #sym
diff --git a/include/asm-v850/me2.h b/include/asm-v850/me2.h
deleted file mode 100644 (file)
index ac7c9ce..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * include/asm-v850/me2.h -- V850E/ME2 cpu chip
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_ME2_H__
-#define __V850_ME2_H__
-
-#include <asm/v850e.h>
-#include <asm/v850e_cache.h>
-
-
-#define CPU_MODEL      "v850e/me2"
-#define CPU_MODEL_LONG "NEC V850E/ME2"
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace).  */
-#define IRQ_INTP(n)       (n) /* Pnnn (pin) interrupts */
-#define IRQ_INTP_NUM      31
-#define IRQ_INTCMD(n)     (0x31 + (n)) /* interval timer interrupts 0-3 */
-#define IRQ_INTCMD_NUM    4
-#define IRQ_INTDMA(n)     (0x41 + (n)) /* DMA interrupts 0-3 */
-#define IRQ_INTDMA_NUM    4
-#define IRQ_INTUBTIRE(n)  (0x49 + (n)*5)/* UARTB 0-1 reception error */
-#define IRQ_INTUBTIRE_NUM 2
-#define IRQ_INTUBTIR(n)   (0x4a + (n)*5) /* UARTB 0-1 reception complete */
-#define IRQ_INTUBTIR_NUM  2
-#define IRQ_INTUBTIT(n)   (0x4b + (n)*5) /* UARTB 0-1 transmission complete */
-#define IRQ_INTUBTIT_NUM  2
-#define IRQ_INTUBTIF(n)   (0x4c + (n)*5) /* UARTB 0-1 FIFO trans. complete */
-#define IRQ_INTUBTIF_NUM  2
-#define IRQ_INTUBTITO(n)  (0x4d + (n)*5) /* UARTB 0-1 reception timeout */
-#define IRQ_INTUBTITO_NUM 2
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS           0x59 /* V850E/ME2 */
-
-
-/* For <asm/entry.h> */
-/* We use on-chip RAM, for a few miscellaneous variables that must be
-   accessible using a load instruction relative to R0.  */
-#define R0_RAM_ADDR                    0xFFFFB000 /* V850E/ME2 */
-
-
-/* V850E/ME2 UARTB details.*/
-#define V850E_UART_NUM_CHANNELS                2
-#define V850E_UARTB_BASE_FREQ          (CPU_CLOCK_FREQ / 4)
-
-/* This is a function that gets called before configuring the UART.  */
-#define V850E_UART_PRE_CONFIGURE       me2_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void me2_uart_pre_configure (unsigned chan,
-                                   unsigned cflags, unsigned baud);
-#endif /* __ASSEMBLY__ */
-
-
-/* V850E/ME2 timer C details.  */
-#define V850E_TIMER_C_BASE_ADDR                0xFFFFF600
-
-
-/* V850E/ME2 timer D details.  */
-#define V850E_TIMER_D_BASE_ADDR                0xFFFFF540
-#define V850E_TIMER_D_TMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_CMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x2)
-#define V850E_TIMER_D_TMCD_BASE_ADDR   (V850E_TIMER_D_BASE_ADDR + 0x4)
-
-#define V850E_TIMER_D_BASE_FREQ                (CPU_CLOCK_FREQ / 2)
-
-
-/* Select iRAM mode.  */
-#define ME2_IRAMM_ADDR                 0xFFFFF80A
-#define ME2_IRAMM                      (*(volatile u8*)ME2_IRAMM_ADDR)
-
-
-/* Interrupt edge-detection configuration.  INTF(n) and INTR(n) are only
-   valid for n == 1, 2, or 5.  */
-#define ME2_INTF_ADDR(n)               (0xFFFFFC00 + (n) * 0x2)
-#define ME2_INTF(n)                    (*(volatile u8*)ME2_INTF_ADDR(n))
-#define ME2_INTR_ADDR(n)               (0xFFFFFC20 + (n) * 0x2)
-#define ME2_INTR(n)                    (*(volatile u8*)ME2_INTR_ADDR(n))
-#define ME2_INTFAL_ADDR                        0xFFFFFC10
-#define ME2_INTFAL                     (*(volatile u8*)ME2_INTFAL_ADDR)
-#define ME2_INTRAL_ADDR                        0xFFFFFC30
-#define ME2_INTRAL                     (*(volatile u8*)ME2_INTRAL_ADDR)
-#define ME2_INTFDH_ADDR                        0xFFFFFC16
-#define ME2_INTFDH                     (*(volatile u16*)ME2_INTFDH_ADDR)
-#define ME2_INTRDH_ADDR                        0xFFFFFC36
-#define ME2_INTRDH                     (*(volatile u16*)ME2_INTRDH_ADDR)
-#define ME2_SESC_ADDR(n)               (0xFFFFF609 + (n) * 0x10)
-#define ME2_SESC(n)                    (*(volatile u8*)ME2_SESC_ADDR(n))
-#define ME2_SESA10_ADDR                        0xFFFFF5AD
-#define ME2_SESA10                     (*(volatile u8*)ME2_SESA10_ADDR)
-#define ME2_SESA11_ADDR                        0xFFFFF5DD
-#define ME2_SESA11                     (*(volatile u8*)ME2_SESA11_ADDR)
-
-
-/* Port 1 */
-/* Direct I/O.  Bits 0-3 are pins P10-P13.  */
-#define ME2_PORT1_IO_ADDR              0xFFFFF402
-#define ME2_PORT1_IO                   (*(volatile u8 *)ME2_PORT1_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define ME2_PORT1_PM_ADDR              0xFFFFF422
-#define ME2_PORT1_PM                   (*(volatile u8 *)ME2_PORT1_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
-#define ME2_PORT1_PMC_ADDR             0xFFFFF442
-#define ME2_PORT1_PMC                  (*(volatile u8 *)ME2_PORT1_PMC_ADDR)
-/* Port function control (for serial interfaces, 0 = CSI30, 1 = UARTB0 ).  */
-#define ME2_PORT1_PFC_ADDR             0xFFFFF462
-#define ME2_PORT1_PFC                  (*(volatile u8 *)ME2_PORT1_PFC_ADDR)
-
-/* Port 2 */
-/* Direct I/O.  Bits 0-3 are pins P20-P25.  */
-#define ME2_PORT2_IO_ADDR              0xFFFFF404
-#define ME2_PORT2_IO                   (*(volatile u8 *)ME2_PORT2_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define ME2_PORT2_PM_ADDR              0xFFFFF424
-#define ME2_PORT2_PM                   (*(volatile u8 *)ME2_PORT2_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
-#define ME2_PORT2_PMC_ADDR             0xFFFFF444
-#define ME2_PORT2_PMC                  (*(volatile u8 *)ME2_PORT2_PMC_ADDR)
-/* Port function control (for serial interfaces, 0 = INTP2x, 1 = UARTB1 ).  */
-#define ME2_PORT2_PFC_ADDR             0xFFFFF464
-#define ME2_PORT2_PFC                  (*(volatile u8 *)ME2_PORT2_PFC_ADDR)
-
-/* Port 5 */
-/* Direct I/O.  Bits 0-5 are pins P50-P55.  */
-#define ME2_PORT5_IO_ADDR              0xFFFFF40A
-#define ME2_PORT5_IO                   (*(volatile u8 *)ME2_PORT5_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define ME2_PORT5_PM_ADDR              0xFFFFF42A
-#define ME2_PORT5_PM                   (*(volatile u8 *)ME2_PORT5_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
-#define ME2_PORT5_PMC_ADDR             0xFFFFF44A
-#define ME2_PORT5_PMC                  (*(volatile u8 *)ME2_PORT5_PMC_ADDR)
-/* Port function control ().  */
-#define ME2_PORT5_PFC_ADDR             0xFFFFF46A
-#define ME2_PORT5_PFC                  (*(volatile u8 *)ME2_PORT5_PFC_ADDR)
-
-/* Port 6 */
-/* Direct I/O.  Bits 5-7 are pins P65-P67.  */
-#define ME2_PORT6_IO_ADDR              0xFFFFF40C
-#define ME2_PORT6_IO                   (*(volatile u8 *)ME2_PORT6_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define ME2_PORT6_PM_ADDR              0xFFFFF42C
-#define ME2_PORT6_PM                   (*(volatile u8 *)ME2_PORT6_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
-#define ME2_PORT6_PMC_ADDR             0xFFFFF44C
-#define ME2_PORT6_PMC                  (*(volatile u8 *)ME2_PORT6_PMC_ADDR)
-/* Port function control ().  */
-#define ME2_PORT6_PFC_ADDR             0xFFFFF46C
-#define ME2_PORT6_PFC                  (*(volatile u8 *)ME2_PORT6_PFC_ADDR)
-
-/* Port 7 */
-/* Direct I/O.  Bits 2-7 are pins P72-P77.  */
-#define ME2_PORT7_IO_ADDR              0xFFFFF40E
-#define ME2_PORT7_IO                   (*(volatile u8 *)ME2_PORT7_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input).  */
-#define ME2_PORT7_PM_ADDR              0xFFFFF42E
-#define ME2_PORT7_PM                   (*(volatile u8 *)ME2_PORT7_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
-#define ME2_PORT7_PMC_ADDR             0xFFFFF44E
-#define ME2_PORT7_PMC                  (*(volatile u8 *)ME2_PORT7_PMC_ADDR)
-/* Port function control ().  */
-#define ME2_PORT7_PFC_ADDR             0xFFFFF46E
-#define ME2_PORT7_PFC                  (*(volatile u8 *)ME2_PORT7_PFC_ADDR)
-
-
-#ifndef __ASSEMBLY__
-/* Initialize V850E/ME2 chip interrupts.  */
-extern void me2_init_irqs (void);
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_ME2_H__ */
diff --git a/include/asm-v850/mman.h b/include/asm-v850/mman.h
deleted file mode 100644 (file)
index edbf6ed..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __V850_MMAN_H__
-#define __V850_MMAN_H__
-
-#include <asm-generic/mman.h>
-
-#define MAP_GROWSDOWN  0x0100          /* stack-like segment */
-#define MAP_DENYWRITE  0x0800          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
-#define MAP_LOCKED     0x2000          /* pages are locked */
-#define MAP_NORESERVE  0x4000          /* don't check for reservations */
-
-#define MCL_CURRENT    1               /* lock all current mappings */
-#define MCL_FUTURE     2               /* lock all future mappings */
-
-#endif /* __V850_MMAN_H__ */
diff --git a/include/asm-v850/mmu.h b/include/asm-v850/mmu.h
deleted file mode 100644 (file)
index 267768c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Copyright (C) 2002, 2005, David McCullough <davidm@snapgear.com> */
-
-#ifndef __V850_MMU_H__
-#define __V850_MMU_H__
-
-typedef struct {
-       struct vm_list_struct   *vmlist;
-       unsigned long           end_brk;
-} mm_context_t;
-
-#endif /* __V850_MMU_H__ */
diff --git a/include/asm-v850/mmu_context.h b/include/asm-v850/mmu_context.h
deleted file mode 100644 (file)
index 01daacd..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __V850_MMU_CONTEXT_H__
-#define __V850_MMU_CONTEXT_H__
-
-#include <asm-generic/mm_hooks.h>
-
-#define destroy_context(mm)            ((void)0)
-#define init_new_context(tsk,mm)       0
-#define switch_mm(prev,next,tsk)       ((void)0)
-#define deactivate_mm(tsk,mm)          do { } while (0)
-#define activate_mm(prev,next)         ((void)0)
-#define enter_lazy_tlb(mm,tsk)         ((void)0)
-
-#endif /* __V850_MMU_CONTEXT_H__ */
diff --git a/include/asm-v850/module.h b/include/asm-v850/module.h
deleted file mode 100644 (file)
index 2c2f494..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * include/asm-v850/module.h -- Architecture-specific module hooks
- *
- *  Copyright (C) 2001,02,03,04  NEC Corporation
- *  Copyright (C) 2001,02,03,04  Miles Bader <miles@gnu.org>
- *  Copyright (C) 2001,03  Rusty Russell
- *
- * 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.
- *
- * Written by Miles Bader <miles@gnu.org>
- *
- * Derived in part from include/asm-ppc/module.h
- */
-
-#ifndef __V850_MODULE_H__
-#define __V850_MODULE_H__
-
-#define MODULE_SYMBOL_PREFIX "_"
-
-struct v850_plt_entry
-{
-       /* Indirect jump instruction sequence (6-byte mov + 2-byte jr).  */
-       unsigned long tramp[2];
-};
-
-struct mod_arch_specific
-{
-       /* Indices of PLT sections within module. */
-       unsigned int core_plt_section, init_plt_section;
-};
-
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
-/* Make empty sections for module_frob_arch_sections to expand. */
-#ifdef MODULE
-asm(".section .plt,\"ax\",@nobits; .align 3; .previous");
-asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous");
-#endif
-
-/* We don't do exception tables.  */
-struct exception_table_entry;
-static inline const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
-              const struct exception_table_entry *last,
-              unsigned long value)
-{
-       return 0;
-}
-#define ARCH_HAS_SEARCH_EXTABLE
-static inline void
-sort_extable(struct exception_table_entry *start,
-            struct exception_table_entry *finish)
-{
-       /* nada */
-}
-#define ARCH_HAS_SORT_EXTABLE
-
-#endif /* __V850_MODULE_H__ */
diff --git a/include/asm-v850/msgbuf.h b/include/asm-v850/msgbuf.h
deleted file mode 100644 (file)
index ed07dbd..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __V850_MSGBUF_H__
-#define __V850_MSGBUF_H__
-
-/* 
- * The msqid64_ds structure for v850 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-       struct ipc64_perm msg_perm;
-       __kernel_time_t msg_stime;      /* last msgsnd time */
-       unsigned long   __unused1;
-       __kernel_time_t msg_rtime;      /* last msgrcv time */
-       unsigned long   __unused2;
-       __kernel_time_t msg_ctime;      /* last change time */
-       unsigned long   __unused3;
-       unsigned long  msg_cbytes;      /* current number of bytes on queue */
-       unsigned long  msg_qnum;        /* number of messages in queue */
-       unsigned long  msg_qbytes;      /* max number of bytes on queue */
-       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
-       __kernel_pid_t msg_lrpid;       /* last receive pid */
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-#endif /* __V850_MSGBUF_H__ */
diff --git a/include/asm-v850/mutex.h b/include/asm-v850/mutex.h
deleted file mode 100644 (file)
index 458c1f7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-v850/namei.h b/include/asm-v850/namei.h
deleted file mode 100644 (file)
index ee8339b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * linux/include/asm-v850/namei.h
- *
- * Included from linux/fs/namei.c
- */
-
-#ifndef __V850_NAMEI_H__
-#define __V850_NAMEI_H__
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __V850_NAMEI_H__ */
diff --git a/include/asm-v850/page.h b/include/asm-v850/page.h
deleted file mode 100644 (file)
index 74a539a..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * include/asm-v850/page.h -- VM ops
- *
- *  Copyright (C) 2001,02,03,05  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03,05  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PAGE_H__
-#define __V850_PAGE_H__
-
-#include <asm/machdep.h>
-
-
-#define PAGE_SHIFT     12
-#define PAGE_SIZE       (1UL << PAGE_SHIFT)
-#define PAGE_MASK       (~(PAGE_SIZE-1))
-
-
-/*
- * PAGE_OFFSET -- the first address of the first page of memory. For archs with
- * no MMU this corresponds to the first free page in physical memory (aligned
- * on a page boundary).
- */
-#ifndef PAGE_OFFSET
-#define PAGE_OFFSET  0x0000000
-#endif
-
-
-#ifndef __ASSEMBLY__
-
-#define STRICT_MM_TYPECHECKS
-
-#define clear_page(page)       memset ((void *)(page), 0, PAGE_SIZE)
-#define copy_page(to, from)    memcpy ((void *)(to), (void *)from, PAGE_SIZE)
-
-#define clear_user_page(addr, vaddr, page)     \
-       do {    clear_page(addr);               \
-               flush_dcache_page(page);        \
-       } while (0)
-#define copy_user_page(to, from, vaddr, page)  \
-       do {    copy_page(to, from);            \
-               flush_dcache_page(page);        \
-       } while (0)
-
-#ifdef STRICT_MM_TYPECHECKS
-/*
- * 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;
-typedef struct page *pgtable_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) } )
-
-#else /* !STRICT_MM_TYPECHECKS */
-/*
- * .. while these make it easier on the compiler
- */
-
-typedef unsigned long pte_t;
-typedef unsigned long pmd_t;
-typedef unsigned long pgd_t;
-typedef unsigned long pgprot_t;
-
-#define pte_val(x)      (x)
-#define pmd_val(x)      (x)
-#define pgd_val(x)      (x)
-#define pgprot_val(x)   (x)
-
-#define __pte(x)        (x)
-#define __pmd(x)        (x)
-#define __pgd(x)        (x)
-#define __pgprot(x)     (x)
-
-#endif /* STRICT_MM_TYPECHECKS */
-
-#endif /* !__ASSEMBLY__ */
-
-
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
-
-/* No current v850 processor has virtual memory.  */
-#define __virt_to_phys(addr)   (addr)
-#define __phys_to_virt(addr)   (addr)
-
-#define virt_to_pfn(kaddr)     (__virt_to_phys (kaddr) >> PAGE_SHIFT)
-#define pfn_to_virt(pfn)       __phys_to_virt ((pfn) << PAGE_SHIFT)
-
-#define MAP_NR(kaddr) \
-  (((unsigned long)(kaddr) - PAGE_OFFSET) >> PAGE_SHIFT)
-#define virt_to_page(kaddr)    (mem_map + MAP_NR (kaddr))
-#define page_to_virt(page) \
-  ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
-
-#define ARCH_PFN_OFFSET                (PAGE_OFFSET >> PAGE_SHIFT)
-#define pfn_valid(pfn)         ((pfn) < max_mapnr)
-
-#define        virt_addr_valid(kaddr)                                          \
-  (((void *)(kaddr) >= (void *)PAGE_OFFSET) && MAP_NR (kaddr) < max_mapnr)
-
-
-#define __pa(x)                     __virt_to_phys ((unsigned long)(x))
-#define __va(x)                     ((void *)__phys_to_virt ((unsigned long)(x)))
-
-
-#include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
-
-#endif /* __V850_PAGE_H__ */
diff --git a/include/asm-v850/param.h b/include/asm-v850/param.h
deleted file mode 100644 (file)
index 4391f5f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * include/asm-v850/param.h -- Varions kernel parameters
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PARAM_H__
-#define __V850_PARAM_H__
-
-#define EXEC_PAGESIZE  4096
-
-#ifndef NOGROUP
-#define NOGROUP                (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64      /* max length of hostname */
-
-#ifdef __KERNEL__
-# define HZ            CONFIG_HZ
-# define USER_HZ       100
-# define CLOCKS_PER_SEC        USER_HZ
-#else
-# define HZ            100
-#endif
-
-#endif /* __V850_PARAM_H__ */
diff --git a/include/asm-v850/pci.h b/include/asm-v850/pci.h
deleted file mode 100644 (file)
index de2a7d0..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * include/asm-v850/pci.h -- PCI support
- *
- *  Copyright (C) 2001,02,05  NEC Corporation
- *  Copyright (C) 2001,02,05  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PCI_H__
-#define __V850_PCI_H__
-
-/* Get any platform-dependent definitions.  */
-#include <asm/machdep.h>
-
-#define pcibios_scan_all_fns(a, b)     0
-
-/* Generic declarations.  */
-
-struct scatterlist;
-
-extern void pcibios_set_master (struct pci_dev *dev);
-
-/* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA.  The
-   32-bit PCI bus mastering address to use is returned.  the device owns
-   this memory until either pci_unmap_single or pci_dma_sync_single_for_cpu is
-   performed.  */
-extern dma_addr_t
-pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir);
-
-/* Return to the CPU the PCI DMA memory block previously `granted' to
-   PDEV, at DMA_ADDR.  */
-extern void
-pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
-                 int dir);
-
-/* Make physical memory consistent for a single streaming mode DMA
-   translation after a transfer.
-
-   If you perform a pci_map_single() but wish to interrogate the
-   buffer using the cpu, yet do not wish to teardown the PCI dma
-   mapping, you must call this function before doing so.  At the next
-   point you give the PCI dma address back to the card, you must first
-   perform a pci_dma_sync_for_device, and then the device again owns
-   the buffer.  */
-extern void
-pci_dma_sync_single_for_cpu (struct pci_dev *dev, dma_addr_t dma_addr,
-                            size_t size, int dir);
-
-extern void
-pci_dma_sync_single_for_device (struct pci_dev *dev, dma_addr_t dma_addr,
-                               size_t size, int dir);
-
-
-/* Do multiple DMA mappings at once.  */
-extern int
-pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir);
-
-/* Unmap multiple DMA mappings at once.  */
-extern void
-pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,
-             int dir);
-
-/* SG-list versions of pci_dma_sync functions.  */
-extern void
-pci_dma_sync_sg_for_cpu (struct pci_dev *dev,
-                        struct scatterlist *sg, int sg_len,
-                        int dir);
-extern void
-pci_dma_sync_sg_for_device (struct pci_dev *dev,
-                           struct scatterlist *sg, int sg_len,
-                           int dir);
-
-#define pci_map_page(dev, page, offs, size, dir) \
-  pci_map_single(dev, (page_address(page) + (offs)), size, dir)
-#define pci_unmap_page(dev,addr,sz,dir) \
-  pci_unmap_single(dev, addr, sz, dir)
-
-/* Test for pci_map_single or pci_map_page having generated an error.  */
-static inline int
-pci_dma_mapping_error (dma_addr_t dma_addr)
-{
-       return dma_addr == 0;
-}
-
-/* Allocate and map kernel buffer using consistent mode DMA for PCI
-   device.  Returns non-NULL cpu-view pointer to the buffer if
-   successful and sets *DMA_ADDR to the pci side dma address as well,
-   else DMA_ADDR is undefined.  */
-extern void *
-pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr);
-
-/* Free and unmap a consistent DMA buffer.  CPU_ADDR and DMA_ADDR must
-   be values that were returned from pci_alloc_consistent.  SIZE must be
-   the same as what as passed into pci_alloc_consistent.  References to
-   the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past
-   this call are illegal.  */
-extern void
-pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
-                    dma_addr_t dma_addr);
-
-#ifdef CONFIG_PCI
-static inline void pci_dma_burst_advice(struct pci_dev *pdev,
-                                       enum pci_dma_burst_strategy *strat,
-                                       unsigned long *strategy_parameter)
-{
-       *strat = PCI_DMA_BURST_INFINITY;
-       *strategy_parameter = ~0UL;
-}
-#endif
-
-extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
-extern void pci_iounmap (struct pci_dev *dev, void __iomem *addr);
-
-#endif /* __V850_PCI_H__ */
diff --git a/include/asm-v850/percpu.h b/include/asm-v850/percpu.h
deleted file mode 100644 (file)
index 755ac65..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __V850_PERCPU_H__
-#define __V850_PERCPU_H__
-
-#include <asm-generic/percpu.h>
-
-/* This is a stupid hack to satisfy some grotty implicit include-file
-   dependency; basically, <linux/smp.h> uses BUG_ON, which calls BUG, but
-   doesn't include the necessary headers to define it.  In the twisted
-   festering mess of includes this must all be resolved somehow on other
-   platforms, but I haven't the faintest idea how, and don't care; here will
-   do, even though doesn't actually make any sense.  */
-#include <asm/page.h>
-
-#endif /* __V850_PERCPU_H__ */
diff --git a/include/asm-v850/pgalloc.h b/include/asm-v850/pgalloc.h
deleted file mode 100644 (file)
index b91eb2d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * include/asm-v850/pgalloc.h
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PGALLOC_H__
-#define __V850_PGALLOC_H__
-
-#include <linux/mm.h>  /* some crap code expects this */
-
-/* ... and then, there was one.  */
-#define check_pgt_cache()      ((void)0)
-
-#endif /* __V850_PGALLOC_H__ */
diff --git a/include/asm-v850/pgtable.h b/include/asm-v850/pgtable.h
deleted file mode 100644 (file)
index 1ea2a90..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef __V850_PGTABLE_H__
-#define __V850_PGTABLE_H__
-
-#include <asm-generic/4level-fixup.h>
-
-#include <asm/page.h>
-
-
-#define pgd_present(pgd)       (1) /* pages are always present on NO_MM */
-#define pgd_none(pgd)          (0)
-#define pgd_bad(pgd)           (0)
-#define pgd_clear(pgdp)                ((void)0)
-
-#define        pmd_offset(a, b)        ((void *)0)
-
-#define kern_addr_valid(addr)  (1)
-
-
-#define __swp_type(x)          (0)
-#define __swp_offset(x)                (0)
-#define __swp_entry(typ,off)   ((swp_entry_t) { ((typ) | ((off) << 7)) })
-#define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
-
-static inline int pte_file (pte_t pte) { return 0; }
-
-
-/* These mean nothing to !CONFIG_MMU.  */
-#define PAGE_NONE              __pgprot(0)
-#define PAGE_SHARED            __pgprot(0)
-#define PAGE_COPY              __pgprot(0)
-#define PAGE_READONLY          __pgprot(0)
-#define PAGE_KERNEL            __pgprot(0)
-
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc.  When CONFIG_MMU is not defined, this
- * should never actually be used, so just define it to something that's
- * will hopefully cause a bus error if it is.
- */
-#define ZERO_PAGE(vaddr)       ((void *)0x87654321)
-
-
-/* Some bogus code in procfs uses these; whatever.  */
-#define VMALLOC_START  0
-#define VMALLOC_END    (~0)
-
-
-extern void paging_init (void);
-#define swapper_pg_dir ((pgd_t *) 0)
-
-#define pgtable_cache_init()   ((void)0)
-
-
-extern unsigned int kobjsize(const void *objp);
-
-
-#endif /* __V850_PGTABLE_H__ */
diff --git a/include/asm-v850/poll.h b/include/asm-v850/poll.h
deleted file mode 100644 (file)
index 803cad0..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __V850_POLL_H__
-#define __V850_POLL_H__
-
-#define POLLWRNORM     POLLOUT
-#define POLLWRBAND     0x0100
-
-#include <asm-generic/poll.h>
-
-#endif /* __V850_POLL_H__ */
diff --git a/include/asm-v850/posix_types.h b/include/asm-v850/posix_types.h
deleted file mode 100644 (file)
index 7f403b7..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * include/asm-v850/posix_types.h -- Kernel versions of standard types
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_POSIX_TYPES_H__
-#define __V850_POSIX_TYPES_H__
-
-typedef unsigned long  __kernel_ino_t;
-typedef unsigned long long __kernel_ino64_t;
-typedef unsigned int   __kernel_mode_t;
-typedef unsigned int   __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef long long      __kernel_loff_t;
-typedef int            __kernel_pid_t;
-typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned int   __kernel_uid_t;
-typedef unsigned int   __kernel_gid_t;
-typedef unsigned int   __kernel_size_t;
-typedef int            __kernel_ssize_t;
-typedef int            __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
-
-/* Some bogus code depends on this; we don't care.  */
-typedef __kernel_uid_t __kernel_old_uid_t;
-typedef unsigned int   __kernel_old_dev_t;
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-
-#if defined(__KERNEL__)
-
-/* We used to include <asm/bitops.h> here, which seems the right thing, but
-   it caused nasty include-file definition order problems.  Removing the
-   include seems to work, so fingers crossed...  */
-
-#undef __FD_SET
-#define __FD_SET(fd, fd_set) \
-  __set_bit (fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
-#undef __FD_CLR
-#define __FD_CLR(fd, fd_set) \
-  __clear_bit (fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
-#undef __FD_ISSET
-#define __FD_ISSET(fd, fd_set) \
-  __test_bit (fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
-#undef __FD_ZERO
-#define __FD_ZERO(fd_set) \
-  memset (fd_set, 0, sizeof (*(fd_set *)fd_set))
-
-#endif /* defined(__KERNEL__) */
-
-#endif /* __V850_POSIX_TYPES_H__ */
diff --git a/include/asm-v850/processor.h b/include/asm-v850/processor.h
deleted file mode 100644 (file)
index 979e346..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * include/asm-v850/processor.h
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PROCESSOR_H__
-#define __V850_PROCESSOR_H__
-
-#ifndef __ASSEMBLY__ /* <linux/thread_info.h> is not asm-safe.  */
-#include <linux/thread_info.h>
-#endif
-
-#include <linux/compiler.h>
-#include <asm/ptrace.h>
-#include <asm/entry.h>
-
-/* Some code expects `segment' stuff to be defined here.  */
-#include <asm/segment.h>
-
-
-/*
- * The only places this is used seem to be horrible bletcherous kludges,
- * so we just define it to be as large as possible.
- */
-#define TASK_SIZE      (0xFFFFFFFF)
-
-/*
- * This decides where the kernel will search for a free chunk of vm
- * space during mmap's.  We won't be using it.
- */
-#define TASK_UNMAPPED_BASE     0
-
-
-#ifndef __ASSEMBLY__
-
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr()    ({ __label__ _l; _l: &&_l;})
-
-/* If you change this, you must change the associated assembly-languages
-   constants defined below, THREAD_*.  */
-struct thread_struct {
-       /* kernel stack pointer (must be first field in structure) */
-       unsigned long  ksp;
-};
-
-#define INIT_THREAD { sizeof init_stack + (unsigned long)init_stack }
-
-
-/* Do necessary setup to start up a newly executed thread.  */
-static inline void start_thread (struct pt_regs *regs,
-                                unsigned long pc, unsigned long usp)
-{
-       regs->pc = pc;
-       regs->gpr[GPR_SP] = usp;
-       regs->kernel_mode = 0;
-}
-
-/* Free all resources held by a thread. */
-static inline void release_thread (struct task_struct *dead_task)
-{
-}
-
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk)   do { } while (0)
-
-extern int kernel_thread (int (*fn)(void *), void * arg, unsigned long flags);
-
-/* Free current thread data structures etc.  */
-static inline void exit_thread (void)
-{
-}
-
-
-/* Return the registers saved during context-switch by the currently
-   not-running thread T.  Note that this only includes some registers!
-   See entry.S for details.  */
-#define thread_saved_regs(t) \
-   ((struct pt_regs*)((t)->thread.ksp + STATE_SAVE_PT_OFFSET))
-/* Return saved (kernel) PC of a blocked thread.  Actually, we return the
-   LP register, because the thread is actually blocked in switch_thread,
-   and we're interested in the PC it will _return_ to.  */
-#define thread_saved_pc(t)   (thread_saved_regs(t)->gpr[GPR_LP])
-
-
-unsigned long get_wchan (struct task_struct *p);
-
-
-/* Return some info about the user process TASK.  */
-#define task_tos(task) ((unsigned long)task_stack_page(task) + THREAD_SIZE)
-#define task_pt_regs(task) ((struct pt_regs *)task_tos (task) - 1)
-#define task_sp(task)  (task_pt_regs (task)->gpr[GPR_SP])
-#define task_pc(task)  (task_pt_regs (task)->pc)
-/* Grotty old names for some.  */
-#define KSTK_EIP(task) task_pc (task)
-#define KSTK_ESP(task) task_sp (task)
-
-
-#define cpu_relax()    barrier()
-
-
-#else /* __ASSEMBLY__ */
-
-#define THREAD_KSP     0
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_PROCESSOR_H__ */
diff --git a/include/asm-v850/ptrace.h b/include/asm-v850/ptrace.h
deleted file mode 100644 (file)
index 4f35cf2..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * include/asm-v850/ptrace.h -- Access to CPU registers
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PTRACE_H__
-#define __V850_PTRACE_H__
-
-
-/* v850 general purpose registers with special meanings.  */
-#define GPR_ZERO       0       /* constant zero */
-#define GPR_ASM                1       /* reserved for assembler */
-#define GPR_SP         3       /* stack pointer */
-#define GPR_GP         4       /* global data pointer */
-#define GPR_TP         5       /* `text pointer' */
-#define GPR_EP         30      /* `element pointer' */
-#define GPR_LP         31      /* link pointer (current return address) */
-
-/* These aren't official names, but they make some code more descriptive.  */
-#define GPR_ARG0       6
-#define GPR_ARG1       7
-#define GPR_ARG2       8
-#define GPR_ARG3       9
-#define GPR_RVAL0      10
-#define GPR_RVAL1      11
-#define GPR_RVAL       GPR_RVAL0
-
-#define NUM_GPRS       32
-
-/* v850 `system' registers.  */
-#define SR_EIPC                0
-#define SR_EIPSW       1
-#define SR_FEPC                2
-#define SR_FEPSW       3
-#define SR_ECR         4
-#define SR_PSW         5
-#define SR_CTPC                16
-#define SR_CTPSW       17
-#define SR_DBPC                18
-#define SR_DBPSW       19
-#define SR_CTBP                20
-#define SR_DIR         21
-#define SR_ASID                23
-
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long v850_reg_t;
-
-/* How processor state is stored on the stack during a syscall/signal.
-   If you change this structure, change the associated assembly-language
-   macros below too (PT_*)!  */
-struct pt_regs
-{
-       /* General purpose registers.  */
-       v850_reg_t gpr[NUM_GPRS];
-
-       v850_reg_t pc;          /* program counter */
-       v850_reg_t psw;         /* program status word */
-
-       /* Registers used by `callt' instruction:  */
-       v850_reg_t ctpc;        /* saved program counter */
-       v850_reg_t ctpsw;       /* saved psw */
-       v850_reg_t ctbp;        /* base pointer for callt table */
-
-       char kernel_mode;       /* 1 if in `kernel mode', 0 if user mode */
-};
-
-
-#define instruction_pointer(regs)      ((regs)->pc)
-#define profile_pc(regs) instruction_pointer(regs)
-#define user_mode(regs)                        (!(regs)->kernel_mode)
-
-/* When a struct pt_regs is used to save user state for a system call in
-   the kernel, the system call is stored in the space for R0 (since it's
-   never used otherwise, R0 being a constant 0).  Non-system-calls
-   simply store 0 there.  */
-#define PT_REGS_SYSCALL(regs)          (regs)->gpr[0]
-#define PT_REGS_SET_SYSCALL(regs, val) ((regs)->gpr[0] = (val))
-
-#endif /* !__ASSEMBLY__ */
-
-
-/* The number of bytes used to store each register.  */
-#define _PT_REG_SIZE   4
-
-/* Offset of a general purpose register in a struct pt_regs.  */
-#define PT_GPR(num)    ((num) * _PT_REG_SIZE)
-
-/* Offsets of various special registers & fields in a struct pt_regs.  */
-#define PT_PC          ((NUM_GPRS + 0) * _PT_REG_SIZE)
-#define PT_PSW         ((NUM_GPRS + 1) * _PT_REG_SIZE)
-#define PT_CTPC                ((NUM_GPRS + 2) * _PT_REG_SIZE)
-#define PT_CTPSW       ((NUM_GPRS + 3) * _PT_REG_SIZE)
-#define PT_CTBP                ((NUM_GPRS + 4) * _PT_REG_SIZE)
-#define PT_KERNEL_MODE ((NUM_GPRS + 5) * _PT_REG_SIZE)
-
-/* Where the current syscall number is stashed; obviously only valid in
-   the kernel!  */
-#define PT_CUR_SYSCALL PT_GPR(0)
-
-/* Size of struct pt_regs, including alignment.  */
-#define PT_SIZE                ((NUM_GPRS + 6) * _PT_REG_SIZE)
-
-
-/* These are `magic' values for PTRACE_PEEKUSR that return info about where
-   a process is located in memory.  */
-#define PT_TEXT_ADDR   (PT_SIZE + 1)
-#define PT_TEXT_LEN    (PT_SIZE + 2)
-#define PT_DATA_ADDR   (PT_SIZE + 3)
-
-
-#endif /* __V850_PTRACE_H__ */
diff --git a/include/asm-v850/resource.h b/include/asm-v850/resource.h
deleted file mode 100644 (file)
index 4b9dcd4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_RESOURCE_H__
-#define __V850_RESOURCE_H__
-
-#include <asm-generic/resource.h>
-
-#endif /* __V850_RESOURCE_H__ */
diff --git a/include/asm-v850/rte_cb.h b/include/asm-v850/rte_cb.h
deleted file mode 100644 (file)
index db9879f..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * include/asm-v850/rte_cb.h -- Midas labs RTE-CB series of evaluation boards
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_RTE_CB_H__
-#define __V850_RTE_CB_H__
-
-
-/* The SRAM on the Mother-A motherboard.  */
-#define MB_A_SRAM_ADDR         GCS0_ADDR
-#define MB_A_SRAM_SIZE         0x00200000 /* 2MB */
-
-
-#ifdef CONFIG_RTE_GBUS_INT
-/* GBUS interrupt support.  */
-
-# include <asm/gbus_int.h>
-
-# define GBUS_INT_BASE_IRQ     NUM_RTE_CB_IRQS
-# define GBUS_INT_BASE_ADDR    (GCS2_ADDR + 0x00006000)
-
-/* Some specific interrupts.  */
-# define IRQ_MB_A_LAN          IRQ_GBUS_INT(10)
-# define IRQ_MB_A_PCI1(n)      (IRQ_GBUS_INT(16) + (n))
-# define IRQ_MB_A_PCI1_NUM     4
-# define IRQ_MB_A_PCI2(n)      (IRQ_GBUS_INT(20) + (n))
-# define IRQ_MB_A_PCI2_NUM     4
-# define IRQ_MB_A_EXT(n)       (IRQ_GBUS_INT(24) + (n))
-# define IRQ_MB_A_EXT_NUM      4
-# define IRQ_MB_A_USB_OC(n)    (IRQ_GBUS_INT(28) + (n))
-# define IRQ_MB_A_USB_OC_NUM   2
-# define IRQ_MB_A_PCMCIA_OC    IRQ_GBUS_INT(30)
-
-/* We define NUM_MACH_IRQS to include extra interrupts from the GBUS.  */
-# define NUM_MACH_IRQS         (NUM_RTE_CB_IRQS + IRQ_GBUS_INT_NUM)
-
-#else /* !CONFIG_RTE_GBUS_INT */
-
-# define NUM_MACH_IRQS         NUM_RTE_CB_IRQS
-
-#endif /* CONFIG_RTE_GBUS_INT */
-
-
-#ifdef CONFIG_RTE_MB_A_PCI
-/* Mother-A PCI bus support.  */
-
-# include <asm/rte_mb_a_pci.h>
-
-/* These are the base addresses used for allocating device address
-   space.  512K of the motherboard SRAM is in the same space, so we have
-   to be careful not to let it be allocated.  */
-# define PCIBIOS_MIN_MEM       (MB_A_PCI_MEM_ADDR + 0x80000)
-# define PCIBIOS_MIN_IO                MB_A_PCI_IO_ADDR
-
-/* As we don't really support PCI DMA to cpu memory, and use bounce-buffers
-   instead, perversely enough, this becomes always true! */
-# define pci_dma_supported(dev, mask)          1
-# define pcibios_assign_all_busses()           1
-
-#endif /* CONFIG_RTE_MB_A_PCI */
-
-
-#ifndef __ASSEMBLY__
-extern void rte_cb_early_init (void);
-extern void rte_cb_init_irqs (void);
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_RTE_CB_H__ */
diff --git a/include/asm-v850/rte_ma1_cb.h b/include/asm-v850/rte_ma1_cb.h
deleted file mode 100644 (file)
index bd3162a..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * include/asm-v850/rte_ma1_cb.h -- Midas labs RTE-V850/MA1-CB board
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_RTE_MA1_CB_H__
-#define __V850_RTE_MA1_CB_H__
-
-#include <asm/rte_cb.h>                /* Common defs for Midas RTE-CB boards.  */
-
-
-#define PLATFORM               "rte-v850e/ma1-cb"
-#define PLATFORM_LONG          "Midas lab RTE-V850E/MA1-CB"
-
-#define CPU_CLOCK_FREQ         50000000 /* 50MHz */
-
-/* 1MB of onboard SRAM.  Note that the monitor ROM uses parts of this
-   for its own purposes, so care must be taken.  Some address lines are
-   not decoded, so the SRAM area is mirrored every 1MB from 0x400000 to
-   0x800000 (exclusive).  */
-#define SRAM_ADDR              0x00400000
-#define SRAM_SIZE              0x00100000 /* 1MB */
-
-/* 32MB of onbard SDRAM.  */
-#define SDRAM_ADDR             0x00800000
-#define SDRAM_SIZE             0x02000000 /* 32MB */
-
-
-/* CPU addresses of GBUS memory spaces.  */
-#define GCS0_ADDR              0x05000000 /* GCS0 - Common SRAM (2MB) */
-#define GCS0_SIZE              0x00200000 /*   2MB */
-#define GCS1_ADDR              0x06000000 /* GCS1 - Flash ROM (8MB) */
-#define GCS1_SIZE              0x00800000 /*   8MB */
-#define GCS2_ADDR              0x07900000 /* GCS2 - I/O registers */
-#define GCS2_SIZE              0x00400000 /*   4MB */
-#define GCS5_ADDR              0x04000000 /* GCS5 - PCI bus space */
-#define GCS5_SIZE              0x01000000 /*   16MB */
-#define GCS6_ADDR              0x07980000 /* GCS6 - PCI control registers */
-#define GCS6_SIZE              0x00000200 /*   512B */
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET            SRAM_ADDR
-
-
-/* The GBUS GINT0 - GINT3 interrupts are connected to the INTP000 - INTP011
-   pins on the CPU.  These are shared among the GBUS interrupts.  */
-#define IRQ_GINT(n)            IRQ_INTP(n)
-#define IRQ_GINT_NUM           4
-
-/* Used by <asm/rte_cb.h> to derive NUM_MACH_IRQS.  */
-#define NUM_RTE_CB_IRQS                NUM_CPU_IRQS
-
-
-#ifdef CONFIG_ROM_KERNEL
-/* Kernel is in ROM, starting at address 0.  */
-
-#define INTV_BASE              0
-
-#else /* !CONFIG_ROM_KERNEL */
-
-#ifdef CONFIG_RTE_CB_MULTI
-/* Using RAM kernel with ROM monitor for Multi debugger.  */
-
-/* The chip's real interrupt vectors are in ROM, but they jump to a
-   secondary interrupt vector table in RAM.  */
-#define INTV_BASE              0x004F8000
-
-/* Scratch memory used by the ROM monitor, which shouldn't be used by
-   linux (except for the alternate interrupt vector area, defined
-   above).  */
-#define MON_SCRATCH_ADDR       0x004F8000
-#define MON_SCRATCH_SIZE       0x00008000 /* 32KB */
-
-#else /* !CONFIG_RTE_CB_MULTI */
-/* Using RAM-kernel.  Assume some sort of boot-loader got us loaded at
-   address 0.  */
-
-#define INTV_BASE              0
-
-#endif /* CONFIG_RTE_CB_MULTI */
-
-#endif /* CONFIG_ROM_KERNEL */
-
-
-/* Some misc. on-board devices.  */
-
-/* Seven-segment LED display (two digits).  Write-only.  */
-#define LED_ADDR(n)            (0x07802000 + (n))
-#define LED(n)                 (*(volatile unsigned char *)LED_ADDR(n))
-#define LED_NUM_DIGITS         2
-
-
-/* Override the basic MA uart pre-initialization so that we can
-   initialize extra stuff.  */
-#undef V850E_UART_PRE_CONFIGURE        /* should be defined by <asm/ma.h> */
-#define V850E_UART_PRE_CONFIGURE       rte_ma1_cb_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void rte_ma1_cb_uart_pre_configure (unsigned chan,
-                                          unsigned cflags, unsigned baud);
-#endif
-
-/* This board supports RTS/CTS for the on-chip UART, but only for channel 0. */
-
-/* CTS for UART channel 0 is pin P43 (bit 3 of port 4).  */
-#define V850E_UART_CTS(chan)   ((chan) == 0 ? !(MA_PORT4_IO & 0x8) : 1)
-/* RTS for UART channel 0 is pin P42 (bit 2 of port 4).  */
-#define V850E_UART_SET_RTS(chan, val)                                        \
-   do {                                                                              \
-          if (chan == 0) {                                                   \
-                  unsigned old = MA_PORT4_IO;                                \
-                  if (val)                                                   \
-                          MA_PORT4_IO = old & ~0x4;                          \
-                  else                                                       \
-                          MA_PORT4_IO = old | 0x4;                           \
-          }                                                                  \
-   } while (0)
-
-
-#endif /* __V850_RTE_MA1_CB_H__ */
diff --git a/include/asm-v850/rte_mb_a_pci.h b/include/asm-v850/rte_mb_a_pci.h
deleted file mode 100644 (file)
index 41ac185..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * include/asm-v850/mb_a_pci.h -- PCI support for Midas lab RTE-MOTHER-A board
- *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MB_A_PCI_H__
-#define __V850_MB_A_PCI_H__
-
-
-#define MB_A_PCI_MEM_ADDR      GCS5_ADDR
-#define MB_A_PCI_MEM_SIZE      (GCS5_SIZE / 2)
-#define MB_A_PCI_IO_ADDR       (GCS5_ADDR + MB_A_PCI_MEM_SIZE)
-#define MB_A_PCI_IO_SIZE       (GCS5_SIZE / 2)
-#define MB_A_PCI_REG_BASE_ADDR GCS6_ADDR
-
-#define MB_A_PCI_PCICR_ADDR    (MB_A_PCI_REG_BASE_ADDR + 0x4)
-#define MB_A_PCI_PCICR         (*(volatile u16 *)MB_A_PCI_PCICR_ADDR)
-#define MB_A_PCI_PCISR_ADDR    (MB_A_PCI_REG_BASE_ADDR + 0x6)
-#define MB_A_PCI_PCISR         (*(volatile u16 *)MB_A_PCI_PCISR_ADDR)
-#define MB_A_PCI_PCILTR_ADDR   (MB_A_PCI_REG_BASE_ADDR + 0xD)
-#define MB_A_PCI_PCILTR                (*(volatile u8 *)MB_A_PCI_PCILTR_ADDR)
-#define MB_A_PCI_PCIBAR0_ADDR  (MB_A_PCI_REG_BASE_ADDR + 0x10)
-#define MB_A_PCI_PCIBAR0       (*(volatile u32 *)MB_A_PCI_PCIBAR0_ADDR)
-#define MB_A_PCI_PCIBAR1_ADDR  (MB_A_PCI_REG_BASE_ADDR + 0x14)
-#define MB_A_PCI_PCIBAR1       (*(volatile u32 *)MB_A_PCI_PCIBAR1_ADDR)
-#define MB_A_PCI_PCIBAR2_ADDR  (MB_A_PCI_REG_BASE_ADDR + 0x18)
-#define MB_A_PCI_PCIBAR2       (*(volatile u32 *)MB_A_PCI_PCIBAR2_ADDR)
-#define MB_A_PCI_VENDOR_ID_ADDR        (MB_A_PCI_REG_BASE_ADDR + 0x2C)
-#define MB_A_PCI_VENDOR_ID     (*(volatile u16 *)MB_A_PCI_VENDOR_ID_ADDR)
-#define MB_A_PCI_DEVICE_ID_ADDR        (MB_A_PCI_REG_BASE_ADDR + 0x2E)
-#define MB_A_PCI_DEVICE_ID     (*(volatile u16 *)MB_A_PCI_DEVICE_ID_ADDR)
-#define MB_A_PCI_DMRR_ADDR     (MB_A_PCI_REG_BASE_ADDR + 0x9C)
-#define MB_A_PCI_DMRR          (*(volatile u32 *)MB_A_PCI_DMRR_ADDR)
-#define MB_A_PCI_DMLBAM_ADDR   (MB_A_PCI_REG_BASE_ADDR + 0xA0)
-#define MB_A_PCI_DMLBAM                (*(volatile u32 *)MB_A_PCI_DMLBAM_ADDR)
-#define MB_A_PCI_DMLBAI_ADDR   (MB_A_PCI_REG_BASE_ADDR + 0xA4)
-#define MB_A_PCI_DMLBAI                (*(volatile u32 *)MB_A_PCI_DMLBAI_ADDR)
-#define MB_A_PCI_PCIPBAM_ADDR  (MB_A_PCI_REG_BASE_ADDR + 0xA8)
-#define MB_A_PCI_PCIPBAM       (*(volatile u32 *)MB_A_PCI_PCIPBAM_ADDR)
-/* `PCI Configuration Address Register for Direct Master to PCI IO/CFG'  */
-#define MB_A_PCI_DMCFGA_ADDR   (MB_A_PCI_REG_BASE_ADDR + 0xAC)
-#define MB_A_PCI_DMCFGA                (*(volatile u32 *)MB_A_PCI_DMCFGA_ADDR)
-/* `PCI Permanent Configuration ID Register'  */
-#define MB_A_PCI_PCIHIDR_ADDR  (MB_A_PCI_REG_BASE_ADDR + 0xF0)
-#define MB_A_PCI_PCIHIDR       (*(volatile u32 *)MB_A_PCI_PCIHIDR_ADDR)
-
-
-#endif /* __V850_MB_A_PCI_H__ */
diff --git a/include/asm-v850/rte_me2_cb.h b/include/asm-v850/rte_me2_cb.h
deleted file mode 100644 (file)
index 9922c85..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * include/asm-v850/rte_me2_cb.h -- Midas labs RTE-V850E/ME2-CB board
- *
- *  Copyright (C) 2001,02,03  NEC Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_RTE_ME2_CB_H__
-#define __V850_RTE_ME2_CB_H__
-
-#include <asm/rte_cb.h>                /* Common defs for Midas RTE-CB boards.  */
-
-
-#define PLATFORM               "rte-v850e/me2-cb"
-#define PLATFORM_LONG          "Midas lab RTE-V850E/ME2-CB"
-
-#define CPU_CLOCK_FREQ         150000000 /* 150MHz */
-#define FIXED_BOGOMIPS         50
-
-/* 32MB of onbard SDRAM.  */
-#define SDRAM_ADDR             0x00800000
-#define SDRAM_SIZE             0x02000000 /* 32MB */
-
-
-/* CPU addresses of GBUS memory spaces.  */
-#define GCS0_ADDR              0x04000000 /* GCS0 - Common SRAM (2MB) */
-#define GCS0_SIZE              0x00800000 /*   8MB */
-#define GCS1_ADDR              0x04800000 /* GCS1 - Flash ROM (8MB) */
-#define GCS1_SIZE              0x00800000 /*   8MB */
-#define GCS2_ADDR              0x07000000 /* GCS2 - I/O registers */
-#define GCS2_SIZE              0x00800000 /*   8MB */
-#define GCS5_ADDR              0x08000000 /* GCS5 - PCI bus space */
-#define GCS5_SIZE              0x02000000 /*   32MB */
-#define GCS6_ADDR              0x07800000 /* GCS6 - PCI control registers */
-#define GCS6_SIZE              0x00800000 /*   8MB */
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET            SDRAM_ADDR
-
-
-#ifdef CONFIG_ROM_KERNEL
-/* Kernel is in ROM, starting at address 0.  */
-
-#define INTV_BASE              0
-#define ROOT_FS_IMAGE_RW       0
-
-#else /* !CONFIG_ROM_KERNEL */
-/* Using RAM-kernel.  Assume some sort of boot-loader got us loaded at
-   address 0.  */
-
-#define INTV_BASE              0
-#define ROOT_FS_IMAGE_RW       1
-
-#endif /* CONFIG_ROM_KERNEL */
-
-
-/* Some misc. on-board devices.  */
-
-/* Seven-segment LED display (four digits).  */
-#define LED_ADDR(n)            (0x0FE02000 + (n))
-#define LED(n)                 (*(volatile unsigned char *)LED_ADDR(n))
-#define LED_NUM_DIGITS         4
-
-
-/* On-board PIC.  */
-
-#define CB_PIC_BASE_ADDR       0x0FE04000
-
-#define CB_PIC_INT0M_ADDR      (CB_PIC_BASE_ADDR + 0x00)
-#define CB_PIC_INT0M           (*(volatile u16 *)CB_PIC_INT0M_ADDR)
-#define CB_PIC_INT1M_ADDR      (CB_PIC_BASE_ADDR + 0x10)
-#define CB_PIC_INT1M           (*(volatile u16 *)CB_PIC_INT1M_ADDR)
-#define CB_PIC_INTR_ADDR       (CB_PIC_BASE_ADDR + 0x20)
-#define CB_PIC_INTR            (*(volatile u16 *)CB_PIC_INTR_ADDR)
-#define CB_PIC_INTEN_ADDR      (CB_PIC_BASE_ADDR + 0x30)
-#define CB_PIC_INTEN           (*(volatile u16 *)CB_PIC_INTEN_ADDR)
-
-#define CB_PIC_INT0EN          0x0001
-#define CB_PIC_INT1EN          0x0002
-#define CB_PIC_INT0SEL         0x0080
-
-/* The PIC interrupts themselves.  */
-#define CB_PIC_BASE_IRQ                NUM_CPU_IRQS
-#define IRQ_CB_PIC_NUM         10
-
-/* Some specific CB_PIC interrupts. */
-#define IRQ_CB_EXTTM0          (CB_PIC_BASE_IRQ + 0)
-#define IRQ_CB_EXTSIO          (CB_PIC_BASE_IRQ + 1)
-#define IRQ_CB_TOVER           (CB_PIC_BASE_IRQ + 2)
-#define IRQ_CB_GINT0           (CB_PIC_BASE_IRQ + 3)
-#define IRQ_CB_USB             (CB_PIC_BASE_IRQ + 4)
-#define IRQ_CB_LANC            (CB_PIC_BASE_IRQ + 5)
-#define IRQ_CB_USB_VBUS_ON     (CB_PIC_BASE_IRQ + 6)
-#define IRQ_CB_USB_VBUS_OFF    (CB_PIC_BASE_IRQ + 7)
-#define IRQ_CB_EXTTM1          (CB_PIC_BASE_IRQ + 8)
-#define IRQ_CB_EXTTM2          (CB_PIC_BASE_IRQ + 9)
-
-/* The GBUS GINT1 - GINT3 (note, not GINT0!) interrupts are connected to
-   the INTP65 - INTP67 pins on the CPU.  These are shared among the GBUS
-   interrupts.  */
-#define IRQ_GINT(n)            IRQ_INTP((n) + 9)  /* 0 is unused! */
-#define IRQ_GINT_NUM           4                  /* 0 is unused! */
-
-/* The shared interrupt line from the PIC is connected to CPU pin INTP23.  */
-#define IRQ_CB_PIC             IRQ_INTP(4) /* P23 */
-
-/* Used by <asm/rte_cb.h> to derive NUM_MACH_IRQS.  */
-#define NUM_RTE_CB_IRQS                (NUM_CPU_IRQS + IRQ_CB_PIC_NUM)
-
-
-#ifndef __ASSEMBLY__
-struct cb_pic_irq_init {
-       const char *name;       /* name of interrupt type */
-
-       /* Range of kernel irq numbers for this type:
-          BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM  */
-       unsigned base, num, interval;
-
-       unsigned priority;      /* interrupt priority to assign */
-};
-struct hw_interrupt_type;      /* fwd decl */
-
-/* Enable interrupt handling for interrupt IRQ.  */
-extern void cb_pic_enable_irq (unsigned irq);
-/* Disable interrupt handling for interrupt IRQ.  Note that any interrupts
-   received while disabled will be delivered once the interrupt is enabled
-   again, unless they are explicitly cleared using `cb_pic_clear_pending_irq'.  */
-extern void cb_pic_disable_irq (unsigned irq);
-/* Initialize HW_IRQ_TYPES for PIC irqs described in array INITS (which is
-   terminated by an entry with the name field == 0).  */
-extern void cb_pic_init_irq_types (struct cb_pic_irq_init *inits,
-                                  struct hw_interrupt_type *hw_irq_types);
-/* Initialize PIC interrupts.  */
-extern void cb_pic_init_irqs (void);
-#endif /* __ASSEMBLY__ */
-
-
-/* TL16C550C on board UART see also asm/serial.h */
-#define CB_UART_BASE           0x0FE08000
-#define CB_UART_REG_GAP        0x10
-#define CB_UART_CLOCK          0x16000000
-
-/* CompactFlash setting */
-#define CB_CF_BASE                     0x0FE0C000
-#define CB_CF_CCR_ADDR                 (CB_CF_BASE+0x200)
-#define CB_CF_CCR                      (*(volatile u8 *)CB_CF_CCR_ADDR)
-#define CB_CF_REG0_ADDR                (CB_CF_BASE+0x1000)
-#define CB_CF_REG0                     (*(volatile u16 *)CB_CF_REG0_ADDR)
-#define CB_CF_STS0_ADDR                (CB_CF_BASE+0x1004)
-#define CB_CF_STS0                     (*(volatile u16 *)CB_CF_STS0_ADDR)
-#define CB_PCATA_BASE                  (CB_CF_BASE+0x800)
-#define CB_IDE_BASE                    (CB_CF_BASE+0x9F0)
-#define CB_IDE_CTRL                    (CB_CF_BASE+0xBF6)
-#define CB_IDE_REG_OFFS                0x1
-
-
-/* SMSC LAN91C111 setting */
-#if defined(CONFIG_SMC91111)
-#define CB_LANC_BASE           0x0FE10300
-#define CONFIG_SMC16BITONLY
-#define ETH0_ADDR              CB_LANC_BASE
-#define ETH0_IRQ               IRQ_CB_LANC
-#endif /* CONFIG_SMC16BITONLY */
-
-
-#undef V850E_UART_PRE_CONFIGURE
-#define V850E_UART_PRE_CONFIGURE       rte_me2_cb_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void rte_me2_cb_uart_pre_configure (unsigned chan,
-                                          unsigned cflags, unsigned baud);
-#endif /* __ASSEMBLY__ */
-
-/* This board supports RTS/CTS for the on-chip UART, but only for channel 0. */
-
-/* CTS for UART channel 0 is pin P22 (bit 2 of port 2).  */
-#define V850E_UART_CTS(chan)   ((chan) == 0 ? !(ME2_PORT2_IO & 0x4) : 1)
-/* RTS for UART channel 0 is pin P21 (bit 1 of port 2).  */
-#define V850E_UART_SET_RTS(chan, val)                                        \
-   do {                                                                              \
-          if (chan == 0) {                                                   \
-                  unsigned old = ME2_PORT2_IO;                               \
-                  if (val)                                                   \
-                          ME2_PORT2_IO = old & ~0x2;                         \
-                  else                                                       \
-                          ME2_PORT2_IO = old | 0x2;                          \
-          }                                                                  \
-   } while (0)
-
-
-#ifndef __ASSEMBLY__
-extern void rte_me2_cb_init_irqs (void);
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_RTE_ME2_CB_H__ */
diff --git a/include/asm-v850/rte_nb85e_cb.h b/include/asm-v850/rte_nb85e_cb.h
deleted file mode 100644 (file)
index f56591c..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * include/asm-v850/rte_nb85e_cb.h -- Midas labs RTE-V850/NB85E-CB board
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_RTE_NB85E_CB_H__
-#define __V850_RTE_NB85E_CB_H__
-
-#include <asm/rte_cb.h>                /* Common defs for Midas RTE-CB boards.  */
-
-
-#define PLATFORM               "rte-v850e/nb85e-cb"
-#define PLATFORM_LONG          "Midas lab RTE-V850E/NB85E-CB"
-
-#define CPU_CLOCK_FREQ         50000000 /* 50MHz */
-
-/* 1MB of onboard SRAM.  Note that the monitor ROM uses parts of this
-   for its own purposes, so care must be taken.  */
-#define SRAM_ADDR              0x03C00000
-#define SRAM_SIZE              0x00100000 /* 1MB */
-
-/* 16MB of onbard SDRAM.  */
-#define SDRAM_ADDR             0x01000000
-#define SDRAM_SIZE             0x01000000 /* 16MB */
-
-
-/* CPU addresses of GBUS memory spaces.  */
-#define GCS0_ADDR              0x00400000 /* GCS0 - Common SRAM (2MB) */
-#define GCS0_SIZE              0x00400000 /*   4MB */
-#define GCS1_ADDR              0x02000000 /* GCS1 - Flash ROM (8MB) */
-#define GCS1_SIZE              0x00800000 /*   8MB */
-#define GCS2_ADDR              0x03900000 /* GCS2 - I/O registers */
-#define GCS2_SIZE              0x00080000 /*   512KB */
-#define GCS3_ADDR              0x02800000 /* GCS3 - EXT-bus: memory space */
-#define GCS3_SIZE              0x00800000 /*   8MB */
-#define GCS4_ADDR              0x03A00000 /* GCS4 - EXT-bus: I/O space */
-#define GCS4_SIZE              0x00200000 /*   2MB */
-#define GCS5_ADDR              0x00800000 /* GCS5 - PCI bus space */
-#define GCS5_SIZE              0x00800000 /*   8MB */
-#define GCS6_ADDR              0x03980000 /* GCS6 - PCI control registers */
-#define GCS6_SIZE              0x00010000 /*   64KB */
-
-
-/* The GBUS GINT0 - GINT3 interrupts are connected to CPU interrupts 10-12.
-   These are shared among the GBUS interrupts.  */
-#define IRQ_GINT(n)            (10 + (n))
-#define IRQ_GINT_NUM           3
-
-/* Used by <asm/rte_cb.h> to derive NUM_MACH_IRQS.  */
-#define NUM_RTE_CB_IRQS                NUM_CPU_IRQS
-
-
-#ifdef CONFIG_ROM_KERNEL
-/* Kernel is in ROM, starting at address 0.  */
-
-#define INTV_BASE      0
-
-#else /* !CONFIG_ROM_KERNEL */
-/* We're using the ROM monitor.  */
-
-/* The chip's real interrupt vectors are in ROM, but they jump to a
-   secondary interrupt vector table in RAM.  */
-#define INTV_BASE              0x03CF8000
-
-/* Scratch memory used by the ROM monitor, which shouldn't be used by
-   linux (except for the alternate interrupt vector area, defined
-   above).  */
-#define MON_SCRATCH_ADDR       0x03CE8000
-#define MON_SCRATCH_SIZE       0x00018000 /* 96KB */
-
-#endif /* CONFIG_ROM_KERNEL */
-
-
-/* Some misc. on-board devices.  */
-
-/* Seven-segment LED display (two digits).  Write-only.  */
-#define LED_ADDR(n)    (0x03802000 + (n))
-#define LED(n)         (*(volatile unsigned char *)LED_ADDR(n))
-#define LED_NUM_DIGITS 4
-
-
-/* Override the basic TEG UART pre-initialization so that we can
-   initialize extra stuff.  */
-#undef V850E_UART_PRE_CONFIGURE        /* should be defined by <asm/teg.h> */
-#define V850E_UART_PRE_CONFIGURE       rte_nb85e_cb_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void rte_nb85e_cb_uart_pre_configure (unsigned chan,
-                                            unsigned cflags, unsigned baud);
-#endif
-
-/* This board supports RTS/CTS for the on-chip UART. */
-
-/* CTS is pin P00.  */
-#define V850E_UART_CTS(chan)   (! (TEG_PORT0_IO & 0x1))
-/* RTS is pin P02.  */
-#define V850E_UART_SET_RTS(chan, val)                                        \
-   do {                                                                              \
-          unsigned old = TEG_PORT0_IO;                                       \
-          TEG_PORT0_IO = val ? (old & ~0x4) : (old | 0x4);                   \
-   } while (0)
-
-
-#endif /* __V850_RTE_NB85E_CB_H__ */
diff --git a/include/asm-v850/scatterlist.h b/include/asm-v850/scatterlist.h
deleted file mode 100644 (file)
index 02d27b3..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * include/asm-v850/scatterlist.h
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SCATTERLIST_H__
-#define __V850_SCATTERLIST_H__
-
-#include <asm/types.h>
-
-struct scatterlist {
-#ifdef CONFIG_DEBUG_SG
-       unsigned long   sg_magic;
-#endif
-       unsigned long   page_link;
-       unsigned        offset;
-       dma_addr_t      dma_address;
-       unsigned        length;
-};
-
-#define ISA_DMA_THRESHOLD      (~0UL)
-
-#endif /* __V850_SCATTERLIST_H__ */
diff --git a/include/asm-v850/sections.h b/include/asm-v850/sections.h
deleted file mode 100644 (file)
index e023825..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_SECTIONS_H__
-#define __V850_SECTIONS_H__
-
-#include <asm-generic/sections.h>
-
-#endif /* __V850_SECTIONS_H__ */
diff --git a/include/asm-v850/segment.h b/include/asm-v850/segment.h
deleted file mode 100644 (file)
index 5e2b15d..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef __V850_SEGMENT_H__
-#define __V850_SEGMENT_H__
-
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long mm_segment_t;    /* domain register */
-
-#endif /* !__ASSEMBLY__ */
-
-
-#define __KERNEL_CS    0x0
-#define __KERNEL_DS    0x0
-
-#define __USER_CS      0x1
-#define __USER_DS      0x1
-
-#define KERNEL_DS      __KERNEL_DS
-#define KERNEL_CS      __KERNEL_CS
-#define USER_DS                __USER_DS
-#define USER_CS                __USER_CS
-
-#define segment_eq(a,b)        ((a) == (b))
-
-#define get_ds()       (KERNEL_DS)
-#define get_fs()       (USER_DS)
-
-#define set_fs(seg)    ((void)(seg))
-
-
-#define copy_segments(task, mm)        ((void)((void)(task), (mm)))
-#define release_segments(mm)   ((void)(mm))
-#define forget_segments()      ((void)0)
-
-
-#endif /* __V850_SEGMENT_H__ */
diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-v850/sembuf.h b/include/asm-v850/sembuf.h
deleted file mode 100644 (file)
index 1622231..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __V850_SEMBUF_H__
-#define __V850_SEMBUF_H__
-
-/* 
- * The semid64_ds structure for v850 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-       __kernel_time_t sem_otime;              /* last semop time */
-       unsigned long   __unused1;
-       __kernel_time_t sem_ctime;              /* last change time */
-       unsigned long   __unused2;
-       unsigned long   sem_nsems;              /* no. of semaphores in array */
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* __V850_SEMBUF_H__ */
diff --git a/include/asm-v850/serial.h b/include/asm-v850/serial.h
deleted file mode 100644 (file)
index 36d8f4c..0000000
+++ /dev/null
@@ -1,56 +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) 1999 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- */ 
-
-#ifdef CONFIG_RTE_CB_ME2
-
-#include <asm/rte_me2_cb.h>
-
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
-#define irq_cannonicalize(x) (x)
-#define BASE_BAUD      250000  /* (16MHz / (16 * 38400)) * 9600 */
-#define SERIAL_PORT_DFNS \
-   { 0, BASE_BAUD, CB_UART_BASE, IRQ_CB_EXTSIO, STD_COM_FLAGS },
-
-/* Redefine UART register offsets.  */
-#undef UART_RX
-#undef UART_TX
-#undef UART_DLL
-#undef UART_TRG
-#undef UART_DLM
-#undef UART_IER
-#undef UART_FCTR
-#undef UART_IIR
-#undef UART_FCR
-#undef UART_EFR
-#undef UART_LCR
-#undef UART_MCR
-#undef UART_LSR
-#undef UART_MSR
-#undef UART_SCR
-#undef UART_EMSR
-
-#define UART_RX                (0 * CB_UART_REG_GAP)
-#define UART_TX                (0 * CB_UART_REG_GAP)
-#define UART_DLL       (0 * CB_UART_REG_GAP)
-#define UART_TRG       (0 * CB_UART_REG_GAP)
-#define UART_DLM       (1 * CB_UART_REG_GAP)
-#define UART_IER       (1 * CB_UART_REG_GAP)
-#define UART_FCTR      (1 * CB_UART_REG_GAP)
-#define UART_IIR       (2 * CB_UART_REG_GAP)
-#define UART_FCR       (2 * CB_UART_REG_GAP)
-#define UART_EFR       (2 * CB_UART_REG_GAP)
-#define UART_LCR       (3 * CB_UART_REG_GAP)
-#define UART_MCR       (4 * CB_UART_REG_GAP)
-#define UART_LSR       (5 * CB_UART_REG_GAP)
-#define UART_MSR       (6 * CB_UART_REG_GAP)
-#define UART_SCR       (7 * CB_UART_REG_GAP)
-#define UART_EMSR      (7 * CB_UART_REG_GAP)
-
-#endif /* CONFIG_RTE_CB_ME2 */
diff --git a/include/asm-v850/setup.h b/include/asm-v850/setup.h
deleted file mode 100644 (file)
index c48a9b9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _V850_SETUP_H
-#define _V850_SETUP_H
-
-#define COMMAND_LINE_SIZE      512
-
-#endif /* __SETUP_H */
diff --git a/include/asm-v850/shmbuf.h b/include/asm-v850/shmbuf.h
deleted file mode 100644 (file)
index 3d085c9..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __V850_SHMBUF_H__
-#define __V850_SHMBUF_H__
-
-/* 
- * The shmid64_ds structure for v850 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-       struct ipc64_perm       shm_perm;       /* operation perms */
-       size_t                  shm_segsz;      /* size of segment (bytes) */
-       __kernel_time_t         shm_atime;      /* last attach time */
-       unsigned long           __unused1;
-       __kernel_time_t         shm_dtime;      /* last detach time */
-       unsigned long           __unused2;
-       __kernel_time_t         shm_ctime;      /* last change time */
-       unsigned long           __unused3;
-       __kernel_pid_t          shm_cpid;       /* pid of creator */
-       __kernel_pid_t          shm_lpid;       /* pid of last operator */
-       unsigned long           shm_nattch;     /* no. of current attaches */
-       unsigned long           __unused4;
-       unsigned long           __unused5;
-};
-
-struct shminfo64 {
-       unsigned long   shmmax;
-       unsigned long   shmmin;
-       unsigned long   shmmni;
-       unsigned long   shmseg;
-       unsigned long   shmall;
-       unsigned long   __unused1;
-       unsigned long   __unused2;
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* __V850_SHMBUF_H__ */
diff --git a/include/asm-v850/shmparam.h b/include/asm-v850/shmparam.h
deleted file mode 100644 (file)
index 7dcb673..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_SHMPARAM_H__
-#define __V850_SHMPARAM_H__
-
-#define        SHMLBA          PAGE_SIZE       /* attach addr a multiple of this */
-
-#endif /* __V850_SHMPARAM_H__ */
diff --git a/include/asm-v850/sigcontext.h b/include/asm-v850/sigcontext.h
deleted file mode 100644 (file)
index e0890f6..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * include/asm-v850/sigcontext.h -- Signal contexts
- *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIGCONTEXT_H__
-#define __V850_SIGCONTEXT_H__
-
-#include <asm/ptrace.h>
-
-struct sigcontext
-{
-       struct pt_regs  regs;
-       unsigned long   oldmask;
-};
-
-#endif /* __V850_SIGCONTEXT_H__ */
diff --git a/include/asm-v850/siginfo.h b/include/asm-v850/siginfo.h
deleted file mode 100644 (file)
index 7eb9470..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_SIGINFO_H__
-#define __V850_SIGINFO_H__
-
-#include <asm-generic/siginfo.h>
-
-#endif /* __V850_SIGINFO_H__ */
diff --git a/include/asm-v850/signal.h b/include/asm-v850/signal.h
deleted file mode 100644 (file)
index a38df08..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-#ifndef __V850_SIGNAL_H__
-#define __V850_SIGNAL_H__
-
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-
-#ifdef __KERNEL__
-
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-#define _NSIG          64
-#define _NSIG_BPW      32
-#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t;            /* at least 32 bits */
-
-typedef struct {
-       unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#else /* !__KERNEL__ */
-
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG           32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGBUS          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/*
-#define SIGLOST                29
-*/
-#define SIGPWR         30
-#define SIGSYS         31
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       32
-#define SIGRTMAX       _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP   0x00000001
-#define SA_NOCLDWAIT   0x00000002
-#define SA_SIGINFO     0x00000004
-#define SA_ONSTACK     0x08000000
-#define SA_RESTART     0x10000000
-#define SA_NODEFER     0x40000000
-#define SA_RESETHAND   0x80000000
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-#define SA_RESTORER    0x04000000
-
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
-
-#include <asm-generic/signal.h>
-
-#ifdef __KERNEL__
-
-struct old_sigaction {
-       __sighandler_t sa_handler;
-       old_sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-struct sigaction {
-       __sighandler_t sa_handler;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-       sigset_t sa_mask;               /* mask last for extensibility */
-};
-
-struct k_sigaction {
-       struct sigaction sa;
-};
-
-#else /* !__KERNEL__ */
-
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-       union {
-         __sighandler_t _sa_handler;
-         void (*_sa_sigaction)(int, struct siginfo *, void *);
-       } _u;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-
-typedef struct sigaltstack {
-       void *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
-#include <asm/sigcontext.h>
-#undef __HAVE_ARCH_SIG_BITOPS
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_SIGNAL_H__ */
diff --git a/include/asm-v850/sim.h b/include/asm-v850/sim.h
deleted file mode 100644 (file)
index 026932d..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * include/asm-v850/sim.h -- Machine-dependent defs for GDB v850e simulator
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIM_H__
-#define __V850_SIM_H__
-
-
-#define CPU_ARCH               "v850e"
-#define CPU_MODEL              "v850e"
-#define CPU_MODEL_LONG         "NEC V850E"
-#define PLATFORM               "gdb/v850e"
-#define PLATFORM_LONG          "GDB V850E simulator"
-
-
-/* We use a weird value for RAM, not just 0, for testing purposes.
-   These must match the values used in the linker script.  */
-#define RAM_ADDR               0x8F000000
-#define RAM_SIZE               0x03000000
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET            RAM_ADDR
-
-
-/* For <asm/entry.h> */
-/* `R0 RAM', used for a few miscellaneous variables that must be
-   accessible using a load instruction relative to R0.  On real
-   processors, this usually is on-chip RAM, but here we just
-   choose an arbitrary address that meets the above constraint.  */
-#define R0_RAM_ADDR            0xFFFFF000
-
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS           6
-
-
-#endif /* __V850_SIM_H__ */
diff --git a/include/asm-v850/sim85e2.h b/include/asm-v850/sim85e2.h
deleted file mode 100644 (file)
index 8b4d697..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * include/asm-v850/sim85e2.h -- Machine-dependent defs for
- *     V850E2 RTL simulator
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIM85E2_H__
-#define __V850_SIM85E2_H__
-
-
-#include <asm/v850e2.h>                /* Based on V850E2 core.  */
-
-
-/* Various memory areas supported by the simulator.
-   These should match the corresponding definitions in the linker script.  */
-
-/* `instruction RAM'; instruction fetches are much faster from IRAM than
-   from DRAM.  */
-#define IRAM_ADDR              0
-#define IRAM_SIZE              0x00100000 /* 1MB */
-/* `data RAM', below and contiguous with the I/O space.
-   Data fetches are much faster from DRAM than from IRAM.  */
-#define DRAM_ADDR              0xfff00000
-#define DRAM_SIZE              0x000ff000 /* 1020KB */
-/* `external ram'.  Unlike the above RAM areas, this memory is cached,
-   so both instruction and data fetches should be (mostly) fast --
-   however, currently only write-through caching is supported, so writes
-   to ERAM will be slow.  */
-#define ERAM_ADDR              0x00100000
-#define ERAM_SIZE              0x07f00000 /* 127MB (max) */
-/* Dynamic RAM; uses memory controller.  */
-#define SDRAM_ADDR             0x10000000
-#define SDRAM_SIZE             0x01000000 /* 16MB */
-
-
-/* Simulator specific control registers.  */
-/* NOTHAL controls whether the simulator will stop at a `halt' insn.  */
-#define SIM85E2_NOTHAL_ADDR    0xffffff22
-#define SIM85E2_NOTHAL         (*(volatile u8 *)SIM85E2_NOTHAL_ADDR)
-/* The simulator will stop N cycles after N is written to SIMFIN.  */
-#define SIM85E2_SIMFIN_ADDR    0xffffff24
-#define SIM85E2_SIMFIN         (*(volatile u16 *)SIM85E2_SIMFIN_ADDR)
-
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS           64
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET            SDRAM_ADDR
-
-
-/* For <asm/entry.h> */
-/* `R0 RAM', used for a few miscellaneous variables that must be accessible
-   using a load instruction relative to R0.  The sim85e2 simulator
-   actually puts 1020K of RAM from FFF00000 to FFFFF000, so we arbitarily
-   choose a small portion at the end of that.  */
-#define R0_RAM_ADDR            0xFFFFE000
-
-
-#endif /* __V850_SIM85E2_H__ */
diff --git a/include/asm-v850/sim85e2c.h b/include/asm-v850/sim85e2c.h
deleted file mode 100644 (file)
index eee543f..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-v850/sim85e2c.h -- Machine-dependent defs for
- *     V850E2 RTL simulator
- *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIM85E2C_H__
-#define __V850_SIM85E2C_H__
-
-/* Use generic sim85e2 settings, other than the various names.  */
-#include <asm/sim85e2.h>
-
-#define CPU_MODEL      "v850e2"
-#define CPU_MODEL_LONG "NEC V850E2"
-#define PLATFORM       "sim85e2c"
-#define PLATFORM_LONG  "SIM85E2C V850E2 simulator"
-
-#endif /* __V850_SIM85E2C_H__ */
diff --git a/include/asm-v850/sim85e2s.h b/include/asm-v850/sim85e2s.h
deleted file mode 100644 (file)
index ee066d5..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * include/asm-v850/sim85e2s.h -- Machine-dependent defs for
- *     V850E2 RTL simulator
- *
- *  Copyright (C) 2003  NEC Electronics Corporation
- *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIM85E2S_H__
-#define __V850_SIM85E2S_H__
-
-#include <asm/sim85e2.h>       /* Use generic sim85e2 settings.  */
-#if 0
-#include <asm/v850e2_cache.h>  /* + cache */
-#endif
-
-#define CPU_MODEL      "v850e2"
-#define CPU_MODEL_LONG "NEC V850E2"
-#define PLATFORM       "sim85e2s"
-#define PLATFORM_LONG  "SIM85E2S V850E2 simulator"
-
-#endif /* __V850_SIM85E2S_H__ */
diff --git a/include/asm-v850/simsyscall.h b/include/asm-v850/simsyscall.h
deleted file mode 100644 (file)
index 4a19d5a..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * include/asm-v850/simsyscall.h -- `System calls' under the v850e emulator
- *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIMSYSCALL_H__
-#define __V850_SIMSYSCALL_H__
-
-#define V850_SIM_SYS_exit(a...)                V850_SIM_SYSCALL_1 (1   , ##a)
-#define V850_SIM_SYS_fork(a...)                V850_SIM_SYSCALL_0 (2   , ##a)
-#define V850_SIM_SYS_read(a...)                V850_SIM_SYSCALL_3 (3   , ##a)
-#define V850_SIM_SYS_write(a...)       V850_SIM_SYSCALL_3 (4   , ##a)
-#define V850_SIM_SYS_open(a...)                V850_SIM_SYSCALL_2 (5   , ##a)
-#define V850_SIM_SYS_close(a...)       V850_SIM_SYSCALL_1 (6   , ##a)
-#define V850_SIM_SYS_wait4(a...)       V850_SIM_SYSCALL_4 (7   , ##a)
-/* #define V850_SIM_SYS_creat(a...)    V850_SIM_SYSCALL_1 (8   , ##a) */
-/* #define V850_SIM_SYS_link(a...)     V850_SIM_SYSCALL_1 (9   , ##a) */
-/* #define V850_SIM_SYS_unlink(a...)   V850_SIM_SYSCALL_1 (10  , ##a) */
-#define V850_SIM_SYS_execv(a...)       V850_SIM_SYSCALL_2 (11  , ##a)
-/* #define V850_SIM_SYS_chdir(a...)    V850_SIM_SYSCALL_1 (12  , ##a) */
-/* #define V850_SIM_SYS_mknod(a...)    V850_SIM_SYSCALL_1 (14  , ##a) */
-#define V850_SIM_SYS_chmod(a...)       V850_SIM_SYSCALL_2 (15  , ##a)
-#define V850_SIM_SYS_chown(a...)       V850_SIM_SYSCALL_2 (16  , ##a)
-#define V850_SIM_SYS_lseek(a...)       V850_SIM_SYSCALL_3 (19  , ##a)
-/* #define V850_SIM_SYS_getpid(a...)   V850_SIM_SYSCALL_1 (20  , ##a) */
-/* #define V850_SIM_SYS_isatty(a...)   V850_SIM_SYSCALL_1 (21  , ##a) */
-/* #define V850_SIM_SYS_fstat(a...)    V850_SIM_SYSCALL_1 (22  , ##a) */
-#define V850_SIM_SYS_time(a...)                V850_SIM_SYSCALL_1 (23  , ##a)
-#define V850_SIM_SYS_poll(a...)                V850_SIM_SYSCALL_3 (24  , ##a)
-#define V850_SIM_SYS_stat(a...)                V850_SIM_SYSCALL_2 (38  , ##a)
-#define V850_SIM_SYS_pipe(a...)                V850_SIM_SYSCALL_1 (42  , ##a)
-#define V850_SIM_SYS_times(a...)       V850_SIM_SYSCALL_1 (43  , ##a)
-#define V850_SIM_SYS_execve(a...)      V850_SIM_SYSCALL_3 (59  , ##a)
-#define V850_SIM_SYS_gettimeofday(a...)        V850_SIM_SYSCALL_2 (116 , ##a)
-/* #define V850_SIM_SYS_utime(a...)    V850_SIM_SYSCALL_2 (201 , ##a) */
-/* #define V850_SIM_SYS_wait(a...)     V850_SIM_SYSCALL_1 (202 , ##a) */
-
-#define V850_SIM_SYS_make_raw(a...)    V850_SIM_SYSCALL_1 (1024 , ##a)
-
-
-#define V850_SIM_SYSCALL_0(_call)                                            \
-({                                                                           \
-       register int call __asm__ ("r6") = _call;                             \
-       register int rval __asm__ ("r10");                                    \
-       __asm__ __volatile__ ("trap 31"                                       \
-                             : "=r" (rval)                                   \
-                             : "r" (call)                                    \
-                             : "r11", "memory");                             \
-       rval;                                                                 \
-})
-#define V850_SIM_SYSCALL_1(_call, _arg0)                                     \
-({                                                                           \
-       register int call __asm__ ("r6") = _call;                             \
-       register long arg0 __asm__ ("r7") = (long)_arg0;                      \
-       register int rval __asm__ ("r10");                                    \
-       __asm__ __volatile__ ("trap 31"                                       \
-                             : "=r" (rval)                                   \
-                             : "r" (call), "r" (arg0)                        \
-                             : "r11", "memory");                             \
-       rval;                                                                 \
-})
-#define V850_SIM_SYSCALL_2(_call, _arg0, _arg1)                                      \
-({                                                                           \
-       register int call __asm__ ("r6") = _call;                             \
-       register long arg0 __asm__ ("r7") = (long)_arg0;                      \
-       register long arg1 __asm__ ("r8") = (long)_arg1;                      \
-       register int rval __asm__ ("r10");                                    \
-       __asm__ __volatile__ ("trap 31"                                       \
-                             : "=r" (rval)                                   \
-                             : "r" (call), "r" (arg0), "r" (arg1)            \
-                             : "r11", "memory");                             \
-       rval;                                                                 \
-})
-#define V850_SIM_SYSCALL_3(_call, _arg0, _arg1, _arg2)                       \
-({                                                                           \
-       register int call __asm__ ("r6") = _call;                             \
-       register long arg0 __asm__ ("r7") = (long)_arg0;                      \
-       register long arg1 __asm__ ("r8") = (long)_arg1;                      \
-       register long arg2 __asm__ ("r9") = (long)_arg2;                      \
-       register int rval __asm__ ("r10");                                    \
-       __asm__ __volatile__ ("trap 31"                                       \
-                             : "=r" (rval)                                   \
-                             : "r" (call), "r" (arg0), "r" (arg1), "r" (arg2)\
-                             : "r11", "memory");                             \
-       rval;                                                                 \
-})
-
-#define V850_SIM_SYSCALL(call, args...) \
-   V850_SIM_SYS_##call (args)
-
-#endif /* __V850_SIMSYSCALL_H__ */
diff --git a/include/asm-v850/socket.h b/include/asm-v850/socket.h
deleted file mode 100644 (file)
index e199a2b..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef __V850_SOCKET_H__
-#define __V850_SOCKET_H__
-
-#include <asm/sockios.h>
-
-/* For setsockoptions(2) */
-#define SOL_SOCKET     1
-
-#define SO_DEBUG       1
-#define SO_REUSEADDR   2
-#define SO_TYPE                3
-#define SO_ERROR       4
-#define SO_DONTROUTE   5
-#define SO_BROADCAST   6
-#define SO_SNDBUF      7
-#define SO_RCVBUF      8
-#define SO_SNDBUFFORCE 32
-#define SO_RCVBUFFORCE 33
-#define SO_KEEPALIVE   9
-#define SO_OOBINLINE   10
-#define SO_NO_CHECK    11
-#define SO_PRIORITY    12
-#define SO_LINGER      13
-#define SO_BSDCOMPAT   14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED    16
-#define SO_PEERCRED    17
-#define SO_RCVLOWAT    18
-#define SO_SNDLOWAT    19
-#define SO_RCVTIMEO    20
-#define SO_SNDTIMEO    21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION             22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
-#define SO_SECURITY_ENCRYPTION_NETWORK         24
-
-#define SO_BINDTODEVICE        25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
-
-#define SO_PEERNAME             28
-#define SO_TIMESTAMP           29
-#define SCM_TIMESTAMP          SO_TIMESTAMP
-
-#define SO_ACCEPTCONN          30
-
-#define SO_PEERSEC             31
-#define SO_PASSSEC             34
-#define SO_TIMESTAMPNS         35
-#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
-
-#define SO_MARK                        36
-
-#endif /* __V850_SOCKET_H__ */
diff --git a/include/asm-v850/sockios.h b/include/asm-v850/sockios.h
deleted file mode 100644 (file)
index 823e106..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __V850_SOCKIOS_H__
-#define __V850_SOCKIOS_H__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN      0x8901
-#define SIOCSPGRP      0x8902
-#define FIOGETOWN      0x8903
-#define SIOCGPGRP      0x8904
-#define SIOCATMARK     0x8905
-#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
-#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
-
-#endif /* __V850_SOCKIOS_H__ */
diff --git a/include/asm-v850/stat.h b/include/asm-v850/stat.h
deleted file mode 100644 (file)
index c68c60d..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * include/asm-v850/stat.h -- v850 stat structure
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_STAT_H__
-#define __V850_STAT_H__
-
-#include <asm/posix_types.h>
-
-struct stat {
-       unsigned int    st_dev;
-       unsigned long   st_ino;
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-       unsigned int    st_uid;
-       unsigned int    st_gid;
-       unsigned int    st_rdev;
-       long            st_size;
-       unsigned long   st_blksize;
-       unsigned long   st_blocks;
-       unsigned long   st_atime;
-       unsigned long   __unused1;
-       unsigned long   st_mtime;
-       unsigned long   __unused2;
-       unsigned long   st_ctime;
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-       unsigned long   __unused5;
-};
-
-struct stat64 {
-       unsigned long long      st_dev;
-       unsigned long   __unused1;
-
-       unsigned long long      st_ino;
-
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-
-       unsigned int    st_uid;
-       unsigned int    st_gid;
-
-       unsigned long long      st_rdev;
-       unsigned long   __unused3;
-
-       long long       st_size;
-       unsigned long   st_blksize;
-
-       unsigned long   st_blocks; /* No. of 512-byte blocks allocated */
-       unsigned long   __unused4; /* future possible st_blocks high bits */
-
-       unsigned long   st_atime;
-       unsigned long   st_atime_nsec;
-
-       unsigned long   st_mtime;
-       unsigned long   st_mtime_nsec;
-
-       unsigned long   st_ctime;
-       unsigned long   st_ctime_nsec;
-
-       unsigned long   __unused8;
-};
-
-#endif /* __V850_STAT_H__ */
diff --git a/include/asm-v850/statfs.h b/include/asm-v850/statfs.h
deleted file mode 100644 (file)
index ea15966..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_STATFS_H__
-#define __V850_STATFS_H__
-
-#include <asm-generic/statfs.h>
-
-#endif /* __V850_STATFS_H__ */
diff --git a/include/asm-v850/string.h b/include/asm-v850/string.h
deleted file mode 100644 (file)
index 478e234..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * include/asm-v850/string.h -- Architecture specific string routines
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_STRING_H__
-#define __V850_STRING_H__
-
-#define __HAVE_ARCH_MEMCPY
-#define __HAVE_ARCH_MEMSET
-#define __HAVE_ARCH_MEMMOVE
-
-extern void *memcpy (void *, const void *, __kernel_size_t);
-extern void *memset (void *, int, __kernel_size_t);
-extern void *memmove (void *, const void *, __kernel_size_t);
-
-#endif /* __V850_STRING_H__ */
diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h
deleted file mode 100644 (file)
index 7daf1fd..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * include/asm-v850/system.h -- Low-level interrupt/thread ops
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SYSTEM_H__
-#define __V850_SYSTEM_H__
-
-#include <linux/linkage.h>
-#include <asm/ptrace.h>
-
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing.
- */
-struct thread_struct;
-extern void *switch_thread (struct thread_struct *last,
-                           struct thread_struct *next);
-#define switch_to(prev,next,last)                                            \
-  do {                                                                       \
-        if (prev != next) {                                                  \
-               (last) = switch_thread (&prev->thread, &next->thread);        \
-       }                                                                     \
-  } while (0)
-
-
-/* Enable/disable interrupts.  */
-#define local_irq_enable()     __asm__ __volatile__ ("ei")
-#define local_irq_disable()    __asm__ __volatile__ ("di")
-
-#define local_save_flags(flags) \
-  __asm__ __volatile__ ("stsr %1, %0" : "=r" (flags) : "i" (SR_PSW))
-#define local_restore_flags(flags) \
-  __asm__ __volatile__ ("ldsr %0, %1" :: "r" (flags), "i" (SR_PSW))
-
-/* For spinlocks etc */
-#define        local_irq_save(flags) \
-  do { local_save_flags (flags); local_irq_disable (); } while (0) 
-#define local_irq_restore(flags) \
-  local_restore_flags (flags);
-
-
-static inline int irqs_disabled (void)
-{
-       unsigned flags;
-       local_save_flags (flags);
-       return !!(flags & 0x20);
-}
-
-
-/*
- * Force strict CPU ordering.
- * Not really required on v850...
- */
-#define nop()                  __asm__ __volatile__ ("nop")
-#define mb()                   __asm__ __volatile__ ("" ::: "memory")
-#define rmb()                  mb ()
-#define wmb()                  mb ()
-#define read_barrier_depends() ((void)0)
-#define set_mb(var, value)     do { xchg (&var, value); } while (0)
-
-#define smp_mb()       mb ()
-#define smp_rmb()      rmb ()
-#define smp_wmb()      wmb ()
-#define smp_read_barrier_depends()     read_barrier_depends()
-
-#define xchg(ptr, with) \
-  ((__typeof__ (*(ptr)))__xchg ((unsigned long)(with), (ptr), sizeof (*(ptr))))
-
-static inline unsigned long __xchg (unsigned long with,
-                                   __volatile__ void *ptr, int size)
-{
-       unsigned long tmp, flags;
-
-       local_irq_save (flags);
-
-       switch (size) {
-       case 1:
-               tmp = *(unsigned char *)ptr;
-               *(unsigned char *)ptr = with;
-               break;
-       case 2:
-               tmp = *(unsigned short *)ptr;
-               *(unsigned short *)ptr = with;
-               break;
-       case 4:
-               tmp = *(unsigned long *)ptr;
-               *(unsigned long *)ptr = with;
-               break;
-       }
-
-       local_irq_restore (flags);
-
-       return tmp;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* __V850_SYSTEM_H__ */
diff --git a/include/asm-v850/teg.h b/include/asm-v850/teg.h
deleted file mode 100644 (file)
index acc8c7d..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * include/asm-v850/teg.h -- NB85E-TEG cpu chip
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_TEG_H__
-#define __V850_TEG_H__
-
-
-/* The TEG uses the V850E cpu core.  */
-#include <asm/v850e.h>
-#include <asm/v850e_cache.h>
-
-
-#define CPU_MODEL      "v850e/nb85e-teg"
-#define CPU_MODEL_LONG "NEC V850E/NB85E TEG"
-
-
-/* For <asm/entry.h> */
-/* We use on-chip RAM, for a few miscellaneous variables that must be
-   accessible using a load instruction relative to R0.  On the NB85E/TEG,
-   There's 60KB of iRAM starting at 0xFFFF0000, however we need the base
-   address to be addressable by a 16-bit signed offset, so we only use the
-   second half of it starting from 0xFFFF8000.  */
-#define R0_RAM_ADDR                    0xFFFF8000
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace).
-   Some of these are parameterized even though there's only a single
-   interrupt, for compatibility with some generic code that works on other
-   processor models.  */
-#define IRQ_INTCMD(n)  6       /* interval timer interrupt */
-#define IRQ_INTCMD_NUM 1
-#define IRQ_INTSER(n)  16      /* UART reception error */
-#define IRQ_INTSER_NUM 1
-#define IRQ_INTSR(n)   17      /* UART reception completion */
-#define IRQ_INTSR_NUM  1
-#define IRQ_INTST(n)   18      /* UART transmission completion */
-#define IRQ_INTST_NUM  1
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS   64
-
-
-/* TEG UART details.  */
-#define V850E_UART_BASE_ADDR(n)                (0xFFFFF600 + 0x10 * (n))
-#define V850E_UART_ASIM_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x0)
-#define V850E_UART_ASIS_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x2)
-#define V850E_UART_ASIF_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x4)
-#define V850E_UART_CKSR_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x6)
-#define V850E_UART_BRGC_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x8)
-#define V850E_UART_TXB_ADDR(n)         (V850E_UART_BASE_ADDR(n) + 0xA)
-#define V850E_UART_RXB_ADDR(n)         (V850E_UART_BASE_ADDR(n) + 0xC)
-#define V850E_UART_NUM_CHANNELS                1
-#define V850E_UART_BASE_FREQ           CPU_CLOCK_FREQ
-/* This is a function that gets called before configuring the UART.  */
-#define V850E_UART_PRE_CONFIGURE       teg_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void teg_uart_pre_configure (unsigned chan,
-                                   unsigned cflags, unsigned baud);
-#endif
-
-
-/* The TEG RTPU.  */
-#define V850E_RTPU_BASE_ADDR           0xFFFFF210
-
-
-/* TEG series timer D details.  */
-#define V850E_TIMER_D_BASE_ADDR                0xFFFFF210
-#define V850E_TIMER_D_TMCD_BASE_ADDR   (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_TMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x4)
-#define V850E_TIMER_D_CMD_BASE_ADDR    (V850E_TIMER_D_BASE_ADDR + 0x8)
-#define V850E_TIMER_D_BASE_FREQ                CPU_CLOCK_FREQ
-
-
-/* `Interrupt Source Select' control register.  */
-#define TEG_ISS_ADDR                   0xFFFFF7FA
-#define TEG_ISS                                (*(volatile u8 *)TEG_ISS_ADDR)
-
-/* Port 0 I/O register (bits 0-3 used).  */
-#define TEG_PORT0_IO_ADDR              0xFFFFF7F2
-#define TEG_PORT0_IO                   (*(volatile u8 *)TEG_PORT0_IO_ADDR)
-/* Port 0 control register (bits 0-3 control mode, 0 = output, 1 = input).  */
-#define TEG_PORT0_PM_ADDR              0xFFFFF7F4
-#define TEG_PORT0_PM                   (*(volatile u8 *)TEG_PORT0_PM_ADDR)
-
-
-#ifndef __ASSEMBLY__
-extern void teg_init_irqs (void);
-#endif
-
-
-#endif /* __V850_TEG_H__ */
diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h
deleted file mode 100644 (file)
index 295d7bf..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-#ifndef __V850_TERMBITS_H__
-#define __V850_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char  cc_t;
-typedef unsigned int   speed_t;
-typedef unsigned int   tcflag_t;
-
-#define NCCS 19
-struct termios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-};
-
-struct termios2 {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-struct ktermios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK  0000020
-#define ISTRIP 0000040
-#define INLCR  0000100
-#define IGNCR  0000200
-#define ICRNL  0000400
-#define IUCLC  0001000
-#define IXON   0002000
-#define IXANY  0004000
-#define IXOFF  0010000
-#define IMAXBEL        0020000
-#define IUTF8  0040000
-
-/* c_oflag bits */
-#define OPOST  0000001
-#define OLCUC  0000002
-#define ONLCR  0000004
-#define OCRNL  0000010
-#define ONOCR  0000020
-#define ONLRET 0000040
-#define OFILL  0000100
-#define OFDEL  0000200
-#define NLDLY  0000400
-#define   NL0  0000000
-#define   NL1  0000400
-#define CRDLY  0003000
-#define   CR0  0000000
-#define   CR1  0001000
-#define   CR2  0002000
-#define   CR3  0003000
-#define TABDLY 0014000
-#define   TAB0 0000000
-#define   TAB1 0004000
-#define   TAB2 0010000
-#define   TAB3 0014000
-#define   XTABS        0014000
-#define BSDLY  0020000
-#define   BS0  0000000
-#define   BS1  0020000
-#define VTDLY  0040000
-#define   VT0  0000000
-#define   VT1  0040000
-#define FFDLY  0100000
-#define   FF0  0000000
-#define   FF1  0100000
-
-/* c_cflag bit meaning */
-#define CBAUD  0010017
-#define  B0    0000000         /* hang up */
-#define  B50   0000001
-#define  B75   0000002
-#define  B110  0000003
-#define  B134  0000004
-#define  B150  0000005
-#define  B200  0000006
-#define  B300  0000007
-#define  B600  0000010
-#define  B1200 0000011
-#define  B1800 0000012
-#define  B2400 0000013
-#define  B4800 0000014
-#define  B9600 0000015
-#define  B19200        0000016
-#define  B38400        0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE  0000060
-#define   CS5  0000000
-#define   CS6  0000020
-#define   CS7  0000040
-#define   CS8  0000060
-#define CSTOPB 0000100
-#define CREAD  0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL  0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define    BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD   002003600000          /* input baud rate */
-#define CMSPAR   010000000000          /* mark or space (stick) parity */
-#define CRTSCTS          020000000000          /* flow control */
-
-#define        IBSHIFT 16              /* Shifr from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG   0000001
-#define ICANON 0000002
-#define XCASE  0000004
-#define ECHO   0000010
-#define ECHOE  0000020
-#define ECHOK  0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL        0001000
-#define ECHOPRT        0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-
-
-/* tcflow() and TCXONC use these */
-#define        TCOOFF          0
-#define        TCOON           1
-#define        TCIOFF          2
-#define        TCION           3
-
-/* tcflush() and TCFLSH use these */
-#define        TCIFLUSH        0
-#define        TCOFLUSH        1
-#define        TCIOFLUSH       2
-
-/* tcsetattr uses these */
-#define        TCSANOW         0
-#define        TCSADRAIN       1
-#define        TCSAFLUSH       2
-
-#endif /* __V850_TERMBITS_H__ */
diff --git a/include/asm-v850/termios.h b/include/asm-v850/termios.h
deleted file mode 100644 (file)
index fcd1718..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef __V850_TERMIOS_H__
-#define __V850_TERMIOS_H__
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/*     intr=^C         quit=^\         erase=del       kill=^U
-       eof=^D          vtime=\0        vmin=\1         sxtc=\0
-       start=^Q        stop=^S         susp=^Z         eol=\0
-       reprint=^R      discard=^U      werase=^W       lnext=^V
-       eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
-       unsigned short __tmp; \
-       get_user(__tmp,&(termio)->x); \
-       *(unsigned short *) &(termios)->x = __tmp; \
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
-       copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-       put_user((termios)->c_iflag, &(termio)->c_iflag); \
-       put_user((termios)->c_oflag, &(termio)->c_oflag); \
-       put_user((termios)->c_cflag, &(termio)->c_cflag); \
-       put_user((termios)->c_lflag, &(termio)->c_lflag); \
-       put_user((termios)->c_line,  &(termio)->c_line); \
-       copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_TERMIOS_H__ */
diff --git a/include/asm-v850/thread_info.h b/include/asm-v850/thread_info.h
deleted file mode 100644 (file)
index 1a9e6ae..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * include/asm-v850/thread_info.h -- v850 low-level thread information
- *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
- *  Copyright (C) 2002  David Howells (dhowells@redhat.com)
- *    - Incorporating suggestions made by Linus Torvalds and Dave Miller
- *
- * 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 was derived from the PPC version, include/asm-ppc/thread_info.h
- * which was adapted from the i386 version by Paul Mackerras
- */
-
-#ifndef __V850_THREAD_INFO_H__
-#define __V850_THREAD_INFO_H__
-
-#ifdef __KERNEL__
-
-#ifndef __ASSEMBLY__
-
-/*
- * low level task data.
- * If you change this, change the TI_* offsets below to match.
- */
-struct thread_info {
-       struct task_struct      *task;          /* main task structure */
-       struct exec_domain      *exec_domain;   /* execution domain */
-       unsigned long           flags;          /* low level flags */
-       int                     cpu;            /* cpu we're on */
-       int                     preempt_count;  /* 0 => preemptable,
-                                                  <0 => BUG */
-       struct restart_block    restart_block;
-};
-
-#define INIT_THREAD_INFO(tsk)                                                \
-{                                                                            \
-       .task =         &tsk,                                                 \
-       .exec_domain =  &default_exec_domain,                                 \
-       .flags =        0,                                                    \
-       .cpu =          0,                                                    \
-       .preempt_count = 1,                                                   \
-       .restart_block = {                                                    \
-               .fn = do_no_restart_syscall,                                  \
-       },                                                                    \
-}
-
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
-/*
- * macros/functions for gaining access to the thread information structure
- */
-
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-                               __get_free_pages(GFP_KERNEL, 1))
-#define free_thread_info(ti)   free_pages((unsigned long) (ti), 1)
-
-#endif /* __ASSEMBLY__ */
-
-
-/*
- * Offsets in thread_info structure, used in assembly code
- */
-#define TI_TASK                0
-#define TI_EXECDOMAIN  4
-#define TI_FLAGS       8
-#define TI_CPU         12
-#define TI_PREEMPT     16
-
-#define PREEMPT_ACTIVE         0x4000000
-
-/*
- * thread information flag bit numbers
- */
-#define TIF_SYSCALL_TRACE      0       /* syscall trace active */
-#define TIF_SIGPENDING         1       /* signal pending */
-#define TIF_NEED_RESCHED       2       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG     3       /* true if poll_idle() is polling
-                                          TIF_NEED_RESCHED */
-#define TIF_MEMDIE             4
-
-/* as above, but as bit values */
-#define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
-#define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
-
-
-/* Size of kernel stack for each process.  */
-#define THREAD_SIZE            0x2000
-
-/* The alignment of kernel threads, with thread_info structures at their
-   base.  Thus, a pointer for a task's task structure can be derived from
-   its kernel stack pointer.  */
-#define THREAD_ALIGNMENT       THREAD_SIZE
-#define THREAD_MASK            (-THREAD_ALIGNMENT)
-
-
-#ifdef __ASSEMBLY__
-
-/* Put a pointer to the current thread_info structure into REG.  Note that
-   this definition requires THREAD_MASK to be representable as a signed
-   16-bit value.  */
-#define GET_CURRENT_THREAD(reg)                                                \
-        /* Use `addi' and then `and' instead of just `andi', because   \
-          `addi' sign-extends the immediate value, whereas `andi'      \
-          zero-extends it.  */                                         \
-       addi    THREAD_MASK, r0, reg;                                   \
-       and     sp, reg
-
-#else
-
-/* Return a pointer to the current thread_info structure.  */
-static inline struct thread_info *current_thread_info (void)
-{
-       register unsigned long sp __asm__ ("sp");
-       return (struct thread_info *)(sp & THREAD_MASK);
-}
-
-#endif /* __ASSEMBLY__ */
-
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_THREAD_INFO_H__ */
diff --git a/include/asm-v850/timex.h b/include/asm-v850/timex.h
deleted file mode 100644 (file)
index 6279e5a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * linux/include/asm-v850/timex.h
- *
- * v850 architecture timex specifications
- */
-#ifndef __V850_TIMEX_H__
-#define __V850_TIMEX_H__
-
-#define CLOCK_TICK_RATE        1193180 /* Underlying HZ */
-
-typedef unsigned long cycles_t;
-
-static inline cycles_t get_cycles(void)
-{
-       return 0;
-}
-
-#endif /* __V850_TIMEX_H__ */
diff --git a/include/asm-v850/tlb.h b/include/asm-v850/tlb.h
deleted file mode 100644 (file)
index 73bc9ea..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * include/asm-v850/tlb.h
- *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_TLB_H__
-#define __V850_TLB_H__
-
-#define tlb_flush(tlb) ((void)0)
-
-#include <asm-generic/tlb.h>
-
-#endif /* __V850_TLB_H__ */
diff --git a/include/asm-v850/tlbflush.h b/include/asm-v850/tlbflush.h
deleted file mode 100644 (file)
index c44aa64..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * include/asm-v850/tlbflush.h
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_TLBFLUSH_H__
-#define __V850_TLBFLUSH_H__
-
-#include <asm/machdep.h>
-
-
-/*
- * flush all user-space atc entries.
- */
-static inline void __flush_tlb(void)
-{
-       BUG ();
-}
-
-static inline void __flush_tlb_one(unsigned long addr)
-{
-       BUG ();
-}
-
-#define flush_tlb() __flush_tlb()
-
-/*
- * flush all atc entries (both kernel and user-space entries).
- */
-static inline void flush_tlb_all(void)
-{
-       BUG ();
-}
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
-       BUG ();
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
-{
-       BUG ();
-}
-
-static inline void flush_tlb_range(struct vm_area_struct *vma,
-                                  unsigned long start, unsigned long end)
-{
-       BUG ();
-}
-
-static inline void flush_tlb_kernel_page(unsigned long addr)
-{
-       BUG ();
-}
-
-#endif /* __V850_TLBFLUSH_H__ */
diff --git a/include/asm-v850/topology.h b/include/asm-v850/topology.h
deleted file mode 100644 (file)
index 6040e41..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_TOPOLOGY_H__
-#define __V850_TOPOLOGY_H__
-
-#include <asm-generic/topology.h>
-
-#endif /* __V850_TOPOLOGY_H__ */
diff --git a/include/asm-v850/types.h b/include/asm-v850/types.h
deleted file mode 100644 (file)
index 89f735e..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef __V850_TYPES_H__
-#define __V850_TYPES_H__
-
-#ifndef __ASSEMBLY__
-
-/*
- * This file is never included by application software unless
- * explicitly requested (e.g., via linux/types.h) in which case the
- * application is Linux specific so (user-) name space pollution is
- * not a major issue.  However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
- */
-#include <asm-generic/int-ll64.h>
-
-typedef unsigned short umode_t;
-
-#endif /* !__ASSEMBLY__ */
-
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-
-#define BITS_PER_LONG 32
-
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_TYPES_H__ */
diff --git a/include/asm-v850/uaccess.h b/include/asm-v850/uaccess.h
deleted file mode 100644 (file)
index 64563c4..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-#ifndef __V850_UACCESS_H__
-#define __V850_UACCESS_H__
-
-/*
- * User space memory access functions
- */
-
-#include <linux/errno.h>
-#include <linux/string.h>
-
-#include <asm/segment.h>
-#include <asm/machdep.h>
-
-#define VERIFY_READ    0
-#define VERIFY_WRITE   1
-
-static inline int access_ok (int type, const void *addr, unsigned long size)
-{
-       /* XXX I guess we should check against real ram bounds at least, and
-          possibly make sure ADDR is not within the kernel.
-          For now we just check to make sure it's not a small positive
-          or negative value, as that will at least catch some kinds of
-          error.  In particular, we make sure that ADDR's not within the
-          interrupt vector area, which we know starts at zero, or within the
-          peripheral-I/O area, which is located just _before_ zero.  */
-       unsigned long val = (unsigned long)addr;
-       return val >= (0x80 + NUM_CPU_IRQS*16) && val < 0xFFFFF000;
-}
-
-/*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue.  No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
- *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path.  This means when everything is well,
- * we don't even have to jump over them.  Further, they do not intrude
- * on our cache or tlb entries.
- */
-
-struct exception_table_entry
-{
-       unsigned long insn, fixup;
-};
-
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_exception_table (unsigned long);
-
-
-/*
- * These are the main single-value transfer routines.  They automatically
- * use the right size if we just have the right pointer type.
- */
-
-extern int bad_user_access_length (void);
-
-#define __get_user(var, ptr)                                                 \
-  ({                                                                         \
-         int __gu_err = 0;                                                   \
-         typeof(*(ptr)) __gu_val = 0;                                        \
-         switch (sizeof (*(ptr))) {                                          \
-         case 1:                                                             \
-         case 2:                                                             \
-         case 4:                                                             \
-                 __gu_val = *(ptr);                                          \
-                 break;                                                      \
-         case 8:                                                             \
-                 memcpy(&__gu_val, ptr, sizeof(__gu_val));                   \
-                 break;                                                      \
-         default:                                                            \
-                 __gu_val = 0;                                               \
-                 __gu_err = __get_user_bad ();                               \
-                 break;                                                      \
-         }                                                                   \
-         (var) = __gu_val;                                                   \
-         __gu_err;                                                           \
-  })
-#define __get_user_bad()       (bad_user_access_length (), (-EFAULT))
-
-#define __put_user(var, ptr)                                                 \
-  ({                                                                         \
-         int __pu_err = 0;                                                   \
-         switch (sizeof (*(ptr))) {                                          \
-         case 1:                                                             \
-         case 2:                                                             \
-         case 4:                                                             \
-                 *(ptr) = (var);                                             \
-                 break;                                                      \
-         case 8: {                                                           \
-                 typeof(*(ptr)) __pu_val = 0;                                \
-                 memcpy(ptr, &__pu_val, sizeof(__pu_val));                   \
-                 }                                                           \
-                 break;                                                      \
-         default:                                                            \
-                 __pu_err = __put_user_bad ();                               \
-                 break;                                                      \
-         }                                                                   \
-         __pu_err;                                                           \
-  })
-#define __put_user_bad()       (bad_user_access_length (), (-EFAULT))
-
-#define put_user(x, ptr)       __put_user(x, ptr)
-#define get_user(x, ptr)       __get_user(x, ptr)
-
-#define __copy_from_user(to, from, n)  (memcpy (to, from, n), 0)
-#define __copy_to_user(to, from, n)    (memcpy(to, from, n), 0)
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-#define copy_from_user(to, from, n)    __copy_from_user (to, from, n)
-#define copy_to_user(to, from, n)      __copy_to_user(to, from, n)
-
-#define copy_to_user_ret(to,from,n,retval) \
-  ({ if (copy_to_user (to,from,n)) return retval; })
-
-#define copy_from_user_ret(to,from,n,retval) \
-  ({ if (copy_from_user (to,from,n)) return retval; })
-
-/*
- * Copy a null terminated string from userspace.
- */
-
-static inline long
-strncpy_from_user (char *dst, const char *src, long count)
-{
-       char *tmp;
-       strncpy (dst, src, count);
-       for (tmp = dst; *tmp && count > 0; tmp++, count--)
-               ;
-       return tmp - dst;
-}
-
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 on exception, a value greater than N if too long
- */
-static inline long strnlen_user (const char *src, long n)
-{
-       return strlen (src) + 1;
-}
-
-#define strlen_user(str)       strnlen_user (str, 32767)
-
-/*
- * Zero Userspace
- */
-
-static inline unsigned long
-clear_user (void *to, unsigned long n)
-{
-       memset (to, 0, n);
-       return 0;
-}
-
-#endif /* __V850_UACCESS_H__ */
diff --git a/include/asm-v850/ucontext.h b/include/asm-v850/ucontext.h
deleted file mode 100644 (file)
index 303c215..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __V850_UCONTEXT_H__
-#define __V850_UCONTEXT_H__
-
-#include <asm/sigcontext.h>
-
-struct ucontext {
-       unsigned long     uc_flags;
-       struct ucontext  *uc_link;
-       stack_t           uc_stack;
-       struct sigcontext uc_mcontext;
-       sigset_t          uc_sigmask;   /* mask last for extensibility */
-};
-
-#endif /* __V850_UCONTEXT_H__ */
diff --git a/include/asm-v850/unaligned.h b/include/asm-v850/unaligned.h
deleted file mode 100644 (file)
index 53122b2..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Note that some v850 chips support unaligned access, but it seems too
- * annoying to use.
- */
-#ifndef _ASM_V850_UNALIGNED_H
-#define _ASM_V850_UNALIGNED_H
-
-#include <linux/unaligned/be_byteshift.h>
-#include <linux/unaligned/le_byteshift.h>
-#include <linux/unaligned/generic.h>
-
-#define get_unaligned  __get_unaligned_le
-#define put_unaligned  __put_unaligned_le
-
-#endif /* _ASM_V850_UNALIGNED_H */
diff --git a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h
deleted file mode 100644 (file)
index 2241ed4..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * include/asm-v850/unistd.h -- System call numbers and invocation mechanism
- *
- *  Copyright (C) 2001,02,03,04  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03,04  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_UNISTD_H__
-#define __V850_UNISTD_H__
-
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_chown              16
-#define __NR_break              17
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_pause              29
-#define __NR_utime              30
-#define __NR_stty               31
-#define __NR_gtty               32
-#define __NR_access             33
-#define __NR_nice               34
-#define __NR_ftime              35
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-#define __NR_prof               44
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-#define __NR_lock               53
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-#define __NR_setpgid            57
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_ugetrlimit                 76
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-#define __NR_profil             98
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-#define __NR_vhangup           111
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_cacheflush                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-#define __NR_query_module      167
-#define __NR_poll              168
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl             172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread             180
-#define __NR_pwrite            181
-#define __NR_lchown            182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-#define __NR_getpmsg           188     /* some people actually want streams */
-#define __NR_putpmsg           189     /* some people actually want streams */
-#define __NR_vfork             190
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_fcntl64           198
-#define __NR_getdents64                199
-#define __NR_pivot_root                200
-#define __NR_gettid            201
-#define __NR_tkill             202
-
-#ifdef __KERNEL__
-
-#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_RT_SIGACTION
-
-/*
- * "Conditional" syscalls
- */
-#define cond_syscall(name)                                                   \
-  asm (".weak\t" C_SYMBOL_STRING(name) ";"                                   \
-       ".set\t" C_SYMBOL_STRING(name) "," C_SYMBOL_STRING(sys_ni_syscall))
-#if 0
-/* This doesn't work if there's a function prototype for NAME visible,
-   because the argument types probably won't match.  */
-#define cond_syscall(name)  \
-  void name (void) __attribute__ ((weak, alias ("sys_ni_syscall")));
-#endif
-
-#endif /* __KERNEL__ */
-#endif /* __V850_UNISTD_H__ */
diff --git a/include/asm-v850/user.h b/include/asm-v850/user.h
deleted file mode 100644 (file)
index 63cdc56..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef __V850_USER_H__
-#define __V850_USER_H__
-
-/* Adapted from <asm-ppc/user.h>.  */
-
-#include <linux/ptrace.h>
-#include <asm/page.h>
-
-/*
- * Core file format: The core file is written in such a way that gdb
- * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the osf-core).  The file contents
- * are as follows:
- *
- *  upage: 1 page consisting of a user struct that tells gdb
- *     what is present in the file.  Directly after this is a
- *     copy of the task_struct, which is currently not used by gdb,
- *     but it may come in handy at some point.  All of the registers
- *     are stored as part of the upage.  The upage should always be
- *     only one page long.
- *  data: The data segment follows next.  We use current->end_text to
- *     current->brk to pick up all of the user variables, plus any memory
- *     that may have been sbrk'ed.  No attempt is made to determine if a
- *     page is demand-zero or if a page is totally unused, we just cover
- *     the entire range.  All of the addresses are rounded in such a way
- *     that an integral number of pages is written.
- *  stack: We need the stack information in order to get a meaningful
- *     backtrace.  We need to write the data from usp to
- *     current->start_stack, so we round each of these in order to be able
- *     to write an integer number of pages.
- */
-struct user {
-       struct pt_regs  regs;                   /* entire machine state */
-       size_t          u_tsize;                /* text size (pages) */
-       size_t          u_dsize;                /* data size (pages) */
-       size_t          u_ssize;                /* stack size (pages) */
-       unsigned long   start_code;             /* text starting address */
-       unsigned long   start_data;             /* data starting address */
-       unsigned long   start_stack;            /* stack starting address */
-       long int        signal;                 /* signal causing core dump */
-       unsigned long   u_ar0;                  /* help gdb find registers */
-       unsigned long   magic;                  /* identifies a core file */
-       char            u_comm[32];             /* user command name */
-};
-
-#define NBPG                   PAGE_SIZE
-#define UPAGES                 1
-#define HOST_TEXT_START_ADDR   (u.start_code)
-#define HOST_DATA_START_ADDR   (u.start_data)
-#define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
-
-#endif /* __V850_USER_H__ */
diff --git a/include/asm-v850/v850e.h b/include/asm-v850/v850e.h
deleted file mode 100644 (file)
index 5a222eb..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * include/asm-v850/v850e.h -- V850E CPU
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E_H__
-#define __V850_V850E_H__
-
-#include <asm/v850e_intc.h>
-
-#define CPU_ARCH "v850e"
-
-#endif /* __V850_V850E_H__ */
diff --git a/include/asm-v850/v850e2.h b/include/asm-v850/v850e2.h
deleted file mode 100644 (file)
index 4868040..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * include/asm-v850/v850e2.h -- Machine-dependent defs for V850E2 CPUs
- *
- *  Copyright (C) 2002,03  NEC Electronics Corporation
- *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E2_H__
-#define __V850_V850E2_H__
-
-#include <asm/v850e_intc.h>    /* v850e-style interrupt system.  */
-
-
-#define CPU_ARCH "v850e2"
-
-
-/* Control registers.  */
-
-/* Chip area select control */ 
-#define V850E2_CSC_ADDR(n)     (0xFFFFF060 + (n) * 2)
-#define V850E2_CSC(n)          (*(volatile u16 *)V850E2_CSC_ADDR(n))
-/* I/O area select control */
-#define V850E2_BPC_ADDR                0xFFFFF064
-#define V850E2_BPC             (*(volatile u16 *)V850E2_BPC_ADDR)
-/* Bus size configuration */
-#define V850E2_BSC_ADDR                0xFFFFF066
-#define V850E2_BSC             (*(volatile u16 *)V850E2_BSC_ADDR)
-/* Endian configuration */
-#define V850E2_BEC_ADDR                0xFFFFF068
-#define V850E2_BEC             (*(volatile u16 *)V850E2_BEC_ADDR)
-/* Cache configuration */
-#define V850E2_BHC_ADDR                0xFFFFF06A
-#define V850E2_BHC             (*(volatile u16 *)V850E2_BHC_ADDR)
-/* NPB strobe-wait configuration */
-#define V850E2_VSWC_ADDR       0xFFFFF06E
-#define V850E2_VSWC            (*(volatile u16 *)V850E2_VSWC_ADDR)
-/* Bus cycle type */
-#define V850E2_BCT_ADDR(n)     (0xFFFFF480 + (n) * 2)
-#define V850E2_BCT(n)          (*(volatile u16 *)V850E2_BCT_ADDR(n))
-/* Data wait control */
-#define V850E2_DWC_ADDR(n)     (0xFFFFF484 + (n) * 2)
-#define V850E2_DWC(n)          (*(volatile u16 *)V850E2_DWC_ADDR(n))
-/* Bus cycle control */
-#define V850E2_BCC_ADDR                0xFFFFF488
-#define V850E2_BCC             (*(volatile u16 *)V850E2_BCC_ADDR)
-/* Address wait control */
-#define V850E2_ASC_ADDR                0xFFFFF48A
-#define V850E2_ASC             (*(volatile u16 *)V850E2_ASC_ADDR)
-/* Local bus sizing control */
-#define V850E2_LBS_ADDR                0xFFFFF48E
-#define V850E2_LBS             (*(volatile u16 *)V850E2_LBS_ADDR)
-/* Line buffer control */
-#define V850E2_LBC_ADDR(n)     (0xFFFFF490 + (n) * 2)
-#define V850E2_LBC(n)          (*(volatile u16 *)V850E2_LBC_ADDR(n))
-/* SDRAM configuration */
-#define V850E2_SCR_ADDR(n)     (0xFFFFF4A0 + (n) * 4)
-#define V850E2_SCR(n)          (*(volatile u16 *)V850E2_SCR_ADDR(n))
-/* SDRAM refresh cycle control */
-#define V850E2_RFS_ADDR(n)     (0xFFFFF4A2 + (n) * 4)
-#define V850E2_RFS(n)          (*(volatile u16 *)V850E2_RFS_ADDR(n))
-
-
-#endif /* __V850_V850E2_H__ */
diff --git a/include/asm-v850/v850e2_cache.h b/include/asm-v850/v850e2_cache.h
deleted file mode 100644 (file)
index 87edf0d..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * include/asm-v850/v850e2_cache_cache.h -- Cache control for V850E2
- *     cache memories
- *
- *  Copyright (C) 2003,05  NEC Electronics Corporation
- *  Copyright (C) 2003,05  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E2_CACHE_H__
-#define __V850_V850E2_CACHE_H__
-
-#include <asm/types.h>
-
-
-/* Cache control registers.  */
-
-/* Bus Transaction Control */
-#define V850E2_CACHE_BTSC_ADDR 0xFFFFF070
-#define V850E2_CACHE_BTSC      (*(volatile u16 *)V850E2_CACHE_BTSC_ADDR)
-#define V850E2_CACHE_BTSC_ICM  0x0001 /* icache enable */
-#define V850E2_CACHE_BTSC_DCM0 0x0004 /* dcache enable, bit 0 */
-#define V850E2_CACHE_BTSC_DCM1 0x0008 /* dcache enable, bit 1 */
-#define V850E2_CACHE_BTSC_DCM_WT                     /* write-through */ \
-                       V850E2_CACHE_BTSC_DCM0
-#ifdef CONFIG_V850E2_V850E2S
-# define V850E2_CACHE_BTSC_DCM_WB_NO_ALLOC    /* write-back, non-alloc */ \
-                       V850E2_CACHE_BTSC_DCM1  
-# define V850E2_CACHE_BTSC_DCM_WB_ALLOC              /* write-back, non-alloc */ \
-                       (V850E2_CACHE_BTSC_DCM1 | V850E2_CACHE_BTSC_DCM0)
-# define V850E2_CACHE_BTSC_ISEQ        0x0010 /* icache `address sequence mode' */
-# define V850E2_CACHE_BTSC_DSEQ        0x0020 /* dcache `address sequence mode' */
-# define V850E2_CACHE_BTSC_IRFC        0x0030
-# define V850E2_CACHE_BTSC_ILCD        0x4000
-# define V850E2_CACHE_BTSC_VABE        0x8000
-#endif /* CONFIG_V850E2_V850E2S */
-
-/* Cache operation start address register (low-bits).  */
-#define V850E2_CACHE_CADL_ADDR 0xFFFFF074
-#define V850E2_CACHE_CADL      (*(volatile u16 *)V850E2_CACHE_CADL_ADDR)
-/* Cache operation start address register (high-bits).  */
-#define V850E2_CACHE_CADH_ADDR 0xFFFFF076
-#define V850E2_CACHE_CADH      (*(volatile u16 *)V850E2_CACHE_CADH_ADDR)
-/* Cache operation count register.  */
-#define V850E2_CACHE_CCNT_ADDR 0xFFFFF078
-#define V850E2_CACHE_CCNT      (*(volatile u16 *)V850E2_CACHE_CCNT_ADDR)
-/* Cache operation specification register.  */
-#define V850E2_CACHE_COPR_ADDR 0xFFFFF07A
-#define V850E2_CACHE_COPR      (*(volatile u16 *)V850E2_CACHE_COPR_ADDR)
-#define V850E2_CACHE_COPR_STRT 0x0001 /* start cache operation */
-#define V850E2_CACHE_COPR_LBSL 0x0100 /* 0 = icache, 1 = dcache */
-#define V850E2_CACHE_COPR_WSLE 0x0200 /* operate on cache way */
-#define V850E2_CACHE_COPR_WSL(way) ((way) * 0x0400) /* way select */
-#define V850E2_CACHE_COPR_CFC(op)  ((op)  * 0x1000) /* cache function code */
-
-
-/* Size of a cache line in bytes.  */
-#define V850E2_CACHE_LINE_SIZE_BITS    4
-#define V850E2_CACHE_LINE_SIZE         (1 << V850E2_CACHE_LINE_SIZE_BITS)
-
-/* The size of each cache `way' in lines.  */
-#define V850E2_CACHE_WAY_SIZE          256
-
-
-/* For <asm/cache.h> */
-#define L1_CACHE_BYTES                 V850E2_CACHE_LINE_SIZE
-#define L1_CACHE_SHIFT                 V850E2_CACHE_LINE_SIZE_BITS
-
-
-#endif /* __V850_V850E2_CACHE_H__ */
diff --git a/include/asm-v850/v850e_cache.h b/include/asm-v850/v850e_cache.h
deleted file mode 100644 (file)
index aa7d7eb..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * include/asm-v850/v850e_cache.h -- Cache control for V850E cache memories
- *
- *  Copyright (C) 2001,03  NEC Electronics Corporation
- *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* This file implements cache control for the rather simple cache used on
-   some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2
-   CPU.  V850E2 processors have their own (better) cache
-   implementation.  */
-
-#ifndef __V850_V850E_CACHE_H__
-#define __V850_V850E_CACHE_H__
-
-#include <asm/types.h>
-
-
-/* Cache control registers.  */
-#define V850E_CACHE_BHC_ADDR   0xFFFFF06A
-#define V850E_CACHE_BHC                (*(volatile u16 *)V850E_CACHE_BHC_ADDR)
-#define V850E_CACHE_ICC_ADDR   0xFFFFF070
-#define V850E_CACHE_ICC                (*(volatile u16 *)V850E_CACHE_ICC_ADDR)
-#define V850E_CACHE_ISI_ADDR   0xFFFFF072
-#define V850E_CACHE_ISI                (*(volatile u16 *)V850E_CACHE_ISI_ADDR)
-#define V850E_CACHE_DCC_ADDR   0xFFFFF078
-#define V850E_CACHE_DCC                (*(volatile u16 *)V850E_CACHE_DCC_ADDR)
-
-/* Size of a cache line in bytes.  */
-#define V850E_CACHE_LINE_SIZE  16
-
-/* For <asm/cache.h> */
-#define L1_CACHE_BYTES         V850E_CACHE_LINE_SIZE
-
-
-#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
-/* Set caching params via the BHC, ICC, and DCC registers.  */
-void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc);
-#endif /* __KERNEL__ && !__ASSEMBLY__ */
-
-
-#endif /* __V850_V850E_CACHE_H__ */
diff --git a/include/asm-v850/v850e_intc.h b/include/asm-v850/v850e_intc.h
deleted file mode 100644 (file)
index 6fdf957..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * include/asm-v850/v850e_intc.h -- V850E CPU interrupt controller (INTC)
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E_INTC_H__
-#define __V850_V850E_INTC_H__
-
-
-/* There are 4 16-bit `Interrupt Mask Registers' located contiguously
-   starting from this base.  Each interrupt uses a single bit to
-   indicated enabled/disabled status.  */
-#define V850E_INTC_IMR_BASE_ADDR  0xFFFFF100
-#define V850E_INTC_IMR_ADDR(irq)  (V850E_INTC_IMR_BASE_ADDR + ((irq) >> 3))
-#define V850E_INTC_IMR_BIT(irq)          ((irq) & 0x7)
-
-/* Each maskable interrupt has a single-byte control register at this
-   address.  */
-#define V850E_INTC_IC_BASE_ADDR          0xFFFFF110
-#define V850E_INTC_IC_ADDR(irq)          (V850E_INTC_IC_BASE_ADDR + ((irq) << 1))
-#define V850E_INTC_IC(irq)       (*(volatile u8 *)V850E_INTC_IC_ADDR(irq))
-/* Encode priority PR for storing in an interrupt control register.  */
-#define V850E_INTC_IC_PR(pr)     (pr)
-/* Interrupt disable bit in an interrupt control register.  */
-#define V850E_INTC_IC_MK_BIT     6
-#define V850E_INTC_IC_MK         (1 << V850E_INTC_IC_MK_BIT)
-/* Interrupt pending flag in an interrupt control register.  */
-#define V850E_INTC_IC_IF_BIT     7
-#define V850E_INTC_IC_IF         (1 << V850E_INTC_IC_IF_BIT)
-
-/* The ISPR (In-service priority register) contains one bit for each interrupt
-   priority level, which is set to one when that level is currently being
-   serviced (and thus blocking any interrupts of equal or lesser level).  */
-#define V850E_INTC_ISPR_ADDR     0xFFFFF1FA
-#define V850E_INTC_ISPR                  (*(volatile u8 *)V850E_INTC_ISPR_ADDR)
-
-
-#ifndef __ASSEMBLY__
-
-/* Enable interrupt handling for interrupt IRQ.  */
-static inline void v850e_intc_enable_irq (unsigned irq)
-{
-       __asm__ __volatile__ ("clr1 %0, [%1]"
-                             :: "r" (V850E_INTC_IMR_BIT (irq)),
-                                "r" (V850E_INTC_IMR_ADDR (irq))
-                             : "memory");
-}
-
-/* Disable interrupt handling for interrupt IRQ.  Note that any
-   interrupts received while disabled will be delivered once the
-   interrupt is enabled again, unless they are explicitly cleared using
-   `v850e_intc_clear_pending_irq'.  */
-static inline void v850e_intc_disable_irq (unsigned irq)
-{
-       __asm__ __volatile__ ("set1 %0, [%1]"
-                             :: "r" (V850E_INTC_IMR_BIT (irq)),
-                                "r" (V850E_INTC_IMR_ADDR (irq))
-                             : "memory");
-}
-
-/* Return true if interrupt handling for interrupt IRQ is enabled.  */
-static inline int v850e_intc_irq_enabled (unsigned irq)
-{
-       int rval;
-       __asm__ __volatile__ ("tst1 %1, [%2]; setf z, %0"
-                             : "=r" (rval)
-                             : "r" (V850E_INTC_IMR_BIT (irq)),
-                               "r" (V850E_INTC_IMR_ADDR (irq)));
-       return rval;
-}
-
-/* Disable irqs from 0 until LIMIT.  LIMIT must be a multiple of 8.  */
-static inline void _v850e_intc_disable_irqs (unsigned limit)
-{
-       unsigned long addr;
-       for (addr = V850E_INTC_IMR_BASE_ADDR; limit >= 8; addr++, limit -= 8)
-               *(char *)addr = 0xFF;
-}
-
-/* Disable all irqs.  This is purposely a macro, because NUM_MACH_IRQS
-   will be only be defined later.  */
-#define v850e_intc_disable_irqs()   _v850e_intc_disable_irqs (NUM_MACH_IRQS)
-
-/* Clear any pending interrupts for IRQ.  */
-static inline void v850e_intc_clear_pending_irq (unsigned irq)
-{
-       __asm__ __volatile__ ("clr1 %0, 0[%1]"
-                             :: "i" (V850E_INTC_IC_IF_BIT),
-                                "r" (V850E_INTC_IC_ADDR (irq))
-                             : "memory");
-}
-
-/* Return true if interrupt IRQ is pending (but disabled).  */
-static inline int v850e_intc_irq_pending (unsigned irq)
-{
-       int rval;
-       __asm__ __volatile__ ("tst1 %1, 0[%2]; setf nz, %0"
-                             : "=r" (rval)
-                             : "i" (V850E_INTC_IC_IF_BIT),
-                               "r" (V850E_INTC_IC_ADDR (irq)));
-       return rval;
-}
-
-
-struct v850e_intc_irq_init {
-       const char *name;       /* name of interrupt type */
-
-       /* Range of kernel irq numbers for this type:
-          BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM  */
-       unsigned base, num, interval;
-
-       unsigned priority;      /* interrupt priority to assign */
-};
-struct hw_interrupt_type;      /* fwd decl */
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
-   INITS (which is terminated by an entry with the name field == 0).  */
-extern void v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits,
-                                      struct hw_interrupt_type *hw_irq_types);
-
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_V850E_INTC_H__ */
diff --git a/include/asm-v850/v850e_timer_c.h b/include/asm-v850/v850e_timer_c.h
deleted file mode 100644 (file)
index f70575d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * include/asm-v850/v850e_timer_c.h -- `Timer C' component often used
- *     with the V850E cpu core
- *
- *  Copyright (C) 2001,03  NEC Electronics Corporation
- *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* NOTE: this include file currently contains only enough to allow us to
-   use timer C as an interrupt pass-through.  */
-
-#ifndef __V850_V850E_TIMER_C_H__
-#define __V850_V850E_TIMER_C_H__
-
-#include <asm/types.h>
-#include <asm/machdep.h>       /* Pick up chip-specific defs.  */
-
-
-/* Timer C (16-bit interval timers).  */
-
-/* Control register 0 for timer C.  */
-#define V850E_TIMER_C_TMCC0_ADDR(n) (V850E_TIMER_C_BASE_ADDR + 0x6 + 0x10 *(n))
-#define V850E_TIMER_C_TMCC0(n)   (*(volatile u8 *)V850E_TIMER_C_TMCC0_ADDR(n))
-#define V850E_TIMER_C_TMCC0_CAE          0x01 /* clock action enable */
-#define V850E_TIMER_C_TMCC0_CE   0x02 /* count enable */
-/* ... */
-
-/* Control register 1 for timer C.  */
-#define V850E_TIMER_C_TMCC1_ADDR(n) (V850E_TIMER_C_BASE_ADDR + 0x8 + 0x10 *(n))
-#define V850E_TIMER_C_TMCC1(n)   (*(volatile u8 *)V850E_TIMER_C_TMCC1_ADDR(n))
-#define V850E_TIMER_C_TMCC1_CMS0  0x01 /* capture/compare mode select (ccc0) */
-#define V850E_TIMER_C_TMCC1_CMS1  0x02 /* capture/compare mode select (ccc1) */
-/* ... */
-
-/* Interrupt edge-sensitivity control for timer C.  */
-#define V850E_TIMER_C_SESC_ADDR(n) (V850E_TIMER_C_BASE_ADDR + 0x9 + 0x10 *(n))
-#define V850E_TIMER_C_SESC(n)    (*(volatile u8 *)V850E_TIMER_C_SESC_ADDR(n))
-
-/* ...etc... */
-
-
-#endif /* __V850_V850E_TIMER_C_H__  */
diff --git a/include/asm-v850/v850e_timer_d.h b/include/asm-v850/v850e_timer_d.h
deleted file mode 100644 (file)
index 417612c..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * include/asm-v850/v850e_timer_d.h -- `Timer D' component often used
- *     with the V850E cpu core
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E_TIMER_D_H__
-#define __V850_V850E_TIMER_D_H__
-
-#include <asm/types.h>
-#include <asm/machdep.h>       /* Pick up chip-specific defs.  */
-
-
-/* Timer D (16-bit interval timers).  */
-
-/* Count registers for timer D.  */
-#define V850E_TIMER_D_TMD_ADDR(n) (V850E_TIMER_D_TMD_BASE_ADDR + 0x10 * (n))
-#define V850E_TIMER_D_TMD(n)     (*(volatile u16 *)V850E_TIMER_D_TMD_ADDR(n))
-
-/* Count compare registers for timer D.  */
-#define V850E_TIMER_D_CMD_ADDR(n) (V850E_TIMER_D_CMD_BASE_ADDR + 0x10 * (n))
-#define V850E_TIMER_D_CMD(n)     (*(volatile u16 *)V850E_TIMER_D_CMD_ADDR(n))
-
-/* Control registers for timer D.  */
-#define V850E_TIMER_D_TMCD_ADDR(n) (V850E_TIMER_D_TMCD_BASE_ADDR + 0x10 * (n))
-#define V850E_TIMER_D_TMCD(n)     (*(volatile u8 *)V850E_TIMER_D_TMCD_ADDR(n))
-/* Control bits for timer D.  */
-#define V850E_TIMER_D_TMCD_CE             0x2 /* count enable */
-#define V850E_TIMER_D_TMCD_CAE    0x1 /* clock action enable */
-/* Clock divider setting (log2).  */
-#define V850E_TIMER_D_TMCD_CS(divlog2) (((divlog2) - V850E_TIMER_D_TMCD_CS_MIN) << 4)
-/* Minimum clock divider setting (log2).  */
-#ifndef V850E_TIMER_D_TMCD_CS_MIN /* Can be overridden by mach-specific hdrs */
-#define V850E_TIMER_D_TMCD_CS_MIN  2 /* Default is correct for the v850e/ma1 */
-#endif
-/* Maximum clock divider setting (log2).  */
-#define V850E_TIMER_D_TMCD_CS_MAX  (V850E_TIMER_D_TMCD_CS_MIN + 7)
-
-/* Return the clock-divider (log2) of timer D unit N.  */
-#define V850E_TIMER_D_DIVLOG2(n) \
-  (((V850E_TIMER_D_TMCD(n) >> 4) & 0x7) + V850E_TIMER_D_TMCD_CS_MIN)
-
-
-#ifndef __ASSEMBLY__
-
-/* Start interval timer TIMER (0-3).  The timer will issue the
-   corresponding INTCMD interrupt RATE times per second.  This function
-   does not enable the interrupt.  */
-extern void v850e_timer_d_configure (unsigned timer, unsigned rate);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_V850E_TIMER_D_H__  */
diff --git a/include/asm-v850/v850e_uart.h b/include/asm-v850/v850e_uart.h
deleted file mode 100644 (file)
index 5182fb4..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * include/asm-v850/v850e_uart.h -- common V850E on-chip UART driver
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* There's not actually a single UART implementation used by V850E CPUs,
-   but rather a series of implementations that are all `close' to one
-   another.  This file corresponds to the single driver which handles all
-   of them.  */
-
-#ifndef __V850_V850E_UART_H__
-#define __V850_V850E_UART_H__
-
-#include <linux/termios.h>
-
-#include <asm/v850e_utils.h>
-#include <asm/types.h>
-#include <asm/machdep.h>       /* Pick up chip-specific defs.  */
-
-
-/* Include model-specific definitions.  */
-#ifdef CONFIG_V850E_UART
-# ifdef CONFIG_V850E_UARTB
-#  include <asm-v850/v850e_uartb.h>
-# else
-#  include <asm-v850/v850e_uarta.h> /* original V850E UART */
-# endif
-#endif
-
-
-/* Optional capabilities some hardware provides.  */
-
-/* This UART doesn't implement RTS/CTS by default, but some platforms
-   implement them externally, so check to see if <asm/machdep.h> defined
-   anything.  */
-#ifdef V850E_UART_CTS
-#define v850e_uart_cts(n)              V850E_UART_CTS(n)
-#else
-#define v850e_uart_cts(n)              (1)
-#endif
-
-/* Do the same for RTS.  */
-#ifdef V850E_UART_SET_RTS
-#define v850e_uart_set_rts(n,v)                V850E_UART_SET_RTS(n,v)
-#else
-#define v850e_uart_set_rts(n,v)                ((void)0)
-#endif
-
-
-/* This is the serial channel to use for the boot console (if desired).  */
-#ifndef V850E_UART_CONSOLE_CHANNEL
-# define V850E_UART_CONSOLE_CHANNEL 0
-#endif
-
-
-#ifndef __ASSEMBLY__
-
-/* Setup a console using channel 0 of the builtin uart.  */
-extern void v850e_uart_cons_init (unsigned chan);
-
-/* Configure and turn on uart channel CHAN, using the termios `control
-   modes' bits in CFLAGS, and a baud-rate of BAUD.  */
-void v850e_uart_configure (unsigned chan, unsigned cflags, unsigned baud);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_V850E_UART_H__ */
diff --git a/include/asm-v850/v850e_uarta.h b/include/asm-v850/v850e_uarta.h
deleted file mode 100644 (file)
index e483e09..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * include/asm-v850/v850e_uarta.h -- original V850E on-chip UART
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* This is the original V850E UART implementation is called just `UART' in
-   the docs, but we name this header file <asm/v850e_uarta.h> because the
-   name <asm/v850e_uart.h> is used for the common driver that handles both
-   `UART' and `UARTB' implementations.  */
-
-#ifndef __V850_V850E_UARTA_H__
-#define __V850_V850E_UARTA_H__
-
-\f
-/* Raw hardware interface.  */
-
-/* The base address of the UART control registers for channel N.
-   The default is the address used on the V850E/MA1.  */
-#ifndef V850E_UART_BASE_ADDR
-#define V850E_UART_BASE_ADDR(n)                (0xFFFFFA00 + 0x10 * (n))
-#endif 
-
-/* Addresses of specific UART control registers for channel N.
-   The defaults are the addresses used on the V850E/MA1; if a platform
-   wants to redefine any of these, it must redefine them all.  */
-#ifndef V850E_UART_ASIM_ADDR
-#define V850E_UART_ASIM_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x0)
-#define V850E_UART_RXB_ADDR(n)         (V850E_UART_BASE_ADDR(n) + 0x2)
-#define V850E_UART_ASIS_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x3)
-#define V850E_UART_TXB_ADDR(n)         (V850E_UART_BASE_ADDR(n) + 0x4)
-#define V850E_UART_ASIF_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x5)
-#define V850E_UART_CKSR_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x6)
-#define V850E_UART_BRGC_ADDR(n)                (V850E_UART_BASE_ADDR(n) + 0x7)
-#endif
-
-/* UART config registers.  */
-#define V850E_UART_ASIM(n)     (*(volatile u8 *)V850E_UART_ASIM_ADDR(n))
-/* Control bits for config registers.  */
-#define V850E_UART_ASIM_CAE    0x80 /* clock enable */
-#define V850E_UART_ASIM_TXE    0x40 /* transmit enable */
-#define V850E_UART_ASIM_RXE    0x20 /* receive enable */
-#define V850E_UART_ASIM_PS_MASK        0x18 /* mask covering parity-select bits */
-#define V850E_UART_ASIM_PS_NONE        0x00 /* no parity */
-#define V850E_UART_ASIM_PS_ZERO        0x08 /* zero parity */
-#define V850E_UART_ASIM_PS_ODD 0x10 /* odd parity */
-#define V850E_UART_ASIM_PS_EVEN        0x18 /* even parity */
-#define V850E_UART_ASIM_CL_8   0x04 /* char len is 8 bits (otherwise, 7) */
-#define V850E_UART_ASIM_SL_2   0x02 /* 2 stop bits (otherwise, 1) */
-#define V850E_UART_ASIM_ISRM   0x01 /* generate INTSR interrupt on errors
-                                       (otherwise, generate INTSER) */
-
-/* UART serial interface status registers.  */
-#define V850E_UART_ASIS(n)     (*(volatile u8 *)V850E_UART_ASIS_ADDR(n))
-/* Control bits for status registers.  */
-#define V850E_UART_ASIS_PE     0x04 /* parity error */
-#define V850E_UART_ASIS_FE     0x02 /* framing error */
-#define V850E_UART_ASIS_OVE    0x01 /* overrun error */
-
-/* UART serial interface transmission status registers.  */
-#define V850E_UART_ASIF(n)     (*(volatile u8 *)V850E_UART_ASIF_ADDR(n))
-#define V850E_UART_ASIF_TXBF   0x02 /* transmit buffer flag (data in TXB) */
-#define V850E_UART_ASIF_TXSF   0x01 /* transmit shift flag (sending data) */
-
-/* UART receive buffer register.  */
-#define V850E_UART_RXB(n)      (*(volatile u8 *)V850E_UART_RXB_ADDR(n))
-
-/* UART transmit buffer register.  */
-#define V850E_UART_TXB(n)      (*(volatile u8 *)V850E_UART_TXB_ADDR(n))
-
-/* UART baud-rate generator control registers.  */
-#define V850E_UART_CKSR(n)     (*(volatile u8 *)V850E_UART_CKSR_ADDR(n))
-#define V850E_UART_CKSR_MAX    11
-#define V850E_UART_BRGC(n)     (*(volatile u8 *)V850E_UART_BRGC_ADDR(n))
-#define V850E_UART_BRGC_MIN    8
-
-
-#ifndef V850E_UART_CKSR_MAX_FREQ
-#define V850E_UART_CKSR_MAX_FREQ (25*1000*1000)
-#endif
-
-/* Calculate the minimum value for CKSR on this processor.  */
-static inline unsigned v850e_uart_cksr_min (void)
-{
-       int min = 0;
-       unsigned freq = V850E_UART_BASE_FREQ;
-       while (freq > V850E_UART_CKSR_MAX_FREQ) {
-               freq >>= 1;
-               min++;
-       }
-       return min;
-}
-
-\f
-/* Slightly abstract interface used by driver.  */
-
-
-/* Interrupts used by the UART.  */
-
-/* Received when the most recently transmitted character has been sent.  */
-#define V850E_UART_TX_IRQ(chan)                IRQ_INTST (chan)
-/* Received when a new character has been received.  */
-#define V850E_UART_RX_IRQ(chan)                IRQ_INTSR (chan)
-
-
-/* UART clock generator interface.  */
-
-/* This type encapsulates a particular uart frequency.  */
-typedef struct {
-       unsigned clk_divlog2;
-       unsigned brgen_count;
-} v850e_uart_speed_t;
-
-/* Calculate a uart speed from BAUD for this uart.  */
-static inline v850e_uart_speed_t v850e_uart_calc_speed (unsigned baud)
-{
-       v850e_uart_speed_t speed;
-
-       /* Calculate the log2 clock divider and baud-rate counter values
-          (note that the UART divides the resulting clock by 2, so
-          multiply BAUD by 2 here to compensate).  */
-       calc_counter_params (V850E_UART_BASE_FREQ, baud * 2,
-                            v850e_uart_cksr_min(),
-                            V850E_UART_CKSR_MAX, 8/*bits*/,
-                            &speed.clk_divlog2, &speed.brgen_count);
-
-       return speed;
-}
-
-/* Return the current speed of uart channel CHAN.  */
-static inline v850e_uart_speed_t v850e_uart_speed (unsigned chan)
-{
-       v850e_uart_speed_t speed;
-       speed.clk_divlog2 = V850E_UART_CKSR (chan);
-       speed.brgen_count = V850E_UART_BRGC (chan);
-       return speed;
-}
-
-/* Set the current speed of uart channel CHAN.  */
-static inline void v850e_uart_set_speed(unsigned chan,v850e_uart_speed_t speed)
-{
-       V850E_UART_CKSR (chan) = speed.clk_divlog2;
-       V850E_UART_BRGC (chan) = speed.brgen_count;
-}
-
-static inline int
-v850e_uart_speed_eq (v850e_uart_speed_t speed1, v850e_uart_speed_t speed2)
-{
-       return speed1.clk_divlog2 == speed2.clk_divlog2
-               && speed1.brgen_count == speed2.brgen_count;
-}
-
-/* Minimum baud rate possible.  */
-#define v850e_uart_min_baud() \
-   ((V850E_UART_BASE_FREQ >> V850E_UART_CKSR_MAX) / (2 * 255) + 1)
-
-/* Maximum baud rate possible.  The error is quite high at max, though.  */
-#define v850e_uart_max_baud() \
-   ((V850E_UART_BASE_FREQ >> v850e_uart_cksr_min()) / (2 *V850E_UART_BRGC_MIN))
-
-/* The `maximum' clock rate the uart can used, which is wanted (though not
-   really used in any useful way) by the serial framework.  */
-#define v850e_uart_max_clock() \
-   ((V850E_UART_BASE_FREQ >> v850e_uart_cksr_min()) / 2)
-
-
-/* UART configuration interface.  */
-
-/* Type of the uart config register; must be a scalar.  */
-typedef u16 v850e_uart_config_t;
-
-/* The uart hardware config register for channel CHAN.  */
-#define V850E_UART_CONFIG(chan)                V850E_UART_ASIM (chan)
-
-/* This config bit set if the uart is enabled.  */
-#define V850E_UART_CONFIG_ENABLED      V850E_UART_ASIM_CAE
-/* If the uart _isn't_ enabled, store this value to it to do so.  */
-#define V850E_UART_CONFIG_INIT         V850E_UART_ASIM_CAE
-/* Store this config value to disable the uart channel completely.  */
-#define V850E_UART_CONFIG_FINI         0
-
-/* Setting/clearing these bits enable/disable TX/RX, respectively (but
-   otherwise generally leave things running).  */
-#define V850E_UART_CONFIG_RX_ENABLE    V850E_UART_ASIM_RXE
-#define V850E_UART_CONFIG_TX_ENABLE    V850E_UART_ASIM_TXE
-
-/* These masks define which config bits affect TX/RX modes, respectively.  */
-#define V850E_UART_CONFIG_RX_BITS \
-  (V850E_UART_ASIM_PS_MASK | V850E_UART_ASIM_CL_8 | V850E_UART_ASIM_ISRM)
-#define V850E_UART_CONFIG_TX_BITS \
-  (V850E_UART_ASIM_PS_MASK | V850E_UART_ASIM_CL_8 | V850E_UART_ASIM_SL_2)
-
-static inline v850e_uart_config_t v850e_uart_calc_config (unsigned cflags)
-{
-       v850e_uart_config_t config = 0;
-
-       /* Figure out new configuration of control register.  */
-       if (cflags & CSTOPB)
-               /* Number of stop bits, 1 or 2.  */
-               config |= V850E_UART_ASIM_SL_2;
-       if ((cflags & CSIZE) == CS8)
-               /* Number of data bits, 7 or 8.  */
-               config |= V850E_UART_ASIM_CL_8;
-       if (! (cflags & PARENB))
-               /* No parity check/generation.  */
-               config |= V850E_UART_ASIM_PS_NONE;
-       else if (cflags & PARODD)
-               /* Odd parity check/generation.  */
-               config |= V850E_UART_ASIM_PS_ODD;
-       else
-               /* Even parity check/generation.  */
-               config |= V850E_UART_ASIM_PS_EVEN;
-       if (cflags & CREAD)
-               /* Reading enabled.  */
-               config |= V850E_UART_ASIM_RXE;
-
-       config |= V850E_UART_ASIM_CAE;
-       config |= V850E_UART_ASIM_TXE; /* Writing is always enabled.  */
-       config |= V850E_UART_ASIM_ISRM; /* Errors generate a read-irq.  */
-
-       return config;
-}
-
-/* This should delay as long as necessary for a recently written config
-   setting to settle, before we turn the uart back on.  */
-static inline void
-v850e_uart_config_delay (v850e_uart_config_t config, v850e_uart_speed_t speed)
-{
-       /* The UART may not be reset properly unless we wait at least 2
-          `basic-clocks' until turning on the TXE/RXE bits again.
-          A `basic clock' is the clock used by the baud-rate generator,
-          i.e., the cpu clock divided by the 2^new_clk_divlog2.
-          The loop takes 2 insns, so loop CYCLES / 2 times.  */
-       register unsigned count = 1 << speed.clk_divlog2;
-       while (--count != 0)
-               /* nothing */;
-}
-
-
-/* RX/TX interface.  */
-
-/* Return true if all characters awaiting transmission on uart channel N
-   have been transmitted.  */
-#define v850e_uart_xmit_done(n)                                                      \
-   (! (V850E_UART_ASIF(n) & V850E_UART_ASIF_TXBF))
-/* Wait for this to be true.  */
-#define v850e_uart_wait_for_xmit_done(n)                                     \
-   do { } while (! v850e_uart_xmit_done (n))
-
-/* Return true if uart channel N is ready to transmit a character.  */
-#define v850e_uart_xmit_ok(n)                                                \
-   (v850e_uart_xmit_done(n) && v850e_uart_cts(n))
-/* Wait for this to be true.  */
-#define v850e_uart_wait_for_xmit_ok(n)                                       \
-   do { } while (! v850e_uart_xmit_ok (n))
-
-/* Write character CH to uart channel CHAN.  */
-#define v850e_uart_putc(chan, ch)      (V850E_UART_TXB(chan) = (ch))
-
-/* Return latest character read on channel CHAN.  */
-#define v850e_uart_getc(chan)          V850E_UART_RXB (chan)
-
-/* Return bit-mask of uart error status.  */
-#define v850e_uart_err(chan)           V850E_UART_ASIS (chan)
-/* Various error bits set in the error result.  */
-#define V850E_UART_ERR_OVERRUN         V850E_UART_ASIS_OVE
-#define V850E_UART_ERR_FRAME           V850E_UART_ASIS_FE
-#define V850E_UART_ERR_PARITY          V850E_UART_ASIS_PE
-
-
-#endif /* __V850_V850E_UARTA_H__ */
diff --git a/include/asm-v850/v850e_uartb.h b/include/asm-v850/v850e_uartb.h
deleted file mode 100644 (file)
index 6d4767d..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * include/asm-v850/v850e_uartb.h -- V850E on-chip `UARTB' UART
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* The V850E UARTB is basically a superset of the original V850E UART, but
-   even where it's the same, the names and details have changed a bit.
-   It's similar enough to use the same driver (v850e_uart.c), but the
-   details have been abstracted slightly to do so.  */
-
-#ifndef __V850_V850E_UARTB_H__
-#define __V850_V850E_UARTB_H__
-
-\f
-/* Raw hardware interface.  */
-
-#define V850E_UARTB_BASE_ADDR(n)       (0xFFFFFA00 + 0x10 * (n))
-
-/* Addresses of specific UART control registers for channel N.  */
-#define V850E_UARTB_CTL0_ADDR(n)       (V850E_UARTB_BASE_ADDR(n) + 0x0)
-#define V850E_UARTB_CTL2_ADDR(n)       (V850E_UARTB_BASE_ADDR(n) + 0x2)
-#define V850E_UARTB_STR_ADDR(n)                (V850E_UARTB_BASE_ADDR(n) + 0x4)
-#define V850E_UARTB_RX_ADDR(n)         (V850E_UARTB_BASE_ADDR(n) + 0x6)
-#define V850E_UARTB_RXAP_ADDR(n)       (V850E_UARTB_BASE_ADDR(n) + 0x6)
-#define V850E_UARTB_TX_ADDR(n)         (V850E_UARTB_BASE_ADDR(n) + 0x8)
-#define V850E_UARTB_FIC0_ADDR(n)       (V850E_UARTB_BASE_ADDR(n) + 0xA)
-#define V850E_UARTB_FIC1_ADDR(n)       (V850E_UARTB_BASE_ADDR(n) + 0xB)
-#define V850E_UARTB_FIC2_ADDR(n)       (V850E_UARTB_BASE_ADDR(n) + 0xC)
-#define V850E_UARTB_FIS0_ADDR(n)       (V850E_UARTB_BASE_ADDR(n) + 0xE)
-#define V850E_UARTB_FIS1_ADDR(n)       (V850E_UARTB_BASE_ADDR(n) + 0xF)
-
-/* UARTB control register 0 (general config).  */
-#define V850E_UARTB_CTL0(n)    (*(volatile u8 *)V850E_UARTB_CTL0_ADDR(n))
-/* Control bits for config registers.  */
-#define V850E_UARTB_CTL0_PWR           0x80    /* clock enable */
-#define V850E_UARTB_CTL0_TXE           0x40    /* transmit enable */
-#define V850E_UARTB_CTL0_RXE           0x20    /* receive enable */
-#define V850E_UARTB_CTL0_DIR           0x10    /*  */
-#define V850E_UARTB_CTL0_PS1           0x08    /* parity */
-#define V850E_UARTB_CTL0_PS0           0x04    /* parity */
-#define V850E_UARTB_CTL0_CL            0x02    /* char len 1:8bit, 0:7bit */
-#define V850E_UARTB_CTL0_SL            0x01    /* stop bit 1:2bit, 0:1bit */
-#define V850E_UARTB_CTL0_PS_MASK       0x0C    /* mask covering parity bits */
-#define V850E_UARTB_CTL0_PS_NONE       0x00    /* no parity */
-#define V850E_UARTB_CTL0_PS_ZERO       0x04    /* zero parity */
-#define V850E_UARTB_CTL0_PS_ODD                0x08    /* odd parity */
-#define V850E_UARTB_CTL0_PS_EVEN       0x0C    /* even parity */
-#define V850E_UARTB_CTL0_CL_8          0x02    /* char len 1:8bit, 0:7bit */
-#define V850E_UARTB_CTL0_SL_2          0x01    /* stop bit 1:2bit, 0:1bit */
-
-/* UARTB control register 2 (clock divider).  */
-#define V850E_UARTB_CTL2(n)    (*(volatile u16 *)V850E_UARTB_CTL2_ADDR(n))
-#define V850E_UARTB_CTL2_MIN   4
-#define V850E_UARTB_CTL2_MAX   0xFFFF
-
-/* UARTB serial interface status register.  */
-#define V850E_UARTB_STR(n)     (*(volatile u8 *)V850E_UARTB_STR_ADDR(n))
-/* Control bits for status registers.  */
-#define V850E_UARTB_STR_TSF    0x80    /* UBTX or FIFO exist data  */
-#define V850E_UARTB_STR_OVF    0x08    /* overflow error */
-#define V850E_UARTB_STR_PE     0x04    /* parity error */
-#define V850E_UARTB_STR_FE     0x02    /* framing error */
-#define V850E_UARTB_STR_OVE    0x01    /* overrun error */
-
-/* UARTB receive data register.  */
-#define V850E_UARTB_RX(n)      (*(volatile u8 *)V850E_UARTB_RX_ADDR(n))
-#define V850E_UARTB_RXAP(n)    (*(volatile u16 *)V850E_UARTB_RXAP_ADDR(n))
-/* Control bits for status registers.  */
-#define V850E_UARTB_RXAP_PEF   0x0200 /* parity error */
-#define V850E_UARTB_RXAP_FEF   0x0100 /* framing error */
-
-/* UARTB transmit data register.  */
-#define V850E_UARTB_TX(n)      (*(volatile u8 *)V850E_UARTB_TX_ADDR(n))
-
-/* UARTB FIFO control register 0.  */
-#define V850E_UARTB_FIC0(n)    (*(volatile u8 *)V850E_UARTB_FIC0_ADDR(n))
-
-/* UARTB FIFO control register 1.  */
-#define V850E_UARTB_FIC1(n)    (*(volatile u8 *)V850E_UARTB_FIC1_ADDR(n))
-
-/* UARTB FIFO control register 2.  */
-#define V850E_UARTB_FIC2(n)    (*(volatile u16 *)V850E_UARTB_FIC2_ADDR(n))
-
-/* UARTB FIFO status register 0.  */
-#define V850E_UARTB_FIS0(n)    (*(volatile u8 *)V850E_UARTB_FIS0_ADDR(n))
-
-/* UARTB FIFO status register 1.  */
-#define V850E_UARTB_FIS1(n)    (*(volatile u8 *)V850E_UARTB_FIS1_ADDR(n))
-
-\f
-/* Slightly abstract interface used by driver.  */
-
-
-/* Interrupts used by the UART.  */
-
-/* Received when the most recently transmitted character has been sent.  */
-#define V850E_UART_TX_IRQ(chan)                IRQ_INTUBTIT (chan)
-/* Received when a new character has been received.  */
-#define V850E_UART_RX_IRQ(chan)                IRQ_INTUBTIR (chan)
-
-/* Use by serial driver for information purposes.  */
-#define V850E_UART_BASE_ADDR(chan)     V850E_UARTB_BASE_ADDR(chan)
-
-
-/* UART clock generator interface.  */
-
-/* This type encapsulates a particular uart frequency.  */
-typedef u16 v850e_uart_speed_t;
-
-/* Calculate a uart speed from BAUD for this uart.  */
-static inline v850e_uart_speed_t v850e_uart_calc_speed (unsigned baud)
-{
-       v850e_uart_speed_t speed;
-
-       /*
-        * V850E/ME2 UARTB baud rate is determined by the value of UBCTL2
-        * fx = V850E_UARTB_BASE_FREQ = CPU_CLOCK_FREQ/4
-        * baud = fx / 2*speed   [ speed >= 4 ]
-        */
-       speed = V850E_UARTB_CTL2_MIN;
-       while (((V850E_UARTB_BASE_FREQ / 2) / speed ) > baud)
-               speed++;
-
-       return speed;
-}
-
-/* Return the current speed of uart channel CHAN.  */
-#define v850e_uart_speed(chan)             V850E_UARTB_CTL2 (chan)
-
-/* Set the current speed of uart channel CHAN.  */
-#define v850e_uart_set_speed(chan, speed)   (V850E_UARTB_CTL2 (chan) = (speed))
-
-/* Return true if SPEED1 and SPEED2 are the same.  */
-#define v850e_uart_speed_eq(speed1, speed2) ((speed1) == (speed2))
-
-/* Minimum baud rate possible.  */
-#define v850e_uart_min_baud() \
-   ((V850E_UARTB_BASE_FREQ / 2) / V850E_UARTB_CTL2_MAX)
-
-/* Maximum baud rate possible.  The error is quite high at max, though.  */
-#define v850e_uart_max_baud() \
-   ((V850E_UARTB_BASE_FREQ / 2) / V850E_UARTB_CTL2_MIN)
-
-/* The `maximum' clock rate the uart can used, which is wanted (though not
-   really used in any useful way) by the serial framework.  */
-#define v850e_uart_max_clock() \
-   (V850E_UARTB_BASE_FREQ / 2)
-
-
-/* UART configuration interface.  */
-
-/* Type of the uart config register; must be a scalar.  */
-typedef u16 v850e_uart_config_t;
-
-/* The uart hardware config register for channel CHAN.  */
-#define V850E_UART_CONFIG(chan)                V850E_UARTB_CTL0 (chan)
-
-/* This config bit set if the uart is enabled.  */
-#define V850E_UART_CONFIG_ENABLED      V850E_UARTB_CTL0_PWR
-/* If the uart _isn't_ enabled, store this value to it to do so.  */
-#define V850E_UART_CONFIG_INIT         V850E_UARTB_CTL0_PWR
-/* Store this config value to disable the uart channel completely.  */
-#define V850E_UART_CONFIG_FINI         0
-
-/* Setting/clearing these bits enable/disable TX/RX, respectively (but
-   otherwise generally leave things running).  */
-#define V850E_UART_CONFIG_RX_ENABLE    V850E_UARTB_CTL0_RXE
-#define V850E_UART_CONFIG_TX_ENABLE    V850E_UARTB_CTL0_TXE
-
-/* These masks define which config bits affect TX/RX modes, respectively.  */
-#define V850E_UART_CONFIG_RX_BITS \
-  (V850E_UARTB_CTL0_PS_MASK | V850E_UARTB_CTL0_CL_8)
-#define V850E_UART_CONFIG_TX_BITS \
-  (V850E_UARTB_CTL0_PS_MASK | V850E_UARTB_CTL0_CL_8 | V850E_UARTB_CTL0_SL_2)
-
-static inline v850e_uart_config_t v850e_uart_calc_config (unsigned cflags)
-{
-       v850e_uart_config_t config = 0;
-
-       /* Figure out new configuration of control register.  */
-       if (cflags & CSTOPB)
-               /* Number of stop bits, 1 or 2.  */
-               config |= V850E_UARTB_CTL0_SL_2;
-       if ((cflags & CSIZE) == CS8)
-               /* Number of data bits, 7 or 8.  */
-               config |= V850E_UARTB_CTL0_CL_8;
-       if (! (cflags & PARENB))
-               /* No parity check/generation.  */
-               config |= V850E_UARTB_CTL0_PS_NONE;
-       else if (cflags & PARODD)
-               /* Odd parity check/generation.  */
-               config |= V850E_UARTB_CTL0_PS_ODD;
-       else
-               /* Even parity check/generation.  */
-               config |= V850E_UARTB_CTL0_PS_EVEN;
-       if (cflags & CREAD)
-               /* Reading enabled.  */
-               config |= V850E_UARTB_CTL0_RXE;
-
-       config |= V850E_UARTB_CTL0_PWR;
-       config |= V850E_UARTB_CTL0_TXE; /* Writing is always enabled.  */
-       config |= V850E_UARTB_CTL0_DIR; /* LSB first.  */
-
-       return config;
-}
-
-/* This should delay as long as necessary for a recently written config
-   setting to settle, before we turn the uart back on.  */
-static inline void
-v850e_uart_config_delay (v850e_uart_config_t config, v850e_uart_speed_t speed)
-{
-       /* The UART may not be reset properly unless we wait at least 2
-          `basic-clocks' until turning on the TXE/RXE bits again.
-          A `basic clock' is the clock used by the baud-rate generator,
-          i.e., the cpu clock divided by the 2^new_clk_divlog2.
-          The loop takes 2 insns, so loop CYCLES / 2 times.  */
-       register unsigned count = 1 << speed;
-       while (--count != 0)
-               /* nothing */;
-}
-
-
-/* RX/TX interface.  */
-
-/* Return true if all characters awaiting transmission on uart channel N
-   have been transmitted.  */
-#define v850e_uart_xmit_done(n)                                                      \
-   (! (V850E_UARTB_STR(n) & V850E_UARTB_STR_TSF))
-/* Wait for this to be true.  */
-#define v850e_uart_wait_for_xmit_done(n)                                     \
-   do { } while (! v850e_uart_xmit_done (n))
-
-/* Return true if uart channel N is ready to transmit a character.  */
-#define v850e_uart_xmit_ok(n)                                                \
-   (v850e_uart_xmit_done(n) && v850e_uart_cts(n))
-/* Wait for this to be true.  */
-#define v850e_uart_wait_for_xmit_ok(n)                                       \
-   do { } while (! v850e_uart_xmit_ok (n))
-
-/* Write character CH to uart channel CHAN.  */
-#define v850e_uart_putc(chan, ch)      (V850E_UARTB_TX(chan) = (ch))
-
-/* Return latest character read on channel CHAN.  */
-#define v850e_uart_getc(chan)          V850E_UARTB_RX (chan)
-
-/* Return bit-mask of uart error status.  */
-#define v850e_uart_err(chan)           V850E_UARTB_STR (chan)
-/* Various error bits set in the error result.  */
-#define V850E_UART_ERR_OVERRUN         V850E_UARTB_STR_OVE
-#define V850E_UART_ERR_FRAME           V850E_UARTB_STR_FE
-#define V850E_UART_ERR_PARITY          V850E_UARTB_STR_PE
-
-
-#endif /* __V850_V850E_UARTB_H__ */
diff --git a/include/asm-v850/v850e_utils.h b/include/asm-v850/v850e_utils.h
deleted file mode 100644 (file)
index 52eb728..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * include/asm-v850/v850e_utils.h -- Utility functions associated with
- *     V850E CPUs
- *
- *  Copyright (C) 2001,03  NEC Electronics Corporation
- *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E_UTILS_H__
-#define __V850_V850E_UTILS_H__
-
-/* Calculate counter clock-divider and count values to attain the
-   desired frequency RATE from the base frequency BASE_FREQ.  The
-   counter is expected to have a clock-divider, which can divide the
-   system cpu clock by a power of two value from MIN_DIVLOG2 to
-   MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
-   counts up and resets whenever it's equal to the compare register,
-   generating an interrupt or whatever when it does so).  The returned
-   values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
-   -- the counter compare value to use.  Returns true if it was possible
-   to find a reasonable value, otherwise false (and the other return
-   values will be set to be as good as possible).  */
-extern int calc_counter_params (unsigned long base_freq,
-                               unsigned long rate,
-                               unsigned min_divlog2, unsigned max_divlog2,
-                               unsigned counter_size,
-                               unsigned *divlog2, unsigned *count);
-
-#endif /* __V850_V850E_UTILS_H__ */
index 1e3554596f72189a6a2ddc03c2d6b0298215356d..4a8e80cdcfa57a7faff08a2042a6b6fb64f5ae66 100644 (file)
@@ -3,7 +3,6 @@ include include/asm-generic/Kbuild.asm
 header-y += boot.h
 header-y += bootparam.h
 header-y += debugreg.h
-header-y += kvm.h
 header-y += ldt.h
 header-y += msr-index.h
 header-y += prctl.h
@@ -19,7 +18,6 @@ unifdef-y += msr.h
 unifdef-y += mtrr.h
 unifdef-y += posix_types_32.h
 unifdef-y += posix_types_64.h
-unifdef-y += ptrace.h
 unifdef-y += unistd_32.h
 unifdef-y += unistd_64.h
 unifdef-y += vm86.h
index a44c4dc705902c6b1e76c92d71f1c68f759a0df4..06f786f4b4fbdd6f912fafae47c5805045ba313b 100644 (file)
@@ -24,6 +24,11 @@ static inline void fill_ldt(struct desc_struct *desc,
        desc->d = info->seg_32bit;
        desc->g = info->limit_in_pages;
        desc->base2 = (info->base_addr & 0xff000000) >> 24;
+       /*
+        * Don't allow setting of the lm bit. It is useless anyway
+        * because 64bit system calls require __USER_CS:
+        */
+       desc->l = 0;
 }
 
 extern struct desc_ptr idt_descr;
@@ -97,7 +102,15 @@ static inline int desc_empty(const void *ptr)
        native_write_gdt_entry(dt, entry, desc, type)
 #define write_idt_entry(dt, entry, g)          \
        native_write_idt_entry(dt, entry, g)
-#endif
+
+static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries)
+{
+}
+
+static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
+{
+}
+#endif /* CONFIG_PARAVIRT */
 
 static inline void native_write_idt_entry(gate_desc *idt, int entry,
                                          const gate_desc *gate)
index 87a715367a1b11a9db24d569682d22f780352be7..3c034f48fdb0a12f5a3fefe1499d014b68e6f4a2 100644 (file)
@@ -5,6 +5,9 @@ struct dev_archdata {
 #ifdef CONFIG_ACPI
        void    *acpi_handle;
 #endif
+#ifdef CONFIG_X86_64
+struct dma_mapping_ops *dma_ops;
+#endif
 #ifdef CONFIG_DMAR
        void *iommu; /* hook for IOMMU specific extension */
 #endif
index c2ddd3d1b8831a98fe139639e131f458bfc41d99..ad9cd6d49bfc9bc624747709da188301b35f5b55 100644 (file)
@@ -17,7 +17,8 @@ extern int panic_on_overflow;
 extern int force_iommu;
 
 struct dma_mapping_ops {
-       int             (*mapping_error)(dma_addr_t dma_addr);
+       int             (*mapping_error)(struct device *dev,
+                                        dma_addr_t dma_addr);
        void*           (*alloc_coherent)(struct device *dev, size_t size,
                                dma_addr_t *dma_handle, gfp_t gfp);
        void            (*free_coherent)(struct device *dev, size_t size,
@@ -56,14 +57,32 @@ struct dma_mapping_ops {
        int             is_phys;
 };
 
-extern const struct dma_mapping_ops *dma_ops;
+extern struct dma_mapping_ops *dma_ops;
 
-static inline int dma_mapping_error(dma_addr_t dma_addr)
+static inline struct dma_mapping_ops *get_dma_ops(struct device *dev)
 {
-       if (dma_ops->mapping_error)
-               return dma_ops->mapping_error(dma_addr);
+#ifdef CONFIG_X86_32
+       return dma_ops;
+#else
+       if (unlikely(!dev) || !dev->archdata.dma_ops)
+               return dma_ops;
+       else
+               return dev->archdata.dma_ops;
+#endif
+}
+
+/* Make sure we keep the same behaviour */
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+#ifdef CONFIG_X86_32
+       return 0;
+#else
+       struct dma_mapping_ops *ops = get_dma_ops(dev);
+       if (ops->mapping_error)
+               return ops->mapping_error(dev, dma_addr);
 
        return (dma_addr == bad_dma_address);
+#endif
 }
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
@@ -83,44 +102,53 @@ static inline dma_addr_t
 dma_map_single(struct device *hwdev, void *ptr, size_t size,
               int direction)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(hwdev);
+
        BUG_ON(!valid_dma_direction(direction));
-       return dma_ops->map_single(hwdev, virt_to_phys(ptr), size, direction);
+       return ops->map_single(hwdev, virt_to_phys(ptr), size, direction);
 }
 
 static inline void
 dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size,
                 int direction)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(dev);
+
        BUG_ON(!valid_dma_direction(direction));
-       if (dma_ops->unmap_single)
-               dma_ops->unmap_single(dev, addr, size, direction);
+       if (ops->unmap_single)
+               ops->unmap_single(dev, addr, size, direction);
 }
 
 static inline int
 dma_map_sg(struct device *hwdev, struct scatterlist *sg,
           int nents, int direction)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(hwdev);
+
        BUG_ON(!valid_dma_direction(direction));
-       return dma_ops->map_sg(hwdev, sg, nents, direction);
+       return ops->map_sg(hwdev, sg, nents, direction);
 }
 
 static inline void
 dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
             int direction)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(hwdev);
+
        BUG_ON(!valid_dma_direction(direction));
-       if (dma_ops->unmap_sg)
-               dma_ops->unmap_sg(hwdev, sg, nents, direction);
+       if (ops->unmap_sg)
+               ops->unmap_sg(hwdev, sg, nents, direction);
 }
 
 static inline void
 dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
                        size_t size, int direction)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(hwdev);
+
        BUG_ON(!valid_dma_direction(direction));
-       if (dma_ops->sync_single_for_cpu)
-               dma_ops->sync_single_for_cpu(hwdev, dma_handle, size,
-                                            direction);
+       if (ops->sync_single_for_cpu)
+               ops->sync_single_for_cpu(hwdev, dma_handle, size, direction);
        flush_write_buffers();
 }
 
@@ -128,10 +156,11 @@ static inline void
 dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
                           size_t size, int direction)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(hwdev);
+
        BUG_ON(!valid_dma_direction(direction));
-       if (dma_ops->sync_single_for_device)
-               dma_ops->sync_single_for_device(hwdev, dma_handle, size,
-                                               direction);
+       if (ops->sync_single_for_device)
+               ops->sync_single_for_device(hwdev, dma_handle, size, direction);
        flush_write_buffers();
 }
 
@@ -139,11 +168,12 @@ static inline void
 dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
                              unsigned long offset, size_t size, int direction)
 {
-       BUG_ON(!valid_dma_direction(direction));
-       if (dma_ops->sync_single_range_for_cpu)
-               dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset,
-                                                  size, direction);
+       struct dma_mapping_ops *ops = get_dma_ops(hwdev);
 
+       BUG_ON(!valid_dma_direction(direction));
+       if (ops->sync_single_range_for_cpu)
+               ops->sync_single_range_for_cpu(hwdev, dma_handle, offset,
+                                              size, direction);
        flush_write_buffers();
 }
 
@@ -152,11 +182,12 @@ dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
                                 unsigned long offset, size_t size,
                                 int direction)
 {
-       BUG_ON(!valid_dma_direction(direction));
-       if (dma_ops->sync_single_range_for_device)
-               dma_ops->sync_single_range_for_device(hwdev, dma_handle,
-                                                     offset, size, direction);
+       struct dma_mapping_ops *ops = get_dma_ops(hwdev);
 
+       BUG_ON(!valid_dma_direction(direction));
+       if (ops->sync_single_range_for_device)
+               ops->sync_single_range_for_device(hwdev, dma_handle,
+                                                 offset, size, direction);
        flush_write_buffers();
 }
 
@@ -164,9 +195,11 @@ static inline void
 dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
                    int nelems, int direction)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(hwdev);
+
        BUG_ON(!valid_dma_direction(direction));
-       if (dma_ops->sync_sg_for_cpu)
-               dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
+       if (ops->sync_sg_for_cpu)
+               ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
        flush_write_buffers();
 }
 
@@ -174,9 +207,11 @@ static inline void
 dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
                       int nelems, int direction)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(hwdev);
+
        BUG_ON(!valid_dma_direction(direction));
-       if (dma_ops->sync_sg_for_device)
-               dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction);
+       if (ops->sync_sg_for_device)
+               ops->sync_sg_for_device(hwdev, sg, nelems, direction);
 
        flush_write_buffers();
 }
@@ -185,9 +220,11 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
                                      size_t offset, size_t size,
                                      int direction)
 {
+       struct dma_mapping_ops *ops = get_dma_ops(dev);
+
        BUG_ON(!valid_dma_direction(direction));
-       return dma_ops->map_single(dev, page_to_phys(page)+offset,
-                                  size, direction);
+       return ops->map_single(dev, page_to_phys(page) + offset,
+                              size, direction);
 }
 
 static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
@@ -212,25 +249,5 @@ static inline int dma_get_cache_alignment(void)
 
 #define dma_is_consistent(d, h)        (1)
 
-#ifdef CONFIG_X86_32
-#  define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
-struct dma_coherent_mem {
-       void            *virt_base;
-       u32             device_base;
-       int             size;
-       int             flags;
-       unsigned long   *bitmap;
-};
-
-extern int
-dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
-                           dma_addr_t device_addr, size_t size, int flags);
-
-extern void
-dma_release_declared_memory(struct device *dev);
-
-extern void *
-dma_mark_declared_memory_occupied(struct device *dev,
-                                 dma_addr_t device_addr, size_t size);
-#endif /* CONFIG_X86_32 */
+#include <asm-generic/dma-coherent.h>
 #endif
index ff87fca0caf9e60f416f7097653c7dfcfd898d06..c4c91b37c104810433f074c396ca3bbc0e69c701 100644 (file)
@@ -1,6 +1,56 @@
+/*
+ * Generic GPIO API implementation for x86.
+ *
+ * Derived from the generic GPIO API for powerpc:
+ *
+ * Copyright (c) 2007-2008  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.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.
+ */
+
 #ifndef _ASM_I386_GPIO_H
 #define _ASM_I386_GPIO_H
 
-#include <gpio.h>
+#include <asm-generic/gpio.h>
+
+#ifdef CONFIG_GPIOLIB
+
+/*
+ * Just call gpiolib.
+ */
+static inline int gpio_get_value(unsigned int gpio)
+{
+       return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+       __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+       return __gpio_cansleep(gpio);
+}
+
+/*
+ * Not implemented, yet.
+ */
+static inline int gpio_to_irq(unsigned int gpio)
+{
+       return -ENOSYS;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+       return -EINVAL;
+}
+
+#endif /* CONFIG_GPIOLIB */
 
 #endif /* _ASM_I386_GPIO_H */
index 14171a4924f695b1634ad0a322ae6a2813d8adc6..439a9acc132d10f77b469fc24b250f3acc2f51d9 100644 (file)
@@ -14,11 +14,13 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
  * If the arch doesn't supply something else, assume that hugepage
  * size aligned regions are ok without further preparation.
  */
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+                       unsigned long addr, unsigned long len)
 {
-       if (len & ~HPAGE_MASK)
+       struct hstate *h = hstate_file(file);
+       if (len & ~huge_page_mask(h))
                return -EINVAL;
-       if (addr & ~HPAGE_MASK)
+       if (addr & ~huge_page_mask(h))
                return -EINVAL;
        return 0;
 }
@@ -26,7 +28,7 @@ static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
 static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) {
 }
 
-static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
                                          unsigned long addr, unsigned long end,
                                          unsigned long floor,
                                          unsigned long ceiling)
index 37672f79dcc8f3c879e7899f31868d7d06c2e0ae..96fa8449ff11de8dcf4926f3ac541286597168d3 100644 (file)
@@ -137,60 +137,6 @@ static inline void __save_init_fpu(struct task_struct *tsk)
        task_thread_info(tsk)->status &= ~TS_USEDFPU;
 }
 
-/*
- * Signal frame handlers.
- */
-
-static inline int save_i387(struct _fpstate __user *buf)
-{
-       struct task_struct *tsk = current;
-       int err = 0;
-
-       BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
-                       sizeof(tsk->thread.xstate->fxsave));
-
-       if ((unsigned long)buf % 16)
-               printk("save_i387: bad fpstate %p\n", buf);
-
-       if (!used_math())
-               return 0;
-       clear_used_math(); /* trigger finit */
-       if (task_thread_info(tsk)->status & TS_USEDFPU) {
-               err = save_i387_checking((struct i387_fxsave_struct __user *)
-                                        buf);
-               if (err)
-                       return err;
-               task_thread_info(tsk)->status &= ~TS_USEDFPU;
-               stts();
-       } else {
-               if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
-                                  sizeof(struct i387_fxsave_struct)))
-                       return -1;
-       }
-       return 1;
-}
-
-/*
- * This restores directly out of user space. Exceptions are handled.
- */
-static inline int restore_i387(struct _fpstate __user *buf)
-{
-       struct task_struct *tsk = current;
-       int err;
-
-       if (!used_math()) {
-               err = init_fpu(tsk);
-               if (err)
-                       return err;
-       }
-
-       if (!(task_thread_info(current)->status & TS_USEDFPU)) {
-               clts();
-               task_thread_info(current)->status |= TS_USEDFPU;
-       }
-       return restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
-}
-
 #else  /* CONFIG_X86_32 */
 
 extern void finit(void);
diff --git a/include/asm-x86/ide.h b/include/asm-x86/ide.h
deleted file mode 100644 (file)
index cf9c98e..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
- */
-
-/*
- *  This file contains the i386 architecture specific IDE code.
- */
-
-#ifndef __ASMi386_IDE_H
-#define __ASMi386_IDE_H
-
-#ifdef __KERNEL__
-
-
-#ifndef MAX_HWIFS
-# ifdef CONFIG_BLK_DEV_IDEPCI
-#define MAX_HWIFS      10
-# else
-#define MAX_HWIFS      6
-# endif
-#endif
-
-static __inline__ int ide_default_irq(unsigned long base)
-{
-       switch (base) {
-               case 0x1f0: return 14;
-               case 0x170: return 15;
-               case 0x1e8: return 11;
-               case 0x168: return 10;
-               case 0x1e0: return 8;
-               case 0x160: return 12;
-               default:
-                       return 0;
-       }
-}
-
-static __inline__ unsigned long ide_default_io_base(int index)
-{
-       /*
-        *      If PCI is present then it is not safe to poke around
-        *      the other legacy IDE ports. Only 0x1f0 and 0x170 are
-        *      defined compatibility mode ports for PCI. A user can 
-        *      override this using ide= but we must default safe.
-        */
-       if (no_pci_devices()) {
-               switch(index) {
-                       case 2: return 0x1e8;
-                       case 3: return 0x168;
-                       case 4: return 0x1e0;
-                       case 5: return 0x160;
-               }
-       }
-       switch (index) {
-               case 0: return 0x1f0;
-               case 1: return 0x170;
-               default:
-                       return 0;
-       }
-}
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASMi386_IDE_H */
index 4df44ed54077453db66bcd1f2a31f10d3519e97c..e876d89ac15618f88ea4b624de64c6b1fc27e9cd 100644 (file)
@@ -110,6 +110,8 @@ static inline void *phys_to_virt(unsigned long address)
  */
 extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
 extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
+extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
+                               unsigned long prot_val);
 
 /*
  * The default ioremap() behavior is non-cached:
index ddd8058a50267766cb398984220462589ee6d362..22995c5c5adc0d001bb40730fbeb15d47951ff01 100644 (file)
@@ -175,6 +175,8 @@ extern void early_iounmap(void *addr, unsigned long size);
  */
 extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
 extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
+extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
+                               unsigned long prot_val);
 
 /*
  * The default ioremap() behavior is non-cached:
index d63166fb3ab705a3e294b0b5f4c75bd544d17411..ecc8061904a9ee27210d27efd74dfe4534212fb6 100644 (file)
@@ -3,6 +3,7 @@
 
 extern void pci_iommu_shutdown(void);
 extern void no_iommu_init(void);
+extern struct dma_mapping_ops nommu_dma_ops;
 extern int force_iommu, no_iommu;
 extern int iommu_detected;
 
index 8f855a15f64d357e945e72b853a5c1d6db13c284..c0e52a14fd4dd981ee36ea66484f7f564b40bd04 100644 (file)
 # define VA_PTE_0              5
 # define PA_PTE_1              6
 # define VA_PTE_1              7
+# define PA_SWAP_PAGE          8
 # ifdef CONFIG_X86_PAE
-#  define PA_PMD_0             8
-#  define VA_PMD_0             9
-#  define PA_PMD_1             10
-#  define VA_PMD_1             11
-#  define PAGES_NR             12
+#  define PA_PMD_0             9
+#  define VA_PMD_0             10
+#  define PA_PMD_1             11
+#  define VA_PMD_1             12
+#  define PAGES_NR             13
 # else
-#  define PAGES_NR             8
+#  define PAGES_NR             9
 # endif
 #else
 # define PA_CONTROL_PAGE       0
@@ -152,11 +153,12 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
 }
 
 #ifdef CONFIG_X86_32
-asmlinkage NORET_TYPE void
+asmlinkage unsigned long
 relocate_kernel(unsigned long indirection_page,
                unsigned long control_page,
                unsigned long start_address,
-               unsigned int has_pae) ATTRIB_NORET;
+               unsigned int has_pae,
+               unsigned int preserve_context);
 #else
 NORET_TYPE void
 relocate_kernel(unsigned long indirection_page,
index fdde0bedaa90dd310e60862a52ef8a73f09a2f47..bc34dc21f178a0381441f49a580e788df7d8d2cd 100644 (file)
@@ -556,6 +556,7 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu);
 int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code);
 
 void kvm_enable_tdp(void);
+void kvm_disable_tdp(void);
 
 int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
 int complete_pio(struct kvm_vcpu *vcpu);
index 75d2c95005d74b8eab2c2fce764dfc925f5aa876..c47e2ab5c5ca06515c87b7a320e42fccff3e8ed2 100644 (file)
@@ -122,7 +122,7 @@ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_id_map)
 
 static inline physid_mask_t apicid_to_cpu_present(int apicid)
 {
-       return physid_mask_of_physid(0);
+       return physid_mask_of_physid(apicid);
 }
 
 static inline void setup_portio_remap(void)
diff --git a/include/asm-x86/namei.h b/include/asm-x86/namei.h
deleted file mode 100644 (file)
index 415ef5d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_X86_NAMEI_H
-#define _ASM_X86_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* _ASM_X86_NAMEI_H */
index 6c846228948d54f739ca59385ea647b521e39f32..49982110e4d94e4025896a6c05d7fddecca382ae 100644 (file)
@@ -32,8 +32,7 @@
 #define HPAGE_MASK             (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+#define HUGE_MAX_HSTATE 2
 
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
index fbbde93f12d6d5ad0aaca4fb1e6db0860cb5a351..db9b0647b346e87ce6eb9f31567ebe8017e47a57 100644 (file)
@@ -124,6 +124,9 @@ struct pv_cpu_ops {
                                int entrynum, const void *desc, int size);
        void (*write_idt_entry)(gate_desc *,
                                int entrynum, const gate_desc *gate);
+       void (*alloc_ldt)(struct desc_struct *ldt, unsigned entries);
+       void (*free_ldt)(struct desc_struct *ldt, unsigned entries);
+
        void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);
 
        void (*set_iopl_mask)(unsigned mask);
@@ -824,6 +827,16 @@ do {                                                       \
        (aux) = __aux;                                  \
 } while (0)
 
+static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries)
+{
+       PVOP_VCALL2(pv_cpu_ops.alloc_ldt, ldt, entries);
+}
+
+static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
+{
+       PVOP_VCALL2(pv_cpu_ops.free_ldt, ldt, entries);
+}
+
 static inline void load_TR_desc(void)
 {
        PVOP_VCALL0(pv_cpu_ops.load_tr_desc);
index 3e5dbc4195f4f71fc61ee906fbcc8f8dec0beb79..04caa2f544df4dc8c1d7798498b39d7896db1eb9 100644 (file)
@@ -18,6 +18,7 @@
 #define _PAGE_BIT_UNUSED2      10
 #define _PAGE_BIT_UNUSED3      11
 #define _PAGE_BIT_PAT_LARGE    12      /* On 2MB or 1GB pages */
+#define _PAGE_BIT_SPECIAL      _PAGE_BIT_UNUSED1
 #define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
 
 #define _PAGE_PRESENT  (_AT(pteval_t, 1) << _PAGE_BIT_PRESENT)
@@ -34,6 +35,8 @@
 #define _PAGE_UNUSED3  (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
 #define _PAGE_PAT      (_AT(pteval_t, 1) << _PAGE_BIT_PAT)
 #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
+#define _PAGE_SPECIAL  (_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
+#define __HAVE_ARCH_PTE_SPECIAL
 
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
 #define _PAGE_NX       (_AT(pteval_t, 1) << _PAGE_BIT_NX)
@@ -54,7 +57,7 @@
 
 /* Set of bits not changed in pte_modify */
 #define _PAGE_CHG_MASK (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT |         \
-                        _PAGE_ACCESSED | _PAGE_DIRTY)
+                        _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY)
 
 #define _PAGE_CACHE_MASK       (_PAGE_PCD | _PAGE_PWT)
 #define _PAGE_CACHE_WB         (0)
@@ -180,7 +183,7 @@ static inline int pte_exec(pte_t pte)
 
 static inline int pte_special(pte_t pte)
 {
-       return 0;
+       return pte_val(pte) & _PAGE_SPECIAL;
 }
 
 static inline int pmd_large(pmd_t pte)
@@ -246,7 +249,7 @@ static inline pte_t pte_clrglobal(pte_t pte)
 
 static inline pte_t pte_mkspecial(pte_t pte)
 {
-       return pte;
+       return __pte(pte_val(pte) | _PAGE_SPECIAL);
 }
 
 extern pteval_t __supported_pte_mask;
index 092b39b3a7e691588de38e4b3a44f2cf76f5051e..eff2ecd7fff067caf89bc48cd81bebe111a43363 100644 (file)
 #define CX86_ARR_BASE  0xc4
 #define CX86_RCR_BASE  0xdc
 
+#ifdef __KERNEL__
 #ifdef CONFIG_VM86
 #define X86_VM_MASK    X86_EFLAGS_VM
 #else
 #define X86_VM_MASK    0 /* No VM86 support */
 #endif
+#endif
 
 #endif /* __ASM_I386_PROCESSOR_FLAGS_H */
diff --git a/include/asm-x86/semaphore.h b/include/asm-x86/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index c706a7442633f1f3fdf051598f06326157d51b7a..2730b351afcf2422695ca176cf8a7edbee57b9cc 100644 (file)
@@ -35,7 +35,7 @@ extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
                          int nents, int direction);
 extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
                             int nents, int direction);
-extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
+extern int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
 extern void swiotlb_free_coherent(struct device *hwdev, size_t size,
                                  void *vaddr, dma_addr_t dma_handle);
 extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
index 3f2de10509884c9ff917b9653855ca34cce45a06..da0a675adf94a1a753792d1bca54c45d4fe3bed4 100644 (file)
@@ -152,6 +152,8 @@ struct thread_info {
 #define THREAD_FLAGS GFP_KERNEL
 #endif
 
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
 #define alloc_thread_info(tsk)                                         \
        ((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER))
 
index f6fa4d841bbcd3cbd552bb205c84facc688bf050..5f702d1d52184424941d3238ee82597c9f05ce37 100644 (file)
@@ -451,3 +451,4 @@ extern struct movsl_mask {
 #endif
 
 #endif
+
index 8317d94771d32622dad406f68d84f77e0823628d..d7394673b772442677ed3ec7063a4ea384ad7b62 100644 (file)
 #define __NR_fallocate         324
 #define __NR_timerfd_settime   325
 #define __NR_timerfd_gettime   326
+#define __NR_signalfd4         327
+#define __NR_eventfd2          328
+#define __NR_epoll_create1     329
+#define __NR_dup3              330
+#define __NR_pipe2             331
+#define __NR_inotify_init1     332
 
 #ifdef __KERNEL__
 
index 9c1a4a3470d96441d4bd194d12ff5541b321d135..3a341d791792ad41999893f7034e529cce28e880 100644 (file)
@@ -639,6 +639,20 @@ __SYSCALL(__NR_fallocate, sys_fallocate)
 __SYSCALL(__NR_timerfd_settime, sys_timerfd_settime)
 #define __NR_timerfd_gettime                   287
 __SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime)
+#define __NR_paccept                           288
+__SYSCALL(__NR_paccept, sys_paccept)
+#define __NR_signalfd4                         289
+__SYSCALL(__NR_signalfd4, sys_signalfd4)
+#define __NR_eventfd2                          290
+__SYSCALL(__NR_eventfd2, sys_eventfd2)
+#define __NR_epoll_create1                     291
+__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
+#define __NR_dup3                              292
+__SYSCALL(__NR_dup3, sys_dup3)
+#define __NR_pipe2                             293
+__SYSCALL(__NR_pipe2, sys_pipe2)
+#define __NR_inotify_init1                     294
+__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
 
 
 #ifndef __NO_STUBS
index 3c7d537dd15d36a775cbe098f9948be8a5c680bf..51882ae3db4d18ceb3a1536745d55ca00948ea65 100644 (file)
@@ -139,7 +139,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
                consistent_sync(sg_virt(sg), sg->length, dir);
 }
 static inline int
-dma_mapping_error(dma_addr_t dma_addr)
+dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        return 0;
 }
diff --git a/include/asm-xtensa/ide.h b/include/asm-xtensa/ide.h
deleted file mode 100644 (file)
index 6b91274..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * include/asm-xtensa/ide.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 1996  Linus Torvalds & authors
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_IDE_H
-#define _XTENSA_IDE_H
-
-#ifdef __KERNEL__
-
-
-#ifndef MAX_HWIFS
-# define MAX_HWIFS     1
-#endif
-
-static __inline__ int ide_default_irq(unsigned long base)
-{
-       /* Unsupported! */
-       return 0;
-}
-
-static __inline__ unsigned long ide_default_io_base(int index)
-{
-       /* Unsupported! */
-       return 0;
-}
-
-#endif /* __KERNEL__ */
-#endif /* _XTENSA_IDE_H */
diff --git a/include/asm-xtensa/kvm.h b/include/asm-xtensa/kvm.h
deleted file mode 100644 (file)
index bda4e33..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_XTENSA_H
-#define __LINUX_KVM_XTENSA_H
-
-/* xtensa does not support KVM */
-
-#endif
diff --git a/include/asm-xtensa/namei.h b/include/asm-xtensa/namei.h
deleted file mode 100644 (file)
index 3fdff03..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-xtensa/namei.h
- *
- * Included from linux/fs/namei.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.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_NAMEI_H
-#define _XTENSA_NAMEI_H
-
-#ifdef __KERNEL__
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __KERNEL__ */
-#endif /* _XTENSA_NAMEI_H */
index 80a6ae0dd25957e548d53b4c3e125f32df042ba9..11f7dc2dbec769f4ed5dd4233a6bc787d983556e 100644 (file)
 
 /*
  * PAGE_SHIFT determines the page size
- * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
  */
 
 #define PAGE_SHIFT             12
 #define PAGE_SIZE              (__XTENSA_UL_CONST(1) << PAGE_SHIFT)
 #define PAGE_MASK              (~(PAGE_SIZE-1))
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
 
 #define PAGE_OFFSET            XCHAL_KSEG_CACHED_VADDR
 #define MAX_MEM_PFN            XCHAL_KSEG_SIZE
index 422c73e26937de34f292a387b1b48360ae702932..089b0db44816f30242a1c6b1db18e1da651855b1 100644 (file)
 #define PTRACE_GETXTREGS       18
 #define PTRACE_SETXTREGS       19
 
-#ifndef __ASSEMBLY__
-
 #ifdef __KERNEL__
 
+#ifndef __ASSEMBLY__
+
 /*
  * This struct defines the way the registers are stored on the
  * kernel stack during a system call or other kernel entry.
@@ -122,14 +122,14 @@ extern void show_regs(struct pt_regs *);
 # ifndef CONFIG_SMP
 #  define profile_pc(regs) instruction_pointer(regs)
 # endif
-#endif /* __KERNEL__ */
 
 #else  /* __ASSEMBLY__ */
 
-#ifdef __KERNEL__
 # include <asm/asm-offsets.h>
 #define PT_REGS_OFFSET   (KERNEL_STACK_SIZE - PT_USER_SIZE)
-#endif
 
 #endif /* !__ASSEMBLY__ */
+
+#endif  /* __KERNEL__ */
+
 #endif /* _XTENSA_PTRACE_H */
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
deleted file mode 100644 (file)
index d9b2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
index a2c640682ed94f05f030a6b07b968456b7a294ac..7e4131dd546c5d62655b12fc89460a5e44b31a82 100644 (file)
@@ -111,10 +111,6 @@ static inline struct thread_info *current_thread_info(void)
        return ti;
 }
 
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-
 #else /* !__ASSEMBLY__ */
 
 /* how to get the thread information struct from ASM */
@@ -160,6 +156,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TS_USEDFPU             0x0001  /* FPU was used by this task this quantum (SMP) */
 
 #define THREAD_SIZE 8192       //(2*PAGE_SIZE)
+#define THREAD_SIZE_ORDER 1
 
 #endif /* __KERNEL__ */
 #endif /* _XTENSA_THREAD_INFO */
index 71d70d1fbce280585d575ba3f131847c0da19cd8..4c4142c5aa6ef26839e4acceb8bcb8b009bf5861 100644 (file)
@@ -189,7 +189,6 @@ unifdef-y += connector.h
 unifdef-y += cuda.h
 unifdef-y += cyclades.h
 unifdef-y += dccp.h
-unifdef-y += dirent.h
 unifdef-y += dlm.h
 unifdef-y += dlm_plock.h
 unifdef-y += edd.h
@@ -256,7 +255,9 @@ unifdef-y += kd.h
 unifdef-y += kernelcapi.h
 unifdef-y += kernel.h
 unifdef-y += keyboard.h
+ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),)
 unifdef-y += kvm.h
+endif
 unifdef-y += llc.h
 unifdef-y += loop.h
 unifdef-y += lp.h
index e8cae54e8d88b9116d4813771978f2acecc58bf2..882dc7248766367bb451e283e6cbb6b2936cbc3c 100644 (file)
@@ -120,17 +120,20 @@ struct acct_v3
 struct vfsmount;
 struct super_block;
 struct pacct_struct;
+struct pid_namespace;
 extern void acct_auto_close_mnt(struct vfsmount *m);
 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_exit_ns(struct pid_namespace *);
 #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_exit_ns(ns)       do { } while (0)
 #endif
 
 /*
index a171776393767ab0e23411c4ff2d8a89f15676e2..702f79dad16a98a3638957bf64423c5b128423ce 100644 (file)
@@ -236,6 +236,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
                      const char *name);
 
 #ifdef CONFIG_PM_SLEEP
+void __init acpi_no_s4_hw_signature(void);
 void __init acpi_old_suspend_ordering(void);
 #endif /* CONFIG_PM_SLEEP */
 #else  /* CONFIG_ACPI */
index b51ddd28444e38763e7066ed36ffa9a3a2b6b355..09b276c35227f43ef120d3e729dc0d27f68e303e 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/uio.h>
 
 #include <asm/atomic.h>
-#include <linux/uio.h>
 
 #define AIO_MAXSEGS            4
 #define AIO_KIOGRP_NR_ATOMIC   8
index 6129e58ca7c99407716acbf6482e2d02d09956e9..e0a0cdc2da43c6e21fdb6656dd33cd1ed12d4dec 100644 (file)
@@ -9,7 +9,7 @@
 #define _LINUX_ANON_INODES_H
 
 int anon_inode_getfd(const char *name, const struct file_operations *fops,
-                    void *priv);
+                    void *priv, int flags);
 
 #endif /* _LINUX_ANON_INODES_H */
 
diff --git a/include/linux/atmel-pwm-bl.h b/include/linux/atmel-pwm-bl.h
new file mode 100644 (file)
index 0000000..0153a47
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * Driver for the AT32AP700X PS/2 controller (PSIF).
+ *
+ * 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 __INCLUDE_ATMEL_PWM_BL_H
+#define __INCLUDE_ATMEL_PWM_BL_H
+
+/**
+ * struct atmel_pwm_bl_platform_data
+ * @pwm_channel: which PWM channel in the PWM module to use.
+ * @pwm_frequency: PWM frequency to generate, the driver will try to be as
+ *     close as the prescaler allows.
+ * @pwm_compare_max: value to use in the PWM channel compare register.
+ * @pwm_duty_max: maximum duty cycle value, must be less than or equal to
+ *     pwm_compare_max.
+ * @pwm_duty_min: minimum duty cycle value, must be less than pwm_duty_max.
+ * @pwm_active_low: set to one if the low part of the PWM signal increases the
+ *     brightness of the backlight.
+ * @gpio_on: GPIO line to control the backlight on/off, set to -1 if not used.
+ * @on_active_low: set to one if the on/off signal is on when GPIO is low.
+ *
+ * This struct must be added to the platform device in the board code. It is
+ * used by the atmel-pwm-bl driver to setup the GPIO to control on/off and the
+ * PWM device.
+ */
+struct atmel_pwm_bl_platform_data {
+       unsigned int pwm_channel;
+       unsigned int pwm_frequency;
+       unsigned int pwm_compare_max;
+       unsigned int pwm_duty_max;
+       unsigned int pwm_duty_min;
+       unsigned int pwm_active_low;
+       int gpio_on;
+       unsigned int on_active_low;
+};
+
+#endif /* __INCLUDE_ATMEL_PWM_BL_H */
index 8b82974bdc125b561bf156a1dbfa58d3a51e3751..6272a395d43c0b73a6ef4fd5d0a19062d6154a38 100644 (file)
 #define AUDIT_ARCH_SHEL64      (EM_SH|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_SPARC       (EM_SPARC)
 #define AUDIT_ARCH_SPARC64     (EM_SPARCV9|__AUDIT_ARCH_64BIT)
-#define AUDIT_ARCH_V850                (EM_V850|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_X86_64      (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
 
 #define AUDIT_PERM_EXEC                1
index 31a29541b504234174c0a9678bba9b60bc60e7ac..b785c6f8644dc28ca92793f96c31ab0b53ab4c85 100644 (file)
@@ -98,8 +98,6 @@ union autofs_v5_packet_union {
 #define AUTOFS_IOC_EXPIRE_INDIRECT     AUTOFS_IOC_EXPIRE_MULTI
 #define AUTOFS_IOC_EXPIRE_DIRECT       AUTOFS_IOC_EXPIRE_MULTI
 #define AUTOFS_IOC_PROTOSUBVER         _IOR(0x93,0x67,int)
-#define AUTOFS_IOC_ASKREGHOST           _IOR(0x93,0x68,int)
-#define AUTOFS_IOC_TOGGLEREGHOST        _IOR(0x93,0x69,int)
 #define AUTOFS_IOC_ASKUMOUNT           _IOR(0x93,0x70,int)
 
 
index 0da17d14fd139f548cc18c3076a8390a8089918f..d7afa9dd6635cc812a87d8b6b291c3fd2419f095 100644 (file)
 
 #define AT_SECURE 23   /* secure mode boolean */
 
+#define AT_BASE_PLATFORM 24    /* string identifying real platform, may
+                                * differ from AT_PLATFORM. */
+
 #define AT_EXECFN  31  /* filename of program */
+
 #ifdef __KERNEL__
-#define AT_VECTOR_SIZE_BASE 17 /* NEW_AUX_ENT entries in auxiliary table */
+#define AT_VECTOR_SIZE_BASE 18 /* NEW_AUX_ENT entries in auxiliary table */
   /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */
 #endif
 
index c545308125b0904a070e3cccd611f83ff37b71e1..7ac518e3c152d9da46f53ed097adb3019245dd5f 100644 (file)
 #ifndef _BCD_H
 #define _BCD_H
 
-#define BCD2BIN(val)   (((val) & 0x0f) + ((val)>>4)*10)
-#define BIN2BCD(val)   ((((val)/10)<<4) + (val)%10)
+#include <linux/compiler.h>
+
+unsigned bcd2bin(unsigned char val) __attribute_const__;
+unsigned char bin2bcd(unsigned val) __attribute_const__;
+
+#define BCD2BIN(val)   bcd2bin(val)
+#define BIN2BCD(val)   bin2bcd(val)
 
 /* backwards compat */
 #define BCD_TO_BIN(val) ((val)=BCD2BIN(val))
index ee0ed48e834809778a946343d6840e446eb9f2b7..826f62350805ed782976008db013203061306744 100644 (file)
@@ -38,7 +38,7 @@ struct linux_binprm{
                     misc_bang:1;
        struct file * file;
        int e_uid, e_gid;
-       kernel_cap_t cap_inheritable, cap_permitted;
+       kernel_cap_t cap_post_exec_permitted;
        bool cap_effective;
        void *security;
        int argc, envc;
index a1d9b79078ea03425cb1ce4ae8746daf01c46fd5..652470b687c9533f09fc8829d829f3d8fa768b6b 100644 (file)
@@ -28,52 +28,73 @@ extern unsigned long saved_max_pfn;
  * memory pages (including holes) on the node.
  */
 typedef struct bootmem_data {
-       unsigned long node_boot_start;
+       unsigned long node_min_pfn;
        unsigned long node_low_pfn;
        void *node_bootmem_map;
-       unsigned long last_offset;
-       unsigned long last_pos;
-       unsigned long last_success;     /* Previous allocation point.  To speed
-                                        * up searching */
+       unsigned long last_end_off;
+       unsigned long hint_idx;
        struct list_head list;
 } bootmem_data_t;
 
+extern bootmem_data_t bootmem_node_data[];
+
 extern unsigned long bootmem_bootmap_pages(unsigned long);
+
+extern unsigned long init_bootmem_node(pg_data_t *pgdat,
+                                      unsigned long freepfn,
+                                      unsigned long startpfn,
+                                      unsigned long endpfn);
 extern unsigned long init_bootmem(unsigned long addr, unsigned long memend);
+
+extern unsigned long free_all_bootmem_node(pg_data_t *pgdat);
+extern unsigned long free_all_bootmem(void);
+
+extern void free_bootmem_node(pg_data_t *pgdat,
+                             unsigned long addr,
+                             unsigned long size);
 extern void free_bootmem(unsigned long addr, unsigned long size);
-extern void *__alloc_bootmem(unsigned long size,
+
+/*
+ * Flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE,
+ * the architecture-specific code should honor this).
+ *
+ * If flags is 0, then the return value is always 0 (success). If
+ * flags contains BOOTMEM_EXCLUSIVE, then -EBUSY is returned if the
+ * memory already was reserved.
+ */
+#define BOOTMEM_DEFAULT                0
+#define BOOTMEM_EXCLUSIVE      (1<<0)
+
+extern int reserve_bootmem_node(pg_data_t *pgdat,
+                                unsigned long physaddr,
+                                unsigned long size,
+                                int flags);
+#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
+extern int reserve_bootmem(unsigned long addr, unsigned long size, int flags);
+#endif
+
+extern void *__alloc_bootmem_nopanic(unsigned long size,
                             unsigned long align,
                             unsigned long goal);
-extern void *__alloc_bootmem_nopanic(unsigned long size,
+extern void *__alloc_bootmem(unsigned long size,
                                     unsigned long align,
                                     unsigned long goal);
 extern void *__alloc_bootmem_low(unsigned long size,
                                 unsigned long align,
                                 unsigned long goal);
+extern void *__alloc_bootmem_node(pg_data_t *pgdat,
+                                 unsigned long size,
+                                 unsigned long align,
+                                 unsigned long goal);
+extern void *__alloc_bootmem_node_nopanic(pg_data_t *pgdat,
+                                 unsigned long size,
+                                 unsigned long align,
+                                 unsigned long goal);
 extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
                                      unsigned long size,
                                      unsigned long align,
                                      unsigned long goal);
-extern void *__alloc_bootmem_core(struct bootmem_data *bdata,
-                                 unsigned long size,
-                                 unsigned long align,
-                                 unsigned long goal,
-                                 unsigned long limit);
-
-/*
- * flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE,
- * the architecture-specific code should honor this)
- */
-#define BOOTMEM_DEFAULT                0
-#define BOOTMEM_EXCLUSIVE      (1<<0)
-
 #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
-/*
- * If flags is 0, then the return value is always 0 (success). If
- * flags contains BOOTMEM_EXCLUSIVE, then -EBUSY is returned if the
- * memory already was reserved.
- */
-extern int reserve_bootmem(unsigned long addr, unsigned long size, int flags);
 #define alloc_bootmem(x) \
        __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_low(x) \
@@ -82,31 +103,6 @@ extern int reserve_bootmem(unsigned long addr, unsigned long size, int flags);
        __alloc_bootmem(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_low_pages(x) \
        __alloc_bootmem_low(x, PAGE_SIZE, 0)
-#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
-
-extern int reserve_bootmem_generic(unsigned long addr, unsigned long size,
-                                  int flags);
-extern unsigned long free_all_bootmem(void);
-extern unsigned long free_all_bootmem_node(pg_data_t *pgdat);
-extern void *__alloc_bootmem_node(pg_data_t *pgdat,
-                                 unsigned long size,
-                                 unsigned long align,
-                                 unsigned long goal);
-extern unsigned long init_bootmem_node(pg_data_t *pgdat,
-                                      unsigned long freepfn,
-                                      unsigned long startpfn,
-                                      unsigned long endpfn);
-extern int reserve_bootmem_node(pg_data_t *pgdat,
-                                unsigned long physaddr,
-                                unsigned long size,
-                                int flags);
-extern void free_bootmem_node(pg_data_t *pgdat,
-                             unsigned long addr,
-                             unsigned long size);
-extern void *alloc_bootmem_section(unsigned long size,
-                                  unsigned long section_nr);
-
-#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
 #define alloc_bootmem_node(pgdat, x) \
        __alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_pages_node(pgdat, x) \
@@ -115,6 +111,12 @@ extern void *alloc_bootmem_section(unsigned long size,
        __alloc_bootmem_low_node(pgdat, x, PAGE_SIZE, 0)
 #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 
+extern int reserve_bootmem_generic(unsigned long addr, unsigned long size,
+                                  int flags);
+
+extern void *alloc_bootmem_section(unsigned long size,
+                                  unsigned long section_nr);
+
 #ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP
 extern void *alloc_remap(int nid, unsigned long size);
 #else
index 82aa36c53ea7a38e413a384a646f241ef1ebaf1c..50cfe8ceb478508c3fd587fbe8109f0ad146259e 100644 (file)
@@ -205,6 +205,8 @@ void block_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*);
+int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
+                               unsigned long from);
 int block_write_begin(struct file *, struct address_space *,
                                loff_t, unsigned, unsigned,
                                struct page **, void **, get_block_t*);
index 961ed4b48d8eba1b7d72628cec0f65be7cacde32..44f95b92393b89b19186166232efa4a797f7314a 100644 (file)
@@ -94,12 +94,12 @@ static inline __u16 __be16_to_cpup(const __be16 *p)
 #define __le32_to_cpus(x) __swab32s((x))
 #define __cpu_to_le16s(x) __swab16s((x))
 #define __le16_to_cpus(x) __swab16s((x))
-#define __cpu_to_be64s(x) do {} while (0)
-#define __be64_to_cpus(x) do {} while (0)
-#define __cpu_to_be32s(x) do {} while (0)
-#define __be32_to_cpus(x) do {} while (0)
-#define __cpu_to_be16s(x) do {} while (0)
-#define __be16_to_cpus(x) do {} while (0)
+#define __cpu_to_be64s(x) do { (void)(x); } while (0)
+#define __be64_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_be32s(x) do { (void)(x); } while (0)
+#define __be32_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_be16s(x) do { (void)(x); } while (0)
+#define __be16_to_cpus(x) do { (void)(x); } while (0)
 
 #ifdef __KERNEL__
 #include <linux/byteorder/generic.h>
index 05dc7c35b3b21e93956f5c462f24a79305749aed..4cc170a3176219b69ab73bec0035c0868a0362a2 100644 (file)
@@ -88,12 +88,12 @@ static inline __u16 __be16_to_cpup(const __be16 *p)
 {
        return __swab16p((__u16 *)p);
 }
-#define __cpu_to_le64s(x) do {} while (0)
-#define __le64_to_cpus(x) do {} while (0)
-#define __cpu_to_le32s(x) do {} while (0)
-#define __le32_to_cpus(x) do {} while (0)
-#define __cpu_to_le16s(x) do {} while (0)
-#define __le16_to_cpus(x) do {} while (0)
+#define __cpu_to_le64s(x) do { (void)(x); } while (0)
+#define __le64_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_le32s(x) do { (void)(x); } while (0)
+#define __le32_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_le16s(x) do { (void)(x); } while (0)
+#define __le16_to_cpus(x) do { (void)(x); } while (0)
 #define __cpu_to_be64s(x) __swab64s((x))
 #define __be64_to_cpus(x) __swab64s((x))
 #define __cpu_to_be32s(x) __swab32s((x))
index e155aa78d8594eb545547f48f47c7b53bf9fc36a..c98dd7cb7076f44484a68643995f10fd1bbc2ff8 100644 (file)
 struct cgroupfs_root;
 struct cgroup_subsys;
 struct inode;
+struct cgroup;
 
 extern int cgroup_init_early(void);
 extern int cgroup_init(void);
 extern void cgroup_init_smp(void);
 extern void cgroup_lock(void);
+extern bool cgroup_lock_live_group(struct cgroup *cgrp);
 extern void cgroup_unlock(void);
 extern void cgroup_fork(struct task_struct *p);
 extern void cgroup_fork_callbacks(struct task_struct *p);
@@ -205,49 +207,63 @@ struct cftype {
         * subsystem, followed by a period */
        char name[MAX_CFTYPE_NAME];
        int private;
-       int (*open) (struct inode *inode, struct file *file);
-       ssize_t (*read) (struct cgroup *cgrp, struct cftype *cft,
-                        struct file *file,
-                        char __user *buf, size_t nbytes, loff_t *ppos);
+
+       /*
+        * If non-zero, defines the maximum length of string that can
+        * be passed to write_string; defaults to 64
+        */
+       size_t max_write_len;
+
+       int (*open)(struct inode *inode, struct file *file);
+       ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft,
+                       struct file *file,
+                       char __user *buf, size_t nbytes, loff_t *ppos);
        /*
         * read_u64() is a shortcut for the common case of returning a
         * single integer. Use it in place of read()
         */
-       u64 (*read_u64) (struct cgroup *cgrp, struct cftype *cft);
+       u64 (*read_u64)(struct cgroup *cgrp, struct cftype *cft);
        /*
         * read_s64() is a signed version of read_u64()
         */
-       s64 (*read_s64) (struct cgroup *cgrp, struct cftype *cft);
+       s64 (*read_s64)(struct cgroup *cgrp, struct cftype *cft);
        /*
         * read_map() is used for defining a map of key/value
         * pairs. It should call cb->fill(cb, key, value) for each
         * entry. The key/value pairs (and their ordering) should not
         * change between reboots.
         */
-       int (*read_map) (struct cgroup *cont, struct cftype *cft,
-                        struct cgroup_map_cb *cb);
+       int (*read_map)(struct cgroup *cont, struct cftype *cft,
+                       struct cgroup_map_cb *cb);
        /*
         * read_seq_string() is used for outputting a simple sequence
         * using seqfile.
         */
-       int (*read_seq_string) (struct cgroup *cont, struct cftype *cft,
-                        struct seq_file *m);
+       int (*read_seq_string)(struct cgroup *cont, struct cftype *cft,
+                              struct seq_file *m);
 
-       ssize_t (*write) (struct cgroup *cgrp, struct cftype *cft,
-                         struct file *file,
-                         const char __user *buf, size_t nbytes, loff_t *ppos);
+       ssize_t (*write)(struct cgroup *cgrp, struct cftype *cft,
+                        struct file *file,
+                        const char __user *buf, size_t nbytes, loff_t *ppos);
 
        /*
         * write_u64() is a shortcut for the common case of accepting
         * a single integer (as parsed by simple_strtoull) from
         * userspace. Use in place of write(); return 0 or error.
         */
-       int (*write_u64) (struct cgroup *cgrp, struct cftype *cft, u64 val);
+       int (*write_u64)(struct cgroup *cgrp, struct cftype *cft, u64 val);
        /*
         * write_s64() is a signed version of write_u64()
         */
-       int (*write_s64) (struct cgroup *cgrp, struct cftype *cft, s64 val);
+       int (*write_s64)(struct cgroup *cgrp, struct cftype *cft, s64 val);
 
+       /*
+        * write_string() is passed a nul-terminated kernelspace
+        * buffer of maximum length determined by max_write_len.
+        * Returns 0 or -ve error code.
+        */
+       int (*write_string)(struct cgroup *cgrp, struct cftype *cft,
+                           const char *buffer);
        /*
         * trigger() callback can be used to get some kick from the
         * userspace, when the actual string written is not important
@@ -256,7 +272,7 @@ struct cftype {
         */
        int (*trigger)(struct cgroup *cgrp, unsigned int event);
 
-       int (*release) (struct inode *inode, struct file *file);
+       int (*release)(struct inode *inode, struct file *file);
 };
 
 struct cgroup_scanner {
@@ -348,7 +364,8 @@ static inline struct cgroup* task_cgroup(struct task_struct *task,
        return task_subsys_state(task, subsys_id)->cgroup;
 }
 
-int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss);
+int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss,
+                                                       char *nodename);
 
 /* A cgroup_iter should be treated as an opaque object */
 struct cgroup_iter {
index b5cf0780c51a6a0e9ebc243a6053922572756f09..96c87693800ba1b0eaf46065f670b46fb4e3cbfc 100644 (file)
@@ -199,28 +199,6 @@ typedef u_int32_t vuid_t;
 typedef u_int32_t vgid_t;
 #endif /*_VUID_T_ */
 
-#ifdef CONFIG_CODA_FS_OLD_API
-struct CodaFid {
-       u_int32_t opaque[3];
-};
-
-static __inline__ ino_t  coda_f2i(struct CodaFid *fid)
-{
-       if ( ! fid ) 
-               return 0; 
-       if (fid->opaque[1] == 0xfffffffe || fid->opaque[1] == 0xffffffff)
-               return ((fid->opaque[0] << 20) | (fid->opaque[2] & 0xfffff));
-       else
-               return (fid->opaque[2] + (fid->opaque[1]<<10) + (fid->opaque[0]<<20));
-}
-
-struct coda_cred {
-    vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/
-    vgid_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */
-};
-
-#else /* not defined(CONFIG_CODA_FS_OLD_API) */
-
 struct CodaFid {
        u_int32_t opaque[4];
 };
@@ -228,8 +206,6 @@ struct CodaFid {
 #define coda_f2i(fid)\
        (fid ? (fid->opaque[3] ^ (fid->opaque[2]<<10) ^ (fid->opaque[1]<<20) ^ fid->opaque[0]) : 0)
 
-#endif
-
 #ifndef _VENUS_VATTR_T_
 #define _VENUS_VATTR_T_
 /*
@@ -313,15 +289,7 @@ struct coda_statfs {
 
 #define CIOC_KERNEL_VERSION _IOWR('c', 10, size_t)
 
-#if 0
-#define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */
-#define CODA_KERNEL_VERSION 1 /* The old venus 4.6 compatible interface */
-#endif
-#ifdef CONFIG_CODA_FS_OLD_API
-#define CODA_KERNEL_VERSION 2 /* venus_lookup got an extra parameter */
-#else
 #define CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */
-#endif
 
 /*
  *        Venus <-> Coda  RPC arguments
@@ -329,16 +297,9 @@ struct coda_statfs {
 struct coda_in_hdr {
     u_int32_t opcode;
     u_int32_t unique;      /* Keep multiple outstanding msgs distinct */
-#ifdef CONFIG_CODA_FS_OLD_API
-    u_int16_t pid;         /* Common to all */
-    u_int16_t pgid;        /* Common to all */
-    u_int16_t sid;          /* Common to all */
-    struct coda_cred cred;  /* Common to all */
-#else
     pid_t pid;
     pid_t pgid;
     vuid_t uid;
-#endif
 };
 
 /* Really important that opcode and unique are 1st two fields! */
@@ -613,11 +574,7 @@ struct coda_vget_out {
 /* CODA_PURGEUSER is a venus->kernel call */
 struct coda_purgeuser_out {
     struct coda_out_hdr oh;
-#ifdef CONFIG_CODA_FS_OLD_API
-    struct coda_cred cred;
-#else
     vuid_t uid;
-#endif
 };
 
 /* coda_zapfile: */
index 31b75311e2ca381bc4d12fef44f577919a7e57a5..dcc228aa335ae43b77febde77dbecf4d031773b4 100644 (file)
@@ -37,7 +37,7 @@ extern const struct file_operations coda_ioctl_operations;
 /* operations shared over more than one file */
 int coda_open(struct inode *i, struct file *f);
 int coda_release(struct inode *i, struct file *f);
-int coda_permission(struct inode *inode, int mask, struct nameidata *nd);
+int coda_permission(struct inode *inode, int mask);
 int coda_revalidate_inode(struct dentry *);
 int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int coda_setattr(struct dentry *, struct iattr *);
index e2bf7e5db39a513c650e1e422f024f31c0e6ed2d..c4811da1338b7c92546e5d0d0a48c8c4d8c9c7c6 100644 (file)
@@ -3,6 +3,9 @@
  *
  * Interface between console.c, selection.c  and consolemap.c
  */
+#ifndef __LINUX_CONSOLEMAP_H__
+#define __LINUX_CONSOLEMAP_H__
+
 #define LAT1_MAP 0
 #define GRAF_MAP 1
 #define IBMPC_MAP 2
@@ -10,6 +13,7 @@
 
 #include <linux/types.h>
 
+#ifdef CONFIG_CONSOLE_TRANSLATIONS
 struct vc_data;
 
 extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode);
@@ -18,3 +22,13 @@ extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
 extern u32 conv_8bit_to_uni(unsigned char c);
 extern int conv_uni_to_8bit(u32 uni);
 void console_map_init(void);
+#else
+#define inverse_translate(conp, glyph, uni) ((uint16_t)glyph)
+#define set_translate(m, vc) ((unsigned short *)NULL)
+#define conv_uni_to_pc(conp, ucs) ((int) (ucs > 0xff ? -1: ucs))
+#define conv_8bit_to_uni(c) ((uint32_t)(c))
+#define conv_uni_to_8bit(c) ((int) ((c) & 0xff))
+#define console_map_init(c) do { ; } while (0)
+#endif /* CONFIG_CONSOLE_TRANSLATIONS */
+
+#endif /* __LINUX_CONSOLEMAP_H__ */
index 7464ba3b4333980268d4af8e71318a0b27a37e9d..d7faf88084973c6a5bfbfca9fe717352b2e1e1a2 100644 (file)
@@ -69,10 +69,11 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb)
 #endif
 
 int cpu_up(unsigned int cpu);
-
 extern void cpu_hotplug_init(void);
+extern void cpu_maps_update_begin(void);
+extern void cpu_maps_update_done(void);
 
-#else
+#else  /* CONFIG_SMP */
 
 static inline int register_cpu_notifier(struct notifier_block *nb)
 {
@@ -87,10 +88,16 @@ static inline void cpu_hotplug_init(void)
 {
 }
 
+static inline void cpu_maps_update_begin(void)
+{
+}
+
+static inline void cpu_maps_update_done(void)
+{
+}
+
 #endif /* CONFIG_SMP */
 extern struct sysdev_class cpu_sysdev_class;
-extern void cpu_maps_update_begin(void);
-extern void cpu_maps_update_done(void);
 
 #ifdef CONFIG_HOTPLUG_CPU
 /* Stop CPUs going up and down. */
index 1b5c98e7fef79fffd94805cb1d8cfd9fdadb39f5..96d0509fb8d85a6ce9ba52842080df475fc1aef4 100644 (file)
  * int next_cpu_nr(cpu, mask)          Next cpu past 'cpu', or nr_cpu_ids
  *
  * cpumask_t cpumask_of_cpu(cpu)       Return cpumask with bit 'cpu' set
- *ifdef CONFIG_HAS_CPUMASK_OF_CPU
- * cpumask_of_cpu_ptr_declare(v)       Declares cpumask_t *v
- * cpumask_of_cpu_ptr_next(v, cpu)     Sets v = &cpumask_of_cpu_map[cpu]
- * cpumask_of_cpu_ptr(v, cpu)          Combines above two operations
- *else
- * cpumask_of_cpu_ptr_declare(v)       Declares cpumask_t _v and *v = &_v
- * cpumask_of_cpu_ptr_next(v, cpu)     Sets _v = cpumask_of_cpu(cpu)
- * cpumask_of_cpu_ptr(v, cpu)          Combines above two operations
- *endif
+ *                                     (can be used as an lvalue)
  * CPU_MASK_ALL                                Initializer - all bits set
  * CPU_MASK_NONE                       Initializer - no bits set
  * unsigned long *cpus_addr(mask)      Array of unsigned long's in mask
@@ -273,37 +265,30 @@ static inline void __cpus_shift_left(cpumask_t *dstp,
        bitmap_shift_left(dstp->bits, srcp->bits, n, nbits);
 }
 
+/*
+ * Special-case data structure for "single bit set only" constant CPU masks.
+ *
+ * We pre-generate all the 64 (or 32) possible bit positions, with enough
+ * padding to the left and the right, and return the constant pointer
+ * appropriately offset.
+ */
+extern const unsigned long
+       cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)];
+
+static inline const cpumask_t *get_cpu_mask(unsigned int cpu)
+{
+       const unsigned long *p = cpu_bit_bitmap[1 + cpu % BITS_PER_LONG];
+       p -= cpu / BITS_PER_LONG;
+       return (const cpumask_t *)p;
+}
+
+/*
+ * In cases where we take the address of the cpumask immediately,
+ * gcc optimizes it out (it's a constant) and there's no huge stack
+ * variable created:
+ */
+#define cpumask_of_cpu(cpu) ({ *get_cpu_mask(cpu); })
 
-#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
-extern cpumask_t *cpumask_of_cpu_map;
-#define cpumask_of_cpu(cpu)    (cpumask_of_cpu_map[cpu])
-#define        cpumask_of_cpu_ptr(v, cpu)                                      \
-               const cpumask_t *v = &cpumask_of_cpu(cpu)
-#define        cpumask_of_cpu_ptr_declare(v)                                   \
-               const cpumask_t *v
-#define cpumask_of_cpu_ptr_next(v, cpu)                                        \
-                                       v = &cpumask_of_cpu(cpu)
-#else
-#define cpumask_of_cpu(cpu)                                            \
-({                                                                     \
-       typeof(_unused_cpumask_arg_) m;                                 \
-       if (sizeof(m) == sizeof(unsigned long)) {                       \
-               m.bits[0] = 1UL<<(cpu);                                 \
-       } else {                                                        \
-               cpus_clear(m);                                          \
-               cpu_set((cpu), m);                                      \
-       }                                                               \
-       m;                                                              \
-})
-#define        cpumask_of_cpu_ptr(v, cpu)                                      \
-               cpumask_t _##v = cpumask_of_cpu(cpu);                   \
-               const cpumask_t *v = &_##v
-#define        cpumask_of_cpu_ptr_declare(v)                                   \
-               cpumask_t _##v;                                         \
-               const cpumask_t *v = &_##v
-#define cpumask_of_cpu_ptr_next(v, cpu)                                        \
-                                       _##v = cpumask_of_cpu(cpu)
-#endif
 
 #define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS)
 
index 22c7ac5cd80cbd18ec3aeb1da42cac0493af8078..025e4f5751034ac15139a704a63941a0f1d6dbce 100644 (file)
@@ -8,7 +8,13 @@
 #include <linux/proc_fs.h>
 
 #define ELFCORE_ADDR_MAX       (-1ULL)
+
+#ifdef CONFIG_PROC_VMCORE
 extern unsigned long long elfcorehdr_addr;
+#else
+static const unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+#endif
+
 extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
                                                unsigned long, int);
 extern const struct file_operations proc_vmcore_operations;
@@ -22,5 +28,13 @@ extern struct proc_dir_entry *proc_vmcore;
 
 #define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
 
+static inline int is_kdump_kernel(void)
+{
+       return (elfcorehdr_addr != ELFCORE_ADDR_MAX) ? 1 : 0;
+}
+#else /* !CONFIG_CRASH_DUMP */
+static inline int is_kdump_kernel(void) { return 0; }
 #endif /* CONFIG_CRASH_DUMP */
+
+extern unsigned long saved_max_pfn;
 #endif /* LINUX_CRASHDUMP_H */
index ab94bc083558c329c8a59e49ff3c7af6076627ca..f352f06fa063b2bd73543403a4e24aca39f4a9d1 100644 (file)
@@ -39,6 +39,8 @@ extern void __delayacct_blkio_start(void);
 extern void __delayacct_blkio_end(void);
 extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
 extern __u64 __delayacct_blkio_ticks(struct task_struct *);
+extern void __delayacct_freepages_start(void);
+extern void __delayacct_freepages_end(void);
 
 static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
 {
@@ -107,6 +109,18 @@ static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
        return 0;
 }
 
+static inline void delayacct_freepages_start(void)
+{
+       if (current->delays)
+               __delayacct_freepages_start();
+}
+
+static inline void delayacct_freepages_end(void)
+{
+       if (current->delays)
+               __delayacct_freepages_end();
+}
+
 #else
 static inline void delayacct_set_flag(int flag)
 {}
@@ -129,6 +143,11 @@ static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
 { return 0; }
 static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
 { return 0; }
+static inline void delayacct_freepages_start(void)
+{}
+static inline void delayacct_freepages_end(void)
+{}
+
 #endif /* CONFIG_TASK_DELAY_ACCT */
 
 #endif
index 5d6023b878003e65d5547f17faf4aea45fde89b4..f072fb8d10a3268b402323c91b40be250872726a 100644 (file)
@@ -1,23 +1,6 @@
 #ifndef _LINUX_DIRENT_H
 #define _LINUX_DIRENT_H
 
-struct dirent {
-       long            d_ino;
-       __kernel_off_t  d_off;
-       unsigned short  d_reclen;
-       char            d_name[256]; /* We must not include limits.h! */
-};
-
-struct dirent64 {
-       __u64           d_ino;
-       __s64           d_off;
-       unsigned short  d_reclen;
-       unsigned char   d_type;
-       char            d_name[256];
-};
-
-#ifdef __KERNEL__
-
 struct linux_dirent64 {
        u64             d_ino;
        s64             d_off;
@@ -26,7 +9,4 @@ struct linux_dirent64 {
        char            d_name[0];
 };
 
-#endif /* __KERNEL__ */
-
-
 #endif
index a701399b7fed915e8cbd057be25a57d32bb2de10..a667637b54e3912783c9f1e086c57df74784e05b 100644 (file)
 
 #ifdef CONFIG_EVENTFD
 
+/* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/fcntl.h>
+
+/* Flags for eventfd2.  */
+#define EFD_CLOEXEC O_CLOEXEC
+#define EFD_NONBLOCK O_NONBLOCK
+
 struct file *eventfd_fget(int fd);
 int eventfd_signal(struct file *file, int n);
 
index cf79853967ffb25b839e7c77c3bf8ef9956d95e8..f1e1d3c471250bf67d7b50d8e7fd62240c4deef1 100644 (file)
 #ifndef _LINUX_EVENTPOLL_H
 #define _LINUX_EVENTPOLL_H
 
+/* For O_CLOEXEC */
+#include <linux/fcntl.h>
 #include <linux/types.h>
 
+/* Flags for epoll_create1.  */
+#define EPOLL_CLOEXEC O_CLOEXEC
 
 /* Valid opcodes to issue to sys_epoll_ctl() */
 #define EPOLL_CTL_ADD 1
index 84cec2aa9f1e98bd70ad9bb65ac58c06e2e9e5b4..2efe7b863cff361301d4a73c1c4e46338d0b02b1 100644 (file)
@@ -284,8 +284,8 @@ struct ext2_inode {
 
 #ifdef __hurd__
 #define i_translator   osd1.hurd1.h_i_translator
-#define i_frag         osd2.hurd2.h_i_frag;
-#define i_fsize                osd2.hurd2.h_i_fsize;
+#define i_frag         osd2.hurd2.h_i_frag
+#define i_fsize                osd2.hurd2.h_i_fsize
 #define i_uid_high     osd2.hurd2.h_i_uid_high
 #define i_gid_high     osd2.hurd2.h_i_gid_high
 #define i_author       osd2.hurd2.h_i_author
index 36c5403963778bcb5a1a5b9193267a616728cdde..80171ee89a2222b8e00fb65b2220b4f0fcf78165 100644 (file)
@@ -832,6 +832,7 @@ extern void ext3_discard_reservation (struct inode *);
 extern void ext3_dirty_inode(struct inode *);
 extern int ext3_change_inode_journal_flag(struct inode *, int);
 extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *);
+extern int ext3_can_truncate(struct inode *inode);
 extern void ext3_truncate (struct inode *);
 extern void ext3_set_inode_flags(struct inode *);
 extern void ext3_get_inode_flags(struct ext3_inode_info *);
index 72295b099228637fe7a6291eca43790b91260334..3b8870e32afdd14b8166dd876762c0986cafd4ab 100644 (file)
@@ -8,7 +8,6 @@ struct dentry;
 
 /* Definitions of frame buffers                                                */
 
-#define FB_MAJOR               29
 #define FB_MAX                 32      /* sufficient for now */
 
 /* ioctls
@@ -120,6 +119,10 @@ struct dentry;
 #define FB_ACCEL_XGI_VOLARI_V  47      /* XGI Volari V3XT, V5, V8      */
 #define FB_ACCEL_XGI_VOLARI_Z  48      /* XGI Volari Z7                */
 #define FB_ACCEL_OMAP1610      49      /* TI OMAP16xx                  */
+#define FB_ACCEL_TRIDENT_TGUI  50      /* Trident TGUI                 */
+#define FB_ACCEL_TRIDENT_3DIMAGE 51    /* Trident 3DImage              */
+#define FB_ACCEL_TRIDENT_BLADE3D 52    /* Trident Blade3D              */
+#define FB_ACCEL_TRIDENT_BLADEXP 53    /* Trident BladeXP              */
 #define FB_ACCEL_NEOMAGIC_NM2070 90    /* NeoMagic NM2070              */
 #define FB_ACCEL_NEOMAGIC_NM2090 91    /* NeoMagic NM2090              */
 #define FB_ACCEL_NEOMAGIC_NM2093 92    /* NeoMagic NM2093              */
diff --git a/include/linux/fd1772.h b/include/linux/fd1772.h
deleted file mode 100644 (file)
index 871d6e4..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef _LINUX_FD1772REG_H
-#define _LINUX_FD1772REG_H
-
-/*
-** WD1772 stuff - originally from the M68K Linux
- * Modified for Archimedes by Dave Gilbert (gilbertd@cs.man.ac.uk)
- */
-
-/* register codes */
-
-#define FDC1772SELREG_STP   (0x80)   /* command/status register */
-#define FDC1772SELREG_TRA   (0x82)   /* track register */
-#define FDC1772SELREG_SEC   (0x84)   /* sector register */
-#define FDC1772SELREG_DTA   (0x86)   /* data register */
-
-/* register names for FDC1772_READ/WRITE macros */
-
-#define FDC1772REG_CMD         0
-#define FDC1772REG_STATUS      0
-#define FDC1772REG_TRACK       2
-#define FDC1772REG_SECTOR      4
-#define FDC1772REG_DATA                6
-
-/* command opcodes */
-
-#define FDC1772CMD_RESTORE  (0x00)   /*  -                   */
-#define FDC1772CMD_SEEK     (0x10)   /*   |                  */
-#define FDC1772CMD_STEP     (0x20)   /*   |  TYP 1 Commands  */
-#define FDC1772CMD_STIN     (0x40)   /*   |                  */
-#define FDC1772CMD_STOT     (0x60)   /*  -                   */
-#define FDC1772CMD_RDSEC    (0x80)   /*  -   TYP 2 Commands  */
-#define FDC1772CMD_WRSEC    (0xa0)   /*  -          "        */
-#define FDC1772CMD_RDADR    (0xc0)   /*  -                   */
-#define FDC1772CMD_RDTRA    (0xe0)   /*   |  TYP 3 Commands  */
-#define FDC1772CMD_WRTRA    (0xf0)   /*  -                   */
-#define FDC1772CMD_FORCI    (0xd0)   /*  -   TYP 4 Command   */
-
-/* command modifier bits */
-
-#define FDC1772CMDADD_SR6   (0x00)   /* step rate settings */
-#define FDC1772CMDADD_SR12  (0x01)
-#define FDC1772CMDADD_SR2   (0x02)
-#define FDC1772CMDADD_SR3   (0x03)
-#define FDC1772CMDADD_V     (0x04)   /* verify */
-#define FDC1772CMDADD_H     (0x08)   /* wait for spin-up */
-#define FDC1772CMDADD_U     (0x10)   /* update track register */
-#define FDC1772CMDADD_M     (0x10)   /* multiple sector access */
-#define FDC1772CMDADD_E     (0x04)   /* head settling flag */
-#define FDC1772CMDADD_P     (0x02)   /* precompensation */
-#define FDC1772CMDADD_A0    (0x01)   /* DAM flag */
-
-/* status register bits */
-
-#define        FDC1772STAT_MOTORON     (0x80)   /* motor on */
-#define        FDC1772STAT_WPROT       (0x40)   /* write protected (FDC1772CMD_WR*) */
-#define        FDC1772STAT_SPINUP      (0x20)   /* motor speed stable (Type I) */
-#define        FDC1772STAT_DELDAM      (0x20)   /* sector has deleted DAM (Type II+III) */
-#define        FDC1772STAT_RECNF       (0x10)   /* record not found */
-#define        FDC1772STAT_CRC         (0x08)   /* CRC error */
-#define        FDC1772STAT_TR00        (0x04)   /* Track 00 flag (Type I) */
-#define        FDC1772STAT_LOST        (0x04)   /* Lost Data (Type II+III) */
-#define        FDC1772STAT_IDX         (0x02)   /* Index status (Type I) */
-#define        FDC1772STAT_DRQ         (0x02)   /* DRQ status (Type II+III) */
-#define        FDC1772STAT_BUSY        (0x01)   /* FDC1772 is busy */
-
-
-/* PSG Port A Bit Nr 0 .. Side Sel .. 0 -> Side 1  1 -> Side 2 */
-#define DSKSIDE     (0x01)
-        
-#define DSKDRVNONE  (0x06)
-#define DSKDRV0     (0x02)
-#define DSKDRV1     (0x04)
-
-/* step rates */
-#define        FDC1772STEP_6   0x00
-#define        FDC1772STEP_12  0x01
-#define        FDC1772STEP_2   0x02
-#define        FDC1772STEP_3   0x03
-
-#endif
index 9c2ac5c0ef5cb3db65050866694d4cf8af2c8dc3..580b513668feffbb32f9d161113e10b17718dfe5 100644 (file)
@@ -60,6 +60,8 @@ extern int dir_notify_enable;
 #define MAY_WRITE 2
 #define MAY_READ 4
 #define MAY_APPEND 8
+#define MAY_ACCESS 16
+#define MAY_OPEN 32
 
 #define FMODE_READ 1
 #define FMODE_WRITE 2
@@ -277,7 +279,7 @@ extern int dir_notify_enable;
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 #include <linux/dcache.h>
-#include <linux/namei.h>
+#include <linux/path.h>
 #include <linux/stat.h>
 #include <linux/cache.h>
 #include <linux/kobject.h>
@@ -318,22 +320,23 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
  * Attribute flags.  These should be or-ed together to figure out what
  * has been changed!
  */
-#define ATTR_MODE      1
-#define ATTR_UID       2
-#define ATTR_GID       4
-#define ATTR_SIZE      8
-#define ATTR_ATIME     16
-#define ATTR_MTIME     32
-#define ATTR_CTIME     64
-#define ATTR_ATIME_SET 128
-#define ATTR_MTIME_SET 256
-#define ATTR_FORCE     512     /* Not a change, but a change it */
-#define ATTR_ATTR_FLAG 1024
-#define ATTR_KILL_SUID 2048
-#define ATTR_KILL_SGID 4096
-#define ATTR_FILE      8192
-#define ATTR_KILL_PRIV 16384
-#define ATTR_OPEN      32768   /* Truncating from open(O_TRUNC) */
+#define ATTR_MODE      (1 << 0)
+#define ATTR_UID       (1 << 1)
+#define ATTR_GID       (1 << 2)
+#define ATTR_SIZE      (1 << 3)
+#define ATTR_ATIME     (1 << 4)
+#define ATTR_MTIME     (1 << 5)
+#define ATTR_CTIME     (1 << 6)
+#define ATTR_ATIME_SET (1 << 7)
+#define ATTR_MTIME_SET (1 << 8)
+#define ATTR_FORCE     (1 << 9) /* Not a change, but a change it */
+#define ATTR_ATTR_FLAG (1 << 10)
+#define ATTR_KILL_SUID (1 << 11)
+#define ATTR_KILL_SGID (1 << 12)
+#define ATTR_FILE      (1 << 13)
+#define ATTR_KILL_PRIV (1 << 14)
+#define ATTR_OPEN      (1 << 15) /* Truncating from open(O_TRUNC) */
+#define ATTR_TIMES_SET (1 << 16)
 
 /*
  * This is the Inode Attributes structure, used for notify_change().  It
@@ -440,6 +443,27 @@ static inline size_t iov_iter_count(struct iov_iter *i)
        return i->count;
 }
 
+/*
+ * "descriptor" for what we're up to with a read.
+ * This allows us to use the same read code yet
+ * have multiple different users of the data that
+ * we read from a file.
+ *
+ * The simplest case just copies the data to user
+ * mode.
+ */
+typedef struct {
+       size_t written;
+       size_t count;
+       union {
+               char __user *buf;
+               void *data;
+       } arg;
+       int error;
+} read_descriptor_t;
+
+typedef int (*read_actor_t)(read_descriptor_t *, struct page *,
+               unsigned long, unsigned long);
 
 struct address_space_operations {
        int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -481,6 +505,8 @@ struct address_space_operations {
        int (*migratepage) (struct address_space *,
                        struct page *, struct page *);
        int (*launder_page) (struct page *);
+       int (*is_partially_uptodate) (struct page *, read_descriptor_t *,
+                                       unsigned long);
 };
 
 /*
@@ -499,7 +525,7 @@ struct backing_dev_info;
 struct address_space {
        struct inode            *host;          /* owner: inode, block_device */
        struct radix_tree_root  page_tree;      /* radix tree of all pages */
-       rwlock_t                tree_lock;      /* and rwlock protecting it */
+       spinlock_t              tree_lock;      /* and lock protecting it */
        unsigned int            i_mmap_writable;/* count VM_SHARED mappings */
        struct prio_tree_root   i_mmap;         /* tree of private and shared mappings */
        struct list_head        i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
@@ -792,7 +818,7 @@ struct file {
 #define f_dentry       f_path.dentry
 #define f_vfsmnt       f_path.mnt
        const struct file_operations    *f_op;
-       atomic_t                f_count;
+       atomic_long_t           f_count;
        unsigned int            f_flags;
        mode_t                  f_mode;
        loff_t                  f_pos;
@@ -821,8 +847,8 @@ extern spinlock_t files_lock;
 #define file_list_lock() spin_lock(&files_lock);
 #define file_list_unlock() spin_unlock(&files_lock);
 
-#define get_file(x)    atomic_inc(&(x)->f_count)
-#define file_count(x)  atomic_read(&(x)->f_count)
+#define get_file(x)    atomic_long_inc(&(x)->f_count)
+#define file_count(x)  atomic_long_read(&(x)->f_count)
 
 #ifdef CONFIG_DEBUG_WRITECOUNT
 static inline void file_take_write(struct file *f)
@@ -885,6 +911,12 @@ static inline int file_check_writeable(struct file *filp)
 #define FL_CLOSE       64      /* unlock on close */
 #define FL_SLEEP       128     /* A blocking lock */
 
+/*
+ * Special return value from posix_lock_file() and vfs_lock_file() for
+ * asynchronous locking.
+ */
+#define FILE_LOCK_DEFERRED 1
+
 /*
  * The POSIX file lock owner is determined by
  * the "struct files_struct" in the thread group
@@ -1025,6 +1057,7 @@ extern int send_sigurg(struct fown_struct *fown);
 extern struct list_head super_blocks;
 extern spinlock_t sb_lock;
 
+#define sb_entry(list)  list_entry((list), struct super_block, s_list)
 #define S_BIAS (1<<30)
 struct super_block {
        struct list_head        s_list;         /* Keep this first */
@@ -1058,6 +1091,9 @@ struct super_block {
        struct list_head        s_more_io;      /* parked for more writeback */
        struct hlist_head       s_anon;         /* anonymous dentries for (nfs) exporting */
        struct list_head        s_files;
+       /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */
+       struct list_head        s_dentry_lru;   /* unused dentry lru */
+       int                     s_nr_dentry_unused;     /* # of dentry on lru */
 
        struct block_device     *s_bdev;
        struct mtd_info         *s_mtd;
@@ -1126,7 +1162,7 @@ extern int vfs_permission(struct nameidata *, int);
 extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
 extern int vfs_mkdir(struct inode *, struct dentry *, int);
 extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
-extern int vfs_symlink(struct inode *, struct dentry *, const char *, int);
+extern int vfs_symlink(struct inode *, struct dentry *, const char *);
 extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
 extern int vfs_rmdir(struct inode *, struct dentry *);
 extern int vfs_unlink(struct inode *, struct dentry *);
@@ -1185,27 +1221,6 @@ struct block_device_operations {
        struct module *owner;
 };
 
-/*
- * "descriptor" for what we're up to with a read.
- * This allows us to use the same read code yet
- * have multiple different users of the data that
- * we read from a file.
- *
- * The simplest case just copies the data to user
- * mode.
- */
-typedef struct {
-       size_t written;
-       size_t count;
-       union {
-               char __user * buf;
-               void *data;
-       } arg;
-       int error;
-} read_descriptor_t;
-
-typedef int (*read_actor_t)(read_descriptor_t *, struct page *, unsigned long, unsigned long);
-
 /* These macros are for out of kernel modules to test that
  * the kernel supports the unlocked_ioctl and compat_ioctl
  * fields in struct file_operations. */
@@ -1262,7 +1277,7 @@ struct inode_operations {
        void * (*follow_link) (struct dentry *, struct nameidata *);
        void (*put_link) (struct dentry *, struct nameidata *, void *);
        void (*truncate) (struct inode *);
-       int (*permission) (struct inode *, int, struct nameidata *);
+       int (*permission) (struct inode *, int);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
        int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -1686,9 +1701,9 @@ extern void init_special_inode(struct inode *, umode_t, dev_t);
 extern void make_bad_inode(struct inode *);
 extern int is_bad_inode(struct inode *);
 
-extern const struct file_operations read_fifo_fops;
-extern const struct file_operations write_fifo_fops;
-extern const struct file_operations rdwr_fifo_fops;
+extern const struct file_operations read_pipefifo_fops;
+extern const struct file_operations write_pipefifo_fops;
+extern const struct file_operations rdwr_pipefifo_fops;
 
 extern int fs_may_remount_ro(struct super_block *);
 
@@ -1757,7 +1772,7 @@ extern int do_remount_sb(struct super_block *sb, int flags,
 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 inode_permission(struct inode *, int);
 extern int generic_permission(struct inode *, int,
                int (*check_acl)(struct inode *, int));
 
@@ -1773,8 +1788,9 @@ static inline void allow_write_access(struct file *file)
                atomic_inc(&file->f_path.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 int do_pipe_flags(int *, int);
+extern struct file *create_read_pipe(struct file *f, int flags);
+extern struct file *create_write_pipe(int flags);
 extern void free_write_pipe(struct file *);
 
 extern struct file *do_filp_open(int dfd, const char *pathname,
@@ -1820,7 +1836,7 @@ extern void clear_inode(struct inode *);
 extern void destroy_inode(struct inode *);
 extern struct inode *new_inode(struct super_block *);
 extern int should_remove_suid(struct dentry *);
-extern int remove_suid(struct dentry *);
+extern int file_remove_suid(struct file *);
 
 extern void __insert_inode_hash(struct inode *, unsigned long hashval);
 extern void remove_inode_hash(struct inode *);
@@ -2006,8 +2022,6 @@ extern void simple_release_fs(struct vfsmount **mount, int *count);
 
 extern ssize_t simple_read_from_buffer(void __user *to, size_t count,
                        loff_t *ppos, const void *from, size_t available);
-extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
-                       const void *from, size_t available);
 
 #ifdef CONFIG_MIGRATION
 extern int buffer_migrate_page(struct address_space *,
index 282f542191294112610661ac76f0e5fa015435f8..9e5a06e78d0290870a5504e0ba277de476beae5a 100644 (file)
@@ -7,7 +7,7 @@ struct fs_struct {
        atomic_t count;
        rwlock_t lock;
        int umask;
-       struct path root, pwd, altroot;
+       struct path root, pwd;
 };
 
 #define INIT_FS {                              \
@@ -19,7 +19,6 @@ struct fs_struct {
 extern struct kmem_cache *fs_cachep;
 
 extern void exit_fs(struct task_struct *);
-extern void set_fs_altroot(void);
 extern void set_fs_root(struct fs_struct *, struct path *);
 extern void set_fs_pwd(struct fs_struct *, struct path *);
 extern struct fs_struct *copy_fs_struct(struct fs_struct *);
index d48282197696fdf1644820a121ce75cd5571bd67..265635dc990812a319dcd632131e8c9f79051f1d 100644 (file)
@@ -104,11 +104,14 @@ struct fuse_file_lock {
 
 /**
  * INIT request/reply flags
+ *
+ * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
  */
 #define FUSE_ASYNC_READ                (1 << 0)
 #define FUSE_POSIX_LOCKS       (1 << 1)
 #define FUSE_FILE_OPS          (1 << 2)
 #define FUSE_ATOMIC_O_TRUNC    (1 << 3)
+#define FUSE_EXPORT_SUPPORT    (1 << 4)
 #define FUSE_BIG_WRITES                (1 << 5)
 
 /**
index e8787417f65a1175cb4e1542f7271c0d3dbfd87b..118216f1bd3c357a61b154face10a267a67f3290 100644 (file)
@@ -541,7 +541,7 @@ extern dev_t blk_lookup_devt(const char *name, int part);
 extern char *disk_name (struct gendisk *hd, int part, char *buf);
 
 extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
-extern void add_partition(struct gendisk *, int, sector_t, sector_t, int);
+extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int);
 extern void delete_partition(struct gendisk *, int);
 extern void printk_all_partitions(void);
 
index b414be387180f1db79c90977921296640e15f5e9..e8003afeffba340aab45281ab5d4a7689f2ce891 100644 (file)
@@ -173,11 +173,24 @@ static inline void arch_free_page(struct page *page, int order) { }
 static inline void arch_alloc_page(struct page *page, int order) { }
 #endif
 
-extern struct page *__alloc_pages(gfp_t, unsigned int, struct zonelist *);
+struct page *
+__alloc_pages_internal(gfp_t gfp_mask, unsigned int order,
+                      struct zonelist *zonelist, nodemask_t *nodemask);
+
+static inline struct page *
+__alloc_pages(gfp_t gfp_mask, unsigned int order,
+               struct zonelist *zonelist)
+{
+       return __alloc_pages_internal(gfp_mask, order, zonelist, NULL);
+}
+
+static inline struct page *
+__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
+               struct zonelist *zonelist, nodemask_t *nodemask)
+{
+       return __alloc_pages_internal(gfp_mask, order, zonelist, nodemask);
+}
 
-extern struct page *
-__alloc_pages_nodemask(gfp_t, unsigned int,
-                               struct zonelist *, nodemask_t *nodemask);
 
 static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
                                                unsigned int order)
@@ -215,6 +228,9 @@ extern struct page *alloc_page_vma(gfp_t gfp_mask,
 extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
 extern unsigned long get_zeroed_page(gfp_t gfp_mask);
 
+void *alloc_pages_exact(size_t size, gfp_t gfp_mask);
+void free_pages_exact(void *virt, size_t size);
+
 #define __get_free_page(gfp_mask) \
                __get_free_pages((gfp_mask),0)
 
index 98be6c5762b923fcb2a98ced684051c3ea7f773c..730a20b83576b4ab39d81810085c20d61eec0225 100644 (file)
@@ -79,6 +79,19 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
        WARN_ON(1);
 }
 
+static inline int gpio_export(unsigned gpio, bool direction_may_change)
+{
+       /* GPIO can never have been requested or set as {in,out}put */
+       WARN_ON(1);
+       return -EINVAL;
+}
+
+static inline void gpio_unexport(unsigned gpio)
+{
+       /* GPIO can never have been exported */
+       WARN_ON(1);
+}
+
 static inline int gpio_to_irq(unsigned gpio)
 {
        /* GPIO can never have been requested or set as input */
index a79e80b689d803d161a4ca694370aeec1ba25629..32e0ef0f6e1fcdd7f67d83ffe985e6cbe8eb9a08 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/mempolicy.h>
 #include <linux/shm.h>
 #include <asm/tlbflush.h>
-#include <asm/hugetlb.h>
 
 struct ctl_table;
 
@@ -17,38 +16,45 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
        return vma->vm_flags & VM_HUGETLB;
 }
 
+void reset_vma_resv_huge_pages(struct vm_area_struct *vma);
 int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
 int hugetlb_overcommit_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
 int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
 int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
 int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int, int);
-void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
-void __unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
+void unmap_hugepage_range(struct vm_area_struct *,
+                       unsigned long, unsigned long, struct page *);
+void __unmap_hugepage_range(struct vm_area_struct *,
+                       unsigned long, unsigned long, struct page *);
 int hugetlb_prefault(struct address_space *, struct vm_area_struct *);
 int hugetlb_report_meminfo(char *);
 int hugetlb_report_node_meminfo(int, char *);
 unsigned long hugetlb_total_pages(void);
 int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                        unsigned long address, int write_access);
-int hugetlb_reserve_pages(struct inode *inode, long from, long to);
+int hugetlb_reserve_pages(struct inode *inode, long from, long to,
+                                               struct vm_area_struct *vma);
 void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
 
-extern unsigned long max_huge_pages;
-extern unsigned long sysctl_overcommit_huge_pages;
 extern unsigned long hugepages_treat_as_movable;
 extern const unsigned long hugetlb_zero, hugetlb_infinity;
 extern int sysctl_hugetlb_shm_group;
+extern struct list_head huge_boot_pages;
 
 /* arch callbacks */
 
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr);
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+                       unsigned long addr, unsigned long sz);
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr);
 int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep);
 struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
                              int write);
 struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
                                pmd_t *pmd, int write);
+struct page *follow_huge_pud(struct mm_struct *mm, unsigned long address,
+                               pud_t *pud, int write);
 int pmd_huge(pmd_t pmd);
+int pud_huge(pud_t pmd);
 void hugetlb_change_protection(struct vm_area_struct *vma,
                unsigned long address, unsigned long end, pgprot_t newprot);
 
@@ -58,6 +64,11 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
 {
        return 0;
 }
+
+static inline void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
+{
+}
+
 static inline unsigned long hugetlb_total_pages(void)
 {
        return 0;
@@ -67,12 +78,14 @@ static inline unsigned long hugetlb_total_pages(void)
 #define follow_huge_addr(mm, addr, write)      ERR_PTR(-EINVAL)
 #define copy_hugetlb_page_range(src, dst, vma) ({ BUG(); 0; })
 #define hugetlb_prefault(mapping, vma)         ({ BUG(); 0; })
-#define unmap_hugepage_range(vma, start, end)  BUG()
+#define unmap_hugepage_range(vma, start, end, page)    BUG()
 #define hugetlb_report_meminfo(buf)            0
 #define hugetlb_report_node_meminfo(n, buf)    0
 #define follow_huge_pmd(mm, addr, pmd, write)  NULL
-#define prepare_hugepage_range(addr,len)       (-EINVAL)
+#define follow_huge_pud(mm, addr, pud, write)  NULL
+#define prepare_hugepage_range(file, addr, len)        (-EINVAL)
 #define pmd_huge(x)    0
+#define pud_huge(x)    0
 #define is_hugepage_only_range(mm, addr, len)  0
 #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; })
 #define hugetlb_fault(mm, vma, addr, write)    ({ BUG(); 0; })
@@ -93,6 +106,7 @@ struct hugetlbfs_config {
        umode_t mode;
        long    nr_blocks;
        long    nr_inodes;
+       struct hstate *hstate;
 };
 
 struct hugetlbfs_sb_info {
@@ -101,6 +115,7 @@ struct hugetlbfs_sb_info {
        long    max_inodes;   /* inodes allowed */
        long    free_inodes;  /* inodes free */
        spinlock_t      stat_lock;
+       struct hstate *hstate;
 };
 
 
@@ -125,8 +140,6 @@ struct file *hugetlb_file_setup(const char *name, size_t);
 int hugetlb_get_quota(struct address_space *mapping, long delta);
 void hugetlb_put_quota(struct address_space *mapping, long delta);
 
-#define BLOCKS_PER_HUGEPAGE    (HPAGE_SIZE / 512)
-
 static inline int is_file_hugepages(struct file *file)
 {
        if (file->f_op == &hugetlbfs_file_operations)
@@ -155,4 +168,115 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                                        unsigned long flags);
 #endif /* HAVE_ARCH_HUGETLB_UNMAPPED_AREA */
 
+#ifdef CONFIG_HUGETLB_PAGE
+
+#define HSTATE_NAME_LEN 32
+/* Defines one hugetlb page size */
+struct hstate {
+       int hugetlb_next_nid;
+       unsigned int order;
+       unsigned long mask;
+       unsigned long max_huge_pages;
+       unsigned long nr_huge_pages;
+       unsigned long free_huge_pages;
+       unsigned long resv_huge_pages;
+       unsigned long surplus_huge_pages;
+       unsigned long nr_overcommit_huge_pages;
+       struct list_head hugepage_freelists[MAX_NUMNODES];
+       unsigned int nr_huge_pages_node[MAX_NUMNODES];
+       unsigned int free_huge_pages_node[MAX_NUMNODES];
+       unsigned int surplus_huge_pages_node[MAX_NUMNODES];
+       char name[HSTATE_NAME_LEN];
+};
+
+struct huge_bootmem_page {
+       struct list_head list;
+       struct hstate *hstate;
+};
+
+/* arch callback */
+int __init alloc_bootmem_huge_page(struct hstate *h);
+
+void __init hugetlb_add_hstate(unsigned order);
+struct hstate *size_to_hstate(unsigned long size);
+
+#ifndef HUGE_MAX_HSTATE
+#define HUGE_MAX_HSTATE 1
+#endif
+
+extern struct hstate hstates[HUGE_MAX_HSTATE];
+extern unsigned int default_hstate_idx;
+
+#define default_hstate (hstates[default_hstate_idx])
+
+static inline struct hstate *hstate_inode(struct inode *i)
+{
+       struct hugetlbfs_sb_info *hsb;
+       hsb = HUGETLBFS_SB(i->i_sb);
+       return hsb->hstate;
+}
+
+static inline struct hstate *hstate_file(struct file *f)
+{
+       return hstate_inode(f->f_dentry->d_inode);
+}
+
+static inline struct hstate *hstate_vma(struct vm_area_struct *vma)
+{
+       return hstate_file(vma->vm_file);
+}
+
+static inline unsigned long huge_page_size(struct hstate *h)
+{
+       return (unsigned long)PAGE_SIZE << h->order;
+}
+
+static inline unsigned long huge_page_mask(struct hstate *h)
+{
+       return h->mask;
+}
+
+static inline unsigned int huge_page_order(struct hstate *h)
+{
+       return h->order;
+}
+
+static inline unsigned huge_page_shift(struct hstate *h)
+{
+       return h->order + PAGE_SHIFT;
+}
+
+static inline unsigned int pages_per_huge_page(struct hstate *h)
+{
+       return 1 << h->order;
+}
+
+static inline unsigned int blocks_per_huge_page(struct hstate *h)
+{
+       return huge_page_size(h) / 512;
+}
+
+#include <asm/hugetlb.h>
+
+static inline struct hstate *page_hstate(struct page *page)
+{
+       return size_to_hstate(PAGE_SIZE << compound_order(page));
+}
+
+#else
+struct hstate {};
+#define alloc_bootmem_huge_page(h) NULL
+#define hstate_file(f) NULL
+#define hstate_vma(v) NULL
+#define hstate_inode(i) NULL
+#define huge_page_size(h) PAGE_SIZE
+#define huge_page_mask(h) PAGE_MASK
+#define huge_page_order(h) 0
+#define huge_page_shift(h) PAGE_SHIFT
+static inline unsigned int pages_per_huge_page(struct hstate *h)
+{
+       return 1;
+}
+#endif
+
 #endif /* _LINUX_HUGETLB_H */
diff --git a/include/linux/i2c/max732x.h b/include/linux/i2c/max732x.h
new file mode 100644 (file)
index 0000000..e103366
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __LINUX_I2C_MAX732X_H
+#define __LINUX_I2C_MAX732X_H
+
+/* platform data for the MAX732x 8/16-bit I/O expander driver */
+
+struct max732x_platform_data {
+       /* number of the first GPIO */
+       unsigned        gpio_base;
+
+       void            *context;       /* param to setup/teardown */
+
+       int             (*setup)(struct i2c_client *client,
+                               unsigned gpio, unsigned ngpio,
+                               void *context);
+       int             (*teardown)(struct i2c_client *client,
+                               unsigned gpio, unsigned ngpio,
+                               void *context);
+};
+#endif /* __LINUX_I2C_MAX732X_H */
index 7d51cbca49ab230f15d5e8f1276d8ad5f5537b82..75ae6d8aba4fff5167faf5e8b570f78956ccef91 100644 (file)
@@ -758,7 +758,7 @@ static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
        }
 
        dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);
-       if (!dma_mapping_error(dma_addr)) {
+       if (!dma_mapping_error(&c->pdev->dev, dma_addr)) {
 #ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
                if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
                        *mptr++ = cpu_to_le32(0x7C020002);
index d67ccca2b96472b229ffd264642ff420aae66cba..b846bc44a27ed62a62c6c30cf69ed2897579e7f1 100644 (file)
@@ -211,7 +211,21 @@ static inline int __ide_default_irq(unsigned long base)
        return 0;
 }
 
+#if defined(CONFIG_ARM) || defined(CONFIG_FRV) || defined(CONFIG_M68K) || \
+    defined(CONFIG_MIPS) || defined(CONFIG_MN10300) || defined(CONFIG_PARISC) \
+    || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || defined(CONFIG_SPARC64)
 #include <asm/ide.h>
+#else
+#include <asm-generic/ide_iops.h>
+#endif
+
+#ifndef MAX_HWIFS
+#if defined(CONFIG_BLACKFIN) || defined(CONFIG_H8300) || defined(CONFIG_XTENSA)
+# define MAX_HWIFS     1
+#else
+# define MAX_HWIFS     10
+#endif
+#endif
 
 #if !defined(MAX_HWIFS) || defined(CONFIG_EMBEDDED)
 #undef MAX_HWIFS
@@ -532,12 +546,16 @@ struct ide_dma_ops {
        void    (*dma_timeout)(struct ide_drive_s *);
 };
 
+struct ide_host;
+
 typedef struct hwif_s {
        struct hwif_s *next;            /* for linked-list in ide_hwgroup_t */
        struct hwif_s *mate;            /* other hwif from same PCI chip */
        struct hwgroup_s *hwgroup;      /* actually (ide_hwgroup_t *) */
        struct proc_dir_entry *proc;    /* /proc/ide/ directory entry */
 
+       struct ide_host *host;
+
        char name[6];                   /* name of interface, eg. "ide0" */
 
        struct ide_io_ports     io_ports;
@@ -626,6 +644,9 @@ typedef struct hwif_s {
 struct ide_host {
        ide_hwif_t      *ports[MAX_HWIFS];
        unsigned int    n_ports;
+       struct device   *dev[2];
+       unsigned long   host_flags;
+       void            *host_priv;
 };
 
 /*
@@ -874,6 +895,9 @@ struct ide_driver_s {
 
 #define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver)
 
+int ide_device_get(ide_drive_t *);
+void ide_device_put(ide_drive_t *);
+
 int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
 
 extern int ide_vlb_clk;
@@ -1182,7 +1206,7 @@ enum {
 
 struct ide_port_info {
        char                    *name;
-       unsigned int            (*init_chipset)(struct pci_dev *, const char *);
+       unsigned int            (*init_chipset)(struct pci_dev *);
        void                    (*init_iops)(ide_hwif_t *);
        void                    (*init_hwif)(ide_hwif_t *);
        int                     (*init_dma)(ide_hwif_t *,
@@ -1201,8 +1225,10 @@ struct ide_port_info {
        u8                      udma_mask;
 };
 
-int ide_setup_pci_device(struct pci_dev *, const struct ide_port_info *);
-int ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, const struct ide_port_info *);
+int ide_pci_init_one(struct pci_dev *, const struct ide_port_info *, void *);
+int ide_pci_init_two(struct pci_dev *, struct pci_dev *,
+                    const struct ide_port_info *, void *);
+void ide_pci_remove(struct pci_dev *);
 
 void ide_map_sg(ide_drive_t *, struct request *);
 void ide_init_sg_cmd(ide_drive_t *, struct request *);
index 9a2d762124de7684983cdb36a51dc3814b461a8f..fa035f96f2a3b340c468e4b58d9010df3b21be69 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/bitops.h>
 #include <linux/init.h>
+#include <linux/rcupdate.h>
 
 #if BITS_PER_LONG == 32
 # define IDR_BITS 5
@@ -51,6 +52,7 @@ struct idr_layer {
        unsigned long            bitmap; /* A zero bit means "space here" */
        struct idr_layer        *ary[1<<IDR_BITS];
        int                      count;  /* When zero, we can release it */
+       struct rcu_head          rcu_head;
 };
 
 struct idr {
@@ -71,6 +73,28 @@ struct idr {
 }
 #define DEFINE_IDR(name)       struct idr name = IDR_INIT(name)
 
+/* Actions to be taken after a call to _idr_sub_alloc */
+#define IDR_NEED_TO_GROW -2
+#define IDR_NOMORE_SPACE -3
+
+#define _idr_rc_to_errno(rc) ((rc) == -1 ? -EAGAIN : -ENOSPC)
+
+/**
+ * idr synchronization (stolen from radix-tree.h)
+ *
+ * idr_find() is able to be called locklessly, using RCU. The caller must
+ * ensure calls to this function are made within rcu_read_lock() regions.
+ * Other readers (lock-free or otherwise) and modifications may be running
+ * concurrently.
+ *
+ * It is still required that the caller manage the synchronization and
+ * lifetimes of the items. So if RCU lock-free lookups are used, typically
+ * this would mean that the items have their own locks, or are amenable to
+ * lock-free access; and that the items are freed by RCU (or only freed after
+ * having been deleted from the idr tree *and* a synchronize_rcu() grace
+ * period).
+ */
+
 /*
  * This is what we export.
  */
index 21d658cdfa27769146ea52dae2cbf61b3de7f302..11b84e1060532ecf62f73e3151b9f6eaed043c8b 100644 (file)
@@ -169,6 +169,13 @@ extern void (*late_time_init)(void);
        static initcall_t __initcall_##fn##id __used \
        __attribute__((__section__(".initcall" level ".init"))) = fn
 
+/*
+ * Early initcalls run before initializing SMP.
+ *
+ * Only for built-in code, not modules.
+ */
+#define early_initcall(fn)             __define_initcall("early",fn,early)
+
 /*
  * A "pure" initcall has no dependencies on anything else, and purely
  * initializes variables that couldn't be statically initialized.
@@ -275,13 +282,7 @@ void __init parse_early_param(void);
 
 #define security_initcall(fn)          module_init(fn)
 
-/* These macros create a dummy inline: gcc 2.9x does not count alias
- as usage, hence the `unused function' warning when __init functions
- are declared static. We use the dummy __*_module_inline functions
- both to kill the warning and check the type of the init/cleanup
- function. */
-
-/* Each module must use one module_init(), or one no_module_init */
+/* Each module must use one module_init(). */
 #define module_init(initfn)                                    \
        static inline initcall_t __inittest(void)               \
        { return initfn; }                                      \
index 93c45acf249ab20cc19d43c94021a25691be9c76..021d8e720c7941f17cd6a541a63b7a9275f68c9c 100644 (file)
@@ -122,7 +122,7 @@ extern struct group_info init_groups;
        .state          = 0,                                            \
        .stack          = &init_thread_info,                            \
        .usage          = ATOMIC_INIT(2),                               \
-       .flags          = 0,                                            \
+       .flags          = PF_KTHREAD,                                   \
        .lock_depth     = -1,                                           \
        .prio           = MAX_PRIO-20,                                  \
        .static_prio    = MAX_PRIO-20,                                  \
index 742b917e7d1b274e5582ec30d387b4d881fe5915..bd578578a8b98408844e272fc65dc9f694692d0f 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _LINUX_INOTIFY_H
 #define _LINUX_INOTIFY_H
 
+/* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/fcntl.h>
 #include <linux/types.h>
 
 /*
@@ -63,6 +65,10 @@ struct inotify_event {
                         IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
                         IN_MOVE_SELF)
 
+/* Flags for sys_inotify_init1.  */
+#define IN_CLOEXEC O_CLOEXEC
+#define IN_NONBLOCK O_NONBLOCK
+
 #ifdef __KERNEL__
 
 #include <linux/dcache.h>
index c975caf75385d2e634cdb151dae416e2487533a0..f8598f583944a5355b4ee33ddef3a785b3adcc79 100644 (file)
@@ -8,3 +8,4 @@ extern unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
                                      unsigned long align_mask);
 extern void iommu_area_free(unsigned long *map, unsigned long start,
                            unsigned int nr);
+extern unsigned long iommu_num_pages(unsigned long addr, unsigned long len);
index ea6c18a8b0d442d13dabcdeca9961fb8540ca451..ea330f9e710015c2c8a4b80ebfaec9cd133ffcdd 100644 (file)
@@ -36,6 +36,7 @@ struct ipc_namespace {
        int             msg_ctlmni;
        atomic_t        msg_bytes;
        atomic_t        msg_hdrs;
+       int             auto_msgmni;
 
        size_t          shm_ctlmax;
        size_t          shm_ctlall;
@@ -53,7 +54,7 @@ extern atomic_t nr_ipc_ns;
 
 extern int register_ipcns_notifier(struct ipc_namespace *);
 extern int cond_register_ipcns_notifier(struct ipc_namespace *);
-extern int unregister_ipcns_notifier(struct ipc_namespace *);
+extern void unregister_ipcns_notifier(struct ipc_namespace *);
 extern int ipcns_notify(unsigned long);
 
 #else /* CONFIG_SYSVIPC */
index 2b1c2e58566ea04460370fef4a4b686794ab512d..74bde13224c926f5204a2c514609def00d465325 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef _LINUX_TRACE_IRQFLAGS_H
 #define _LINUX_TRACE_IRQFLAGS_H
 
+#include <linux/typecheck.h>
+
 #ifdef CONFIG_TRACE_IRQFLAGS
   extern void trace_softirqs_on(unsigned long ip);
   extern void trace_softirqs_off(unsigned long ip);
        do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
 #define local_irq_disable() \
        do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
-#define local_irq_save(flags) \
-       do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0)
+#define local_irq_save(flags)                          \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               raw_local_irq_save(flags);              \
+               trace_hardirqs_off();                   \
+       } while (0)
 
-#define local_irq_restore(flags)                               \
-       do {                                                    \
-               if (raw_irqs_disabled_flags(flags)) {           \
-                       raw_local_irq_restore(flags);           \
-                       trace_hardirqs_off();                   \
-               } else {                                        \
-                       trace_hardirqs_on();                    \
-                       raw_local_irq_restore(flags);           \
-               }                                               \
+
+#define local_irq_restore(flags)                       \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               if (raw_irqs_disabled_flags(flags)) {   \
+                       raw_local_irq_restore(flags);   \
+                       trace_hardirqs_off();           \
+               } else {                                \
+                       trace_hardirqs_on();            \
+                       raw_local_irq_restore(flags);   \
+               }                                       \
        } while (0)
 #else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
 /*
  */
 # define raw_local_irq_disable()       local_irq_disable()
 # define raw_local_irq_enable()                local_irq_enable()
-# define raw_local_irq_save(flags)     local_irq_save(flags)
-# define raw_local_irq_restore(flags)  local_irq_restore(flags)
+# define raw_local_irq_save(flags)                     \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               local_irq_save(flags);                  \
+       } while (0)
+# define raw_local_irq_restore(flags)                  \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               local_irq_restore(flags);               \
+       } while (0)
 #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
 
 #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
                raw_safe_halt();                                \
        } while (0)
 
-#define local_save_flags(flags)                raw_local_save_flags(flags)
+#define local_save_flags(flags)                                \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               raw_local_save_flags(flags);            \
+       } while (0)
 
 #define irqs_disabled()                                                \
 ({                                                             \
        raw_irqs_disabled_flags(_flags);                        \
 })
 
-#define irqs_disabled_flags(flags)     raw_irqs_disabled_flags(flags)
+#define irqs_disabled_flags(flags)             \
+({                                             \
+       typecheck(unsigned long, flags);        \
+       raw_irqs_disabled_flags(flags);         \
+})
 #endif         /* CONFIG_X86 */
 
 #endif
index 6b563cae23df22c768f63cbb5610d35cd6771a26..da720bc3eb15c2ec7f930a7c9ac8335a6f8ec3c4 100644 (file)
@@ -7,9 +7,6 @@
  *
  * For licensing information, see the file 'LICENCE' in the
  * jffs2 directory.
- *
- * $Id: jffs2.h,v 1.38 2005/09/26 11:37:23 havasi Exp $
- *
  */
 
 #ifndef __LINUX_JFFS2_H__
index 00c1801099fa0de4024690c6c415fe0b58724bc5..57aefa160a926863c752bd1a3a312c0781ecc9b8 100644 (file)
@@ -6,6 +6,7 @@
 #define _LINUX_KALLSYMS_H
 
 #include <linux/errno.h>
+#include <linux/kernel.h>
 #include <linux/stddef.h>
 
 #define KSYM_NAME_LEN 128
@@ -105,18 +106,10 @@ static inline void print_fn_descriptor_symbol(const char *fmt, void *addr)
        print_symbol(fmt, (unsigned long)addr);
 }
 
-#ifndef CONFIG_64BIT
-#define print_ip_sym(ip)               \
-do {                                   \
-       printk("[<%08lx>]", ip);        \
-       print_symbol(" %s\n", ip);      \
-} while(0)
-#else
-#define print_ip_sym(ip)               \
-do {                                   \
-       printk("[<%016lx>]", ip);       \
-       print_symbol(" %s\n", ip);      \
-} while(0)
-#endif
+static inline void print_ip_sym(unsigned long ip)
+{
+       printk("[<%p>]", (void *) ip);
+       print_symbol(" %s\n", ip);
+}
 
 #endif /*_LINUX_KALLSYMS_H*/
index f9cd7a513f9c5f91a0d703a2b8080250ecf7805e..7889c2f9b75d7a37eb0bcc9615a7107871b5d997 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/compiler.h>
 #include <linux/bitops.h>
 #include <linux/log2.h>
+#include <linux/typecheck.h>
+#include <linux/ratelimit.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
@@ -174,7 +176,7 @@ extern int vsscanf(const char *, const char *, va_list)
 
 extern int get_option(char **str, int *pint);
 extern char *get_options(const char *str, int nints, int *ints);
-extern unsigned long long memparse(char *ptr, char **retptr);
+extern unsigned long long memparse(const char *ptr, char **retptr);
 
 extern int core_kernel_text(unsigned long addr);
 extern int __kernel_text_address(unsigned long addr);
@@ -188,11 +190,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 asmlinkage int printk(const char * fmt, ...)
        __attribute__ ((format (printf, 1, 2))) __cold;
 
-extern int printk_ratelimit_jiffies;
-extern int printk_ratelimit_burst;
+extern struct ratelimit_state printk_ratelimit_state;
 extern int printk_ratelimit(void);
-extern int __ratelimit(int ratelimit_jiffies, int ratelimit_burst);
-extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
 extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
                                   unsigned int interval_msec);
 #else
@@ -203,8 +202,6 @@ static inline int printk(const char *s, ...)
        __attribute__ ((format (printf, 1, 2)));
 static inline int __cold printk(const char *s, ...) { return 0; }
 static inline int printk_ratelimit(void) { return 0; }
-static inline int __printk_ratelimit(int ratelimit_jiffies, \
-                                    int ratelimit_burst) { return 0; }
 static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \
                                          unsigned int interval_msec)   \
                { return false; }
@@ -441,26 +438,6 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})
 
-/*
- * Check at compile time that something is of a particular type.
- * Always evaluates to 1 so you may use it easily in comparisons.
- */
-#define typecheck(type,x) \
-({     type __dummy; \
-       typeof(x) __dummy2; \
-       (void)(&__dummy == &__dummy2); \
-       1; \
-})
-
-/*
- * Check at compile time that 'function' is a certain type, or is a pointer
- * to that type (needs to use typedef for the function type.)
- */
-#define typecheck_fn(type,function) \
-({     typeof(type) __tmp = function; \
-       (void)__tmp; \
-})
-
 struct sysinfo;
 extern int do_sysinfo(struct sysinfo *info);
 
index 3265968cd2cd4cab38bdff1017e763c24304f842..82f88a8a827b4a41adc4199a38605d7dac7dd680 100644 (file)
@@ -83,6 +83,7 @@ struct kimage {
 
        unsigned long start;
        struct page *control_code_page;
+       struct page *swap_page;
 
        unsigned long nr_segments;
        struct kexec_segment segment[KEXEC_SEGMENT_MAX];
@@ -98,18 +99,20 @@ struct kimage {
        unsigned int type : 1;
 #define KEXEC_TYPE_DEFAULT 0
 #define KEXEC_TYPE_CRASH   1
+       unsigned int preserve_context : 1;
 };
 
 
 
 /* kexec interface functions */
-extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET;
+extern void machine_kexec(struct kimage *image);
 extern int machine_kexec_prepare(struct kimage *image);
 extern void machine_kexec_cleanup(struct kimage *image);
 extern asmlinkage long sys_kexec_load(unsigned long entry,
                                        unsigned long nr_segments,
                                        struct kexec_segment __user *segments,
                                        unsigned long flags);
+extern int kernel_kexec(void);
 #ifdef CONFIG_COMPAT
 extern asmlinkage long compat_sys_kexec_load(unsigned long entry,
                                unsigned long nr_segments,
@@ -156,8 +159,9 @@ extern struct kimage *kexec_crash_image;
 #define kexec_flush_icache_page(page)
 #endif
 
-#define KEXEC_ON_CRASH  0x00000001
-#define KEXEC_ARCH_MASK 0xffff0000
+#define KEXEC_ON_CRASH         0x00000001
+#define KEXEC_PRESERVE_CONTEXT 0x00000002
+#define KEXEC_ARCH_MASK                0xffff0000
 
 /* These values match the ELF architecture values.
  * Unless there is a good reason that should continue to be the case.
@@ -174,7 +178,12 @@ extern struct kimage *kexec_crash_image;
 #define KEXEC_ARCH_MIPS_LE (10 << 16)
 #define KEXEC_ARCH_MIPS    ( 8 << 16)
 
-#define KEXEC_FLAGS    (KEXEC_ON_CRASH)  /* List of defined/legal kexec flags */
+/* List of defined/legal kexec flags */
+#ifndef CONFIG_KEXEC_JUMP
+#define KEXEC_FLAGS    KEXEC_ON_CRASH
+#else
+#define KEXEC_FLAGS    (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT)
+#endif
 
 #define VMCOREINFO_BYTES           (4096)
 #define VMCOREINFO_NOTE_NAME       "VMCOREINFO"
index 0509c4ce485793e748054aa558e559691a6af79d..a1a91577813c6bfb25ea89c9304f0c2128a87464 100644 (file)
@@ -19,6 +19,7 @@
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/gfp.h>
 #include <linux/stddef.h>
 #include <linux/errno.h>
 #include <linux/compiler.h>
@@ -41,8 +42,8 @@ struct file;
 struct subprocess_info;
 
 /* Allocate a subprocess_info structure */
-struct subprocess_info *call_usermodehelper_setup(char *path,
-                                                 char **argv, char **envp);
+struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
+                                                 char **envp, gfp_t gfp_mask);
 
 /* Set various pieces of state into the subprocess_info structure */
 void call_usermodehelper_setkeys(struct subprocess_info *info,
@@ -69,8 +70,9 @@ static inline int
 call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
 {
        struct subprocess_info *info;
+       gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
 
-       info = call_usermodehelper_setup(path, argv, envp);
+       info = call_usermodehelper_setup(path, argv, envp, gfp_mask);
        if (info == NULL)
                return -ENOMEM;
        return call_usermodehelper_exec(info, wait);
@@ -81,8 +83,9 @@ call_usermodehelper_keys(char *path, char **argv, char **envp,
                         struct key *session_keyring, enum umh_wait wait)
 {
        struct subprocess_info *info;
+       gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
 
-       info = call_usermodehelper_setup(path, argv, envp);
+       info = call_usermodehelper_setup(path, argv, envp, gfp_mask);
        if (info == NULL)
                return -ENOMEM;
 
index 60f0d418ae3264c8684accf0f44cbab9c2db700e..5437ac0276e232d259a886e7b644f4b4e2e44935 100644 (file)
@@ -186,6 +186,8 @@ extern struct kobject *kset_find_obj(struct kset *, const char *);
 
 /* The global /sys/kernel/ kobject for people to chain off of */
 extern struct kobject *kernel_kobj;
+/* The global /sys/kernel/mm/ kobject for people to chain off of */
+extern struct kobject *mm_kobj;
 /* The global /sys/hypervisor/ kobject for people to chain off of */
 extern struct kobject *hypervisor_kobj;
 /* The global /sys/power/ kobject for people to chain off of */
index 04a3556bdea6b87e654db168240139dc887decb4..0be7795655fab4279d3b9b4a6fa110b01a4fc070 100644 (file)
@@ -157,11 +157,10 @@ struct kretprobe {
        int nmissed;
        size_t data_size;
        struct hlist_head free_instances;
-       struct hlist_head used_instances;
+       spinlock_t lock;
 };
 
 struct kretprobe_instance {
-       struct hlist_node uflist; /* either on free list or used list */
        struct hlist_node hlist;
        struct kretprobe *rp;
        kprobe_opcode_t *ret_addr;
@@ -201,7 +200,6 @@ static inline int init_test_probes(void)
 }
 #endif /* CONFIG_KPROBES_SANITY_TEST */
 
-extern spinlock_t kretprobe_lock;
 extern struct mutex kprobe_mutex;
 extern int arch_prepare_kprobe(struct kprobe *p);
 extern void arch_arm_kprobe(struct kprobe *p);
@@ -214,6 +212,9 @@ extern void kprobes_inc_nmissed_count(struct kprobe *p);
 
 /* Get the kprobe at this addr (if any) - called with preemption disabled */
 struct kprobe *get_kprobe(void *addr);
+void kretprobe_hash_lock(struct task_struct *tsk,
+                        struct hlist_head **head, unsigned long *flags);
+void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags);
 struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
 
 /* kprobe_running() will just return the current_kprobe on this CPU */
index 00dd957e245b43839db5e0972e74ff541e4dafd1..aabc8a13ba71c7b6f9eab1ddf3842b18800045d4 100644 (file)
@@ -6,7 +6,8 @@
 
 struct task_struct *kthread_create(int (*threadfn)(void *data),
                                   void *data,
-                                  const char namefmt[], ...);
+                                  const char namefmt[], ...)
+       __attribute__((format(printf, 3, 4)));
 
 /**
  * kthread_run - create and wake a thread.
index 1d379787f2e78e4a1b56cb35c448e8e84ff39f38..173febac6656c20eaec69a8a03dc5fe53d9d9759 100644 (file)
@@ -47,7 +47,7 @@ struct lcd_ops {
         int (*set_contrast)(struct lcd_device *, int contrast);
        /* Check if given framebuffer device is the one LCD is bound to;
           return 0 if not, !=0 if it is. If NULL, lcd always matches the fb. */
-       int (*check_fb)(struct fb_info *);
+       int (*check_fb)(struct lcd_device *, struct fb_info *);
 };
 
 struct lcd_device {
diff --git a/include/linux/leds-pca9532.h b/include/linux/leds-pca9532.h
new file mode 100644 (file)
index 0000000..81b4207
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * pca9532.h - platform data structure for pca9532 led controller
+ *
+ * Copyright (C) 2008 Riku Voipio <riku.voipio@movial.fi>
+ *
+ * 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.
+ *
+ * Datasheet: http://www.nxp.com/acrobat/datasheets/PCA9532_3.pdf
+ *
+ */
+
+#ifndef __LINUX_PCA9532_H
+#define __LINUX_PCA9532_H
+
+#include <linux/leds.h>
+
+enum pca9532_state {
+       PCA9532_OFF  = 0x0,
+       PCA9532_ON   = 0x1,
+       PCA9532_PWM0 = 0x2,
+       PCA9532_PWM1 = 0x3
+};
+
+enum pca9532_type { PCA9532_TYPE_NONE, PCA9532_TYPE_LED,
+       PCA9532_TYPE_N2100_BEEP };
+
+struct pca9532_led {
+       u8 id;
+       struct i2c_client *client;
+       char *name;
+       struct led_classdev ldev;
+       enum pca9532_type type;
+       enum pca9532_state state;
+};
+
+struct pca9532_platform_data {
+       struct pca9532_led leds[16];
+       u8 pwm[2];
+       u8 psc[2];
+};
+
+#endif /* __LINUX_PCA9532_H */
+
index 519df72e939d30a4355747aa4cea1140b5c3bef9..d41ccb56146ace0077cf09b2add2a5c6209a266b 100644 (file)
@@ -48,7 +48,7 @@ struct led_classdev {
 
        struct device           *dev;
        struct list_head         node;                  /* LED Device list */
-       char                    *default_trigger;       /* Trigger to use */
+       const char              *default_trigger;       /* Trigger to use */
 
 #ifdef CONFIG_LEDS_TRIGGERS
        /* Protects the trigger data below */
@@ -118,6 +118,20 @@ extern void ledtrig_ide_activity(void);
 #define ledtrig_ide_activity() do {} while(0)
 #endif
 
+/*
+ * Generic LED platform data for describing LED names and default triggers.
+ */
+struct led_info {
+       const char      *name;
+       char            *default_trigger;
+       int             flags;
+};
+
+struct led_platform_data {
+       int             num_leds;
+       struct led_info *leds;
+};
+
 /* For the leds-gpio driver */
 struct gpio_led {
        const char *name;
index 139ec41d9c2ebd7e74d0c53e04433dd996a3f233..453916bc0412cbacd4ed2844fe71599ac07bc086 100644 (file)
@@ -61,14 +61,10 @@ extern 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
 
 
 /**
diff --git a/include/linux/mISDNdsp.h b/include/linux/mISDNdsp.h
new file mode 100644 (file)
index 0000000..6b71d2d
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef __mISDNdsp_H__
+#define __mISDNdsp_H__
+
+struct mISDN_dsp_element_arg {
+       char    *name;
+       char    *def;
+       char    *desc;
+};
+
+struct mISDN_dsp_element {
+       char    *name;
+       void    *(*new)(const char *arg);
+       void    (*free)(void *p);
+       void    (*process_tx)(void *p, unsigned char *data, int len);
+       void    (*process_rx)(void *p, unsigned char *data, int len);
+       int     num_args;
+       struct mISDN_dsp_element_arg
+               *args;
+};
+
+extern int  mISDN_dsp_element_register(struct mISDN_dsp_element *elem);
+extern void mISDN_dsp_element_unregister(struct mISDN_dsp_element *elem);
+
+struct dsp_features {
+       int     hfc_id; /* unique id to identify the chip (or -1) */
+       int     hfc_dtmf; /* set if HFCmulti card supports dtmf */
+       int     hfc_loops; /* set if card supports tone loops */
+       int     hfc_echocanhw; /* set if card supports echocancelation*/
+       int     pcm_id; /* unique id to identify the pcm bus (or -1) */
+       int     pcm_slots; /* number of slots on the pcm bus */
+       int     pcm_banks; /* number of IO banks of pcm bus */
+       int     unclocked; /* data is not clocked (has jitter/loss) */
+       int     unordered; /* data is unordered (packets have index) */
+};
+
+#endif
+
diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h
new file mode 100644 (file)
index 0000000..e794dfb
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ *
+ * Author      Karsten Keil <kkeil@novell.com>
+ *
+ *   Basic declarations for the mISDN HW channels
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MISDNHW_H
+#define MISDNHW_H
+#include <linux/mISDNif.h>
+#include <linux/timer.h>
+
+/*
+ * HW DEBUG 0xHHHHGGGG
+ * H - hardware driver specific bits
+ * G - for all drivers
+ */
+
+#define DEBUG_HW               0x00000001
+#define DEBUG_HW_OPEN          0x00000002
+#define DEBUG_HW_DCHANNEL      0x00000100
+#define DEBUG_HW_DFIFO         0x00000200
+#define DEBUG_HW_BCHANNEL      0x00001000
+#define DEBUG_HW_BFIFO         0x00002000
+
+#define MAX_DFRAME_LEN_L1      300
+#define MAX_MON_FRAME          32
+#define MAX_LOG_SPACE          2048
+#define MISDN_COPY_SIZE                32
+
+/* channel->Flags bit field */
+#define FLG_TX_BUSY            0       /* tx_buf in use */
+#define FLG_TX_NEXT            1       /* next_skb in use */
+#define FLG_L1_BUSY            2       /* L1 is permanent busy */
+#define FLG_L2_ACTIVATED       3       /* activated from L2 */
+#define FLG_OPEN               5       /* channel is in use */
+#define FLG_ACTIVE             6       /* channel is activated */
+#define FLG_BUSY_TIMER         7
+/* channel type */
+#define FLG_DCHANNEL           8       /* channel is D-channel */
+#define FLG_BCHANNEL           9       /* channel is B-channel */
+#define FLG_ECHANNEL           10      /* channel is E-channel */
+#define FLG_TRANSPARENT                12      /* channel use transparent data */
+#define FLG_HDLC               13      /* channel use hdlc data */
+#define FLG_L2DATA             14      /* channel use L2 DATA primitivs */
+#define FLG_ORIGIN             15      /* channel is on origin site */
+/* channel specific stuff */
+/* arcofi specific */
+#define FLG_ARCOFI_TIMER       16
+#define FLG_ARCOFI_ERROR       17
+/* isar specific */
+#define FLG_INITIALIZED                16
+#define FLG_DLEETX             17
+#define FLG_LASTDLE            18
+#define FLG_FIRST              19
+#define FLG_LASTDATA           20
+#define FLG_NMD_DATA           21
+#define FLG_FTI_RUN            22
+#define FLG_LL_OK              23
+#define FLG_LL_CONN            24
+#define FLG_DTMFSEND           25
+
+/* workq events */
+#define FLG_RECVQUEUE          30
+#define        FLG_PHCHANGE            31
+
+#define schedule_event(s, ev)  do { \
+                                       test_and_set_bit(ev, &((s)->Flags)); \
+                                       schedule_work(&((s)->workq)); \
+                               } while (0)
+
+struct dchannel {
+       struct mISDNdevice      dev;
+       u_long                  Flags;
+       struct work_struct      workq;
+       void                    (*phfunc) (struct dchannel *);
+       u_int                   state;
+       void                    *l1;
+       /* HW access */
+       u_char                  (*read_reg) (void *, u_char);
+       void                    (*write_reg) (void *, u_char, u_char);
+       void                    (*read_fifo) (void *, u_char *, int);
+       void                    (*write_fifo) (void *, u_char *, int);
+       void                    *hw;
+       int                     slot;   /* multiport card channel slot */
+       struct timer_list       timer;
+       /* receive data */
+       struct sk_buff          *rx_skb;
+       int                     maxlen;
+       /* send data */
+       struct sk_buff_head     squeue;
+       struct sk_buff_head     rqueue;
+       struct sk_buff          *tx_skb;
+       int                     tx_idx;
+       int                     debug;
+       /* statistics */
+       int                     err_crc;
+       int                     err_tx;
+       int                     err_rx;
+};
+
+typedef int    (dchannel_l1callback)(struct dchannel *, u_int);
+extern int     create_l1(struct dchannel *, dchannel_l1callback *);
+
+/* private L1 commands */
+#define INFO0          0x8002
+#define INFO1          0x8102
+#define INFO2          0x8202
+#define INFO3_P8       0x8302
+#define INFO3_P10      0x8402
+#define INFO4_P8       0x8502
+#define INFO4_P10      0x8602
+#define LOSTFRAMING    0x8702
+#define ANYSIGNAL      0x8802
+#define HW_POWERDOWN   0x8902
+#define HW_RESET_REQ   0x8a02
+#define HW_POWERUP_REQ 0x8b02
+#define HW_DEACT_REQ   0x8c02
+#define HW_ACTIVATE_REQ        0x8e02
+#define HW_D_NOBLOCKED  0x8f02
+#define HW_RESET_IND   0x9002
+#define HW_POWERUP_IND 0x9102
+#define HW_DEACT_IND   0x9202
+#define HW_ACTIVATE_IND        0x9302
+#define HW_DEACT_CNF   0x9402
+#define HW_TESTLOOP    0x9502
+#define HW_TESTRX_RAW  0x9602
+#define HW_TESTRX_HDLC 0x9702
+#define HW_TESTRX_OFF  0x9802
+
+struct layer1;
+extern int     l1_event(struct layer1 *, u_int);
+
+
+struct bchannel {
+       struct mISDNchannel     ch;
+       int                     nr;
+       u_long                  Flags;
+       struct work_struct      workq;
+       u_int                   state;
+       /* HW access */
+       u_char                  (*read_reg) (void *, u_char);
+       void                    (*write_reg) (void *, u_char, u_char);
+       void                    (*read_fifo) (void *, u_char *, int);
+       void                    (*write_fifo) (void *, u_char *, int);
+       void                    *hw;
+       int                     slot;   /* multiport card channel slot */
+       struct timer_list       timer;
+       /* receive data */
+       struct sk_buff          *rx_skb;
+       int                     maxlen;
+       /* send data */
+       struct sk_buff          *next_skb;
+       struct sk_buff          *tx_skb;
+       struct sk_buff_head     rqueue;
+       int                     rcount;
+       int                     tx_idx;
+       int                     debug;
+       /* statistics */
+       int                     err_crc;
+       int                     err_tx;
+       int                     err_rx;
+};
+
+extern int     mISDN_initdchannel(struct dchannel *, int, void *);
+extern int     mISDN_initbchannel(struct bchannel *, int);
+extern int     mISDN_freedchannel(struct dchannel *);
+extern int     mISDN_freebchannel(struct bchannel *);
+extern void    queue_ch_frame(struct mISDNchannel *, u_int,
+                       int, struct sk_buff *);
+extern int     dchannel_senddata(struct dchannel *, struct sk_buff *);
+extern int     bchannel_senddata(struct bchannel *, struct sk_buff *);
+extern void    recv_Dchannel(struct dchannel *);
+extern void    recv_Bchannel(struct bchannel *);
+extern void    recv_Dchannel_skb(struct dchannel *, struct sk_buff *);
+extern void    recv_Bchannel_skb(struct bchannel *, struct sk_buff *);
+extern void    confirm_Bsend(struct bchannel *bch);
+extern int     get_next_bframe(struct bchannel *);
+extern int     get_next_dframe(struct dchannel *);
+
+#endif
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
new file mode 100644 (file)
index 0000000..5c948f3
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ *
+ * Author      Karsten Keil <kkeil@novell.com>
+ *
+ * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
+ *
+ */
+
+#ifndef mISDNIF_H
+#define mISDNIF_H
+
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/socket.h>
+
+/*
+ * ABI Version 32 bit
+ *
+ * <8 bit> Major version
+ *             - changed if any interface become backwards incompatible
+ *
+ * <8 bit> Minor version
+ *              - changed if any interface is extended but backwards compatible
+ *
+ * <16 bit> Release number
+ *              - should be incremented on every checkin
+ */
+#define        MISDN_MAJOR_VERSION     1
+#define        MISDN_MINOR_VERSION     0
+#define MISDN_RELEASE          18
+
+/* primitives for information exchange
+ * generell format
+ * <16  bit  0 >
+ * <8  bit command>
+ *    BIT 8 = 1 LAYER private
+ *    BIT 7 = 1 answer
+ *    BIT 6 = 1 DATA
+ * <8  bit target layer mask>
+ *
+ * Layer = 00 is reserved for general commands
+   Layer = 01  L2 -> HW
+   Layer = 02  HW -> L2
+   Layer = 04  L3 -> L2
+   Layer = 08  L2 -> L3
+ * Layer = FF is reserved for broadcast commands
+ */
+
+#define MISDN_CMDMASK          0xff00
+#define MISDN_LAYERMASK                0x00ff
+
+/* generell commands */
+#define OPEN_CHANNEL           0x0100
+#define CLOSE_CHANNEL          0x0200
+#define CONTROL_CHANNEL                0x0300
+#define CHECK_DATA             0x0400
+
+/* layer 2 -> layer 1 */
+#define PH_ACTIVATE_REQ                0x0101
+#define PH_DEACTIVATE_REQ      0x0201
+#define PH_DATA_REQ            0x2001
+#define MPH_ACTIVATE_REQ       0x0501
+#define MPH_DEACTIVATE_REQ     0x0601
+#define MPH_INFORMATION_REQ    0x0701
+#define PH_CONTROL_REQ         0x0801
+
+/* layer 1 -> layer 2 */
+#define PH_ACTIVATE_IND                0x0102
+#define PH_ACTIVATE_CNF                0x4102
+#define PH_DEACTIVATE_IND      0x0202
+#define PH_DEACTIVATE_CNF      0x4202
+#define PH_DATA_IND            0x2002
+#define MPH_ACTIVATE_IND       0x0502
+#define MPH_DEACTIVATE_IND     0x0602
+#define MPH_INFORMATION_IND    0x0702
+#define PH_DATA_CNF            0x6002
+#define PH_CONTROL_IND         0x0802
+#define PH_CONTROL_CNF         0x4802
+
+/* layer 3 -> layer 2 */
+#define DL_ESTABLISH_REQ       0x1004
+#define DL_RELEASE_REQ         0x1104
+#define DL_DATA_REQ            0x3004
+#define DL_UNITDATA_REQ                0x3104
+#define DL_INFORMATION_REQ     0x0004
+
+/* layer 2 -> layer 3 */
+#define DL_ESTABLISH_IND       0x1008
+#define DL_ESTABLISH_CNF       0x5008
+#define DL_RELEASE_IND         0x1108
+#define DL_RELEASE_CNF         0x5108
+#define DL_DATA_IND            0x3008
+#define DL_UNITDATA_IND                0x3108
+#define DL_INFORMATION_IND     0x0008
+
+/* intern layer 2 managment */
+#define MDL_ASSIGN_REQ         0x1804
+#define MDL_ASSIGN_IND         0x1904
+#define MDL_REMOVE_REQ         0x1A04
+#define MDL_REMOVE_IND         0x1B04
+#define MDL_STATUS_UP_IND      0x1C04
+#define MDL_STATUS_DOWN_IND    0x1D04
+#define MDL_STATUS_UI_IND      0x1E04
+#define MDL_ERROR_IND          0x1F04
+#define MDL_ERROR_RSP          0x5F04
+
+/* DL_INFORMATION_IND types */
+#define DL_INFO_L2_CONNECT     0x0001
+#define DL_INFO_L2_REMOVED     0x0002
+
+/* PH_CONTROL types */
+/* TOUCH TONE IS 0x20XX  XX "0"..."9", "A","B","C","D","*","#" */
+#define DTMF_TONE_VAL          0x2000
+#define DTMF_TONE_MASK         0x007F
+#define DTMF_TONE_START                0x2100
+#define DTMF_TONE_STOP         0x2200
+#define DTMF_HFC_COEF          0x4000
+#define DSP_CONF_JOIN          0x2403
+#define DSP_CONF_SPLIT         0x2404
+#define DSP_RECEIVE_OFF                0x2405
+#define DSP_RECEIVE_ON         0x2406
+#define DSP_ECHO_ON            0x2407
+#define DSP_ECHO_OFF           0x2408
+#define DSP_MIX_ON             0x2409
+#define DSP_MIX_OFF            0x240a
+#define DSP_DELAY              0x240b
+#define DSP_JITTER             0x240c
+#define DSP_TXDATA_ON          0x240d
+#define DSP_TXDATA_OFF         0x240e
+#define DSP_TX_DEJITTER                0x240f
+#define DSP_TX_DEJ_OFF         0x2410
+#define DSP_TONE_PATT_ON       0x2411
+#define DSP_TONE_PATT_OFF      0x2412
+#define DSP_VOL_CHANGE_TX      0x2413
+#define DSP_VOL_CHANGE_RX      0x2414
+#define DSP_BF_ENABLE_KEY      0x2415
+#define DSP_BF_DISABLE         0x2416
+#define DSP_BF_ACCEPT          0x2416
+#define DSP_BF_REJECT          0x2417
+#define DSP_PIPELINE_CFG       0x2418
+#define HFC_VOL_CHANGE_TX      0x2601
+#define HFC_VOL_CHANGE_RX      0x2602
+#define HFC_SPL_LOOP_ON                0x2603
+#define HFC_SPL_LOOP_OFF       0x2604
+
+/* DSP_TONE_PATT_ON parameter */
+#define TONE_OFF                       0x0000
+#define TONE_GERMAN_DIALTONE           0x0001
+#define TONE_GERMAN_OLDDIALTONE                0x0002
+#define TONE_AMERICAN_DIALTONE         0x0003
+#define TONE_GERMAN_DIALPBX            0x0004
+#define TONE_GERMAN_OLDDIALPBX         0x0005
+#define TONE_AMERICAN_DIALPBX          0x0006
+#define TONE_GERMAN_RINGING            0x0007
+#define TONE_GERMAN_OLDRINGING         0x0008
+#define TONE_AMERICAN_RINGPBX          0x000b
+#define TONE_GERMAN_RINGPBX            0x000c
+#define TONE_GERMAN_OLDRINGPBX         0x000d
+#define TONE_AMERICAN_RINGING          0x000e
+#define TONE_GERMAN_BUSY               0x000f
+#define TONE_GERMAN_OLDBUSY            0x0010
+#define TONE_AMERICAN_BUSY             0x0011
+#define TONE_GERMAN_HANGUP             0x0012
+#define TONE_GERMAN_OLDHANGUP          0x0013
+#define TONE_AMERICAN_HANGUP           0x0014
+#define TONE_SPECIAL_INFO              0x0015
+#define TONE_GERMAN_GASSENBESETZT      0x0016
+#define TONE_GERMAN_AUFSCHALTTON       0x0016
+
+/* MPH_INFORMATION_IND */
+#define L1_SIGNAL_LOS_OFF      0x0010
+#define L1_SIGNAL_LOS_ON       0x0011
+#define L1_SIGNAL_AIS_OFF      0x0012
+#define L1_SIGNAL_AIS_ON       0x0013
+#define L1_SIGNAL_RDI_OFF      0x0014
+#define L1_SIGNAL_RDI_ON       0x0015
+#define L1_SIGNAL_SLIP_RX      0x0020
+#define L1_SIGNAL_SLIP_TX      0x0021
+
+/*
+ * protocol ids
+ * D channel 1-31
+ * B channel 33 - 63
+ */
+
+#define ISDN_P_NONE            0
+#define ISDN_P_BASE            0
+#define ISDN_P_TE_S0           0x01
+#define ISDN_P_NT_S0           0x02
+#define ISDN_P_TE_E1           0x03
+#define ISDN_P_NT_E1           0x04
+#define ISDN_P_LAPD_TE         0x10
+#define        ISDN_P_LAPD_NT          0x11
+
+#define ISDN_P_B_MASK          0x1f
+#define ISDN_P_B_START         0x20
+
+#define ISDN_P_B_RAW           0x21
+#define ISDN_P_B_HDLC          0x22
+#define ISDN_P_B_X75SLP                0x23
+#define ISDN_P_B_L2DTMF                0x24
+#define ISDN_P_B_L2DSP         0x25
+#define ISDN_P_B_L2DSPHDLC     0x26
+
+#define OPTION_L2_PMX          1
+#define OPTION_L2_PTP          2
+#define OPTION_L2_FIXEDTEI     3
+#define OPTION_L2_CLEANUP      4
+
+/* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */
+#define MISDN_MAX_IDLEN                20
+
+struct mISDNhead {
+       unsigned int    prim;
+       unsigned int    id;
+}  __attribute__((packed));
+
+#define MISDN_HEADER_LEN       sizeof(struct mISDNhead)
+#define MAX_DATA_SIZE          2048
+#define MAX_DATA_MEM           (MAX_DATA_SIZE + MISDN_HEADER_LEN)
+#define MAX_DFRAME_LEN         260
+
+#define MISDN_ID_ADDR_MASK     0xFFFF
+#define MISDN_ID_TEI_MASK      0xFF00
+#define MISDN_ID_SAPI_MASK     0x00FF
+#define MISDN_ID_TEI_ANY       0x7F00
+
+#define MISDN_ID_ANY           0xFFFF
+#define MISDN_ID_NONE          0xFFFE
+
+#define GROUP_TEI              127
+#define TEI_SAPI               63
+#define CTRL_SAPI              0
+
+#define MISDN_CHMAP_SIZE       4
+
+#define SOL_MISDN      0
+
+struct sockaddr_mISDN {
+       sa_family_t    family;
+       unsigned char   dev;
+       unsigned char   channel;
+       unsigned char   sapi;
+       unsigned char   tei;
+};
+
+/* timer device ioctl */
+#define IMADDTIMER     _IOR('I', 64, int)
+#define IMDELTIMER     _IOR('I', 65, int)
+/* socket ioctls */
+#define        IMGETVERSION    _IOR('I', 66, int)
+#define        IMGETCOUNT      _IOR('I', 67, int)
+#define IMGETDEVINFO   _IOR('I', 68, int)
+#define IMCTRLREQ      _IOR('I', 69, int)
+#define IMCLEAR_L2     _IOR('I', 70, int)
+
+struct mISDNversion {
+       unsigned char   major;
+       unsigned char   minor;
+       unsigned short  release;
+};
+
+struct mISDN_devinfo {
+       u_int                   id;
+       u_int                   Dprotocols;
+       u_int                   Bprotocols;
+       u_int                   protocol;
+       u_long                  channelmap[MISDN_CHMAP_SIZE];
+       u_int                   nrbchan;
+       char                    name[MISDN_MAX_IDLEN];
+};
+
+/* CONTROL_CHANNEL parameters */
+#define MISDN_CTRL_GETOP               0x0000
+#define MISDN_CTRL_LOOP                        0x0001
+#define MISDN_CTRL_CONNECT             0x0002
+#define MISDN_CTRL_DISCONNECT          0x0004
+#define MISDN_CTRL_PCMCONNECT          0x0010
+#define MISDN_CTRL_PCMDISCONNECT       0x0020
+#define MISDN_CTRL_SETPEER             0x0040
+#define MISDN_CTRL_UNSETPEER           0x0080
+#define MISDN_CTRL_RX_OFF              0x0100
+#define MISDN_CTRL_HW_FEATURES_OP      0x2000
+#define MISDN_CTRL_HW_FEATURES         0x2001
+#define MISDN_CTRL_HFC_OP              0x4000
+#define MISDN_CTRL_HFC_PCM_CONN                0x4001
+#define MISDN_CTRL_HFC_PCM_DISC                0x4002
+#define MISDN_CTRL_HFC_CONF_JOIN       0x4003
+#define MISDN_CTRL_HFC_CONF_SPLIT      0x4004
+#define MISDN_CTRL_HFC_RECEIVE_OFF     0x4005
+#define MISDN_CTRL_HFC_RECEIVE_ON      0x4006
+#define MISDN_CTRL_HFC_ECHOCAN_ON      0x4007
+#define MISDN_CTRL_HFC_ECHOCAN_OFF     0x4008
+
+
+/* socket options */
+#define MISDN_TIME_STAMP               0x0001
+
+struct mISDN_ctrl_req {
+       int             op;
+       int             channel;
+       int             p1;
+       int             p2;
+};
+
+/* muxer options */
+#define MISDN_OPT_ALL          1
+#define MISDN_OPT_TEIMGR       2
+
+#ifdef __KERNEL__
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/net.h>
+#include <net/sock.h>
+#include <linux/completion.h>
+
+#define DEBUG_CORE             0x000000ff
+#define DEBUG_CORE_FUNC                0x00000002
+#define DEBUG_SOCKET           0x00000004
+#define DEBUG_MANAGER          0x00000008
+#define DEBUG_SEND_ERR         0x00000010
+#define DEBUG_MSG_THREAD       0x00000020
+#define DEBUG_QUEUE_FUNC       0x00000040
+#define DEBUG_L1               0x0000ff00
+#define DEBUG_L1_FSM           0x00000200
+#define DEBUG_L2               0x00ff0000
+#define DEBUG_L2_FSM           0x00020000
+#define DEBUG_L2_CTRL          0x00040000
+#define DEBUG_L2_RECV          0x00080000
+#define DEBUG_L2_TEI           0x00100000
+#define DEBUG_L2_TEIFSM                0x00200000
+#define DEBUG_TIMER            0x01000000
+
+#define mISDN_HEAD_P(s)                ((struct mISDNhead *)&s->cb[0])
+#define mISDN_HEAD_PRIM(s)     (((struct mISDNhead *)&s->cb[0])->prim)
+#define mISDN_HEAD_ID(s)       (((struct mISDNhead *)&s->cb[0])->id)
+
+/* socket states */
+#define MISDN_OPEN     1
+#define MISDN_BOUND    2
+#define MISDN_CLOSED   3
+
+struct mISDNchannel;
+struct mISDNdevice;
+struct mISDNstack;
+
+struct channel_req {
+       u_int                   protocol;
+       struct sockaddr_mISDN   adr;
+       struct mISDNchannel     *ch;
+};
+
+typedef        int     (ctrl_func_t)(struct mISDNchannel *, u_int, void *);
+typedef        int     (send_func_t)(struct mISDNchannel *, struct sk_buff *);
+typedef int    (create_func_t)(struct channel_req *);
+
+struct Bprotocol {
+       struct list_head        list;
+       char                    *name;
+       u_int                   Bprotocols;
+       create_func_t           *create;
+};
+
+struct mISDNchannel {
+       struct list_head        list;
+       u_int                   protocol;
+       u_int                   nr;
+       u_long                  opt;
+       u_int                   addr;
+       struct mISDNstack       *st;
+       struct mISDNchannel     *peer;
+       send_func_t             *send;
+       send_func_t             *recv;
+       ctrl_func_t             *ctrl;
+};
+
+struct mISDN_sock_list {
+       struct hlist_head       head;
+       rwlock_t                lock;
+};
+
+struct mISDN_sock {
+       struct sock             sk;
+       struct mISDNchannel     ch;
+       u_int                   cmask;
+       struct mISDNdevice      *dev;
+};
+
+
+
+struct mISDNdevice {
+       struct mISDNchannel     D;
+       u_int                   id;
+       char                    name[MISDN_MAX_IDLEN];
+       u_int                   Dprotocols;
+       u_int                   Bprotocols;
+       u_int                   nrbchan;
+       u_long                  channelmap[MISDN_CHMAP_SIZE];
+       struct list_head        bchannels;
+       struct mISDNchannel     *teimgr;
+       struct device           dev;
+};
+
+struct mISDNstack {
+       u_long                  status;
+       struct mISDNdevice      *dev;
+       struct task_struct      *thread;
+       struct completion       *notify;
+       wait_queue_head_t       workq;
+       struct sk_buff_head     msgq;
+       struct list_head        layer2;
+       struct mISDNchannel     *layer1;
+       struct mISDNchannel     own;
+       struct mutex            lmutex; /* protect lists */
+       struct mISDN_sock_list  l1sock;
+#ifdef MISDN_MSG_STATS
+       u_int                   msg_cnt;
+       u_int                   sleep_cnt;
+       u_int                   stopped_cnt;
+#endif
+};
+
+/* global alloc/queue dunctions */
+
+static inline struct sk_buff *
+mI_alloc_skb(unsigned int len, gfp_t gfp_mask)
+{
+       struct sk_buff  *skb;
+
+       skb = alloc_skb(len + MISDN_HEADER_LEN, gfp_mask);
+       if (likely(skb))
+               skb_reserve(skb, MISDN_HEADER_LEN);
+       return skb;
+}
+
+static inline struct sk_buff *
+_alloc_mISDN_skb(u_int prim, u_int id, u_int len, void *dp, gfp_t gfp_mask)
+{
+       struct sk_buff  *skb = mI_alloc_skb(len, gfp_mask);
+       struct mISDNhead *hh;
+
+       if (!skb)
+               return NULL;
+       if (len)
+               memcpy(skb_put(skb, len), dp, len);
+       hh = mISDN_HEAD_P(skb);
+       hh->prim = prim;
+       hh->id = id;
+       return skb;
+}
+
+static inline void
+_queue_data(struct mISDNchannel *ch, u_int prim,
+    u_int id, u_int len, void *dp, gfp_t gfp_mask)
+{
+       struct sk_buff          *skb;
+
+       if (!ch->peer)
+               return;
+       skb = _alloc_mISDN_skb(prim, id, len, dp, gfp_mask);
+       if (!skb)
+               return;
+       if (ch->recv(ch->peer, skb))
+               dev_kfree_skb(skb);
+}
+
+/* global register/unregister functions */
+
+extern int     mISDN_register_device(struct mISDNdevice *, char *name);
+extern void    mISDN_unregister_device(struct mISDNdevice *);
+extern int     mISDN_register_Bprotocol(struct Bprotocol *);
+extern void    mISDN_unregister_Bprotocol(struct Bprotocol *);
+
+extern void    set_channel_address(struct mISDNchannel *, u_int, u_int);
+
+#endif /* __KERNEL__ */
+#endif /* mISDNIF_H */
index 0cb98053537af4874ef83cfc149c6af629758694..53d5fafd85c30a61e381f7d3762fa6a3841aca6c 100644 (file)
@@ -53,7 +53,7 @@
 #define STL_SIOMEMMAJOR                28
 #define ACSI_MAJOR             28
 #define AZTECH_CDROM_MAJOR     29
-#define GRAPHDEV_MAJOR         29   /* SparcLinux & Linux/68k /dev/fb */
+#define FB_MAJOR               29   /* /dev/fb* framebuffers */
 #define CM206_CDROM_MAJOR      32
 #define IDE2_MAJOR             33
 #define IDE3_MAJOR             34
index d31e36ebb436fd25ec087ac135b5fdbef68ff815..523a286bb477d1d6ab1020140aa4390a5b568571 100644 (file)
@@ -61,8 +61,6 @@ struct maple_device {
 
 struct maple_driver {
        unsigned long function;
-       int (*connect) (struct maple_device * dev);
-       void (*disconnect) (struct maple_device * dev);
        struct device_driver drv;
 };
 
index e6608776bc96138c4fac9eea0b2a4126997bc7b8..fdf3967e13975a4dc24ec7c37026295ea4fa8f0e 100644 (file)
@@ -35,7 +35,10 @@ extern int mem_cgroup_charge(struct page *page, struct mm_struct *mm,
 extern int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
                                        gfp_t gfp_mask);
 extern void mem_cgroup_uncharge_page(struct page *page);
+extern void mem_cgroup_uncharge_cache_page(struct page *page);
 extern void mem_cgroup_move_lists(struct page *page, bool active);
+extern int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask);
+
 extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
                                        struct list_head *dst,
                                        unsigned long *scanned, int order,
@@ -50,9 +53,9 @@ extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
 #define mm_match_cgroup(mm, cgroup)    \
        ((cgroup) == mem_cgroup_from_task((mm)->owner))
 
-extern int mem_cgroup_prepare_migration(struct page *page);
+extern int
+mem_cgroup_prepare_migration(struct page *page, struct page *newpage);
 extern void mem_cgroup_end_migration(struct page *page);
-extern void mem_cgroup_page_migration(struct page *page, struct page *newpage);
 
 /*
  * For memory reclaim.
@@ -97,6 +100,15 @@ static inline void mem_cgroup_uncharge_page(struct page *page)
 {
 }
 
+static inline void mem_cgroup_uncharge_cache_page(struct page *page)
+{
+}
+
+static inline int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask)
+{
+       return 0;
+}
+
 static inline void mem_cgroup_move_lists(struct page *page, bool active)
 {
 }
@@ -112,7 +124,8 @@ static inline int task_in_mem_cgroup(struct task_struct *task,
        return 1;
 }
 
-static inline int mem_cgroup_prepare_migration(struct page *page)
+static inline int
+mem_cgroup_prepare_migration(struct page *page, struct page *newpage)
 {
        return 0;
 }
@@ -121,11 +134,6 @@ static inline void mem_cgroup_end_migration(struct page *page)
 {
 }
 
-static inline void
-mem_cgroup_page_migration(struct page *page, struct page *newpage)
-{
-}
-
 static inline int mem_cgroup_calc_mapped_ratio(struct mem_cgroup *mem)
 {
        return 0;
index ea9f5ad9ec8ea72f56eeff6a9e42a2053e2ba623..763ba81fc0f0a5c6adcb623501ebed6c28200e58 100644 (file)
@@ -13,12 +13,12 @@ struct mem_section;
 #ifdef CONFIG_MEMORY_HOTPLUG
 
 /*
- * Magic number for free bootmem.
+ * Types for free bootmem.
  * The normal smallest mapcount is -1. Here is smaller value than it.
  */
-#define SECTION_INFO           0xfffffffe
-#define MIX_INFO               0xfffffffd
-#define NODE_INFO              0xfffffffc
+#define SECTION_INFO           (-1 - 1)
+#define MIX_SECTION_INFO       (-1 - 2)
+#define NODE_INFO              (-1 - 3)
 
 /*
  * pgdat resizing functions
@@ -199,6 +199,18 @@ extern int walk_memory_resource(unsigned long start_pfn,
                        unsigned long nr_pages, void *arg,
                        int (*func)(unsigned long, unsigned long, void *));
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+
+extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages);
+
+#else
+static inline int is_mem_section_removable(unsigned long pfn,
+                                       unsigned long nr_pages)
+{
+       return 0;
+}
+#endif /* CONFIG_MEMORY_HOTREMOVE */
+
 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);
index 3a39570b81b85e525bea4cde10429ac470546bbe..085c903fe0f1832ce0f46debd8ffcd3f9d5d0564 100644 (file)
@@ -59,6 +59,7 @@ enum {
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
 #include <linux/nodemask.h>
+#include <linux/pagemap.h>
 
 struct mm_struct;
 
@@ -220,6 +221,24 @@ extern int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context);
 extern int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol,
                        int no_context);
 #endif
+
+/* Check if a vma is migratable */
+static inline int vma_migratable(struct vm_area_struct *vma)
+{
+       if (vma->vm_flags & (VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED))
+               return 0;
+       /*
+        * Migration allocates pages in the highest zone. If we cannot
+        * do so then migration (at least from node to node) is not
+        * possible.
+        */
+       if (vma->vm_file &&
+               gfp_zone(mapping_gfp_mask(vma->vm_file->f_mapping))
+                                                               < policy_zone)
+                       return 0;
+       return 1;
+}
+
 #else
 
 struct mempolicy {};
index 37a5cdb03918ffcee2a390b12fe391cdfbf62e69..a9f998a3f48b3d10a35eb0cc08d3e691fe8578e5 100644 (file)
@@ -263,6 +263,10 @@ struct memstick_dev {
        /* Get next request from the media driver.                         */
        int                      (*next_request)(struct memstick_dev *card,
                                                 struct memstick_request **mrq);
+       /* Tell the media driver to stop doing things                      */
+       void                     (*stop)(struct memstick_dev *card);
+       /* Allow the media driver to continue                              */
+       void                     (*start)(struct memstick_dev *card);
 
        struct device            dev;
 };
@@ -284,7 +288,7 @@ struct memstick_host {
        /* Notify the host that some requests are pending. */
        void                (*request)(struct memstick_host *host);
        /* Set host IO parameters (power, clock, etc).     */
-       void                (*set_param)(struct memstick_host *host,
+       int                 (*set_param)(struct memstick_host *host,
                                         enum memstick_param param,
                                         int value);
        unsigned long       private[0] ____cacheline_aligned;
index bb3dd0545928b0e52c6e3e11a326a7f8c48c5a32..49ef857cdb2dc63d6001b843587d742bff17092a 100644 (file)
@@ -1,5 +1,3 @@
-#ifndef MFD_CORE_H
-#define MFD_CORE_H
 /*
  * drivers/mfd/mfd-core.h
  *
@@ -13,6 +11,9 @@
  *
  */
 
+#ifndef MFD_CORE_H
+#define MFD_CORE_H
+
 #include <linux/platform_device.h>
 
 /*
@@ -28,7 +29,13 @@ struct mfd_cell {
        int                     (*suspend)(struct platform_device *dev);
        int                     (*resume)(struct platform_device *dev);
 
-       void                    *driver_data; /* driver-specific data */
+       /* driver-specific data for MFD-aware "cell" drivers */
+       void                    *driver_data;
+
+       /* platform_data can be used to either pass data to "generic"
+          driver or as a hook to mfd_cell for the "cell" drivers */
+       void                    *platform_data;
+       size_t                  data_size;
 
        /*
         * This resources can be specified relatievly to the parent device.
@@ -38,18 +45,11 @@ struct mfd_cell {
        const struct resource   *resources;
 };
 
-static inline struct mfd_cell *
-mfd_get_cell(struct platform_device *pdev)
-{
-       return (struct mfd_cell *)pdev->dev.platform_data;
-}
-
-extern int mfd_add_devices(
-               struct platform_device *parent,
-               const struct mfd_cell *cells, int n_devs,
-               struct resource *mem_base,
-               int irq_base);
+extern int mfd_add_devices(struct device *parent, int id,
+                          const struct mfd_cell *cells, int n_devs,
+                          struct resource *mem_base,
+                          int irq_base);
 
-extern void mfd_remove_devices(struct platform_device *parent);
+extern void mfd_remove_devices(struct device *parent);
 
 #endif
index e10a90a93b5d25a53fd12b5e623e40ffbc285bf3..03aea612d28450f24f96274c922a8da987bb918b 100644 (file)
@@ -3,28 +3,10 @@
 
 #include <linux/mm.h>
 #include <linux/mempolicy.h>
-#include <linux/pagemap.h>
 
 typedef struct page *new_page_t(struct page *, unsigned long private, int **);
 
 #ifdef CONFIG_MIGRATION
-/* Check if a vma is migratable */
-static inline int vma_migratable(struct vm_area_struct *vma)
-{
-       if (vma->vm_flags & (VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED))
-               return 0;
-       /*
-        * Migration allocates pages in the highest zone. If we cannot
-        * do so then migration (at least from node to node) is not
-        * possible.
-        */
-       if (vma->vm_file &&
-               gfp_zone(mapping_gfp_mask(vma->vm_file->f_mapping))
-                                                               < policy_zone)
-                       return 0;
-       return 1;
-}
-
 extern int isolate_lru_page(struct page *p, struct list_head *pagelist);
 extern int putback_lru_pages(struct list_head *l);
 extern int migrate_page(struct address_space *,
@@ -39,9 +21,6 @@ extern int migrate_vmas(struct mm_struct *mm,
                const nodemask_t *from, const nodemask_t *to,
                unsigned long flags);
 #else
-static inline int vma_migratable(struct vm_area_struct *vma)
-                                       { return 0; }
-
 static inline int isolate_lru_page(struct page *p, struct list_head *list)
                                        { return -ENOSYS; }
 static inline int putback_lru_pages(struct list_head *l) { return 0; }
index 81b3dd5206e04e659c3fae8114e12a20175c5128..655ea0d1ee1474d11a1dbd23c51bf5ef8f679fda 100644 (file)
@@ -68,6 +68,14 @@ enum {
        MLX4_DEV_CAP_FLAG_UD_MCAST      = 1 << 21
 };
 
+enum {
+       MLX4_BMME_FLAG_LOCAL_INV        = 1 <<  6,
+       MLX4_BMME_FLAG_REMOTE_INV       = 1 <<  7,
+       MLX4_BMME_FLAG_TYPE_2_WIN       = 1 <<  9,
+       MLX4_BMME_FLAG_RESERVED_LKEY    = 1 << 10,
+       MLX4_BMME_FLAG_FAST_REG_WR      = 1 << 11,
+};
+
 enum mlx4_event {
        MLX4_EVENT_TYPE_COMP               = 0x00,
        MLX4_EVENT_TYPE_PATH_MIG           = 0x01,
@@ -184,6 +192,8 @@ struct mlx4_caps {
        u32                     max_msg_sz;
        u32                     page_size_cap;
        u32                     flags;
+       u32                     bmme_flags;
+       u32                     reserved_lkey;
        u16                     stat_rate_support;
        u8                      port_width_cap[MLX4_MAX_PORTS + 1];
        int                     max_gso_sz;
index 7f128b266faa39044cc85e4f7175aed51664fe16..bf8f11982dae374f70f3b8b79494823ca96d2e36 100644 (file)
@@ -164,11 +164,13 @@ enum {
        MLX4_WQE_CTRL_SOLICITED         = 1 << 1,
        MLX4_WQE_CTRL_IP_CSUM           = 1 << 4,
        MLX4_WQE_CTRL_TCP_UDP_CSUM      = 1 << 5,
+       MLX4_WQE_CTRL_INS_VLAN          = 1 << 6,
 };
 
 struct mlx4_wqe_ctrl_seg {
        __be32                  owner_opcode;
-       u8                      reserved2[3];
+       __be16                  vlan_tag;
+       u8                      ins_vlan;
        u8                      fence_size;
        /*
         * High 24 bits are SRC remote buffer; low 8 bits are flags:
@@ -219,7 +221,7 @@ struct mlx4_wqe_datagram_seg {
        __be32                  reservd[2];
 };
 
-struct mlx4_lso_seg {
+struct mlx4_wqe_lso_seg {
        __be32                  mss_hdr_size;
        __be32                  header[0];
 };
@@ -233,6 +235,14 @@ struct mlx4_wqe_bind_seg {
        __be64                  length;
 };
 
+enum {
+       MLX4_WQE_FMR_PERM_LOCAL_READ    = 1 << 27,
+       MLX4_WQE_FMR_PERM_LOCAL_WRITE   = 1 << 28,
+       MLX4_WQE_FMR_PERM_REMOTE_READ   = 1 << 29,
+       MLX4_WQE_FMR_PERM_REMOTE_WRITE  = 1 << 30,
+       MLX4_WQE_FMR_PERM_ATOMIC        = 1 << 31
+};
+
 struct mlx4_wqe_fmr_seg {
        __be32                  flags;
        __be32                  mem_key;
@@ -255,11 +265,11 @@ struct mlx4_wqe_fmr_ext_seg {
 };
 
 struct mlx4_wqe_local_inval_seg {
-       u8                      flags;
-       u8                      reserved1[3];
+       __be32                  flags;
+       u32                     reserved1;
        __be32                  mem_key;
-       u8                      reserved2[3];
-       u8                      guest_id;
+       u32                     reserved2[2];
+       __be32                  guest_id;
        __be64                  pa;
 };
 
index 2128ef7780c6f475a8b3574fdd1a2ad99ad36a4a..866a3dbe5c75b98659ecdd7d2514f63fb9de87cc 100644 (file)
@@ -41,6 +41,9 @@ extern unsigned long mmap_min_addr;
 
 #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
 
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
+
 /*
  * Linux kernel virtual memory manager primitives.
  * The idea being to have a "virtual" mm in the same way
@@ -100,6 +103,7 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_DONTEXPAND  0x00040000      /* Cannot expand with mremap() */
 #define VM_RESERVED    0x00080000      /* Count as reserved_vm like IO */
 #define VM_ACCOUNT     0x00100000      /* Is a VM accounted object */
+#define VM_NORESERVE   0x00200000      /* should the VM suppress accounting */
 #define VM_HUGETLB     0x00400000      /* Huge TLB Page VM */
 #define VM_NONLINEAR   0x00800000      /* Is non-linear (remap_file_pages) */
 #define VM_MAPPED_COPY 0x01000000      /* T if mapped copy of data (nommu mmap) */
@@ -166,12 +170,16 @@ struct vm_operations_struct {
        void (*open)(struct vm_area_struct * area);
        void (*close)(struct vm_area_struct * area);
        int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
-       unsigned long (*nopfn)(struct vm_area_struct *area,
-                       unsigned long address);
 
        /* notification that a previously read-only page is about to become
         * writable, if an error is returned it will cause a SIGBUS */
        int (*page_mkwrite)(struct vm_area_struct *vma, struct page *page);
+
+       /* called by access_process_vm when get_user_pages() fails, typically
+        * for use by special VMAs that can switch between memory and hardware
+        */
+       int (*access)(struct vm_area_struct *vma, unsigned long addr,
+                     void *buf, int len, int write);
 #ifdef CONFIG_NUMA
        /*
         * set_policy() op must add a reference to any non-NULL @new mempolicy
@@ -674,13 +682,6 @@ static inline int page_mapped(struct page *page)
        return atomic_read(&(page)->_mapcount) >= 0;
 }
 
-/*
- * Error return values for the *_nopfn functions
- */
-#define NOPFN_SIGBUS   ((unsigned long) -1)
-#define NOPFN_OOM      ((unsigned long) -2)
-#define NOPFN_REFAULT  ((unsigned long) -3)
-
 /*
  * Different kinds of faults, as returned by handle_mm_fault().
  * Used to decide whether a process gets delivered SIGBUS or
@@ -772,14 +773,14 @@ struct mm_walk {
 
 int walk_page_range(unsigned long addr, unsigned long end,
                struct mm_walk *walk);
-void free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
                unsigned long end, unsigned long floor, unsigned long ceiling);
-void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *start_vma,
-               unsigned long floor, unsigned long ceiling);
 int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
                        struct vm_area_struct *vma);
 void unmap_mapping_range(struct address_space *mapping,
                loff_t const holebegin, loff_t const holelen, int even_cows);
+int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
+                       void *buf, int len, int write);
 
 static inline void unmap_shared_mapping_range(struct address_space *mapping,
                loff_t const holebegin, loff_t const holelen)
@@ -809,7 +810,6 @@ extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *
 
 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);
-void print_bad_pte(struct vm_area_struct *, pte_t, unsigned long);
 
 extern int try_to_release_page(struct page * page, gfp_t gfp_mask);
 extern void do_invalidatepage(struct page *page, unsigned long offset);
@@ -832,6 +832,39 @@ extern int mprotect_fixup(struct vm_area_struct *vma,
                          struct vm_area_struct **pprev, unsigned long start,
                          unsigned long end, unsigned long newflags);
 
+#ifdef CONFIG_HAVE_GET_USER_PAGES_FAST
+/*
+ * get_user_pages_fast provides equivalent functionality to get_user_pages,
+ * operating on current and current->mm (force=0 and doesn't return any vmas).
+ *
+ * get_user_pages_fast may take mmap_sem and page tables, so no assumptions
+ * can be made about locking. get_user_pages_fast is to be implemented in a
+ * way that is advantageous (vs get_user_pages()) when the user memory area is
+ * already faulted in and present in ptes. However if the pages have to be
+ * faulted in, it may turn out to be slightly slower).
+ */
+int get_user_pages_fast(unsigned long start, int nr_pages, int write,
+                       struct page **pages);
+
+#else
+/*
+ * Should probably be moved to asm-generic, and architectures can include it if
+ * they don't implement their own get_user_pages_fast.
+ */
+#define get_user_pages_fast(start, nr_pages, write, pages)     \
+({                                                             \
+       struct mm_struct *mm = current->mm;                     \
+       int ret;                                                \
+                                                               \
+       down_read(&mm->mmap_sem);                               \
+       ret = get_user_pages(current, mm, start, nr_pages,      \
+                                       write, 0, pages, NULL); \
+       up_read(&mm->mmap_sem);                                 \
+                                                               \
+       ret;                                                    \
+})
+#endif
+
 /*
  * A callback you can register to apply pressure to ageable caches.
  *
@@ -965,9 +998,8 @@ static inline void pgtable_page_dtor(struct page *page)
                NULL: pte_offset_kernel(pmd, address))
 
 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);
+extern void free_area_init_node(int nid, 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
@@ -1072,6 +1104,9 @@ extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
        unsigned long addr, unsigned long len, pgoff_t pgoff);
 extern void exit_mmap(struct mm_struct *);
 
+extern int mm_take_all_locks(struct mm_struct *mm);
+extern void mm_drop_all_locks(struct mm_struct *mm);
+
 #ifdef CONFIG_PROC_FS
 /* From fs/proc/base.c. callers must _not_ hold the mm's exe_file_lock */
 extern void added_exe_file_vma(struct mm_struct *mm);
index 02a27ae78539cfe536106f46a8f89b50ea63985e..386edbe2cb4e98b1a01767e15978b02df896d895 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/rbtree.h>
 #include <linux/rwsem.h>
 #include <linux/completion.h>
+#include <linux/cpumask.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
 
@@ -159,6 +160,17 @@ struct vm_area_struct {
 #endif
 };
 
+struct core_thread {
+       struct task_struct *task;
+       struct core_thread *next;
+};
+
+struct core_state {
+       atomic_t nr_threads;
+       struct core_thread dumper;
+       struct completion startup;
+};
+
 struct mm_struct {
        struct vm_area_struct * mmap;           /* list of VMAs */
        struct rb_root mm_rb;
@@ -175,7 +187,6 @@ struct mm_struct {
        atomic_t mm_users;                      /* How many users with user space? */
        atomic_t mm_count;                      /* How many references to "struct mm_struct" (users count as 1) */
        int map_count;                          /* number of VMAs */
-       int core_waiters;
        struct rw_semaphore mmap_sem;
        spinlock_t page_table_lock;             /* Protects page tables and some counters */
 
@@ -219,8 +230,7 @@ struct mm_struct {
 
        unsigned long flags; /* Must use atomic bitops to access the bits */
 
-       /* coredumping support */
-       struct completion *core_startup_done, core_done;
+       struct core_state *core_state; /* coredumping support */
 
        /* aio bits */
        rwlock_t                ioctx_list_lock;        /* aio lock */
@@ -244,6 +254,9 @@ struct mm_struct {
        struct file *exe_file;
        unsigned long num_exe_file_vmas;
 #endif
+#ifdef CONFIG_MMU_NOTIFIER
+       struct mmu_notifier_mm *mmu_notifier_mm;
+#endif
 };
 
 #endif /* _LINUX_MM_TYPES_H */
index 0d508ac17d6452b5a35429fd38704c8de2c13de4..ee6e822d59947312d3bc464508e9f38ff1686e91 100644 (file)
@@ -111,6 +111,8 @@ struct mmc_card {
        unsigned                num_info;       /* number of info strings */
        const char              **info;         /* info strings */
        struct sdio_func_tuple  *tuples;        /* unknown common tuples */
+
+       struct dentry           *debugfs_root;
 };
 
 #define mmc_card_mmc(c)                ((c)->type == MMC_TYPE_MMC)
index 10a2080086ca9e6402eec37178bd8dea384f3f92..9c288c9098783cfc3ef1b4d6357081b7d3f44849 100644 (file)
@@ -157,6 +157,8 @@ struct mmc_host {
        struct led_trigger      *led;           /* activity led */
 #endif
 
+       struct dentry           *debugfs_root;
+
        unsigned long           private[0] ____cacheline_aligned;
 };
 
diff --git a/include/linux/mmu_notifier.h b/include/linux/mmu_notifier.h
new file mode 100644 (file)
index 0000000..b77486d
--- /dev/null
@@ -0,0 +1,279 @@
+#ifndef _LINUX_MMU_NOTIFIER_H
+#define _LINUX_MMU_NOTIFIER_H
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/mm_types.h>
+
+struct mmu_notifier;
+struct mmu_notifier_ops;
+
+#ifdef CONFIG_MMU_NOTIFIER
+
+/*
+ * The mmu notifier_mm structure is allocated and installed in
+ * mm->mmu_notifier_mm inside the mm_take_all_locks() protected
+ * critical section and it's released only when mm_count reaches zero
+ * in mmdrop().
+ */
+struct mmu_notifier_mm {
+       /* all mmu notifiers registerd in this mm are queued in this list */
+       struct hlist_head list;
+       /* to serialize the list modifications and hlist_unhashed */
+       spinlock_t lock;
+};
+
+struct mmu_notifier_ops {
+       /*
+        * Called either by mmu_notifier_unregister or when the mm is
+        * being destroyed by exit_mmap, always before all pages are
+        * freed. This can run concurrently with other mmu notifier
+        * methods (the ones invoked outside the mm context) and it
+        * should tear down all secondary mmu mappings and freeze the
+        * secondary mmu. If this method isn't implemented you've to
+        * be sure that nothing could possibly write to the pages
+        * through the secondary mmu by the time the last thread with
+        * tsk->mm == mm exits.
+        *
+        * As side note: the pages freed after ->release returns could
+        * be immediately reallocated by the gart at an alias physical
+        * address with a different cache model, so if ->release isn't
+        * implemented because all _software_ driven memory accesses
+        * through the secondary mmu are terminated by the time the
+        * last thread of this mm quits, you've also to be sure that
+        * speculative _hardware_ operations can't allocate dirty
+        * cachelines in the cpu that could not be snooped and made
+        * coherent with the other read and write operations happening
+        * through the gart alias address, so leading to memory
+        * corruption.
+        */
+       void (*release)(struct mmu_notifier *mn,
+                       struct mm_struct *mm);
+
+       /*
+        * clear_flush_young is called after the VM is
+        * test-and-clearing the young/accessed bitflag in the
+        * pte. This way the VM will provide proper aging to the
+        * accesses to the page through the secondary MMUs and not
+        * only to the ones through the Linux pte.
+        */
+       int (*clear_flush_young)(struct mmu_notifier *mn,
+                                struct mm_struct *mm,
+                                unsigned long address);
+
+       /*
+        * Before this is invoked any secondary MMU is still ok to
+        * read/write to the page previously pointed to by the Linux
+        * pte because the page hasn't been freed yet and it won't be
+        * freed until this returns. If required set_page_dirty has to
+        * be called internally to this method.
+        */
+       void (*invalidate_page)(struct mmu_notifier *mn,
+                               struct mm_struct *mm,
+                               unsigned long address);
+
+       /*
+        * invalidate_range_start() and invalidate_range_end() must be
+        * paired and are called only when the mmap_sem and/or the
+        * locks protecting the reverse maps are held. The subsystem
+        * must guarantee that no additional references are taken to
+        * the pages in the range established between the call to
+        * invalidate_range_start() and the matching call to
+        * invalidate_range_end().
+        *
+        * Invalidation of multiple concurrent ranges may be
+        * optionally permitted by the driver. Either way the
+        * establishment of sptes is forbidden in the range passed to
+        * invalidate_range_begin/end for the whole duration of the
+        * invalidate_range_begin/end critical section.
+        *
+        * invalidate_range_start() is called when all pages in the
+        * range are still mapped and have at least a refcount of one.
+        *
+        * invalidate_range_end() is called when all pages in the
+        * range have been unmapped and the pages have been freed by
+        * the VM.
+        *
+        * The VM will remove the page table entries and potentially
+        * the page between invalidate_range_start() and
+        * invalidate_range_end(). If the page must not be freed
+        * because of pending I/O or other circumstances then the
+        * invalidate_range_start() callback (or the initial mapping
+        * by the driver) must make sure that the refcount is kept
+        * elevated.
+        *
+        * If the driver increases the refcount when the pages are
+        * initially mapped into an address space then either
+        * invalidate_range_start() or invalidate_range_end() may
+        * decrease the refcount. If the refcount is decreased on
+        * invalidate_range_start() then the VM can free pages as page
+        * table entries are removed.  If the refcount is only
+        * droppped on invalidate_range_end() then the driver itself
+        * will drop the last refcount but it must take care to flush
+        * any secondary tlb before doing the final free on the
+        * page. Pages will no longer be referenced by the linux
+        * address space but may still be referenced by sptes until
+        * the last refcount is dropped.
+        */
+       void (*invalidate_range_start)(struct mmu_notifier *mn,
+                                      struct mm_struct *mm,
+                                      unsigned long start, unsigned long end);
+       void (*invalidate_range_end)(struct mmu_notifier *mn,
+                                    struct mm_struct *mm,
+                                    unsigned long start, unsigned long end);
+};
+
+/*
+ * The notifier chains are protected by mmap_sem and/or the reverse map
+ * semaphores. Notifier chains are only changed when all reverse maps and
+ * the mmap_sem locks are taken.
+ *
+ * Therefore notifier chains can only be traversed when either
+ *
+ * 1. mmap_sem is held.
+ * 2. One of the reverse map locks is held (i_mmap_lock or anon_vma->lock).
+ * 3. No other concurrent thread can access the list (release)
+ */
+struct mmu_notifier {
+       struct hlist_node hlist;
+       const struct mmu_notifier_ops *ops;
+};
+
+static inline int mm_has_notifiers(struct mm_struct *mm)
+{
+       return unlikely(mm->mmu_notifier_mm);
+}
+
+extern int mmu_notifier_register(struct mmu_notifier *mn,
+                                struct mm_struct *mm);
+extern int __mmu_notifier_register(struct mmu_notifier *mn,
+                                  struct mm_struct *mm);
+extern void mmu_notifier_unregister(struct mmu_notifier *mn,
+                                   struct mm_struct *mm);
+extern void __mmu_notifier_mm_destroy(struct mm_struct *mm);
+extern void __mmu_notifier_release(struct mm_struct *mm);
+extern int __mmu_notifier_clear_flush_young(struct mm_struct *mm,
+                                         unsigned long address);
+extern void __mmu_notifier_invalidate_page(struct mm_struct *mm,
+                                         unsigned long address);
+extern void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end);
+extern void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end);
+
+static inline void mmu_notifier_release(struct mm_struct *mm)
+{
+       if (mm_has_notifiers(mm))
+               __mmu_notifier_release(mm);
+}
+
+static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
+                                         unsigned long address)
+{
+       if (mm_has_notifiers(mm))
+               return __mmu_notifier_clear_flush_young(mm, address);
+       return 0;
+}
+
+static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
+                                         unsigned long address)
+{
+       if (mm_has_notifiers(mm))
+               __mmu_notifier_invalidate_page(mm, address);
+}
+
+static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end)
+{
+       if (mm_has_notifiers(mm))
+               __mmu_notifier_invalidate_range_start(mm, start, end);
+}
+
+static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end)
+{
+       if (mm_has_notifiers(mm))
+               __mmu_notifier_invalidate_range_end(mm, start, end);
+}
+
+static inline void mmu_notifier_mm_init(struct mm_struct *mm)
+{
+       mm->mmu_notifier_mm = NULL;
+}
+
+static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
+{
+       if (mm_has_notifiers(mm))
+               __mmu_notifier_mm_destroy(mm);
+}
+
+/*
+ * These two macros will sometime replace ptep_clear_flush.
+ * ptep_clear_flush is impleemnted as macro itself, so this also is
+ * implemented as a macro until ptep_clear_flush will converted to an
+ * inline function, to diminish the risk of compilation failure. The
+ * invalidate_page method over time can be moved outside the PT lock
+ * and these two macros can be later removed.
+ */
+#define ptep_clear_flush_notify(__vma, __address, __ptep)              \
+({                                                                     \
+       pte_t __pte;                                                    \
+       struct vm_area_struct *___vma = __vma;                          \
+       unsigned long ___address = __address;                           \
+       __pte = ptep_clear_flush(___vma, ___address, __ptep);           \
+       mmu_notifier_invalidate_page(___vma->vm_mm, ___address);        \
+       __pte;                                                          \
+})
+
+#define ptep_clear_flush_young_notify(__vma, __address, __ptep)                \
+({                                                                     \
+       int __young;                                                    \
+       struct vm_area_struct *___vma = __vma;                          \
+       unsigned long ___address = __address;                           \
+       __young = ptep_clear_flush_young(___vma, ___address, __ptep);   \
+       __young |= mmu_notifier_clear_flush_young(___vma->vm_mm,        \
+                                                 ___address);          \
+       __young;                                                        \
+})
+
+#else /* CONFIG_MMU_NOTIFIER */
+
+static inline void mmu_notifier_release(struct mm_struct *mm)
+{
+}
+
+static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
+                                         unsigned long address)
+{
+       return 0;
+}
+
+static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
+                                         unsigned long address)
+{
+}
+
+static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end)
+{
+}
+
+static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end)
+{
+}
+
+static inline void mmu_notifier_mm_init(struct mm_struct *mm)
+{
+}
+
+static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
+{
+}
+
+#define ptep_clear_flush_young_notify ptep_clear_flush_young
+#define ptep_clear_flush_notify ptep_clear_flush
+
+#endif /* CONFIG_MMU_NOTIFIER */
+
+#endif /* _LINUX_MMU_NOTIFIER_H */
index fce15ebd0e1cb6eca3831a77bbcc0d1887c50bc6..68e09557c9511ab31da394afd80a58decad3ee71 100644 (file)
@@ -23,7 +23,7 @@
 /* Not Yet Implemented */
 #define MODULE_SUPPORTED_DEVICE(name)
 
-/* v850 toolchain uses a `_' prefix for all user symbols */
+/* some toolchains uses a `_' prefix for all user symbols */
 #ifndef MODULE_SYMBOL_PREFIX
 #define MODULE_SYMBOL_PREFIX ""
 #endif
index 4374d1adeb4b755b4227bccf1f3afaa0b214fc35..b5efaa2132ab2ff79b624e09ab7eba0adcd18a04 100644 (file)
@@ -47,7 +47,7 @@ struct vfsmount {
        struct list_head mnt_child;     /* and going through their mnt_child */
        int mnt_flags;
        /* 4 bytes hole on 64bits arches */
-       char *mnt_devname;              /* Name of device e.g. /dev/dsk/hda1 */
+       const char *mnt_devname;        /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        struct list_head mnt_expire;    /* link in fs-specific expiry list */
        struct list_head mnt_share;     /* circular list of shared mounts */
index 81cd36b735b0de3677f76b116d047a1089166bdf..ba63858056c7a5f0d3e7017fb19808e6e9dae5b1 100644 (file)
@@ -2,11 +2,11 @@
 #define _LINUX_MSDOS_FS_H
 
 #include <linux/magic.h>
+#include <asm/byteorder.h>
 
 /*
  * The MS-DOS filesystem constants/structures
  */
-#include <asm/byteorder.h>
 
 #define SECTOR_SIZE    512             /* sector size (bytes) */
 #define SECTOR_BITS    9               /* log2(SECTOR_SIZE) */
 #define IS_FSINFO(x)   (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \
                         && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2)
 
+struct __fat_dirent {
+       long            d_ino;
+       __kernel_off_t  d_off;
+       unsigned short  d_reclen;
+       char            d_name[256]; /* We must not include limits.h! */
+};
+
 /*
  * ioctl commands
  */
-#define VFAT_IOCTL_READDIR_BOTH                _IOR('r', 1, struct dirent [2])
-#define VFAT_IOCTL_READDIR_SHORT       _IOR('r', 2, struct dirent [2])
+#define VFAT_IOCTL_READDIR_BOTH                _IOR('r', 1, struct __fat_dirent[2])
+#define VFAT_IOCTL_READDIR_SHORT       _IOR('r', 2, struct __fat_dirent[2])
 /* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */
 #define FAT_IOCTL_GET_ATTRIBUTES       _IOR('r', 0x10, __u32)
 #define FAT_IOCTL_SET_ATTRIBUTES       _IOW('r', 0x11, __u32)
 
-/*
- * vfat shortname flags
- */
-#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */
-#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */
-#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */
-#define VFAT_SFN_CREATE_WIN95  0x0100 /* emulate win95 rule for create */
-#define VFAT_SFN_CREATE_WINNT  0x0200 /* emulate winnt rule for create */
-
 struct fat_boot_sector {
        __u8    ignored[3];     /* Boot strap short or near jump */
        __u8    system_id[8];   /* Name - can be used to special case
@@ -168,14 +166,6 @@ struct msdos_dir_slot {
        __u8    name11_12[4];   /* last 2 characters in name */
 };
 
-struct fat_slot_info {
-       loff_t i_pos;           /* on-disk position of directory entry */
-       loff_t slot_off;        /* offset for slot or de start */
-       int nr_slots;           /* number of slots + 1(de) in filename */
-       struct msdos_dir_entry *de;
-       struct buffer_head *bh;
-};
-
 #ifdef __KERNEL__
 
 #include <linux/buffer_head.h>
@@ -184,6 +174,15 @@ struct fat_slot_info {
 #include <linux/fs.h>
 #include <linux/mutex.h>
 
+/*
+ * vfat shortname flags
+ */
+#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */
+#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */
+#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */
+#define VFAT_SFN_CREATE_WIN95  0x0100 /* emulate win95 rule for create */
+#define VFAT_SFN_CREATE_WINNT  0x0200 /* emulate winnt rule for create */
+
 struct fat_mount_options {
        uid_t fs_uid;
        gid_t fs_gid;
@@ -202,10 +201,10 @@ struct fat_mount_options {
                 utf8:1,          /* Use of UTF-8 character set (Default) */
                 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*/
-                usefree:1;       /* Use free_clusters for FAT32 */
+                usefree:1,       /* Use free_clusters for FAT32 */
+                tz_utc:1;        /* Filesystem timestamps are in UTC */
 };
 
 #define FAT_HASH_BITS  8
@@ -267,6 +266,14 @@ struct msdos_inode_info {
        struct inode vfs_inode;
 };
 
+struct fat_slot_info {
+       loff_t i_pos;           /* on-disk position of directory entry */
+       loff_t slot_off;        /* offset for slot or de start */
+       int nr_slots;           /* number of slots + 1(de) in filename */
+       struct msdos_dir_entry *de;
+       struct buffer_head *bh;
+};
+
 static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb)
 {
        return sb->s_fs_info;
@@ -428,8 +435,9 @@ extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
 extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
 extern void fat_clusters_flush(struct super_block *sb);
 extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
-extern int date_dos2unix(unsigned short time, unsigned short date);
-extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
+extern int date_dos2unix(unsigned short time, unsigned short date, int tz_utc);
+extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date,
+                             int tz_utc);
 extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
 
 int fat_cache_init(void);
index 9a6e2f953cba17292fb222bc616c70a1563b4439..310e616064158d68afb3e3fcdfcc31a56421b1bb 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: blktrans.h,v 1.6 2005/11/07 11:14:54 gleixner Exp $
- *
  * (C) 2003 David Woodhouse <dwmw2@infradead.org>
  *
  * Interface to Linux block layer for MTD 'translation layers'.
index b0ddf4b25862392d90443a8ad88a9d6c7ad68b95..d6fb115f5a0714794c077ea6ff98ea18243d537e 100644 (file)
@@ -1,7 +1,6 @@
 
 /* Common Flash Interface structures
  * See http://support.intel.com/design/flash/technote/index.htm
- * $Id: cfi.h,v 1.57 2005/11/15 23:28:17 tpoynor Exp $
  */
 
 #ifndef __MTD_CFI_H__
index 25724f7d3867a5ee69eb671c9e9713061a165fd4..d802f7736be3a474b0cee222b5d3648d8caf1812 100644 (file)
@@ -1,8 +1,3 @@
-/*
- * $Id: cfi_endian.h,v 1.11 2002/01/30 23:20:48 awozniak Exp $
- *
- */
-
 #include <asm/byteorder.h>
 
 #ifndef CONFIG_MTD_CFI_ADV_OPTIONS
index ed8dc675521917b14d12a492abe5a7c8f754a8e6..c02f3d264ecf8d24181463497aafddaa66197447 100644 (file)
@@ -4,8 +4,6 @@
  * (C) 2002 Robert Kaiser <rkaiser@sysgo.de>
  *
  * This code is GPL
- *
- * $Id: concat.h,v 1.1 2002/03/08 16:34:36 rkaiser Exp $
  */
 
 #ifndef MTD_CONCAT_H
index 9addd073bf15957ba8ce3d11675e614b042f4748..0a6d516ab71d9ba2eb97a7789593b040fb99dcb8 100644 (file)
@@ -6,8 +6,6 @@
  * Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com>
  * Copyright (C) 2002-2003 SnapGear Inc
  *
- * $Id: doc2000.h,v 1.25 2005/11/07 11:14:54 gleixner Exp $
- *
  * Released under GPL
  */
 
index 39e7d2a1be9a5a93657e3af6d62c8f9dd901ac88..08dd131301c1fe98e87d900f9173cc054f953a84 100644 (file)
@@ -5,9 +5,6 @@
  * Contains information about the location and state of a given flash device
  *
  * (C) 2000 Red Hat. GPLd.
- *
- * $Id: flashchip.h,v 1.18 2005/11/07 11:14:54 gleixner Exp $
- *
  */
 
 #ifndef __MTD_FLASHCHIP_H__
index d996091133076141ab35abef365017fd956ae556..0be442f881dd66eb9e324f4f9da0790afa1ab4d4 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: ftl.h,v 1.7 2005/11/07 11:14:54 gleixner Exp $
- *
  * Derived from (and probably identical to):
  * ftl.h 1.7 1999/10/25 20:23:17
  *
index 256e7342ed1eead34a474f13d762f7b91885127b..df362ddf2949f0f9a49bbd278f87dfa0ec8f5bae 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * (C) 2001, 2001 Red Hat, Inc.
  * GPL'd
- * $Id: gen_probe.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $
  */
 
 #ifndef __LINUX_MTD_GEN_PROBE_H__
index 85fd041d44ad30ca9fea26eef7dfafb164d611f2..64ee53ce95a94cbe483ec39cbe8a5d50ecad3dd1 100644 (file)
@@ -2,8 +2,6 @@
  *     inftl.h -- defines to support the Inverse NAND Flash Translation Layer
  *
  *     (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
- *
- *     $Id: inftl.h,v 1.7 2005/06/13 13:08:45 sean Exp $
  */
 
 #ifndef __MTD_INFTL_H__
@@ -52,8 +50,6 @@ struct INFTLrecord {
 int INFTL_mount(struct INFTLrecord *s);
 int INFTL_formatblock(struct INFTLrecord *s, int block);
 
-extern char inftlmountrev[];
-
 void INFTL_dumptables(struct INFTLrecord *s);
 void INFTL_dumpVUchains(struct INFTLrecord *s);
 
index 9c1d95491f8b0a7d208257b39f6fd794d713be84..aa30244492c6770a5ccdaf9c6a21536c9f6ea579 100644 (file)
@@ -1,6 +1,5 @@
 
 /* Overhauled routines for dealing with different mmap regions of flash */
-/* $Id: map.h,v 1.54 2005/11/07 11:14:54 gleixner Exp $ */
 
 #ifndef __LINUX_MTD_MAP_H__
 #define __LINUX_MTD_MAP_H__
index 8b5d49133ec616a80fdc7f375b95e9cc244e16cc..4ed40caff4e58161a8e5d545421e375d0b81f7e2 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: mtd.h,v 1.61 2005/11/07 11:14:54 gleixner Exp $
- *
  * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
  *
  * Released under GPL
index 53ea3dc8b0e8ac98347d28170533de9a77dd55f7..83f678702dff3903a262956e21c306bc068c9bbf 100644 (file)
@@ -5,8 +5,6 @@
  *                     Steven J. Hill <sjhill@realitydiluted.com>
  *                    Thomas Gleixner <tglx@linutronix.de>
  *
- * $Id: nand.h,v 1.74 2005/09/15 13:58:50 vwool Exp $
- *
  * 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.
@@ -179,6 +177,7 @@ typedef enum {
 #define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
 #define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
 #define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
+#define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT))
 
 /* Mask to zero out the chip options, which come from the id table */
 #define NAND_CHIPOPTIONS_MSK   (0x0000ffff & ~NAND_NO_AUTOINCR)
@@ -276,6 +275,10 @@ struct nand_ecc_ctrl {
        int                     (*read_page)(struct mtd_info *mtd,
                                             struct nand_chip *chip,
                                             uint8_t *buf);
+       int                     (*read_subpage)(struct mtd_info *mtd,
+                                            struct nand_chip *chip,
+                                            uint32_t offs, uint32_t len,
+                                            uint8_t *buf);
        void                    (*write_page)(struct mtd_info *mtd,
                                              struct nand_chip *chip,
                                              const uint8_t *buf);
index 12c5bc342ead0341838b2053071df6b80d55dd6f..090da505425d77d105acb6133d63dfaaa7c95b7b 100644 (file)
@@ -3,8 +3,6 @@
  *
  *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
  *
- * $Id: nand_ecc.h,v 1.4 2004/06/17 02:35:02 dbrown Exp $
- *
  * 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.
index 001eec50cac6d12c12e3362ef1ca9687400357b8..dcaf611ed74826a5b2a018482e84b38449e08681 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: nftl.h,v 1.16 2004/06/30 14:49:00 dbrown Exp $
- *
  * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
  */
 
index 7c37d7e55abcbc119f3496c08e92868343dcd782..5014f7a9f5dfe57a8df546d4cee4edb2e6a065df 100644 (file)
@@ -4,8 +4,6 @@
  * (C) 2000 Nicolas Pitre <nico@cam.org>
  *
  * This code is GPL
- *
- * $Id: partitions.h,v 1.17 2005/11/07 11:14:55 gleixner Exp $
  */
 
 #ifndef MTD_PARTITIONS_H
index 0dc07d5f33545ae37ec667f74ef16a3b593f7ad6..c8e63a5ee72e1a0cbbffc06a02a327d2c0772ed5 100644 (file)
@@ -2,8 +2,6 @@
  * For boards with physically mapped flash and using
  * drivers/mtd/maps/physmap.c mapping driver.
  *
- * $Id: physmap.h,v 1.4 2005/11/07 11:14:55 gleixner Exp $
- *
  * Copyright (C) 2003 MontaVista Software Inc.
  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  *
index 0e37ad07bce2bb4895d9913350958d80016b83d5..e07890aff1cf9523cb0fe4d07b0c06353da046c9 100644 (file)
@@ -6,8 +6,6 @@
  *
  * Generic platform device based RAM map
  *
- * $Id: plat-ram.h,v 1.2 2005/01/24 00:37:40 bjd Exp $
- *
  * 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.
index 5cc070c24d88646229bfd7f1f64aa06b76ebdbac..27ad40aed19f34faa11b0dcca3f9251290382413 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $
- *
  * PMC551 PCI Mezzanine Ram Device
  *
  * Author:
@@ -17,7 +15,7 @@
 
 #include <linux/mtd/mtd.h>
 
-#define PMC551_VERSION "$Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $\n"\
+#define PMC551_VERSION \
        "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
 
 /*
index f71201d0f3e7e42f2ffe22d571231cc958dff04f..6316fafe5c2a99558197520d8ccb05046c7fe629 100644 (file)
@@ -45,13 +45,13 @@ enum {
  * @size: how many physical eraseblocks are reserved for this volume
  * @used_bytes: how many bytes of data this volume contains
  * @used_ebs: how many physical eraseblocks of this volume actually contain any
- * data
+ *            data
  * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
  * @corrupted: non-zero if the volume is corrupted (static volumes only)
  * @upd_marker: non-zero if the volume has update marker set
  * @alignment: volume alignment
  * @usable_leb_size: how many bytes are available in logical eraseblocks of
- * this volume
+ *                   this volume
  * @name_len: volume name length
  * @name: volume name
  * @cdev: UBI volume character device major and minor numbers
@@ -152,6 +152,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum);
 int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum);
 int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
 int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum);
+int ubi_sync(int ubi_num);
 
 /*
  * This function is the same as the 'ubi_leb_read()' function, but it does not
index e9d40bdde48cba0f5d3083028e152aa6bac60269..36efcba15ecddc9a0557883b8690e1fe74bbf224 100644 (file)
@@ -11,8 +11,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.
- *
- * $Id: xip.h,v 1.5 2005/11/07 11:14:55 gleixner Exp $
  */
 
 #ifndef __LINUX_MTD_XIP_H__
index 24d88e98a62648180a553fdfb457837bcbcb5c00..68f8c3203c89d4d7c42404e4084051342206b875 100644 (file)
@@ -47,27 +47,24 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 #define LOOKUP_DIRECTORY        2
 #define LOOKUP_CONTINUE                 4
 #define LOOKUP_PARENT          16
-#define LOOKUP_NOALT           32
 #define LOOKUP_REVAL           64
 /*
  * Intent data
  */
 #define LOOKUP_OPEN            (0x0100)
 #define LOOKUP_CREATE          (0x0200)
-#define LOOKUP_ACCESS          (0x0400)
-#define LOOKUP_CHDIR           (0x0800)
-
-extern int __user_walk(const char __user *, unsigned, struct nameidata *);
-extern int __user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *);
-#define user_path_walk(name,nd) \
-       __user_walk_fd(AT_FDCWD, name, LOOKUP_FOLLOW, nd)
-#define user_path_walk_link(name,nd) \
-       __user_walk_fd(AT_FDCWD, name, 0, nd)
+
+extern int user_path_at(int, const char __user *, unsigned, struct path *);
+
+#define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path)
+#define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path)
+#define user_path_dir(name, path) \
+       user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, path)
+
 extern int path_lookup(const char *, unsigned, struct nameidata *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
                           const char *, unsigned int, struct nameidata *);
 
-extern int __user_path_lookup_open(const char __user *, unsigned lookup_flags, struct nameidata *nd, int open_flags);
 extern int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags);
 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
                int (*open)(struct inode *, struct file *));
index 150a48c68d52b044ef2c40c7be8b3e81a3b99971..4a9a30f2d68fe65e5184e367b488b4759ef20e33 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/wait.h>
 #include <linux/socket.h>
+#include <linux/fcntl.h>       /* For O_CLOEXEC and O_NONBLOCK */
 #include <asm/socket.h>
 
 struct poll_table_struct;
@@ -46,6 +47,7 @@ struct net;
 #define SYS_GETSOCKOPT 15              /* sys_getsockopt(2)            */
 #define SYS_SENDMSG    16              /* sys_sendmsg(2)               */
 #define SYS_RECVMSG    17              /* sys_recvmsg(2)               */
+#define SYS_PACCEPT    18              /* sys_paccept(2)               */
 
 typedef enum {
        SS_FREE = 0,                    /* not allocated                */
@@ -94,6 +96,15 @@ enum sock_type {
 };
 
 #define SOCK_MAX (SOCK_PACKET + 1)
+/* Mask which covers at least up to SOCK_MASK-1.  The
+ * remaining bits are used as flags. */
+#define SOCK_TYPE_MASK 0xf
+
+/* Flags for socket, socketpair, paccept */
+#define SOCK_CLOEXEC   O_CLOEXEC
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK  O_NONBLOCK
+#endif
 
 #endif /* ARCH_HAS_SOCKET_TYPES */
 
@@ -208,10 +219,12 @@ extern int             sock_sendmsg(struct socket *sock, struct msghdr *msg,
                                  size_t len);
 extern int          sock_recvmsg(struct socket *sock, struct msghdr *msg,
                                  size_t size, int flags);
-extern int          sock_map_fd(struct socket *sock);
+extern int          sock_map_fd(struct socket *sock, int flags);
 extern struct socket *sockfd_lookup(int fd, int *err);
 #define                     sockfd_put(sock) fput(sock->file)
 extern int          net_ratelimit(void);
+extern long         do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
+                              int __user *upeer_addrlen, int flags);
 
 #define net_random()           random32()
 #define net_srandom(seed)      srandom32((__force u32)seed)
@@ -338,8 +351,7 @@ static const struct proto_ops name##_ops = {                        \
 
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
-extern int net_msg_cost;
-extern int net_msg_burst;
+extern struct ratelimit_state net_ratelimit_state;
 #endif
 
 #endif /* __KERNEL__ */
index 29d26191873428cecde2b29f3fd68b855684f614..78a5922a2f111dc7d08b8d7d5bef59c2511cef15 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/in.h>
 #include <linux/kref.h>
 #include <linux/mm.h>
-#include <linux/namei.h>
 #include <linux/pagemap.h>
 #include <linux/rbtree.h>
 #include <linux/rwsem.h>
@@ -332,7 +331,7 @@ extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern int nfs_permission(struct inode *, int, struct nameidata *);
+extern int nfs_permission(struct inode *, int);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
 extern int nfs_attribute_timeout(struct inode *inode);
index a2861d95ecc35fff2d9fb9652dabf0a6754f8a4c..108f47e5fd9511796516d758dca90b1232321bea 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/types.h>
 #include <linux/unistd.h>
-#include <linux/dirent.h>
 #include <linux/fs.h>
 #include <linux/posix_acl.h>
 #include <linux/mount.h>
index bd3d72ddf33398254a503fdbc8709e3cbccdc19e..da2698b0fdd1d0989e5f1e0c2739262d002eb3df 100644 (file)
@@ -214,6 +214,8 @@ static inline int notifier_to_errno(int ret)
 #define CPU_DEAD               0x0007 /* CPU (unsigned)v dead */
 #define CPU_DYING              0x0008 /* CPU (unsigned)v not running any task,
                                        * not handling interrupts, soon dead */
+#define CPU_POST_DEAD          0x0009 /* CPU (unsigned)v dead, cpu_hotplug
+                                       * lock is dropped */
 
 /* Used for CPU hotplug events occuring while tasks are frozen due to a suspend
  * operation in progress
index 0e66b57631fc767f202c32771f2ab5c8194c34cd..c8a768e59640665af635cedb9c84745e421fdbab 100644 (file)
@@ -82,9 +82,12 @@ static inline void get_nsproxy(struct nsproxy *ns)
 }
 
 #ifdef CONFIG_CGROUP_NS
-int ns_cgroup_clone(struct task_struct *tsk);
+int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid);
 #else
-static inline int ns_cgroup_clone(struct task_struct *tsk) { return 0; }
+static inline int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid)
+{
+       return 0;
+}
 #endif
 
 #endif
index 59a61bdc98b69b58da4f6f9797c131a275c690d1..79886ade070f2e791274c92814bc04bfbcff4947 100644 (file)
@@ -70,5 +70,6 @@ extern int of_n_addr_cells(struct device_node *np);
 extern int of_n_size_cells(struct device_node *np);
 extern const struct of_device_id *of_match_node(
        const struct of_device_id *matches, const struct device_node *node);
+extern int of_modalias_node(struct device_node *node, char *modalias, int len);
 
 #endif /* _LINUX_OF_H */
diff --git a/include/linux/of_spi.h b/include/linux/of_spi.h
new file mode 100644 (file)
index 0000000..5f71ee8
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * OpenFirmware SPI support routines
+ * Copyright (C) 2008 Secret Lab Technologies Ltd.
+ *
+ * Support routines for deriving SPI device attachments from the device
+ * tree.
+ */
+
+#ifndef __LINUX_OF_SPI_H
+#define __LINUX_OF_SPI_H
+
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+
+extern void of_register_spi_devices(struct spi_master *master,
+                                   struct device_node *np);
+
+#endif /* __LINUX_OF_SPI */
index 0d2a4e7012aa4663722527bba42c99e4b3b2a6a6..54590a9a103e22a341362623599135f0c3c01cae 100644 (file)
@@ -96,7 +96,22 @@ enum pageflags {
 #ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
        PG_uncached,            /* Page has been mapped as uncached */
 #endif
-       __NR_PAGEFLAGS
+       __NR_PAGEFLAGS,
+
+       /* Filesystems */
+       PG_checked = PG_owner_priv_1,
+
+       /* XEN */
+       PG_pinned = PG_owner_priv_1,
+       PG_savepinned = PG_dirty,
+
+       /* SLOB */
+       PG_slob_page = PG_active,
+       PG_slob_free = PG_private,
+
+       /* SLUB */
+       PG_slub_frozen = PG_active,
+       PG_slub_debug = PG_error,
 };
 
 #ifndef __GENERATING_BOUNDS_H
@@ -155,13 +170,19 @@ PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty)
 PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru)
 PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active)
 __PAGEFLAG(Slab, slab)
-PAGEFLAG(Checked, owner_priv_1)                /* Used by some filesystems */
-PAGEFLAG(Pinned, owner_priv_1) TESTSCFLAG(Pinned, owner_priv_1) /* Xen */
-PAGEFLAG(SavePinned, dirty);                                   /* Xen */
+PAGEFLAG(Checked, checked)             /* Used by some filesystems */
+PAGEFLAG(Pinned, pinned) TESTSCFLAG(Pinned, pinned)    /* Xen */
+PAGEFLAG(SavePinned, savepinned);                      /* Xen */
 PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
 PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private)
        __SETPAGEFLAG(Private, private)
 
+__PAGEFLAG(SlobPage, slob_page)
+__PAGEFLAG(SlobFree, slob_free)
+
+__PAGEFLAG(SlubFrozen, slub_frozen)
+__PAGEFLAG(SlubDebug, slub_debug)
+
 /*
  * Only test-and-set exist for PG_writeback.  The unconditional operators are
  * risky: they bypass page accounting.
index d2fca802f809972a9b9b05171e02fa78fa054de7..a39b38ccdc976e920b077fcd484cabb8cc402ba8 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/uaccess.h>
 #include <linux/gfp.h>
 #include <linux/bitops.h>
+#include <linux/hardirq.h> /* for in_interrupt() */
 
 /*
  * Bits in mapping->flags.  The lower __GFP_BITS_SHIFT bits are the page
  */
 #define        AS_EIO          (__GFP_BITS_SHIFT + 0)  /* IO error on async write */
 #define AS_ENOSPC      (__GFP_BITS_SHIFT + 1)  /* ENOSPC on async write */
+#define AS_MM_ALL_LOCKS        (__GFP_BITS_SHIFT + 2)  /* under mm_take_all_locks() */
 
 static inline void mapping_set_error(struct address_space *mapping, int error)
 {
-       if (error) {
+       if (unlikely(error)) {
                if (error == -ENOSPC)
                        set_bit(AS_ENOSPC, &mapping->flags);
                else
@@ -62,6 +64,98 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
 #define page_cache_release(page)       put_page(page)
 void release_pages(struct page **pages, int nr, int cold);
 
+/*
+ * speculatively take a reference to a page.
+ * If the page is free (_count == 0), then _count is untouched, and 0
+ * is returned. Otherwise, _count is incremented by 1 and 1 is returned.
+ *
+ * This function must be called inside the same rcu_read_lock() section as has
+ * been used to lookup the page in the pagecache radix-tree (or page table):
+ * this allows allocators to use a synchronize_rcu() to stabilize _count.
+ *
+ * Unless an RCU grace period has passed, the count of all pages coming out
+ * of the allocator must be considered unstable. page_count may return higher
+ * than expected, and put_page must be able to do the right thing when the
+ * page has been finished with, no matter what it is subsequently allocated
+ * for (because put_page is what is used here to drop an invalid speculative
+ * reference).
+ *
+ * This is the interesting part of the lockless pagecache (and lockless
+ * get_user_pages) locking protocol, where the lookup-side (eg. find_get_page)
+ * has the following pattern:
+ * 1. find page in radix tree
+ * 2. conditionally increment refcount
+ * 3. check the page is still in pagecache (if no, goto 1)
+ *
+ * Remove-side that cares about stability of _count (eg. reclaim) has the
+ * following (with tree_lock held for write):
+ * A. atomically check refcount is correct and set it to 0 (atomic_cmpxchg)
+ * B. remove page from pagecache
+ * C. free the page
+ *
+ * There are 2 critical interleavings that matter:
+ * - 2 runs before A: in this case, A sees elevated refcount and bails out
+ * - A runs before 2: in this case, 2 sees zero refcount and retries;
+ *   subsequently, B will complete and 1 will find no page, causing the
+ *   lookup to return NULL.
+ *
+ * It is possible that between 1 and 2, the page is removed then the exact same
+ * page is inserted into the same position in pagecache. That's OK: the
+ * old find_get_page using tree_lock could equally have run before or after
+ * such a re-insertion, depending on order that locks are granted.
+ *
+ * Lookups racing against pagecache insertion isn't a big problem: either 1
+ * will find the page or it will not. Likewise, the old find_get_page could run
+ * either before the insertion or afterwards, depending on timing.
+ */
+static inline int page_cache_get_speculative(struct page *page)
+{
+       VM_BUG_ON(in_interrupt());
+
+#if !defined(CONFIG_SMP) && defined(CONFIG_CLASSIC_RCU)
+# ifdef CONFIG_PREEMPT
+       VM_BUG_ON(!in_atomic());
+# endif
+       /*
+        * Preempt must be disabled here - we rely on rcu_read_lock doing
+        * this for us.
+        *
+        * Pagecache won't be truncated from interrupt context, so if we have
+        * found a page in the radix tree here, we have pinned its refcount by
+        * disabling preempt, and hence no need for the "speculative get" that
+        * SMP requires.
+        */
+       VM_BUG_ON(page_count(page) == 0);
+       atomic_inc(&page->_count);
+
+#else
+       if (unlikely(!get_page_unless_zero(page))) {
+               /*
+                * Either the page has been freed, or will be freed.
+                * In either case, retry here and the caller should
+                * do the right thing (see comments above).
+                */
+               return 0;
+       }
+#endif
+       VM_BUG_ON(PageTail(page));
+
+       return 1;
+}
+
+static inline int page_freeze_refs(struct page *page, int count)
+{
+       return likely(atomic_cmpxchg(&page->_count, count, 0) == count);
+}
+
+static inline void page_unfreeze_refs(struct page *page, int count)
+{
+       VM_BUG_ON(page_count(page) != 0);
+       VM_BUG_ON(count == 0);
+
+       atomic_set(&page->_count, count);
+}
+
 #ifdef CONFIG_NUMA
 extern struct page *__page_cache_alloc(gfp_t gfp);
 #else
@@ -133,13 +227,29 @@ static inline struct page *read_mapping_page(struct address_space *mapping,
        return read_cache_page(mapping, index, filler, data);
 }
 
-int add_to_page_cache(struct page *page, struct address_space *mapping,
+int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
                                pgoff_t index, gfp_t gfp_mask);
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
                                pgoff_t index, gfp_t gfp_mask);
 extern void remove_from_page_cache(struct page *page);
 extern void __remove_from_page_cache(struct page *page);
 
+/*
+ * Like add_to_page_cache_locked, but used to add newly allocated pages:
+ * the page is new, so we can just run SetPageLocked() against it.
+ */
+static inline int add_to_page_cache(struct page *page,
+               struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
+{
+       int error;
+
+       SetPageLocked(page);
+       error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
+       if (unlikely(error))
+               ClearPageLocked(page);
+       return error;
+}
+
 /*
  * Return byte-offset into filesystem object for page.
  */
index dcb9e01a69ca9672879be141eb7d449b3297445b..6a0d7cdb577465a84bf5ccf3ef8ff0b86edc4002 100644 (file)
@@ -560,5 +560,8 @@ extern int parport_device_proc_unregister(struct pardevice *device);
 
 #endif /*  !CONFIG_PARPORT_NOT_PC  */
 
+extern unsigned long parport_default_timeslice;
+extern int parport_default_spintime;
+
 #endif /* __KERNEL__ */
 #endif /* _PARPORT_H_ */
index 7dcd050757567eb94265fb12b29d6f79e5cbcb3f..cc554ca8bc7836401807ec1359a13f44f679c908 100644 (file)
@@ -14,7 +14,7 @@ struct match_token {
        const char *pattern;
 };
 
-typedef struct match_token match_table_t[];
+typedef const struct match_token match_table_t[];
 
 /* Maximum number of arguments that match_token will find in a pattern */
 enum {MAX_OPT_ARGS = 3};
index a1a1e618e996ba16dbc69e56a78d127829a6fd1a..91ba0b338b472905e05ca2ba7676a33bc2a6530d 100644 (file)
@@ -27,6 +27,7 @@ extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
 extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
 extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
 extern void pci_disable_link_state(struct pci_dev *pdev, int state);
+extern void pcie_no_aspm(void);
 #else
 static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
 {
@@ -40,6 +41,10 @@ static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev)
 static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
 {
 }
+
+static inline void pcie_no_aspm(void)
+{
+}
 #endif
 
 #ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
index a6a088e1a8049bf7b15fe5dac91b87f9a938133a..825be3878f6845cc3c0eaa0651164394e1974a57 100644 (file)
@@ -124,6 +124,8 @@ enum pci_dev_flags {
         * generation too.
         */
        PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1,
+       /* Device configuration is irrevocably lost if disabled into D3 */
+       PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
 };
 
 typedef unsigned short __bitwise pci_bus_flags_t;
@@ -638,7 +640,9 @@ int pci_save_state(struct pci_dev *dev);
 int pci_restore_state(struct pci_dev *dev);
 int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
 pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
+bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);
 int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
+pci_power_t pci_target_state(struct pci_dev *dev);
 int pci_prepare_to_sleep(struct pci_dev *dev);
 int pci_back_from_sleep(struct pci_dev *dev);
 
index 119ae7b8f028cb9795fddb16a28abc7530294764..35a78415acccfab8f58a56fb3e6ef14449f0ee04 100644 (file)
 #define PCI_VENDOR_ID_TI               0x104c
 #define PCI_DEVICE_ID_TI_TVP4020       0x3d07
 #define PCI_DEVICE_ID_TI_4450          0x8011
+#define PCI_DEVICE_ID_TI_TSB43AB22     0x8023
 #define PCI_DEVICE_ID_TI_XX21_XX11     0x8031
 #define PCI_DEVICE_ID_TI_XX21_XX11_FM  0x8033
 #define PCI_DEVICE_ID_TI_XX21_XX11_SD  0x8034
 #define PCI_DEVICE_ID_MOXA_C320                0x3200
 
 #define PCI_VENDOR_ID_CCD              0x1397
+#define PCI_DEVICE_ID_CCD_HFC4S                0x08B4
+#define PCI_SUBDEVICE_ID_CCD_PMX2S     0x1234
+#define PCI_DEVICE_ID_CCD_HFC8S                0x16B8
 #define PCI_DEVICE_ID_CCD_2BD0         0x2bd0
+#define PCI_DEVICE_ID_CCD_HFCE1                0x30B1
+#define PCI_SUBDEVICE_ID_CCD_SPD4S     0x3136
+#define PCI_SUBDEVICE_ID_CCD_SPDE1     0x3137
 #define PCI_DEVICE_ID_CCD_B000         0xb000
 #define PCI_DEVICE_ID_CCD_B006         0xb006
 #define PCI_DEVICE_ID_CCD_B007         0xb007
 #define PCI_DEVICE_ID_CCD_B00B         0xb00b
 #define PCI_DEVICE_ID_CCD_B00C         0xb00c
 #define PCI_DEVICE_ID_CCD_B100         0xb100
+#define PCI_SUBDEVICE_ID_CCD_IOB4ST    0xB520
+#define PCI_SUBDEVICE_ID_CCD_IOB8STR   0xB521
+#define PCI_SUBDEVICE_ID_CCD_IOB8ST    0xB522
+#define PCI_SUBDEVICE_ID_CCD_IOB1E1    0xB523
+#define PCI_SUBDEVICE_ID_CCD_SWYX4S    0xB540
+#define PCI_SUBDEVICE_ID_CCD_JH4S20    0xB550
+#define PCI_SUBDEVICE_ID_CCD_IOB8ST_1  0xB552
+#define PCI_SUBDEVICE_ID_CCD_BN4S      0xB560
+#define PCI_SUBDEVICE_ID_CCD_BN8S      0xB562
+#define PCI_SUBDEVICE_ID_CCD_BNE1      0xB563
+#define PCI_SUBDEVICE_ID_CCD_BNE1D     0xB564
+#define PCI_SUBDEVICE_ID_CCD_BNE1DP    0xB565
+#define PCI_SUBDEVICE_ID_CCD_BN2S      0xB566
+#define PCI_SUBDEVICE_ID_CCD_BN1SM     0xB567
+#define PCI_SUBDEVICE_ID_CCD_BN4SM     0xB568
+#define PCI_SUBDEVICE_ID_CCD_BN2SM     0xB569
+#define PCI_SUBDEVICE_ID_CCD_BNE1M     0xB56A
+#define PCI_SUBDEVICE_ID_CCD_BN8SP     0xB56B
+#define PCI_SUBDEVICE_ID_CCD_HFC4S     0xB620
+#define PCI_SUBDEVICE_ID_CCD_HFC8S     0xB622
 #define PCI_DEVICE_ID_CCD_B700         0xb700
 #define PCI_DEVICE_ID_CCD_B701         0xb701
+#define PCI_SUBDEVICE_ID_CCD_HFCE1     0xC523
+#define PCI_SUBDEVICE_ID_CCD_OV2S      0xE884
+#define PCI_SUBDEVICE_ID_CCD_OV4S      0xE888
+#define PCI_SUBDEVICE_ID_CCD_OV8S      0xE998
 
 #define PCI_VENDOR_ID_EXAR             0x13a8
 #define PCI_DEVICE_ID_EXAR_XR17C152    0x0152
 #define PCI_DEVICE_ID_INTEL_ICH10_4    0x3a30
 #define PCI_DEVICE_ID_INTEL_ICH10_5    0x3a60
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB   0x402f
+#define PCI_DEVICE_ID_INTEL_5100_16    0x65f0
+#define PCI_DEVICE_ID_INTEL_5100_21    0x65f5
+#define PCI_DEVICE_ID_INTEL_5100_22    0x65f6
 #define PCI_DEVICE_ID_INTEL_5400_ERR   0x4030
 #define PCI_DEVICE_ID_INTEL_5400_FBD0  0x4035
 #define PCI_DEVICE_ID_INTEL_5400_FBD1  0x4036
 
 #define PCI_VENDOR_ID_3COM_2           0xa727
 
+#define PCI_VENDOR_ID_DIGIUM           0xd161
+#define PCI_DEVICE_ID_DIGIUM_HFC4S     0xb410
+
 #define PCI_SUBVENDOR_ID_EXSYS         0xd84d
 #define PCI_SUBDEVICE_ID_EXSYS_4014    0x4014
 #define PCI_SUBDEVICE_ID_EXSYS_4055    0x4055
index 19958b929905beb2af8a0a6ca6802510379c232a..450684f7eaacd41e08d57b08b0698dadffab1281 100644 (file)
 #define  PCI_EXP_DEVCAP_ATN_BUT        0x1000  /* Attention Button Present */
 #define  PCI_EXP_DEVCAP_ATN_IND        0x2000  /* Attention Indicator Present */
 #define  PCI_EXP_DEVCAP_PWR_IND        0x4000  /* Power Indicator Present */
+#define  PCI_EXP_DEVCAP_RBER   0x8000  /* Role-Based Error Reporting */
 #define  PCI_EXP_DEVCAP_PWR_VAL        0x3fc0000 /* Slot Power Limit Value */
 #define  PCI_EXP_DEVCAP_PWR_SCL        0xc000000 /* Slot Power Limit Scale */
 #define PCI_EXP_DEVCTL         8       /* Device Control */
index 4cdd393e71e1bb70ee0286c16f2aeb08d1458d98..fac3337547eb862e268587e082d885e0c01577d8 100644 (file)
@@ -74,11 +74,6 @@ struct percpu_data {
         (__typeof__(ptr))__p->ptrs[(cpu)];               \
 })
 
-extern void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu);
-extern void percpu_depopulate(void *__pdata, int cpu);
-extern int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
-                                 cpumask_t *mask);
-extern void __percpu_depopulate_mask(void *__pdata, cpumask_t *mask);
 extern void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask);
 extern void percpu_free(void *__pdata);
 
@@ -86,26 +81,6 @@ extern void percpu_free(void *__pdata);
 
 #define percpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); })
 
-static inline void percpu_depopulate(void *__pdata, int cpu)
-{
-}
-
-static inline void __percpu_depopulate_mask(void *__pdata, cpumask_t *mask)
-{
-}
-
-static inline void *percpu_populate(void *__pdata, size_t size, gfp_t gfp,
-                                   int cpu)
-{
-       return percpu_ptr(__pdata, cpu);
-}
-
-static inline int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
-                                        cpumask_t *mask)
-{
-       return 0;
-}
-
 static __always_inline void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask)
 {
        return kzalloc(size, gfp);
@@ -118,10 +93,6 @@ static inline void percpu_free(void *__pdata)
 
 #endif /* CONFIG_SMP */
 
-#define percpu_populate_mask(__pdata, size, gfp, mask) \
-       __percpu_populate_mask((__pdata), (size), (gfp), &(mask))
-#define percpu_depopulate_mask(__pdata, mask) \
-       __percpu_depopulate_mask((__pdata), &(mask))
 #define percpu_alloc_mask(size, gfp, mask) \
        __percpu_alloc_mask((size), (gfp), &(mask))
 
index c21c7e8124a7bb7bde92937fc37cf0810598d091..22921ac4cfd948b88e10a06c0725b33363b38caf 100644 (file)
@@ -48,7 +48,7 @@ enum pid_type
  */
 
 struct upid {
-       /* Try to keep pid_chain in the same cacheline as nr for find_pid */
+       /* Try to keep pid_chain in the same cacheline as nr for find_vpid */
        int nr;
        struct pid_namespace *ns;
        struct hlist_node pid_chain;
@@ -57,10 +57,10 @@ struct upid {
 struct pid
 {
        atomic_t count;
+       unsigned int level;
        /* lists of tasks that use this pid */
        struct hlist_head tasks[PIDTYPE_MAX];
        struct rcu_head rcu;
-       unsigned int level;
        struct upid numbers[1];
 };
 
@@ -105,14 +105,12 @@ extern struct pid_namespace init_pid_ns;
  * or rcu_read_lock() held.
  *
  * find_pid_ns() finds the pid in the namespace specified
- * find_pid() find the pid by its global id, i.e. in the init namespace
  * find_vpid() finr the pid by its virtual id, i.e. in the current namespace
  *
- * see also find_task_by_pid() set in include/linux/sched.h
+ * see also find_task_by_vpid() set in include/linux/sched.h
  */
 extern struct pid *find_pid_ns(int nr, struct pid_namespace *ns);
 extern struct pid *find_vpid(int nr);
-extern struct pid *find_pid(int nr);
 
 /*
  * Lookup a PID in the hash table, and return with it's count elevated.
index caff5283d15c6e11fe838ffad6b2877077af490e..1af82c4e17d4e79a14d1854b35fd39ef93bdb649 100644 (file)
@@ -14,6 +14,8 @@ struct pidmap {
 
 #define PIDMAP_ENTRIES         ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
 
+struct bsd_acct_struct;
+
 struct pid_namespace {
        struct kref kref;
        struct pidmap pidmap[PIDMAP_ENTRIES];
@@ -25,6 +27,9 @@ struct pid_namespace {
 #ifdef CONFIG_PROC_FS
        struct vfsmount *proc_mnt;
 #endif
+#ifdef CONFIG_BSD_PROCESS_ACCT
+       struct bsd_acct_struct *bacct;
+#endif
 };
 
 extern struct pid_namespace init_pid_ns;
@@ -85,4 +90,7 @@ static inline struct task_struct *task_child_reaper(struct task_struct *tsk)
        return tsk->nsproxy->pid_ns->child_reaper;
 }
 
+void pidhash_init(void);
+void pidmap_init(void);
+
 #endif /* _LINUX_PID_NS_H */
index 4ad9de94449a67d598ea51bbb9a322fdfbce8b11..4dcce54b6d76f798e11f3e3ae08032ee0fbac592 100644 (file)
 #define _LINUX_PM_H
 
 #include <linux/list.h>
-#include <asm/atomic.h>
-#include <asm/errno.h>
-
-/*
- * Power management requests... these are passed to pm_send_all() and friends.
- *
- * these functions are old and deprecated, see below.
- */
-typedef int __bitwise pm_request_t;
-
-#define PM_SUSPEND     ((__force pm_request_t) 1)      /* enter D1-D3 */
-#define PM_RESUME      ((__force pm_request_t) 2)      /* enter D0 */
-
-
-/*
- * Device types... these are passed to pm_register
- */
-typedef int __bitwise pm_dev_t;
-
-#define PM_UNKNOWN_DEV ((__force pm_dev_t) 0)  /* generic */
-#define PM_SYS_DEV     ((__force pm_dev_t) 1)  /* system device (fan, KB controller, ...) */
-#define PM_PCI_DEV     ((__force pm_dev_t) 2)  /* PCI device */
-#define PM_USB_DEV     ((__force pm_dev_t) 3)  /* USB device */
-#define PM_SCSI_DEV    ((__force pm_dev_t) 4)  /* SCSI device */
-#define PM_ISA_DEV     ((__force pm_dev_t) 5)  /* ISA device */
-#define        PM_MTD_DEV      ((__force pm_dev_t) 6)  /* Memory Technology Device */
-
-/*
- * System device hardware ID (PnP) values
- */
-enum
-{
-       PM_SYS_UNKNOWN = 0x00000000, /* generic */
-       PM_SYS_KBC =     0x41d00303, /* keyboard controller */
-       PM_SYS_COM =     0x41d00500, /* serial port */
-       PM_SYS_IRDA =    0x41d00510, /* IRDA controller */
-       PM_SYS_FDC =     0x41d00700, /* floppy controller */
-       PM_SYS_VGA =     0x41d00900, /* VGA controller */
-       PM_SYS_PCMCIA =  0x41d00e00, /* PCMCIA controller */
-};
-
-/*
- * Device identifier
- */
-#define PM_PCI_ID(dev) ((dev)->bus->number << 16 | (dev)->devfn)
-
-/*
- * Request handler callback
- */
-struct pm_dev;
-
-typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data);
-
-/*
- * Dynamic device information
- */
-struct pm_dev
-{
-       pm_dev_t         type;
-       unsigned long    id;
-       pm_callback      callback;
-       void            *data;
-
-       unsigned long    flags;
-       unsigned long    state;
-       unsigned long    prev_state;
-
-       struct list_head entry;
-};
-
-/* Functions above this comment are list-based old-style power
- * management. Please avoid using them.  */
 
 /*
  * Callbacks for platform drivers to implement.
@@ -317,6 +245,21 @@ struct pm_ext_ops {
  * RECOVER     Creation of a hibernation image or restoration of the main
  *             memory contents from a hibernation image has failed, call
  *             ->thaw() and ->complete() for all devices.
+ *
+ * The following PM_EVENT_ messages are defined for internal use by
+ * kernel subsystems.  They are never issued by the PM core.
+ *
+ * USER_SUSPEND                Manual selective suspend was issued by userspace.
+ *
+ * USER_RESUME         Manual selective resume was issued by userspace.
+ *
+ * REMOTE_WAKEUP       Remote-wakeup request was received from the device.
+ *
+ * AUTO_SUSPEND                Automatic (device idle) runtime suspend was
+ *                     initiated by the subsystem.
+ *
+ * AUTO_RESUME         Automatic (device needed) runtime resume was
+ *                     requested by a driver.
  */
 
 #define PM_EVENT_ON            0x0000
@@ -328,9 +271,18 @@ struct pm_ext_ops {
 #define PM_EVENT_THAW          0x0020
 #define PM_EVENT_RESTORE       0x0040
 #define PM_EVENT_RECOVER       0x0080
+#define PM_EVENT_USER          0x0100
+#define PM_EVENT_REMOTE                0x0200
+#define PM_EVENT_AUTO          0x0400
 
-#define PM_EVENT_SLEEP (PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE)
+#define PM_EVENT_SLEEP         (PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE)
+#define PM_EVENT_USER_SUSPEND  (PM_EVENT_USER | PM_EVENT_SUSPEND)
+#define PM_EVENT_USER_RESUME   (PM_EVENT_USER | PM_EVENT_RESUME)
+#define PM_EVENT_REMOTE_WAKEUP (PM_EVENT_REMOTE | PM_EVENT_RESUME)
+#define PM_EVENT_AUTO_SUSPEND  (PM_EVENT_AUTO | PM_EVENT_SUSPEND)
+#define PM_EVENT_AUTO_RESUME   (PM_EVENT_AUTO | PM_EVENT_RESUME)
 
+#define PMSG_ON                ((struct pm_message){ .event = PM_EVENT_ON, })
 #define PMSG_FREEZE    ((struct pm_message){ .event = PM_EVENT_FREEZE, })
 #define PMSG_QUIESCE   ((struct pm_message){ .event = PM_EVENT_QUIESCE, })
 #define PMSG_SUSPEND   ((struct pm_message){ .event = PM_EVENT_SUSPEND, })
@@ -339,7 +291,16 @@ struct pm_ext_ops {
 #define PMSG_THAW      ((struct pm_message){ .event = PM_EVENT_THAW, })
 #define PMSG_RESTORE   ((struct pm_message){ .event = PM_EVENT_RESTORE, })
 #define PMSG_RECOVER   ((struct pm_message){ .event = PM_EVENT_RECOVER, })
-#define PMSG_ON                ((struct pm_message){ .event = PM_EVENT_ON, })
+#define PMSG_USER_SUSPEND      ((struct pm_messge) \
+                                       { .event = PM_EVENT_USER_SUSPEND, })
+#define PMSG_USER_RESUME       ((struct pm_messge) \
+                                       { .event = PM_EVENT_USER_RESUME, })
+#define PMSG_REMOTE_RESUME     ((struct pm_messge) \
+                                       { .event = PM_EVENT_REMOTE_RESUME, })
+#define PMSG_AUTO_SUSPEND      ((struct pm_messge) \
+                                       { .event = PM_EVENT_AUTO_SUSPEND, })
+#define PMSG_AUTO_RESUME               ((struct pm_messge) \
+                                       { .event = PM_EVENT_AUTO_RESUME, })
 
 /**
  * Device power management states
diff --git a/include/linux/pm_legacy.h b/include/linux/pm_legacy.h
deleted file mode 100644 (file)
index 446f4f4..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __LINUX_PM_LEGACY_H__
-#define __LINUX_PM_LEGACY_H__
-
-
-#ifdef CONFIG_PM_LEGACY
-
-/*
- * Register a device with power management
- */
-struct pm_dev __deprecated *
-pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
-
-/*
- * Send a request to all devices
- */
-int __deprecated pm_send_all(pm_request_t rqst, void *data);
-
-#else /* CONFIG_PM_LEGACY */
-
-static inline struct pm_dev *pm_register(pm_dev_t type,
-                                        unsigned long id,
-                                        pm_callback callback)
-{
-       return NULL;
-}
-
-static inline int pm_send_all(pm_request_t rqst, void *data)
-{
-       return 0;
-}
-
-#endif /* CONFIG_PM_LEGACY */
-
-#endif /* __LINUX_PM_LEGACY_H__ */
-
index 15a9eaf4a8026101a042be7f67bd67e6d9d4411b..fb61850d1cfcf7b04352c6fa2a9d12c6c91e77f0 100644 (file)
@@ -79,6 +79,7 @@ struct proc_dir_entry {
        int pde_users;  /* number of callers into module in progress */
        spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
        struct completion *pde_unload_completion;
+       struct list_head pde_openers;   /* who did ->open, but not ->release */
 };
 
 struct kcore_list {
@@ -138,7 +139,6 @@ extern int proc_readdir(struct file *, void *, filldir_t);
 extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
 
 extern const struct file_operations proc_kcore_operations;
-extern const struct file_operations proc_kmsg_operations;
 extern const struct file_operations ppc_htab_operations;
 
 extern int pid_ns_prepare_proc(struct pid_namespace *ns);
@@ -282,11 +282,16 @@ union proc_op {
                struct task_struct *task);
 };
 
+struct ctl_table_header;
+struct ctl_table;
+
 struct proc_inode {
        struct pid *pid;
        int fd;
        union proc_op op;
        struct proc_dir_entry *pde;
+       struct ctl_table_header *sysctl;
+       struct ctl_table *sysctl_entry;
        struct inode vfs_inode;
 };
 
index 05c1cc736937fcc48d5df8781a6ad1b391f73807..7e7087239af5fc0497ebf40bf92d65cb99b5749f 100644 (file)
@@ -8,8 +8,6 @@
 
 #include <asm/errno.h>
 
-extern int prof_on __read_mostly;
-
 #define CPU_PROFILING  1
 #define SCHED_PROFILING        2
 #define SLEEP_PROFILING        3
@@ -19,14 +17,31 @@ struct proc_dir_entry;
 struct pt_regs;
 struct notifier_block;
 
+#if defined(CONFIG_PROFILING) && defined(CONFIG_PROC_FS)
+void create_prof_cpu_mask(struct proc_dir_entry *de);
+#else
+static inline void create_prof_cpu_mask(struct proc_dir_entry *de)
+{
+}
+#endif
+
+enum profile_type {
+       PROFILE_TASK_EXIT,
+       PROFILE_MUNMAP
+};
+
+#ifdef CONFIG_PROFILING
+
+extern int prof_on __read_mostly;
+
 /* init basic kernel profiler */
 void __init profile_init(void);
-void profile_tick(int);
+void profile_tick(int type);
 
 /*
  * Add multiple profiler hits to a given address:
  */
-void profile_hits(int, void *ip, unsigned int nr_hits);
+void profile_hits(int type, void *ip, unsigned int nr_hits);
 
 /*
  * Single profiler hit:
@@ -40,19 +55,6 @@ static inline void profile_hit(int type, void *ip)
                profile_hits(type, ip, 1);
 }
 
-#ifdef CONFIG_PROC_FS
-void create_prof_cpu_mask(struct proc_dir_entry *);
-#else
-#define create_prof_cpu_mask(x)                        do { (void)(x); } while (0)
-#endif
-
-enum profile_type {
-       PROFILE_TASK_EXIT,
-       PROFILE_MUNMAP
-};
-
-#ifdef CONFIG_PROFILING
-
 struct task_struct;
 struct mm_struct;
 
@@ -80,6 +82,28 @@ struct pt_regs;
 
 #else
 
+#define prof_on 0
+
+static inline void profile_init(void)
+{
+       return;
+}
+
+static inline void profile_tick(int type)
+{
+       return;
+}
+
+static inline void profile_hits(int type, void *ip, unsigned int nr_hits)
+{
+       return;
+}
+
+static inline void profile_hit(int type, void *ip)
+{
+       return;
+}
+
 static inline int task_handoff_register(struct notifier_block * n)
 {
        return -ENOSYS;
index c6f5f9dd0cee41636f282237e0ccfacf07586f96..fd31756e1a00f632189022dec352a49fe525ac62 100644 (file)
@@ -121,6 +121,74 @@ static inline void ptrace_unlink(struct task_struct *child)
 int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data);
 int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data);
 
+/**
+ * task_ptrace - return %PT_* flags that apply to a task
+ * @task:      pointer to &task_struct in question
+ *
+ * Returns the %PT_* flags that apply to @task.
+ */
+static inline int task_ptrace(struct task_struct *task)
+{
+       return task->ptrace;
+}
+
+/**
+ * ptrace_event - possibly stop for a ptrace event notification
+ * @mask:      %PT_* bit to check in @current->ptrace
+ * @event:     %PTRACE_EVENT_* value to report if @mask is set
+ * @message:   value for %PTRACE_GETEVENTMSG to return
+ *
+ * This checks the @mask bit to see if ptrace wants stops for this event.
+ * If so we stop, reporting @event and @message to the ptrace parent.
+ *
+ * Returns nonzero if we did a ptrace notification, zero if not.
+ *
+ * Called without locks.
+ */
+static inline int ptrace_event(int mask, int event, unsigned long message)
+{
+       if (mask && likely(!(current->ptrace & mask)))
+               return 0;
+       current->ptrace_message = message;
+       ptrace_notify((event << 8) | SIGTRAP);
+       return 1;
+}
+
+/**
+ * ptrace_init_task - initialize ptrace state for a new child
+ * @child:             new child task
+ * @ptrace:            true if child should be ptrace'd by parent's tracer
+ *
+ * This is called immediately after adding @child to its parent's children
+ * list.  @ptrace is false in the normal case, and true to ptrace @child.
+ *
+ * Called with current's siglock and write_lock_irq(&tasklist_lock) held.
+ */
+static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
+{
+       INIT_LIST_HEAD(&child->ptrace_entry);
+       INIT_LIST_HEAD(&child->ptraced);
+       child->parent = child->real_parent;
+       child->ptrace = 0;
+       if (unlikely(ptrace)) {
+               child->ptrace = current->ptrace;
+               __ptrace_link(child, current->parent);
+       }
+}
+
+/**
+ * ptrace_release_task - final ptrace-related cleanup of a zombie being reaped
+ * @task:      task in %EXIT_DEAD state
+ *
+ * Called with write_lock(&tasklist_lock) held.
+ */
+static inline void ptrace_release_task(struct task_struct *task)
+{
+       BUG_ON(!list_empty(&task->ptraced));
+       ptrace_unlink(task);
+       BUG_ON(!list_empty(&task->ptrace_entry));
+}
+
 #ifndef force_successful_syscall_return
 /*
  * System call handlers that, upon successful completion, need to return a
@@ -246,6 +314,10 @@ static inline void user_enable_block_step(struct task_struct *task)
 #define arch_ptrace_stop(code, info)           do { } while (0)
 #endif
 
+extern int task_current_syscall(struct task_struct *target, long *callno,
+                               unsigned long args[6], unsigned int maxargs,
+                               unsigned long *sp, unsigned long *pc);
+
 #endif
 
 #endif
index dcddfb2009479f42a543363d0c0873c76d4bfcee..376a05048bc580650bd1923c9f21c6e3852cea11 100644 (file)
@@ -41,9 +41,6 @@
 #define __DQUOT_VERSION__      "dquot_6.5.1"
 #define __DQUOT_NUM_VERSION__  6*10000+5*100+1
 
-typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
-typedef __u64 qsize_t;          /* Type in which we store sizes */
-
 /* Size of blocks in which are counted size limits */
 #define QUOTABLOCK_BITS 10
 #define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
@@ -138,6 +135,10 @@ struct if_dqinfo {
 #define QUOTA_NL_BHARDWARN 4           /* Block hardlimit reached */
 #define QUOTA_NL_BSOFTLONGWARN 5       /* Block grace time expired */
 #define QUOTA_NL_BSOFTWARN 6           /* Block softlimit reached */
+#define QUOTA_NL_IHARDBELOW 7          /* Usage got below inode hardlimit */
+#define QUOTA_NL_ISOFTBELOW 8          /* Usage got below inode softlimit */
+#define QUOTA_NL_BHARDBELOW 9          /* Usage got below block hardlimit */
+#define QUOTA_NL_BSOFTBELOW 10         /* Usage got below block softlimit */
 
 enum {
        QUOTA_NL_C_UNSPEC,
@@ -172,6 +173,9 @@ enum {
 
 #include <asm/atomic.h>
 
+typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
+typedef __u64 qsize_t;          /* Type in which we store sizes */
+
 extern spinlock_t dq_data_lock;
 
 /* Maximal numbers of writes for quota operation (insert/delete/update)
@@ -223,12 +227,10 @@ struct super_block;
 #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */
 
 extern void mark_info_dirty(struct super_block *sb, int type);
-#define info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags)
-#define info_any_dquot_dirty(info) (!list_empty(&(info)->dqi_dirty_list))
-#define info_any_dirty(info) (info_dirty(info) || info_any_dquot_dirty(info))
-
-#define sb_dqopt(sb) (&(sb)->s_dquot)
-#define sb_dqinfo(sb, type) (sb_dqopt(sb)->info+(type))
+static inline int info_dirty(struct mem_dqinfo *info)
+{
+       return test_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
+}
 
 struct dqstats {
        int lookups;
@@ -337,19 +339,6 @@ struct quota_info {
        struct quota_format_ops *ops[MAXQUOTAS];        /* Operations for each type */
 };
 
-#define sb_has_quota_enabled(sb, type) ((type)==USRQUOTA ? \
-       (sb_dqopt(sb)->flags & DQUOT_USR_ENABLED) : (sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED))
-
-#define sb_any_quota_enabled(sb) (sb_has_quota_enabled(sb, USRQUOTA) | \
-                                 sb_has_quota_enabled(sb, GRPQUOTA))
-
-#define sb_has_quota_suspended(sb, type) \
-       ((type) == USRQUOTA ? (sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED) : \
-                             (sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED))
-
-#define sb_any_quota_suspended(sb) (sb_has_quota_suspended(sb, USRQUOTA) | \
-                                 sb_has_quota_suspended(sb, GRPQUOTA))
-
 int register_quota_format(struct quota_format_type *fmt);
 void unregister_quota_format(struct quota_format_type *fmt);
 
index f867020538539738cafa8ac22130379889452833..742187f7a05c54051da11975373acd5cc3de56e2 100644 (file)
 #define _LINUX_QUOTAOPS_
 
 #include <linux/smp_lock.h>
-
 #include <linux/fs.h>
 
+static inline struct quota_info *sb_dqopt(struct super_block *sb)
+{
+       return &sb->s_dquot;
+}
+
 #if defined(CONFIG_QUOTA)
 
 /*
  * declaration of quota_function calls in kernel.
  */
-extern void sync_dquots(struct super_block *sb, int type);
-
-extern int dquot_initialize(struct inode *inode, int type);
-extern int dquot_drop(struct inode *inode);
-
-extern int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
-extern int dquot_alloc_inode(const struct inode *inode, unsigned long number);
-
-extern int dquot_free_space(struct inode *inode, qsize_t number);
-extern int dquot_free_inode(const struct inode *inode, unsigned long number);
-
-extern int dquot_transfer(struct inode *inode, struct iattr *iattr);
-extern int dquot_commit(struct dquot *dquot);
-extern int dquot_acquire(struct dquot *dquot);
-extern int dquot_release(struct dquot *dquot);
-extern int dquot_commit_info(struct super_block *sb, int type);
-extern int dquot_mark_dquot_dirty(struct dquot *dquot);
-
-extern int vfs_quota_on(struct super_block *sb, int type, int format_id,
-               char *path, int remount);
-extern int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
-               int format_id, int type);
-extern int vfs_quota_off(struct super_block *sb, int type, int remount);
-extern int vfs_quota_sync(struct super_block *sb, int type);
-extern int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
-extern int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
-extern int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
-extern int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
+void sync_dquots(struct super_block *sb, int type);
+
+int dquot_initialize(struct inode *inode, int type);
+int dquot_drop(struct inode *inode);
+
+int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
+int dquot_alloc_inode(const struct inode *inode, unsigned long number);
+
+int dquot_free_space(struct inode *inode, qsize_t number);
+int dquot_free_inode(const struct inode *inode, unsigned long number);
+
+int dquot_transfer(struct inode *inode, struct iattr *iattr);
+int dquot_commit(struct dquot *dquot);
+int dquot_acquire(struct dquot *dquot);
+int dquot_release(struct dquot *dquot);
+int dquot_commit_info(struct super_block *sb, int type);
+int dquot_mark_dquot_dirty(struct dquot *dquot);
+
+int vfs_quota_on(struct super_block *sb, int type, int format_id,
+       char *path, int remount);
+int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
+       int format_id, int type);
+int vfs_quota_off(struct super_block *sb, int type, int remount);
+int vfs_quota_sync(struct super_block *sb, int type);
+int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
+int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
+
+void vfs_dq_drop(struct inode *inode);
+int vfs_dq_transfer(struct inode *inode, struct iattr *iattr);
+int vfs_dq_quota_on_remount(struct super_block *sb);
+
+static inline struct mem_dqinfo *sb_dqinfo(struct super_block *sb, int type)
+{
+       return sb_dqopt(sb)->info + type;
+}
+
+/*
+ * Functions for checking status of quota
+ */
+
+static inline int sb_has_quota_enabled(struct super_block *sb, int type)
+{
+       if (type == USRQUOTA)
+               return sb_dqopt(sb)->flags & DQUOT_USR_ENABLED;
+       return sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED;
+}
+
+static inline int sb_any_quota_enabled(struct super_block *sb)
+{
+       return sb_has_quota_enabled(sb, USRQUOTA) ||
+               sb_has_quota_enabled(sb, GRPQUOTA);
+}
+
+static inline int sb_has_quota_suspended(struct super_block *sb, int type)
+{
+       if (type == USRQUOTA)
+               return sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED;
+       return sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED;
+}
+
+static inline int sb_any_quota_suspended(struct super_block *sb)
+{
+       return sb_has_quota_suspended(sb, USRQUOTA) ||
+               sb_has_quota_suspended(sb, GRPQUOTA);
+}
 
 /*
  * Operations supported for diskquotas.
@@ -59,38 +102,16 @@ extern struct quotactl_ops vfs_quotactl_ops;
 
 /* It is better to call this function outside of any transaction as it might
  * need a lot of space in journal for dquot structure allocation. */
-static inline void DQUOT_INIT(struct inode *inode)
+static inline void vfs_dq_init(struct inode *inode)
 {
        BUG_ON(!inode->i_sb);
        if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode))
                inode->i_sb->dq_op->initialize(inode, -1);
 }
 
-/* The same as with DQUOT_INIT */
-static inline void DQUOT_DROP(struct inode *inode)
-{
-       /* Here we can get arbitrary inode from clear_inode() so we have
-        * to be careful. OTOH we don't need locking as quota operations
-        * are allowed to change only at mount time */
-       if (!IS_NOQUOTA(inode) && inode->i_sb && inode->i_sb->dq_op
-           && inode->i_sb->dq_op->drop) {
-               int cnt;
-               /* Test before calling to rule out calls from proc and such
-                 * where we are not allowed to block. Note that this is
-                * actually reliable test even without the lock - the caller
-                * must assure that nobody can come after the DQUOT_DROP and
-                * add quota pointers back anyway */
-               for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-                       if (inode->i_dquot[cnt] != NODQUOT)
-                               break;
-               if (cnt < MAXQUOTAS)
-                       inode->i_sb->dq_op->drop(inode);
-       }
-}
-
 /* The following allocation/freeing/transfer functions *must* be called inside
  * a transaction (deadlocks possible otherwise) */
-static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr)
 {
        if (sb_any_quota_enabled(inode->i_sb)) {
                /* Used space is updated in alloc_space() */
@@ -102,15 +123,15 @@ static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
        return 0;
 }
 
-static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr)
 {
        int ret;
-        if (!(ret =  DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr)))
+        if (!(ret =  vfs_dq_prealloc_space_nodirty(inode, nr)))
                mark_inode_dirty(inode);
        return ret;
 }
 
-static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr)
 {
        if (sb_any_quota_enabled(inode->i_sb)) {
                /* Used space is updated in alloc_space() */
@@ -122,25 +143,25 @@ static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
        return 0;
 }
 
-static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
 {
        int ret;
-       if (!(ret = DQUOT_ALLOC_SPACE_NODIRTY(inode, nr)))
+       if (!(ret = vfs_dq_alloc_space_nodirty(inode, nr)))
                mark_inode_dirty(inode);
        return ret;
 }
 
-static inline int DQUOT_ALLOC_INODE(struct inode *inode)
+static inline int vfs_dq_alloc_inode(struct inode *inode)
 {
        if (sb_any_quota_enabled(inode->i_sb)) {
-               DQUOT_INIT(inode);
+               vfs_dq_init(inode);
                if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA)
                        return 1;
        }
        return 0;
 }
 
-static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
        if (sb_any_quota_enabled(inode->i_sb))
                inode->i_sb->dq_op->free_space(inode, nr);
@@ -148,35 +169,25 @@ static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
                inode_sub_bytes(inode, nr);
 }
 
-static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
 {
-       DQUOT_FREE_SPACE_NODIRTY(inode, nr);
+       vfs_dq_free_space_nodirty(inode, nr);
        mark_inode_dirty(inode);
 }
 
-static inline void DQUOT_FREE_INODE(struct inode *inode)
+static inline void vfs_dq_free_inode(struct inode *inode)
 {
        if (sb_any_quota_enabled(inode->i_sb))
                inode->i_sb->dq_op->free_inode(inode, 1);
 }
 
-static inline int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
-{
-       if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) {
-               DQUOT_INIT(inode);
-               if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA)
-                       return 1;
-       }
-       return 0;
-}
-
 /* The following two functions cannot be called inside a transaction */
-static inline void DQUOT_SYNC(struct super_block *sb)
+static inline void vfs_dq_sync(struct super_block *sb)
 {
        sync_dquots(sb, -1);
 }
 
-static inline int DQUOT_OFF(struct super_block *sb, int remount)
+static inline int vfs_dq_off(struct super_block *sb, int remount)
 {
        int ret = -ENOSYS;
 
@@ -185,22 +196,27 @@ static inline int DQUOT_OFF(struct super_block *sb, int remount)
        return ret;
 }
 
-static inline int DQUOT_ON_REMOUNT(struct super_block *sb)
+#else
+
+static inline int sb_has_quota_enabled(struct super_block *sb, int type)
 {
-       int cnt;
-       int ret = 0, err;
+       return 0;
+}
 
-       if (!sb->s_qcop || !sb->s_qcop->quota_on)
-               return -ENOSYS;
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               err = sb->s_qcop->quota_on(sb, cnt, 0, NULL, 1);
-               if (err < 0 && !ret)
-                       ret = err;
-       }
-       return ret;
+static inline int sb_any_quota_enabled(struct super_block *sb)
+{
+       return 0;
 }
 
-#else
+static inline int sb_has_quota_suspended(struct super_block *sb, int type)
+{
+       return 0;
+}
+
+static inline int sb_any_quota_suspended(struct super_block *sb)
+{
+       return 0;
+}
 
 /*
  * NO-OP when quota not configured.
@@ -208,113 +224,144 @@ static inline int DQUOT_ON_REMOUNT(struct super_block *sb)
 #define sb_dquot_ops                           (NULL)
 #define sb_quotactl_ops                                (NULL)
 
-static inline void DQUOT_INIT(struct inode *inode)
+static inline void vfs_dq_init(struct inode *inode)
 {
 }
 
-static inline void DQUOT_DROP(struct inode *inode)
+static inline void vfs_dq_drop(struct inode *inode)
 {
 }
 
-static inline int DQUOT_ALLOC_INODE(struct inode *inode)
+static inline int vfs_dq_alloc_inode(struct inode *inode)
 {
        return 0;
 }
 
-static inline void DQUOT_FREE_INODE(struct inode *inode)
+static inline void vfs_dq_free_inode(struct inode *inode)
 {
 }
 
-static inline void DQUOT_SYNC(struct super_block *sb)
+static inline void vfs_dq_sync(struct super_block *sb)
 {
 }
 
-static inline int DQUOT_OFF(struct super_block *sb, int remount)
+static inline int vfs_dq_off(struct super_block *sb, int remount)
 {
        return 0;
 }
 
-static inline int DQUOT_ON_REMOUNT(struct super_block *sb)
+static inline int vfs_dq_quota_on_remount(struct super_block *sb)
 {
        return 0;
 }
 
-static inline int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
+static inline int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
 {
        return 0;
 }
 
-static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr)
 {
        inode_add_bytes(inode, nr);
        return 0;
 }
 
-static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr)
 {
-       DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr);
+       vfs_dq_prealloc_space_nodirty(inode, nr);
        mark_inode_dirty(inode);
        return 0;
 }
 
-static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr)
 {
        inode_add_bytes(inode, nr);
        return 0;
 }
 
-static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
 {
-       DQUOT_ALLOC_SPACE_NODIRTY(inode, nr);
+       vfs_dq_alloc_space_nodirty(inode, nr);
        mark_inode_dirty(inode);
        return 0;
 }
 
-static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
        inode_sub_bytes(inode, nr);
 }
 
-static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
 {
-       DQUOT_FREE_SPACE_NODIRTY(inode, nr);
+       vfs_dq_free_space_nodirty(inode, nr);
        mark_inode_dirty(inode);
 }      
 
 #endif /* CONFIG_QUOTA */
 
-static inline int DQUOT_PREALLOC_BLOCK_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_block_nodirty(struct inode *inode, qsize_t nr)
 {
-       return DQUOT_PREALLOC_SPACE_NODIRTY(inode,
+       return vfs_dq_prealloc_space_nodirty(inode,
                        nr << inode->i_sb->s_blocksize_bits);
 }
 
-static inline int DQUOT_PREALLOC_BLOCK(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_block(struct inode *inode, qsize_t nr)
 {
-       return DQUOT_PREALLOC_SPACE(inode,
+       return vfs_dq_prealloc_space(inode,
                        nr << inode->i_sb->s_blocksize_bits);
 }
 
-static inline int DQUOT_ALLOC_BLOCK_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_block_nodirty(struct inode *inode, qsize_t nr)
 {
-       return DQUOT_ALLOC_SPACE_NODIRTY(inode,
+       return vfs_dq_alloc_space_nodirty(inode,
                        nr << inode->i_sb->s_blocksize_bits);
 }
 
-static inline int DQUOT_ALLOC_BLOCK(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr)
 {
-       return DQUOT_ALLOC_SPACE(inode,
+       return vfs_dq_alloc_space(inode,
                        nr << inode->i_sb->s_blocksize_bits);
 }
 
-static inline void DQUOT_FREE_BLOCK_NODIRTY(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
 {
-       DQUOT_FREE_SPACE_NODIRTY(inode, nr << inode->i_sb->s_blocksize_bits);
+       vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);
 }
 
-static inline void DQUOT_FREE_BLOCK(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr)
 {
-       DQUOT_FREE_SPACE(inode, nr << inode->i_sb->s_blocksize_bits);
+       vfs_dq_free_space(inode, nr << inode->i_sb->s_blocksize_bits);
 }
 
+/*
+ * Define uppercase equivalents for compatibility with old function names
+ * Can go away when we think all users have been converted (15/04/2008)
+ */
+#define DQUOT_INIT(inode) vfs_dq_init(inode)
+#define DQUOT_DROP(inode) vfs_dq_drop(inode)
+#define DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr) \
+                               vfs_dq_prealloc_space_nodirty(inode, nr)
+#define DQUOT_PREALLOC_SPACE(inode, nr) vfs_dq_prealloc_space(inode, nr)
+#define DQUOT_ALLOC_SPACE_NODIRTY(inode, nr) \
+                               vfs_dq_alloc_space_nodirty(inode, nr)
+#define DQUOT_ALLOC_SPACE(inode, nr) vfs_dq_alloc_space(inode, nr)
+#define DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr) \
+                               vfs_dq_prealloc_block_nodirty(inode, nr)
+#define DQUOT_PREALLOC_BLOCK(inode, nr) vfs_dq_prealloc_block(inode, nr)
+#define DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr) \
+                               vfs_dq_alloc_block_nodirty(inode, nr)
+#define DQUOT_ALLOC_BLOCK(inode, nr) vfs_dq_alloc_block(inode, nr)
+#define DQUOT_ALLOC_INODE(inode) vfs_dq_alloc_inode(inode)
+#define DQUOT_FREE_SPACE_NODIRTY(inode, nr) \
+                               vfs_dq_free_space_nodirty(inode, nr)
+#define DQUOT_FREE_SPACE(inode, nr) vfs_dq_free_space(inode, nr)
+#define DQUOT_FREE_BLOCK_NODIRTY(inode, nr) \
+                               vfs_dq_free_block_nodirty(inode, nr)
+#define DQUOT_FREE_BLOCK(inode, nr) vfs_dq_free_block(inode, nr)
+#define DQUOT_FREE_INODE(inode) vfs_dq_free_inode(inode)
+#define DQUOT_TRANSFER(inode, iattr) vfs_dq_transfer(inode, iattr)
+#define DQUOT_SYNC(sb) vfs_dq_sync(sb)
+#define DQUOT_OFF(sb, remount) vfs_dq_off(sb, remount)
+#define DQUOT_ON_REMOUNT(sb) vfs_dq_quota_on_remount(sb)
+
 #endif /* _LINUX_QUOTAOPS_ */
index b8ce2b444bb51b3f74130a0ad11acbf3d729069e..a916c6660dfa0ac94d9c08768b9b627470985247 100644 (file)
@@ -99,12 +99,15 @@ do {                                                                        \
  *
  * The notable exceptions to this rule are the following functions:
  * radix_tree_lookup
+ * radix_tree_lookup_slot
  * radix_tree_tag_get
  * radix_tree_gang_lookup
+ * radix_tree_gang_lookup_slot
  * radix_tree_gang_lookup_tag
+ * radix_tree_gang_lookup_tag_slot
  * radix_tree_tagged
  *
- * The first 4 functions are able to be called locklessly, using RCU. The
+ * The first 7 functions are able to be called locklessly, using RCU. The
  * caller must ensure calls to these functions are made within rcu_read_lock()
  * regions. Other readers (lock-free or otherwise) and modifications may be
  * running concurrently.
@@ -159,6 +162,9 @@ void *radix_tree_delete(struct radix_tree_root *, unsigned long);
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
                        unsigned long first_index, unsigned int max_items);
+unsigned int
+radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
+                       unsigned long first_index, unsigned int max_items);
 unsigned long radix_tree_next_hole(struct radix_tree_root *root,
                                unsigned long index, unsigned long max_scan);
 int radix_tree_preload(gfp_t gfp_mask);
@@ -173,6 +179,10 @@ unsigned int
 radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
                unsigned long first_index, unsigned int max_items,
                unsigned int tag);
+unsigned int
+radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results,
+               unsigned long first_index, unsigned int max_items,
+               unsigned int tag);
 int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag);
 
 static inline void radix_tree_preload_end(void)
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h
new file mode 100644 (file)
index 0000000..18a5b9b
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _LINUX_RATELIMIT_H
+#define _LINUX_RATELIMIT_H
+#include <linux/param.h>
+
+#define DEFAULT_RATELIMIT_INTERVAL (5 * HZ)
+#define DEFAULT_RATELIMIT_BURST 10
+
+struct ratelimit_state {
+       int interval;
+       int burst;
+       int printed;
+       int missed;
+       unsigned long begin;
+};
+
+#define DEFINE_RATELIMIT_STATE(name, interval, burst)          \
+               struct ratelimit_state name = {interval, burst,}
+
+extern int __ratelimit(struct ratelimit_state *rs);
+
+static inline int ratelimit(void)
+{
+       static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
+                                       DEFAULT_RATELIMIT_BURST);
+       return __ratelimit(&rs);
+}
+#endif
index b0f39be08b6c31a6d723f107e52cc31a7f3b1f78..eb4443c7e05be213f49596b81b50f209923ab4da 100644 (file)
@@ -97,6 +97,34 @@ static inline void list_del_rcu(struct list_head *entry)
        entry->prev = LIST_POISON2;
 }
 
+/**
+ * hlist_del_init_rcu - deletes entry from hash list with re-initialization
+ * @n: the element to delete from the hash list.
+ *
+ * Note: list_unhashed() on the node return true after this. It is
+ * useful for RCU based read lockfree traversal if the writer side
+ * must know if the list entry is still hashed or already unhashed.
+ *
+ * In particular, it means that we can not poison the forward pointers
+ * that may still be used for walking the hash list and we can only
+ * zero the pprev pointer so list_unhashed() will return true after
+ * this.
+ *
+ * The caller must take whatever precautions are necessary (such as
+ * holding appropriate locks) to avoid racing with another
+ * list-mutation primitive, such as hlist_add_head_rcu() or
+ * hlist_del_rcu(), running on this same list.  However, it is
+ * perfectly legal to run concurrently with the _rcu list-traversal
+ * primitives, such as hlist_for_each_entry_rcu().
+ */
+static inline void hlist_del_init_rcu(struct hlist_node *n)
+{
+       if (!hlist_unhashed(n)) {
+               __hlist_del(n);
+               n->pprev = NULL;
+       }
+}
+
 /**
  * list_replace_rcu - replace old entry by new one
  * @old : the element to be replaced
index f04b64eca6366766d2abf74ded470bce99791e3d..0967f03b07056928c4176826d4bf216f329cbde9 100644 (file)
@@ -115,16 +115,21 @@ DECLARE_PER_CPU(struct rcu_dyntick_sched, rcu_dyntick_sched);
 
 static inline void rcu_enter_nohz(void)
 {
+       static DEFINE_RATELIMIT_STATE(rs, 10 * HZ, 1);
+
        smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */
        __get_cpu_var(rcu_dyntick_sched).dynticks++;
-       WARN_ON(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1);
+       WARN_ON_RATELIMIT(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1, &rs);
 }
 
 static inline void rcu_exit_nohz(void)
 {
+       static DEFINE_RATELIMIT_STATE(rs, 10 * HZ, 1);
+
        smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */
        __get_cpu_var(rcu_dyntick_sched).dynticks++;
-       WARN_ON(!(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1));
+       WARN_ON_RATELIMIT(!(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1),
+                               &rs);
 }
 
 #else /* CONFIG_NO_HZ */
index 4aacaeecb56f503adf60a680710b46fc485a39d4..e9963af16cda6ade6ede6dded784c2624f4bc449 100644 (file)
@@ -526,8 +526,8 @@ struct item_head {
 ** p is the array of __u32, i is the index into the array, v is the value
 ** to store there.
 */
-#define get_block_num(p, i) le32_to_cpu(get_unaligned((p) + (i)))
-#define put_block_num(p, i, v) put_unaligned(cpu_to_le32(v), (p) + (i))
+#define get_block_num(p, i) get_unaligned_le32((p) + (i))
+#define put_block_num(p, i, v) put_unaligned_le32((v), (p) + (i))
 
 //
 // in old version uniqueness field shows key type
index 336ee43ed7d8897eb9a1b4c7453123bf7ab3ebc8..315517e8bfa1cdd6704f4a9620ca8a3d8c7f5d2a 100644 (file)
@@ -152,7 +152,7 @@ struct reiserfs_journal_list {
        atomic_t j_nonzerolen;
        atomic_t j_commit_left;
        atomic_t j_older_commits_done;  /* all commits older than this on disk */
-       struct semaphore j_commit_lock;
+       struct mutex j_commit_mutex;
        unsigned long j_trans_id;
        time_t j_timestamp;
        struct reiserfs_list_bitmap *j_list_bitmap;
@@ -193,8 +193,8 @@ struct reiserfs_journal {
        struct buffer_head *j_header_bh;
 
        time_t j_trans_start_time;      /* time this transaction started */
-       struct semaphore j_lock;
-       struct semaphore j_flush_sem;
+       struct mutex j_mutex;
+       struct mutex j_flush_mutex;
        wait_queue_head_t j_join_wait;  /* wait for current transaction to finish before starting new one */
        atomic_t j_jlock;       /* lock for j_join_wait */
        int j_list_bitmap_index;        /* number of next list bitmap to use */
index 66a96814d614c7dd23c4371d80a54a1a829b6a84..af135ae895db2d3523839c5f1a0857ed54db3aca 100644 (file)
@@ -55,7 +55,7 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name);
 int reiserfs_delete_xattrs(struct inode *inode);
 int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
 int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
-int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd);
+int reiserfs_permission(struct inode *inode, int mask);
 
 int reiserfs_xattr_del(struct inode *, const char *);
 int reiserfs_xattr_get(const struct inode *, const char *, void *, size_t);
index 6cd8c4425fc7d5dfb400b37b436c960bf6e163d7..953fc055e87567fc4034af88020c114885b78b3c 100644 (file)
@@ -48,6 +48,7 @@ struct rchan_buf
        size_t *padding;                /* padding counts per sub-buffer */
        size_t prev_padding;            /* temporary variable */
        size_t bytes_consumed;          /* bytes consumed in cur read subbuf */
+       size_t early_bytes;             /* bytes consumed before VFS inited */
        unsigned int cpu;               /* this buf's cpu */
 } ____cacheline_aligned;
 
@@ -68,6 +69,7 @@ struct rchan
        int is_global;                  /* One global buffer ? */
        struct list_head list;          /* for channel list */
        struct dentry *parent;          /* parent dentry passed to open */
+       int has_base_filename;          /* has a filename associated? */
        char base_filename[NAME_MAX];   /* saved base filename */
 };
 
@@ -169,6 +171,9 @@ struct rchan *relay_open(const char *base_filename,
                         size_t n_subbufs,
                         struct rchan_callbacks *cb,
                         void *private_data);
+extern int relay_late_setup_files(struct rchan *chan,
+                                 const char *base_filename,
+                                 struct dentry *parent);
 extern void relay_close(struct rchan *chan);
 extern void relay_flush(struct rchan *chan);
 extern void relay_subbufs_consumed(struct rchan *chan,
index 6d9e1fca098c468b49287791e181f6e4f51e7d54..fdeadd9740dc5f99deaa4a8662494914f438e8c4 100644 (file)
@@ -63,9 +63,14 @@ u64 res_counter_read_u64(struct res_counter *counter, int member);
 ssize_t res_counter_read(struct res_counter *counter, int member,
                const char __user *buf, size_t nbytes, loff_t *pos,
                int (*read_strategy)(unsigned long long val, char *s));
-ssize_t res_counter_write(struct res_counter *counter, int member,
-               const char __user *buf, size_t nbytes, loff_t *pos,
-               int (*write_strategy)(char *buf, unsigned long long *val));
+
+typedef int (*write_strategy_fn)(const char *buf, unsigned long long *val);
+
+int res_counter_memparse_write_strategy(const char *buf,
+                                       unsigned long long *res);
+
+int res_counter_write(struct res_counter *counter, int member,
+                     const char *buffer, write_strategy_fn write_strategy);
 
 /*
  * the field descriptors. one for each member of res_counter
@@ -95,8 +100,10 @@ void res_counter_init(struct res_counter *counter);
  * counter->limit _locked call expects the counter->lock to be taken
  */
 
-int res_counter_charge_locked(struct res_counter *counter, unsigned long val);
-int res_counter_charge(struct res_counter *counter, unsigned long val);
+int __must_check res_counter_charge_locked(struct res_counter *counter,
+               unsigned long val);
+int __must_check res_counter_charge(struct res_counter *counter,
+               unsigned long val);
 
 /*
  * uncharge - tell that some portion of the resource is released
@@ -151,4 +158,20 @@ static inline void res_counter_reset_failcnt(struct res_counter *cnt)
        cnt->failcnt = 0;
        spin_unlock_irqrestore(&cnt->lock, flags);
 }
+
+static inline int res_counter_set_limit(struct res_counter *cnt,
+               unsigned long long limit)
+{
+       unsigned long flags;
+       int ret = -EBUSY;
+
+       spin_lock_irqsave(&cnt->lock, flags);
+       if (cnt->usage < limit) {
+               cnt->limit = limit;
+               ret = 0;
+       }
+       spin_unlock_irqrestore(&cnt->lock, flags);
+       return ret;
+}
+
 #endif
index 1383692ac5bd8c8dc5c06498a38795a256f56c93..69407f85e10b32daa4bd8ac82f88d43e36b82f78 100644 (file)
  */
 struct anon_vma {
        spinlock_t lock;        /* Serialize access to vma list */
+       /*
+        * NOTE: the LSB of the head.next is set by
+        * mm_take_all_locks() _after_ taking the above lock. So the
+        * head must only be read/written after taking the above lock
+        * to be sure to see a valid next pointer. The LSB bit itself
+        * is serialized by a system wide lock only visible to
+        * mm_take_all_locks() (mm_all_locks_mutex).
+        */
        struct list_head head;  /* List of private "related" vmas */
 };
 
index f2d0d15277216f9655ab254f3f9c9ef3ea471972..91f597ad6acc5d1659f66f90039408b01b23e8b5 100644 (file)
@@ -115,6 +115,23 @@ extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
 
 extern struct class *rtc_class;
 
+/*
+ * For these RTC methods the device parameter is the physical device
+ * on whatever bus holds the hardware (I2C, Platform, SPI, etc), which
+ * was passed to rtc_device_register().  Its driver_data normally holds
+ * device state, including the rtc_device pointer for the RTC.
+ *
+ * Most of these methods are called with rtc_device.ops_lock held,
+ * through the rtc_*(struct rtc_device *, ...) calls.
+ *
+ * The (current) exceptions are mostly filesystem hooks:
+ *   - the proc() hook for procfs
+ *   - non-ioctl() chardev hooks:  open(), release(), read_callback()
+ *   - periodic irq calls:  irq_set_state(), irq_set_freq()
+ *
+ * REVISIT those periodic irq calls *do* have ops_lock when they're
+ * issued through ioctl() ...
+ */
 struct rtc_class_ops {
        int (*open)(struct device *);
        void (*release)(struct device *);
@@ -208,8 +225,6 @@ typedef struct rtc_task {
 int rtc_register(rtc_task_t *task);
 int rtc_unregister(rtc_task_t *task);
 int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg);
-void rtc_get_rtc_time(struct rtc_time *rtc_tm);
-irqreturn_t rtc_interrupt(int irq, void *dev_id);
 
 #endif /* __KERNEL__ */
 
index f4d386c191f587507dac62b17de0ea26cfe3fbee..ca643b13b02635bfd33bae20588418ca52ff3f3b 100644 (file)
@@ -755,13 +755,6 @@ extern void __rtnl_unlock(void);
        } \
 } while(0)
 
-#define BUG_TRAP(x) do { \
-       if (unlikely(!(x))) { \
-               printk(KERN_ERR "KERNEL: assertion (%s) failed at %s (%d)\n", \
-                       #x,  __FILE__ , __LINE__); \
-       } \
-} while(0)
-
 static inline u32 rtm_get_table(struct rtattr **rta, u8 table)
 {
        return RTA_GET_U32(rta[RTA_TABLE-1]);
index dc7e592c473a85bc393ccff60c54ccbda87e1e32..5270d449ff9deb9036f0b4d7852c4877dc561262 100644 (file)
@@ -292,7 +292,6 @@ extern void sched_show_task(struct task_struct *p);
 
 #ifdef CONFIG_DETECT_SOFTLOCKUP
 extern void softlockup_tick(void);
-extern void spawn_softlockup_task(void);
 extern void touch_softlockup_watchdog(void);
 extern void touch_all_softlockup_watchdogs(void);
 extern unsigned int  softlockup_panic;
@@ -506,6 +505,7 @@ struct signal_struct {
        unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
        unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
        unsigned long inblock, oublock, cinblock, coublock;
+       struct task_io_accounting ioac;
 
        /*
         * Cumulative ns of scheduled CPU time for dead threads in the
@@ -668,6 +668,10 @@ struct task_delay_info {
                                /* io operations performed */
        u32 swapin_count;       /* total count of the number of swapin block */
                                /* io operations performed */
+
+       struct timespec freepages_start, freepages_end;
+       u64 freepages_delay;    /* wait for memory reclaim */
+       u32 freepages_count;    /* total count of memory reclaim */
 };
 #endif /* CONFIG_TASK_DELAY_ACCT */
 
@@ -1249,15 +1253,11 @@ struct task_struct {
 
        unsigned long ptrace_message;
        siginfo_t *last_siginfo; /* For ptrace use.  */
-#ifdef CONFIG_TASK_XACCT
-/* i/o counters(bytes read/written, #syscalls */
-       u64 rchar, wchar, syscr, syscw;
-#endif
        struct task_io_accounting ioac;
 #if defined(CONFIG_TASK_XACCT)
        u64 acct_rss_mem1;      /* accumulated rss usage */
        u64 acct_vm_mem1;       /* accumulated virtual memory usage */
-       cputime_t acct_stimexpd;/* stime since last update */
+       cputime_t acct_timexpd; /* stime + utime since last update */
 #endif
 #ifdef CONFIG_CPUSETS
        nodemask_t mems_allowed;
@@ -1496,7 +1496,7 @@ static inline void put_task_struct(struct task_struct *t)
 #define PF_KSWAPD      0x00040000      /* I am kswapd */
 #define PF_SWAPOFF     0x00080000      /* I am in swapoff */
 #define PF_LESS_THROTTLE 0x00100000    /* Throttle me less: I clean memory */
-#define PF_BORROWED_MM 0x00200000      /* I am a kthread doing use_mm */
+#define PF_KTHREAD     0x00200000      /* I am a kernel thread */
 #define PF_RANDOMIZE   0x00400000      /* randomize virtual address space */
 #define PF_SWAPWRITE   0x00800000      /* Allowed to write to swap */
 #define PF_SPREAD_PAGE 0x01000000      /* Spread page cache over cpuset */
@@ -1715,19 +1715,13 @@ extern struct pid_namespace init_pid_ns;
  *      finds a task by its pid in the specified namespace
  * find_task_by_vpid():
  *      finds a task by its virtual pid
- * find_task_by_pid():
- *      finds a task by its global pid
  *
- * see also find_pid() etc in include/linux/pid.h
+ * see also find_vpid() etc in include/linux/pid.h
  */
 
 extern struct task_struct *find_task_by_pid_type_ns(int type, int pid,
                struct pid_namespace *ns);
 
-static inline struct task_struct *__deprecated find_task_by_pid(pid_t nr)
-{
-       return find_task_by_pid_type_ns(PIDTYPE_PID, nr, &init_pid_ns);
-}
 extern struct task_struct *find_task_by_vpid(pid_t nr);
 extern struct task_struct *find_task_by_pid_ns(pid_t nr,
                struct pid_namespace *ns);
@@ -1795,12 +1789,11 @@ extern int kill_pid_info_as_uid(int, struct siginfo *, struct pid *, uid_t, uid_
 extern int kill_pgrp(struct pid *pid, int sig, int priv);
 extern int kill_pid(struct pid *pid, int sig, int priv);
 extern int kill_proc_info(int, struct siginfo *, pid_t);
-extern void do_notify_parent(struct task_struct *, int);
+extern int do_notify_parent(struct task_struct *, int);
 extern void force_sig(int, struct task_struct *);
 extern void force_sig_specific(int, struct task_struct *);
 extern int send_sig(int, struct task_struct *, int);
 extern void zap_other_threads(struct task_struct *p);
-extern int kill_proc(pid_t, int, int);
 extern struct sigqueue *sigqueue_alloc(void);
 extern void sigqueue_free(struct sigqueue *);
 extern int send_sigqueue(struct sigqueue *,  struct task_struct *, int group);
@@ -1882,9 +1875,13 @@ extern void set_task_comm(struct task_struct *tsk, char *from);
 extern char *get_task_comm(char *to, struct task_struct *tsk);
 
 #ifdef CONFIG_SMP
-extern void wait_task_inactive(struct task_struct * p);
+extern unsigned long wait_task_inactive(struct task_struct *, long match_state);
 #else
-#define wait_task_inactive(p)  do { } while (0)
+static inline unsigned long wait_task_inactive(struct task_struct *p,
+                                              long match_state)
+{
+       return 1;
+}
 #endif
 
 #define next_task(p)   list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
@@ -1983,6 +1980,13 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
 
 #endif
 
+static inline int object_is_on_stack(void *obj)
+{
+       void *stack = task_stack_page(current);
+
+       return (obj >= stack) && (obj < (stack + THREAD_SIZE));
+}
+
 extern void thread_info_cache_init(void);
 
 /* set thread flags in other task's structures
@@ -2047,9 +2051,6 @@ static inline int signal_pending_state(long state, struct task_struct *p)
        if (!signal_pending(p))
                return 0;
 
-       if (state & (__TASK_STOPPED | __TASK_TRACED))
-               return 0;
-
        return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p);
 }
 
@@ -2134,16 +2135,7 @@ static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
 
 #endif /* CONFIG_SMP */
 
-#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
 extern void arch_pick_mmap_layout(struct mm_struct *mm);
-#else
-static inline void arch_pick_mmap_layout(struct mm_struct *mm)
-{
-       mm->mmap_base = TASK_UNMAPPED_BASE;
-       mm->get_unmapped_area = arch_get_unmapped_area;
-       mm->unmap_area = arch_unmap_area;
-}
-#endif
 
 #ifdef CONFIG_TRACING
 extern void
@@ -2191,22 +2183,22 @@ extern long sched_group_rt_period(struct task_group *tg);
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
-       tsk->rchar += amt;
+       tsk->ioac.rchar += amt;
 }
 
 static inline void add_wchar(struct task_struct *tsk, ssize_t amt)
 {
-       tsk->wchar += amt;
+       tsk->ioac.wchar += amt;
 }
 
 static inline void inc_syscr(struct task_struct *tsk)
 {
-       tsk->syscr++;
+       tsk->ioac.syscr++;
 }
 
 static inline void inc_syscw(struct task_struct *tsk)
 {
-       tsk->syscw++;
+       tsk->ioac.syscw++;
 }
 #else
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
@@ -2226,14 +2218,6 @@ static inline void inc_syscw(struct task_struct *tsk)
 }
 #endif
 
-#ifdef CONFIG_SMP
-void migration_init(void);
-#else
-static inline void migration_init(void)
-{
-}
-#endif
-
 #ifndef TASK_SIZE_OF
 #define TASK_SIZE_OF(tsk)      TASK_SIZE
 #endif
index 31c8851ec5d0fba51ceab47da8d76f424f7e0345..fd96e7f8a6f9c9ecad138a0eaae84c5f6c82dc64 100644 (file)
@@ -102,9 +102,7 @@ extern unsigned long mmap_min_addr;
 #define LSM_SETID_FS   8
 
 /* forward declares to avoid warnings */
-struct nfsctl_arg;
 struct sched_param;
-struct swap_info_struct;
 struct request_sock;
 
 /* bprm_apply_creds unsafe reasons */
@@ -1364,7 +1362,7 @@ struct security_operations {
                             struct inode *new_dir, struct dentry *new_dentry);
        int (*inode_readlink) (struct dentry *dentry);
        int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
-       int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
+       int (*inode_permission) (struct inode *inode, int mask);
        int (*inode_setattr)    (struct dentry *dentry, struct iattr *attr);
        int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
        void (*inode_delete) (struct inode *inode);
@@ -1630,7 +1628,7 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
                          struct inode *new_dir, struct dentry *new_dentry);
 int security_inode_readlink(struct dentry *dentry);
 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
-int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
+int security_inode_permission(struct inode *inode, int mask);
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
 int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
 void security_inode_delete(struct inode *inode);
@@ -2023,8 +2021,7 @@ static inline int security_inode_follow_link(struct dentry *dentry,
        return 0;
 }
 
-static inline int security_inode_permission(struct inode *inode, int mask,
-                                            struct nameidata *nd)
+static inline int security_inode_permission(struct inode *inode, int mask)
 {
        return 0;
 }
index c8eaad9e4b72afacb1725204abbda308df0b3d45..1b191c176bcd33ecfe5f16d41ff53376635e52c0 100644 (file)
@@ -78,6 +78,7 @@ struct  seminfo {
 
 #ifdef __KERNEL__
 #include <asm/atomic.h>
+#include <linux/rcupdate.h>
 
 struct task_struct;
 
@@ -93,23 +94,19 @@ struct sem_array {
        time_t                  sem_otime;      /* last semop time */
        time_t                  sem_ctime;      /* last change time */
        struct sem              *sem_base;      /* ptr to first semaphore in array */
-       struct sem_queue        *sem_pending;   /* pending operations to be processed */
-       struct sem_queue        **sem_pending_last; /* last pending operation */
-       struct sem_undo         *undo;          /* undo requests on this array */
+       struct list_head        sem_pending;    /* pending operations to be processed */
+       struct list_head        list_id;        /* undo requests on this array */
        unsigned long           sem_nsems;      /* no. of semaphores in array */
 };
 
 /* One queue for each sleeping process in the system. */
 struct sem_queue {
-       struct sem_queue *      next;    /* next entry in the queue */
-       struct sem_queue **     prev;    /* previous entry in the queue, *(q->prev) == q */
-       struct task_struct*     sleeper; /* this process */
-       struct sem_undo *       undo;    /* undo structure */
+       struct list_head        list;    /* queue of pending operations */
+       struct task_struct      *sleeper; /* this process */
+       struct sem_undo         *undo;   /* undo structure */
        int                     pid;     /* process id of requesting process */
        int                     status;  /* completion status of operation */
-       struct sem_array *      sma;     /* semaphore array for operations */
-       int                     id;      /* internal sem id */
-       struct sembuf *         sops;    /* array of pending operations */
+       struct sembuf           *sops;   /* array of pending operations */
        int                     nsops;   /* number of operations */
        int                     alter;   /* does the operation alter the array? */
 };
@@ -118,8 +115,11 @@ struct sem_queue {
  * when the process exits.
  */
 struct sem_undo {
-       struct sem_undo *       proc_next;      /* next entry on this process */
-       struct sem_undo *       id_next;        /* next entry on this semaphore set */
+       struct list_head        list_proc;      /* per-process list: all undos from one process. */
+                                               /* rcu protected */
+       struct rcu_head         rcu;            /* rcu struct for sem_undo() */
+       struct sem_undo_list    *ulp;           /* sem_undo_list for the process */
+       struct list_head        list_id;        /* per semaphore array list: all undos for one array */
        int                     semid;          /* semaphore set identifier */
        short *                 semadj;         /* array of adjustments, one per semaphore */
 };
@@ -128,9 +128,9 @@ struct sem_undo {
  * that may be shared among all a CLONE_SYSVSEM task group.
  */ 
 struct sem_undo_list {
-       atomic_t        refcnt;
-       spinlock_t      lock;
-       struct sem_undo *proc_list;
+       atomic_t                refcnt;
+       spinlock_t              lock;
+       struct list_head        list_proc;
 };
 
 struct sysv_sem {
index 9cae64b00d6bb0e19e33ab9cc70c6df58089325a..7415839ac890f538b88611f7843b5b770e73292f 100644 (file)
@@ -26,10 +26,8 @@ struct semaphore {
        .wait_list      = LIST_HEAD_INIT((name).wait_list),             \
 }
 
-#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
-       struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
-
-#define DECLARE_MUTEX(name)    __DECLARE_SEMAPHORE_GENERIC(name, 1)
+#define DECLARE_MUTEX(name)    \
+       struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
 
 static inline void sema_init(struct semaphore *sem, int val)
 {
index f3a1c0e45021eaf37878fc3c9d0807ecfc88ea8e..3b2f6c04855e73d0ea300803c13970729e9b2989 100644 (file)
@@ -59,9 +59,6 @@
 #define PORT_SUNZILOG  38
 #define PORT_SUNSAB    39
 
-/* NEC v850.  */
-#define PORT_V850E_UART        40
-
 /* DEC */
 #define PORT_DZ                46
 #define PORT_ZS                47
index e72716cca57700fe51ab7adff654d799e3531529..25641d9e0ea85c9901d42045a551580e6ccdecfd 100644 (file)
@@ -87,11 +87,10 @@ void serio_unregister_port(struct serio *serio);
 void serio_unregister_child_port(struct serio *serio);
 
 int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name);
-static inline int serio_register_driver(struct serio_driver *drv)
+static inline int __must_check serio_register_driver(struct serio_driver *drv)
 {
        return __serio_register_driver(drv, THIS_MODULE, KBUILD_MODNAME);
 }
-int serio_register_driver(struct serio_driver *drv);
 void serio_unregister_driver(struct serio_driver *drv);
 
 static inline int serio_write(struct serio *serio, unsigned char data)
index f2d12d5a21b891cf53cbe19da6d10ded434aab59..fd83f2584b157b5e76b593344c55f3381f149014 100644 (file)
@@ -43,7 +43,7 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
 }
 
 #ifdef CONFIG_TMPFS_POSIX_ACL
-int shmem_permission(struct inode *, int, struct nameidata *);
+int shmem_permission(struct inode *, int);
 int shmem_acl_init(struct inode *, struct inode *);
 void shmem_acl_destroy_inode(struct inode *);
 
index ea037f28df91372d208a2e4301b24e21369596ca..bef0c46d4713cb82a041907fe62b21c71175d930 100644 (file)
@@ -8,6 +8,12 @@
 #ifndef _LINUX_SIGNALFD_H
 #define _LINUX_SIGNALFD_H
 
+/* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/fcntl.h>
+
+/* Flags for signalfd4.  */
+#define SFD_CLOEXEC O_CLOEXEC
+#define SFD_NONBLOCK O_NONBLOCK
 
 struct signalfd_siginfo {
        __u32 ssi_signo;
index 9aa90a6f20e02e920e883f17e7393aa0e0046400..5ff9676c1e2ca83e93511891230189772fafe2a0 100644 (file)
@@ -58,7 +58,7 @@ int slab_is_available(void);
 
 struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
                        unsigned long,
-                       void (*)(struct kmem_cache *, void *));
+                       void (*)(void *));
 void kmem_cache_destroy(struct kmem_cache *);
 int kmem_cache_shrink(struct kmem_cache *);
 void kmem_cache_free(struct kmem_cache *, void *);
@@ -96,6 +96,7 @@ int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
 /*
  * Common kmalloc functions provided by all allocators
  */
+void * __must_check __krealloc(const void *, size_t, gfp_t);
 void * __must_check krealloc(const void *, size_t, gfp_t);
 void kfree(const void *);
 size_t ksize(const void *);
@@ -180,7 +181,7 @@ size_t ksize(const void *);
  */
 static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
 {
-       if (n != 0 && size > ULONG_MAX / n)
+       if (size != 0 && n > ULONG_MAX / size)
                return NULL;
        return __kmalloc(n * size, flags | __GFP_ZERO);
 }
index d117ea2825a9187b44e37a12602b5538ec175839..5bad61a93f65566cc59716ebe4cae2e0d5f88f14 100644 (file)
@@ -85,7 +85,7 @@ struct kmem_cache {
        struct kmem_cache_order_objects min;
        gfp_t allocflags;       /* gfp flags to use on each alloc */
        int refcount;           /* Refcount for slab cache destroy */
-       void (*ctor)(struct kmem_cache *, void *);
+       void (*ctor)(void *);
        int inuse;              /* Offset to metadata */
        int align;              /* Alignment */
        const char *name;       /* Name (only for display!) */
index 95c1c39ba44598da0828d746f99435432f25fdb4..214f93209b8c0fb847971b41f0b5ea242b241e8a 100644 (file)
@@ -46,24 +46,6 @@ extern unsigned long sm501_modify_reg(struct device *dev,
                                      unsigned long set,
                                      unsigned long clear);
 
-/* sm501_gpio_set
- *
- * set the state of the given GPIO line
-*/
-
-extern void sm501_gpio_set(struct device *dev,
-                          unsigned long gpio,
-                          unsigned int to,
-                          unsigned int dir);
-
-/* sm501_gpio_get
- *
- * get the state of the given GPIO line
-*/
-
-extern unsigned long sm501_gpio_get(struct device *dev,
-                                   unsigned long gpio);
-
 
 /* Platform data definitions */
 
@@ -73,6 +55,8 @@ extern unsigned long sm501_gpio_get(struct device *dev,
 #define SM501FB_FLAG_USE_HWACCEL       (1<<3)
 #define SM501FB_FLAG_PANEL_NO_FPEN     (1<<4)
 #define SM501FB_FLAG_PANEL_NO_VBIASEN  (1<<5)
+#define SM501FB_FLAG_PANEL_INV_FPEN    (1<<6)
+#define SM501FB_FLAG_PANEL_INV_VBIASEN (1<<7)
 
 struct sm501_platdata_fbsub {
        struct fb_videomode     *def_mode;
@@ -102,11 +86,19 @@ struct sm501_platdata_fb {
        struct sm501_platdata_fbsub     *fb_pnl;
 };
 
-/* gpio i2c */
+/* gpio i2c
+ *
+ * Note, we have to pass in the bus number, as the number used will be
+ * passed to the i2c-gpio driver's platform_device.id, subsequently used
+ * to register the i2c bus.
+*/
 
 struct sm501_platdata_gpio_i2c {
+       unsigned int            bus_num;
        unsigned int            pin_sda;
        unsigned int            pin_scl;
+       int                     udelay;
+       int                     timeout;
 };
 
 /* sm501_initdata
@@ -129,6 +121,7 @@ struct sm501_reg_init {
 #define SM501_USE_FBACCEL      (1<<6)
 #define SM501_USE_AC97         (1<<7)
 #define SM501_USE_I2S          (1<<8)
+#define SM501_USE_GPIO         (1<<9)
 
 #define SM501_USE_ALL          (0xffffffff)
 
@@ -155,6 +148,8 @@ struct sm501_init_gpio {
        struct sm501_reg_init   gpio_ddr_high;
 };
 
+#define SM501_FLAG_SUSPEND_OFF         (1<<4)
+
 /* sm501_platdata
  *
  * This is passed with the platform device to allow the board
@@ -168,6 +163,12 @@ struct sm501_platdata {
        struct sm501_init_gpio          *init_gpiop;
        struct sm501_platdata_fb        *fb;
 
+       int                              flags;
+       int                              gpio_base;
+
+       int     (*get_power)(struct device *dev);
+       int     (*set_power)(struct device *dev, unsigned int on);
+
        struct sm501_platdata_gpio_i2c  *gpio_i2c;
        unsigned int                     gpio_i2c_nr;
 };
index 2c5cd55f44fff4ab96bda8b48cd439d4bcf47099..923cd8a247b103bfeae72cc2680b55db0636d8ad 100644 (file)
@@ -43,18 +43,13 @@ static inline struct smb_inode_info *SMB_I(struct inode *inode)
 }
 
 /* macro names are short for word, double-word, long value (?) */
-#define WVAL(buf,pos) \
-       (le16_to_cpu(get_unaligned((__le16 *)((u8 *)(buf) + (pos)))))
-#define DVAL(buf,pos) \
-       (le32_to_cpu(get_unaligned((__le32 *)((u8 *)(buf) + (pos)))))
-#define LVAL(buf,pos) \
-       (le64_to_cpu(get_unaligned((__le64 *)((u8 *)(buf) + (pos)))))
-#define WSET(buf,pos,val) \
-       put_unaligned(cpu_to_le16((u16)(val)), (__le16 *)((u8 *)(buf) + (pos)))
-#define DSET(buf,pos,val) \
-       put_unaligned(cpu_to_le32((u32)(val)), (__le32 *)((u8 *)(buf) + (pos)))
-#define LSET(buf,pos,val) \
-       put_unaligned(cpu_to_le64((u64)(val)), (__le64 *)((u8 *)(buf) + (pos)))
+#define WVAL(buf, pos) (get_unaligned_le16((u8 *)(buf) + (pos)))
+#define DVAL(buf, pos) (get_unaligned_le32((u8 *)(buf) + (pos)))
+#define LVAL(buf, pos) (get_unaligned_le64((u8 *)(buf) + (pos)))
+
+#define WSET(buf, pos, val) put_unaligned_le16((val), (u8 *)(buf) + (pos))
+#define DSET(buf, pos, val) put_unaligned_le32((val), (u8 *)(buf) + (pos))
+#define LSET(buf, pos, val) put_unaligned_le64((val), (u8 *)(buf) + (pos))
 
 /* where to find the base of the SMB packet proper */
 #define smb_base(buf) ((u8 *)(((u8 *)(buf))+4))
index 48262f86c969dccd11486ef772907845d6cb45cb..66484d4a845944d8e7250f0cd6932febe2c8933b 100644 (file)
@@ -74,15 +74,10 @@ void __smp_call_function_single(int cpuid, struct call_single_data *data);
 #ifdef CONFIG_USE_GENERIC_SMP_HELPERS
 void generic_smp_call_function_single_interrupt(void);
 void generic_smp_call_function_interrupt(void);
-void init_call_single_data(void);
 void ipi_call_lock(void);
 void ipi_call_unlock(void);
 void ipi_call_lock_irq(void);
 void ipi_call_unlock_irq(void);
-#else
-static inline void init_call_single_data(void)
-{
-}
 #endif
 
 /*
index 950af631e7fb17981e94d65b21345a3d737c2cfb..dc5086fe7736c10f40bfbab0996b7d589ccf5bbe 100644 (file)
@@ -189,7 +189,8 @@ struct ucred {
 #define AF_BLUETOOTH   31      /* Bluetooth sockets            */
 #define AF_IUCV                32      /* IUCV sockets                 */
 #define AF_RXRPC       33      /* RxRPC sockets                */
-#define AF_MAX         34      /* For now.. */
+#define AF_ISDN                34      /* mISDN sockets                */
+#define AF_MAX         35      /* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC      AF_UNSPEC
@@ -225,6 +226,7 @@ struct ucred {
 #define PF_BLUETOOTH   AF_BLUETOOTH
 #define PF_IUCV                AF_IUCV
 #define PF_RXRPC       AF_RXRPC
+#define PF_ISDN                AF_ISDN
 #define PF_MAX         AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
diff --git a/include/linux/spi/ds1305.h b/include/linux/spi/ds1305.h
new file mode 100644 (file)
index 0000000..287ec83
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __LINUX_SPI_DS1305_H
+#define __LINUX_SPI_DS1305_H
+
+/*
+ * One-time configuration for ds1305 and ds1306 RTC chips.
+ *
+ * Put a pointer to this in spi_board_info.platform_data if you want to
+ * be sure that Linux (re)initializes this as needed ... after losing
+ * backup power, and potentially on the first boot.
+ */
+struct ds1305_platform_data {
+
+       /* Trickle charge configuration:  it's OK to leave out the MAGIC
+        * bitmask; mask in either DS1 or DS2, and then one of 2K/4k/8K.
+        */
+#define DS1305_TRICKLE_MAGIC   0xa0
+#define DS1305_TRICKLE_DS2     0x08    /* two diodes */
+#define DS1305_TRICKLE_DS1     0x04    /* one diode */
+#define DS1305_TRICKLE_2K      0x01    /* 2 KOhm resistance */
+#define DS1305_TRICKLE_4K      0x02    /* 4 KOhm resistance */
+#define DS1305_TRICKLE_8K      0x03    /* 8 KOhm resistance */
+       u8      trickle;
+
+       /* set only on ds1306 parts */
+       bool    is_ds1306;
+
+       /* ds1306 only:  enable 1 Hz output */
+       bool    en_1hz;
+
+       /* REVISIT:  the driver currently expects nINT0 to be wired
+        * as the alarm IRQ.  ALM1 may also need to be set up ...
+        */
+};
+
+#endif /* __LINUX_SPI_DS1305_H */
index 835ddf47d45caa571e14e410ba4ed003d9ca172a..22ef107d7704432b52287fd9fd4df95945c23aef 100644 (file)
@@ -1,18 +1,25 @@
 
-/* FIXME driver should be able to handle all four slaves that
- * can be hooked up to each chipselect, as well as IRQs...
- */
+/* FIXME driver should be able to handle IRQs...  */
+
+struct mcp23s08_chip_info {
+       bool    is_present;             /* true iff populated */
+       u8      pullups;                /* BIT(x) means enable pullup x */
+};
 
 struct mcp23s08_platform_data {
-       /* four slaves can share one SPI chipselect */
-       u8              slave;
+       /* Four slaves (numbered 0..3) can share one SPI chipselect, and
+        * will provide 8..32 GPIOs using 1..4 gpio_chip instances.
+        */
+       struct mcp23s08_chip_info       chip[4];
 
-       /* number assigned to the first GPIO */
+       /* "base" is the number of the first GPIO.  Dynamic assignment is
+        * not currently supported, and even if there are gaps in chip
+        * addressing the GPIO numbers are sequential .. so for example
+        * if only slaves 0 and 3 are present, their GPIOs range from
+        * base to base+15.
+        */
        unsigned        base;
 
-       /* pins with pullups */
-       u8              pullups;
-
        void            *context;       /* param to setup/teardown */
 
        int             (*setup)(struct spi_device *spi,
index b9a76c9720844105eccc6fe89dc139dd54c8095e..4be01bb4437748c27f80aa79733c3a1360ca13e0 100644 (file)
@@ -82,7 +82,7 @@ struct spi_device {
        int                     irq;
        void                    *controller_state;
        void                    *controller_data;
-       const char              *modalias;
+       char                    modalias[32];
 
        /*
         * likely need more hooks for more protocol options affecting how
@@ -778,7 +778,19 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
  * use spi_new_device() to describe each device.  You can also call
  * spi_unregister_device() to start making that device vanish, but
  * normally that would be handled by spi_unregister_master().
+ *
+ * You can also use spi_alloc_device() and spi_add_device() to use a two
+ * stage registration sequence for each spi_device.  This gives the caller
+ * some more control over the spi_device structure before it is registered,
+ * but requires that caller to initialize fields that would otherwise
+ * be defined using the board info.
  */
+extern struct spi_device *
+spi_alloc_device(struct spi_master *master);
+
+extern int
+spi_add_device(struct spi_device *spi);
+
 extern struct spi_device *
 spi_new_device(struct spi_master *, struct spi_board_info *);
 
index d311a090fae7f38d999904d22e909700d86e3849..61e5610ad165592c0605eb68330ff50d9e0b77f8 100644 (file)
@@ -46,6 +46,7 @@
  *  linux/spinlock.h:     builds the final spin_*() APIs.
  */
 
+#include <linux/typecheck.h>
 #include <linux/preempt.h>
 #include <linux/linkage.h>
 #include <linux/compiler.h>
@@ -191,23 +192,53 @@ do {                                                              \
 
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
 
-#define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock)
-#define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock)
-#define write_lock_irqsave(lock, flags)        flags = _write_lock_irqsave(lock)
+#define spin_lock_irqsave(lock, flags)                 \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               flags = _spin_lock_irqsave(lock);       \
+       } while (0)
+#define read_lock_irqsave(lock, flags)                 \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               flags = _read_lock_irqsave(lock);       \
+       } while (0)
+#define write_lock_irqsave(lock, flags)                        \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               flags = _write_lock_irqsave(lock);      \
+       } while (0)
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
-#define spin_lock_irqsave_nested(lock, flags, subclass) \
-       flags = _spin_lock_irqsave_nested(lock, subclass)
+#define spin_lock_irqsave_nested(lock, flags, subclass)                        \
+       do {                                                            \
+               typecheck(unsigned long, flags);                        \
+               flags = _spin_lock_irqsave_nested(lock, subclass);      \
+       } while (0)
 #else
-#define spin_lock_irqsave_nested(lock, flags, subclass) \
-       flags = _spin_lock_irqsave(lock)
+#define spin_lock_irqsave_nested(lock, flags, subclass)                        \
+       do {                                                            \
+               typecheck(unsigned long, flags);                        \
+               flags = _spin_lock_irqsave(lock);                       \
+       } while (0)
 #endif
 
 #else
 
-#define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags)
-#define read_lock_irqsave(lock, flags) _read_lock_irqsave(lock, flags)
-#define write_lock_irqsave(lock, flags)        _write_lock_irqsave(lock, flags)
+#define spin_lock_irqsave(lock, flags)                 \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               _spin_lock_irqsave(lock, flags);        \
+       } while (0)
+#define read_lock_irqsave(lock, flags)                 \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               _read_lock_irqsave(lock, flags);        \
+       } while (0)
+#define write_lock_irqsave(lock, flags)                        \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               _write_lock_irqsave(lock, flags);       \
+       } while (0)
 #define spin_lock_irqsave_nested(lock, flags, subclass)        \
        spin_lock_irqsave(lock, flags)
 
@@ -260,16 +291,25 @@ do {                                              \
 } while (0)
 #endif
 
-#define spin_unlock_irqrestore(lock, flags) \
-                                       _spin_unlock_irqrestore(lock, flags)
+#define spin_unlock_irqrestore(lock, flags)            \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               _spin_unlock_irqrestore(lock, flags);   \
+       } while (0)
 #define spin_unlock_bh(lock)           _spin_unlock_bh(lock)
 
-#define read_unlock_irqrestore(lock, flags) \
-                                       _read_unlock_irqrestore(lock, flags)
+#define read_unlock_irqrestore(lock, flags)            \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               _read_unlock_irqrestore(lock, flags);   \
+       } while (0)
 #define read_unlock_bh(lock)           _read_unlock_bh(lock)
 
-#define write_unlock_irqrestore(lock, flags) \
-                                       _write_unlock_irqrestore(lock, flags)
+#define write_unlock_irqrestore(lock, flags)           \
+       do {                                            \
+               typecheck(unsigned long, flags);        \
+               _write_unlock_irqrestore(lock, flags);  \
+       } while (0)
 #define write_unlock_bh(lock)          _write_unlock_bh(lock)
 
 #define spin_trylock_bh(lock)  __cond_lock(lock, _spin_trylock_bh(lock))
index 4bf8cade9dbc5fa534963e40fe99de303f54296a..e530026eedf76b6f40402b3ecd03d1b05c234fd1 100644 (file)
@@ -427,9 +427,9 @@ static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr)
 {
        switch (dev->bus->bustype) {
        case SSB_BUSTYPE_PCI:
-               return pci_dma_mapping_error(addr);
+               return pci_dma_mapping_error(dev->bus->host_pci, addr);
        case SSB_BUSTYPE_SSB:
-               return dma_mapping_error(addr);
+               return dma_mapping_error(dev->dev, addr);
        default:
                __ssb_dma_not_implemented(dev);
        }
index 5bfc553bdb21f0d5d4353f12c6a13fd802613000..f1cb0ba6d71586a5cd2f5b41172ee5b32b55631d 100644 (file)
@@ -5,41 +5,43 @@
    (and more).  So the "read" side to such a lock is anything which
    diables preeempt. */
 #include <linux/cpu.h>
+#include <linux/cpumask.h>
 #include <asm/system.h>
 
 #if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
+
+/* Deprecated, but useful for transition. */
+#define ALL_CPUS ~0U
+
 /**
- * stop_machine_run: freeze the machine on all CPUs and run this function
+ * stop_machine: freeze the machine on all CPUs and run this function
  * @fn: the function to run
  * @data: the data ptr for the @fn()
- * @cpu: the cpu to run @fn() on (or any, if @cpu == NR_CPUS.
+ * @cpus: the cpus to run the @fn() on (NULL = any online cpu)
  *
- * Description: This causes a thread to be scheduled on every other cpu,
- * each of which disables interrupts, and finally interrupts are disabled
- * on the current CPU.  The result is that noone is holding a spinlock
- * or inside any other preempt-disabled region when @fn() runs.
+ * Description: This causes a thread to be scheduled on every cpu,
+ * each of which disables interrupts.  The result is that noone is
+ * holding a spinlock or inside any other preempt-disabled region when
+ * @fn() runs.
  *
  * This can be thought of as a very heavy write lock, equivalent to
  * grabbing every spinlock in the kernel. */
-int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu);
+int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus);
 
 /**
- * __stop_machine_run: freeze the machine on all CPUs and run this function
+ * __stop_machine: freeze the machine on all CPUs and run this function
  * @fn: the function to run
  * @data: the data ptr for the @fn
- * @cpu: the cpu to run @fn on (or any, if @cpu == NR_CPUS.
+ * @cpus: the cpus to run the @fn() on (NULL = any online cpu)
  *
- * Description: This is a special version of the above, which returns the
- * thread which has run @fn(): kthread_stop will return the return value
- * of @fn().  Used by hotplug cpu.
+ * Description: This is a special version of the above, which assumes cpus
+ * won't come or go while it's being called.  Used by hotplug cpu.
  */
-struct task_struct *__stop_machine_run(int (*fn)(void *), void *data,
-                                      unsigned int cpu);
-
+int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus);
 #else
 
-static inline int stop_machine_run(int (*fn)(void *), void *data,
-                                  unsigned int cpu)
+static inline int stop_machine(int (*fn)(void *), void *data,
+                              const cpumask_t *cpus)
 {
        int ret;
        local_irq_disable();
@@ -48,4 +50,18 @@ static inline int stop_machine_run(int (*fn)(void *), void *data,
        return ret;
 }
 #endif /* CONFIG_SMP */
+
+static inline int __deprecated stop_machine_run(int (*fn)(void *), void *data,
+                                               unsigned int cpu)
+{
+       /* If they don't care which cpu fn runs on, just pick one. */
+       if (cpu == NR_CPUS)
+               return stop_machine(fn, data, NULL);
+       else if (cpu == ~0U)
+               return stop_machine(fn, data, &cpu_possible_map);
+       else {
+               cpumask_t cpus = cpumask_of_cpu(cpu);
+               return stop_machine(fn, data, &cpus);
+       }
+}
 #endif /* _LINUX_STOP_MACHINE */
index efdc44593b522054dda0454f105fb0636b8ec0c2..810d80df0a1d1700956e40ededaeefe29883ab46 100644 (file)
@@ -111,5 +111,8 @@ extern void argv_free(char **argv);
 
 extern bool sysfs_streq(const char *s1, const char *s2);
 
+extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
+                       const void *from, size_t available);
+
 #endif
 #endif /* _LINUX_STRING_H_ */
index e8e69159af71c2ed546fb97f25316bcd5de1ea0f..c63435095970660b585a232bc50bcdedc94e80c4 100644 (file)
@@ -278,4 +278,6 @@ static inline void register_nosave_region_late(unsigned long b, unsigned long e)
 }
 #endif
 
+extern struct mutex pm_mutex;
+
 #endif /* _LINUX_SUSPEND_H */
index 0b3377650c859784686109395e8604affed2f701..de40f169a4e4134fa79c2ab0c360d057d2a1f62d 100644 (file)
@@ -237,7 +237,6 @@ extern struct page *swapin_readahead(swp_entry_t, gfp_t,
 
 /* linux/mm/swapfile.c */
 extern long total_swap_pages;
-extern unsigned int nr_swapfiles;
 extern void si_swapinfo(struct sysinfo *);
 extern swp_entry_t get_swap_page(void);
 extern swp_entry_t get_swap_page_of_type(int);
@@ -254,8 +253,6 @@ extern int can_share_swap_page(struct page *);
 extern int remove_exclusive_swap_page(struct page *);
 struct backing_dev_info;
 
-extern spinlock_t swap_lock;
-
 /* linux/mm/thrash.c */
 extern struct mm_struct * swap_token_mm;
 extern void grab_swap_token(void);
index 0522f368f9d737d7f65376c8cc122cc2ea92c900..d6ff145919ca3d3db7a01cf53c93ff628b0d29a6 100644 (file)
@@ -305,6 +305,7 @@ asmlinkage long sys_fcntl64(unsigned int fd,
 #endif
 asmlinkage long sys_dup(unsigned int fildes);
 asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd);
+asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags);
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd,
                                unsigned long arg);
@@ -409,6 +410,8 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname,
 asmlinkage long sys_bind(int, struct sockaddr __user *, int);
 asmlinkage long sys_connect(int, struct sockaddr __user *, int);
 asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *);
+asmlinkage long sys_paccept(int, struct sockaddr __user *, int __user *,
+                           const __user sigset_t *, size_t, int);
 asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *);
 asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *);
 asmlinkage long sys_send(int, void __user *, size_t, unsigned);
@@ -428,6 +431,7 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
 asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
                        fd_set __user *exp, struct timeval __user *tvp);
 asmlinkage long sys_epoll_create(int size);
+asmlinkage long sys_epoll_create1(int flags);
 asmlinkage long sys_epoll_ctl(int epfd, int op, int fd,
                                struct epoll_event __user *event);
 asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
@@ -443,7 +447,7 @@ asmlinkage long sys_newuname(struct new_utsname __user *name);
 
 asmlinkage long sys_getrlimit(unsigned int resource,
                                struct rlimit __user *rlim);
-#if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64) || defined(CONFIG_V850))
+#if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64))
 asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim);
 #endif
 asmlinkage long sys_setrlimit(unsigned int resource,
@@ -543,6 +547,7 @@ asmlinkage long sys_get_mempolicy(int __user *policy,
                                unsigned long addr, unsigned long flags);
 
 asmlinkage long sys_inotify_init(void);
+asmlinkage long sys_inotify_init1(int flags);
 asmlinkage long sys_inotify_add_watch(int fd, const char __user *path,
                                        u32 mask);
 asmlinkage long sys_inotify_rm_watch(int fd, u32 wd);
@@ -608,12 +613,14 @@ asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
                                    size_t len);
 asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);
 asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask);
+asmlinkage long sys_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, int flags);
 asmlinkage long sys_timerfd_create(int clockid, int flags);
 asmlinkage long sys_timerfd_settime(int ufd, int flags,
                                    const struct itimerspec __user *utmr,
                                    struct itimerspec __user *otmr);
 asmlinkage long sys_timerfd_gettime(int ufd, struct itimerspec __user *otmr);
 asmlinkage long sys_eventfd(unsigned int count);
+asmlinkage long sys_eventfd2(unsigned int count, int flags);
 asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len);
 
 int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
index 24141b4d1a116a4523ab9085e8f830cdd26cb471..d0437f36921f803e1bd8be49d1066a7ad1796928 100644 (file)
@@ -947,6 +947,22 @@ struct ctl_table;
 struct nsproxy;
 struct ctl_table_root;
 
+struct ctl_table_set {
+       struct list_head list;
+       struct ctl_table_set *parent;
+       int (*is_seen)(struct ctl_table_set *);
+};
+
+extern void setup_sysctl_set(struct ctl_table_set *p,
+       struct ctl_table_set *parent,
+       int (*is_seen)(struct ctl_table_set *));
+
+struct ctl_table_header;
+
+extern void sysctl_head_get(struct ctl_table_header *);
+extern void sysctl_head_put(struct ctl_table_header *);
+extern int sysctl_is_seen(struct ctl_table_header *);
+extern struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *);
 extern struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev);
 extern struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
                                                struct ctl_table_header *prev);
@@ -1049,8 +1065,8 @@ struct ctl_table
 
 struct ctl_table_root {
        struct list_head root_list;
-       struct list_head header_list;
-       struct list_head *(*lookup)(struct ctl_table_root *root,
+       struct ctl_table_set default_set;
+       struct ctl_table_set *(*lookup)(struct ctl_table_root *root,
                                           struct nsproxy *namespaces);
        int (*permissions)(struct ctl_table_root *root,
                        struct nsproxy *namespaces, struct ctl_table *table);
@@ -1063,9 +1079,14 @@ struct ctl_table_header
        struct ctl_table *ctl_table;
        struct list_head ctl_entry;
        int used;
+       int count;
        struct completion *unregistering;
        struct ctl_table *ctl_table_arg;
        struct ctl_table_root *root;
+       struct ctl_table_set *set;
+       struct ctl_table *attached_by;
+       struct ctl_table *attached_to;
+       struct ctl_table_header *parent;
 };
 
 /* struct ctl_path describes where in the hierarchy a table is added */
index 44d00e9cceea551256df7428be8856e719d04ef1..5e88afc9a2fbd5b5e82bc9486087d9f9017cadcd 100644 (file)
@@ -8,8 +8,19 @@
  * Blame akpm@osdl.org for all this.
  */
 
-#ifdef CONFIG_TASK_IO_ACCOUNTING
 struct task_io_accounting {
+#ifdef CONFIG_TASK_XACCT
+       /* bytes read */
+       u64 rchar;
+       /*  bytes written */
+       u64 wchar;
+       /* # of read syscalls */
+       u64 syscr;
+       /* # of write syscalls */
+       u64 syscw;
+#endif /* CONFIG_TASK_XACCT */
+
+#ifdef CONFIG_TASK_IO_ACCOUNTING
        /*
         * The number of bytes which this task has caused to be read from
         * storage.
@@ -30,8 +41,5 @@ struct task_io_accounting {
         * information loss in doing that.
         */
        u64 cancelled_write_bytes;
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
 };
-#else
-struct task_io_accounting {
-};
-#endif
index ff46c6fad79da300afaa621a41abcfb1bf4c787f..4d090f9ee60878683b1b3542eda603a975114f4d 100644 (file)
@@ -40,9 +40,17 @@ static inline void task_io_account_cancelled_write(size_t bytes)
        current->ioac.cancelled_write_bytes += bytes;
 }
 
-static inline void task_io_accounting_init(struct task_struct *tsk)
+static inline void task_io_accounting_init(struct task_io_accounting *ioac)
 {
-       memset(&tsk->ioac, 0, sizeof(tsk->ioac));
+       memset(ioac, 0, sizeof(*ioac));
+}
+
+static inline void task_blk_io_accounting_add(struct task_io_accounting *dst,
+                                               struct task_io_accounting *src)
+{
+       dst->read_bytes += src->read_bytes;
+       dst->write_bytes += src->write_bytes;
+       dst->cancelled_write_bytes += src->cancelled_write_bytes;
 }
 
 #else
@@ -69,9 +77,37 @@ static inline void task_io_account_cancelled_write(size_t bytes)
 {
 }
 
-static inline void task_io_accounting_init(struct task_struct *tsk)
+static inline void task_io_accounting_init(struct task_io_accounting *ioac)
+{
+}
+
+static inline void task_blk_io_accounting_add(struct task_io_accounting *dst,
+                                               struct task_io_accounting *src)
 {
 }
 
-#endif         /* CONFIG_TASK_IO_ACCOUNTING */
-#endif         /* __TASK_IO_ACCOUNTING_OPS_INCLUDED */
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
+
+#ifdef CONFIG_TASK_XACCT
+static inline void task_chr_io_accounting_add(struct task_io_accounting *dst,
+                                               struct task_io_accounting *src)
+{
+       dst->rchar += src->rchar;
+       dst->wchar += src->wchar;
+       dst->syscr += src->syscr;
+       dst->syscw += src->syscw;
+}
+#else
+static inline void task_chr_io_accounting_add(struct task_io_accounting *dst,
+                                               struct task_io_accounting *src)
+{
+}
+#endif /* CONFIG_TASK_XACCT */
+
+static inline void task_io_accounting_add(struct task_io_accounting *dst,
+                                               struct task_io_accounting *src)
+{
+       task_chr_io_accounting_add(dst, src);
+       task_blk_io_accounting_add(dst, src);
+}
+#endif /* __TASK_IO_ACCOUNTING_OPS_INCLUDED */
index 5d69c0744fff60283c74fbd4ca7a8c28ee4715cf..18269e956a7189d600387a12f70e7bf9c2996d55 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 
-#define TASKSTATS_VERSION      6
+#define TASKSTATS_VERSION      7
 #define TS_COMM_LEN            32      /* should be >= TASK_COMM_LEN
                                         * in linux/sched.h */
 
@@ -157,6 +157,10 @@ struct taskstats {
        __u64   ac_utimescaled;         /* utime scaled on frequency etc */
        __u64   ac_stimescaled;         /* stime scaled on frequency etc */
        __u64   cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
+
+       /* Delay waiting for memory reclaim */
+       __u64   freepages_count;
+       __u64   freepages_delay_total;
 };
 
 
index a881c652f7e925cb8e3d2f296c492800c3f163eb..d3c02695dc5d7e0826a7fa6ac4eb27bfbd937374 100644 (file)
@@ -49,6 +49,7 @@ struct tick_sched {
        unsigned long                   check_clocks;
        enum tick_nohz_mode             nohz_mode;
        ktime_t                         idle_tick;
+       int                             inidle;
        int                             tick_stopped;
        unsigned long                   idle_jiffies;
        unsigned long                   idle_calls;
@@ -105,14 +106,14 @@ static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 # ifdef CONFIG_NO_HZ
-extern void tick_nohz_stop_sched_tick(void);
+extern void tick_nohz_stop_sched_tick(int inidle);
 extern void tick_nohz_restart_sched_tick(void);
 extern void tick_nohz_update_jiffies(void);
 extern ktime_t tick_nohz_get_sleep_length(void);
 extern void tick_nohz_stop_idle(int cpu);
 extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
 # else
-static inline void tick_nohz_stop_sched_tick(void) { }
+static inline void tick_nohz_stop_sched_tick(int inidle) { }
 static inline void tick_nohz_restart_sched_tick(void) { }
 static inline void tick_nohz_update_jiffies(void) { }
 static inline ktime_t tick_nohz_get_sleep_length(void)
index cf2b10d757312b66d2ae35fd24d99246a3739fe4..86cb0501d3e20428b749eb2156bf5abc301e1c20 100644 (file)
@@ -8,9 +8,15 @@
 #ifndef _LINUX_TIMERFD_H
 #define _LINUX_TIMERFD_H
 
+/* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/fcntl.h>
 
+/* Flags for timerfd_settime.  */
 #define TFD_TIMER_ABSTIME (1 << 0)
 
+/* Flags for timerfd_create.  */
+#define TFD_CLOEXEC O_CLOEXEC
+#define TFD_NONBLOCK O_NONBLOCK
 
 
 #endif /* _LINUX_TIMERFD_H */
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
new file mode 100644 (file)
index 0000000..b187558
--- /dev/null
@@ -0,0 +1,576 @@
+/*
+ * Tracing hooks
+ *
+ * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * This file defines hook entry points called by core code where
+ * user tracing/debugging support might need to do something.  These
+ * entry points are called tracehook_*().  Each hook declared below
+ * has a detailed kerneldoc comment giving the context (locking et
+ * al) from which it is called, and the meaning of its return value.
+ *
+ * Each function here typically has only one call site, so it is ok
+ * to have some nontrivial tracehook_*() inlines.  In all cases, the
+ * fast path when no tracing is enabled should be very short.
+ *
+ * The purpose of this file and the tracehook_* layer is to consolidate
+ * the interface that the kernel core and arch code uses to enable any
+ * user debugging or tracing facility (such as ptrace).  The interfaces
+ * here are carefully documented so that maintainers of core and arch
+ * code do not need to think about the implementation details of the
+ * tracing facilities.  Likewise, maintainers of the tracing code do not
+ * need to understand all the calling core or arch code in detail, just
+ * documented circumstances of each call, such as locking conditions.
+ *
+ * If the calling core code changes so that locking is different, then
+ * it is ok to change the interface documented here.  The maintainer of
+ * core code changing should notify the maintainers of the tracing code
+ * that they need to work out the change.
+ *
+ * Some tracehook_*() inlines take arguments that the current tracing
+ * implementations might not necessarily use.  These function signatures
+ * are chosen to pass in all the information that is on hand in the
+ * caller and might conceivably be relevant to a tracer, so that the
+ * core code won't have to be updated when tracing adds more features.
+ * If a call site changes so that some of those parameters are no longer
+ * already on hand without extra work, then the tracehook_* interface
+ * can change so there is no make-work burden on the core code.  The
+ * maintainer of core code changing should notify the maintainers of the
+ * tracing code that they need to work out the change.
+ */
+
+#ifndef _LINUX_TRACEHOOK_H
+#define _LINUX_TRACEHOOK_H     1
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/security.h>
+struct linux_binprm;
+
+/**
+ * tracehook_expect_breakpoints - guess if task memory might be touched
+ * @task:              current task, making a new mapping
+ *
+ * Return nonzero if @task is expected to want breakpoint insertion in
+ * its memory at some point.  A zero return is no guarantee it won't
+ * be done, but this is a hint that it's known to be likely.
+ *
+ * May be called with @task->mm->mmap_sem held for writing.
+ */
+static inline int tracehook_expect_breakpoints(struct task_struct *task)
+{
+       return (task_ptrace(task) & PT_PTRACED) != 0;
+}
+
+/*
+ * ptrace report for syscall entry and exit looks identical.
+ */
+static inline void ptrace_report_syscall(struct pt_regs *regs)
+{
+       int ptrace = task_ptrace(current);
+
+       if (!(ptrace & PT_PTRACED))
+               return;
+
+       ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
+
+       /*
+        * this isn't the same as continuing with a signal, but it will do
+        * for normal use.  strace only continues with a signal if the
+        * stopping signal is not SIGTRAP.  -brl
+        */
+       if (current->exit_code) {
+               send_sig(current->exit_code, current, 1);
+               current->exit_code = 0;
+       }
+}
+
+/**
+ * tracehook_report_syscall_entry - task is about to attempt a system call
+ * @regs:              user register state of current task
+ *
+ * This will be called if %TIF_SYSCALL_TRACE has been set, when the
+ * current task has just entered the kernel for a system call.
+ * Full user register state is available here.  Changing the values
+ * in @regs can affect the system call number and arguments to be tried.
+ * It is safe to block here, preventing the system call from beginning.
+ *
+ * Returns zero normally, or nonzero if the calling arch code should abort
+ * the system call.  That must prevent normal entry so no system call is
+ * made.  If @task ever returns to user mode after this, its register state
+ * is unspecified, but should be something harmless like an %ENOSYS error
+ * return.  It should preserve enough information so that syscall_rollback()
+ * can work (see asm-generic/syscall.h).
+ *
+ * Called without locks, just after entering kernel mode.
+ */
+static inline __must_check int tracehook_report_syscall_entry(
+       struct pt_regs *regs)
+{
+       ptrace_report_syscall(regs);
+       return 0;
+}
+
+/**
+ * tracehook_report_syscall_exit - task has just finished a system call
+ * @regs:              user register state of current task
+ * @step:              nonzero if simulating single-step or block-step
+ *
+ * This will be called if %TIF_SYSCALL_TRACE has been set, when the
+ * current task has just finished an attempted system call.  Full
+ * user register state is available here.  It is safe to block here,
+ * preventing signals from being processed.
+ *
+ * If @step is nonzero, this report is also in lieu of the normal
+ * trap that would follow the system call instruction because
+ * user_enable_block_step() or user_enable_single_step() was used.
+ * In this case, %TIF_SYSCALL_TRACE might not be set.
+ *
+ * Called without locks, just before checking for pending signals.
+ */
+static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
+{
+       ptrace_report_syscall(regs);
+}
+
+/**
+ * tracehook_unsafe_exec - check for exec declared unsafe due to tracing
+ * @task:              current task doing exec
+ *
+ * Return %LSM_UNSAFE_* bits applied to an exec because of tracing.
+ *
+ * Called with task_lock() held on @task.
+ */
+static inline int tracehook_unsafe_exec(struct task_struct *task)
+{
+       int unsafe = 0;
+       int ptrace = task_ptrace(task);
+       if (ptrace & PT_PTRACED) {
+               if (ptrace & PT_PTRACE_CAP)
+                       unsafe |= LSM_UNSAFE_PTRACE_CAP;
+               else
+                       unsafe |= LSM_UNSAFE_PTRACE;
+       }
+       return unsafe;
+}
+
+/**
+ * tracehook_tracer_task - return the task that is tracing the given task
+ * @tsk:               task to consider
+ *
+ * Returns NULL if noone is tracing @task, or the &struct task_struct
+ * pointer to its tracer.
+ *
+ * Must called under rcu_read_lock().  The pointer returned might be kept
+ * live only by RCU.  During exec, this may be called with task_lock()
+ * held on @task, still held from when tracehook_unsafe_exec() was called.
+ */
+static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
+{
+       if (task_ptrace(tsk) & PT_PTRACED)
+               return rcu_dereference(tsk->parent);
+       return NULL;
+}
+
+/**
+ * tracehook_report_exec - a successful exec was completed
+ * @fmt:               &struct linux_binfmt that performed the exec
+ * @bprm:              &struct linux_binprm containing exec details
+ * @regs:              user-mode register state
+ *
+ * An exec just completed, we are shortly going to return to user mode.
+ * The freshly initialized register state can be seen and changed in @regs.
+ * The name, file and other pointers in @bprm are still on hand to be
+ * inspected, but will be freed as soon as this returns.
+ *
+ * Called with no locks, but with some kernel resources held live
+ * and a reference on @fmt->module.
+ */
+static inline void tracehook_report_exec(struct linux_binfmt *fmt,
+                                        struct linux_binprm *bprm,
+                                        struct pt_regs *regs)
+{
+       if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) &&
+           unlikely(task_ptrace(current) & PT_PTRACED))
+               send_sig(SIGTRAP, current, 0);
+}
+
+/**
+ * tracehook_report_exit - task has begun to exit
+ * @exit_code:         pointer to value destined for @current->exit_code
+ *
+ * @exit_code points to the value passed to do_exit(), which tracing
+ * might change here.  This is almost the first thing in do_exit(),
+ * before freeing any resources or setting the %PF_EXITING flag.
+ *
+ * Called with no locks held.
+ */
+static inline void tracehook_report_exit(long *exit_code)
+{
+       ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code);
+}
+
+/**
+ * tracehook_prepare_clone - prepare for new child to be cloned
+ * @clone_flags:       %CLONE_* flags from clone/fork/vfork system call
+ *
+ * This is called before a new user task is to be cloned.
+ * Its return value will be passed to tracehook_finish_clone().
+ *
+ * Called with no locks held.
+ */
+static inline int tracehook_prepare_clone(unsigned clone_flags)
+{
+       if (clone_flags & CLONE_UNTRACED)
+               return 0;
+
+       if (clone_flags & CLONE_VFORK) {
+               if (current->ptrace & PT_TRACE_VFORK)
+                       return PTRACE_EVENT_VFORK;
+       } else if ((clone_flags & CSIGNAL) != SIGCHLD) {
+               if (current->ptrace & PT_TRACE_CLONE)
+                       return PTRACE_EVENT_CLONE;
+       } else if (current->ptrace & PT_TRACE_FORK)
+               return PTRACE_EVENT_FORK;
+
+       return 0;
+}
+
+/**
+ * tracehook_finish_clone - new child created and being attached
+ * @child:             new child task
+ * @clone_flags:       %CLONE_* flags from clone/fork/vfork system call
+ * @trace:             return value from tracehook_prepare_clone()
+ *
+ * This is called immediately after adding @child to its parent's children list.
+ * The @trace value is that returned by tracehook_prepare_clone().
+ *
+ * Called with current's siglock and write_lock_irq(&tasklist_lock) held.
+ */
+static inline void tracehook_finish_clone(struct task_struct *child,
+                                         unsigned long clone_flags, int trace)
+{
+       ptrace_init_task(child, (clone_flags & CLONE_PTRACE) || trace);
+}
+
+/**
+ * tracehook_report_clone - in parent, new child is about to start running
+ * @trace:             return value from tracehook_prepare_clone()
+ * @regs:              parent's user register state
+ * @clone_flags:       flags from parent's system call
+ * @pid:               new child's PID in the parent's namespace
+ * @child:             new child task
+ *
+ * Called after a child is set up, but before it has been started
+ * running.  @trace is the value returned by tracehook_prepare_clone().
+ * This is not a good place to block, because the child has not started
+ * yet.  Suspend the child here if desired, and then block in
+ * tracehook_report_clone_complete().  This must prevent the child from
+ * self-reaping if tracehook_report_clone_complete() uses the @child
+ * pointer; otherwise it might have died and been released by the time
+ * tracehook_report_report_clone_complete() is called.
+ *
+ * Called with no locks held, but the child cannot run until this returns.
+ */
+static inline void tracehook_report_clone(int trace, struct pt_regs *regs,
+                                         unsigned long clone_flags,
+                                         pid_t pid, struct task_struct *child)
+{
+       if (unlikely(trace)) {
+               /*
+                * The child starts up with an immediate SIGSTOP.
+                */
+               sigaddset(&child->pending.signal, SIGSTOP);
+               set_tsk_thread_flag(child, TIF_SIGPENDING);
+       }
+}
+
+/**
+ * tracehook_report_clone_complete - new child is running
+ * @trace:             return value from tracehook_prepare_clone()
+ * @regs:              parent's user register state
+ * @clone_flags:       flags from parent's system call
+ * @pid:               new child's PID in the parent's namespace
+ * @child:             child task, already running
+ *
+ * This is called just after the child has started running.  This is
+ * just before the clone/fork syscall returns, or blocks for vfork
+ * child completion if @clone_flags has the %CLONE_VFORK bit set.
+ * The @child pointer may be invalid if a self-reaping child died and
+ * tracehook_report_clone() took no action to prevent it from self-reaping.
+ *
+ * Called with no locks held.
+ */
+static inline void tracehook_report_clone_complete(int trace,
+                                                  struct pt_regs *regs,
+                                                  unsigned long clone_flags,
+                                                  pid_t pid,
+                                                  struct task_struct *child)
+{
+       if (unlikely(trace))
+               ptrace_event(0, trace, pid);
+}
+
+/**
+ * tracehook_report_vfork_done - vfork parent's child has exited or exec'd
+ * @child:             child task, already running
+ * @pid:               new child's PID in the parent's namespace
+ *
+ * Called after a %CLONE_VFORK parent has waited for the child to complete.
+ * The clone/vfork system call will return immediately after this.
+ * The @child pointer may be invalid if a self-reaping child died and
+ * tracehook_report_clone() took no action to prevent it from self-reaping.
+ *
+ * Called with no locks held.
+ */
+static inline void tracehook_report_vfork_done(struct task_struct *child,
+                                              pid_t pid)
+{
+       ptrace_event(PT_TRACE_VFORK_DONE, PTRACE_EVENT_VFORK_DONE, pid);
+}
+
+/**
+ * tracehook_prepare_release_task - task is being reaped, clean up tracing
+ * @task:              task in %EXIT_DEAD state
+ *
+ * This is called in release_task() just before @task gets finally reaped
+ * and freed.  This would be the ideal place to remove and clean up any
+ * tracing-related state for @task.
+ *
+ * Called with no locks held.
+ */
+static inline void tracehook_prepare_release_task(struct task_struct *task)
+{
+}
+
+/**
+ * tracehook_finish_release_task - final tracing clean-up
+ * @task:              task in %EXIT_DEAD state
+ *
+ * This is called in release_task() when @task is being in the middle of
+ * being reaped.  After this, there must be no tracing entanglements.
+ *
+ * Called with write_lock_irq(&tasklist_lock) held.
+ */
+static inline void tracehook_finish_release_task(struct task_struct *task)
+{
+       ptrace_release_task(task);
+}
+
+/**
+ * tracehook_signal_handler - signal handler setup is complete
+ * @sig:               number of signal being delivered
+ * @info:              siginfo_t of signal being delivered
+ * @ka:                        sigaction setting that chose the handler
+ * @regs:              user register state
+ * @stepping:          nonzero if debugger single-step or block-step in use
+ *
+ * Called by the arch code after a signal handler has been set up.
+ * Register and stack state reflects the user handler about to run.
+ * Signal mask changes have already been made.
+ *
+ * Called without locks, shortly before returning to user mode
+ * (or handling more signals).
+ */
+static inline void tracehook_signal_handler(int sig, siginfo_t *info,
+                                           const struct k_sigaction *ka,
+                                           struct pt_regs *regs, int stepping)
+{
+       if (stepping)
+               ptrace_notify(SIGTRAP);
+}
+
+/**
+ * tracehook_consider_ignored_signal - suppress short-circuit of ignored signal
+ * @task:              task receiving the signal
+ * @sig:               signal number being sent
+ * @handler:           %SIG_IGN or %SIG_DFL
+ *
+ * Return zero iff tracing doesn't care to examine this ignored signal,
+ * so it can short-circuit normal delivery and never even get queued.
+ * Either @handler is %SIG_DFL and @sig's default is ignore, or it's %SIG_IGN.
+ *
+ * Called with @task->sighand->siglock held.
+ */
+static inline int tracehook_consider_ignored_signal(struct task_struct *task,
+                                                   int sig,
+                                                   void __user *handler)
+{
+       return (task_ptrace(task) & PT_PTRACED) != 0;
+}
+
+/**
+ * tracehook_consider_fatal_signal - suppress special handling of fatal signal
+ * @task:              task receiving the signal
+ * @sig:               signal number being sent
+ * @handler:           %SIG_DFL or %SIG_IGN
+ *
+ * Return nonzero to prevent special handling of this termination signal.
+ * Normally @handler is %SIG_DFL.  It can be %SIG_IGN if @sig is ignored,
+ * in which case force_sig() is about to reset it to %SIG_DFL.
+ * When this returns zero, this signal might cause a quick termination
+ * that does not give the debugger a chance to intercept the signal.
+ *
+ * Called with or without @task->sighand->siglock held.
+ */
+static inline int tracehook_consider_fatal_signal(struct task_struct *task,
+                                                 int sig,
+                                                 void __user *handler)
+{
+       return (task_ptrace(task) & PT_PTRACED) != 0;
+}
+
+/**
+ * tracehook_force_sigpending - let tracing force signal_pending(current) on
+ *
+ * Called when recomputing our signal_pending() flag.  Return nonzero
+ * to force the signal_pending() flag on, so that tracehook_get_signal()
+ * will be called before the next return to user mode.
+ *
+ * Called with @current->sighand->siglock held.
+ */
+static inline int tracehook_force_sigpending(void)
+{
+       return 0;
+}
+
+/**
+ * tracehook_get_signal - deliver synthetic signal to traced task
+ * @task:              @current
+ * @regs:              task_pt_regs(@current)
+ * @info:              details of synthetic signal
+ * @return_ka:         sigaction for synthetic signal
+ *
+ * Return zero to check for a real pending signal normally.
+ * Return -1 after releasing the siglock to repeat the check.
+ * Return a signal number to induce an artifical signal delivery,
+ * setting *@info and *@return_ka to specify its details and behavior.
+ *
+ * The @return_ka->sa_handler value controls the disposition of the
+ * signal, no matter the signal number.  For %SIG_DFL, the return value
+ * is a representative signal to indicate the behavior (e.g. %SIGTERM
+ * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop,
+ * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number
+ * reported will be @info->si_signo instead.
+ *
+ * Called with @task->sighand->siglock held, before dequeuing pending signals.
+ */
+static inline int tracehook_get_signal(struct task_struct *task,
+                                      struct pt_regs *regs,
+                                      siginfo_t *info,
+                                      struct k_sigaction *return_ka)
+{
+       return 0;
+}
+
+/**
+ * tracehook_notify_jctl - report about job control stop/continue
+ * @notify:            nonzero if this is the last thread in the group to stop
+ * @why:               %CLD_STOPPED or %CLD_CONTINUED
+ *
+ * This is called when we might call do_notify_parent_cldstop().
+ * It's called when about to stop for job control; we are already in
+ * %TASK_STOPPED state, about to call schedule().  It's also called when
+ * a delayed %CLD_STOPPED or %CLD_CONTINUED report is ready to be made.
+ *
+ * Return nonzero to generate a %SIGCHLD with @why, which is
+ * normal if @notify is nonzero.
+ *
+ * Called with no locks held.
+ */
+static inline int tracehook_notify_jctl(int notify, int why)
+{
+       return notify || (current->ptrace & PT_PTRACED);
+}
+
+/**
+ * tracehook_notify_death - task is dead, ready to notify parent
+ * @task:              @current task now exiting
+ * @death_cookie:      value to pass to tracehook_report_death()
+ * @group_dead:                nonzero if this was the last thread in the group to die
+ *
+ * Return the signal number to send our parent with do_notify_parent(), or
+ * zero to send no signal and leave a zombie, or -1 to self-reap right now.
+ *
+ * Called with write_lock_irq(&tasklist_lock) held.
+ */
+static inline int tracehook_notify_death(struct task_struct *task,
+                                        void **death_cookie, int group_dead)
+{
+       if (task->exit_signal == -1)
+               return task->ptrace ? SIGCHLD : -1;
+
+       /*
+        * If something other than our normal parent is ptracing us, then
+        * send it a SIGCHLD instead of honoring exit_signal.  exit_signal
+        * only has special meaning to our real parent.
+        */
+       if (thread_group_empty(task) && !ptrace_reparented(task))
+               return task->exit_signal;
+
+       return task->ptrace ? SIGCHLD : 0;
+}
+
+/**
+ * tracehook_report_death - task is dead and ready to be reaped
+ * @task:              @current task now exiting
+ * @signal:            signal number sent to parent, or 0 or -1
+ * @death_cookie:      value passed back from tracehook_notify_death()
+ * @group_dead:                nonzero if this was the last thread in the group to die
+ *
+ * Thread has just become a zombie or is about to self-reap.  If positive,
+ * @signal is the signal number just sent to the parent (usually %SIGCHLD).
+ * If @signal is -1, this thread will self-reap.  If @signal is 0, this is
+ * a delayed_group_leader() zombie.  The @death_cookie was passed back by
+ * tracehook_notify_death().
+ *
+ * If normal reaping is not inhibited, @task->exit_state might be changing
+ * in parallel.
+ *
+ * Called without locks.
+ */
+static inline void tracehook_report_death(struct task_struct *task,
+                                         int signal, void *death_cookie,
+                                         int group_dead)
+{
+}
+
+#ifdef TIF_NOTIFY_RESUME
+/**
+ * set_notify_resume - cause tracehook_notify_resume() to be called
+ * @task:              task that will call tracehook_notify_resume()
+ *
+ * Calling this arranges that @task will call tracehook_notify_resume()
+ * before returning to user mode.  If it's already running in user mode,
+ * it will enter the kernel and call tracehook_notify_resume() soon.
+ * If it's blocked, it will not be woken.
+ */
+static inline void set_notify_resume(struct task_struct *task)
+{
+       if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_RESUME))
+               kick_process(task);
+}
+
+/**
+ * tracehook_notify_resume - report when about to return to user mode
+ * @regs:              user-mode registers of @current task
+ *
+ * This is called when %TIF_NOTIFY_RESUME has been set.  Now we are
+ * about to return to user mode, and the user state in @regs can be
+ * inspected or adjusted.  The caller in arch code has cleared
+ * %TIF_NOTIFY_RESUME before the call.  If the flag gets set again
+ * asynchronously, this will be called again before we return to
+ * user mode.
+ *
+ * Called without locks.
+ */
+static inline void tracehook_notify_resume(struct pt_regs *regs)
+{
+}
+#endif /* TIF_NOTIFY_RESUME */
+
+#endif /* <linux/tracehook.h> */
diff --git a/include/linux/typecheck.h b/include/linux/typecheck.h
new file mode 100644 (file)
index 0000000..eb5b74a
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef TYPECHECK_H_INCLUDED
+#define TYPECHECK_H_INCLUDED
+
+/*
+ * Check at compile time that something is of a particular type.
+ * Always evaluates to 1 so you may use it easily in comparisons.
+ */
+#define typecheck(type,x) \
+({     type __dummy; \
+       typeof(x) __dummy2; \
+       (void)(&__dummy == &__dummy2); \
+       1; \
+})
+
+/*
+ * Check at compile time that 'function' is a certain type, or is a pointer
+ * to that type (needs to use typedef for the function type.)
+ */
+#define typecheck_fn(type,function) \
+({     typeof(type) __tmp = function; \
+       (void)__tmp; \
+})
+
+#endif         /* TYPECHECK_H_INCLUDED */
index 747c3a49cdc9489ca791460794266553174246e3..c932390c6da08c2715b39db9eb19ecea75709023 100644 (file)
@@ -330,7 +330,7 @@ extern int usb_string_id(struct usb_composite_dev *c);
        dev_vdbg(&(d)->gadget->dev , fmt , ## args)
 #define ERROR(d, fmt, args...) \
        dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
+#define WARNING(d, fmt, args...) \
        dev_warn(&(d)->gadget->dev , fmt , ## args)
 #define INFO(d, fmt, args...) \
        dev_info(&(d)->gadget->dev , fmt , ## args)
index 9385a566aed8dd5136c0be1f2fc01981d1a849be..15a653d411329dc8cb7eb8584120b93243bfcede 100644 (file)
 
 #if defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__)
 
+#define VID_TYPE_CAPTURE       1       /* Can capture */
+#define VID_TYPE_TUNER         2       /* Can tune */
+#define VID_TYPE_TELETEXT      4       /* Does teletext */
+#define VID_TYPE_OVERLAY       8       /* Overlay onto frame buffer */
+#define VID_TYPE_CHROMAKEY     16      /* Overlay by chromakey */
+#define VID_TYPE_CLIPPING      32      /* Can clip */
+#define VID_TYPE_FRAMERAM      64      /* Uses the frame buffer memory */
+#define VID_TYPE_SCALES                128     /* Scalable */
+#define VID_TYPE_MONOCHROME    256     /* Monochrome only */
+#define VID_TYPE_SUBCAPTURE    512     /* Can capture subareas of the image */
+#define VID_TYPE_MPEG_DECODER  1024    /* Can decode MPEG streams */
+#define VID_TYPE_MPEG_ENCODER  2048    /* Can encode MPEG streams */
+#define VID_TYPE_MJPEG_DECODER 4096    /* Can decode MJPEG streams */
+#define VID_TYPE_MJPEG_ENCODER 8192    /* Can encode MJPEG streams */
+
 struct video_capability
 {
        char name[32];
index 2e66a95e8d32f5e19ee073891b0b103765cc865d..e466bd54a50e25b9a719799672e988c3a924c5c5 100644 (file)
  */
 #define VIDEO_MAX_FRAME               32
 
+#ifndef __KERNEL__
+
+/* These defines are V4L1 specific and should not be used with the V4L2 API!
+   They will be removed from this header in the future. */
+
 #define VID_TYPE_CAPTURE       1       /* Can capture */
 #define VID_TYPE_TUNER         2       /* Can tune */
 #define VID_TYPE_TELETEXT      4       /* Does teletext */
 #define VID_TYPE_MPEG_ENCODER  2048    /* Can encode MPEG streams */
 #define VID_TYPE_MJPEG_DECODER 4096    /* Can decode MJPEG streams */
 #define VID_TYPE_MJPEG_ENCODER 8192    /* Can encode MJPEG streams */
+#endif
 
 /*
  *     M I S C E L L A N E O U S
  */
 
 /*  Four-character-code (FOURCC) */
-#define v4l2_fourcc(a,b,c,d)\
-       (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
+#define v4l2_fourcc(a, b, c, d)\
+       ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24))
 
 /*
  *     E N U M S
@@ -226,8 +232,7 @@ struct v4l2_fract {
 /*
  *     D R I V E R   C A P A B I L I T I E S
  */
-struct v4l2_capability
-{
+struct v4l2_capability {
        __u8    driver[16];     /* i.e. "bttv" */
        __u8    card[32];       /* i.e. "Hauppauge WinTV" */
        __u8    bus_info[32];   /* "PCI:" + pci_name(pci_dev) */
@@ -259,8 +264,7 @@ struct v4l2_capability
 /*
  *     V I D E O   I M A G E   F O R M A T
  */
-struct v4l2_pix_format
-{
+struct v4l2_pix_format {
        __u32                   width;
        __u32                   height;
        __u32                   pixelformat;
@@ -272,68 +276,69 @@ struct v4l2_pix_format
 };
 
 /*      Pixel format         FOURCC                        depth  Description  */
-#define V4L2_PIX_FMT_RGB332  v4l2_fourcc('R','G','B','1') /*  8  RGB-3-3-2     */
-#define V4L2_PIX_FMT_RGB444  v4l2_fourcc('R','4','4','4') /* 16  xxxxrrrr ggggbbbb */
-#define V4L2_PIX_FMT_RGB555  v4l2_fourcc('R','G','B','O') /* 16  RGB-5-5-5     */
-#define V4L2_PIX_FMT_RGB565  v4l2_fourcc('R','G','B','P') /* 16  RGB-5-6-5     */
-#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R','G','B','Q') /* 16  RGB-5-5-5 BE  */
-#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R','G','B','R') /* 16  RGB-5-6-5 BE  */
-#define V4L2_PIX_FMT_BGR24   v4l2_fourcc('B','G','R','3') /* 24  BGR-8-8-8     */
-#define V4L2_PIX_FMT_RGB24   v4l2_fourcc('R','G','B','3') /* 24  RGB-8-8-8     */
-#define V4L2_PIX_FMT_BGR32   v4l2_fourcc('B','G','R','4') /* 32  BGR-8-8-8-8   */
-#define V4L2_PIX_FMT_RGB32   v4l2_fourcc('R','G','B','4') /* 32  RGB-8-8-8-8   */
-#define V4L2_PIX_FMT_GREY    v4l2_fourcc('G','R','E','Y') /*  8  Greyscale     */
-#define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y','1','6',' ') /* 16  Greyscale     */
-#define V4L2_PIX_FMT_PAL8    v4l2_fourcc('P','A','L','8') /*  8  8-bit palette */
-#define V4L2_PIX_FMT_YVU410  v4l2_fourcc('Y','V','U','9') /*  9  YVU 4:1:0     */
-#define V4L2_PIX_FMT_YVU420  v4l2_fourcc('Y','V','1','2') /* 12  YVU 4:2:0     */
-#define V4L2_PIX_FMT_YUYV    v4l2_fourcc('Y','U','Y','V') /* 16  YUV 4:2:2     */
-#define V4L2_PIX_FMT_UYVY    v4l2_fourcc('U','Y','V','Y') /* 16  YUV 4:2:2     */
-#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4','2','2','P') /* 16  YVU422 planar */
-#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4','1','1','P') /* 16  YVU411 planar */
-#define V4L2_PIX_FMT_Y41P    v4l2_fourcc('Y','4','1','P') /* 12  YUV 4:1:1     */
-#define V4L2_PIX_FMT_YUV444  v4l2_fourcc('Y','4','4','4') /* 16  xxxxyyyy uuuuvvvv */
-#define V4L2_PIX_FMT_YUV555  v4l2_fourcc('Y','U','V','O') /* 16  YUV-5-5-5     */
-#define V4L2_PIX_FMT_YUV565  v4l2_fourcc('Y','U','V','P') /* 16  YUV-5-6-5     */
-#define V4L2_PIX_FMT_YUV32   v4l2_fourcc('Y','U','V','4') /* 32  YUV-8-8-8-8   */
+#define V4L2_PIX_FMT_RGB332  v4l2_fourcc('R', 'G', 'B', '1') /*  8  RGB-3-3-2     */
+#define V4L2_PIX_FMT_RGB444  v4l2_fourcc('R', '4', '4', '4') /* 16  xxxxrrrr ggggbbbb */
+#define V4L2_PIX_FMT_RGB555  v4l2_fourcc('R', 'G', 'B', 'O') /* 16  RGB-5-5-5     */
+#define V4L2_PIX_FMT_RGB565  v4l2_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5     */
+#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
+#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16  RGB-5-6-5 BE  */
+#define V4L2_PIX_FMT_BGR24   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8     */
+#define V4L2_PIX_FMT_RGB24   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8     */
+#define V4L2_PIX_FMT_BGR32   v4l2_fourcc('B', 'G', 'R', '4') /* 32  BGR-8-8-8-8   */
+#define V4L2_PIX_FMT_RGB32   v4l2_fourcc('R', 'G', 'B', '4') /* 32  RGB-8-8-8-8   */
+#define V4L2_PIX_FMT_GREY    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
+#define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
+#define V4L2_PIX_FMT_PAL8    v4l2_fourcc('P', 'A', 'L', '8') /*  8  8-bit palette */
+#define V4L2_PIX_FMT_YVU410  v4l2_fourcc('Y', 'V', 'U', '9') /*  9  YVU 4:1:0     */
+#define V4L2_PIX_FMT_YVU420  v4l2_fourcc('Y', 'V', '1', '2') /* 12  YVU 4:2:0     */
+#define V4L2_PIX_FMT_YUYV    v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_UYVY    v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4', '2', '2', 'P') /* 16  YVU422 planar */
+#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4', '1', '1', 'P') /* 16  YVU411 planar */
+#define V4L2_PIX_FMT_Y41P    v4l2_fourcc('Y', '4', '1', 'P') /* 12  YUV 4:1:1     */
+#define V4L2_PIX_FMT_YUV444  v4l2_fourcc('Y', '4', '4', '4') /* 16  xxxxyyyy uuuuvvvv */
+#define V4L2_PIX_FMT_YUV555  v4l2_fourcc('Y', 'U', 'V', 'O') /* 16  YUV-5-5-5     */
+#define V4L2_PIX_FMT_YUV565  v4l2_fourcc('Y', 'U', 'V', 'P') /* 16  YUV-5-6-5     */
+#define V4L2_PIX_FMT_YUV32   v4l2_fourcc('Y', 'U', 'V', '4') /* 32  YUV-8-8-8-8   */
 
 /* two planes -- one Y, one Cr + Cb interleaved  */
-#define V4L2_PIX_FMT_NV12    v4l2_fourcc('N','V','1','2') /* 12  Y/CbCr 4:2:0  */
-#define V4L2_PIX_FMT_NV21    v4l2_fourcc('N','V','2','1') /* 12  Y/CrCb 4:2:0  */
+#define V4L2_PIX_FMT_NV12    v4l2_fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */
+#define V4L2_PIX_FMT_NV21    v4l2_fourcc('N', 'V', '2', '1') /* 12  Y/CrCb 4:2:0  */
 
 /*  The following formats are not defined in the V4L2 specification */
-#define V4L2_PIX_FMT_YUV410  v4l2_fourcc('Y','U','V','9') /*  9  YUV 4:1:0     */
-#define V4L2_PIX_FMT_YUV420  v4l2_fourcc('Y','U','1','2') /* 12  YUV 4:2:0     */
-#define V4L2_PIX_FMT_YYUV    v4l2_fourcc('Y','Y','U','V') /* 16  YUV 4:2:2     */
-#define V4L2_PIX_FMT_HI240   v4l2_fourcc('H','I','2','4') /*  8  8-bit color   */
-#define V4L2_PIX_FMT_HM12    v4l2_fourcc('H','M','1','2') /*  8  YUV 4:2:0 16x16 macroblocks */
+#define V4L2_PIX_FMT_YUV410  v4l2_fourcc('Y', 'U', 'V', '9') /*  9  YUV 4:1:0     */
+#define V4L2_PIX_FMT_YUV420  v4l2_fourcc('Y', 'U', '1', '2') /* 12  YUV 4:2:0     */
+#define V4L2_PIX_FMT_YYUV    v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_HI240   v4l2_fourcc('H', 'I', '2', '4') /*  8  8-bit color   */
+#define V4L2_PIX_FMT_HM12    v4l2_fourcc('H', 'M', '1', '2') /*  8  YUV 4:2:0 16x16 macroblocks */
 
 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
-#define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B','A','8','1') /*  8  BGBG.. GRGR.. */
-#define V4L2_PIX_FMT_SGBRG8  v4l2_fourcc('G','B','R','G') /*  8  GBGB.. RGRG.. */
-#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG8  v4l2_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16  BGBG.. GRGR.. */
 
 /* compressed formats */
-#define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M','J','P','G') /* Motion-JPEG   */
-#define V4L2_PIX_FMT_JPEG     v4l2_fourcc('J','P','E','G') /* JFIF JPEG     */
-#define V4L2_PIX_FMT_DV       v4l2_fourcc('d','v','s','d') /* 1394          */
-#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M','P','E','G') /* MPEG-1/2/4    */
+#define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG   */
+#define V4L2_PIX_FMT_JPEG     v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG     */
+#define V4L2_PIX_FMT_DV       v4l2_fourcc('d', 'v', 's', 'd') /* 1394          */
+#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4    */
 
 /*  Vendor-specific formats   */
-#define V4L2_PIX_FMT_WNVA     v4l2_fourcc('W','N','V','A') /* Winnov hw compress */
-#define V4L2_PIX_FMT_SN9C10X  v4l2_fourcc('S','9','1','0') /* SN9C10x compression */
-#define V4L2_PIX_FMT_PWC1     v4l2_fourcc('P','W','C','1') /* pwc older webcam */
-#define V4L2_PIX_FMT_PWC2     v4l2_fourcc('P','W','C','2') /* pwc newer webcam */
-#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */
-#define V4L2_PIX_FMT_SPCA501  v4l2_fourcc('S','5','0','1') /* YUYV per line */
-#define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S','5','6','1') /* compressed GBRG bayer */
-#define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P','2','0','7') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_WNVA     v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
+#define V4L2_PIX_FMT_SN9C10X  v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
+#define V4L2_PIX_FMT_PWC1     v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */
+#define V4L2_PIX_FMT_PWC2     v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */
+#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */
+#define V4L2_PIX_FMT_SPCA501  v4l2_fourcc('S', '5', '0', '1') /* YUYV per line */
+#define V4L2_PIX_FMT_SPCA505  v4l2_fourcc('S', '5', '0', '5') /* YYUV per line */
+#define V4L2_PIX_FMT_SPCA508  v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */
+#define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
+#define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
 
 /*
  *     F O R M A T   E N U M E R A T I O N
  */
-struct v4l2_fmtdesc
-{
+struct v4l2_fmtdesc {
        __u32               index;             /* Format number      */
        enum v4l2_buf_type  type;              /* buffer type        */
        __u32               flags;
@@ -349,21 +354,18 @@ struct v4l2_fmtdesc
 /*
  *     F R A M E   S I Z E   E N U M E R A T I O N
  */
-enum v4l2_frmsizetypes
-{
+enum v4l2_frmsizetypes {
        V4L2_FRMSIZE_TYPE_DISCRETE      = 1,
        V4L2_FRMSIZE_TYPE_CONTINUOUS    = 2,
        V4L2_FRMSIZE_TYPE_STEPWISE      = 3,
 };
 
-struct v4l2_frmsize_discrete
-{
+struct v4l2_frmsize_discrete {
        __u32                   width;          /* Frame width [pixel] */
        __u32                   height;         /* Frame height [pixel] */
 };
 
-struct v4l2_frmsize_stepwise
-{
+struct v4l2_frmsize_stepwise {
        __u32                   min_width;      /* Minimum frame width [pixel] */
        __u32                   max_width;      /* Maximum frame width [pixel] */
        __u32                   step_width;     /* Frame width step size [pixel] */
@@ -372,8 +374,7 @@ struct v4l2_frmsize_stepwise
        __u32                   step_height;    /* Frame height step size [pixel] */
 };
 
-struct v4l2_frmsizeenum
-{
+struct v4l2_frmsizeenum {
        __u32                   index;          /* Frame size number */
        __u32                   pixel_format;   /* Pixel format */
        __u32                   type;           /* Frame size type the device supports. */
@@ -389,22 +390,19 @@ struct v4l2_frmsizeenum
 /*
  *     F R A M E   R A T E   E N U M E R A T I O N
  */
-enum v4l2_frmivaltypes
-{
+enum v4l2_frmivaltypes {
        V4L2_FRMIVAL_TYPE_DISCRETE      = 1,
        V4L2_FRMIVAL_TYPE_CONTINUOUS    = 2,
        V4L2_FRMIVAL_TYPE_STEPWISE      = 3,
 };
 
-struct v4l2_frmival_stepwise
-{
+struct v4l2_frmival_stepwise {
        struct v4l2_fract       min;            /* Minimum frame interval [s] */
        struct v4l2_fract       max;            /* Maximum frame interval [s] */
        struct v4l2_fract       step;           /* Frame interval step size [s] */
 };
 
-struct v4l2_frmivalenum
-{
+struct v4l2_frmivalenum {
        __u32                   index;          /* Frame format index */
        __u32                   pixel_format;   /* Pixel format */
        __u32                   width;          /* Frame width */
@@ -423,8 +421,7 @@ struct v4l2_frmivalenum
 /*
  *     T I M E C O D E
  */
-struct v4l2_timecode
-{
+struct v4l2_timecode {
        __u32   type;
        __u32   flags;
        __u8    frames;
@@ -449,8 +446,7 @@ struct v4l2_timecode
 #define V4L2_TC_USERBITS_8BITCHARS     0x0008
 /* The above is based on SMPTE timecodes */
 
-struct v4l2_jpegcompression
-{
+struct v4l2_jpegcompression {
        int quality;
 
        int  APPn;              /* Number of APP segment to be written,
@@ -482,16 +478,14 @@ struct v4l2_jpegcompression
 /*
  *     M E M O R Y - M A P P I N G   B U F F E R S
  */
-struct v4l2_requestbuffers
-{
+struct v4l2_requestbuffers {
        __u32                   count;
        enum v4l2_buf_type      type;
        enum v4l2_memory        memory;
        __u32                   reserved[2];
 };
 
-struct v4l2_buffer
-{
+struct v4l2_buffer {
        __u32                   index;
        enum v4l2_buf_type      type;
        __u32                   bytesused;
@@ -525,13 +519,12 @@ struct v4l2_buffer
 /*
  *     O V E R L A Y   P R E V I E W
  */
-struct v4l2_framebuffer
-{
+struct v4l2_framebuffer {
        __u32                   capability;
        __u32                   flags;
 /* FIXME: in theory we should pass something like PCI device + memory
  * region + offset instead of some physical address */
-       void*                   base;
+       void                    *base;
        struct v4l2_pix_format  fmt;
 };
 /*  Flags for the 'capability' field. Read only */
@@ -550,14 +543,12 @@ struct v4l2_framebuffer
 #define V4L2_FBUF_FLAG_GLOBAL_ALPHA    0x0010
 #define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020
 
-struct v4l2_clip
-{
+struct v4l2_clip {
        struct v4l2_rect        c;
        struct v4l2_clip        __user *next;
 };
 
-struct v4l2_window
-{
+struct v4l2_window {
        struct v4l2_rect        w;
        enum v4l2_field         field;
        __u32                   chromakey;
@@ -570,8 +561,7 @@ struct v4l2_window
 /*
  *     C A P T U R E   P A R A M E T E R S
  */
-struct v4l2_captureparm
-{
+struct v4l2_captureparm {
        __u32              capability;    /*  Supported modes */
        __u32              capturemode;   /*  Current mode */
        struct v4l2_fract  timeperframe;  /*  Time per frame in .1us units */
@@ -584,8 +574,7 @@ struct v4l2_captureparm
 #define V4L2_MODE_HIGHQUALITY  0x0001  /*  High quality imaging mode */
 #define V4L2_CAP_TIMEPERFRAME  0x1000  /*  timeperframe field is supported */
 
-struct v4l2_outputparm
-{
+struct v4l2_outputparm {
        __u32              capability;   /*  Supported modes */
        __u32              outputmode;   /*  Current mode */
        struct v4l2_fract  timeperframe; /*  Time per frame in seconds */
@@ -702,8 +691,7 @@ typedef __u64 v4l2_std_id;
 #define V4L2_STD_ALL            (V4L2_STD_525_60       |\
                                 V4L2_STD_625_50)
 
-struct v4l2_standard
-{
+struct v4l2_standard {
        __u32                index;
        v4l2_std_id          id;
        __u8                 name[24];
@@ -715,8 +703,7 @@ struct v4l2_standard
 /*
  *     V I D E O   I N P U T S
  */
-struct v4l2_input
-{
+struct v4l2_input {
        __u32        index;             /*  Which input */
        __u8         name[32];          /*  Label */
        __u32        type;              /*  Type of input */
@@ -753,8 +740,7 @@ struct v4l2_input
 /*
  *     V I D E O   O U T P U T S
  */
-struct v4l2_output
-{
+struct v4l2_output {
        __u32        index;             /*  Which output */
        __u8         name[32];          /*  Label */
        __u32        type;              /*  Type of output */
@@ -771,14 +757,12 @@ struct v4l2_output
 /*
  *     C O N T R O L S
  */
-struct v4l2_control
-{
+struct v4l2_control {
        __u32                id;
        __s32                value;
 };
 
-struct v4l2_ext_control
-{
+struct v4l2_ext_control {
        __u32 id;
        __u32 reserved2[2];
        union {
@@ -788,8 +772,7 @@ struct v4l2_ext_control
        };
 } __attribute__ ((packed));
 
-struct v4l2_ext_controls
-{
+struct v4l2_ext_controls {
        __u32 ctrl_class;
        __u32 count;
        __u32 error_idx;
@@ -807,8 +790,7 @@ struct v4l2_ext_controls
 #define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000)
 
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
-struct v4l2_queryctrl
-{
+struct v4l2_queryctrl {
        __u32                id;
        enum v4l2_ctrl_type  type;
        __u8                 name[32];  /* Whatever */
@@ -821,8 +803,7 @@ struct v4l2_queryctrl
 };
 
 /*  Used in the VIDIOC_QUERYMENU ioctl for querying menu items */
-struct v4l2_querymenu
-{
+struct v4l2_querymenu {
        __u32           id;
        __u32           index;
        __u8            name[32];       /* Whatever */
@@ -1104,8 +1085,7 @@ enum  v4l2_exposure_auto_type {
 /*
  *     T U N I N G
  */
-struct v4l2_tuner
-{
+struct v4l2_tuner {
        __u32                   index;
        __u8                    name[32];
        enum v4l2_tuner_type    type;
@@ -1119,8 +1099,7 @@ struct v4l2_tuner
        __u32                   reserved[4];
 };
 
-struct v4l2_modulator
-{
+struct v4l2_modulator {
        __u32                   index;
        __u8                    name[32];
        __u32                   capability;
@@ -1153,8 +1132,7 @@ struct v4l2_modulator
 #define V4L2_TUNER_MODE_LANG1          0x0003
 #define V4L2_TUNER_MODE_LANG1_LANG2    0x0004
 
-struct v4l2_frequency
-{
+struct v4l2_frequency {
        __u32                 tuner;
        enum v4l2_tuner_type  type;
        __u32                 frequency;
@@ -1172,8 +1150,7 @@ struct v4l2_hw_freq_seek {
 /*
  *     A U D I O
  */
-struct v4l2_audio
-{
+struct v4l2_audio {
        __u32   index;
        __u8    name[32];
        __u32   capability;
@@ -1188,8 +1165,7 @@ struct v4l2_audio
 /*  Flags for the 'mode' field */
 #define V4L2_AUDMODE_AVL               0x00001
 
-struct v4l2_audioout
-{
+struct v4l2_audioout {
        __u32   index;
        __u8    name[32];
        __u32   capability;
@@ -1253,8 +1229,7 @@ struct v4l2_encoder_cmd {
  */
 
 /* Raw VBI */
-struct v4l2_vbi_format
-{
+struct v4l2_vbi_format {
        __u32   sampling_rate;          /* in 1 Hz */
        __u32   offset;
        __u32   samples_per_line;
@@ -1266,8 +1241,8 @@ struct v4l2_vbi_format
 };
 
 /*  VBI flags  */
-#define V4L2_VBI_UNSYNC                (1<< 0)
-#define V4L2_VBI_INTERLACED    (1<< 1)
+#define V4L2_VBI_UNSYNC                (1 << 0)
+#define V4L2_VBI_INTERLACED    (1 << 1)
 
 /* Sliced VBI
  *
@@ -1276,8 +1251,7 @@ struct v4l2_vbi_format
  * notice in the definitive implementation.
  */
 
-struct v4l2_sliced_vbi_format
-{
+struct v4l2_sliced_vbi_format {
        __u16   service_set;
        /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
           service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
@@ -1301,8 +1275,7 @@ struct v4l2_sliced_vbi_format
 #define V4L2_SLICED_VBI_525             (V4L2_SLICED_CAPTION_525)
 #define V4L2_SLICED_VBI_625             (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625)
 
-struct v4l2_sliced_vbi_cap
-{
+struct v4l2_sliced_vbi_cap {
        __u16   service_set;
        /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
           service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
@@ -1313,8 +1286,7 @@ struct v4l2_sliced_vbi_cap
        __u32   reserved[3];    /* must be 0 */
 };
 
-struct v4l2_sliced_vbi_data
-{
+struct v4l2_sliced_vbi_data {
        __u32   id;
        __u32   field;          /* 0: first field, 1: second field */
        __u32   line;           /* 1-23 */
@@ -1328,27 +1300,23 @@ struct v4l2_sliced_vbi_data
 
 /*     Stream data format
  */
-struct v4l2_format
-{
+struct v4l2_format {
        enum v4l2_buf_type type;
-       union
-       {
-               struct v4l2_pix_format          pix;     // V4L2_BUF_TYPE_VIDEO_CAPTURE
-               struct v4l2_window              win;     // V4L2_BUF_TYPE_VIDEO_OVERLAY
-               struct v4l2_vbi_format          vbi;     // V4L2_BUF_TYPE_VBI_CAPTURE
-               struct v4l2_sliced_vbi_format   sliced;  // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
-               __u8    raw_data[200];                   // user-defined
+       union {
+               struct v4l2_pix_format          pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
+               struct v4l2_window              win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
+               struct v4l2_vbi_format          vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
+               struct v4l2_sliced_vbi_format   sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
+               __u8    raw_data[200];                   /* user-defined */
        } fmt;
 };
 
 
 /*     Stream type-dependent parameters
  */
-struct v4l2_streamparm
-{
+struct v4l2_streamparm {
        enum v4l2_buf_type type;
-       union
-       {
+       union {
                struct v4l2_captureparm capture;
                struct v4l2_outputparm  output;
                __u8    raw_data[200];  /* user-defined */
@@ -1386,92 +1354,86 @@ struct v4l2_chip_ident {
  *     I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
  */
-#define VIDIOC_QUERYCAP                _IOR  ('V',  0, struct v4l2_capability)
-#define VIDIOC_RESERVED                _IO   ('V',  1)
-#define VIDIOC_ENUM_FMT         _IOWR ('V',  2, struct v4l2_fmtdesc)
-#define VIDIOC_G_FMT           _IOWR ('V',  4, struct v4l2_format)
-#define VIDIOC_S_FMT           _IOWR ('V',  5, struct v4l2_format)
-#define VIDIOC_REQBUFS         _IOWR ('V',  8, struct v4l2_requestbuffers)
-#define VIDIOC_QUERYBUF                _IOWR ('V',  9, struct v4l2_buffer)
-#define VIDIOC_G_FBUF          _IOR  ('V', 10, struct v4l2_framebuffer)
-#define VIDIOC_S_FBUF          _IOW  ('V', 11, struct v4l2_framebuffer)
-#define VIDIOC_OVERLAY         _IOW  ('V', 14, int)
-#define VIDIOC_QBUF            _IOWR ('V', 15, struct v4l2_buffer)
-#define VIDIOC_DQBUF           _IOWR ('V', 17, struct v4l2_buffer)
-#define VIDIOC_STREAMON                _IOW  ('V', 18, int)
-#define VIDIOC_STREAMOFF       _IOW  ('V', 19, int)
-#define VIDIOC_G_PARM          _IOWR ('V', 21, struct v4l2_streamparm)
-#define VIDIOC_S_PARM          _IOWR ('V', 22, struct v4l2_streamparm)
-#define VIDIOC_G_STD           _IOR  ('V', 23, v4l2_std_id)
-#define VIDIOC_S_STD           _IOW  ('V', 24, v4l2_std_id)
-#define VIDIOC_ENUMSTD         _IOWR ('V', 25, struct v4l2_standard)
-#define VIDIOC_ENUMINPUT       _IOWR ('V', 26, struct v4l2_input)
-#define VIDIOC_G_CTRL          _IOWR ('V', 27, struct v4l2_control)
-#define VIDIOC_S_CTRL          _IOWR ('V', 28, struct v4l2_control)
-#define VIDIOC_G_TUNER         _IOWR ('V', 29, struct v4l2_tuner)
-#define VIDIOC_S_TUNER         _IOW  ('V', 30, struct v4l2_tuner)
-#define VIDIOC_G_AUDIO         _IOR  ('V', 33, struct v4l2_audio)
-#define VIDIOC_S_AUDIO         _IOW  ('V', 34, struct v4l2_audio)
-#define VIDIOC_QUERYCTRL       _IOWR ('V', 36, struct v4l2_queryctrl)
-#define VIDIOC_QUERYMENU       _IOWR ('V', 37, struct v4l2_querymenu)
-#define VIDIOC_G_INPUT         _IOR  ('V', 38, int)
-#define VIDIOC_S_INPUT         _IOWR ('V', 39, int)
-#define VIDIOC_G_OUTPUT                _IOR  ('V', 46, int)
-#define VIDIOC_S_OUTPUT                _IOWR ('V', 47, int)
-#define VIDIOC_ENUMOUTPUT      _IOWR ('V', 48, struct v4l2_output)
-#define VIDIOC_G_AUDOUT                _IOR  ('V', 49, struct v4l2_audioout)
-#define VIDIOC_S_AUDOUT                _IOW  ('V', 50, struct v4l2_audioout)
-#define VIDIOC_G_MODULATOR     _IOWR ('V', 54, struct v4l2_modulator)
-#define VIDIOC_S_MODULATOR     _IOW  ('V', 55, struct v4l2_modulator)
-#define VIDIOC_G_FREQUENCY     _IOWR ('V', 56, struct v4l2_frequency)
-#define VIDIOC_S_FREQUENCY     _IOW  ('V', 57, struct v4l2_frequency)
-#define VIDIOC_CROPCAP         _IOWR ('V', 58, struct v4l2_cropcap)
-#define VIDIOC_G_CROP          _IOWR ('V', 59, struct v4l2_crop)
-#define VIDIOC_S_CROP          _IOW  ('V', 60, struct v4l2_crop)
-#define VIDIOC_G_JPEGCOMP      _IOR  ('V', 61, struct v4l2_jpegcompression)
-#define VIDIOC_S_JPEGCOMP      _IOW  ('V', 62, struct v4l2_jpegcompression)
-#define VIDIOC_QUERYSTD        _IOR  ('V', 63, v4l2_std_id)
-#define VIDIOC_TRY_FMT         _IOWR ('V', 64, struct v4l2_format)
-#define VIDIOC_ENUMAUDIO       _IOWR ('V', 65, struct v4l2_audio)
-#define VIDIOC_ENUMAUDOUT      _IOWR ('V', 66, struct v4l2_audioout)
-#define VIDIOC_G_PRIORITY       _IOR  ('V', 67, enum v4l2_priority)
-#define VIDIOC_S_PRIORITY       _IOW  ('V', 68, enum v4l2_priority)
-#define VIDIOC_G_SLICED_VBI_CAP _IOWR ('V', 69, struct v4l2_sliced_vbi_cap)
-#define VIDIOC_LOG_STATUS       _IO   ('V', 70)
-#define VIDIOC_G_EXT_CTRLS     _IOWR ('V', 71, struct v4l2_ext_controls)
-#define VIDIOC_S_EXT_CTRLS     _IOWR ('V', 72, struct v4l2_ext_controls)
-#define VIDIOC_TRY_EXT_CTRLS   _IOWR ('V', 73, struct v4l2_ext_controls)
+#define VIDIOC_QUERYCAP                 _IOR('V',  0, struct v4l2_capability)
+#define VIDIOC_RESERVED                  _IO('V',  1)
+#define VIDIOC_ENUM_FMT         _IOWR('V',  2, struct v4l2_fmtdesc)
+#define VIDIOC_G_FMT           _IOWR('V',  4, struct v4l2_format)
+#define VIDIOC_S_FMT           _IOWR('V',  5, struct v4l2_format)
+#define VIDIOC_REQBUFS         _IOWR('V',  8, struct v4l2_requestbuffers)
+#define VIDIOC_QUERYBUF                _IOWR('V',  9, struct v4l2_buffer)
+#define VIDIOC_G_FBUF           _IOR('V', 10, struct v4l2_framebuffer)
+#define VIDIOC_S_FBUF           _IOW('V', 11, struct v4l2_framebuffer)
+#define VIDIOC_OVERLAY          _IOW('V', 14, int)
+#define VIDIOC_QBUF            _IOWR('V', 15, struct v4l2_buffer)
+#define VIDIOC_DQBUF           _IOWR('V', 17, struct v4l2_buffer)
+#define VIDIOC_STREAMON                 _IOW('V', 18, int)
+#define VIDIOC_STREAMOFF        _IOW('V', 19, int)
+#define VIDIOC_G_PARM          _IOWR('V', 21, struct v4l2_streamparm)
+#define VIDIOC_S_PARM          _IOWR('V', 22, struct v4l2_streamparm)
+#define VIDIOC_G_STD            _IOR('V', 23, v4l2_std_id)
+#define VIDIOC_S_STD            _IOW('V', 24, v4l2_std_id)
+#define VIDIOC_ENUMSTD         _IOWR('V', 25, struct v4l2_standard)
+#define VIDIOC_ENUMINPUT       _IOWR('V', 26, struct v4l2_input)
+#define VIDIOC_G_CTRL          _IOWR('V', 27, struct v4l2_control)
+#define VIDIOC_S_CTRL          _IOWR('V', 28, struct v4l2_control)
+#define VIDIOC_G_TUNER         _IOWR('V', 29, struct v4l2_tuner)
+#define VIDIOC_S_TUNER          _IOW('V', 30, struct v4l2_tuner)
+#define VIDIOC_G_AUDIO          _IOR('V', 33, struct v4l2_audio)
+#define VIDIOC_S_AUDIO          _IOW('V', 34, struct v4l2_audio)
+#define VIDIOC_QUERYCTRL       _IOWR('V', 36, struct v4l2_queryctrl)
+#define VIDIOC_QUERYMENU       _IOWR('V', 37, struct v4l2_querymenu)
+#define VIDIOC_G_INPUT          _IOR('V', 38, int)
+#define VIDIOC_S_INPUT         _IOWR('V', 39, int)
+#define VIDIOC_G_OUTPUT                 _IOR('V', 46, int)
+#define VIDIOC_S_OUTPUT                _IOWR('V', 47, int)
+#define VIDIOC_ENUMOUTPUT      _IOWR('V', 48, struct v4l2_output)
+#define VIDIOC_G_AUDOUT                 _IOR('V', 49, struct v4l2_audioout)
+#define VIDIOC_S_AUDOUT                 _IOW('V', 50, struct v4l2_audioout)
+#define VIDIOC_G_MODULATOR     _IOWR('V', 54, struct v4l2_modulator)
+#define VIDIOC_S_MODULATOR      _IOW('V', 55, struct v4l2_modulator)
+#define VIDIOC_G_FREQUENCY     _IOWR('V', 56, struct v4l2_frequency)
+#define VIDIOC_S_FREQUENCY      _IOW('V', 57, struct v4l2_frequency)
+#define VIDIOC_CROPCAP         _IOWR('V', 58, struct v4l2_cropcap)
+#define VIDIOC_G_CROP          _IOWR('V', 59, struct v4l2_crop)
+#define VIDIOC_S_CROP           _IOW('V', 60, struct v4l2_crop)
+#define VIDIOC_G_JPEGCOMP       _IOR('V', 61, struct v4l2_jpegcompression)
+#define VIDIOC_S_JPEGCOMP       _IOW('V', 62, struct v4l2_jpegcompression)
+#define VIDIOC_QUERYSTD         _IOR('V', 63, v4l2_std_id)
+#define VIDIOC_TRY_FMT         _IOWR('V', 64, struct v4l2_format)
+#define VIDIOC_ENUMAUDIO       _IOWR('V', 65, struct v4l2_audio)
+#define VIDIOC_ENUMAUDOUT      _IOWR('V', 66, struct v4l2_audioout)
+#define VIDIOC_G_PRIORITY        _IOR('V', 67, enum v4l2_priority)
+#define VIDIOC_S_PRIORITY        _IOW('V', 68, enum v4l2_priority)
+#define VIDIOC_G_SLICED_VBI_CAP _IOWR('V', 69, struct v4l2_sliced_vbi_cap)
+#define VIDIOC_LOG_STATUS         _IO('V', 70)
+#define VIDIOC_G_EXT_CTRLS     _IOWR('V', 71, struct v4l2_ext_controls)
+#define VIDIOC_S_EXT_CTRLS     _IOWR('V', 72, struct v4l2_ext_controls)
+#define VIDIOC_TRY_EXT_CTRLS   _IOWR('V', 73, struct v4l2_ext_controls)
 #if 1
-#define VIDIOC_ENUM_FRAMESIZES _IOWR ('V', 74, struct v4l2_frmsizeenum)
-#define VIDIOC_ENUM_FRAMEINTERVALS     _IOWR ('V', 75, struct v4l2_frmivalenum)
-#define VIDIOC_G_ENC_INDEX      _IOR  ('V', 76, struct v4l2_enc_idx)
-#define VIDIOC_ENCODER_CMD      _IOWR ('V', 77, struct v4l2_encoder_cmd)
-#define VIDIOC_TRY_ENCODER_CMD  _IOWR ('V', 78, struct v4l2_encoder_cmd)
+#define VIDIOC_ENUM_FRAMESIZES _IOWR('V', 74, struct v4l2_frmsizeenum)
+#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct v4l2_frmivalenum)
+#define VIDIOC_G_ENC_INDEX       _IOR('V', 76, struct v4l2_enc_idx)
+#define VIDIOC_ENCODER_CMD      _IOWR('V', 77, struct v4l2_encoder_cmd)
+#define VIDIOC_TRY_ENCODER_CMD  _IOWR('V', 78, struct v4l2_encoder_cmd)
 
 /* Experimental, only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
-#define        VIDIOC_DBG_S_REGISTER   _IOW  ('V', 79, struct v4l2_register)
-#define        VIDIOC_DBG_G_REGISTER   _IOWR ('V', 80, struct v4l2_register)
+#define        VIDIOC_DBG_S_REGISTER    _IOW('V', 79, struct v4l2_register)
+#define        VIDIOC_DBG_G_REGISTER   _IOWR('V', 80, struct v4l2_register)
 
-#define VIDIOC_G_CHIP_IDENT     _IOWR ('V', 81, struct v4l2_chip_ident)
+#define VIDIOC_G_CHIP_IDENT     _IOWR('V', 81, struct v4l2_chip_ident)
 #endif
-#define VIDIOC_S_HW_FREQ_SEEK  _IOW  ('V', 82, struct v4l2_hw_freq_seek)
+#define VIDIOC_S_HW_FREQ_SEEK   _IOW('V', 82, struct v4l2_hw_freq_seek)
 
 #ifdef __OLD_VIDIOC_
 /* for compatibility, will go away some day */
-#define VIDIOC_OVERLAY_OLD             _IOWR ('V', 14, int)
-#define VIDIOC_S_PARM_OLD              _IOW  ('V', 22, struct v4l2_streamparm)
-#define VIDIOC_S_CTRL_OLD              _IOW  ('V', 28, struct v4l2_control)
-#define VIDIOC_G_AUDIO_OLD             _IOWR ('V', 33, struct v4l2_audio)
-#define VIDIOC_G_AUDOUT_OLD            _IOWR ('V', 49, struct v4l2_audioout)
-#define VIDIOC_CROPCAP_OLD             _IOR  ('V', 58, struct v4l2_cropcap)
+#define VIDIOC_OVERLAY_OLD             _IOWR('V', 14, int)
+#define VIDIOC_S_PARM_OLD               _IOW('V', 22, struct v4l2_streamparm)
+#define VIDIOC_S_CTRL_OLD               _IOW('V', 28, struct v4l2_control)
+#define VIDIOC_G_AUDIO_OLD             _IOWR('V', 33, struct v4l2_audio)
+#define VIDIOC_G_AUDOUT_OLD            _IOWR('V', 49, struct v4l2_audioout)
+#define VIDIOC_CROPCAP_OLD              _IOR('V', 58, struct v4l2_cropcap)
 #endif
 
 #define BASE_VIDIOC_PRIVATE    192             /* 192-255 are private */
 
 #endif /* __LINUX_VIDEODEV2_H */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
index 018f92047ff83c9417393a1ebef5285bbce66ab6..3e68c8d1c7f7ad6f60392747530e64aa9058b0f8 100644 (file)
 #define VTXIOCCLRCACHE_OLD 0x710b  /* clear cache on VTX-interface (if avail.) */
 #define VTXIOCSETVIRT_OLD  0x710c  /* turn on virtual mode (this disables TV-display) */
 
-/* 
+/*
  *     Definitions for VTXIOCGETINFO
  */
+
 #define SAA5243 0
 #define SAA5246 1
 #define SAA5249 2
 
 typedef struct {
        int version_major, version_minor;       /* version of driver; if version_major changes, driver */
-                                               /* is not backward compatible!!! CHECK THIS!!! */  
+                                               /* is not backward compatible!!! CHECK THIS!!! */
        int numpages;                           /* number of page-buffers of vtx-chipset */
        int cct_type;                           /* type of vtx-chipset (SAA5243, SAA5246, SAA5248 or
-                                                * SAA5249) */
+                                                * SAA5249) */
 }
 vtx_info_t;
 
@@ -81,7 +81,7 @@ vtx_info_t;
 #define PGMASK_HOUR (HR_TEN | HR_UNIT)
 #define PGMASK_MINUTE (MIN_TEN | MIN_UNIT)
 
-typedef struct 
+typedef struct
 {
        int page;       /* number of requested page (hexadecimal) */
        int hour;       /* requested hour (hexadecimal) */
@@ -98,11 +98,11 @@ vtx_pagereq_t;
 /*
  *     Definitions for VTXIOC{GETSTAT,PUTSTAT}
  */
+
 #define VTX_PAGESIZE (40 * 24)
 #define VTX_VIRTUALSIZE (40 * 49)
 
-typedef struct 
+typedef struct
 {
        int pagenum;                    /* number of page (hexadecimal) */
        int hour;                       /* hour (hexadecimal) */
@@ -121,5 +121,5 @@ typedef struct
        unsigned hamming : 1;           /* hamming-error occurred */
 }
 vtx_pageinfo_t;
+
 #endif /* _VTX_H */
index 8eff0b53910b961ac76b662267c620a92a693a6f..b3c4a60ceeb305ffc9a670e57c08a580ab36798c 100644 (file)
@@ -1,5 +1,7 @@
 #ifndef _LINUX_VIRTIO_9P_H
 #define _LINUX_VIRTIO_9P_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
 #include <linux/virtio_config.h>
 
 /* The ID for virtio console */
index 979524ee75b7eeec0fac53aeb01c0fa1592911fc..c30c7bfbf39bcb0f26507b88a9e82ec336d6eff6 100644 (file)
@@ -1,5 +1,7 @@
 #ifndef _LINUX_VIRTIO_BALLOON_H
 #define _LINUX_VIRTIO_BALLOON_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
 #include <linux/virtio_config.h>
 
 /* The ID for virtio_balloon */
index 5f79a5f9de796b297c86f2647acfce713a533826..c1aef85243bf468522364425b6e06c022d9c8071 100644 (file)
@@ -1,5 +1,7 @@
 #ifndef _LINUX_VIRTIO_BLK_H
 #define _LINUX_VIRTIO_BLK_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
 #include <linux/virtio_config.h>
 
 /* The ID for virtio_block */
@@ -11,6 +13,7 @@
 #define VIRTIO_BLK_F_SEG_MAX   2       /* Indicates maximum # of segments */
 #define VIRTIO_BLK_F_GEOMETRY  4       /* Legacy geometry available  */
 #define VIRTIO_BLK_F_RO                5       /* Disk is read-only */
+#define VIRTIO_BLK_F_BLK_SIZE  6       /* Block size of disk is available*/
 
 struct virtio_blk_config
 {
@@ -26,6 +29,8 @@ struct virtio_blk_config
                __u8 heads;
                __u8 sectors;
        } geometry;
+       /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
+       __u32 blk_size;
 } __attribute__((packed));
 
 /* These two define direction. */
index f364bbf63c3413547738ae4028b399577bc76650..bf8ec283b232af65116af4fa338ad602f1b8d798 100644 (file)
@@ -1,5 +1,8 @@
 #ifndef _LINUX_VIRTIO_CONFIG_H
 #define _LINUX_VIRTIO_CONFIG_H
+/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
+ * anyone can use the definitions to implement compatible drivers/servers. */
+
 /* Virtio devices use a standardized configuration space to define their
  * features and pass configuration information, but each implementation can
  * store and access that space differently. */
 /* We've given up on this device. */
 #define VIRTIO_CONFIG_S_FAILED         0x80
 
+/* Some virtio feature bits (currently bits 28 through 31) are reserved for the
+ * transport being used (eg. virtio_ring), the rest are per-device feature
+ * bits. */
+#define VIRTIO_TRANSPORT_F_START       28
+#define VIRTIO_TRANSPORT_F_END         32
+
 /* Do we get callbacks when the ring is completely used, even if we've
  * suppressed them? */
 #define VIRTIO_F_NOTIFY_ON_EMPTY       24
  * @get_features: get the array of feature bits for this device.
  *     vdev: the virtio_device
  *     Returns the first 32 feature bits (all we currently need).
- * @set_features: confirm what device features we'll be using.
+ * @finalize_features: confirm what device features we'll be using.
  *     vdev: the virtio_device
- *     feature: the first 32 feature bits
+ *     This gives the final feature bits for the device: it can change
+ *     the dev->feature bits if it wants.
  */
 struct virtio_config_ops
 {
@@ -70,7 +80,7 @@ struct virtio_config_ops
                                     void (*callback)(struct virtqueue *));
        void (*del_vq)(struct virtqueue *vq);
        u32 (*get_features)(struct virtio_device *vdev);
-       void (*set_features)(struct virtio_device *vdev, u32 features);
+       void (*finalize_features)(struct virtio_device *vdev);
 };
 
 /* If driver didn't advertise the feature, it will never appear. */
index ed2d4ead7eb7ad67f0531f299e2076be201a1e92..19a0da0dba41203a59d5d2bce2762d2c2b78a240 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_VIRTIO_CONSOLE_H
 #define _LINUX_VIRTIO_CONSOLE_H
 #include <linux/virtio_config.h>
+/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
+ * anyone can use the definitions to implement compatible drivers/servers. */
 
 /* The ID for virtio console */
 #define VIRTIO_ID_CONSOLE      3
index 38c0571820fbffa6851fb1dd2707a925d94e6b81..5e33761b9b8a9d7c038d6e062221f5f68a0def3b 100644 (file)
@@ -1,5 +1,7 @@
 #ifndef _LINUX_VIRTIO_NET_H
 #define _LINUX_VIRTIO_NET_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
 #include <linux/virtio_config.h>
 
 /* The ID for virtio_net */
index b3151659cf497872578d0f4b37da6577cf7d050b..cdef3574293274eb7fa61d7a34c9315cfbe6ab88 100644 (file)
@@ -9,9 +9,8 @@
  * Authors:
  *  Anthony Liguori  <aliguori@us.ibm.com>
  *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
  */
 
 #ifndef _LINUX_VIRTIO_PCI_H
index abe481ed990e328bd6f5ec1f5212deeed07b9fea..c4a598fb3826f1de5f2fe6f62a536c148d3f77a9 100644 (file)
@@ -120,6 +120,8 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
                                      void (*notify)(struct virtqueue *vq),
                                      void (*callback)(struct virtqueue *vq));
 void vring_del_virtqueue(struct virtqueue *vq);
+/* Filter out transport-specific feature bits. */
+void vring_transport_features(struct virtio_device *vdev);
 
 irqreturn_t vring_interrupt(int irq, void *_vq);
 #endif /* __KERNEL__ */
index 331afb6c9f6282a21b9efb7972a161563122974e..1a85dab8a940c31b66cb1a5a36de381418b20739 100644 (file)
@@ -1,5 +1,7 @@
 #ifndef _LINUX_VIRTIO_RNG_H
 #define _LINUX_VIRTIO_RNG_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
 #include <linux/virtio_config.h>
 
 /* The ID for virtio_rng */
index e83b69346d2342fd2927278d40f98c4fb1afdff3..58334d4395167b9f3105cba86b0b68b60bca39d0 100644 (file)
@@ -44,6 +44,12 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
                NR_VM_EVENT_ITEMS
 };
 
+extern const struct seq_operations fragmentation_op;
+extern const struct seq_operations pagetypeinfo_op;
+extern const struct seq_operations zoneinfo_op;
+extern const struct seq_operations vmstat_op;
+extern int sysctl_stat_interval;
+
 #ifdef CONFIG_VM_EVENT_COUNTERS
 /*
  * Light weight per cpu counter implementation.
index 9448ffbdcbf62937047a69f1281116f133d5c079..14c0e91be9b5121f811a2375382d0096270b4486 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/mutex.h>
 #include <linux/console_struct.h>
 #include <linux/mm.h>
+#include <linux/consolemap.h>
 
 /*
  * Presently, a lot of graphics programs do not restore the contents of
@@ -54,6 +55,7 @@ void redraw_screen(struct vc_data *vc, int is_switch);
 struct tty_struct;
 int tioclinux(struct tty_struct *tty, unsigned long arg);
 
+#ifdef CONFIG_CONSOLE_TRANSLATIONS
 /* consolemap.c */
 
 struct unimapinit;
@@ -71,6 +73,23 @@ void con_free_unimap(struct vc_data *vc);
 void con_protect_unimap(struct vc_data *vc, int rdonly);
 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
 
+#define vc_translate(vc, c) ((vc)->vc_translate[(c) |                  \
+                                       (vc)->vc_toggle_meta ? 0x80 : 0])
+#else
+#define con_set_trans_old(arg) (0)
+#define con_get_trans_old(arg) (-EINVAL)
+#define con_set_trans_new(arg) (0)
+#define con_get_trans_new(arg) (-EINVAL)
+#define con_clear_unimap(vc, ui) (0)
+#define con_set_unimap(vc, ct, list) (0)
+#define con_set_default_unimap(vc) (0)
+#define con_copy_unimap(d, s) (0)
+#define con_get_unimap(vc, ct, uct, list) (-EINVAL)
+#define con_free_unimap(vc) do { ; } while (0)
+
+#define vc_translate(vc, c) (c)
+#endif
+
 /* vt.c */
 int vt_waitactive(int vt);
 void change_console(struct vc_data *new_vc);
index 542526c6e8ef118a057a2441429f79701f2b320d..5c158c477ac76c688cc53fa17bc61bae4e04dd43 100644 (file)
@@ -179,6 +179,8 @@ __create_workqueue_key(const char *name, int singlethread,
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
 extern int queue_work(struct workqueue_struct *wq, struct work_struct *work);
+extern int queue_work_on(int cpu, struct workqueue_struct *wq,
+                       struct work_struct *work);
 extern int queue_delayed_work(struct workqueue_struct *wq,
                        struct delayed_work *work, unsigned long delay);
 extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
@@ -188,6 +190,7 @@ extern void flush_workqueue(struct workqueue_struct *wq);
 extern void flush_scheduled_work(void);
 
 extern int schedule_work(struct work_struct *work);
+extern int schedule_work_on(int cpu, struct work_struct *work);
 extern int schedule_delayed_work(struct delayed_work *work, unsigned long delay);
 extern int schedule_delayed_work_on(int cpu, struct delayed_work *work,
                                        unsigned long delay);
@@ -198,6 +201,8 @@ extern int keventd_up(void);
 extern void init_workqueues(void);
 int execute_in_process_context(work_func_t fn, struct execute_work *);
 
+extern int flush_work(struct work_struct *work);
+
 extern int cancel_work_sync(struct work_struct *work);
 
 /*
index db8823d45a7d7936fc855706787bfce855cf723c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,26 +0,0 @@
-/*
- */
-
-#ifndef AUDIOCHIP_H
-#define AUDIOCHIP_H
-
-enum audiochip {
-       AUDIO_CHIP_NONE,
-       AUDIO_CHIP_UNKNOWN,
-       /* Provided by video chip */
-       AUDIO_CHIP_INTERNAL,
-       /* Provided by tvaudio.c */
-       AUDIO_CHIP_TDA8425,
-       AUDIO_CHIP_TEA6300,
-       AUDIO_CHIP_TEA6420,
-       AUDIO_CHIP_TDA9840,
-       AUDIO_CHIP_TDA985X,
-       AUDIO_CHIP_TDA9874,
-       AUDIO_CHIP_PIC16C54,
-       /* Provided by msp3400.c */
-       AUDIO_CHIP_MSP34XX,
-       /* Provided by wm8775.c */
-       AUDIO_CHIP_WM8775
-};
-
-#endif /* AUDIOCHIP_H */
index 89c442eb884930b2f5f92de6e2da78ddd7845771..1d104096619cf78d779e573c6a6fb1795117e81c 100644 (file)
@@ -2,6 +2,7 @@
 #define __SAA7146_VV__
 
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/saa7146.h>
 #include <media/videobuf-dma-sg.h>
 
index 5660ea24996b42f0634c5fb0a6267131d36fca25..a8ad75a9152a7e609f0be55d8f804f0e9b72c21f 100644 (file)
@@ -3,7 +3,12 @@
 
 struct tveeprom {
        u32 has_radio;
-       u32 has_ir;     /* bit 0: IR receiver present, bit 1: IR transmitter (blaster) present. -1 == unknown */
+       /* If has_ir == 0, then it is unknown what the IR capabilities are,
+          otherwise:
+          bit 0: 1 (= IR capabilities are known)
+          bit 1: IR receiver present
+          bit 2: IR transmitter (blaster) present */
+       u32 has_ir;
        u32 has_MAC_address; /* 0: no MAC, 1: MAC present, 2: unknown */
 
        u32 tuner_type;
index 2a527742701a2232090cc7e35334ebac12601b9d..41b509babf3f4e895878118fd799b1b4d8e664cd 100644 (file)
@@ -90,7 +90,10 @@ enum {
        /* module m52790: just ident 52790 */
        V4L2_IDENT_M52790 = 52790,
 
-       /* module msp34xx: reserved range 34000-34999 */
+       /* module msp3400: reserved range 34000-34999 and 44000-44999 */
+       V4L2_IDENT_MSPX4XX  = 34000, /* generic MSPX4XX identifier, only
+                                       use internally (tveeprom.c). */
+
        V4L2_IDENT_MSP3400B = 34002,
        V4L2_IDENT_MSP3410B = 34102,
 
@@ -142,7 +145,7 @@ enum {
        V4L2_IDENT_MSP3457G = 34577,
        V4L2_IDENT_MSP3467G = 34677,
 
-       /* module msp44xx: reserved range 44000-44999 */
+       /* module msp3400: reserved range 34000-34999 and 44000-44999 */
        V4L2_IDENT_MSP4400G = 44007,
        V4L2_IDENT_MSP4410G = 44107,
        V4L2_IDENT_MSP4420G = 44207,
index 020d05758bd8b951a352aabc043b0312de827800..07d3a9a575d1422c1d1b1cb16b7cf58e137111f2 100644 (file)
 
 #include <media/v4l2-dev.h>
 
-/* v4l debugging and diagnostics */
-
-/* Debug bitmask flags to be used on V4L2 */
-#define V4L2_DEBUG_IOCTL     0x01
-#define V4L2_DEBUG_IOCTL_ARG 0x02
-
 /* Common printk constucts for v4l-i2c drivers. These macros create a unique
    prefix consisting of the driver name, the adapter number and the i2c
    address. */
                        v4l_client_printk(KERN_DEBUG, client, fmt , ## arg); \
        } while (0)
 
+/* ------------------------------------------------------------------------- */
 
-/* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */
-#define v4l_print_ioctl(name, cmd)              \
-       do {                                     \
-               printk(KERN_DEBUG "%s: ", name); \
-               v4l_printk_ioctl(cmd);           \
-       } while (0)
+/* Priority helper functions */
 
-/* Use this macro in I2C drivers where 'client' is the struct i2c_client
-   pointer */
-#define v4l_i2c_print_ioctl(client, cmd)                  \
-       do {                                               \
-               v4l_client_printk(KERN_DEBUG, client, ""); \
-               v4l_printk_ioctl(cmd);                     \
-       } while (0)
+struct v4l2_prio_state {
+       atomic_t prios[4];
+};
+int v4l2_prio_init(struct v4l2_prio_state *global);
+int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
+                    enum v4l2_priority new);
+int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local);
+int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local);
+enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
+int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
 
 /* ------------------------------------------------------------------------- */
 
index 33f379b1ecfeac87bfaf3d0c3cdf92137e8af802..2745e1afc72267f7be541e7c52ea05371d33d451 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _V4L2_DEV_H
 #define _V4L2_DEV_H
 
-#define OBSOLETE_OWNER   1 /* to be removed soon */
 #define OBSOLETE_DEVDATA 1 /* to be removed soon */
 
 #include <linux/poll.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/compiler.h> /* need __user */
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-#include <linux/videodev.h>
-#else
 #include <linux/videodev2.h>
-#endif
 
 #define VIDEO_MAJOR    81
 /* Minor device allocation */
 #define VFL_TYPE_RADIO         2
 #define VFL_TYPE_VTX           3
 
-/*  Video standard functions  */
-extern const char *v4l2_norm_to_name(v4l2_std_id id);
-extern int v4l2_video_std_construct(struct v4l2_standard *vs,
-                                   int id, const char *name);
-/* Prints the ioctl in a human-readable format */
-extern void v4l_printk_ioctl(unsigned int cmd);
-
-/* prority handling */
-struct v4l2_prio_state {
-       atomic_t prios[4];
-};
-int v4l2_prio_init(struct v4l2_prio_state *global);
-int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
-                    enum v4l2_priority new);
-int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local);
-int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local);
-enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
-int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
-
-/* names for fancy debug output */
-extern const char *v4l2_field_names[];
-extern const char *v4l2_type_names[];
-
-/*  Compatibility layer interface  --  v4l1-compat module */
-typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
-                          unsigned int cmd, void *arg);
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
-                              int cmd, void *arg, v4l2_kioctl driver_ioctl);
-#else
-#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL
-#endif
-
-/* 32 Bits compatibility layer for 64 bits processors */
-extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
-                               unsigned long arg);
+struct v4l2_ioctl_callbacks;
 
 /*
  * Newer version of video_device, handled by videodev2.c
@@ -88,18 +48,17 @@ struct video_device
        const struct file_operations *fops;
 
        /* sysfs */
-       struct device class_dev;        /* v4l device */
-       struct device *dev;             /* device parent */
+       struct device dev;              /* v4l device */
+       struct device *parent;          /* device parent */
 
        /* device info */
        char name[32];
-       int type;       /* v4l1 */
-       int type2;      /* v4l2 */
+       int vfl_type;
        int minor;
-       /* attribute to diferentiate multiple indexs on one physical device */
+       /* attribute to differentiate multiple indices on one physical device */
        int index;
 
-       int debug;      /* Activates debug level*/
+       int debug;                      /* Activates debug level*/
 
        /* Video standard vars */
        v4l2_std_id tvnorms;            /* Supported tv norms */
@@ -109,285 +68,36 @@ struct video_device
        void (*release)(struct video_device *vfd);
 
        /* ioctl callbacks */
+       const struct v4l2_ioctl_ops *ioctl_ops;
 
-       /* VIDIOC_QUERYCAP handler */
-       int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);
-
-       /* Priority handling */
-       int (*vidioc_g_priority)   (struct file *file, void *fh,
-                                   enum v4l2_priority *p);
-       int (*vidioc_s_priority)   (struct file *file, void *fh,
-                                   enum v4l2_priority p);
-
-       /* VIDIOC_ENUM_FMT handlers */
-       int (*vidioc_enum_fmt_vid_cap)     (struct file *file, void *fh,
-                                           struct v4l2_fmtdesc *f);
-       int (*vidioc_enum_fmt_vid_overlay) (struct file *file, void *fh,
-                                           struct v4l2_fmtdesc *f);
-       int (*vidioc_enum_fmt_vid_out)     (struct file *file, void *fh,
-                                           struct v4l2_fmtdesc *f);
-#if 1
-       /* deprecated, will be removed in 2.6.28 */
-       int (*vidioc_enum_fmt_vbi_cap)     (struct file *file, void *fh,
-                                           struct v4l2_fmtdesc *f);
-#endif
-       int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
-                                           struct v4l2_fmtdesc *f);
-
-       /* VIDIOC_G_FMT handlers */
-       int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_g_fmt_vid_out)    (struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_g_fmt_vbi_cap)    (struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_g_fmt_vbi_out)    (struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_g_fmt_sliced_vbi_cap)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-
-       /* VIDIOC_S_FMT handlers */
-       int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_s_fmt_vid_out)    (struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_s_fmt_vbi_cap)    (struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_s_fmt_vbi_out)    (struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_s_fmt_sliced_vbi_cap)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-       int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
-
-       /* VIDIOC_TRY_FMT handlers */
-       int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
-                                         struct v4l2_format *f);
-       int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh,
-                                         struct v4l2_format *f);
-       int (*vidioc_try_fmt_vid_out)    (struct file *file, void *fh,
-                                         struct v4l2_format *f);
-       int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *fh,
-                                         struct v4l2_format *f);
-       int (*vidioc_try_fmt_vbi_cap)    (struct file *file, void *fh,
-                                         struct v4l2_format *f);
-       int (*vidioc_try_fmt_vbi_out)    (struct file *file, void *fh,
-                                         struct v4l2_format *f);
-       int (*vidioc_try_fmt_sliced_vbi_cap)(struct file *file, void *fh,
-                                         struct v4l2_format *f);
-       int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh,
-                                         struct v4l2_format *f);
-       int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
-                                         struct v4l2_format *f);
-
-       /* Buffer handlers */
-       int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
-       int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
-       int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
-       int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
-
-
-       int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-                       /* buffer type is struct vidio_mbuf * */
-       int (*vidiocgmbuf)  (struct file *file, void *fh, struct video_mbuf *p);
-#endif
-       int (*vidioc_g_fbuf)   (struct file *file, void *fh,
-                               struct v4l2_framebuffer *a);
-       int (*vidioc_s_fbuf)   (struct file *file, void *fh,
-                               struct v4l2_framebuffer *a);
-
-               /* Stream on/off */
-       int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i);
-       int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);
-
-               /* Standard handling
-                       ENUMSTD is handled by videodev.c
-                */
-       int (*vidioc_g_std) (struct file *file, void *fh, v4l2_std_id *norm);
-       int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
-       int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
-
-               /* Input handling */
-       int (*vidioc_enum_input)(struct file *file, void *fh,
-                                struct v4l2_input *inp);
-       int (*vidioc_g_input)   (struct file *file, void *fh, unsigned int *i);
-       int (*vidioc_s_input)   (struct file *file, void *fh, unsigned int i);
-
-               /* Output handling */
-       int (*vidioc_enum_output) (struct file *file, void *fh,
-                                 struct v4l2_output *a);
-       int (*vidioc_g_output)   (struct file *file, void *fh, unsigned int *i);
-       int (*vidioc_s_output)   (struct file *file, void *fh, unsigned int i);
-
-               /* Control handling */
-       int (*vidioc_queryctrl)        (struct file *file, void *fh,
-                                       struct v4l2_queryctrl *a);
-       int (*vidioc_g_ctrl)           (struct file *file, void *fh,
-                                       struct v4l2_control *a);
-       int (*vidioc_s_ctrl)           (struct file *file, void *fh,
-                                       struct v4l2_control *a);
-       int (*vidioc_g_ext_ctrls)      (struct file *file, void *fh,
-                                       struct v4l2_ext_controls *a);
-       int (*vidioc_s_ext_ctrls)      (struct file *file, void *fh,
-                                       struct v4l2_ext_controls *a);
-       int (*vidioc_try_ext_ctrls)    (struct file *file, void *fh,
-                                       struct v4l2_ext_controls *a);
-       int (*vidioc_querymenu)        (struct file *file, void *fh,
-                                       struct v4l2_querymenu *a);
-
-       /* Audio ioctls */
-       int (*vidioc_enumaudio)        (struct file *file, void *fh,
-                                       struct v4l2_audio *a);
-       int (*vidioc_g_audio)          (struct file *file, void *fh,
-                                       struct v4l2_audio *a);
-       int (*vidioc_s_audio)          (struct file *file, void *fh,
-                                       struct v4l2_audio *a);
-
-       /* Audio out ioctls */
-       int (*vidioc_enumaudout)       (struct file *file, void *fh,
-                                       struct v4l2_audioout *a);
-       int (*vidioc_g_audout)         (struct file *file, void *fh,
-                                       struct v4l2_audioout *a);
-       int (*vidioc_s_audout)         (struct file *file, void *fh,
-                                       struct v4l2_audioout *a);
-       int (*vidioc_g_modulator)      (struct file *file, void *fh,
-                                       struct v4l2_modulator *a);
-       int (*vidioc_s_modulator)      (struct file *file, void *fh,
-                                       struct v4l2_modulator *a);
-       /* Crop ioctls */
-       int (*vidioc_cropcap)          (struct file *file, void *fh,
-                                       struct v4l2_cropcap *a);
-       int (*vidioc_g_crop)           (struct file *file, void *fh,
-                                       struct v4l2_crop *a);
-       int (*vidioc_s_crop)           (struct file *file, void *fh,
-                                       struct v4l2_crop *a);
-       /* Compression ioctls */
-       int (*vidioc_g_jpegcomp)       (struct file *file, void *fh,
-                                       struct v4l2_jpegcompression *a);
-       int (*vidioc_s_jpegcomp)       (struct file *file, void *fh,
-                                       struct v4l2_jpegcompression *a);
-       int (*vidioc_g_enc_index)      (struct file *file, void *fh,
-                                       struct v4l2_enc_idx *a);
-       int (*vidioc_encoder_cmd)      (struct file *file, void *fh,
-                                       struct v4l2_encoder_cmd *a);
-       int (*vidioc_try_encoder_cmd)  (struct file *file, void *fh,
-                                       struct v4l2_encoder_cmd *a);
-
-       /* Stream type-dependent parameter ioctls */
-       int (*vidioc_g_parm)           (struct file *file, void *fh,
-                                       struct v4l2_streamparm *a);
-       int (*vidioc_s_parm)           (struct file *file, void *fh,
-                                       struct v4l2_streamparm *a);
-
-       /* Tuner ioctls */
-       int (*vidioc_g_tuner)          (struct file *file, void *fh,
-                                       struct v4l2_tuner *a);
-       int (*vidioc_s_tuner)          (struct file *file, void *fh,
-                                       struct v4l2_tuner *a);
-       int (*vidioc_g_frequency)      (struct file *file, void *fh,
-                                       struct v4l2_frequency *a);
-       int (*vidioc_s_frequency)      (struct file *file, void *fh,
-                                       struct v4l2_frequency *a);
-
-       /* Sliced VBI cap */
-       int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh,
-                                       struct v4l2_sliced_vbi_cap *a);
-
-       /* Log status ioctl */
-       int (*vidioc_log_status)       (struct file *file, void *fh);
-
-       int (*vidioc_s_hw_freq_seek)   (struct file *file, void *fh,
-                                       struct v4l2_hw_freq_seek *a);
-
-       /* Debugging ioctls */
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       int (*vidioc_g_register)       (struct file *file, void *fh,
-                                       struct v4l2_register *reg);
-       int (*vidioc_s_register)       (struct file *file, void *fh,
-                                       struct v4l2_register *reg);
-#endif
-       int (*vidioc_g_chip_ident)     (struct file *file, void *fh,
-                                       struct v4l2_chip_ident *chip);
-
-       /* For other private ioctls */
-       int (*vidioc_default)          (struct file *file, void *fh,
-                                       int cmd, void *arg);
-
-
-#ifdef OBSOLETE_OWNER /* to be removed soon */
-/* obsolete -- fops->owner is used instead */
-struct module *owner;
-/* dev->driver_data will be used instead some day.
-       * Use the video_{get|set}_drvdata() helper functions,
-       * so the switch over will be transparent for you.
-       * Or use {pci|usb}_{get|set}_drvdata() directly. */
-void *priv;
+#ifdef OBSOLETE_DEVDATA /* to be removed soon */
+       /* dev->driver_data will be used instead some day.
+        * Use the video_{get|set}_drvdata() helper functions,
+        * so the switch over will be transparent for you.
+        * Or use {pci|usb}_{get|set}_drvdata() directly. */
+       void *priv;
 #endif
 
-       /* for videodev.c intenal usage -- please don't touch */
+       /* for videodev.c internal usage -- please don't touch */
        int users;                     /* video_exclusive_{open|close} ... */
        struct mutex lock;             /* ... helper function uses these   */
 };
 
 /* Class-dev to video-device */
-#define to_video_device(cd) container_of(cd, struct video_device, class_dev)
+#define to_video_device(cd) container_of(cd, struct video_device, dev)
 
 /* Version 2 functions */
 extern int video_register_device(struct video_device *vfd, int type, int nr);
 int video_register_device_index(struct video_device *vfd, int type, int nr,
                                        int index);
 void video_unregister_device(struct video_device *);
-extern int video_ioctl2(struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg);
 
 /* helper functions to alloc / release struct video_device, the
    later can be used for video_device->release() */
 struct video_device *video_device_alloc(void);
 void video_device_release(struct video_device *vfd);
 
-/* Include support for obsoleted stuff */
-extern int video_usercopy(struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg,
-                         int (*func)(struct inode *inode, struct file *file,
-                                     unsigned int cmd, void *arg));
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-#include <linux/mm.h>
-
-static inline int __must_check
-video_device_create_file(struct video_device *vfd,
-                        struct device_attribute *attr)
-{
-       int ret = device_create_file(&vfd->class_dev, attr);
-       if (ret < 0)
-               printk(KERN_WARNING "%s error: %d\n", __func__, ret);
-       return ret;
-}
-static inline void
-video_device_remove_file(struct video_device *vfd,
-                        struct device_attribute *attr)
-{
-       device_remove_file(&vfd->class_dev, attr);
-}
-
-#endif /* CONFIG_VIDEO_V4L1_COMPAT */
-
-#ifdef OBSOLETE_OWNER /* to be removed soon */
+#ifdef OBSOLETE_DEVDATA /* to be removed soon */
 /* helper functions to access driver private data. */
 static inline void *video_get_drvdata(struct video_device *dev)
 {
@@ -399,9 +109,6 @@ 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);
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
new file mode 100644 (file)
index 0000000..dc64046
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ *
+ *     V 4 L 2   D R I V E R   H E L P E R   A P I
+ *
+ * Moved from videodev2.h
+ *
+ *     Some commonly needed functions for drivers (v4l2-common.o module)
+ */
+#ifndef _V4L2_IOCTL_H
+#define _V4L2_IOCTL_H
+
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/compiler.h> /* need __user */
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+#include <linux/videodev.h>
+#else
+#include <linux/videodev2.h>
+#endif
+
+struct v4l2_ioctl_ops {
+       /* ioctl callbacks */
+
+       /* VIDIOC_QUERYCAP handler */
+       int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);
+
+       /* Priority handling */
+       int (*vidioc_g_priority)   (struct file *file, void *fh,
+                                   enum v4l2_priority *p);
+       int (*vidioc_s_priority)   (struct file *file, void *fh,
+                                   enum v4l2_priority p);
+
+       /* VIDIOC_ENUM_FMT handlers */
+       int (*vidioc_enum_fmt_vid_cap)     (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_vid_overlay) (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_vid_out)     (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+#if 1
+       /* deprecated, will be removed in 2.6.28 */
+       int (*vidioc_enum_fmt_vbi_cap)     (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+#endif
+       int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+
+       /* VIDIOC_G_FMT handlers */
+       int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vid_out)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vbi_cap)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vbi_out)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_sliced_vbi_cap)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+
+       /* VIDIOC_S_FMT handlers */
+       int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vid_out)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vbi_cap)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vbi_out)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_sliced_vbi_cap)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+
+       /* VIDIOC_TRY_FMT handlers */
+       int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vid_out)    (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vbi_cap)    (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vbi_out)    (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_sliced_vbi_cap)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+
+       /* Buffer handlers */
+       int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
+       int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
+       int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
+       int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
+
+
+       int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+                       /* buffer type is struct vidio_mbuf * */
+       int (*vidiocgmbuf)  (struct file *file, void *fh, struct video_mbuf *p);
+#endif
+       int (*vidioc_g_fbuf)   (struct file *file, void *fh,
+                               struct v4l2_framebuffer *a);
+       int (*vidioc_s_fbuf)   (struct file *file, void *fh,
+                               struct v4l2_framebuffer *a);
+
+               /* Stream on/off */
+       int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i);
+       int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);
+
+               /* Standard handling
+                       ENUMSTD is handled by videodev.c
+                */
+       int (*vidioc_g_std) (struct file *file, void *fh, v4l2_std_id *norm);
+       int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
+       int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
+
+               /* Input handling */
+       int (*vidioc_enum_input)(struct file *file, void *fh,
+                                struct v4l2_input *inp);
+       int (*vidioc_g_input)   (struct file *file, void *fh, unsigned int *i);
+       int (*vidioc_s_input)   (struct file *file, void *fh, unsigned int i);
+
+               /* Output handling */
+       int (*vidioc_enum_output) (struct file *file, void *fh,
+                                 struct v4l2_output *a);
+       int (*vidioc_g_output)   (struct file *file, void *fh, unsigned int *i);
+       int (*vidioc_s_output)   (struct file *file, void *fh, unsigned int i);
+
+               /* Control handling */
+       int (*vidioc_queryctrl)        (struct file *file, void *fh,
+                                       struct v4l2_queryctrl *a);
+       int (*vidioc_g_ctrl)           (struct file *file, void *fh,
+                                       struct v4l2_control *a);
+       int (*vidioc_s_ctrl)           (struct file *file, void *fh,
+                                       struct v4l2_control *a);
+       int (*vidioc_g_ext_ctrls)      (struct file *file, void *fh,
+                                       struct v4l2_ext_controls *a);
+       int (*vidioc_s_ext_ctrls)      (struct file *file, void *fh,
+                                       struct v4l2_ext_controls *a);
+       int (*vidioc_try_ext_ctrls)    (struct file *file, void *fh,
+                                       struct v4l2_ext_controls *a);
+       int (*vidioc_querymenu)        (struct file *file, void *fh,
+                                       struct v4l2_querymenu *a);
+
+       /* Audio ioctls */
+       int (*vidioc_enumaudio)        (struct file *file, void *fh,
+                                       struct v4l2_audio *a);
+       int (*vidioc_g_audio)          (struct file *file, void *fh,
+                                       struct v4l2_audio *a);
+       int (*vidioc_s_audio)          (struct file *file, void *fh,
+                                       struct v4l2_audio *a);
+
+       /* Audio out ioctls */
+       int (*vidioc_enumaudout)       (struct file *file, void *fh,
+                                       struct v4l2_audioout *a);
+       int (*vidioc_g_audout)         (struct file *file, void *fh,
+                                       struct v4l2_audioout *a);
+       int (*vidioc_s_audout)         (struct file *file, void *fh,
+                                       struct v4l2_audioout *a);
+       int (*vidioc_g_modulator)      (struct file *file, void *fh,
+                                       struct v4l2_modulator *a);
+       int (*vidioc_s_modulator)      (struct file *file, void *fh,
+                                       struct v4l2_modulator *a);
+       /* Crop ioctls */
+       int (*vidioc_cropcap)          (struct file *file, void *fh,
+                                       struct v4l2_cropcap *a);
+       int (*vidioc_g_crop)           (struct file *file, void *fh,
+                                       struct v4l2_crop *a);
+       int (*vidioc_s_crop)           (struct file *file, void *fh,
+                                       struct v4l2_crop *a);
+       /* Compression ioctls */
+       int (*vidioc_g_jpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_jpegcompression *a);
+       int (*vidioc_s_jpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_jpegcompression *a);
+       int (*vidioc_g_enc_index)      (struct file *file, void *fh,
+                                       struct v4l2_enc_idx *a);
+       int (*vidioc_encoder_cmd)      (struct file *file, void *fh,
+                                       struct v4l2_encoder_cmd *a);
+       int (*vidioc_try_encoder_cmd)  (struct file *file, void *fh,
+                                       struct v4l2_encoder_cmd *a);
+
+       /* Stream type-dependent parameter ioctls */
+       int (*vidioc_g_parm)           (struct file *file, void *fh,
+                                       struct v4l2_streamparm *a);
+       int (*vidioc_s_parm)           (struct file *file, void *fh,
+                                       struct v4l2_streamparm *a);
+
+       /* Tuner ioctls */
+       int (*vidioc_g_tuner)          (struct file *file, void *fh,
+                                       struct v4l2_tuner *a);
+       int (*vidioc_s_tuner)          (struct file *file, void *fh,
+                                       struct v4l2_tuner *a);
+       int (*vidioc_g_frequency)      (struct file *file, void *fh,
+                                       struct v4l2_frequency *a);
+       int (*vidioc_s_frequency)      (struct file *file, void *fh,
+                                       struct v4l2_frequency *a);
+
+       /* Sliced VBI cap */
+       int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh,
+                                       struct v4l2_sliced_vbi_cap *a);
+
+       /* Log status ioctl */
+       int (*vidioc_log_status)       (struct file *file, void *fh);
+
+       int (*vidioc_s_hw_freq_seek)   (struct file *file, void *fh,
+                                       struct v4l2_hw_freq_seek *a);
+
+       /* Debugging ioctls */
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       int (*vidioc_g_register)       (struct file *file, void *fh,
+                                       struct v4l2_register *reg);
+       int (*vidioc_s_register)       (struct file *file, void *fh,
+                                       struct v4l2_register *reg);
+#endif
+       int (*vidioc_g_chip_ident)     (struct file *file, void *fh,
+                                       struct v4l2_chip_ident *chip);
+
+       /* For other private ioctls */
+       int (*vidioc_default)          (struct file *file, void *fh,
+                                       int cmd, void *arg);
+};
+
+
+/* v4l debugging and diagnostics */
+
+/* Debug bitmask flags to be used on V4L2 */
+#define V4L2_DEBUG_IOCTL     0x01
+#define V4L2_DEBUG_IOCTL_ARG 0x02
+
+/* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */
+#define v4l_print_ioctl(name, cmd)              \
+       do {                                     \
+               printk(KERN_DEBUG "%s: ", name); \
+               v4l_printk_ioctl(cmd);           \
+       } while (0)
+
+/* Use this macro in I2C drivers where 'client' is the struct i2c_client
+   pointer */
+#define v4l_i2c_print_ioctl(client, cmd)                  \
+       do {                                               \
+               v4l_client_printk(KERN_DEBUG, client, ""); \
+               v4l_printk_ioctl(cmd);                     \
+       } while (0)
+
+/*  Video standard functions  */
+extern const char *v4l2_norm_to_name(v4l2_std_id id);
+extern int v4l2_video_std_construct(struct v4l2_standard *vs,
+                                   int id, const char *name);
+/* Prints the ioctl in a human-readable format */
+extern void v4l_printk_ioctl(unsigned int cmd);
+
+/* names for fancy debug output */
+extern const char *v4l2_field_names[];
+extern const char *v4l2_type_names[];
+
+/*  Compatibility layer interface  --  v4l1-compat module */
+typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
+                          unsigned int cmd, void *arg);
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
+                              int cmd, void *arg, v4l2_kioctl driver_ioctl);
+#else
+#define v4l_compat_translate_ioctl(inode, file, cmd, arg, ioctl) (-EINVAL)
+#endif
+
+/* 32 Bits compatibility layer for 64 bits processors */
+extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
+                               unsigned long arg);
+
+extern int video_ioctl2(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg);
+
+/* Include support for obsoleted stuff */
+extern int video_usercopy(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg,
+                         int (*func)(struct inode *inode, struct file *file,
+                                     unsigned int cmd, void *arg));
+
+#endif /* _V4L2_IOCTL_H */
index 9b1e2526b45ec2be45e58768f8ad3e801dc8dcd5..e17eda302b2d6c505902d8992f89712f362c9197 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: inftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $
- *
  * Parts of INFTL headers shared with userspace
  *
  */
index d508ef0ae091bd2c76b549461f3065679cb012dc..001685d7fa889b8fc8f325df833fc5140f9831a6 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: jffs2-user.h,v 1.1 2004/05/05 11:57:54 dwmw2 Exp $
- *
  * JFFS2 definitions for use in user space only
  */
 
index 615072c4da04415e8f14e02372078abb3d987941..c6c61cd5a254aaa03348924d0f0f864d8bf845e0 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
- *
  * Portions of MTD ABI definition which are shared by kernel and user space
  */
 
index 713f34d3e62e184aa6712ee53ac8308412d26593..170ceca3b2d08fb2c77362d8c061f6dc6d51f59d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $
- *
  * MTD ABI header for use by user space only.
  */
 
index b2bca18e7311bf1670271b3cf5988b0c933278fe..390d21c080aa98108d4cfef8bc5f10c2a1e84a0e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: nftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $
- *
  * Parts of NFTL headers shared with userspace
  *
  */
index a7421f130cc019a3e4144090a3848bf338f3be4b..ccdc562e444e316ec08ba15dc24da4685ed86766 100644 (file)
  * device should be used. A &struct ubi_rsvol_req object has to be properly
  * filled and a pointer to it has to be passed to the IOCTL.
  *
+ * UBI volumes re-name
+ * ~~~~~~~~~~~~~~~~~~~
+ *
+ * To re-name several volumes atomically at one go, the %UBI_IOCRNVOL command
+ * of the UBI character device should be used. A &struct ubi_rnvol_req object
+ * has to be properly filled and a pointer to it has to be passed to the IOCTL.
+ *
  * UBI volume update
  * ~~~~~~~~~~~~~~~~~
  *
 #define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t)
 /* Re-size an UBI volume */
 #define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req)
+/* Re-name volumes */
+#define UBI_IOCRNVOL _IOW(UBI_IOC_MAGIC, 3, struct ubi_rnvol_req)
 
 /* IOCTL commands of the UBI control character device */
 
 /* Maximum MTD device name length supported by UBI */
 #define MAX_UBI_MTD_NAME_LEN 127
 
+/* Maximum amount of UBI volumes that can be re-named at one go */
+#define UBI_MAX_RNVOL 32
+
 /*
  * UBI data type hint constants.
  *
@@ -176,20 +188,20 @@ enum {
  * it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages.
  *
  * But in rare cases, if this optimizes things, the VID header may be placed to
- * a different offset. For example, the boot-loader might do things faster if the
- * VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. As
- * the boot-loader would not normally need to read EC headers (unless it needs
- * UBI in RW mode), it might be faster to calculate ECC. This is weird example,
- * but it real-life example. So, in this example, @vid_hdr_offer would be
- * 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes
- * aligned, which is OK, as UBI is clever enough to realize this is 4th sub-page
- * of the first page and add needed padding.
+ * a different offset. For example, the boot-loader might do things faster if
+ * the VID header sits at the end of the first 2KiB NAND page with 4 sub-pages.
+ * As the boot-loader would not normally need to read EC headers (unless it
+ * needs UBI in RW mode), it might be faster to calculate ECC. This is weird
+ * example, but it real-life example. So, in this example, @vid_hdr_offer would
+ * be 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes
+ * aligned, which is OK, as UBI is clever enough to realize this is 4th
+ * sub-page of the first page and add needed padding.
  */
 struct ubi_attach_req {
        int32_t ubi_num;
        int32_t mtd_num;
        int32_t vid_hdr_offset;
-       uint8_t padding[12];
+       int8_t padding[12];
 };
 
 /**
@@ -250,6 +262,48 @@ struct ubi_rsvol_req {
        int32_t vol_id;
 } __attribute__ ((packed));
 
+/**
+ * struct ubi_rnvol_req - volumes re-name request.
+ * @count: count of volumes to re-name
+ * @padding1:  reserved for future, not used, has to be zeroed
+ * @vol_id: ID of the volume to re-name
+ * @name_len: name length
+ * @padding2:  reserved for future, not used, has to be zeroed
+ * @name: new volume name
+ *
+ * UBI allows to re-name up to %32 volumes at one go. The count of volumes to
+ * re-name is specified in the @count field. The ID of the volumes to re-name
+ * and the new names are specified in the @vol_id and @name fields.
+ *
+ * The UBI volume re-name operation is atomic, which means that should power cut
+ * happen, the volumes will have either old name or new name. So the possible
+ * use-cases of this command is atomic upgrade. Indeed, to upgrade, say, volumes
+ * A and B one may create temporary volumes %A1 and %B1 with the new contents,
+ * then atomically re-name A1->A and B1->B, in which case old %A and %B will
+ * be removed.
+ *
+ * If it is not desirable to remove old A and B, the re-name request has to
+ * contain 4 entries: A1->A, A->A1, B1->B, B->B1, in which case old A1 and B1
+ * become A and B, and old A and B will become A1 and B1.
+ *
+ * It is also OK to request: A1->A, A1->X, B1->B, B->Y, in which case old A1
+ * and B1 become A and B, and old A and B become X and Y.
+ *
+ * In other words, in case of re-naming into an existing volume name, the
+ * existing volume is removed, unless it is re-named as well at the same
+ * re-name request.
+ */
+struct ubi_rnvol_req {
+       int32_t count;
+       int8_t padding1[12];
+       struct {
+               int32_t vol_id;
+               int16_t name_len;
+               int8_t  padding2[2];
+               char    name[UBI_MAX_VOLUME_NAME + 1];
+       } ents[UBI_MAX_RNVOL];
+} __attribute__ ((packed));
+
 /**
  * struct ubi_leb_change_req - a data structure used in atomic logical
  *                             eraseblock change requests.
@@ -261,8 +315,8 @@ struct ubi_rsvol_req {
 struct ubi_leb_change_req {
        int32_t lnum;
        int32_t bytes;
-       uint8_t dtype;
-       uint8_t padding[7];
+       int8_t  dtype;
+       int8_t  padding[7];
 } __attribute__ ((packed));
 
 #endif /* __UBI_USER_H__ */
index 2dfa96b0575e638233475bd7af33a457319dd1c9..7dd29b7e461dead402b25d6b0fb27451d6896441 100644 (file)
@@ -51,7 +51,7 @@ struct unix_sock {
         struct sock            *peer;
         struct sock            *other;
        struct list_head        link;
-        atomic_t                inflight;
+        atomic_long_t           inflight;
         spinlock_t             lock;
        unsigned int            gc_candidate : 1;
         wait_queue_head_t       peer_wait;
index dfd8bf66ce274f99e486cf80794980f255b398ae..d364fd594ea4d7f2b3f088f460e2e2bc09ae6697 100644 (file)
@@ -262,7 +262,7 @@ static inline int ieee80211_get_radiotap_len(unsigned char *data)
        struct ieee80211_radiotap_header *hdr =
                (struct ieee80211_radiotap_header *)data;
 
-       return le16_to_cpu(get_unaligned(&hdr->it_len));
+       return get_unaligned_le16(&hdr->it_len);
 }
 
 #endif                         /* IEEE80211_RADIOTAP_H */
index b5862b975207950c91e0af30b361b63c86fcd0db..250e6ef025a460e16e58636645a71cd51dbce887 100644 (file)
@@ -188,6 +188,8 @@ extern int sysctl_ip_dynaddr;
 
 extern void ipfrag_init(void);
 
+extern void ip_static_sysctl_init(void);
+
 #ifdef CONFIG_INET
 #include <net/dst.h>
 
index 330b74e813a9b834d2cb8b7e155fac7e02e8685b..2a1092abaa078c790a5203887e503b3278b02245 100644 (file)
@@ -14,6 +14,12 @@ struct ipcomp_data {
 
 struct ip_comp_hdr;
 struct sk_buff;
+struct xfrm_state;
+
+int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb);
+int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb);
+void ipcomp_destroy(struct xfrm_state *x);
+int ipcomp_init_state(struct xfrm_state *x);
 
 static inline struct ip_comp_hdr *ip_comp_hdr(const struct sk_buff *skb)
 {
index 2d5c18514a2d2d3b3e77e0a0d141d07dafec0c6d..113028fb8f6610c912e57326dbaf6f4bd1c5c649 100644 (file)
@@ -608,6 +608,8 @@ extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
 extern struct ctl_table *ipv6_route_sysctl_init(struct net *net);
 extern int ipv6_sysctl_register(void);
 extern void ipv6_sysctl_unregister(void);
+extern int ipv6_static_sysctl_register(void);
+extern void ipv6_static_sysctl_unregister(void);
 #endif
 
 #endif /* __KERNEL__ */
index 3855620b78a9760081c590d44bf9794f0e993390..a8eb43cf0c7ed8fe895f901ddbc25f85bc608806 100644 (file)
@@ -38,7 +38,9 @@ struct net {
        struct proc_dir_entry   *proc_net;
        struct proc_dir_entry   *proc_net_stat;
 
-       struct list_head        sysctl_table_headers;
+#ifdef CONFIG_SYSCTL
+       struct ctl_table_set    sysctls;
+#endif
 
        struct net_device       *loopback_dev;          /* The loopback */
 
index 0c96e7bed5db39e7eff4718353697ce52e06df96..8d6e991ef4dfb79d2a8d75bd14cf4241bafbfc95 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
+#include <linux/bug.h>
 
 #include <net/sock.h>
 
@@ -170,7 +171,7 @@ static inline struct request_sock *reqsk_queue_remove(struct request_sock_queue
 {
        struct request_sock *req = queue->rskq_accept_head;
 
-       BUG_TRAP(req != NULL);
+       WARN_ON(req == NULL);
 
        queue->rskq_accept_head = req->dl_next;
        if (queue->rskq_accept_head == NULL)
@@ -185,7 +186,7 @@ static inline struct sock *reqsk_queue_get_child(struct request_sock_queue *queu
        struct request_sock *req = reqsk_queue_remove(queue);
        struct sock *child = req->sk;
 
-       BUG_TRAP(child != NULL);
+       WARN_ON(child == NULL);
 
        sk_acceptq_removed(parent);
        __reqsk_free(req);
index 3140cc500854064b647245366ee112115dea40e2..4f0d8c14736cba916799c7793848d8d42595483f 100644 (file)
@@ -204,6 +204,4 @@ static inline struct inet_peer *rt_get_peer(struct rtable *rt)
        return rt->peer;
 }
 
-extern ctl_table ipv4_route_table[];
-
 #endif /* _ROUTE_H */
index 90b529f7a154efdc26c02b43b7e591022b491987..936e333e7ce598e9fc46a7b5d96c9ad233a34924 100644 (file)
@@ -1590,7 +1590,7 @@ static inline int ib_dma_mapping_error(struct ib_device *dev, u64 dma_addr)
 {
        if (dev->dma_ops)
                return dev->dma_ops->mapping_error(dev, dma_addr);
-       return dma_mapping_error(dma_addr);
+       return dma_mapping_error(dev->dma_device, dma_addr);
 }
 
 /**
index 22bb2e7bab1a9ea7c879d60696854232f270a363..df7faf09d66f782f47fdfa845677a5177fdd6ada 100644 (file)
@@ -57,7 +57,9 @@ enum rdma_cm_event_type {
        RDMA_CM_EVENT_DISCONNECTED,
        RDMA_CM_EVENT_DEVICE_REMOVAL,
        RDMA_CM_EVENT_MULTICAST_JOIN,
-       RDMA_CM_EVENT_MULTICAST_ERROR
+       RDMA_CM_EVENT_MULTICAST_ERROR,
+       RDMA_CM_EVENT_ADDR_CHANGE,
+       RDMA_CM_EVENT_TIMEWAIT_EXIT
 };
 
 enum rdma_port_space {
index 00137a7769ee267f76679966cdb4e5e6005d9f8d..5c40cc537d4cc625a9ad94d76190405c52694379 100644 (file)
 #define VARIABLE_LENGTH_CMD   0x7f
 #define REPORT_LUNS           0xa0
 #define MAINTENANCE_IN        0xa3
+#define MAINTENANCE_OUT       0xa4
 #define MOVE_MEDIUM           0xa5
 #define EXCHANGE_MEDIUM       0xa6
 #define READ_12               0xa8
 #define        SAI_READ_CAPACITY_16  0x10
 /* values for maintenance in */
 #define MI_REPORT_TARGET_PGS  0x0a
+/* values for maintenance out */
+#define MO_SET_TARGET_PGS     0x0a
 
 /* Values for T10/04-262r7 */
 #define        ATA_16                0x85      /* 16-byte pass-thru */
index 66c944849d6b385f1e6d25fe81be0eff59e1b471..f9f6e793575c0b7114c3162b25e430978977d2eb 100644 (file)
@@ -77,6 +77,9 @@ struct scsi_cmnd {
        int allowed;
        int timeout_per_command;
 
+       unsigned char prot_op;
+       unsigned char prot_type;
+
        unsigned short cmd_len;
        enum dma_data_direction sc_data_direction;
 
@@ -87,6 +90,8 @@ struct scsi_cmnd {
 
        /* These elements define the operation we ultimately want to perform */
        struct scsi_data_buffer sdb;
+       struct scsi_data_buffer *prot_sdb;
+
        unsigned underflow;     /* Return error if less than
                                   this amount is transferred */
 
@@ -208,4 +213,85 @@ static inline int scsi_sg_copy_to_buffer(struct scsi_cmnd *cmd,
                                 buf, buflen);
 }
 
+/*
+ * The operations below are hints that tell the controller driver how
+ * to handle I/Os with DIF or similar types of protection information.
+ */
+enum scsi_prot_operations {
+       /* Normal I/O */
+       SCSI_PROT_NORMAL = 0,
+
+       /* OS-HBA: Protected, HBA-Target: Unprotected */
+       SCSI_PROT_READ_INSERT,
+       SCSI_PROT_WRITE_STRIP,
+
+       /* OS-HBA: Unprotected, HBA-Target: Protected */
+       SCSI_PROT_READ_STRIP,
+       SCSI_PROT_WRITE_INSERT,
+
+       /* OS-HBA: Protected, HBA-Target: Protected */
+       SCSI_PROT_READ_PASS,
+       SCSI_PROT_WRITE_PASS,
+
+       /* OS-HBA: Protected, HBA-Target: Protected, checksum conversion */
+       SCSI_PROT_READ_CONVERT,
+       SCSI_PROT_WRITE_CONVERT,
+};
+
+static inline void scsi_set_prot_op(struct scsi_cmnd *scmd, unsigned char op)
+{
+       scmd->prot_op = op;
+}
+
+static inline unsigned char scsi_get_prot_op(struct scsi_cmnd *scmd)
+{
+       return scmd->prot_op;
+}
+
+/*
+ * The controller usually does not know anything about the target it
+ * is communicating with.  However, when DIX is enabled the controller
+ * must be know target type so it can verify the protection
+ * information passed along with the I/O.
+ */
+enum scsi_prot_target_type {
+       SCSI_PROT_DIF_TYPE0 = 0,
+       SCSI_PROT_DIF_TYPE1,
+       SCSI_PROT_DIF_TYPE2,
+       SCSI_PROT_DIF_TYPE3,
+};
+
+static inline void scsi_set_prot_type(struct scsi_cmnd *scmd, unsigned char type)
+{
+       scmd->prot_type = type;
+}
+
+static inline unsigned char scsi_get_prot_type(struct scsi_cmnd *scmd)
+{
+       return scmd->prot_type;
+}
+
+static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd)
+{
+       return scmd->request->sector;
+}
+
+static inline unsigned scsi_prot_sg_count(struct scsi_cmnd *cmd)
+{
+       return cmd->prot_sdb ? cmd->prot_sdb->table.nents : 0;
+}
+
+static inline struct scatterlist *scsi_prot_sglist(struct scsi_cmnd *cmd)
+{
+       return cmd->prot_sdb ? cmd->prot_sdb->table.sgl : NULL;
+}
+
+static inline struct scsi_data_buffer *scsi_prot(struct scsi_cmnd *cmd)
+{
+       return cmd->prot_sdb;
+}
+
+#define scsi_for_each_prot_sg(cmd, sg, nseg, __i)              \
+       for_each_sg(scsi_prot_sglist(cmd), sg, nseg, __i)
+
 #endif /* _SCSI_SCSI_CMND_H */
index 6467f78b191fdf3334d714341c01c78044871175..291d56a19167db9b8688dbbba446d051daae3b17 100644 (file)
@@ -140,7 +140,8 @@ struct scsi_device {
        unsigned fix_capacity:1;        /* READ_CAPACITY is too high by 1 */
        unsigned guess_capacity:1;      /* READ_CAPACITY might be too high by 1 */
        unsigned retry_hwerror:1;       /* Retry HARDWARE_ERROR */
-       unsigned last_sector_bug:1;     /* Always read last sector in a 1 sector read */
+       unsigned last_sector_bug:1;     /* do not use multisector accesses on
+                                          SD_LAST_BUGGY_SECTORS */
 
        DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
        struct list_head event_list;    /* asserted events */
@@ -167,15 +168,22 @@ struct scsi_device {
        unsigned long           sdev_data[0];
 } __attribute__((aligned(sizeof(unsigned long))));
 
+struct scsi_dh_devlist {
+       char *vendor;
+       char *model;
+};
+
 struct scsi_device_handler {
        /* Used by the infrastructure */
        struct list_head list; /* list of scsi_device_handlers */
-       struct notifier_block nb;
 
        /* Filled by the hardware handler */
        struct module *module;
        const char *name;
+       const struct scsi_dh_devlist *devlist;
        int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *);
+       int (*attach)(struct scsi_device *);
+       void (*detach)(struct scsi_device *);
        int (*activate)(struct scsi_device *);
        int (*prep_fn)(struct scsi_device *, struct request *);
 };
@@ -416,6 +424,11 @@ static inline int scsi_device_enclosure(struct scsi_device *sdev)
        return sdev->inquiry[6] & (1<<6);
 }
 
+static inline int scsi_device_protection(struct scsi_device *sdev)
+{
+       return sdev->inquiry[5] & (1<<0);
+}
+
 #define MODULE_ALIAS_SCSI_DEVICE(type) \
        MODULE_ALIAS("scsi:t-" __stringify(type) "*")
 #define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x"
index 3ad2303d1a166ec69efb9350e63d8ec77444c565..33efce20c26c937c08a89380dd1949b9eed60806 100644 (file)
@@ -32,6 +32,7 @@ enum {
         */
        SCSI_DH_DEV_FAILED,     /* generic device error */
        SCSI_DH_DEV_TEMP_BUSY,
+       SCSI_DH_DEV_UNSUPP,     /* device handler not supported */
        SCSI_DH_DEVICE_MAX,     /* max device blkerr definition */
 
        /*
@@ -57,6 +58,8 @@ enum {
 #if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE)
 extern int scsi_dh_activate(struct request_queue *);
 extern int scsi_dh_handler_exist(const char *);
+extern int scsi_dh_attach(struct request_queue *, const char *);
+extern void scsi_dh_detach(struct request_queue *);
 #else
 static inline int scsi_dh_activate(struct request_queue *req)
 {
@@ -66,4 +69,12 @@ static inline int scsi_dh_handler_exist(const char *name)
 {
        return 0;
 }
+static inline int scsi_dh_attach(struct request_queue *req, const char *name)
+{
+       return SCSI_DH_NOSYS;
+}
+static inline void scsi_dh_detach(struct request_queue *q)
+{
+       return;
+}
 #endif
index 2a9add21267d7fddfc4f443b6d5f475eba65b31e..06a8790893ef60e15cdd100550134e698e6a5e2e 100644 (file)
@@ -74,7 +74,9 @@ struct scsi_eh_save {
        /* saved state */
        int result;
        enum dma_data_direction data_direction;
+       unsigned underflow;
        unsigned char cmd_len;
+       unsigned char prot_op;
        unsigned char *cmnd;
        struct scsi_data_buffer sdb;
        struct request *next_rq;
index a594bac4a77db2b5f311470cc2e2324d5cf6bedb..44a55d1bf530c070e86eb8381901a3ba63dfd51c 100644 (file)
@@ -547,7 +547,7 @@ struct Scsi_Host {
        unsigned int host_failed;          /* commands that failed. */
        unsigned int host_eh_scheduled;    /* EH scheduled without command */
     
-       unsigned short host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
+       unsigned int host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
        int resetting; /* if set, it means that last_reset is a valid value */
        unsigned long last_reset;
 
@@ -636,6 +636,10 @@ struct Scsi_Host {
         */
        unsigned int max_host_blocked;
 
+       /* Protection Information */
+       unsigned int prot_capabilities;
+       unsigned char prot_guard_type;
+
        /*
         * q used for scsi_tgt msgs, async events or any other requests that
         * need to be processed in userspace
@@ -756,6 +760,86 @@ extern struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
 extern void scsi_free_host_dev(struct scsi_device *);
 extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *);
 
+/*
+ * DIF defines the exchange of protection information between
+ * initiator and SBC block device.
+ *
+ * DIX defines the exchange of protection information between OS and
+ * initiator.
+ */
+enum scsi_host_prot_capabilities {
+       SHOST_DIF_TYPE1_PROTECTION = 1 << 0, /* T10 DIF Type 1 */
+       SHOST_DIF_TYPE2_PROTECTION = 1 << 1, /* T10 DIF Type 2 */
+       SHOST_DIF_TYPE3_PROTECTION = 1 << 2, /* T10 DIF Type 3 */
+
+       SHOST_DIX_TYPE0_PROTECTION = 1 << 3, /* DIX between OS and HBA only */
+       SHOST_DIX_TYPE1_PROTECTION = 1 << 4, /* DIX with DIF Type 1 */
+       SHOST_DIX_TYPE2_PROTECTION = 1 << 5, /* DIX with DIF Type 2 */
+       SHOST_DIX_TYPE3_PROTECTION = 1 << 6, /* DIX with DIF Type 3 */
+};
+
+/*
+ * SCSI hosts which support the Data Integrity Extensions must
+ * indicate their capabilities by setting the prot_capabilities using
+ * this call.
+ */
+static inline void scsi_host_set_prot(struct Scsi_Host *shost, unsigned int mask)
+{
+       shost->prot_capabilities = mask;
+}
+
+static inline unsigned int scsi_host_get_prot(struct Scsi_Host *shost)
+{
+       return shost->prot_capabilities;
+}
+
+static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type)
+{
+       switch (target_type) {
+       case 1: return shost->prot_capabilities & SHOST_DIF_TYPE1_PROTECTION;
+       case 2: return shost->prot_capabilities & SHOST_DIF_TYPE2_PROTECTION;
+       case 3: return shost->prot_capabilities & SHOST_DIF_TYPE3_PROTECTION;
+       }
+
+       return 0;
+}
+
+static inline unsigned int scsi_host_dix_capable(struct Scsi_Host *shost, unsigned int target_type)
+{
+       switch (target_type) {
+       case 0: return shost->prot_capabilities & SHOST_DIX_TYPE0_PROTECTION;
+       case 1: return shost->prot_capabilities & SHOST_DIX_TYPE1_PROTECTION;
+       case 2: return shost->prot_capabilities & SHOST_DIX_TYPE2_PROTECTION;
+       case 3: return shost->prot_capabilities & SHOST_DIX_TYPE3_PROTECTION;
+       }
+
+       return 0;
+}
+
+/*
+ * All DIX-capable initiators must support the T10-mandated CRC
+ * checksum.  Controllers can optionally implement the IP checksum
+ * scheme which has much lower impact on system performance.  Note
+ * that the main rationale for the checksum is to match integrity
+ * metadata with data.  Detecting bit errors are a job for ECC memory
+ * and buses.
+ */
+
+enum scsi_host_guard_type {
+       SHOST_DIX_GUARD_CRC = 1 << 0,
+       SHOST_DIX_GUARD_IP  = 1 << 1,
+};
+
+static inline void scsi_host_set_guard(struct Scsi_Host *shost, unsigned char type)
+{
+       shost->prot_guard_type = type;
+}
+
+static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost)
+{
+       return shost->prot_guard_type;
+}
+
 /* legacy interfaces */
 extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
 extern void scsi_unregister(struct Scsi_Host *);
index ed64862c4e18c13eaf5060679f42e5ec8f25556f..613173b5db6991040484908e1c0940c00f247d04 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef __ATMEL_LCDC_H__
 #define __ATMEL_LCDC_H__
 
+#include <linux/workqueue.h>
 
 /* Way LCD wires are connected to the chip:
  * Some Atmel chips use BGR color mode (instead of standard RGB)
@@ -37,6 +38,7 @@ struct atmel_lcdfb_info {
        struct fb_info          *info;
        void __iomem            *mmio;
        unsigned long           irq_base;
+       struct work_struct      task;
 
        unsigned int            guard_time;
        struct platform_device  *pdev;
diff --git a/include/video/ili9320.h b/include/video/ili9320.h
new file mode 100644 (file)
index 0000000..e5d1622
--- /dev/null
@@ -0,0 +1,201 @@
+/* include/video/ili9320.c
+ *
+ * ILI9320 LCD controller configuration control.
+ *
+ * Copyright 2007 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.
+*/
+
+#define ILI9320_REG(x) (x)
+
+#define ILI9320_INDEX                  ILI9320_REG(0x00)
+
+#define ILI9320_OSCILATION             ILI9320_REG(0x00)
+#define ILI9320_DRIVER                 ILI9320_REG(0x01)
+#define ILI9320_DRIVEWAVE              ILI9320_REG(0x02)
+#define ILI9320_ENTRYMODE              ILI9320_REG(0x03)
+#define ILI9320_RESIZING               ILI9320_REG(0x04)
+#define ILI9320_DISPLAY1               ILI9320_REG(0x07)
+#define ILI9320_DISPLAY2               ILI9320_REG(0x08)
+#define ILI9320_DISPLAY3               ILI9320_REG(0x09)
+#define ILI9320_DISPLAY4               ILI9320_REG(0x0A)
+#define ILI9320_RGB_IF1                        ILI9320_REG(0x0C)
+#define ILI9320_FRAMEMAKER             ILI9320_REG(0x0D)
+#define ILI9320_RGB_IF2                        ILI9320_REG(0x0F)
+
+#define ILI9320_POWER1                 ILI9320_REG(0x10)
+#define ILI9320_POWER2                 ILI9320_REG(0x11)
+#define ILI9320_POWER3                 ILI9320_REG(0x12)
+#define ILI9320_POWER4                 ILI9320_REG(0x13)
+#define ILI9320_GRAM_HORIZ_ADDR                ILI9320_REG(0x20)
+#define ILI9320_GRAM_VERT_ADD          ILI9320_REG(0x21)
+#define ILI9320_POWER7                 ILI9320_REG(0x29)
+#define ILI9320_FRAME_RATE_COLOUR      ILI9320_REG(0x2B)
+
+#define ILI9320_GAMMA1                 ILI9320_REG(0x30)
+#define ILI9320_GAMMA2                 ILI9320_REG(0x31)
+#define ILI9320_GAMMA3                 ILI9320_REG(0x32)
+#define ILI9320_GAMMA4                 ILI9320_REG(0x35)
+#define ILI9320_GAMMA5                 ILI9320_REG(0x36)
+#define ILI9320_GAMMA6                 ILI9320_REG(0x37)
+#define ILI9320_GAMMA7                 ILI9320_REG(0x38)
+#define ILI9320_GAMMA8                 ILI9320_REG(0x39)
+#define ILI9320_GAMMA9                 ILI9320_REG(0x3C)
+#define ILI9320_GAMMA10                        ILI9320_REG(0x3D)
+
+#define ILI9320_HORIZ_START            ILI9320_REG(0x50)
+#define ILI9320_HORIZ_END              ILI9320_REG(0x51)
+#define ILI9320_VERT_START             ILI9320_REG(0x52)
+#define ILI9320_VERT_END               ILI9320_REG(0x53)
+
+#define ILI9320_DRIVER2                        ILI9320_REG(0x60)
+#define ILI9320_BASE_IMAGE             ILI9320_REG(0x61)
+#define ILI9320_VERT_SCROLL            ILI9320_REG(0x6a)
+
+#define ILI9320_PARTIAL1_POSITION      ILI9320_REG(0x80)
+#define ILI9320_PARTIAL1_START         ILI9320_REG(0x81)
+#define ILI9320_PARTIAL1_END           ILI9320_REG(0x82)
+#define ILI9320_PARTIAL2_POSITION      ILI9320_REG(0x83)
+#define ILI9320_PARTIAL2_START         ILI9320_REG(0x84)
+#define ILI9320_PARTIAL2_END           ILI9320_REG(0x85)
+
+#define ILI9320_INTERFACE1             ILI9320_REG(0x90)
+#define ILI9320_INTERFACE2             ILI9320_REG(0x92)
+#define ILI9320_INTERFACE3             ILI9320_REG(0x93)
+#define ILI9320_INTERFACE4             ILI9320_REG(0x95)
+#define ILI9320_INTERFACE5             ILI9320_REG(0x97)
+#define ILI9320_INTERFACE6             ILI9320_REG(0x98)
+
+/* Register contents definitions. */
+
+#define ILI9320_OSCILATION_OSC         (1 << 0)
+
+#define ILI9320_DRIVER_SS              (1 << 8)
+#define ILI9320_DRIVER_SM              (1 << 10)
+
+#define ILI9320_DRIVEWAVE_EOR          (1 << 8)
+#define ILI9320_DRIVEWAVE_BC           (1 << 9)
+#define ILI9320_DRIVEWAVE_MUSTSET      (1 << 10)
+
+#define ILI9320_ENTRYMODE_AM           (1 << 3)
+#define ILI9320_ENTRYMODE_ID(x)                ((x) << 4)
+#define ILI9320_ENTRYMODE_ORG          (1 << 7)
+#define ILI9320_ENTRYMODE_HWM          (1 << 8)
+#define ILI9320_ENTRYMODE_BGR          (1 << 12)
+#define ILI9320_ENTRYMODE_DFM          (1 << 14)
+#define ILI9320_ENTRYMODE_TRI          (1 << 15)
+
+
+#define ILI9320_RESIZING_RSZ(x)                ((x) << 0)
+#define ILI9320_RESIZING_RCH(x)                ((x) << 4)
+#define ILI9320_RESIZING_RCV(x)                ((x) << 8)
+
+
+#define ILI9320_DISPLAY1_D(x)          ((x) << 0)
+#define ILI9320_DISPLAY1_CL            (1 << 3)
+#define ILI9320_DISPLAY1_DTE           (1 << 4)
+#define ILI9320_DISPLAY1_GON           (1 << 5)
+#define ILI9320_DISPLAY1_BASEE         (1 << 8)
+#define ILI9320_DISPLAY1_PTDE(x)       ((x) << 12)
+
+
+#define ILI9320_DISPLAY2_BP(x)         ((x) << 0)
+#define ILI9320_DISPLAY2_FP(x)         ((x) << 8)
+
+
+#define ILI9320_RGBIF1_RIM_RGB18       (0 << 0)
+#define ILI9320_RGBIF1_RIM_RGB16       (1 << 0)
+#define ILI9320_RGBIF1_RIM_RGB6                (2 << 0)
+
+#define ILI9320_RGBIF1_CLK_INT         (0 << 4)
+#define ILI9320_RGBIF1_CLK_RGBIF       (1 << 4)
+#define ILI9320_RGBIF1_CLK_VSYNC       (2 << 4)
+
+#define ILI9320_RGBIF1_RM              (1 << 8)
+
+#define ILI9320_RGBIF1_ENC_FRAMES(x)   (((x) - 1)<< 13)
+
+#define ILI9320_RGBIF2_DPL             (1 << 0)
+#define ILI9320_RGBIF2_EPL             (1 << 1)
+#define ILI9320_RGBIF2_HSPL            (1 << 3)
+#define ILI9320_RGBIF2_VSPL            (1 << 4)
+
+
+#define ILI9320_POWER1_SLP             (1 << 1)
+#define ILI9320_POWER1_DSTB            (1 << 2)
+#define ILI9320_POWER1_AP(x)           ((x) << 4)
+#define ILI9320_POWER1_APE             (1 << 7)
+#define ILI9320_POWER1_BT(x)           ((x) << 8)
+#define ILI9320_POWER1_SAP             (1 << 12)
+
+
+#define ILI9320_POWER2_VC(x)           ((x) << 0)
+#define ILI9320_POWER2_DC0(x)          ((x) << 4)
+#define ILI9320_POWER2_DC1(x)          ((x) << 8)
+
+
+#define ILI9320_POWER3_VRH(x)          ((x) << 0)
+#define ILI9320_POWER3_PON             (1 << 4)
+#define ILI9320_POWER3_VCMR            (1 << 8)
+
+
+#define ILI9320_POWER4_VREOUT(x)       ((x) << 8)
+
+
+#define ILI9320_DRIVER2_SCNL(x)                ((x) << 0)
+#define ILI9320_DRIVER2_NL(x)          ((x) << 8)
+#define ILI9320_DRIVER2_GS             (1 << 15)
+
+
+#define ILI9320_BASEIMAGE_REV          (1 << 0)
+#define ILI9320_BASEIMAGE_VLE          (1 << 1)
+#define ILI9320_BASEIMAGE_NDL          (1 << 2)
+
+
+#define ILI9320_INTERFACE4_RTNE(x)     (x)
+#define ILI9320_INTERFACE4_DIVE(x)     ((x) << 8)
+
+/* SPI interface definitions */
+
+#define ILI9320_SPI_IDCODE             (0x70)
+#define ILI9320_SPI_ID(x)              ((x) << 2)
+#define ILI9320_SPI_READ               (0x01)
+#define ILI9320_SPI_WRITE              (0x00)
+#define ILI9320_SPI_DATA               (0x02)
+#define ILI9320_SPI_INDEX              (0x00)
+
+/* platform data to pass configuration from lcd */
+
+enum ili9320_suspend {
+       ILI9320_SUSPEND_OFF,
+       ILI9320_SUSPEND_DEEP,
+};
+
+struct ili9320_platdata {
+       unsigned short  hsize;
+       unsigned short  vsize;
+
+       enum ili9320_suspend suspend;
+
+       /* set the reset line, 0 = reset asserted, 1 = normal */
+       void            (*reset)(unsigned int val);
+
+       unsigned short  entry_mode;
+       unsigned short  display2;
+       unsigned short  display3;
+       unsigned short  display4;
+       unsigned short  rgb_if1;
+       unsigned short  rgb_if2;
+       unsigned short  interface2;
+       unsigned short  interface3;
+       unsigned short  interface4;
+       unsigned short  interface5;
+       unsigned short  interface6;
+};
+
index a9e118a1cd1628cc0679e216bfbc8b5c137ef6de..38910da0ae59f083c27312674413c73e4a32034b 100644 (file)
 #define PCI_CHIP_NM2360 0x0006
 #define PCI_CHIP_NM2380 0x0016
 
-
-struct xtimings {
-       unsigned int pixclock;
-       unsigned int HDisplay;
-       unsigned int HSyncStart;
-       unsigned int HSyncEnd;
-       unsigned int HTotal;
-       unsigned int VDisplay;
-       unsigned int VSyncStart;
-       unsigned int VSyncEnd;
-       unsigned int VTotal;
-       unsigned int sync;
-       int dblscan;
-       int interlaced;
-};
-
-
 /* --------------------------------------------------------------------- */
 
 typedef volatile struct {
diff --git a/include/video/platform_lcd.h b/include/video/platform_lcd.h
new file mode 100644 (file)
index 0000000..ad3bdfe
--- /dev/null
@@ -0,0 +1,21 @@
+/* include/video/platform_lcd.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Generic platform-device LCD power control interface.
+ *
+ * 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.
+ *
+*/
+
+struct plat_lcd_data;
+struct fb_info;
+
+struct plat_lcd_data {
+       void    (*set_power)(struct plat_lcd_data *, unsigned int power);
+       int     (*match_fb)(struct plat_lcd_data *, struct fb_info *);
+};
+
index 200be255168191e32bff744c91839bca1a2b7f4a..b6ce19d1b61be4509b0d6fd2e014ebbb9251cd7e 100644 (file)
@@ -4,9 +4,9 @@
 #endif
 
 #if TRIDENTFB_DEBUG
-#define debug(f,a...)  printk("%s:" f,  __FUNCTION__ , ## a);mdelay(1000);
+#define debug(f, a...) printk("%s:" f,  __func__ , ## a);
 #else
-#define debug(f,a...)
+#define debug(f, a...)
 #endif
 
 #define output(f, a...) pr_info("tridentfb: " f, ## a)
@@ -24,7 +24,9 @@
 #define CYBER9397DVD   0x939A
 #define CYBER9520      0x9520
 #define CYBER9525DVD   0x9525
+#define TGUI9440       0x9440
 #define TGUI9660       0x9660
+#define PROVIDIA9685   0x9685
 #define IMAGE975       0x9750
 #define IMAGE985       0x9850
 #define BLADE3D                0x9880
 #define CYBERBLADEXPm8  0x9910
 #define CYBERBLADEXPm16 0x9930
 
-/* acceleration families */
-#define IMAGE  0
-#define BLADE  1
-#define XP     2
-
-#define is_image(id)   
-#define is_xp(id)      ((id == CYBERBLADEXPAi1) ||\
-                        (id == CYBERBLADEXPm8) ||\
-                        (id == CYBERBLADEXPm16)) 
-
-#define is_blade(id)   ((id == BLADE3D) ||\
-                        (id == CYBERBLADEE4) ||\
-                        (id == CYBERBLADEi7) ||\
-                        (id == CYBERBLADEi7D) ||\
-                        (id == CYBERBLADEi1) ||\
-                        (id == CYBERBLADEi1D) ||\
-                        (id == CYBERBLADEAi1) ||\
-                        (id == CYBERBLADEAi1D))
-
 /* these defines are for 'lcd' variable */
 #define LCD_STRETCH    0
 #define LCD_CENTER     1
 #define LCD_BIOS       2
 
-/* display types */
-#define DISPLAY_CRT    0
-#define DISPLAY_FP     1
-
-#define flatpanel (displaytype == DISPLAY_FP)
-
 /* General Registers */
 #define SPR    0x1F            /* Software Programming Register (videoram) */
 
 #define SKey 0x37
 #define SPKey 0x57
 
-/* 0x3x4 */
-#define CRTHTotal      0x00
-#define CRTHDispEnd    0x01
-#define CRTHBlankStart 0x02
-#define CRTHBlankEnd   0x03
-#define CRTHSyncStart  0x04
-#define CRTHSyncEnd    0x05
-
-#define CRTVTotal      0x06
-#define CRTVDispEnd    0x12
-#define CRTVBlankStart 0x15
-#define CRTVBlankEnd   0x16
-#define CRTVSyncStart  0x10
-#define CRTVSyncEnd    0x11
-
-#define CRTOverflow    0x07
-#define CRTPRowScan    0x08
-#define CRTMaxScanLine 0x09
-#define CRTModeControl 0x17
-#define CRTLineCompare 0x18
-
 /* 3x4 */
-#define StartAddrHigh 0x0C
-#define StartAddrLow 0x0D
-#define Offset 0x13
-#define Underline 0x14
-#define CRTCMode 0x17
 #define CRTCModuleTest 0x1E
 #define FIFOControl 0x20
 #define LinearAddReg 0x21
 #define BiosMode     0x5c
 #define BiosReg      0x5d
 
+/* Graphics Engine */
+#define STATUS 0x2120
+#define OLDCMD 0x2124
+#define DRAWFL 0x2128
+#define OLDCLR 0x212C
+#define OLDDST 0x2138
+#define OLDSRC 0x213C
+#define OLDDIM 0x2140
+#define CMD    0x2144
+#define ROP    0x2148
+#define COLOR  0x2160
+#define BGCOLOR        0x2164
+#define SRC1   0x2100
+#define SRC2   0x2104
+#define DST1   0x2108
+#define DST2   0x210C
+
+#define ROP_S  0xCC
+#define ROP_P  0xF0
+#define ROP_X  0x66
index a50bdfed2df7664eacbb4a655b07b381caf64d99..250e02c8f8f9b6f68e33a008b5cab014068b8902 100644 (file)
@@ -171,7 +171,7 @@ config BSD_PROCESS_ACCT_V3
          process and it's parent. Note that this file format is incompatible
          with previous v0/v1/v2 file formats, so you will need updated tools
          for processing it. A preliminary version of these tools is available
-         at <http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/>.
+         at <http://www.gnu.org/software/acct/>.
 
 config TASKSTATS
        bool "Export task/process statistics through netlink (EXPERIMENTAL)"
@@ -486,7 +486,7 @@ config PID_NS
        default n
        depends on NAMESPACES && EXPERIMENTAL
        help
-         Suport process id namespaces.  This allows having multiple
+         Support process id namespaces.  This allows having multiple
          process with the same pid as long as they are in different
          pid namespaces.  This is a building block of containers.
 
@@ -802,6 +802,10 @@ config PROC_PAGE_MONITOR
 
 endmenu                # General setup
 
+config HAVE_GENERIC_DMA_COHERENT
+       bool
+       default n
+
 config SLABINFO
        bool
        depends on PROC_FS
index a1de1bf3d6b9d5694cf71b4c4a9dc03193636b96..3715feb8446d5c84796310e975d4948fd88df9ea 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/fs.h>
+#include <linux/initrd.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs_sb.h>
@@ -22,7 +23,7 @@
 int __initdata rd_doload;      /* 1 = load RAM disk, 0 = don't load */
 
 int root_mountflags = MS_RDONLY | MS_SILENT;
-char * __initdata root_device_name;
+static char * __initdata root_device_name;
 static char __initdata saved_root_name[64];
 static int __initdata root_wait;
 
index 735705d137ff9beaf0f7866e7c804d7080183780..9aa968d5432937a3aeb799d87ff42e87dfb5c871 100644 (file)
@@ -11,7 +11,6 @@ void  change_floppy(char *fmt, ...);
 void  mount_block_root(char *name, int flags);
 void  mount_root(void);
 extern int root_mountflags;
-extern char *root_device_name;
 
 static inline int create_dev(char *name, dev_t dev)
 {
index 46dfd64ae8fb027cf74e1252b91b2919f81a1923..fedef93b586fad4146bf1f1cfd04dffbb012c0e1 100644 (file)
@@ -10,8 +10,6 @@
 
 #include "do_mounts.h"
 
-#define BUILD_CRAMDISK
-
 int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
 
 static int __init prompt_ramdisk(char *str)
@@ -162,14 +160,8 @@ int __init rd_load_image(char *from)
                goto done;
 
        if (nblocks == 0) {
-#ifdef BUILD_CRAMDISK
                if (crd_load(in_fd, out_fd) == 0)
                        goto successful_load;
-#else
-               printk(KERN_NOTICE
-                      "RAMDISK: Kernel does not support compressed "
-                      "RAM disk images\n");
-#endif
                goto done;
        }
 
@@ -267,8 +259,6 @@ int __init rd_load_disk(int n)
        return rd_load_image("/dev/root");
 }
 
-#ifdef BUILD_CRAMDISK
-
 /*
  * gzip declarations
  */
@@ -313,32 +303,11 @@ static int crd_infd, crd_outfd;
 
 static int  __init fill_inbuf(void);
 static void __init flush_window(void);
-static void __init *malloc(size_t size);
-static void __init free(void *where);
 static void __init error(char *m);
-static void __init gzip_mark(void **);
-static void __init gzip_release(void **);
-
-#include "../lib/inflate.c"
 
-static void __init *malloc(size_t size)
-{
-       return kmalloc(size, GFP_KERNEL);
-}
-
-static void __init free(void *where)
-{
-       kfree(where);
-}
-
-static void __init gzip_mark(void **ptr)
-{
-}
-
-static void __init gzip_release(void **ptr)
-{
-}
+#define NO_INFLATE_MALLOC
 
+#include "../lib/inflate.c"
 
 /* ===========================================================================
  * Fill the input buffer. This is called only when the buffer is empty
@@ -425,5 +394,3 @@ static int __init crd_load(int in_fd, int out_fd)
        kfree(window);
        return result;
 }
-
-#endif  /* BUILD_CRAMDISK */
index 8eeeccb328c9f984812941592258ebd72e5d96e6..644fc01ad5f05244f3f3012becffda2326b2b65d 100644 (file)
@@ -14,16 +14,6 @@ static void __init error(char *x)
                message = x;
 }
 
-static void __init *malloc(size_t size)
-{
-       return kmalloc(size, GFP_KERNEL);
-}
-
-static void __init free(void *where)
-{
-       kfree(where);
-}
-
 /* link hash */
 
 #define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
@@ -407,18 +397,10 @@ static long bytes_out;
 
 static void __init flush_window(void);
 static void __init error(char *m);
-static void __init gzip_mark(void **);
-static void __init gzip_release(void **);
 
-#include "../lib/inflate.c"
+#define NO_INFLATE_MALLOC
 
-static void __init gzip_mark(void **ptr)
-{
-}
-
-static void __init gzip_release(void **ptr)
-{
-}
+#include "../lib/inflate.c"
 
 /* ===========================================================================
  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
index 2769dc031c6222d077206619f755727f7433d3dd..20fdc9884b77184f1b77d5ca857305c8a0d8dd21 100644 (file)
@@ -87,8 +87,6 @@ extern void init_IRQ(void);
 extern void fork_init(unsigned long);
 extern void mca_init(void);
 extern void sbus_init(void);
-extern void pidhash_init(void);
-extern void pidmap_init(void);
 extern void prio_tree_init(void);
 extern void radix_tree_init(void);
 extern void free_initmem(void);
@@ -745,13 +743,13 @@ static void __init do_one_initcall(initcall_t fn)
 }
 
 
-extern initcall_t __initcall_start[], __initcall_end[];
+extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
 
 static void __init do_initcalls(void)
 {
        initcall_t *call;
 
-       for (call = __initcall_start; call < __initcall_end; call++)
+       for (call = __early_initcall_end; call < __initcall_end; call++)
                do_one_initcall(*call);
 
        /* Make sure there is no pending stuff from the initcall sequence */
@@ -776,24 +774,12 @@ static void __init do_basic_setup(void)
        do_initcalls();
 }
 
-static int __initdata nosoftlockup;
-
-static int __init nosoftlockup_setup(char *str)
-{
-       nosoftlockup = 1;
-       return 1;
-}
-__setup("nosoftlockup", nosoftlockup_setup);
-
 static void __init do_pre_smp_initcalls(void)
 {
-       extern int spawn_ksoftirqd(void);
+       initcall_t *call;
 
-       init_call_single_data();
-       migration_init();
-       spawn_ksoftirqd();
-       if (!nosoftlockup)
-               spawn_softlockup_task();
+       for (call = __initcall_start; call < __early_initcall_end; call++)
+               do_one_initcall(*call);
 }
 
 static void run_init_process(char *init_filename)
index 9d17d70ee02d0165e4f94e5eacda6ea7c808a469..52a8b98642b8fb78343dfd63e20d1f448acb5866 100644 (file)
 #include <linux/utsrelease.h>
 #include <linux/version.h>
 
+#ifndef CONFIG_KALLSYMS
 #define version(a) Version_ ## a
 #define version_string(a) version(a)
 
+extern int version_string(LINUX_VERSION_CODE);
 int version_string(LINUX_VERSION_CODE);
+#endif
 
 struct uts_namespace init_uts_ns = {
        .kref = {
index d3497465cc0a5aa461dabce18b0f7af4dc537cea..69bc85978ba0bb04f0f77745cfa842aea69b7c76 100644 (file)
@@ -27,15 +27,17 @@ static void *get_ipc(ctl_table *table)
 }
 
 /*
- * Routine that is called when a tunable has successfully been changed by
- * hand and it has a callback routine registered on the ipc namespace notifier
- * chain: we don't want such tunables to be recomputed anymore upon memory
- * add/remove or ipc namespace creation/removal.
- * They can come back to a recomputable state by being set to a <0 value.
+ * Routine that is called when the file "auto_msgmni" has successfully been
+ * written.
+ * Two values are allowed:
+ * 0: unregister msgmni's callback routine from the ipc namespace notifier
+ *    chain. This means that msgmni won't be recomputed anymore upon memory
+ *    add/remove or ipc namespace creation/removal.
+ * 1: register back the callback routine.
  */
-static void tunable_set_callback(int val)
+static void ipc_auto_callback(int val)
 {
-       if (val >= 0)
+       if (!val)
                unregister_ipcns_notifier(current->nsproxy->ipc_ns);
        else {
                /*
@@ -71,7 +73,12 @@ static int proc_ipc_callback_dointvec(ctl_table *table, int write,
        rc = proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
 
        if (write && !rc && lenp_bef == *lenp)
-               tunable_set_callback(*((int *)(ipc_table.data)));
+               /*
+                * Tunable has successfully been changed by hand. Disable its
+                * automatic adjustment. This simply requires unregistering
+                * the notifiers that trigger recalculation.
+                */
+               unregister_ipcns_notifier(current->nsproxy->ipc_ns);
 
        return rc;
 }
@@ -87,10 +94,39 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
                                        lenp, ppos);
 }
 
+static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
+       struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table ipc_table;
+       size_t lenp_bef = *lenp;
+       int oldval;
+       int rc;
+
+       memcpy(&ipc_table, table, sizeof(ipc_table));
+       ipc_table.data = get_ipc(table);
+       oldval = *((int *)(ipc_table.data));
+
+       rc = proc_dointvec_minmax(&ipc_table, write, filp, buffer, lenp, ppos);
+
+       if (write && !rc && lenp_bef == *lenp) {
+               int newval = *((int *)(ipc_table.data));
+               /*
+                * The file "auto_msgmni" has correctly been set.
+                * React by (un)registering the corresponding tunable, if the
+                * value has changed.
+                */
+               if (newval != oldval)
+                       ipc_auto_callback(newval);
+       }
+
+       return rc;
+}
+
 #else
 #define proc_ipc_doulongvec_minmax NULL
 #define proc_ipc_dointvec         NULL
 #define proc_ipc_callback_dointvec NULL
+#define proc_ipcauto_dointvec_minmax NULL
 #endif
 
 #ifdef CONFIG_SYSCTL_SYSCALL
@@ -142,14 +178,11 @@ static int sysctl_ipc_registered_data(ctl_table *table, int __user *name,
        rc = sysctl_ipc_data(table, name, nlen, oldval, oldlenp, newval,
                newlen);
 
-       if (newval && newlen && rc > 0) {
+       if (newval && newlen && rc > 0)
                /*
                 * Tunable has successfully been changed from userland
                 */
-               int *data = get_ipc(table);
-
-               tunable_set_callback(*data);
-       }
+               unregister_ipcns_notifier(current->nsproxy->ipc_ns);
 
        return rc;
 }
@@ -158,6 +191,9 @@ static int sysctl_ipc_registered_data(ctl_table *table, int __user *name,
 #define sysctl_ipc_registered_data NULL
 #endif
 
+static int zero;
+static int one = 1;
+
 static struct ctl_table ipc_kern_table[] = {
        {
                .ctl_name       = KERN_SHMMAX,
@@ -222,6 +258,16 @@ static struct ctl_table ipc_kern_table[] = {
                .proc_handler   = proc_ipc_dointvec,
                .strategy       = sysctl_ipc_data,
        },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "auto_msgmni",
+               .data           = &init_ipc_ns.auto_msgmni,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_ipcauto_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
        {}
 };
 
index 70ff09183f7ba73529842fbd9eabda0e3de72269..b9b31a4f77e114cff79eef3cd25e075a3dc8d871 100644 (file)
@@ -55,25 +55,35 @@ static int ipcns_callback(struct notifier_block *self,
 
 int register_ipcns_notifier(struct ipc_namespace *ns)
 {
+       int rc;
+
        memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
        ns->ipcns_nb.notifier_call = ipcns_callback;
        ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
-       return blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb);
+       rc = blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb);
+       if (!rc)
+               ns->auto_msgmni = 1;
+       return rc;
 }
 
 int cond_register_ipcns_notifier(struct ipc_namespace *ns)
 {
+       int rc;
+
        memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
        ns->ipcns_nb.notifier_call = ipcns_callback;
        ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
-       return blocking_notifier_chain_cond_register(&ipcns_chain,
+       rc = blocking_notifier_chain_cond_register(&ipcns_chain,
                                                        &ns->ipcns_nb);
+       if (!rc)
+               ns->auto_msgmni = 1;
+       return rc;
 }
 
-int unregister_ipcns_notifier(struct ipc_namespace *ns)
+void unregister_ipcns_notifier(struct ipc_namespace *ns)
 {
-       return blocking_notifier_chain_unregister(&ipcns_chain,
-                                               &ns->ipcns_nb);
+       blocking_notifier_chain_unregister(&ipcns_chain, &ns->ipcns_nb);
+       ns->auto_msgmni = 0;
 }
 
 int ipcns_notify(unsigned long val)
index 3e84b958186b5d043ef34c706ff4036433f93c8b..96fb36cd9874cb26b242933178426244d1ed7e13 100644 (file)
@@ -207,7 +207,7 @@ static int mqueue_get_sb(struct file_system_type *fs_type,
        return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt);
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
 
@@ -314,15 +314,11 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
 *      through std routines)
 */
 static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
-                               size_t count, loff_t * off)
+                               size_t count, loff_t *off)
 {
        struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
        char buffer[FILENT_SIZE];
-       size_t slen;
-       loff_t o;
-
-       if (!count)
-               return 0;
+       ssize_t ret;
 
        spin_lock(&info->lock);
        snprintf(buffer, sizeof(buffer),
@@ -335,21 +331,14 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
                        pid_vnr(info->notify_owner));
        spin_unlock(&info->lock);
        buffer[sizeof(buffer)-1] = '\0';
-       slen = strlen(buffer)+1;
-
-       o = *off;
-       if (o > slen)
-               return 0;
-
-       if (o + count > slen)
-               count = slen - o;
 
-       if (copy_to_user(u_data, buffer + o, count))
-               return -EFAULT;
+       ret = simple_read_from_buffer(u_data, count, off, buffer,
+                               strlen(buffer));
+       if (ret <= 0)
+               return ret;
 
-       *off = o + count;
        filp->f_path.dentry->d_inode->i_atime = filp->f_path.dentry->d_inode->i_ctime = CURRENT_TIME;
-       return count;
+       return ret;
 }
 
 static int mqueue_flush_file(struct file *filp, fl_owner_t id)
@@ -649,7 +638,7 @@ static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
                return ERR_PTR(-EINVAL);
        }
 
-       if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) {
+       if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) {
                dput(dentry);
                mntput(mqueue_mnt);
                return ERR_PTR(-EACCES);
index e9418df5ff3ecf0c3cb3bb6e6fbac9de5fcac828..bf1bc36cb7ee62bc95021ba62253d5b667802952 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -272,9 +272,8 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
        ns->used_sems += nsems;
 
        sma->sem_base = (struct sem *) &sma[1];
-       /* sma->sem_pending = NULL; */
-       sma->sem_pending_last = &sma->sem_pending;
-       /* sma->undo = NULL; */
+       INIT_LIST_HEAD(&sma->sem_pending);
+       INIT_LIST_HEAD(&sma->list_id);
        sma->sem_nsems = nsems;
        sma->sem_ctime = get_seconds();
        sem_unlock(sma);
@@ -331,38 +330,6 @@ asmlinkage long sys_semget(key_t key, int nsems, int semflg)
        return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params);
 }
 
-/* Manage the doubly linked list sma->sem_pending as a FIFO:
- * insert new queue elements at the tail sma->sem_pending_last.
- */
-static inline void append_to_queue (struct sem_array * sma,
-                                   struct sem_queue * q)
-{
-       *(q->prev = sma->sem_pending_last) = q;
-       *(sma->sem_pending_last = &q->next) = NULL;
-}
-
-static inline void prepend_to_queue (struct sem_array * sma,
-                                    struct sem_queue * q)
-{
-       q->next = sma->sem_pending;
-       *(q->prev = &sma->sem_pending) = q;
-       if (q->next)
-               q->next->prev = &q->next;
-       else /* sma->sem_pending_last == &sma->sem_pending */
-               sma->sem_pending_last = &q->next;
-}
-
-static inline void remove_from_queue (struct sem_array * sma,
-                                     struct sem_queue * q)
-{
-       *(q->prev) = q->next;
-       if (q->next)
-               q->next->prev = q->prev;
-       else /* sma->sem_pending_last == &q->next */
-               sma->sem_pending_last = q->prev;
-       q->prev = NULL; /* mark as removed */
-}
-
 /*
  * Determine whether a sequence of semaphore operations would succeed
  * all at once. Return 0 if yes, 1 if need to sleep, else return error code.
@@ -438,16 +405,15 @@ static void update_queue (struct sem_array * sma)
        int error;
        struct sem_queue * q;
 
-       q = sma->sem_pending;
-       while(q) {
+       q = list_entry(sma->sem_pending.next, struct sem_queue, list);
+       while (&q->list != &sma->sem_pending) {
                error = try_atomic_semop(sma, q->sops, q->nsops,
                                         q->undo, q->pid);
 
                /* Does q->sleeper still need to sleep? */
                if (error <= 0) {
                        struct sem_queue *n;
-                       remove_from_queue(sma,q);
-                       q->status = IN_WAKEUP;
+
                        /*
                         * Continue scanning. The next operation
                         * that must be checked depends on the type of the
@@ -458,11 +424,26 @@ static void update_queue (struct sem_array * sma)
                         *   for semaphore values to become 0.
                         * - if the operation didn't modify the array,
                         *   then just continue.
+                        * The order of list_del() and reading ->next
+                        * is crucial: In the former case, the list_del()
+                        * must be done first [because we might be the
+                        * first entry in ->sem_pending], in the latter
+                        * case the list_del() must be done last
+                        * [because the list is invalid after the list_del()]
                         */
-                       if (q->alter)
-                               n = sma->sem_pending;
-                       else
-                               n = q->next;
+                       if (q->alter) {
+                               list_del(&q->list);
+                               n = list_entry(sma->sem_pending.next,
+                                               struct sem_queue, list);
+                       } else {
+                               n = list_entry(q->list.next, struct sem_queue,
+                                               list);
+                               list_del(&q->list);
+                       }
+
+                       /* wake up the waiting thread */
+                       q->status = IN_WAKEUP;
+
                        wake_up_process(q->sleeper);
                        /* hands-off: q will disappear immediately after
                         * writing q->status.
@@ -471,7 +452,7 @@ static void update_queue (struct sem_array * sma)
                        q->status = error;
                        q = n;
                } else {
-                       q = q->next;
+                       q = list_entry(q->list.next, struct sem_queue, list);
                }
        }
 }
@@ -491,7 +472,7 @@ static int count_semncnt (struct sem_array * sma, ushort semnum)
        struct sem_queue * q;
 
        semncnt = 0;
-       for (q = sma->sem_pending; q; q = q->next) {
+       list_for_each_entry(q, &sma->sem_pending, list) {
                struct sembuf * sops = q->sops;
                int nsops = q->nsops;
                int i;
@@ -503,13 +484,14 @@ static int count_semncnt (struct sem_array * sma, ushort semnum)
        }
        return semncnt;
 }
+
 static int count_semzcnt (struct sem_array * sma, ushort semnum)
 {
        int semzcnt;
        struct sem_queue * q;
 
        semzcnt = 0;
-       for (q = sma->sem_pending; q; q = q->next) {
+       list_for_each_entry(q, &sma->sem_pending, list) {
                struct sembuf * sops = q->sops;
                int nsops = q->nsops;
                int i;
@@ -522,35 +504,41 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)
        return semzcnt;
 }
 
+void free_un(struct rcu_head *head)
+{
+       struct sem_undo *un = container_of(head, struct sem_undo, rcu);
+       kfree(un);
+}
+
 /* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked
  * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex
  * remains locked on exit.
  */
 static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 {
-       struct sem_undo *un;
-       struct sem_queue *q;
+       struct sem_undo *un, *tu;
+       struct sem_queue *q, *tq;
        struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm);
 
-       /* Invalidate the existing undo structures for this semaphore set.
-        * (They will be freed without any further action in exit_sem()
-        * or during the next semop.)
-        */
-       for (un = sma->undo; un; un = un->id_next)
+       /* Free the existing undo structures for this semaphore set.  */
+       assert_spin_locked(&sma->sem_perm.lock);
+       list_for_each_entry_safe(un, tu, &sma->list_id, list_id) {
+               list_del(&un->list_id);
+               spin_lock(&un->ulp->lock);
                un->semid = -1;
+               list_del_rcu(&un->list_proc);
+               spin_unlock(&un->ulp->lock);
+               call_rcu(&un->rcu, free_un);
+       }
 
        /* Wake up all pending processes and let them fail with EIDRM. */
-       q = sma->sem_pending;
-       while(q) {
-               struct sem_queue *n;
-               /* lazy remove_from_queue: we are killing the whole queue */
-               q->prev = NULL;
-               n = q->next;
+       list_for_each_entry_safe(q, tq, &sma->sem_pending, list) {
+               list_del(&q->list);
+
                q->status = IN_WAKEUP;
                wake_up_process(q->sleeper); /* doesn't sleep */
                smp_wmb();
                q->status = -EIDRM;     /* hands-off q */
-               q = n;
        }
 
        /* Remove the semaphore set from the IDR */
@@ -763,9 +751,12 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 
                for (i = 0; i < nsems; i++)
                        sma->sem_base[i].semval = sem_io[i];
-               for (un = sma->undo; un; un = un->id_next)
+
+               assert_spin_locked(&sma->sem_perm.lock);
+               list_for_each_entry(un, &sma->list_id, list_id) {
                        for (i = 0; i < nsems; i++)
                                un->semadj[i] = 0;
+               }
                sma->sem_ctime = get_seconds();
                /* maybe some queued-up processes were waiting for this */
                update_queue(sma);
@@ -797,12 +788,15 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
        {
                int val = arg.val;
                struct sem_undo *un;
+
                err = -ERANGE;
                if (val > SEMVMX || val < 0)
                        goto out_unlock;
 
-               for (un = sma->undo; un; un = un->id_next)
+               assert_spin_locked(&sma->sem_perm.lock);
+               list_for_each_entry(un, &sma->list_id, list_id)
                        un->semadj[semnum] = 0;
+
                curr->semval = val;
                curr->sempid = task_tgid_vnr(current);
                sma->sem_ctime = get_seconds();
@@ -952,6 +946,8 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
                        return -ENOMEM;
                spin_lock_init(&undo_list->lock);
                atomic_set(&undo_list->refcnt, 1);
+               INIT_LIST_HEAD(&undo_list->list_proc);
+
                current->sysvsem.undo_list = undo_list;
        }
        *undo_listp = undo_list;
@@ -960,25 +956,27 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
 
 static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
 {
-       struct sem_undo **last, *un;
+       struct sem_undo *walk;
 
-       last = &ulp->proc_list;
-       un = *last;
-       while(un != NULL) {
-               if(un->semid==semid)
-                       break;
-               if(un->semid==-1) {
-                       *last=un->proc_next;
-                       kfree(un);
-               } else {
-                       last=&un->proc_next;
-               }
-               un=*last;
+       list_for_each_entry_rcu(walk, &ulp->list_proc, list_proc) {
+               if (walk->semid == semid)
+                       return walk;
        }
-       return un;
+       return NULL;
 }
 
-static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
+/**
+ * find_alloc_undo - Lookup (and if not present create) undo array
+ * @ns: namespace
+ * @semid: semaphore array id
+ *
+ * The function looks up (and if not present creates) the undo structure.
+ * The size of the undo structure depends on the size of the semaphore
+ * array, thus the alloc path is not that straightforward.
+ * Lifetime-rules: sem_undo is rcu-protected, on success, the function
+ * performs a rcu_read_lock().
+ */
+static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
 {
        struct sem_array *sma;
        struct sem_undo_list *ulp;
@@ -990,13 +988,16 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
        if (error)
                return ERR_PTR(error);
 
+       rcu_read_lock();
        spin_lock(&ulp->lock);
        un = lookup_undo(ulp, semid);
        spin_unlock(&ulp->lock);
        if (likely(un!=NULL))
                goto out;
+       rcu_read_unlock();
 
        /* no undo structure around - allocate one. */
+       /* step 1: figure out the size of the semaphore array */
        sma = sem_lock_check(ns, semid);
        if (IS_ERR(sma))
                return ERR_PTR(PTR_ERR(sma));
@@ -1004,37 +1005,45 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
        nsems = sma->sem_nsems;
        sem_getref_and_unlock(sma);
 
+       /* step 2: allocate new undo structure */
        new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
        if (!new) {
                sem_putref(sma);
                return ERR_PTR(-ENOMEM);
        }
-       new->semadj = (short *) &new[1];
-       new->semid = semid;
 
-       spin_lock(&ulp->lock);
-       un = lookup_undo(ulp, semid);
-       if (un) {
-               spin_unlock(&ulp->lock);
-               kfree(new);
-               sem_putref(sma);
-               goto out;
-       }
+       /* step 3: Acquire the lock on semaphore array */
        sem_lock_and_putref(sma);
        if (sma->sem_perm.deleted) {
                sem_unlock(sma);
-               spin_unlock(&ulp->lock);
                kfree(new);
                un = ERR_PTR(-EIDRM);
                goto out;
        }
-       new->proc_next = ulp->proc_list;
-       ulp->proc_list = new;
-       new->id_next = sma->undo;
-       sma->undo = new;
-       sem_unlock(sma);
+       spin_lock(&ulp->lock);
+
+       /*
+        * step 4: check for races: did someone else allocate the undo struct?
+        */
+       un = lookup_undo(ulp, semid);
+       if (un) {
+               kfree(new);
+               goto success;
+       }
+       /* step 5: initialize & link new undo structure */
+       new->semadj = (short *) &new[1];
+       new->ulp = ulp;
+       new->semid = semid;
+       assert_spin_locked(&ulp->lock);
+       list_add_rcu(&new->list_proc, &ulp->list_proc);
+       assert_spin_locked(&sma->sem_perm.lock);
+       list_add(&new->list_id, &sma->list_id);
        un = new;
+
+success:
        spin_unlock(&ulp->lock);
+       rcu_read_lock();
+       sem_unlock(sma);
 out:
        return un;
 }
@@ -1090,9 +1099,8 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
                        alter = 1;
        }
 
-retry_undos:
        if (undos) {
-               un = find_undo(ns, semid);
+               un = find_alloc_undo(ns, semid);
                if (IS_ERR(un)) {
                        error = PTR_ERR(un);
                        goto out_free;
@@ -1102,19 +1110,37 @@ retry_undos:
 
        sma = sem_lock_check(ns, semid);
        if (IS_ERR(sma)) {
+               if (un)
+                       rcu_read_unlock();
                error = PTR_ERR(sma);
                goto out_free;
        }
 
        /*
-        * semid identifiers are not unique - find_undo may have
+        * semid identifiers are not unique - find_alloc_undo may have
         * allocated an undo structure, it was invalidated by an RMID
-        * and now a new array with received the same id. Check and retry.
+        * and now a new array with received the same id. Check and fail.
+        * This case can be detected checking un->semid. The existance of
+        * "un" itself is guaranteed by rcu.
         */
-       if (un && un->semid == -1) {
-               sem_unlock(sma);
-               goto retry_undos;
+       error = -EIDRM;
+       if (un) {
+               if (un->semid == -1) {
+                       rcu_read_unlock();
+                       goto out_unlock_free;
+               } else {
+                       /*
+                        * rcu lock can be released, "un" cannot disappear:
+                        * - sem_lock is acquired, thus IPC_RMID is
+                        *   impossible.
+                        * - exit_sem is impossible, it always operates on
+                        *   current (or a dead task).
+                        */
+
+                       rcu_read_unlock();
+               }
        }
+
        error = -EFBIG;
        if (max >= sma->sem_nsems)
                goto out_unlock_free;
@@ -1138,17 +1164,15 @@ retry_undos:
         * task into the pending queue and go to sleep.
         */
                
-       queue.sma = sma;
        queue.sops = sops;
        queue.nsops = nsops;
        queue.undo = un;
        queue.pid = task_tgid_vnr(current);
-       queue.id = semid;
        queue.alter = alter;
        if (alter)
-               append_to_queue(sma ,&queue);
+               list_add_tail(&queue.list, &sma->sem_pending);
        else
-               prepend_to_queue(sma ,&queue);
+               list_add(&queue.list, &sma->sem_pending);
 
        queue.status = -EINTR;
        queue.sleeper = current;
@@ -1174,7 +1198,6 @@ retry_undos:
 
        sma = sem_lock(ns, semid);
        if (IS_ERR(sma)) {
-               BUG_ON(queue.prev != NULL);
                error = -EIDRM;
                goto out_free;
        }
@@ -1192,7 +1215,7 @@ retry_undos:
         */
        if (timeout && jiffies_left == 0)
                error = -EAGAIN;
-       remove_from_queue(sma,&queue);
+       list_del(&queue.list);
        goto out_unlock_free;
 
 out_unlock_free:
@@ -1243,56 +1266,62 @@ int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
  */
 void exit_sem(struct task_struct *tsk)
 {
-       struct sem_undo_list *undo_list;
-       struct sem_undo *u, **up;
-       struct ipc_namespace *ns;
+       struct sem_undo_list *ulp;
 
-       undo_list = tsk->sysvsem.undo_list;
-       if (!undo_list)
+       ulp = tsk->sysvsem.undo_list;
+       if (!ulp)
                return;
        tsk->sysvsem.undo_list = NULL;
 
-       if (!atomic_dec_and_test(&undo_list->refcnt))
+       if (!atomic_dec_and_test(&ulp->refcnt))
                return;
 
-       ns = tsk->nsproxy->ipc_ns;
-       /* There's no need to hold the semundo list lock, as current
-         * is the last task exiting for this undo list.
-        */
-       for (up = &undo_list->proc_list; (u = *up); *up = u->proc_next, kfree(u)) {
+       for (;;) {
                struct sem_array *sma;
-               int nsems, i;
-               struct sem_undo *un, **unp;
+               struct sem_undo *un;
                int semid;
-              
-               semid = u->semid;
+               int i;
 
-               if(semid == -1)
-                       continue;
-               sma = sem_lock(ns, semid);
+               rcu_read_lock();
+               un = list_entry(rcu_dereference(ulp->list_proc.next),
+                                       struct sem_undo, list_proc);
+               if (&un->list_proc == &ulp->list_proc)
+                       semid = -1;
+                else
+                       semid = un->semid;
+               rcu_read_unlock();
+
+               if (semid == -1)
+                       break;
+
+               sma = sem_lock_check(tsk->nsproxy->ipc_ns, un->semid);
+
+               /* exit_sem raced with IPC_RMID, nothing to do */
                if (IS_ERR(sma))
                        continue;
 
-               if (u->semid == -1)
-                       goto next_entry;
+               un = lookup_undo(ulp, semid);
+               if (un == NULL) {
+                       /* exit_sem raced with IPC_RMID+semget() that created
+                        * exactly the same semid. Nothing to do.
+                        */
+                       sem_unlock(sma);
+                       continue;
+               }
 
-               BUG_ON(sem_checkid(sma, u->semid));
+               /* remove un from the linked lists */
+               assert_spin_locked(&sma->sem_perm.lock);
+               list_del(&un->list_id);
 
-               /* remove u from the sma->undo list */
-               for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {
-                       if (u == un)
-                               goto found;
-               }
-               printk ("exit_sem undo list error id=%d\n", u->semid);
-               goto next_entry;
-found:
-               *unp = un->id_next;
-               /* perform adjustments registered in u */
-               nsems = sma->sem_nsems;
-               for (i = 0; i < nsems; i++) {
+               spin_lock(&ulp->lock);
+               list_del_rcu(&un->list_proc);
+               spin_unlock(&ulp->lock);
+
+               /* perform adjustments registered in un */
+               for (i = 0; i < sma->sem_nsems; i++) {
                        struct sem * semaphore = &sma->sem_base[i];
-                       if (u->semadj[i]) {
-                               semaphore->semval += u->semadj[i];
+                       if (un->semadj[i]) {
+                               semaphore->semval += un->semadj[i];
                                /*
                                 * Range checks of the new semaphore value,
                                 * not defined by sus:
@@ -1316,10 +1345,11 @@ found:
                sma->sem_otime = get_seconds();
                /* maybe some queued-up processes were waiting for this */
                update_queue(sma);
-next_entry:
                sem_unlock(sma);
+
+               call_rcu(&un->rcu, free_un);
        }
-       kfree(undo_list);
+       kfree(ulp);
 }
 
 #ifdef CONFIG_PROC_FS
index 790240cd067f60860957951db601dfb2fc81e373..e77ec698cf408c2344d302ac693814d44d411180 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -111,24 +111,9 @@ void __init shm_init (void)
                                IPC_SHM_IDS, sysvipc_shm_proc_show);
 }
 
-/*
- * shm_lock_(check_)down routines are called in the paths where the rw_mutex
- * is held to protect access to the idr tree.
- */
-static inline struct shmid_kernel *shm_lock_down(struct ipc_namespace *ns,
-                                               int id)
-{
-       struct kern_ipc_perm *ipcp = ipc_lock_down(&shm_ids(ns), id);
-
-       if (IS_ERR(ipcp))
-               return (struct shmid_kernel *)ipcp;
-
-       return container_of(ipcp, struct shmid_kernel, shm_perm);
-}
-
 /*
  * shm_lock_(check_) routines are called in the paths where the rw_mutex
- * is not held.
+ * is not necessarily held.
  */
 static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
 {
@@ -211,7 +196,7 @@ static void shm_close(struct vm_area_struct *vma)
 
        down_write(&shm_ids(ns).rw_mutex);
        /* remove from the list of attaches of the shm segment */
-       shp = shm_lock_down(ns, sfd->id);
+       shp = shm_lock(ns, sfd->id);
        BUG_ON(IS_ERR(shp));
        shp->shm_lprid = task_tgid_vnr(current);
        shp->shm_dtim = get_seconds();
@@ -577,7 +562,8 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
 
                if (is_file_hugepages(shp->shm_file)) {
                        struct address_space *mapping = inode->i_mapping;
-                       *rss += (HPAGE_SIZE/PAGE_SIZE)*mapping->nrpages;
+                       struct hstate *h = hstate_file(shp->shm_file);
+                       *rss += pages_per_huge_page(h) * mapping->nrpages;
                } else {
                        struct shmem_inode_info *info = SHMEM_I(inode);
                        spin_lock(&info->lock);
@@ -931,7 +917,7 @@ invalid:
 
 out_nattch:
        down_write(&shm_ids(ns).rw_mutex);
-       shp = shm_lock_down(ns, shmid);
+       shp = shm_lock(ns, shmid);
        BUG_ON(IS_ERR(shp));
        shp->shm_nattch--;
        if(shp->shm_nattch == 0 &&
index 3339177b336cae51c0b5a8085ad9a087891bb0b2..49b3ea615dc5fa991d921667f44172da02331a55 100644 (file)
@@ -688,10 +688,6 @@ void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
  * Look for an id in the ipc ids idr and lock the associated ipc object.
  *
  * The ipc object is locked on exit.
- *
- * This is the routine that should be called when the rw_mutex is not already
- * held, i.e. idr tree not protected: it protects the idr tree in read mode
- * during the idr_find().
  */
 
 struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
@@ -699,18 +695,13 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
        struct kern_ipc_perm *out;
        int lid = ipcid_to_idx(id);
 
-       down_read(&ids->rw_mutex);
-
        rcu_read_lock();
        out = idr_find(&ids->ipcs_idr, lid);
        if (out == NULL) {
                rcu_read_unlock();
-               up_read(&ids->rw_mutex);
                return ERR_PTR(-EINVAL);
        }
 
-       up_read(&ids->rw_mutex);
-
        spin_lock(&out->lock);
        
        /* ipc_rmid() may have already freed the ID while ipc_lock
@@ -725,56 +716,6 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
        return out;
 }
 
-/**
- * ipc_lock_down - Lock an ipc structure with rw_sem held
- * @ids: IPC identifier set
- * @id: ipc id to look for
- *
- * Look for an id in the ipc ids idr and lock the associated ipc object.
- *
- * The ipc object is locked on exit.
- *
- * This is the routine that should be called when the rw_mutex is already
- * held, i.e. idr tree protected.
- */
-
-struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *ids, int id)
-{
-       struct kern_ipc_perm *out;
-       int lid = ipcid_to_idx(id);
-
-       rcu_read_lock();
-       out = idr_find(&ids->ipcs_idr, lid);
-       if (out == NULL) {
-               rcu_read_unlock();
-               return ERR_PTR(-EINVAL);
-       }
-
-       spin_lock(&out->lock);
-
-       /*
-        * No need to verify that the structure is still valid since the
-        * rw_mutex is held.
-        */
-       return out;
-}
-
-struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, int id)
-{
-       struct kern_ipc_perm *out;
-
-       out = ipc_lock_down(ids, id);
-       if (IS_ERR(out))
-               return out;
-
-       if (ipc_checkid(out, id)) {
-               ipc_unlock(out);
-               return ERR_PTR(-EIDRM);
-       }
-
-       return out;
-}
-
 struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id)
 {
        struct kern_ipc_perm *out;
@@ -846,7 +787,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
        int err;
 
        down_write(&ids->rw_mutex);
-       ipcp = ipc_lock_check_down(ids, id);
+       ipcp = ipc_lock_check(ids, id);
        if (IS_ERR(ipcp)) {
                err = PTR_ERR(ipcp);
                goto out_up;
index cdb966aebe0716e8375617431d5734ed45aa639f..3646b45a03c9366d0c1e9b25c950e0edcbaedeef 100644 (file)
@@ -102,11 +102,6 @@ void* ipc_rcu_alloc(int size);
 void ipc_rcu_getref(void *ptr);
 void ipc_rcu_putref(void *ptr);
 
-/*
- * ipc_lock_down: called with rw_mutex held
- * ipc_lock: called without that lock held
- */
-struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *, int);
 struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
 
 void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
@@ -155,7 +150,6 @@ static inline void ipc_unlock(struct kern_ipc_perm *perm)
        rcu_read_unlock();
 }
 
-struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, int id);
 struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id);
 int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
                        struct ipc_ops *ops, struct ipc_params *params);
index 2a202a846757f238cccb290033633e5778bd3bb9..382dd5a8b2d7f5dd97359895358610f2f4866595 100644 (file)
@@ -55,4 +55,4 @@ config HZ
        default 1000 if HZ_1000
 
 config SCHED_HRTICK
-       def_bool HIGH_RES_TIMERS
+       def_bool HIGH_RES_TIMERS && USE_GENERIC_SMP_HELPERS
index 15ab63ffe64d31634d59e1caeff8909043827e97..4e1d7df7c3e279af83ae70f2f70c9196044514f2 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
+obj-y     = sched.o fork.o exec_domain.o panic.o printk.o \
            cpu.o exit.o itimer.o time.o softirq.o resource.o \
            sysctl.o capability.o ptrace.o timer.o user.o \
            signal.o sys.o kmod.o workqueue.o pid.o \
@@ -24,6 +24,7 @@ CFLAGS_REMOVE_sched_clock.o = -pg
 CFLAGS_REMOVE_sched.o = -mno-spe -pg
 endif
 
+obj-$(CONFIG_PROFILING) += profile.o
 obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-y += time/
@@ -83,6 +84,7 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
 obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
 obj-$(CONFIG_MARKERS) += marker.o
 obj-$(CONFIG_LATENCYTOP) += latencytop.o
+obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
 obj-$(CONFIG_FTRACE) += trace/
 obj-$(CONFIG_TRACING) += trace/
 obj-$(CONFIG_SMP) += sched_cpupri.o
index 91e1cfd734d286f922597108e54065ef691d31b2..dd68b905941818df3253e6f60558a49b9fbf2ef4 100644 (file)
@@ -75,37 +75,39 @@ int acct_parm[3] = {4, 2, 30};
 /*
  * External references and all of the globals.
  */
-static void do_acct_process(struct pid_namespace *ns, struct file *);
+static void do_acct_process(struct bsd_acct_struct *acct,
+               struct pid_namespace *ns, struct file *);
 
 /*
  * This structure is used so that all the data protected by lock
  * can be placed in the same cache line as the lock.  This primes
  * the cache line to have the data after getting the lock.
  */
-struct acct_glbs {
-       spinlock_t              lock;
+struct bsd_acct_struct {
        volatile int            active;
        volatile int            needcheck;
        struct file             *file;
        struct pid_namespace    *ns;
        struct timer_list       timer;
+       struct list_head        list;
 };
 
-static struct acct_glbs acct_globals __cacheline_aligned =
-       {__SPIN_LOCK_UNLOCKED(acct_globals.lock)};
+static DEFINE_SPINLOCK(acct_lock);
+static LIST_HEAD(acct_list);
 
 /*
  * Called whenever the timer says to check the free space.
  */
-static void acct_timeout(unsigned long unused)
+static void acct_timeout(unsigned long x)
 {
-       acct_globals.needcheck = 1;
+       struct bsd_acct_struct *acct = (struct bsd_acct_struct *)x;
+       acct->needcheck = 1;
 }
 
 /*
  * Check the amount of free space and suspend/resume accordingly.
  */
-static int check_free_space(struct file *file)
+static int check_free_space(struct bsd_acct_struct *acct, struct file *file)
 {
        struct kstatfs sbuf;
        int res;
@@ -113,11 +115,11 @@ static int check_free_space(struct file *file)
        sector_t resume;
        sector_t suspend;
 
-       spin_lock(&acct_globals.lock);
-       res = acct_globals.active;
-       if (!file || !acct_globals.needcheck)
+       spin_lock(&acct_lock);
+       res = acct->active;
+       if (!file || !acct->needcheck)
                goto out;
-       spin_unlock(&acct_globals.lock);
+       spin_unlock(&acct_lock);
 
        /* May block */
        if (vfs_statfs(file->f_path.dentry, &sbuf))
@@ -136,35 +138,35 @@ static int check_free_space(struct file *file)
                act = 0;
 
        /*
-        * If some joker switched acct_globals.file under us we'ld better be
+        * If some joker switched acct->file under us we'ld better be
         * silent and _not_ touch anything.
         */
-       spin_lock(&acct_globals.lock);
-       if (file != acct_globals.file) {
+       spin_lock(&acct_lock);
+       if (file != acct->file) {
                if (act)
                        res = act>0;
                goto out;
        }
 
-       if (acct_globals.active) {
+       if (acct->active) {
                if (act < 0) {
-                       acct_globals.active = 0;
+                       acct->active = 0;
                        printk(KERN_INFO "Process accounting paused\n");
                }
        } else {
                if (act > 0) {
-                       acct_globals.active = 1;
+                       acct->active = 1;
                        printk(KERN_INFO "Process accounting resumed\n");
                }
        }
 
-       del_timer(&acct_globals.timer);
-       acct_globals.needcheck = 0;
-       acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ;
-       add_timer(&acct_globals.timer);
-       res = acct_globals.active;
+       del_timer(&acct->timer);
+       acct->needcheck = 0;
+       acct->timer.expires = jiffies + ACCT_TIMEOUT*HZ;
+       add_timer(&acct->timer);
+       res = acct->active;
 out:
-       spin_unlock(&acct_globals.lock);
+       spin_unlock(&acct_lock);
        return res;
 }
 
@@ -172,39 +174,41 @@ out:
  * Close the old accounting file (if currently open) and then replace
  * it with file (if non-NULL).
  *
- * NOTE: acct_globals.lock MUST be held on entry and exit.
+ * NOTE: acct_lock MUST be held on entry and exit.
  */
-static void acct_file_reopen(struct file *file)
+static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file,
+               struct pid_namespace *ns)
 {
        struct file *old_acct = NULL;
        struct pid_namespace *old_ns = NULL;
 
-       if (acct_globals.file) {
-               old_acct = acct_globals.file;
-               old_ns = acct_globals.ns;
-               del_timer(&acct_globals.timer);
-               acct_globals.active = 0;
-               acct_globals.needcheck = 0;
-               acct_globals.file = NULL;
+       if (acct->file) {
+               old_acct = acct->file;
+               old_ns = acct->ns;
+               del_timer(&acct->timer);
+               acct->active = 0;
+               acct->needcheck = 0;
+               acct->file = NULL;
+               acct->ns = NULL;
+               list_del(&acct->list);
        }
        if (file) {
-               acct_globals.file = file;
-               acct_globals.ns = get_pid_ns(task_active_pid_ns(current));
-               acct_globals.needcheck = 0;
-               acct_globals.active = 1;
+               acct->file = file;
+               acct->ns = ns;
+               acct->needcheck = 0;
+               acct->active = 1;
+               list_add(&acct->list, &acct_list);
                /* It's been deleted if it was used before so this is safe */
-               init_timer(&acct_globals.timer);
-               acct_globals.timer.function = acct_timeout;
-               acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ;
-               add_timer(&acct_globals.timer);
+               setup_timer(&acct->timer, acct_timeout, (unsigned long)acct);
+               acct->timer.expires = jiffies + ACCT_TIMEOUT*HZ;
+               add_timer(&acct->timer);
        }
        if (old_acct) {
                mnt_unpin(old_acct->f_path.mnt);
-               spin_unlock(&acct_globals.lock);
-               do_acct_process(old_ns, old_acct);
+               spin_unlock(&acct_lock);
+               do_acct_process(acct, old_ns, old_acct);
                filp_close(old_acct, NULL);
-               put_pid_ns(old_ns);
-               spin_lock(&acct_globals.lock);
+               spin_lock(&acct_lock);
        }
 }
 
@@ -212,6 +216,8 @@ static int acct_on(char *name)
 {
        struct file *file;
        int error;
+       struct pid_namespace *ns;
+       struct bsd_acct_struct *acct = NULL;
 
        /* Difference from BSD - they don't do O_APPEND */
        file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
@@ -228,18 +234,34 @@ static int acct_on(char *name)
                return -EIO;
        }
 
+       ns = task_active_pid_ns(current);
+       if (ns->bacct == NULL) {
+               acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL);
+               if (acct == NULL) {
+                       filp_close(file, NULL);
+                       return -ENOMEM;
+               }
+       }
+
        error = security_acct(file);
        if (error) {
+               kfree(acct);
                filp_close(file, NULL);
                return error;
        }
 
-       spin_lock(&acct_globals.lock);
+       spin_lock(&acct_lock);
+       if (ns->bacct == NULL) {
+               ns->bacct = acct;
+               acct = NULL;
+       }
+
        mnt_pin(file->f_path.mnt);
-       acct_file_reopen(file);
-       spin_unlock(&acct_globals.lock);
+       acct_file_reopen(ns->bacct, file, ns);
+       spin_unlock(&acct_lock);
 
        mntput(file->f_path.mnt); /* it's pinned, now give up active reference */
+       kfree(acct);
 
        return 0;
 }
@@ -269,11 +291,17 @@ asmlinkage long sys_acct(const char __user *name)
                error = acct_on(tmp);
                putname(tmp);
        } else {
+               struct bsd_acct_struct *acct;
+
+               acct = task_active_pid_ns(current)->bacct;
+               if (acct == NULL)
+                       return 0;
+
                error = security_acct(NULL);
                if (!error) {
-                       spin_lock(&acct_globals.lock);
-                       acct_file_reopen(NULL);
-                       spin_unlock(&acct_globals.lock);
+                       spin_lock(&acct_lock);
+                       acct_file_reopen(acct, NULL, NULL);
+                       spin_unlock(&acct_lock);
                }
        }
        return error;
@@ -288,10 +316,16 @@ asmlinkage long sys_acct(const char __user *name)
  */
 void acct_auto_close_mnt(struct vfsmount *m)
 {
-       spin_lock(&acct_globals.lock);
-       if (acct_globals.file && acct_globals.file->f_path.mnt == m)
-               acct_file_reopen(NULL);
-       spin_unlock(&acct_globals.lock);
+       struct bsd_acct_struct *acct;
+
+       spin_lock(&acct_lock);
+restart:
+       list_for_each_entry(acct, &acct_list, list)
+               if (acct->file && acct->file->f_path.mnt == m) {
+                       acct_file_reopen(acct, NULL, NULL);
+                       goto restart;
+               }
+       spin_unlock(&acct_lock);
 }
 
 /**
@@ -303,12 +337,31 @@ void acct_auto_close_mnt(struct vfsmount *m)
  */
 void acct_auto_close(struct super_block *sb)
 {
-       spin_lock(&acct_globals.lock);
-       if (acct_globals.file &&
-           acct_globals.file->f_path.mnt->mnt_sb == sb) {
-               acct_file_reopen(NULL);
+       struct bsd_acct_struct *acct;
+
+       spin_lock(&acct_lock);
+restart:
+       list_for_each_entry(acct, &acct_list, list)
+               if (acct->file && acct->file->f_path.mnt->mnt_sb == sb) {
+                       acct_file_reopen(acct, NULL, NULL);
+                       goto restart;
+               }
+       spin_unlock(&acct_lock);
+}
+
+void acct_exit_ns(struct pid_namespace *ns)
+{
+       struct bsd_acct_struct *acct;
+
+       spin_lock(&acct_lock);
+       acct = ns->bacct;
+       if (acct != NULL) {
+               if (acct->file != NULL)
+                       acct_file_reopen(acct, NULL, NULL);
+
+               kfree(acct);
        }
-       spin_unlock(&acct_globals.lock);
+       spin_unlock(&acct_lock);
 }
 
 /*
@@ -425,7 +478,8 @@ static u32 encode_float(u64 value)
 /*
  *  do_acct_process does all actual work. Caller holds the reference to file.
  */
-static void do_acct_process(struct pid_namespace *ns, struct file *file)
+static void do_acct_process(struct bsd_acct_struct *acct,
+               struct pid_namespace *ns, struct file *file)
 {
        struct pacct_struct *pacct = &current->signal->pacct;
        acct_t ac;
@@ -440,7 +494,7 @@ static void do_acct_process(struct pid_namespace *ns, struct file *file)
         * First check to see if there is enough free_space to continue
         * the process accounting system.
         */
-       if (!check_free_space(file))
+       if (!check_free_space(acct, file))
                return;
 
        /*
@@ -577,34 +631,46 @@ void acct_collect(long exitcode, int group_dead)
        spin_unlock_irq(&current->sighand->siglock);
 }
 
-/**
- * acct_process - now just a wrapper around do_acct_process
- * @exitcode: task exit code
- *
- * handles process accounting for an exiting task
- */
-void acct_process(void)
+static void acct_process_in_ns(struct pid_namespace *ns)
 {
        struct file *file = NULL;
-       struct pid_namespace *ns;
+       struct bsd_acct_struct *acct;
 
+       acct = ns->bacct;
        /*
         * accelerate the common fastpath:
         */
-       if (!acct_globals.file)
+       if (!acct || !acct->file)
                return;
 
-       spin_lock(&acct_globals.lock);
-       file = acct_globals.file;
+       spin_lock(&acct_lock);
+       file = acct->file;
        if (unlikely(!file)) {
-               spin_unlock(&acct_globals.lock);
+               spin_unlock(&acct_lock);
                return;
        }
        get_file(file);
-       ns = get_pid_ns(acct_globals.ns);
-       spin_unlock(&acct_globals.lock);
+       spin_unlock(&acct_lock);
 
-       do_acct_process(ns, file);
+       do_acct_process(acct, ns, file);
        fput(file);
-       put_pid_ns(ns);
+}
+
+/**
+ * acct_process - now just a wrapper around acct_process_in_ns,
+ * which in turn is a wrapper around do_acct_process.
+ *
+ * handles process accounting for an exiting task
+ */
+void acct_process(void)
+{
+       struct pid_namespace *ns;
+
+       /*
+        * This loop is safe lockless, since current is still
+        * alive and holds its namespace, which in turn holds
+        * its parent.
+        */
+       for (ns = task_active_pid_ns(current); ns != NULL; ns = ns->parent)
+               acct_process_in_ns(ns);
 }
index 901e0fdc3fffa3b32fca26e0aa4e1985b244bd10..0101e847603e675d46cbfd53154455e3ba8943de 100644 (file)
@@ -115,11 +115,208 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
        return 0;
 }
 
+#ifndef CONFIG_SECURITY_FILE_CAPABILITIES
+
+/*
+ * Without filesystem capability support, we nominally support one process
+ * setting the capabilities of another
+ */
+static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
+                                    kernel_cap_t *pIp, kernel_cap_t *pPp)
+{
+       struct task_struct *target;
+       int ret;
+
+       spin_lock(&task_capability_lock);
+       read_lock(&tasklist_lock);
+
+       if (pid && pid != task_pid_vnr(current)) {
+               target = find_task_by_vpid(pid);
+               if (!target) {
+                       ret = -ESRCH;
+                       goto out;
+               }
+       } else
+               target = current;
+
+       ret = security_capget(target, pEp, pIp, pPp);
+
+out:
+       read_unlock(&tasklist_lock);
+       spin_unlock(&task_capability_lock);
+
+       return ret;
+}
+
+/*
+ * cap_set_pg - set capabilities for all processes in a given process
+ * group.  We call this holding task_capability_lock and tasklist_lock.
+ */
+static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective,
+                            kernel_cap_t *inheritable,
+                            kernel_cap_t *permitted)
+{
+       struct task_struct *g, *target;
+       int ret = -EPERM;
+       int found = 0;
+       struct pid *pgrp;
+
+       spin_lock(&task_capability_lock);
+       read_lock(&tasklist_lock);
+
+       pgrp = find_vpid(pgrp_nr);
+       do_each_pid_task(pgrp, PIDTYPE_PGID, g) {
+               target = g;
+               while_each_thread(g, target) {
+                       if (!security_capset_check(target, effective,
+                                                  inheritable, permitted)) {
+                               security_capset_set(target, effective,
+                                                   inheritable, permitted);
+                               ret = 0;
+                       }
+                       found = 1;
+               }
+       } while_each_pid_task(pgrp, PIDTYPE_PGID, g);
+
+       read_unlock(&tasklist_lock);
+       spin_unlock(&task_capability_lock);
+
+       if (!found)
+               ret = 0;
+       return ret;
+}
+
 /*
- * For sys_getproccap() and sys_setproccap(), any of the three
- * capability set pointers may be NULL -- indicating that that set is
- * uninteresting and/or not to be changed.
+ * cap_set_all - set capabilities for all processes other than init
+ * and self.  We call this holding task_capability_lock and tasklist_lock.
  */
+static inline int cap_set_all(kernel_cap_t *effective,
+                             kernel_cap_t *inheritable,
+                             kernel_cap_t *permitted)
+{
+       struct task_struct *g, *target;
+       int ret = -EPERM;
+       int found = 0;
+
+       spin_lock(&task_capability_lock);
+       read_lock(&tasklist_lock);
+
+       do_each_thread(g, target) {
+               if (target == current
+                   || is_container_init(target->group_leader))
+                       continue;
+               found = 1;
+               if (security_capset_check(target, effective, inheritable,
+                                         permitted))
+                       continue;
+               ret = 0;
+               security_capset_set(target, effective, inheritable, permitted);
+       } while_each_thread(g, target);
+
+       read_unlock(&tasklist_lock);
+       spin_unlock(&task_capability_lock);
+
+       if (!found)
+               ret = 0;
+
+       return ret;
+}
+
+/*
+ * Given the target pid does not refer to the current process we
+ * need more elaborate support... (This support is not present when
+ * filesystem capabilities are configured.)
+ */
+static inline int do_sys_capset_other_tasks(pid_t pid, kernel_cap_t *effective,
+                                           kernel_cap_t *inheritable,
+                                           kernel_cap_t *permitted)
+{
+       struct task_struct *target;
+       int ret;
+
+       if (!capable(CAP_SETPCAP))
+               return -EPERM;
+
+       if (pid == -1)            /* all procs other than current and init */
+               return cap_set_all(effective, inheritable, permitted);
+
+       else if (pid < 0)                    /* all procs in process group */
+               return cap_set_pg(-pid, effective, inheritable, permitted);
+
+       /* target != current */
+       spin_lock(&task_capability_lock);
+       read_lock(&tasklist_lock);
+
+       target = find_task_by_vpid(pid);
+       if (!target)
+               ret = -ESRCH;
+       else {
+               ret = security_capset_check(target, effective, inheritable,
+                                           permitted);
+
+               /* having verified that the proposed changes are legal,
+                  we now put them into effect. */
+               if (!ret)
+                       security_capset_set(target, effective, inheritable,
+                                           permitted);
+       }
+
+       read_unlock(&tasklist_lock);
+       spin_unlock(&task_capability_lock);
+
+       return ret;
+}
+
+#else /* ie., def CONFIG_SECURITY_FILE_CAPABILITIES */
+
+/*
+ * If we have configured with filesystem capability support, then the
+ * only thing that can change the capabilities of the current process
+ * is the current process. As such, we can't be in this code at the
+ * same time as we are in the process of setting capabilities in this
+ * process. The net result is that we can limit our use of locks to
+ * when we are reading the caps of another process.
+ */
+static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
+                                    kernel_cap_t *pIp, kernel_cap_t *pPp)
+{
+       int ret;
+
+       if (pid && (pid != task_pid_vnr(current))) {
+               struct task_struct *target;
+
+               spin_lock(&task_capability_lock);
+               read_lock(&tasklist_lock);
+
+               target = find_task_by_vpid(pid);
+               if (!target)
+                       ret = -ESRCH;
+               else
+                       ret = security_capget(target, pEp, pIp, pPp);
+
+               read_unlock(&tasklist_lock);
+               spin_unlock(&task_capability_lock);
+       } else
+               ret = security_capget(current, pEp, pIp, pPp);
+
+       return ret;
+}
+
+/*
+ * With filesystem capability support configured, the kernel does not
+ * permit the changing of capabilities in one process by another
+ * process. (CAP_SETPCAP has much less broad semantics when configured
+ * this way.)
+ */
+static inline int do_sys_capset_other_tasks(pid_t pid,
+                                           kernel_cap_t *effective,
+                                           kernel_cap_t *inheritable,
+                                           kernel_cap_t *permitted)
+{
+       return -EPERM;
+}
+
+#endif /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */
 
 /*
  * Atomically modify the effective capabilities returning the original
@@ -155,7 +352,6 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
 {
        int ret = 0;
        pid_t pid;
-       struct task_struct *target;
        unsigned tocopy;
        kernel_cap_t pE, pI, pP;
 
@@ -169,23 +365,7 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
        if (pid < 0)
                return -EINVAL;
 
-       spin_lock(&task_capability_lock);
-       read_lock(&tasklist_lock);
-
-       if (pid && pid != task_pid_vnr(current)) {
-               target = find_task_by_vpid(pid);
-               if (!target) {
-                       ret = -ESRCH;
-                       goto out;
-               }
-       } else
-               target = current;
-
-       ret = security_capget(target, &pE, &pI, &pP);
-
-out:
-       read_unlock(&tasklist_lock);
-       spin_unlock(&task_capability_lock);
+       ret = cap_get_target_pid(pid, &pE, &pI, &pP);
 
        if (!ret) {
                struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
@@ -216,7 +396,6 @@ out:
                 * before modification is attempted and the application
                 * fails.
                 */
-
                if (copy_to_user(dataptr, kdata, tocopy
                                 * sizeof(struct __user_cap_data_struct))) {
                        return -EFAULT;
@@ -226,70 +405,8 @@ out:
        return ret;
 }
 
-/*
- * cap_set_pg - set capabilities for all processes in a given process
- * group.  We call this holding task_capability_lock and tasklist_lock.
- */
-static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective,
-                             kernel_cap_t *inheritable,
-                             kernel_cap_t *permitted)
-{
-       struct task_struct *g, *target;
-       int ret = -EPERM;
-       int found = 0;
-       struct pid *pgrp;
-
-       pgrp = find_vpid(pgrp_nr);
-       do_each_pid_task(pgrp, PIDTYPE_PGID, g) {
-               target = g;
-               while_each_thread(g, target) {
-                       if (!security_capset_check(target, effective,
-                                                       inheritable,
-                                                       permitted)) {
-                               security_capset_set(target, effective,
-                                                       inheritable,
-                                                       permitted);
-                               ret = 0;
-                       }
-                       found = 1;
-               }
-       } while_each_pid_task(pgrp, PIDTYPE_PGID, g);
-
-       if (!found)
-               ret = 0;
-       return ret;
-}
-
-/*
- * cap_set_all - set capabilities for all processes other than init
- * and self.  We call this holding task_capability_lock and tasklist_lock.
- */
-static inline int cap_set_all(kernel_cap_t *effective,
-                              kernel_cap_t *inheritable,
-                              kernel_cap_t *permitted)
-{
-     struct task_struct *g, *target;
-     int ret = -EPERM;
-     int found = 0;
-
-     do_each_thread(g, target) {
-             if (target == current || is_container_init(target->group_leader))
-                     continue;
-             found = 1;
-            if (security_capset_check(target, effective, inheritable,
-                                               permitted))
-                    continue;
-            ret = 0;
-            security_capset_set(target, effective, inheritable, permitted);
-     } while_each_thread(g, target);
-
-     if (!found)
-            ret = 0;
-     return ret;
-}
-
 /**
- * sys_capset - set capabilities for a process or a group of processes
+ * sys_capset - set capabilities for a process or (*) a group of processes
  * @header: pointer to struct that contains capability version and
  *     target pid data
  * @data: pointer to struct that contains the effective, permitted,
@@ -313,7 +430,6 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
        struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
        unsigned i, tocopy;
        kernel_cap_t inheritable, permitted, effective;
-       struct task_struct *target;
        int ret;
        pid_t pid;
 
@@ -324,9 +440,6 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
        if (get_user(pid, &header->pid))
                return -EFAULT;
 
-       if (pid && pid != task_pid_vnr(current) && !capable(CAP_SETPCAP))
-               return -EPERM;
-
        if (copy_from_user(&kdata, data, tocopy
                           * sizeof(struct __user_cap_data_struct))) {
                return -EFAULT;
@@ -344,40 +457,31 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
                i++;
        }
 
-       spin_lock(&task_capability_lock);
-       read_lock(&tasklist_lock);
-
-       if (pid > 0 && pid != task_pid_vnr(current)) {
-               target = find_task_by_vpid(pid);
-               if (!target) {
-                       ret = -ESRCH;
-                       goto out;
-               }
-       } else
-               target = current;
-
-       ret = 0;
-
-       /* having verified that the proposed changes are legal,
-          we now put them into effect. */
-       if (pid < 0) {
-               if (pid == -1)  /* all procs other than current and init */
-                       ret = cap_set_all(&effective, &inheritable, &permitted);
+       if (pid && (pid != task_pid_vnr(current)))
+               ret = do_sys_capset_other_tasks(pid, &effective, &inheritable,
+                                               &permitted);
+       else {
+               /*
+                * This lock is required even when filesystem
+                * capability support is configured - it protects the
+                * sys_capget() call from returning incorrect data in
+                * the case that the targeted process is not the
+                * current one.
+                */
+               spin_lock(&task_capability_lock);
 
-               else            /* all procs in process group */
-                       ret = cap_set_pg(-pid, &effective, &inheritable,
-                                        &permitted);
-       } else {
-               ret = security_capset_check(target, &effective, &inheritable,
+               ret = security_capset_check(current, &effective, &inheritable,
                                            &permitted);
+               /*
+                * Having verified that the proposed changes are
+                * legal, we now put them into effect.
+                */
                if (!ret)
-                       security_capset_set(target, &effective, &inheritable,
+                       security_capset_set(current, &effective, &inheritable,
                                            &permitted);
+               spin_unlock(&task_capability_lock);
        }
 
-out:
-       read_unlock(&tasklist_lock);
-       spin_unlock(&task_capability_lock);
 
        return ret;
 }
index 15ac0e1e4f4de9dde14a6fe17e9b3d6e059a4baf..657f8f8d93a5fa947e79d0b8567a9c5288f425d9 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/delayacct.h>
 #include <linux/cgroupstats.h>
 #include <linux/hash.h>
+#include <linux/namei.h>
 
 #include <asm/atomic.h>
 
@@ -89,11 +90,7 @@ struct cgroupfs_root {
        /* Hierarchy-specific flags */
        unsigned long flags;
 
-       /* The path to use for release notifications. No locking
-        * between setting and use - so if userspace updates this
-        * while child cgroups exist, you could miss a
-        * notification. We ensure that it's always a valid
-        * NUL-terminated string */
+       /* The path to use for release notifications. */
        char release_agent_path[PATH_MAX];
 };
 
@@ -118,7 +115,7 @@ static int root_count;
  * extra work in the fork/exit path if none of the subsystems need to
  * be called.
  */
-static int need_forkexit_callback;
+static int need_forkexit_callback __read_mostly;
 static int need_mm_owner_callback __read_mostly;
 
 /* convenient tests for these bits */
@@ -220,7 +217,7 @@ static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[])
  * task until after the first call to cgroup_iter_start(). This
  * reduces the fork()/exit() overhead for people who have cgroups
  * compiled into their kernel but not actually in use */
-static int use_task_css_set_links;
+static int use_task_css_set_links __read_mostly;
 
 /* When we create or destroy a css_set, the operation simply
  * takes/releases a reference count on all the cgroups referenced
@@ -241,17 +238,20 @@ static int use_task_css_set_links;
  */
 static void unlink_css_set(struct css_set *cg)
 {
+       struct cg_cgroup_link *link;
+       struct cg_cgroup_link *saved_link;
+
        write_lock(&css_set_lock);
        hlist_del(&cg->hlist);
        css_set_count--;
-       while (!list_empty(&cg->cg_links)) {
-               struct cg_cgroup_link *link;
-               link = list_entry(cg->cg_links.next,
-                                 struct cg_cgroup_link, cg_link_list);
+
+       list_for_each_entry_safe(link, saved_link, &cg->cg_links,
+                                cg_link_list) {
                list_del(&link->cg_link_list);
                list_del(&link->cgrp_link_list);
                kfree(link);
        }
+
        write_unlock(&css_set_lock);
 }
 
@@ -363,15 +363,14 @@ static struct css_set *find_existing_css_set(
 static int allocate_cg_links(int count, struct list_head *tmp)
 {
        struct cg_cgroup_link *link;
+       struct cg_cgroup_link *saved_link;
        int i;
        INIT_LIST_HEAD(tmp);
        for (i = 0; i < count; i++) {
                link = kmalloc(sizeof(*link), GFP_KERNEL);
                if (!link) {
-                       while (!list_empty(tmp)) {
-                               link = list_entry(tmp->next,
-                                                 struct cg_cgroup_link,
-                                                 cgrp_link_list);
+                       list_for_each_entry_safe(link, saved_link, tmp,
+                                                cgrp_link_list) {
                                list_del(&link->cgrp_link_list);
                                kfree(link);
                        }
@@ -384,11 +383,10 @@ static int allocate_cg_links(int count, struct list_head *tmp)
 
 static void free_cg_links(struct list_head *tmp)
 {
-       while (!list_empty(tmp)) {
-               struct cg_cgroup_link *link;
-               link = list_entry(tmp->next,
-                                 struct cg_cgroup_link,
-                                 cgrp_link_list);
+       struct cg_cgroup_link *link;
+       struct cg_cgroup_link *saved_link;
+
+       list_for_each_entry_safe(link, saved_link, tmp, cgrp_link_list) {
                list_del(&link->cgrp_link_list);
                kfree(link);
        }
@@ -415,11 +413,11 @@ static struct css_set *find_css_set(
 
        /* First see if we already have a cgroup group that matches
         * the desired set */
-       write_lock(&css_set_lock);
+       read_lock(&css_set_lock);
        res = find_existing_css_set(oldcg, cgrp, template);
        if (res)
                get_css_set(res);
-       write_unlock(&css_set_lock);
+       read_unlock(&css_set_lock);
 
        if (res)
                return res;
@@ -507,10 +505,6 @@ static struct css_set *find_css_set(
  * knows that the cgroup won't be removed, as cgroup_rmdir()
  * needs that mutex.
  *
- * The cgroup_common_file_write handler for operations that modify
- * the cgroup hierarchy holds cgroup_mutex across the entire operation,
- * single threading all such cgroup modifications across the system.
- *
  * The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't
  * (usually) take cgroup_mutex.  These are the two most performance
  * critical pieces of code here.  The exception occurs on cgroup_exit(),
@@ -1093,6 +1087,8 @@ static void cgroup_kill_sb(struct super_block *sb) {
        struct cgroupfs_root *root = sb->s_fs_info;
        struct cgroup *cgrp = &root->top_cgroup;
        int ret;
+       struct cg_cgroup_link *link;
+       struct cg_cgroup_link *saved_link;
 
        BUG_ON(!root);
 
@@ -1112,10 +1108,9 @@ static void cgroup_kill_sb(struct super_block *sb) {
         * root cgroup
         */
        write_lock(&css_set_lock);
-       while (!list_empty(&cgrp->css_sets)) {
-               struct cg_cgroup_link *link;
-               link = list_entry(cgrp->css_sets.next,
-                                 struct cg_cgroup_link, cgrp_link_list);
+
+       list_for_each_entry_safe(link, saved_link, &cgrp->css_sets,
+                                cgrp_link_list) {
                list_del(&link->cg_link_list);
                list_del(&link->cgrp_link_list);
                kfree(link);
@@ -1281,18 +1276,14 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
 }
 
 /*
- * Attach task with pid 'pid' to cgroup 'cgrp'. Call with
- * cgroup_mutex, may take task_lock of task
+ * Attach task with pid 'pid' to cgroup 'cgrp'. Call with cgroup_mutex
+ * held. May take task_lock of task
  */
-static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf)
+static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
 {
-       pid_t pid;
        struct task_struct *tsk;
        int ret;
 
-       if (sscanf(pidbuf, "%d", &pid) != 1)
-               return -EIO;
-
        if (pid) {
                rcu_read_lock();
                tsk = find_task_by_vpid(pid);
@@ -1318,6 +1309,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf)
        return ret;
 }
 
+static int cgroup_tasks_write(struct cgroup *cgrp, struct cftype *cft, u64 pid)
+{
+       int ret;
+       if (!cgroup_lock_live_group(cgrp))
+               return -ENODEV;
+       ret = attach_task_by_pid(cgrp, pid);
+       cgroup_unlock();
+       return ret;
+}
+
 /* The various types of files and directories in a cgroup file system */
 enum cgroup_filetype {
        FILE_ROOT,
@@ -1327,12 +1328,54 @@ enum cgroup_filetype {
        FILE_RELEASE_AGENT,
 };
 
+/**
+ * cgroup_lock_live_group - take cgroup_mutex and check that cgrp is alive.
+ * @cgrp: the cgroup to be checked for liveness
+ *
+ * On success, returns true; the lock should be later released with
+ * cgroup_unlock(). On failure returns false with no lock held.
+ */
+bool cgroup_lock_live_group(struct cgroup *cgrp)
+{
+       mutex_lock(&cgroup_mutex);
+       if (cgroup_is_removed(cgrp)) {
+               mutex_unlock(&cgroup_mutex);
+               return false;
+       }
+       return true;
+}
+
+static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft,
+                                     const char *buffer)
+{
+       BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX);
+       if (!cgroup_lock_live_group(cgrp))
+               return -ENODEV;
+       strcpy(cgrp->root->release_agent_path, buffer);
+       cgroup_unlock();
+       return 0;
+}
+
+static int cgroup_release_agent_show(struct cgroup *cgrp, struct cftype *cft,
+                                    struct seq_file *seq)
+{
+       if (!cgroup_lock_live_group(cgrp))
+               return -ENODEV;
+       seq_puts(seq, cgrp->root->release_agent_path);
+       seq_putc(seq, '\n');
+       cgroup_unlock();
+       return 0;
+}
+
+/* A buffer size big enough for numbers or short strings */
+#define CGROUP_LOCAL_BUFFER_SIZE 64
+
 static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft,
                                struct file *file,
                                const char __user *userbuf,
                                size_t nbytes, loff_t *unused_ppos)
 {
-       char buffer[64];
+       char buffer[CGROUP_LOCAL_BUFFER_SIZE];
        int retval = 0;
        char *end;
 
@@ -1361,68 +1404,36 @@ static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft,
        return retval;
 }
 
-static ssize_t cgroup_common_file_write(struct cgroup *cgrp,
-                                          struct cftype *cft,
-                                          struct file *file,
-                                          const char __user *userbuf,
-                                          size_t nbytes, loff_t *unused_ppos)
+static ssize_t cgroup_write_string(struct cgroup *cgrp, struct cftype *cft,
+                                  struct file *file,
+                                  const char __user *userbuf,
+                                  size_t nbytes, loff_t *unused_ppos)
 {
-       enum cgroup_filetype type = cft->private;
-       char *buffer;
+       char local_buffer[CGROUP_LOCAL_BUFFER_SIZE];
        int retval = 0;
+       size_t max_bytes = cft->max_write_len;
+       char *buffer = local_buffer;
 
-       if (nbytes >= PATH_MAX)
+       if (!max_bytes)
+               max_bytes = sizeof(local_buffer) - 1;
+       if (nbytes >= max_bytes)
                return -E2BIG;
-
-       /* +1 for nul-terminator */
-       buffer = kmalloc(nbytes + 1, GFP_KERNEL);
-       if (buffer == NULL)
-               return -ENOMEM;
-
-       if (copy_from_user(buffer, userbuf, nbytes)) {
-               retval = -EFAULT;
-               goto out1;
+       /* Allocate a dynamic buffer if we need one */
+       if (nbytes >= sizeof(local_buffer)) {
+               buffer = kmalloc(nbytes + 1, GFP_KERNEL);
+               if (buffer == NULL)
+                       return -ENOMEM;
        }
-       buffer[nbytes] = 0;     /* nul-terminate */
-       strstrip(buffer);       /* strip -just- trailing whitespace */
-
-       mutex_lock(&cgroup_mutex);
+       if (nbytes && copy_from_user(buffer, userbuf, nbytes))
+               return -EFAULT;
 
-       /*
-        * This was already checked for in cgroup_file_write(), but
-        * check again now we're holding cgroup_mutex.
-        */
-       if (cgroup_is_removed(cgrp)) {
-               retval = -ENODEV;
-               goto out2;
-       }
-
-       switch (type) {
-       case FILE_TASKLIST:
-               retval = attach_task_by_pid(cgrp, buffer);
-               break;
-       case FILE_NOTIFY_ON_RELEASE:
-               clear_bit(CGRP_RELEASABLE, &cgrp->flags);
-               if (simple_strtoul(buffer, NULL, 10) != 0)
-                       set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
-               else
-                       clear_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
-               break;
-       case FILE_RELEASE_AGENT:
-               BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX);
-               strcpy(cgrp->root->release_agent_path, buffer);
-               break;
-       default:
-               retval = -EINVAL;
-               goto out2;
-       }
-
-       if (retval == 0)
+       buffer[nbytes] = 0;     /* nul-terminate */
+       strstrip(buffer);
+       retval = cft->write_string(cgrp, cft, buffer);
+       if (!retval)
                retval = nbytes;
-out2:
-       mutex_unlock(&cgroup_mutex);
-out1:
-       kfree(buffer);
+       if (buffer != local_buffer)
+               kfree(buffer);
        return retval;
 }
 
@@ -1438,6 +1449,8 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf,
                return cft->write(cgrp, cft, file, buf, nbytes, ppos);
        if (cft->write_u64 || cft->write_s64)
                return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos);
+       if (cft->write_string)
+               return cgroup_write_string(cgrp, cft, file, buf, nbytes, ppos);
        if (cft->trigger) {
                int ret = cft->trigger(cgrp, (unsigned int)cft->private);
                return ret ? ret : nbytes;
@@ -1450,7 +1463,7 @@ static ssize_t cgroup_read_u64(struct cgroup *cgrp, struct cftype *cft,
                               char __user *buf, size_t nbytes,
                               loff_t *ppos)
 {
-       char tmp[64];
+       char tmp[CGROUP_LOCAL_BUFFER_SIZE];
        u64 val = cft->read_u64(cgrp, cft);
        int len = sprintf(tmp, "%llu\n", (unsigned long long) val);
 
@@ -1462,56 +1475,13 @@ static ssize_t cgroup_read_s64(struct cgroup *cgrp, struct cftype *cft,
                               char __user *buf, size_t nbytes,
                               loff_t *ppos)
 {
-       char tmp[64];
+       char tmp[CGROUP_LOCAL_BUFFER_SIZE];
        s64 val = cft->read_s64(cgrp, cft);
        int len = sprintf(tmp, "%lld\n", (long long) val);
 
        return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
 }
 
-static ssize_t cgroup_common_file_read(struct cgroup *cgrp,
-                                         struct cftype *cft,
-                                         struct file *file,
-                                         char __user *buf,
-                                         size_t nbytes, loff_t *ppos)
-{
-       enum cgroup_filetype type = cft->private;
-       char *page;
-       ssize_t retval = 0;
-       char *s;
-
-       if (!(page = (char *)__get_free_page(GFP_KERNEL)))
-               return -ENOMEM;
-
-       s = page;
-
-       switch (type) {
-       case FILE_RELEASE_AGENT:
-       {
-               struct cgroupfs_root *root;
-               size_t n;
-               mutex_lock(&cgroup_mutex);
-               root = cgrp->root;
-               n = strnlen(root->release_agent_path,
-                           sizeof(root->release_agent_path));
-               n = min(n, (size_t) PAGE_SIZE);
-               strncpy(s, root->release_agent_path, n);
-               mutex_unlock(&cgroup_mutex);
-               s += n;
-               break;
-       }
-       default:
-               retval = -EINVAL;
-               goto out;
-       }
-       *s++ = '\n';
-
-       retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
-out:
-       free_page((unsigned long)page);
-       return retval;
-}
-
 static ssize_t cgroup_file_read(struct file *file, char __user *buf,
                                   size_t nbytes, loff_t *ppos)
 {
@@ -1560,7 +1530,7 @@ static int cgroup_seqfile_show(struct seq_file *m, void *arg)
        return cft->read_seq_string(state->cgroup, cft, m);
 }
 
-int cgroup_seqfile_release(struct inode *inode, struct file *file)
+static int cgroup_seqfile_release(struct inode *inode, struct file *file)
 {
        struct seq_file *seq = file->private_data;
        kfree(seq->private);
@@ -1569,6 +1539,7 @@ int cgroup_seqfile_release(struct inode *inode, struct file *file)
 
 static struct file_operations cgroup_seqfile_operations = {
        .read = seq_read,
+       .write = cgroup_file_write,
        .llseek = seq_lseek,
        .release = cgroup_seqfile_release,
 };
@@ -1756,15 +1727,11 @@ int cgroup_add_files(struct cgroup *cgrp,
 int cgroup_task_count(const struct cgroup *cgrp)
 {
        int count = 0;
-       struct list_head *l;
+       struct cg_cgroup_link *link;
 
        read_lock(&css_set_lock);
-       l = cgrp->css_sets.next;
-       while (l != &cgrp->css_sets) {
-               struct cg_cgroup_link *link =
-                       list_entry(l, struct cg_cgroup_link, cgrp_link_list);
+       list_for_each_entry(link, &cgrp->css_sets, cgrp_link_list) {
                count += atomic_read(&link->cg->ref.refcount);
-               l = l->next;
        }
        read_unlock(&css_set_lock);
        return count;
@@ -2227,6 +2194,18 @@ static u64 cgroup_read_notify_on_release(struct cgroup *cgrp,
        return notify_on_release(cgrp);
 }
 
+static int cgroup_write_notify_on_release(struct cgroup *cgrp,
+                                         struct cftype *cft,
+                                         u64 val)
+{
+       clear_bit(CGRP_RELEASABLE, &cgrp->flags);
+       if (val)
+               set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
+       else
+               clear_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
+       return 0;
+}
+
 /*
  * for the common functions, 'private' gives the type of file
  */
@@ -2235,7 +2214,7 @@ static struct cftype files[] = {
                .name = "tasks",
                .open = cgroup_tasks_open,
                .read = cgroup_tasks_read,
-               .write = cgroup_common_file_write,
+               .write_u64 = cgroup_tasks_write,
                .release = cgroup_tasks_release,
                .private = FILE_TASKLIST,
        },
@@ -2243,15 +2222,16 @@ static struct cftype files[] = {
        {
                .name = "notify_on_release",
                .read_u64 = cgroup_read_notify_on_release,
-               .write = cgroup_common_file_write,
+               .write_u64 = cgroup_write_notify_on_release,
                .private = FILE_NOTIFY_ON_RELEASE,
        },
 };
 
 static struct cftype cft_release_agent = {
        .name = "release_agent",
-       .read = cgroup_common_file_read,
-       .write = cgroup_common_file_write,
+       .read_seq_string = cgroup_release_agent_show,
+       .write_string = cgroup_release_agent_write,
+       .max_write_len = PATH_MAX,
        .private = FILE_RELEASE_AGENT,
 };
 
@@ -2869,16 +2849,17 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
  * cgroup_clone - clone the cgroup the given subsystem is attached to
  * @tsk: the task to be moved
  * @subsys: the given subsystem
+ * @nodename: the name for the new cgroup
  *
  * Duplicate the current cgroup in the hierarchy that the given
  * subsystem is attached to, and move this task into the new
  * child.
  */
-int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys)
+int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
+                                                       char *nodename)
 {
        struct dentry *dentry;
        int ret = 0;
-       char nodename[MAX_CGROUP_TYPE_NAMELEN];
        struct cgroup *parent, *child;
        struct inode *inode;
        struct css_set *cg;
@@ -2903,8 +2884,6 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys)
        cg = tsk->cgroups;
        parent = task_cgroup(tsk, subsys->subsys_id);
 
-       snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "%d", tsk->pid);
-
        /* Pin the hierarchy */
        atomic_inc(&parent->root->sb->s_active);
 
@@ -3078,27 +3057,24 @@ static void cgroup_release_agent(struct work_struct *work)
        while (!list_empty(&release_list)) {
                char *argv[3], *envp[3];
                int i;
-               char *pathbuf;
+               char *pathbuf = NULL, *agentbuf = NULL;
                struct cgroup *cgrp = list_entry(release_list.next,
                                                    struct cgroup,
                                                    release_list);
                list_del_init(&cgrp->release_list);
                spin_unlock(&release_list_lock);
                pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-               if (!pathbuf) {
-                       spin_lock(&release_list_lock);
-                       continue;
-               }
-
-               if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0) {
-                       kfree(pathbuf);
-                       spin_lock(&release_list_lock);
-                       continue;
-               }
+               if (!pathbuf)
+                       goto continue_free;
+               if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0)
+                       goto continue_free;
+               agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL);
+               if (!agentbuf)
+                       goto continue_free;
 
                i = 0;
-               argv[i++] = cgrp->root->release_agent_path;
-               argv[i++] = (char *)pathbuf;
+               argv[i++] = agentbuf;
+               argv[i++] = pathbuf;
                argv[i] = NULL;
 
                i = 0;
@@ -3112,8 +3088,10 @@ static void cgroup_release_agent(struct work_struct *work)
                 * be a slow process */
                mutex_unlock(&cgroup_mutex);
                call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
-               kfree(pathbuf);
                mutex_lock(&cgroup_mutex);
+ continue_free:
+               kfree(pathbuf);
+               kfree(agentbuf);
                spin_lock(&release_list_lock);
        }
        spin_unlock(&release_list_lock);
index 2cc409ce0a8f93012ff93432f4effe6884b0b01c..e202a68d1cc180cf62ade78b025ec2329c8aabcd 100644 (file)
@@ -216,7 +216,6 @@ static int __ref take_cpu_down(void *_param)
 static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
 {
        int err, nr_calls = 0;
-       struct task_struct *p;
        cpumask_t old_allowed, tmp;
        void *hcpu = (void *)(long)cpu;
        unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
@@ -249,21 +248,18 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
        cpus_setall(tmp);
        cpu_clear(cpu, tmp);
        set_cpus_allowed_ptr(current, &tmp);
+       tmp = cpumask_of_cpu(cpu);
 
-       p = __stop_machine_run(take_cpu_down, &tcd_param, cpu);
-
-       if (IS_ERR(p) || cpu_online(cpu)) {
+       err = __stop_machine(take_cpu_down, &tcd_param, &tmp);
+       if (err) {
                /* CPU didn't die: tell everyone.  Can't complain. */
                if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
                                            hcpu) == NOTIFY_BAD)
                        BUG();
 
-               if (IS_ERR(p)) {
-                       err = PTR_ERR(p);
-                       goto out_allowed;
-               }
-               goto out_thread;
+               goto out_allowed;
        }
+       BUG_ON(cpu_online(cpu));
 
        /* Wait for it to sleep (leaving idle task). */
        while (!idle_cpu(cpu))
@@ -279,12 +275,15 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
 
        check_for_tasks(cpu);
 
-out_thread:
-       err = kthread_stop(p);
 out_allowed:
        set_cpus_allowed_ptr(current, &old_allowed);
 out_release:
        cpu_hotplug_done();
+       if (!err) {
+               if (raw_notifier_call_chain(&cpu_chain, CPU_POST_DEAD | mod,
+                                           hcpu) == NOTIFY_BAD)
+                       BUG();
+       }
        return err;
 }
 
@@ -456,3 +455,28 @@ out:
 #endif /* CONFIG_PM_SLEEP_SMP */
 
 #endif /* CONFIG_SMP */
+
+/*
+ * cpu_bit_bitmap[] is a special, "compressed" data structure that
+ * represents all NR_CPUS bits binary values of 1<<nr.
+ *
+ * It is used by cpumask_of_cpu() to get a constant address to a CPU
+ * mask value that has a single bit set only.
+ */
+
+/* cpu_bit_bitmap[0] is empty - so we can back into it */
+#define MASK_DECLARE_1(x)      [x+1][0] = 1UL << (x)
+#define MASK_DECLARE_2(x)      MASK_DECLARE_1(x), MASK_DECLARE_1(x+1)
+#define MASK_DECLARE_4(x)      MASK_DECLARE_2(x), MASK_DECLARE_2(x+2)
+#define MASK_DECLARE_8(x)      MASK_DECLARE_4(x), MASK_DECLARE_4(x+4)
+
+const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {
+
+       MASK_DECLARE_8(0),      MASK_DECLARE_8(8),
+       MASK_DECLARE_8(16),     MASK_DECLARE_8(24),
+#if BITS_PER_LONG > 32
+       MASK_DECLARE_8(32),     MASK_DECLARE_8(40),
+       MASK_DECLARE_8(48),     MASK_DECLARE_8(56),
+#endif
+};
+EXPORT_SYMBOL_GPL(cpu_bit_bitmap);
index d5738910c34cfbad58d4a90777a2c242ff01ea14..91cf85b36dd577c2a231498575fcea1805ba44b7 100644 (file)
@@ -227,10 +227,6 @@ static struct cpuset top_cpuset = {
  * The task_struct fields mems_allowed and mems_generation may only
  * be accessed in the context of that task, so require no locks.
  *
- * The cpuset_common_file_write handler for operations that modify
- * the cpuset hierarchy holds cgroup_mutex across the entire operation,
- * single threading all such cpuset modifications across the system.
- *
  * The cpuset_common_file_read() handlers only hold callback_mutex across
  * small pieces of code, such as when reading out possibly multi-word
  * cpumasks and nodemasks.
@@ -369,7 +365,7 @@ void cpuset_update_task_memory_state(void)
                my_cpusets_mem_gen = top_cpuset.mems_generation;
        } else {
                rcu_read_lock();
-               my_cpusets_mem_gen = task_cs(current)->mems_generation;
+               my_cpusets_mem_gen = task_cs(tsk)->mems_generation;
                rcu_read_unlock();
        }
 
@@ -500,11 +496,16 @@ update_domain_attr(struct sched_domain_attr *dattr, struct cpuset *c)
 /*
  * rebuild_sched_domains()
  *
- * If the flag 'sched_load_balance' of any cpuset with non-empty
- * 'cpus' changes, or if the 'cpus' allowed changes in any cpuset
- * which has that flag enabled, or if any cpuset with a non-empty
- * 'cpus' is removed, then call this routine to rebuild the
- * scheduler's dynamic sched domains.
+ * This routine will be called to rebuild the scheduler's dynamic
+ * sched domains:
+ * - if the flag 'sched_load_balance' of any cpuset with non-empty
+ *   'cpus' changes,
+ * - or if the 'cpus' allowed changes in any cpuset which has that
+ *   flag enabled,
+ * - or if the 'sched_relax_domain_level' of any cpuset which has
+ *   that flag enabled and with non-empty 'cpus' changes,
+ * - or if any cpuset with non-empty 'cpus' is removed,
+ * - or if a cpu gets offlined.
  *
  * This routine builds a partial partition of the systems CPUs
  * (the set of non-overlappping cpumask_t's in the array 'part'
@@ -609,8 +610,13 @@ void rebuild_sched_domains(void)
        while (__kfifo_get(q, (void *)&cp, sizeof(cp))) {
                struct cgroup *cont;
                struct cpuset *child;   /* scans child cpusets of cp */
+
+               if (cpus_empty(cp->cpus_allowed))
+                       continue;
+
                if (is_sched_load_balance(cp))
                        csa[csn++] = cp;
+
                list_for_each_entry(cont, &cp->css.cgroup->children, sibling) {
                        child = cgroup_cs(cont);
                        __kfifo_put(q, (void *)&child, sizeof(cp));
@@ -703,36 +709,6 @@ done:
        /* Don't kfree(dattr) -- partition_sched_domains() does that. */
 }
 
-static inline int started_after_time(struct task_struct *t1,
-                                    struct timespec *time,
-                                    struct task_struct *t2)
-{
-       int start_diff = timespec_compare(&t1->start_time, time);
-       if (start_diff > 0) {
-               return 1;
-       } else if (start_diff < 0) {
-               return 0;
-       } else {
-               /*
-                * Arbitrarily, if two processes started at the same
-                * time, we'll say that the lower pointer value
-                * started first. Note that t2 may have exited by now
-                * so this may not be a valid pointer any longer, but
-                * that's fine - it still serves to distinguish
-                * between two tasks started (effectively)
-                * simultaneously.
-                */
-               return t1 > t2;
-       }
-}
-
-static inline int started_after(void *p1, void *p2)
-{
-       struct task_struct *t1 = p1;
-       struct task_struct *t2 = p2;
-       return started_after_time(t1, &t2->start_time, t2);
-}
-
 /**
  * cpuset_test_cpumask - test a task's cpus_allowed versus its cpuset's
  * @tsk: task to test
@@ -767,16 +743,50 @@ static void cpuset_change_cpumask(struct task_struct *tsk,
        set_cpus_allowed_ptr(tsk, &((cgroup_cs(scan->cg))->cpus_allowed));
 }
 
+/**
+ * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset.
+ * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed
+ *
+ * Called with cgroup_mutex held
+ *
+ * The cgroup_scan_tasks() function will scan all the tasks in a cgroup,
+ * calling callback functions for each.
+ *
+ * Return 0 if successful, -errno if not.
+ */
+static int update_tasks_cpumask(struct cpuset *cs)
+{
+       struct cgroup_scanner scan;
+       struct ptr_heap heap;
+       int retval;
+
+       /*
+        * cgroup_scan_tasks() will initialize heap->gt for us.
+        * heap_init() is still needed here for we should not change
+        * cs->cpus_allowed when heap_init() fails.
+        */
+       retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL);
+       if (retval)
+               return retval;
+
+       scan.cg = cs->css.cgroup;
+       scan.test_task = cpuset_test_cpumask;
+       scan.process_task = cpuset_change_cpumask;
+       scan.heap = &heap;
+       retval = cgroup_scan_tasks(&scan);
+
+       heap_free(&heap);
+       return retval;
+}
+
 /**
  * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
  * @cs: the cpuset to consider
  * @buf: buffer of cpu numbers written to this cpuset
  */
-static int update_cpumask(struct cpuset *cs, char *buf)
+static int update_cpumask(struct cpuset *cs, const char *buf)
 {
        struct cpuset trialcs;
-       struct cgroup_scanner scan;
-       struct ptr_heap heap;
        int retval;
        int is_load_balanced;
 
@@ -792,7 +802,6 @@ static int update_cpumask(struct cpuset *cs, char *buf)
         * that parsing.  The validate_change() call ensures that cpusets
         * with tasks have cpus.
         */
-       buf = strstrip(buf);
        if (!*buf) {
                cpus_clear(trialcs.cpus_allowed);
        } else {
@@ -811,10 +820,6 @@ static int update_cpumask(struct cpuset *cs, char *buf)
        if (cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed))
                return 0;
 
-       retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, &started_after);
-       if (retval)
-               return retval;
-
        is_load_balanced = is_sched_load_balance(&trialcs);
 
        mutex_lock(&callback_mutex);
@@ -825,12 +830,9 @@ static int update_cpumask(struct cpuset *cs, char *buf)
         * Scan tasks in the cpuset, and update the cpumasks of any
         * that need an update.
         */
-       scan.cg = cs->css.cgroup;
-       scan.test_task = cpuset_test_cpumask;
-       scan.process_task = cpuset_change_cpumask;
-       scan.heap = &heap;
-       cgroup_scan_tasks(&scan);
-       heap_free(&heap);
+       retval = update_tasks_cpumask(cs);
+       if (retval < 0)
+               return retval;
 
        if (is_load_balanced)
                rebuild_sched_domains();
@@ -886,74 +888,25 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
        mutex_unlock(&callback_mutex);
 }
 
-/*
- * Handle user request to change the 'mems' memory placement
- * of a cpuset.  Needs to validate the request, update the
- * cpusets mems_allowed and mems_generation, and for each
- * task in the cpuset, rebind any vma mempolicies and if
- * the cpuset is marked 'memory_migrate', migrate the tasks
- * pages to the new memory.
- *
- * Call with cgroup_mutex held.  May take callback_mutex during call.
- * Will take tasklist_lock, scan tasklist for tasks in cpuset cs,
- * lock each such tasks mm->mmap_sem, scan its vma's and rebind
- * their mempolicies to the cpusets new mems_allowed.
- */
-
 static void *cpuset_being_rebound;
 
-static int update_nodemask(struct cpuset *cs, char *buf)
+/**
+ * update_tasks_nodemask - Update the nodemasks of tasks in the cpuset.
+ * @cs: the cpuset in which each task's mems_allowed mask needs to be changed
+ * @oldmem: old mems_allowed of cpuset cs
+ *
+ * Called with cgroup_mutex held
+ * Return 0 if successful, -errno if not.
+ */
+static int update_tasks_nodemask(struct cpuset *cs, const nodemask_t *oldmem)
 {
-       struct cpuset trialcs;
-       nodemask_t oldmem;
        struct task_struct *p;
        struct mm_struct **mmarray;
        int i, n, ntasks;
        int migrate;
        int fudge;
-       int retval;
        struct cgroup_iter it;
-
-       /*
-        * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY];
-        * it's read-only
-        */
-       if (cs == &top_cpuset)
-               return -EACCES;
-
-       trialcs = *cs;
-
-       /*
-        * An empty mems_allowed is ok iff there are no tasks in the cpuset.
-        * Since nodelist_parse() fails on an empty mask, we special case
-        * that parsing.  The validate_change() call ensures that cpusets
-        * with tasks have memory.
-        */
-       buf = strstrip(buf);
-       if (!*buf) {
-               nodes_clear(trialcs.mems_allowed);
-       } else {
-               retval = nodelist_parse(buf, trialcs.mems_allowed);
-               if (retval < 0)
-                       goto done;
-
-               if (!nodes_subset(trialcs.mems_allowed,
-                               node_states[N_HIGH_MEMORY]))
-                       return -EINVAL;
-       }
-       oldmem = cs->mems_allowed;
-       if (nodes_equal(oldmem, trialcs.mems_allowed)) {
-               retval = 0;             /* Too easy - nothing to do */
-               goto done;
-       }
-       retval = validate_change(cs, &trialcs);
-       if (retval < 0)
-               goto done;
-
-       mutex_lock(&callback_mutex);
-       cs->mems_allowed = trialcs.mems_allowed;
-       cs->mems_generation = cpuset_mems_generation++;
-       mutex_unlock(&callback_mutex);
+       int retval;
 
        cpuset_being_rebound = cs;              /* causes mpol_dup() rebind */
 
@@ -1020,7 +973,7 @@ static int update_nodemask(struct cpuset *cs, char *buf)
 
                mpol_rebind_mm(mm, &cs->mems_allowed);
                if (migrate)
-                       cpuset_migrate_mm(mm, &oldmem, &cs->mems_allowed);
+                       cpuset_migrate_mm(mm, oldmem, &cs->mems_allowed);
                mmput(mm);
        }
 
@@ -1032,6 +985,70 @@ done:
        return retval;
 }
 
+/*
+ * Handle user request to change the 'mems' memory placement
+ * of a cpuset.  Needs to validate the request, update the
+ * cpusets mems_allowed and mems_generation, and for each
+ * task in the cpuset, rebind any vma mempolicies and if
+ * the cpuset is marked 'memory_migrate', migrate the tasks
+ * pages to the new memory.
+ *
+ * Call with cgroup_mutex held.  May take callback_mutex during call.
+ * Will take tasklist_lock, scan tasklist for tasks in cpuset cs,
+ * lock each such tasks mm->mmap_sem, scan its vma's and rebind
+ * their mempolicies to the cpusets new mems_allowed.
+ */
+static int update_nodemask(struct cpuset *cs, const char *buf)
+{
+       struct cpuset trialcs;
+       nodemask_t oldmem;
+       int retval;
+
+       /*
+        * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY];
+        * it's read-only
+        */
+       if (cs == &top_cpuset)
+               return -EACCES;
+
+       trialcs = *cs;
+
+       /*
+        * An empty mems_allowed is ok iff there are no tasks in the cpuset.
+        * Since nodelist_parse() fails on an empty mask, we special case
+        * that parsing.  The validate_change() call ensures that cpusets
+        * with tasks have memory.
+        */
+       if (!*buf) {
+               nodes_clear(trialcs.mems_allowed);
+       } else {
+               retval = nodelist_parse(buf, trialcs.mems_allowed);
+               if (retval < 0)
+                       goto done;
+
+               if (!nodes_subset(trialcs.mems_allowed,
+                               node_states[N_HIGH_MEMORY]))
+                       return -EINVAL;
+       }
+       oldmem = cs->mems_allowed;
+       if (nodes_equal(oldmem, trialcs.mems_allowed)) {
+               retval = 0;             /* Too easy - nothing to do */
+               goto done;
+       }
+       retval = validate_change(cs, &trialcs);
+       if (retval < 0)
+               goto done;
+
+       mutex_lock(&callback_mutex);
+       cs->mems_allowed = trialcs.mems_allowed;
+       cs->mems_generation = cpuset_mems_generation++;
+       mutex_unlock(&callback_mutex);
+
+       retval = update_tasks_nodemask(cs, &oldmem);
+done:
+       return retval;
+}
+
 int current_cpuset_is_being_rebound(void)
 {
        return task_cs(current) == cpuset_being_rebound;
@@ -1044,7 +1061,8 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
 
        if (val != cs->relax_domain_level) {
                cs->relax_domain_level = val;
-               rebuild_sched_domains();
+               if (!cpus_empty(cs->cpus_allowed) && is_sched_load_balance(cs))
+                       rebuild_sched_domains();
        }
 
        return 0;
@@ -1256,72 +1274,14 @@ typedef enum {
        FILE_SPREAD_SLAB,
 } cpuset_filetype_t;
 
-static ssize_t cpuset_common_file_write(struct cgroup *cont,
-                                       struct cftype *cft,
-                                       struct file *file,
-                                       const char __user *userbuf,
-                                       size_t nbytes, loff_t *unused_ppos)
-{
-       struct cpuset *cs = cgroup_cs(cont);
-       cpuset_filetype_t type = cft->private;
-       char *buffer;
-       int retval = 0;
-
-       /* Crude upper limit on largest legitimate cpulist user might write. */
-       if (nbytes > 100U + 6 * max(NR_CPUS, MAX_NUMNODES))
-               return -E2BIG;
-
-       /* +1 for nul-terminator */
-       buffer = kmalloc(nbytes + 1, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       if (copy_from_user(buffer, userbuf, nbytes)) {
-               retval = -EFAULT;
-               goto out1;
-       }
-       buffer[nbytes] = 0;     /* nul-terminate */
-
-       cgroup_lock();
-
-       if (cgroup_is_removed(cont)) {
-               retval = -ENODEV;
-               goto out2;
-       }
-
-       switch (type) {
-       case FILE_CPULIST:
-               retval = update_cpumask(cs, buffer);
-               break;
-       case FILE_MEMLIST:
-               retval = update_nodemask(cs, buffer);
-               break;
-       default:
-               retval = -EINVAL;
-               goto out2;
-       }
-
-       if (retval == 0)
-               retval = nbytes;
-out2:
-       cgroup_unlock();
-out1:
-       kfree(buffer);
-       return retval;
-}
-
 static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
 {
        int retval = 0;
        struct cpuset *cs = cgroup_cs(cgrp);
        cpuset_filetype_t type = cft->private;
 
-       cgroup_lock();
-
-       if (cgroup_is_removed(cgrp)) {
-               cgroup_unlock();
+       if (!cgroup_lock_live_group(cgrp))
                return -ENODEV;
-       }
 
        switch (type) {
        case FILE_CPU_EXCLUSIVE:
@@ -1367,12 +1327,9 @@ static int cpuset_write_s64(struct cgroup *cgrp, struct cftype *cft, s64 val)
        struct cpuset *cs = cgroup_cs(cgrp);
        cpuset_filetype_t type = cft->private;
 
-       cgroup_lock();
-
-       if (cgroup_is_removed(cgrp)) {
-               cgroup_unlock();
+       if (!cgroup_lock_live_group(cgrp))
                return -ENODEV;
-       }
+
        switch (type) {
        case FILE_SCHED_RELAX_DOMAIN_LEVEL:
                retval = update_relax_domain_level(cs, val);
@@ -1385,6 +1342,32 @@ static int cpuset_write_s64(struct cgroup *cgrp, struct cftype *cft, s64 val)
        return retval;
 }
 
+/*
+ * Common handling for a write to a "cpus" or "mems" file.
+ */
+static int cpuset_write_resmask(struct cgroup *cgrp, struct cftype *cft,
+                               const char *buf)
+{
+       int retval = 0;
+
+       if (!cgroup_lock_live_group(cgrp))
+               return -ENODEV;
+
+       switch (cft->private) {
+       case FILE_CPULIST:
+               retval = update_cpumask(cgroup_cs(cgrp), buf);
+               break;
+       case FILE_MEMLIST:
+               retval = update_nodemask(cgroup_cs(cgrp), buf);
+               break;
+       default:
+               retval = -EINVAL;
+               break;
+       }
+       cgroup_unlock();
+       return retval;
+}
+
 /*
  * These ascii lists should be read in a single call, by using a user
  * buffer large enough to hold the entire map.  If read in smaller
@@ -1504,14 +1487,16 @@ static struct cftype files[] = {
        {
                .name = "cpus",
                .read = cpuset_common_file_read,
-               .write = cpuset_common_file_write,
+               .write_string = cpuset_write_resmask,
+               .max_write_len = (100U + 6 * NR_CPUS),
                .private = FILE_CPULIST,
        },
 
        {
                .name = "mems",
                .read = cpuset_common_file_read,
-               .write = cpuset_common_file_write,
+               .write_string = cpuset_write_resmask,
+               .max_write_len = (100U + 6 * MAX_NUMNODES),
                .private = FILE_MEMLIST,
        },
 
@@ -1792,7 +1777,7 @@ static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to)
        scan.scan.heap = NULL;
        scan.to = to->css.cgroup;
 
-       if (cgroup_scan_tasks((struct cgroup_scanner *)&scan))
+       if (cgroup_scan_tasks(&scan.scan))
                printk(KERN_ERR "move_member_tasks_to_cpuset: "
                                "cgroup_scan_tasks failed\n");
 }
@@ -1852,6 +1837,7 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
        struct cpuset *child;   /* scans child cpusets of cp */
        struct list_head queue;
        struct cgroup *cont;
+       nodemask_t oldmems;
 
        INIT_LIST_HEAD(&queue);
 
@@ -1871,6 +1857,8 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
                    nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY]))
                        continue;
 
+               oldmems = cp->mems_allowed;
+
                /* Remove offline cpus and mems from this cpuset. */
                mutex_lock(&callback_mutex);
                cpus_and(cp->cpus_allowed, cp->cpus_allowed, cpu_online_map);
@@ -1882,6 +1870,10 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
                if (cpus_empty(cp->cpus_allowed) ||
                     nodes_empty(cp->mems_allowed))
                        remove_tasks_in_empty_cpuset(cp);
+               else {
+                       update_tasks_cpumask(cp);
+                       update_tasks_nodemask(cp, &oldmems);
+               }
        }
 }
 
@@ -1974,7 +1966,6 @@ void __init cpuset_init_smp(void)
 }
 
 /**
-
  * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
  * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
  * @pmask: pointer to cpumask_t variable to receive cpus_allowed set.
index 10e43fd8b721a7c28f44dbb60515efa9d0d4042d..b3179dad71be87d1f0d17258f82286abce3d9c47 100644 (file)
@@ -145,8 +145,11 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
        d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp;
        tmp = d->swapin_delay_total + tsk->delays->swapin_delay;
        d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp;
+       tmp = d->freepages_delay_total + tsk->delays->freepages_delay;
+       d->freepages_delay_total = (tmp < d->freepages_delay_total) ? 0 : tmp;
        d->blkio_count += tsk->delays->blkio_count;
        d->swapin_count += tsk->delays->swapin_count;
+       d->freepages_count += tsk->delays->freepages_count;
        spin_unlock_irqrestore(&tsk->delays->lock, flags);
 
 done:
@@ -165,3 +168,16 @@ __u64 __delayacct_blkio_ticks(struct task_struct *tsk)
        return ret;
 }
 
+void __delayacct_freepages_start(void)
+{
+       delayacct_start(&current->delays->freepages_start);
+}
+
+void __delayacct_freepages_end(void)
+{
+       delayacct_end(&current->delays->freepages_start,
+                       &current->delays->freepages_end,
+                       &current->delays->freepages_delay,
+                       &current->delays->freepages_count);
+}
+
diff --git a/kernel/dma-coherent.c b/kernel/dma-coherent.c
new file mode 100644 (file)
index 0000000..7517115
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Coherent per-device memory handling.
+ * Borrowed from i386
+ */
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+
+struct dma_coherent_mem {
+       void            *virt_base;
+       u32             device_base;
+       int             size;
+       int             flags;
+       unsigned long   *bitmap;
+};
+
+int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+                               dma_addr_t device_addr, size_t size, int flags)
+{
+       void __iomem *mem_base = NULL;
+       int pages = size >> PAGE_SHIFT;
+       int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+
+       if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
+               goto out;
+       if (!size)
+               goto out;
+       if (dev->dma_mem)
+               goto out;
+
+       /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
+
+       mem_base = ioremap(bus_addr, size);
+       if (!mem_base)
+               goto out;
+
+       dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
+       if (!dev->dma_mem)
+               goto out;
+       dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+       if (!dev->dma_mem->bitmap)
+               goto free1_out;
+
+       dev->dma_mem->virt_base = mem_base;
+       dev->dma_mem->device_base = device_addr;
+       dev->dma_mem->size = pages;
+       dev->dma_mem->flags = flags;
+
+       if (flags & DMA_MEMORY_MAP)
+               return DMA_MEMORY_MAP;
+
+       return DMA_MEMORY_IO;
+
+ free1_out:
+       kfree(dev->dma_mem);
+ out:
+       if (mem_base)
+               iounmap(mem_base);
+       return 0;
+}
+EXPORT_SYMBOL(dma_declare_coherent_memory);
+
+void dma_release_declared_memory(struct device *dev)
+{
+       struct dma_coherent_mem *mem = dev->dma_mem;
+
+       if (!mem)
+               return;
+       dev->dma_mem = NULL;
+       iounmap(mem->virt_base);
+       kfree(mem->bitmap);
+       kfree(mem);
+}
+EXPORT_SYMBOL(dma_release_declared_memory);
+
+void *dma_mark_declared_memory_occupied(struct device *dev,
+                                       dma_addr_t device_addr, size_t size)
+{
+       struct dma_coherent_mem *mem = dev->dma_mem;
+       int pos, err;
+       int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
+
+       pages >>= PAGE_SHIFT;
+
+       if (!mem)
+               return ERR_PTR(-EINVAL);
+
+       pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
+       err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
+       if (err != 0)
+               return ERR_PTR(err);
+       return mem->virt_base + (pos << PAGE_SHIFT);
+}
+EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
+
+/**
+ * Try to allocate memory from the per-device coherent area.
+ *
+ * @dev:       device from which we allocate memory
+ * @size:      size of requested memory area
+ * @dma_handle:        This will be filled with the correct dma handle
+ * @ret:       This pointer will be filled with the virtual address
+ *             to allocated area.
+ *
+ * This function should be only called from per-arch %dma_alloc_coherent()
+ * to support allocation from per-device coherent memory pools.
+ *
+ * Returns 0 if dma_alloc_coherent should continue with allocating from
+ * generic memory areas, or !0 if dma_alloc_coherent should return %ret.
+ */
+int dma_alloc_from_coherent(struct device *dev, ssize_t size,
+                                      dma_addr_t *dma_handle, void **ret)
+{
+       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+       int order = get_order(size);
+
+       if (mem) {
+               int page = bitmap_find_free_region(mem->bitmap, mem->size,
+                                                    order);
+               if (page >= 0) {
+                       *dma_handle = mem->device_base + (page << PAGE_SHIFT);
+                       *ret = mem->virt_base + (page << PAGE_SHIFT);
+                       memset(*ret, 0, size);
+               } else if (mem->flags & DMA_MEMORY_EXCLUSIVE)
+                       *ret = NULL;
+       }
+       return (mem != NULL);
+}
+
+/**
+ * Try to free the memory allocated from per-device coherent memory pool.
+ * @dev:       device from which the memory was allocated
+ * @order:     the order of pages allocated
+ * @vaddr:     virtual address of allocated pages
+ *
+ * This checks whether the memory was allocated from the per-device
+ * coherent memory pool and if so, releases that memory.
+ *
+ * Returns 1 if we correctly released the memory, or 0 if
+ * %dma_release_coherent() should proceed with releasing memory from
+ * generic pools.
+ */
+int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
+{
+       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+
+       if (mem && vaddr >= mem->virt_base && vaddr <
+                  (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+               int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+
+               bitmap_release_region(mem->bitmap, page, order);
+               return 1;
+       }
+       return 0;
+}
index c1ef192aa65592b6286e6c224969e8af1eed3d81..0d407e886735d0b35c36a836f3bc97afa15ad9c6 100644 (file)
@@ -168,7 +168,6 @@ __set_personality(u_long personality)
        current->personality = personality;
        oep = current_thread_info()->exec_domain;
        current_thread_info()->exec_domain = ep;
-       set_fs_altroot();
 
        module_put(oep->module);
        return 0;
index 93d2711b938123d34f1c0011e8f91a589b465615..eb4d6470d1d01f79a33a94df89833c3ba7d4387a 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/resource.h>
 #include <linux/blkdev.h>
 #include <linux/task_io_accounting_ops.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -85,7 +86,6 @@ static void __exit_signal(struct task_struct *tsk)
        BUG_ON(!sig);
        BUG_ON(!atomic_read(&sig->count));
 
-       rcu_read_lock();
        sighand = rcu_dereference(tsk->sighand);
        spin_lock(&sighand->siglock);
 
@@ -121,6 +121,7 @@ static void __exit_signal(struct task_struct *tsk)
                sig->nivcsw += tsk->nivcsw;
                sig->inblock += task_io_get_inblock(tsk);
                sig->oublock += task_io_get_oublock(tsk);
+               task_io_accounting_add(&sig->ioac, &tsk->ioac);
                sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
                sig = NULL; /* Marker for below. */
        }
@@ -136,7 +137,6 @@ static void __exit_signal(struct task_struct *tsk)
        tsk->signal = NULL;
        tsk->sighand = NULL;
        spin_unlock(&sighand->siglock);
-       rcu_read_unlock();
 
        __cleanup_sighand(sighand);
        clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
@@ -152,27 +152,17 @@ static void delayed_put_task_struct(struct rcu_head *rhp)
        put_task_struct(container_of(rhp, struct task_struct, rcu));
 }
 
-/*
- * Do final ptrace-related cleanup of a zombie being reaped.
- *
- * Called with write_lock(&tasklist_lock) held.
- */
-static void ptrace_release_task(struct task_struct *p)
-{
-       BUG_ON(!list_empty(&p->ptraced));
-       ptrace_unlink(p);
-       BUG_ON(!list_empty(&p->ptrace_entry));
-}
 
 void release_task(struct task_struct * p)
 {
        struct task_struct *leader;
        int zap_leader;
 repeat:
+       tracehook_prepare_release_task(p);
        atomic_dec(&p->user->processes);
        proc_flush_task(p);
        write_lock_irq(&tasklist_lock);
-       ptrace_release_task(p);
+       tracehook_finish_release_task(p);
        __exit_signal(p);
 
        /*
@@ -194,6 +184,13 @@ repeat:
                 * that case.
                 */
                zap_leader = task_detached(leader);
+
+               /*
+                * This maintains the invariant that release_task()
+                * only runs on a task in EXIT_DEAD, just for sanity.
+                */
+               if (zap_leader)
+                       leader->exit_state = EXIT_DEAD;
        }
 
        write_unlock_irq(&tasklist_lock);
@@ -432,7 +429,7 @@ void daemonize(const char *name, ...)
         * We don't want to have TIF_FREEZE set if the system-wide hibernation
         * or suspend transition begins right now.
         */
-       current->flags |= PF_NOFREEZE;
+       current->flags |= (PF_NOFREEZE | PF_KTHREAD);
 
        if (current->nsproxy != &init_nsproxy) {
                get_nsproxy(&init_nsproxy);
@@ -557,8 +554,6 @@ void put_fs_struct(struct fs_struct *fs)
        if (atomic_dec_and_test(&fs->count)) {
                path_put(&fs->root);
                path_put(&fs->pwd);
-               if (fs->altroot.dentry)
-                       path_put(&fs->altroot);
                kmem_cache_free(fs_cachep, fs);
        }
 }
@@ -666,26 +661,40 @@ assign_new_owner:
 static void exit_mm(struct task_struct * tsk)
 {
        struct mm_struct *mm = tsk->mm;
+       struct core_state *core_state;
 
        mm_release(tsk, mm);
        if (!mm)
                return;
        /*
         * Serialize with any possible pending coredump.
-        * We must hold mmap_sem around checking core_waiters
+        * We must hold mmap_sem around checking core_state
         * and clearing tsk->mm.  The core-inducing thread
-        * will increment core_waiters for each thread in the
+        * will increment ->nr_threads for each thread in the
         * group with ->mm != NULL.
         */
        down_read(&mm->mmap_sem);
-       if (mm->core_waiters) {
+       core_state = mm->core_state;
+       if (core_state) {
+               struct core_thread self;
                up_read(&mm->mmap_sem);
-               down_write(&mm->mmap_sem);
-               if (!--mm->core_waiters)
-                       complete(mm->core_startup_done);
-               up_write(&mm->mmap_sem);
 
-               wait_for_completion(&mm->core_done);
+               self.task = tsk;
+               self.next = xchg(&core_state->dumper.next, &self);
+               /*
+                * Implies mb(), the result of xchg() must be visible
+                * to core_state->dumper.
+                */
+               if (atomic_dec_and_test(&core_state->nr_threads))
+                       complete(&core_state->startup);
+
+               for (;;) {
+                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+                       if (!self.task) /* see coredump_finish() */
+                               break;
+                       schedule();
+               }
+               __set_task_state(tsk, TASK_RUNNING);
                down_read(&mm->mmap_sem);
        }
        atomic_inc(&mm->mm_count);
@@ -863,7 +872,8 @@ static void forget_original_parent(struct task_struct *father)
  */
 static void exit_notify(struct task_struct *tsk, int group_dead)
 {
-       int state;
+       int signal;
+       void *cookie;
 
        /*
         * This does two things:
@@ -900,22 +910,11 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
            !capable(CAP_KILL))
                tsk->exit_signal = SIGCHLD;
 
-       /* If something other than our normal parent is ptracing us, then
-        * send it a SIGCHLD instead of honoring exit_signal.  exit_signal
-        * only has special meaning to our real parent.
-        */
-       if (!task_detached(tsk) && thread_group_empty(tsk)) {
-               int signal = ptrace_reparented(tsk) ?
-                               SIGCHLD : tsk->exit_signal;
-               do_notify_parent(tsk, signal);
-       } else if (tsk->ptrace) {
-               do_notify_parent(tsk, SIGCHLD);
-       }
+       signal = tracehook_notify_death(tsk, &cookie, group_dead);
+       if (signal > 0)
+               signal = do_notify_parent(tsk, signal);
 
-       state = EXIT_ZOMBIE;
-       if (task_detached(tsk) && likely(!tsk->ptrace))
-               state = EXIT_DEAD;
-       tsk->exit_state = state;
+       tsk->exit_state = signal < 0 ? EXIT_DEAD : EXIT_ZOMBIE;
 
        /* mt-exec, de_thread() is waiting for us */
        if (thread_group_leader(tsk) &&
@@ -925,8 +924,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
 
        write_unlock_irq(&tasklist_lock);
 
+       tracehook_report_death(tsk, signal, cookie, group_dead);
+
        /* If the process is dead, release it - nobody will wait for it */
-       if (state == EXIT_DEAD)
+       if (signal < 0)
                release_task(tsk);
 }
 
@@ -1005,10 +1006,7 @@ NORET_TYPE void do_exit(long code)
        if (unlikely(!tsk->pid))
                panic("Attempted to kill the idle task!");
 
-       if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
-               current->ptrace_message = code;
-               ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
-       }
+       tracehook_report_exit(&code);
 
        /*
         * We're taking recursive faults here in do_exit. Safest is to just
@@ -1354,6 +1352,8 @@ static int wait_task_zombie(struct task_struct *p, int options,
                psig->coublock +=
                        task_io_get_oublock(p) +
                        sig->oublock + sig->coublock;
+               task_io_accounting_add(&psig->ioac, &p->ioac);
+               task_io_accounting_add(&psig->ioac, &sig->ioac);
                spin_unlock_irq(&p->parent->sighand->siglock);
        }
 
index adefc1131f274082960de7f375a67d4949cdfe27..7ce2ebe847964ecd0701c3c74c18994e3eebcf26 100644 (file)
 #include <linux/key.h>
 #include <linux/binfmts.h>
 #include <linux/mman.h>
+#include <linux/mmu_notifier.h>
 #include <linux/fs.h>
 #include <linux/nsproxy.h>
 #include <linux/capability.h>
 #include <linux/cpu.h>
 #include <linux/cgroup.h>
 #include <linux/security.h>
+#include <linux/hugetlb.h>
 #include <linux/swap.h>
 #include <linux/syscalls.h>
 #include <linux/jiffies.h>
+#include <linux/tracehook.h>
 #include <linux/futex.h>
 #include <linux/task_io_accounting_ops.h>
 #include <linux/rcupdate.h>
@@ -92,6 +95,23 @@ int nr_processes(void)
 static struct kmem_cache *task_struct_cachep;
 #endif
 
+#ifndef __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+static inline struct thread_info *alloc_thread_info(struct task_struct *tsk)
+{
+#ifdef CONFIG_DEBUG_STACK_USAGE
+       gfp_t mask = GFP_KERNEL | __GFP_ZERO;
+#else
+       gfp_t mask = GFP_KERNEL;
+#endif
+       return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER);
+}
+
+static inline void free_thread_info(struct thread_info *ti)
+{
+       free_pages((unsigned long)ti, THREAD_SIZE_ORDER);
+}
+#endif
+
 /* SLAB cache for signal_struct structures (tsk->signal) */
 static struct kmem_cache *signal_cachep;
 
@@ -306,6 +326,14 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
                        spin_unlock(&file->f_mapping->i_mmap_lock);
                }
 
+               /*
+                * Clear hugetlb-related page reserves for children. This only
+                * affects MAP_PRIVATE mappings. Faults generated by the child
+                * are not guaranteed to succeed, even if read-only
+                */
+               if (is_vm_hugetlb_page(tmp))
+                       reset_vma_resv_huge_pages(tmp);
+
                /*
                 * Link in the new vma and copy the page table entries.
                 */
@@ -374,7 +402,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
        INIT_LIST_HEAD(&mm->mmlist);
        mm->flags = (current->mm) ? current->mm->flags
                                  : MMF_DUMP_FILTER_DEFAULT;
-       mm->core_waiters = 0;
+       mm->core_state = NULL;
        mm->nr_ptes = 0;
        set_mm_counter(mm, file_rss, 0);
        set_mm_counter(mm, anon_rss, 0);
@@ -387,6 +415,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
+               mmu_notifier_mm_init(mm);
                return mm;
        }
 
@@ -419,6 +448,7 @@ void __mmdrop(struct mm_struct *mm)
        BUG_ON(mm == &init_mm);
        mm_free_pgd(mm);
        destroy_context(mm);
+       mmu_notifier_mm_destroy(mm);
        free_mm(mm);
 }
 EXPORT_SYMBOL_GPL(__mmdrop);
@@ -448,7 +478,7 @@ EXPORT_SYMBOL_GPL(mmput);
 /**
  * get_task_mm - acquire a reference to the task's mm
  *
- * Returns %NULL if the task has no mm.  Checks PF_BORROWED_MM (meaning
+ * Returns %NULL if the task has no mm.  Checks PF_KTHREAD (meaning
  * this kernel workthread has transiently adopted a user mm with use_mm,
  * to do its AIO) is not set and if so returns a reference to it, after
  * bumping up the use count.  User must release the mm via mmput()
@@ -461,7 +491,7 @@ struct mm_struct *get_task_mm(struct task_struct *task)
        task_lock(task);
        mm = task->mm;
        if (mm) {
-               if (task->flags & PF_BORROWED_MM)
+               if (task->flags & PF_KTHREAD)
                        mm = NULL;
                else
                        atomic_inc(&mm->mm_users);
@@ -630,13 +660,6 @@ static struct fs_struct *__copy_fs_struct(struct fs_struct *old)
                path_get(&old->root);
                fs->pwd = old->pwd;
                path_get(&old->pwd);
-               if (old->altroot.dentry) {
-                       fs->altroot = old->altroot;
-                       path_get(&old->altroot);
-               } else {
-                       fs->altroot.mnt = NULL;
-                       fs->altroot.dentry = NULL;
-               }
                read_unlock(&old->lock);
        }
        return fs;
@@ -786,6 +809,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
        sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
        sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
        sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
+       task_io_accounting_init(&sig->ioac);
        sig->sum_sched_runtime = 0;
        INIT_LIST_HEAD(&sig->cpu_timers[0]);
        INIT_LIST_HEAD(&sig->cpu_timers[1]);
@@ -833,8 +857,7 @@ static void copy_flags(unsigned long clone_flags, struct task_struct *p)
 
        new_flags &= ~PF_SUPERPRIV;
        new_flags |= PF_FORKNOEXEC;
-       if (!(clone_flags & CLONE_PTRACE))
-               p->ptrace = 0;
+       new_flags |= PF_STARTING;
        p->flags = new_flags;
        clear_freeze_flag(p);
 }
@@ -875,7 +898,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                                        struct pt_regs *regs,
                                        unsigned long stack_size,
                                        int __user *child_tidptr,
-                                       struct pid *pid)
+                                       struct pid *pid,
+                                       int trace)
 {
        int retval;
        struct task_struct *p;
@@ -968,13 +992,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        p->last_switch_timestamp = 0;
 #endif
 
-#ifdef CONFIG_TASK_XACCT
-       p->rchar = 0;           /* I/O counter: bytes read */
-       p->wchar = 0;           /* I/O counter: bytes written */
-       p->syscr = 0;           /* I/O counter: read syscalls */
-       p->syscw = 0;           /* I/O counter: write syscalls */
-#endif
-       task_io_accounting_init(p);
+       task_io_accounting_init(&p->ioac);
        acct_clear_integrals(p);
 
        p->it_virt_expires = cputime_zero;
@@ -1081,6 +1099,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        if (clone_flags & CLONE_THREAD)
                p->tgid = current->tgid;
 
+       if (current->nsproxy != p->nsproxy) {
+               retval = ns_cgroup_clone(p, pid);
+               if (retval)
+                       goto bad_fork_free_pid;
+       }
+
        p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
        /*
         * Clear TID on mm_release()?
@@ -1125,8 +1149,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
         */
        p->group_leader = p;
        INIT_LIST_HEAD(&p->thread_group);
-       INIT_LIST_HEAD(&p->ptrace_entry);
-       INIT_LIST_HEAD(&p->ptraced);
 
        /* Now that the task is set up, run cgroup callbacks if
         * necessary. We need to run them before the task is visible
@@ -1157,7 +1179,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                p->real_parent = current->real_parent;
        else
                p->real_parent = current;
-       p->parent = p->real_parent;
 
        spin_lock(&current->sighand->siglock);
 
@@ -1199,8 +1220,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 
        if (likely(p->pid)) {
                list_add_tail(&p->sibling, &p->real_parent->children);
-               if (unlikely(p->ptrace & PT_PTRACED))
-                       __ptrace_link(p, current->parent);
+               tracehook_finish_clone(p, clone_flags, trace);
 
                if (thread_group_leader(p)) {
                        if (clone_flags & CLONE_NEWPID)
@@ -1285,29 +1305,13 @@ struct task_struct * __cpuinit fork_idle(int cpu)
        struct pt_regs regs;
 
        task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL,
-                               &init_struct_pid);
+                           &init_struct_pid, 0);
        if (!IS_ERR(task))
                init_idle(task, cpu);
 
        return task;
 }
 
-static int fork_traceflag(unsigned clone_flags)
-{
-       if (clone_flags & CLONE_UNTRACED)
-               return 0;
-       else if (clone_flags & CLONE_VFORK) {
-               if (current->ptrace & PT_TRACE_VFORK)
-                       return PTRACE_EVENT_VFORK;
-       } else if ((clone_flags & CSIGNAL) != SIGCHLD) {
-               if (current->ptrace & PT_TRACE_CLONE)
-                       return PTRACE_EVENT_CLONE;
-       } else if (current->ptrace & PT_TRACE_FORK)
-               return PTRACE_EVENT_FORK;
-
-       return 0;
-}
-
 /*
  *  Ok, this is the main fork-routine.
  *
@@ -1342,14 +1346,14 @@ long do_fork(unsigned long clone_flags,
                }
        }
 
-       if (unlikely(current->ptrace)) {
-               trace = fork_traceflag (clone_flags);
-               if (trace)
-                       clone_flags |= CLONE_PTRACE;
-       }
+       /*
+        * When called from kernel_thread, don't do user tracing stuff.
+        */
+       if (likely(user_mode(regs)))
+               trace = tracehook_prepare_clone(clone_flags);
 
        p = copy_process(clone_flags, stack_start, regs, stack_size,
-                       child_tidptr, NULL);
+                        child_tidptr, NULL, trace);
        /*
         * Do this prior waking up the new thread - the thread pointer
         * might get invalid after that point, if the thread exits quickly.
@@ -1367,32 +1371,35 @@ long do_fork(unsigned long clone_flags,
                        init_completion(&vfork);
                }
 
-               if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) {
+               tracehook_report_clone(trace, regs, clone_flags, nr, p);
+
+               /*
+                * We set PF_STARTING at creation in case tracing wants to
+                * use this to distinguish a fully live task from one that
+                * hasn't gotten to tracehook_report_clone() yet.  Now we
+                * clear it and set the child going.
+                */
+               p->flags &= ~PF_STARTING;
+
+               if (unlikely(clone_flags & CLONE_STOPPED)) {
                        /*
                         * We'll start up with an immediate SIGSTOP.
                         */
                        sigaddset(&p->pending.signal, SIGSTOP);
                        set_tsk_thread_flag(p, TIF_SIGPENDING);
-               }
-
-               if (!(clone_flags & CLONE_STOPPED))
-                       wake_up_new_task(p, clone_flags);
-               else
                        __set_task_state(p, TASK_STOPPED);
-
-               if (unlikely (trace)) {
-                       current->ptrace_message = nr;
-                       ptrace_notify ((trace << 8) | SIGTRAP);
+               } else {
+                       wake_up_new_task(p, clone_flags);
                }
 
+               tracehook_report_clone_complete(trace, regs,
+                                               clone_flags, nr, p);
+
                if (clone_flags & CLONE_VFORK) {
                        freezer_do_not_count();
                        wait_for_completion(&vfork);
                        freezer_count();
-                       if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) {
-                               current->ptrace_message = nr;
-                               ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
-                       }
+                       tracehook_report_vfork_done(p, nr);
                }
        } else {
                nr = PTR_ERR(p);
@@ -1404,7 +1411,7 @@ long do_fork(unsigned long clone_flags,
 #define ARCH_MIN_MMSTRUCT_ALIGN 0
 #endif
 
-static void sighand_ctor(struct kmem_cache *cachep, void *data)
+static void sighand_ctor(void *data)
 {
        struct sighand_struct *sighand = data;
 
index 964964baefa23c2a8bdee504aa053d078ba29ad9..3cd441ebf5d2178fcd2d9bdd49573706d6c78b51 100644 (file)
@@ -28,8 +28,7 @@ void dynamic_irq_init(unsigned int irq)
        unsigned long flags;
 
        if (irq >= NR_IRQS) {
-               printk(KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
-               WARN_ON(1);
+               WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
                return;
        }
 
@@ -62,8 +61,7 @@ void dynamic_irq_cleanup(unsigned int irq)
        unsigned long flags;
 
        if (irq >= NR_IRQS) {
-               printk(KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
-               WARN_ON(1);
+               WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
                return;
        }
 
@@ -71,9 +69,8 @@ void dynamic_irq_cleanup(unsigned int irq)
        spin_lock_irqsave(&desc->lock, flags);
        if (desc->action) {
                spin_unlock_irqrestore(&desc->lock, flags);
-               printk(KERN_ERR "Destroying IRQ%d without calling free_irq\n",
+               WARN(1, KERN_ERR "Destroying IRQ%d without calling free_irq\n",
                        irq);
-               WARN_ON(1);
                return;
        }
        desc->msi_desc = NULL;
@@ -96,8 +93,7 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip)
        unsigned long flags;
 
        if (irq >= NR_IRQS) {
-               printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq);
-               WARN_ON(1);
+               WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq);
                return -EINVAL;
        }
 
index 3cfc0fefb5ee671e1565862f1b54ee431af4eb8a..152abfd3589f8fe77ea7e0e60a20b7812c7a1b0f 100644 (file)
@@ -177,8 +177,7 @@ static void __enable_irq(struct irq_desc *desc, unsigned int irq)
 {
        switch (desc->depth) {
        case 0:
-               printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
-               WARN_ON(1);
+               WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
                break;
        case 1: {
                unsigned int status = desc->status & ~IRQ_DISABLED;
@@ -260,9 +259,7 @@ int set_irq_wake(unsigned int irq, unsigned int on)
                }
        } else {
                if (desc->wake_depth == 0) {
-                       printk(KERN_WARNING "Unbalanced IRQ %d "
-                                       "wake disable\n", irq);
-                       WARN_ON(1);
+                       WARN(1, "Unbalanced IRQ %d wake disable\n", irq);
                } else if (--desc->wake_depth == 0) {
                        ret = set_irq_wake_real(irq, on);
                        if (ret)
@@ -308,6 +305,30 @@ void compat_irq_chip_set_default_handler(struct irq_desc *desc)
                desc->handle_irq = NULL;
 }
 
+static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,
+               unsigned long flags)
+{
+       int ret;
+
+       if (!chip || !chip->set_type) {
+               /*
+                * IRQF_TRIGGER_* but the PIC does not support multiple
+                * flow-types?
+                */
+               pr_warning("No set_type function for IRQ %d (%s)\n", irq,
+                               chip ? (chip->name ? : "unknown") : "unknown");
+               return 0;
+       }
+
+       ret = chip->set_type(irq, flags & IRQF_TRIGGER_MASK);
+
+       if (ret)
+               pr_err("setting flow type for irq %u failed (%pF)\n",
+                               irq, chip->set_type);
+
+       return ret;
+}
+
 /*
  * Internal function to register an irqaction - typically used to
  * allocate special interrupts that are part of the architecture.
@@ -319,6 +340,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
        const char *old_name = NULL;
        unsigned long flags;
        int shared = 0;
+       int ret;
 
        if (irq >= NR_IRQS)
                return -EINVAL;
@@ -376,35 +398,23 @@ int setup_irq(unsigned int irq, struct irqaction *new)
                shared = 1;
        }
 
-       *p = new;
-
-       /* Exclude IRQ from balancing */
-       if (new->flags & IRQF_NOBALANCING)
-               desc->status |= IRQ_NO_BALANCING;
-
        if (!shared) {
                irq_chip_set_defaults(desc->chip);
 
-#if defined(CONFIG_IRQ_PER_CPU)
-               if (new->flags & IRQF_PERCPU)
-                       desc->status |= IRQ_PER_CPU;
-#endif
-
                /* Setup the type (level, edge polarity) if configured: */
                if (new->flags & IRQF_TRIGGER_MASK) {
-                       if (desc->chip->set_type)
-                               desc->chip->set_type(irq,
-                                               new->flags & IRQF_TRIGGER_MASK);
-                       else
-                               /*
-                                * IRQF_TRIGGER_* but the PIC does not support
-                                * multiple flow-types?
-                                */
-                               printk(KERN_WARNING "No IRQF_TRIGGER set_type "
-                                      "function for IRQ %d (%s)\n", irq,
-                                      desc->chip->name);
+                       ret = __irq_set_trigger(desc->chip, irq, new->flags);
+
+                       if (ret) {
+                               spin_unlock_irqrestore(&desc->lock, flags);
+                               return ret;
+                       }
                } else
                        compat_irq_chip_set_default_handler(desc);
+#if defined(CONFIG_IRQ_PER_CPU)
+               if (new->flags & IRQF_PERCPU)
+                       desc->status |= IRQ_PER_CPU;
+#endif
 
                desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
                                  IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
@@ -423,6 +433,13 @@ int setup_irq(unsigned int irq, struct irqaction *new)
                /* Set default affinity mask once everything is setup */
                irq_select_affinity(irq);
        }
+
+       *p = new;
+
+       /* Exclude IRQ from balancing */
+       if (new->flags & IRQF_NOBALANCING)
+               desc->status |= IRQ_NO_BALANCING;
+
        /* Reset broken irq detection when installing new handler */
        desc->irq_count = 0;
        desc->irqs_unhandled = 0;
index 6fc0040f3e3abacade62c7d63f74d240974d80fe..38fc10ac75415a8ff4da69b68d90facf61eb5e41 100644 (file)
@@ -176,7 +176,7 @@ static unsigned long get_symbol_pos(unsigned long addr,
        high = kallsyms_num_syms;
 
        while (high - low > 1) {
-               mid = (low + high) / 2;
+               mid = low + (high - low) / 2;
                if (kallsyms_addresses[mid] <= addr)
                        low = mid;
                else
index 1c5fcacbcf336b8dc82d0b02202a3d95c32fbd13..c8a4370e2a34e94b2e391fada22fec051b162195 100644 (file)
 #include <linux/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/numa.h>
+#include <linux/suspend.h>
+#include <linux/device.h>
+#include <linux/freezer.h>
+#include <linux/pm.h>
+#include <linux/cpu.h>
+#include <linux/console.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -242,6 +248,12 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
                goto out;
        }
 
+       image->swap_page = kimage_alloc_control_pages(image, 0);
+       if (!image->swap_page) {
+               printk(KERN_ERR "Could not allocate swap buffer\n");
+               goto out;
+       }
+
        result = 0;
  out:
        if (result == 0)
@@ -589,14 +601,12 @@ static void kimage_free_extra_pages(struct kimage *image)
        kimage_free_page_list(&image->unuseable_pages);
 
 }
-static int kimage_terminate(struct kimage *image)
+static void kimage_terminate(struct kimage *image)
 {
        if (*image->entry != 0)
                image->entry++;
 
        *image->entry = IND_DONE;
-
-       return 0;
 }
 
 #define for_each_kimage_entry(image, ptr, entry) \
@@ -988,6 +998,8 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
                if (result)
                        goto out;
 
+               if (flags & KEXEC_PRESERVE_CONTEXT)
+                       image->preserve_context = 1;
                result = machine_kexec_prepare(image);
                if (result)
                        goto out;
@@ -997,9 +1009,7 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
                        if (result)
                                goto out;
                }
-               result = kimage_terminate(image);
-               if (result)
-                       goto out;
+               kimage_terminate(image);
        }
        /* Install the new kernel, and  Uninstall the old */
        image = xchg(dest_image, image);
@@ -1415,3 +1425,85 @@ static int __init crash_save_vmcoreinfo_init(void)
 }
 
 module_init(crash_save_vmcoreinfo_init)
+
+/**
+ *     kernel_kexec - reboot the system
+ *
+ *     Move into place and start executing a preloaded standalone
+ *     executable.  If nothing was preloaded return an error.
+ */
+int kernel_kexec(void)
+{
+       int error = 0;
+
+       if (xchg(&kexec_lock, 1))
+               return -EBUSY;
+       if (!kexec_image) {
+               error = -EINVAL;
+               goto Unlock;
+       }
+
+       if (kexec_image->preserve_context) {
+#ifdef CONFIG_KEXEC_JUMP
+               mutex_lock(&pm_mutex);
+               pm_prepare_console();
+               error = freeze_processes();
+               if (error) {
+                       error = -EBUSY;
+                       goto Restore_console;
+               }
+               suspend_console();
+               error = device_suspend(PMSG_FREEZE);
+               if (error)
+                       goto Resume_console;
+               error = disable_nonboot_cpus();
+               if (error)
+                       goto Resume_devices;
+               local_irq_disable();
+               /* At this point, device_suspend() has been called,
+                * but *not* device_power_down(). We *must*
+                * device_power_down() now.  Otherwise, drivers for
+                * some devices (e.g. interrupt controllers) become
+                * desynchronized with the actual state of the
+                * hardware at resume time, and evil weirdness ensues.
+                */
+               error = device_power_down(PMSG_FREEZE);
+               if (error)
+                       goto Enable_irqs;
+               save_processor_state();
+#endif
+       } else {
+               blocking_notifier_call_chain(&reboot_notifier_list,
+                                            SYS_RESTART, NULL);
+               system_state = SYSTEM_RESTART;
+               device_shutdown();
+               sysdev_shutdown();
+               printk(KERN_EMERG "Starting new kernel\n");
+               machine_shutdown();
+       }
+
+       machine_kexec(kexec_image);
+
+       if (kexec_image->preserve_context) {
+#ifdef CONFIG_KEXEC_JUMP
+               restore_processor_state();
+               device_power_up(PMSG_RESTORE);
+ Enable_irqs:
+               local_irq_enable();
+               enable_nonboot_cpus();
+ Resume_devices:
+               device_resume(PMSG_RESTORE);
+ Resume_console:
+               resume_console();
+               thaw_processes();
+ Restore_console:
+               pm_restore_console();
+               mutex_unlock(&pm_mutex);
+#endif
+       }
+
+ Unlock:
+       xchg(&kexec_lock, 0);
+
+       return error;
+}
index 90d7af1c16554ce63c49ad64184fb6077f3b96fc..2456d1a0befbd45b91cd7cb7a97ae6d2fb270c4c 100644 (file)
@@ -352,16 +352,17 @@ static inline void register_pm_notifier_callback(void) {}
  * @path: path to usermode executable
  * @argv: arg vector for process
  * @envp: environment for process
+ * @gfp_mask: gfp mask for memory allocation
  *
  * Returns either %NULL on allocation failure, or a subprocess_info
  * structure.  This should be passed to call_usermodehelper_exec to
  * exec the process and free the structure.
  */
-struct subprocess_info *call_usermodehelper_setup(char *path,
-                                                 char **argv, char **envp)
+struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
+                                                 char **envp, gfp_t gfp_mask)
 {
        struct subprocess_info *sub_info;
-       sub_info = kzalloc(sizeof(struct subprocess_info),  GFP_ATOMIC);
+       sub_info = kzalloc(sizeof(struct subprocess_info), gfp_mask);
        if (!sub_info)
                goto out;
 
@@ -417,12 +418,12 @@ int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
 {
        struct file *f;
 
-       f = create_write_pipe();
+       f = create_write_pipe(0);
        if (IS_ERR(f))
                return PTR_ERR(f);
        *filp = f;
 
-       f = create_read_pipe(f);
+       f = create_read_pipe(f, 0);
        if (IS_ERR(f)) {
                free_write_pipe(*filp);
                return PTR_ERR(f);
@@ -494,7 +495,7 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
        struct subprocess_info *sub_info;
        int ret;
 
-       sub_info = call_usermodehelper_setup(path, argv, envp);
+       sub_info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL);
        if (sub_info == NULL)
                return -ENOMEM;
 
index 1485ca8d0e00503104e81248a7c5e30b58edfb79..75bc2cd9ebc6a7307aa15c404a914559bcab917b 100644 (file)
@@ -62,6 +62,7 @@
        addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name)))
 #endif
 
+static int kprobes_initialized;
 static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
 static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
 
@@ -69,8 +70,15 @@ static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
 static bool kprobe_enabled;
 
 DEFINE_MUTEX(kprobe_mutex);            /* Protects kprobe_table */
-DEFINE_SPINLOCK(kretprobe_lock);       /* Protects kretprobe_inst_table */
 static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
+static struct {
+       spinlock_t lock ____cacheline_aligned;
+} kretprobe_table_locks[KPROBE_TABLE_SIZE];
+
+static spinlock_t *kretprobe_table_lock_ptr(unsigned long hash)
+{
+       return &(kretprobe_table_locks[hash].lock);
+}
 
 /*
  * Normally, functions that we'd want to prohibit kprobes in, are marked
@@ -368,26 +376,53 @@ void __kprobes kprobes_inc_nmissed_count(struct kprobe *p)
        return;
 }
 
-/* Called with kretprobe_lock held */
 void __kprobes recycle_rp_inst(struct kretprobe_instance *ri,
                                struct hlist_head *head)
 {
+       struct kretprobe *rp = ri->rp;
+
        /* remove rp inst off the rprobe_inst_table */
        hlist_del(&ri->hlist);
-       if (ri->rp) {
-               /* remove rp inst off the used list */
-               hlist_del(&ri->uflist);
-               /* put rp inst back onto the free list */
-               INIT_HLIST_NODE(&ri->uflist);
-               hlist_add_head(&ri->uflist, &ri->rp->free_instances);
+       INIT_HLIST_NODE(&ri->hlist);
+       if (likely(rp)) {
+               spin_lock(&rp->lock);
+               hlist_add_head(&ri->hlist, &rp->free_instances);
+               spin_unlock(&rp->lock);
        } else
                /* Unregistering */
                hlist_add_head(&ri->hlist, head);
 }
 
-struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk)
+void kretprobe_hash_lock(struct task_struct *tsk,
+                        struct hlist_head **head, unsigned long *flags)
 {
-       return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
+       unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
+       spinlock_t *hlist_lock;
+
+       *head = &kretprobe_inst_table[hash];
+       hlist_lock = kretprobe_table_lock_ptr(hash);
+       spin_lock_irqsave(hlist_lock, *flags);
+}
+
+void kretprobe_table_lock(unsigned long hash, unsigned long *flags)
+{
+       spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
+       spin_lock_irqsave(hlist_lock, *flags);
+}
+
+void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags)
+{
+       unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
+       spinlock_t *hlist_lock;
+
+       hlist_lock = kretprobe_table_lock_ptr(hash);
+       spin_unlock_irqrestore(hlist_lock, *flags);
+}
+
+void kretprobe_table_unlock(unsigned long hash, unsigned long *flags)
+{
+       spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
+       spin_unlock_irqrestore(hlist_lock, *flags);
 }
 
 /*
@@ -401,17 +436,21 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
        struct kretprobe_instance *ri;
        struct hlist_head *head, empty_rp;
        struct hlist_node *node, *tmp;
-       unsigned long flags = 0;
+       unsigned long hash, flags = 0;
 
-       INIT_HLIST_HEAD(&empty_rp);
-       spin_lock_irqsave(&kretprobe_lock, flags);
-       head = kretprobe_inst_table_head(tk);
+       if (unlikely(!kprobes_initialized))
+               /* Early boot.  kretprobe_table_locks not yet initialized. */
+               return;
+
+       hash = hash_ptr(tk, KPROBE_HASH_BITS);
+       head = &kretprobe_inst_table[hash];
+       kretprobe_table_lock(hash, &flags);
        hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
                if (ri->task == tk)
                        recycle_rp_inst(ri, &empty_rp);
        }
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
-
+       kretprobe_table_unlock(hash, &flags);
+       INIT_HLIST_HEAD(&empty_rp);
        hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
                hlist_del(&ri->hlist);
                kfree(ri);
@@ -423,24 +462,29 @@ static inline void free_rp_inst(struct kretprobe *rp)
        struct kretprobe_instance *ri;
        struct hlist_node *pos, *next;
 
-       hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, uflist) {
-               hlist_del(&ri->uflist);
+       hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, hlist) {
+               hlist_del(&ri->hlist);
                kfree(ri);
        }
 }
 
 static void __kprobes cleanup_rp_inst(struct kretprobe *rp)
 {
-       unsigned long flags;
+       unsigned long flags, hash;
        struct kretprobe_instance *ri;
        struct hlist_node *pos, *next;
+       struct hlist_head *head;
+
        /* No race here */
-       spin_lock_irqsave(&kretprobe_lock, flags);
-       hlist_for_each_entry_safe(ri, pos, next, &rp->used_instances, uflist) {
-               ri->rp = NULL;
-               hlist_del(&ri->uflist);
+       for (hash = 0; hash < KPROBE_TABLE_SIZE; hash++) {
+               kretprobe_table_lock(hash, &flags);
+               head = &kretprobe_inst_table[hash];
+               hlist_for_each_entry_safe(ri, pos, next, head, hlist) {
+                       if (ri->rp == rp)
+                               ri->rp = NULL;
+               }
+               kretprobe_table_unlock(hash, &flags);
        }
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
        free_rp_inst(rp);
 }
 
@@ -831,32 +875,37 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
                                           struct pt_regs *regs)
 {
        struct kretprobe *rp = container_of(p, struct kretprobe, kp);
-       unsigned long flags = 0;
+       unsigned long hash, flags = 0;
+       struct kretprobe_instance *ri;
 
        /*TODO: consider to only swap the RA after the last pre_handler fired */
-       spin_lock_irqsave(&kretprobe_lock, flags);
+       hash = hash_ptr(current, KPROBE_HASH_BITS);
+       spin_lock_irqsave(&rp->lock, flags);
        if (!hlist_empty(&rp->free_instances)) {
-               struct kretprobe_instance *ri;
-
                ri = hlist_entry(rp->free_instances.first,
-                                struct kretprobe_instance, uflist);
+                               struct kretprobe_instance, hlist);
+               hlist_del(&ri->hlist);
+               spin_unlock_irqrestore(&rp->lock, flags);
+
                ri->rp = rp;
                ri->task = current;
 
                if (rp->entry_handler && rp->entry_handler(ri, regs)) {
-                       spin_unlock_irqrestore(&kretprobe_lock, flags);
+                       spin_unlock_irqrestore(&rp->lock, flags);
                        return 0;
                }
 
                arch_prepare_kretprobe(ri, regs);
 
                /* XXX(hch): why is there no hlist_move_head? */
-               hlist_del(&ri->uflist);
-               hlist_add_head(&ri->uflist, &ri->rp->used_instances);
-               hlist_add_head(&ri->hlist, kretprobe_inst_table_head(ri->task));
-       } else
+               INIT_HLIST_NODE(&ri->hlist);
+               kretprobe_table_lock(hash, &flags);
+               hlist_add_head(&ri->hlist, &kretprobe_inst_table[hash]);
+               kretprobe_table_unlock(hash, &flags);
+       } else {
                rp->nmissed++;
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
+               spin_unlock_irqrestore(&rp->lock, flags);
+       }
        return 0;
 }
 
@@ -892,7 +941,7 @@ static int __kprobes __register_kretprobe(struct kretprobe *rp,
                rp->maxactive = NR_CPUS;
 #endif
        }
-       INIT_HLIST_HEAD(&rp->used_instances);
+       spin_lock_init(&rp->lock);
        INIT_HLIST_HEAD(&rp->free_instances);
        for (i = 0; i < rp->maxactive; i++) {
                inst = kmalloc(sizeof(struct kretprobe_instance) +
@@ -901,8 +950,8 @@ static int __kprobes __register_kretprobe(struct kretprobe *rp,
                        free_rp_inst(rp);
                        return -ENOMEM;
                }
-               INIT_HLIST_NODE(&inst->uflist);
-               hlist_add_head(&inst->uflist, &rp->free_instances);
+               INIT_HLIST_NODE(&inst->hlist);
+               hlist_add_head(&inst->hlist, &rp->free_instances);
        }
 
        rp->nmissed = 0;
@@ -1009,6 +1058,7 @@ static int __init init_kprobes(void)
        for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
                INIT_HLIST_HEAD(&kprobe_table[i]);
                INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
+               spin_lock_init(&(kretprobe_table_locks[i].lock));
        }
 
        /*
@@ -1050,6 +1100,7 @@ static int __init init_kprobes(void)
        err = arch_init_kprobes();
        if (!err)
                err = register_die_notifier(&kprobe_exceptions_nb);
+       kprobes_initialized = (err == 0);
 
        if (!err)
                init_test_probes();
@@ -1286,13 +1337,8 @@ EXPORT_SYMBOL_GPL(register_jprobe);
 EXPORT_SYMBOL_GPL(unregister_jprobe);
 EXPORT_SYMBOL_GPL(register_jprobes);
 EXPORT_SYMBOL_GPL(unregister_jprobes);
-#ifdef CONFIG_KPROBES
 EXPORT_SYMBOL_GPL(jprobe_return);
-#endif
-
-#ifdef CONFIG_KPROBES
 EXPORT_SYMBOL_GPL(register_kretprobe);
 EXPORT_SYMBOL_GPL(unregister_kretprobe);
 EXPORT_SYMBOL_GPL(register_kretprobes);
 EXPORT_SYMBOL_GPL(unregister_kretprobes);
-#endif
index ac3fb73266412eaaaad2a904cb5bbe7917a159b7..96cff2f8710baac71e7ce91ec96202665142b5e8 100644 (file)
@@ -106,7 +106,7 @@ static void create_kthread(struct kthread_create_info *create)
                 */
                sched_setscheduler(create->result, SCHED_NORMAL, &param);
                set_user_nice(create->result, KTHREAD_NICE_LEVEL);
-               set_cpus_allowed(create->result, CPU_MASK_ALL);
+               set_cpus_allowed_ptr(create->result, CPU_MASK_ALL_PTR);
        }
        complete(&create->done);
 }
@@ -176,7 +176,7 @@ void kthread_bind(struct task_struct *k, unsigned int cpu)
                return;
        }
        /* Must have done schedule() in kthread() before we set_task_cpu */
-       wait_task_inactive(k);
+       wait_task_inactive(k, 0);
        set_task_cpu(k, cpu);
        k->cpus_allowed = cpumask_of_cpu(cpu);
        k->rt.nr_cpus_allowed = 1;
@@ -233,7 +233,7 @@ int kthreadd(void *unused)
        set_task_comm(tsk, "kthreadd");
        ignore_signals(tsk);
        set_user_nice(tsk, KTHREAD_NICE_LEVEL);
-       set_cpus_allowed(tsk, CPU_MASK_ALL);
+       set_cpus_allowed_ptr(tsk, CPU_MASK_ALL_PTR);
 
        current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG;
 
index 1abfb923b761f46b3266ec471924ade4fc593ef2..971da531790316bbe4bff400d7dec77e46c76a42 100644 (file)
@@ -441,7 +441,7 @@ static int remove_marker(const char *name)
        hlist_del(&e->hlist);
        /* Make sure the call_rcu has been executed */
        if (e->rcu_pending)
-               rcu_barrier();
+               rcu_barrier_sched();
        kfree(e);
        return 0;
 }
@@ -476,7 +476,7 @@ static int marker_set_format(struct marker_entry **entry, const char *format)
        hlist_del(&(*entry)->hlist);
        /* Make sure the call_rcu has been executed */
        if ((*entry)->rcu_pending)
-               rcu_barrier();
+               rcu_barrier_sched();
        kfree(*entry);
        *entry = e;
        trace_mark(core_marker_format, "name %s format %s",
@@ -655,7 +655,7 @@ int marker_probe_register(const char *name, const char *format,
         * make sure it's executed now.
         */
        if (entry->rcu_pending)
-               rcu_barrier();
+               rcu_barrier_sched();
        old = marker_entry_add_probe(entry, probe, probe_private);
        if (IS_ERR(old)) {
                ret = PTR_ERR(old);
@@ -670,10 +670,7 @@ int marker_probe_register(const char *name, const char *format,
        entry->rcu_pending = 1;
        /* write rcu_pending before calling the RCU callback */
        smp_wmb();
-#ifdef CONFIG_PREEMPT_RCU
-       synchronize_sched();    /* Until we have the call_rcu_sched() */
-#endif
-       call_rcu(&entry->rcu, free_old_closure);
+       call_rcu_sched(&entry->rcu, free_old_closure);
 end:
        mutex_unlock(&markers_mutex);
        return ret;
@@ -704,7 +701,7 @@ int marker_probe_unregister(const char *name,
        if (!entry)
                goto end;
        if (entry->rcu_pending)
-               rcu_barrier();
+               rcu_barrier_sched();
        old = marker_entry_remove_probe(entry, probe, probe_private);
        mutex_unlock(&markers_mutex);
        marker_update_probes();         /* may update entry */
@@ -716,10 +713,7 @@ int marker_probe_unregister(const char *name,
        entry->rcu_pending = 1;
        /* write rcu_pending before calling the RCU callback */
        smp_wmb();
-#ifdef CONFIG_PREEMPT_RCU
-       synchronize_sched();    /* Until we have the call_rcu_sched() */
-#endif
-       call_rcu(&entry->rcu, free_old_closure);
+       call_rcu_sched(&entry->rcu, free_old_closure);
        remove_marker(name);    /* Ignore busy error message */
        ret = 0;
 end:
@@ -786,7 +780,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe,
                goto end;
        }
        if (entry->rcu_pending)
-               rcu_barrier();
+               rcu_barrier_sched();
        old = marker_entry_remove_probe(entry, NULL, probe_private);
        mutex_unlock(&markers_mutex);
        marker_update_probes();         /* may update entry */
@@ -797,10 +791,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe,
        entry->rcu_pending = 1;
        /* write rcu_pending before calling the RCU callback */
        smp_wmb();
-#ifdef CONFIG_PREEMPT_RCU
-       synchronize_sched();    /* Until we have the call_rcu_sched() */
-#endif
-       call_rcu(&entry->rcu, free_old_closure);
+       call_rcu_sched(&entry->rcu, free_old_closure);
        remove_marker(entry->name);     /* Ignore busy error message */
 end:
        mutex_unlock(&markers_mutex);
index d8b5605132a038114c53a52279a71d7ba33c88b6..61d212120df48e82a1b6521120fdbd428d983a81 100644 (file)
@@ -325,18 +325,6 @@ static unsigned long find_symbol(const char *name,
        return -ENOENT;
 }
 
-/* lookup symbol in given range of kernel_symbols */
-static const struct kernel_symbol *lookup_symbol(const char *name,
-       const struct kernel_symbol *start,
-       const struct kernel_symbol *stop)
-{
-       const struct kernel_symbol *ks = start;
-       for (; ks < stop; ks++)
-               if (strcmp(ks->name, name) == 0)
-                       return ks;
-       return NULL;
-}
-
 /* Search for module by name: must hold module_mutex. */
 static struct module *find_module(const char *name)
 {
@@ -690,7 +678,7 @@ static int try_stop_module(struct module *mod, int flags, int *forced)
        if (flags & O_NONBLOCK) {
                struct stopref sref = { mod, flags, forced };
 
-               return stop_machine_run(__try_stop_module, &sref, NR_CPUS);
+               return stop_machine(__try_stop_module, &sref, NULL);
        } else {
                /* We don't need to stop the machine for this. */
                mod->state = MODULE_STATE_GOING;
@@ -1428,7 +1416,7 @@ static int __unlink_module(void *_mod)
 static void free_module(struct module *mod)
 {
        /* Delete from various lists */
-       stop_machine_run(__unlink_module, mod, NR_CPUS);
+       stop_machine(__unlink_module, mod, NULL);
        remove_notes_attrs(mod);
        remove_sect_attrs(mod);
        mod_kobject_remove(mod);
@@ -1703,6 +1691,19 @@ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
 }
 
 #ifdef CONFIG_KALLSYMS
+
+/* lookup symbol in given range of kernel_symbols */
+static const struct kernel_symbol *lookup_symbol(const char *name,
+       const struct kernel_symbol *start,
+       const struct kernel_symbol *stop)
+{
+       const struct kernel_symbol *ks = start;
+       for (; ks < stop; ks++)
+               if (strcmp(ks->name, name) == 0)
+                       return ks;
+       return NULL;
+}
+
 static int is_exported(const char *name, const struct module *mod)
 {
        if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab))
@@ -2196,7 +2197,7 @@ static struct module *load_module(void __user *umod,
        /* Now sew it into the lists so we can get lockdep and oops
          * info during argument parsing.  Noone should access us, since
          * strong_try_module_get() will fail. */
-       stop_machine_run(__link_module, mod, NR_CPUS);
+       stop_machine(__link_module, mod, NULL);
 
        /* Size of section 0 is 0, so this works well if no params */
        err = parse_args(mod->name, mod->args,
@@ -2230,7 +2231,7 @@ static struct module *load_module(void __user *umod,
        return mod;
 
  unlink:
-       stop_machine_run(__unlink_module, mod, NR_CPUS);
+       stop_machine(__unlink_module, mod, NULL);
        module_arch_cleanup(mod);
  cleanup:
        kobject_del(&mod->mkobj.kobj);
index 48d7ed6fc3a4d2dcc206d5eb304f55ae7436ac70..43c2111cd54de719917c0cdc9ace9e92445f4513 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/module.h>
 #include <linux/cgroup.h>
 #include <linux/fs.h>
+#include <linux/proc_fs.h>
 #include <linux/slab.h>
 #include <linux/nsproxy.h>
 
@@ -24,9 +25,12 @@ static inline struct ns_cgroup *cgroup_to_ns(
                            struct ns_cgroup, css);
 }
 
-int ns_cgroup_clone(struct task_struct *task)
+int ns_cgroup_clone(struct task_struct *task, struct pid *pid)
 {
-       return cgroup_clone(task, &ns_subsys);
+       char name[PROC_NUMBUF];
+
+       snprintf(name, PROC_NUMBUF, "%d", pid_vnr(pid));
+       return cgroup_clone(task, &ns_subsys, name);
 }
 
 /*
index adc785146a1cb81d6f7b3d676877921f10bb59e7..21575fc46d0597914d4b92b5749c53f59f9be4e1 100644 (file)
@@ -157,12 +157,6 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
                goto out;
        }
 
-       err = ns_cgroup_clone(tsk);
-       if (err) {
-               put_nsproxy(new_ns);
-               goto out;
-       }
-
        tsk->nsproxy = new_ns;
 
 out:
@@ -209,7 +203,7 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
                goto out;
        }
 
-       err = ns_cgroup_clone(current);
+       err = ns_cgroup_clone(current, task_pid(current));
        if (err)
                put_nsproxy(*new_nsp);
 
index 425567f45b9f776148f1767b2f4af2d357a0c2fd..12c5a0a6c89bee42e44c65ee41eb4695ae180983 100644 (file)
@@ -318,6 +318,28 @@ void warn_on_slowpath(const char *file, int line)
        add_taint(TAINT_WARN);
 }
 EXPORT_SYMBOL(warn_on_slowpath);
+
+
+void warn_slowpath(const char *file, int line, const char *fmt, ...)
+{
+       va_list args;
+       char function[KSYM_SYMBOL_LEN];
+       unsigned long caller = (unsigned long)__builtin_return_address(0);
+       sprint_symbol(function, caller);
+
+       printk(KERN_WARNING "------------[ cut here ]------------\n");
+       printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file,
+               line, function);
+       va_start(args, fmt);
+       vprintk(fmt, args);
+       va_end(args);
+
+       print_modules();
+       dump_stack();
+       print_oops_end_marker();
+       add_taint(TAINT_WARN);
+}
+EXPORT_SYMBOL(warn_slowpath);
 #endif
 
 #ifdef CONFIG_CC_STACKPROTECTOR
index 30bd5d4b2ac7b7f2f822ba2b69d2726395974df6..064e76afa507a252f6f4de8aec046f03c6cc62a7 100644 (file)
@@ -309,12 +309,6 @@ struct pid *find_vpid(int nr)
 }
 EXPORT_SYMBOL_GPL(find_vpid);
 
-struct pid *find_pid(int nr)
-{
-       return find_pid_ns(nr, &init_pid_ns);
-}
-EXPORT_SYMBOL_GPL(find_pid);
-
 /*
  * attach_pid() must be called with the tasklist_lock write-held.
  */
@@ -435,6 +429,7 @@ struct pid *find_get_pid(pid_t nr)
 
        return pid;
 }
+EXPORT_SYMBOL_GPL(find_get_pid);
 
 pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
 {
@@ -482,7 +477,7 @@ EXPORT_SYMBOL(task_session_nr_ns);
 /*
  * Used by proc to find the first pid that is greater then or equal to nr.
  *
- * If there is a pid at nr this function is exactly the same as find_pid.
+ * If there is a pid at nr this function is exactly the same as find_pid_ns.
  */
 struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
 {
@@ -497,7 +492,6 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
 
        return pid;
 }
-EXPORT_SYMBOL_GPL(find_get_pid);
 
 /*
  * The pid hash table is scaled according to the amount of memory in the
index 98702b4b8851762969d9ddad76505e5739e8166c..ea567b78d1aa6111bf207ac0556ff1e35b088794 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/pid_namespace.h>
 #include <linux/syscalls.h>
 #include <linux/err.h>
+#include <linux/acct.h>
 
 #define BITS_PER_PAGE          (PAGE_SIZE*8)
 
@@ -71,7 +72,7 @@ static struct pid_namespace *create_pid_namespace(unsigned int level)
        struct pid_namespace *ns;
        int i;
 
-       ns = kmem_cache_alloc(pid_ns_cachep, GFP_KERNEL);
+       ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
        if (ns == NULL)
                goto out;
 
@@ -84,17 +85,13 @@ static struct pid_namespace *create_pid_namespace(unsigned int level)
                goto out_free_map;
 
        kref_init(&ns->kref);
-       ns->last_pid = 0;
-       ns->child_reaper = NULL;
        ns->level = level;
 
        set_bit(0, ns->pidmap[0].page);
        atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1);
 
-       for (i = 1; i < PIDMAP_ENTRIES; i++) {
-               ns->pidmap[i].page = NULL;
+       for (i = 1; i < PIDMAP_ENTRIES; i++)
                atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE);
-       }
 
        return ns;
 
@@ -185,6 +182,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
 
        /* Child reaper for the pid namespace is going away */
        pid_ns->child_reaper = NULL;
+       acct_exit_ns(pid_ns);
        return;
 }
 
index dbd8398ddb0b41fa1f391849b82199078e72de70..9a21681aa80f82f0123917725f341a526d484c89 100644 (file)
@@ -449,9 +449,6 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set)
                spin_unlock_irqrestore(&idr_lock, flags);
        }
        sigqueue_free(tmr->sigq);
-       if (unlikely(tmr->it_process) &&
-           tmr->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
-               put_task_struct(tmr->it_process);
        kmem_cache_free(posix_timers_cache, tmr);
 }
 
@@ -856,11 +853,10 @@ retry_delete:
         * This keeps any tasks waiting on the spin lock from thinking
         * they got something (see the lock code above).
         */
-       if (timer->it_process) {
-               if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
-                       put_task_struct(timer->it_process);
-               timer->it_process = NULL;
-       }
+       if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
+               put_task_struct(timer->it_process);
+       timer->it_process = NULL;
+
        unlock_timer(timer, flags);
        release_posix_timer(timer, IT_ID_SET);
        return 0;
@@ -885,11 +881,10 @@ retry_delete:
         * This keeps any tasks waiting on the spin lock from thinking
         * they got something (see the lock code above).
         */
-       if (timer->it_process) {
-               if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
-                       put_task_struct(timer->it_process);
-               timer->it_process = NULL;
-       }
+       if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
+               put_task_struct(timer->it_process);
+       timer->it_process = NULL;
+
        unlock_timer(timer, flags);
        release_posix_timer(timer, IT_ID_SET);
 }
index 59dfdf1e1d2071ba29b711fbb2b34d28a57cd998..dcd165f92a887881eefaf9f67bf6c612a4a94547 100644 (file)
@@ -94,6 +94,17 @@ config SUSPEND
          powered and thus its contents are preserved, such as the
          suspend-to-RAM state (e.g. the ACPI S3 state).
 
+config PM_TEST_SUSPEND
+       bool "Test suspend/resume and wakealarm during bootup"
+       depends on SUSPEND && PM_DEBUG && RTC_LIB=y
+       ---help---
+       This option will let you suspend your machine during bootup, and
+       make it wake up a few seconds later using an RTC wakeup alarm.
+       Enable this with a kernel parameter like "test_suspend=mem".
+
+       You probably want to have your system's RTC driver statically
+       linked, ensuring that it's available when this test runs.
+
 config SUSPEND_FREEZER
        bool "Enable freezer for suspend to RAM/standby" \
                if ARCH_WANTS_FREEZER_CONTROL || BROKEN
index 3398f4651aa150b370a6eeef95305ca56ff39a0b..0b7476f5d2a64fc848b88bfc51a06eb8d233eae1 100644 (file)
@@ -132,6 +132,61 @@ static inline int suspend_test(int level) { return 0; }
 
 #ifdef CONFIG_SUSPEND
 
+#ifdef CONFIG_PM_TEST_SUSPEND
+
+/*
+ * We test the system suspend code by setting an RTC wakealarm a short
+ * time in the future, then suspending.  Suspending the devices won't
+ * normally take long ... some systems only need a few milliseconds.
+ *
+ * The time it takes is system-specific though, so when we test this
+ * during system bootup we allow a LOT of time.
+ */
+#define TEST_SUSPEND_SECONDS   5
+
+static unsigned long suspend_test_start_time;
+
+static void suspend_test_start(void)
+{
+       /* FIXME Use better timebase than "jiffies", ideally a clocksource.
+        * What we want is a hardware counter that will work correctly even
+        * during the irqs-are-off stages of the suspend/resume cycle...
+        */
+       suspend_test_start_time = jiffies;
+}
+
+static void suspend_test_finish(const char *label)
+{
+       long nj = jiffies - suspend_test_start_time;
+       unsigned msec;
+
+       msec = jiffies_to_msecs(abs(nj));
+       pr_info("PM: %s took %d.%03d seconds\n", label,
+                       msec / 1000, msec % 1000);
+
+       /* Warning on suspend means the RTC alarm period needs to be
+        * larger -- the system was sooo slooowwww to suspend that the
+        * alarm (should have) fired before the system went to sleep!
+        *
+        * Warning on either suspend or resume also means the system
+        * has some performance issues.  The stack dump of a WARN_ON
+        * is more likely to get the right attention than a printk...
+        */
+       WARN_ON(msec > (TEST_SUSPEND_SECONDS * 1000));
+}
+
+#else
+
+static void suspend_test_start(void)
+{
+}
+
+static void suspend_test_finish(const char *label)
+{
+}
+
+#endif
+
 /* This is just an arbitrary number */
 #define FREE_PAGE_NUMBER (100)
 
@@ -266,12 +321,13 @@ int suspend_devices_and_enter(suspend_state_t state)
                        goto Close;
        }
        suspend_console();
+       suspend_test_start();
        error = device_suspend(PMSG_SUSPEND);
        if (error) {
                printk(KERN_ERR "PM: Some devices failed to suspend\n");
                goto Recover_platform;
        }
-
+       suspend_test_finish("suspend devices");
        if (suspend_test(TEST_DEVICES))
                goto Recover_platform;
 
@@ -293,7 +349,9 @@ int suspend_devices_and_enter(suspend_state_t state)
        if (suspend_ops->finish)
                suspend_ops->finish();
  Resume_devices:
+       suspend_test_start();
        device_resume(PMSG_RESUME);
+       suspend_test_finish("resume devices");
        resume_console();
  Close:
        if (suspend_ops->end)
@@ -521,3 +579,144 @@ static int __init pm_init(void)
 }
 
 core_initcall(pm_init);
+
+
+#ifdef CONFIG_PM_TEST_SUSPEND
+
+#include <linux/rtc.h>
+
+/*
+ * To test system suspend, we need a hands-off mechanism to resume the
+ * system.  RTCs wake alarms are a common self-contained mechanism.
+ */
+
+static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)
+{
+       static char err_readtime[] __initdata =
+               KERN_ERR "PM: can't read %s time, err %d\n";
+       static char err_wakealarm [] __initdata =
+               KERN_ERR "PM: can't set %s wakealarm, err %d\n";
+       static char err_suspend[] __initdata =
+               KERN_ERR "PM: suspend test failed, error %d\n";
+       static char info_test[] __initdata =
+               KERN_INFO "PM: test RTC wakeup from '%s' suspend\n";
+
+       unsigned long           now;
+       struct rtc_wkalrm       alm;
+       int                     status;
+
+       /* this may fail if the RTC hasn't been initialized */
+       status = rtc_read_time(rtc, &alm.time);
+       if (status < 0) {
+               printk(err_readtime, rtc->dev.bus_id, status);
+               return;
+       }
+       rtc_tm_to_time(&alm.time, &now);
+
+       memset(&alm, 0, sizeof alm);
+       rtc_time_to_tm(now + TEST_SUSPEND_SECONDS, &alm.time);
+       alm.enabled = true;
+
+       status = rtc_set_alarm(rtc, &alm);
+       if (status < 0) {
+               printk(err_wakealarm, rtc->dev.bus_id, status);
+               return;
+       }
+
+       if (state == PM_SUSPEND_MEM) {
+               printk(info_test, pm_states[state]);
+               status = pm_suspend(state);
+               if (status == -ENODEV)
+                       state = PM_SUSPEND_STANDBY;
+       }
+       if (state == PM_SUSPEND_STANDBY) {
+               printk(info_test, pm_states[state]);
+               status = pm_suspend(state);
+       }
+       if (status < 0)
+               printk(err_suspend, status);
+
+       /* Some platforms can't detect that the alarm triggered the
+        * wakeup, or (accordingly) disable it after it afterwards.
+        * It's supposed to give oneshot behavior; cope.
+        */
+       alm.enabled = false;
+       rtc_set_alarm(rtc, &alm);
+}
+
+static int __init has_wakealarm(struct device *dev, void *name_ptr)
+{
+       struct rtc_device *candidate = to_rtc_device(dev);
+
+       if (!candidate->ops->set_alarm)
+               return 0;
+       if (!device_may_wakeup(candidate->dev.parent))
+               return 0;
+
+       *(char **)name_ptr = dev->bus_id;
+       return 1;
+}
+
+/*
+ * Kernel options like "test_suspend=mem" force suspend/resume sanity tests
+ * at startup time.  They're normally disabled, for faster boot and because
+ * we can't know which states really work on this particular system.
+ */
+static suspend_state_t test_state __initdata = PM_SUSPEND_ON;
+
+static char warn_bad_state[] __initdata =
+       KERN_WARNING "PM: can't test '%s' suspend state\n";
+
+static int __init setup_test_suspend(char *value)
+{
+       unsigned i;
+
+       /* "=mem" ==> "mem" */
+       value++;
+       for (i = 0; i < PM_SUSPEND_MAX; i++) {
+               if (!pm_states[i])
+                       continue;
+               if (strcmp(pm_states[i], value) != 0)
+                       continue;
+               test_state = (__force suspend_state_t) i;
+               return 0;
+       }
+       printk(warn_bad_state, value);
+       return 0;
+}
+__setup("test_suspend", setup_test_suspend);
+
+static int __init test_suspend(void)
+{
+       static char             warn_no_rtc[] __initdata =
+               KERN_WARNING "PM: no wakealarm-capable RTC driver is ready\n";
+
+       char                    *pony = NULL;
+       struct rtc_device       *rtc = NULL;
+
+       /* PM is initialized by now; is that state testable? */
+       if (test_state == PM_SUSPEND_ON)
+               goto done;
+       if (!valid_state(test_state)) {
+               printk(warn_bad_state, pm_states[test_state]);
+               goto done;
+       }
+
+       /* RTCs have initialized by now too ... can we use one? */
+       class_find_device(rtc_class, NULL, &pony, has_wakealarm);
+       if (pony)
+               rtc = rtc_class_open(pony);
+       if (!rtc) {
+               printk(warn_no_rtc);
+               goto done;
+       }
+
+       /* go for it */
+       test_wakealarm(rtc, test_state);
+       rtc_class_close(rtc);
+done:
+       return 0;
+}
+late_initcall(test_suspend);
+
+#endif /* CONFIG_PM_TEST_SUSPEND */
index 700f44ec84067860cb86a79ff8201934c3c59e66..acc0c101dbd54a510049a329260434d56b3c12f9 100644 (file)
@@ -53,8 +53,6 @@ extern int hibernation_platform_enter(void);
 
 extern int pfn_is_nosave(unsigned long);
 
-extern struct mutex pm_mutex;
-
 #define power_attr(_name) \
 static struct kobj_attribute _name##_attr = {  \
        .attr   = {                             \
index 678ec736076b1395b4a16949cb5f595b72bdd616..72016f051477c62941fb7e24697f9b6b87889b96 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/pm.h>
 #include <linux/workqueue.h>
 #include <linux/reboot.h>
+#include <linux/cpumask.h>
 
 /*
  * When the user hits Sys-Rq o to power down the machine this is the
@@ -25,7 +26,8 @@ static DECLARE_WORK(poweroff_work, do_poweroff);
 
 static void handle_poweroff(int key, struct tty_struct *tty)
 {
-       schedule_work(&poweroff_work);
+       /* run sysrq poweroff on boot cpu */
+       schedule_work_on(first_cpu(cpu_online_map), &poweroff_work);
 }
 
 static struct sysrq_key_op     sysrq_poweroff_op = {
index 5fb87652f2149dd3a34f94e61e9a961303611e59..278946aecaf0d24b46b0736506de8ca3aafdc873 100644 (file)
@@ -149,7 +149,7 @@ static int try_to_freeze_tasks(bool sig_only)
        unsigned long end_time;
        unsigned int todo;
        struct timeval start, end;
-       s64 elapsed_csecs64;
+       u64 elapsed_csecs64;
        unsigned int elapsed_csecs;
 
        do_gettimeofday(&start);
index 5f91a07c4eac7e104f3fc9c333a481be11ead921..5d2ab836e9986f650bc86cecc8d45a8f757d15ff 100644 (file)
@@ -205,8 +205,7 @@ static void chain_free(struct chain_allocator *ca, int clear_page_nosave)
  *     objects.  The main list's elements are of type struct zone_bitmap
  *     and each of them corresonds to one zone.  For each zone bitmap
  *     object there is a list of objects of type struct bm_block that
- *     represent each blocks of bit chunks in which information is
- *     stored.
+ *     represent each blocks of bitmap in which information is stored.
  *
  *     struct memory_bitmap contains a pointer to the main list of zone
  *     bitmap objects, a struct bm_position used for browsing the bitmap,
@@ -224,26 +223,27 @@ static void chain_free(struct chain_allocator *ca, int clear_page_nosave)
  *     pfns that correspond to the start and end of the represented zone.
  *
  *     struct bm_block contains a pointer to the memory page in which
- *     information is stored (in the form of a block of bit chunks
- *     of type unsigned long each).  It also contains the pfns that
- *     correspond to the start and end of the represented memory area and
- *     the number of bit chunks in the block.
+ *     information is stored (in the form of a block of bitmap)
+ *     It also contains the pfns that correspond to the start and end of
+ *     the represented memory area.
  */
 
 #define BM_END_OF_MAP  (~0UL)
 
-#define BM_CHUNKS_PER_BLOCK    (PAGE_SIZE / sizeof(long))
-#define BM_BITS_PER_CHUNK      (sizeof(long) << 3)
 #define BM_BITS_PER_BLOCK      (PAGE_SIZE << 3)
 
 struct bm_block {
        struct bm_block *next;          /* next element of the list */
        unsigned long start_pfn;        /* pfn represented by the first bit */
        unsigned long end_pfn;  /* pfn represented by the last bit plus 1 */
-       unsigned int size;      /* number of bit chunks */
-       unsigned long *data;    /* chunks of bits representing pages */
+       unsigned long *data;    /* bitmap representing pages */
 };
 
+static inline unsigned long bm_block_bits(struct bm_block *bb)
+{
+       return bb->end_pfn - bb->start_pfn;
+}
+
 struct zone_bitmap {
        struct zone_bitmap *next;       /* next element of the list */
        unsigned long start_pfn;        /* minimal pfn in this zone */
@@ -257,7 +257,6 @@ struct zone_bitmap {
 struct bm_position {
        struct zone_bitmap *zone_bm;
        struct bm_block *block;
-       int chunk;
        int bit;
 };
 
@@ -272,12 +271,6 @@ struct memory_bitmap {
 
 /* Functions that operate on memory bitmaps */
 
-static inline void memory_bm_reset_chunk(struct memory_bitmap *bm)
-{
-       bm->cur.chunk = 0;
-       bm->cur.bit = -1;
-}
-
 static void memory_bm_position_reset(struct memory_bitmap *bm)
 {
        struct zone_bitmap *zone_bm;
@@ -285,7 +278,7 @@ static void memory_bm_position_reset(struct memory_bitmap *bm)
        zone_bm = bm->zone_bm_list;
        bm->cur.zone_bm = zone_bm;
        bm->cur.block = zone_bm->bm_blocks;
-       memory_bm_reset_chunk(bm);
+       bm->cur.bit = 0;
 }
 
 static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free);
@@ -394,12 +387,10 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed)
                        bb->start_pfn = pfn;
                        if (nr >= BM_BITS_PER_BLOCK) {
                                pfn += BM_BITS_PER_BLOCK;
-                               bb->size = BM_CHUNKS_PER_BLOCK;
                                nr -= BM_BITS_PER_BLOCK;
                        } else {
                                /* This is executed only once in the loop */
                                pfn += nr;
-                               bb->size = DIV_ROUND_UP(nr, BM_BITS_PER_CHUNK);
                        }
                        bb->end_pfn = pfn;
                        bb = bb->next;
@@ -478,8 +469,8 @@ static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
        }
        zone_bm->cur_block = bb;
        pfn -= bb->start_pfn;
-       *bit_nr = pfn % BM_BITS_PER_CHUNK;
-       *addr = bb->data + pfn / BM_BITS_PER_CHUNK;
+       *bit_nr = pfn;
+       *addr = bb->data;
        return 0;
 }
 
@@ -528,36 +519,6 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
        return test_bit(bit, addr);
 }
 
-/* Two auxiliary functions for memory_bm_next_pfn */
-
-/* Find the first set bit in the given chunk, if there is one */
-
-static inline int next_bit_in_chunk(int bit, unsigned long *chunk_p)
-{
-       bit++;
-       while (bit < BM_BITS_PER_CHUNK) {
-               if (test_bit(bit, chunk_p))
-                       return bit;
-
-               bit++;
-       }
-       return -1;
-}
-
-/* Find a chunk containing some bits set in given block of bits */
-
-static inline int next_chunk_in_block(int n, struct bm_block *bb)
-{
-       n++;
-       while (n < bb->size) {
-               if (bb->data[n])
-                       return n;
-
-               n++;
-       }
-       return -1;
-}
-
 /**
  *     memory_bm_next_pfn - find the pfn that corresponds to the next set bit
  *     in the bitmap @bm.  If the pfn cannot be found, BM_END_OF_MAP is
@@ -571,40 +532,33 @@ static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm)
 {
        struct zone_bitmap *zone_bm;
        struct bm_block *bb;
-       int chunk;
        int bit;
 
        do {
                bb = bm->cur.block;
                do {
-                       chunk = bm->cur.chunk;
                        bit = bm->cur.bit;
-                       do {
-                               bit = next_bit_in_chunk(bit, bb->data + chunk);
-                               if (bit >= 0)
-                                       goto Return_pfn;
-
-                               chunk = next_chunk_in_block(chunk, bb);
-                               bit = -1;
-                       } while (chunk >= 0);
+                       bit = find_next_bit(bb->data, bm_block_bits(bb), bit);
+                       if (bit < bm_block_bits(bb))
+                               goto Return_pfn;
+
                        bb = bb->next;
                        bm->cur.block = bb;
-                       memory_bm_reset_chunk(bm);
+                       bm->cur.bit = 0;
                } while (bb);
                zone_bm = bm->cur.zone_bm->next;
                if (zone_bm) {
                        bm->cur.zone_bm = zone_bm;
                        bm->cur.block = zone_bm->bm_blocks;
-                       memory_bm_reset_chunk(bm);
+                       bm->cur.bit = 0;
                }
        } while (zone_bm);
        memory_bm_position_reset(bm);
        return BM_END_OF_MAP;
 
  Return_pfn:
-       bm->cur.chunk = chunk;
-       bm->cur.bit = bit;
-       return bb->start_pfn + chunk * BM_BITS_PER_CHUNK + bit;
+       bm->cur.bit = bit + 1;
+       return bb->start_pfn + bit;
 }
 
 /**
index 07ad9e7f7a66a85fb71a759c0408ccfcab60256a..a7f7559c5f6cbc2a06413622a09dd3a0bc21782d 100644 (file)
@@ -933,7 +933,7 @@ void suspend_console(void)
 {
        if (!console_suspend_enabled)
                return;
-       printk("Suspending console(s)\n");
+       printk("Suspending console(s) (use no_console_suspend to debug)\n");
        acquire_console_sem();
        console_suspended = 1;
 }
@@ -1308,6 +1308,8 @@ void tty_write_message(struct tty_struct *tty, char *msg)
 }
 
 #if defined CONFIG_PRINTK
+
+DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10);
 /*
  * printk rate limiting, lifted from the networking subsystem.
  *
@@ -1315,22 +1317,9 @@ void tty_write_message(struct tty_struct *tty, char *msg)
  * every printk_ratelimit_jiffies to make a denial-of-service
  * attack impossible.
  */
-int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
-{
-       return __ratelimit(ratelimit_jiffies, ratelimit_burst);
-}
-EXPORT_SYMBOL(__printk_ratelimit);
-
-/* minimum time in jiffies between messages */
-int printk_ratelimit_jiffies = 5 * HZ;
-
-/* number of messages we send before ratelimiting */
-int printk_ratelimit_burst = 10;
-
 int printk_ratelimit(void)
 {
-       return __printk_ratelimit(printk_ratelimit_jiffies,
-                               printk_ratelimit_burst);
+       return __ratelimit(&printk_ratelimit_state);
 }
 EXPORT_SYMBOL(printk_ratelimit);
 
index 58926411eb2a5c6ca43bb6fd18b140ddeb6d9515..cd26bed4cc26535ca7398eae07fb9b800b762f2e 100644 (file)
@@ -112,8 +112,6 @@ void __init profile_init(void)
 
 /* Profile event notifications */
 
-#ifdef CONFIG_PROFILING
-
 static BLOCKING_NOTIFIER_HEAD(task_exit_notifier);
 static ATOMIC_NOTIFIER_HEAD(task_free_notifier);
 static BLOCKING_NOTIFIER_HEAD(munmap_notifier);
@@ -203,8 +201,6 @@ void unregister_timer_hook(int (*hook)(struct pt_regs *))
 }
 EXPORT_SYMBOL_GPL(unregister_timer_hook);
 
-#endif /* CONFIG_PROFILING */
-
 
 #ifdef CONFIG_SMP
 /*
index 8392a9da64504054bf804e5809f902bc296f676f..082b3fcb32a09e2110c97b6c7527d5f3eca137b7 100644 (file)
@@ -107,7 +107,7 @@ int ptrace_check_attach(struct task_struct *child, int kill)
        read_unlock(&tasklist_lock);
 
        if (!ret && !kill)
-               wait_task_inactive(child);
+               ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH;
 
        /* All systems go.. */
        return ret;
index 6f8696c502f429ebcbaf65e537fdf47e3127d300..aad93cdc9f68656b95eb496003c593d5d03beed4 100644 (file)
@@ -91,8 +91,8 @@ static void force_quiescent_state(struct rcu_data *rdp,
                 * rdp->cpu is the current cpu.
                 *
                 * cpu_online_map is updated by the _cpu_down()
-                * using stop_machine_run(). Since we're in irqs disabled
-                * section, stop_machine_run() is not exectuting, hence
+                * using __stop_machine(). Since we're in irqs disabled
+                * section, __stop_machine() is not exectuting, hence
                 * the cpu_online_map is stable.
                 *
                 * However,  a cpu might have been offlined _just_ before
index 7de644cdec43590be390d3037206e5722aa46856..04006ef970b818b01d6cb152c5a5997896a06478 100644 (file)
@@ -407,6 +407,35 @@ void relay_reset(struct rchan *chan)
 }
 EXPORT_SYMBOL_GPL(relay_reset);
 
+static inline void relay_set_buf_dentry(struct rchan_buf *buf,
+                                       struct dentry *dentry)
+{
+       buf->dentry = dentry;
+       buf->dentry->d_inode->i_size = buf->early_bytes;
+}
+
+static struct dentry *relay_create_buf_file(struct rchan *chan,
+                                           struct rchan_buf *buf,
+                                           unsigned int cpu)
+{
+       struct dentry *dentry;
+       char *tmpname;
+
+       tmpname = kzalloc(NAME_MAX + 1, GFP_KERNEL);
+       if (!tmpname)
+               return NULL;
+       snprintf(tmpname, NAME_MAX, "%s%d", chan->base_filename, cpu);
+
+       /* Create file in fs */
+       dentry = chan->cb->create_buf_file(tmpname, chan->parent,
+                                          S_IRUSR, buf,
+                                          &chan->is_global);
+
+       kfree(tmpname);
+
+       return dentry;
+}
+
 /*
  *     relay_open_buf - create a new relay channel buffer
  *
@@ -416,45 +445,34 @@ static struct rchan_buf *relay_open_buf(struct rchan *chan, unsigned int cpu)
 {
        struct rchan_buf *buf = NULL;
        struct dentry *dentry;
-       char *tmpname;
 
        if (chan->is_global)
                return chan->buf[0];
 
-       tmpname = kzalloc(NAME_MAX + 1, GFP_KERNEL);
-       if (!tmpname)
-               goto end;
-       snprintf(tmpname, NAME_MAX, "%s%d", chan->base_filename, cpu);
-
        buf = relay_create_buf(chan);
        if (!buf)
-               goto free_name;
+               return NULL;
+
+       if (chan->has_base_filename) {
+               dentry = relay_create_buf_file(chan, buf, cpu);
+               if (!dentry)
+                       goto free_buf;
+               relay_set_buf_dentry(buf, dentry);
+       }
 
        buf->cpu = cpu;
        __relay_reset(buf, 1);
 
-       /* Create file in fs */
-       dentry = chan->cb->create_buf_file(tmpname, chan->parent, S_IRUSR,
-                                          buf, &chan->is_global);
-       if (!dentry)
-               goto free_buf;
-
-       buf->dentry = dentry;
-
        if(chan->is_global) {
                chan->buf[0] = buf;
                buf->cpu = 0;
        }
 
-       goto free_name;
+       return buf;
 
 free_buf:
        relay_destroy_buf(buf);
-       buf = NULL;
-free_name:
-       kfree(tmpname);
-end:
-       return buf;
+       return NULL;
 }
 
 /**
@@ -537,8 +555,8 @@ static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb,
 
 /**
  *     relay_open - create a new relay channel
- *     @base_filename: base name of files to create
- *     @parent: dentry of parent directory, %NULL for root directory
+ *     @base_filename: base name of files to create, %NULL for buffering only
+ *     @parent: dentry of parent directory, %NULL for root directory or buffer
  *     @subbuf_size: size of sub-buffers
  *     @n_subbufs: number of sub-buffers
  *     @cb: client callback functions
@@ -560,8 +578,6 @@ struct rchan *relay_open(const char *base_filename,
 {
        unsigned int i;
        struct rchan *chan;
-       if (!base_filename)
-               return NULL;
 
        if (!(subbuf_size && n_subbufs))
                return NULL;
@@ -576,7 +592,10 @@ struct rchan *relay_open(const char *base_filename,
        chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs);
        chan->parent = parent;
        chan->private_data = private_data;
-       strlcpy(chan->base_filename, base_filename, NAME_MAX);
+       if (base_filename) {
+               chan->has_base_filename = 1;
+               strlcpy(chan->base_filename, base_filename, NAME_MAX);
+       }
        setup_callbacks(chan, cb);
        kref_init(&chan->kref);
 
@@ -604,6 +623,94 @@ free_bufs:
 }
 EXPORT_SYMBOL_GPL(relay_open);
 
+struct rchan_percpu_buf_dispatcher {
+       struct rchan_buf *buf;
+       struct dentry *dentry;
+};
+
+/* Called in atomic context. */
+static void __relay_set_buf_dentry(void *info)
+{
+       struct rchan_percpu_buf_dispatcher *p = info;
+
+       relay_set_buf_dentry(p->buf, p->dentry);
+}
+
+/**
+ *     relay_late_setup_files - triggers file creation
+ *     @chan: channel to operate on
+ *     @base_filename: base name of files to create
+ *     @parent: dentry of parent directory, %NULL for root directory
+ *
+ *     Returns 0 if successful, non-zero otherwise.
+ *
+ *     Use to setup files for a previously buffer-only channel.
+ *     Useful to do early tracing in kernel, before VFS is up, for example.
+ */
+int relay_late_setup_files(struct rchan *chan,
+                          const char *base_filename,
+                          struct dentry *parent)
+{
+       int err = 0;
+       unsigned int i, curr_cpu;
+       unsigned long flags;
+       struct dentry *dentry;
+       struct rchan_percpu_buf_dispatcher disp;
+
+       if (!chan || !base_filename)
+               return -EINVAL;
+
+       strlcpy(chan->base_filename, base_filename, NAME_MAX);
+
+       mutex_lock(&relay_channels_mutex);
+       /* Is chan already set up? */
+       if (unlikely(chan->has_base_filename))
+               return -EEXIST;
+       chan->has_base_filename = 1;
+       chan->parent = parent;
+       curr_cpu = get_cpu();
+       /*
+        * The CPU hotplug notifier ran before us and created buffers with
+        * no files associated. So it's safe to call relay_setup_buf_file()
+        * on all currently online CPUs.
+        */
+       for_each_online_cpu(i) {
+               if (unlikely(!chan->buf[i])) {
+                       printk(KERN_ERR "relay_late_setup_files: CPU %u "
+                                       "has no buffer, it must have!\n", i);
+                       BUG();
+                       err = -EINVAL;
+                       break;
+               }
+
+               dentry = relay_create_buf_file(chan, chan->buf[i], i);
+               if (unlikely(!dentry)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (curr_cpu == i) {
+                       local_irq_save(flags);
+                       relay_set_buf_dentry(chan->buf[i], dentry);
+                       local_irq_restore(flags);
+               } else {
+                       disp.buf = chan->buf[i];
+                       disp.dentry = dentry;
+                       smp_mb();
+                       /* relay_channels_mutex must be held, so wait. */
+                       err = smp_call_function_single(i,
+                                                      __relay_set_buf_dentry,
+                                                      &disp, 1);
+               }
+               if (unlikely(err))
+                       break;
+       }
+       put_cpu();
+       mutex_unlock(&relay_channels_mutex);
+
+       return err;
+}
+
 /**
  *     relay_switch_subbuf - switch to a new sub-buffer
  *     @buf: channel buffer
@@ -627,8 +734,13 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
                old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
                buf->padding[old_subbuf] = buf->prev_padding;
                buf->subbufs_produced++;
-               buf->dentry->d_inode->i_size += buf->chan->subbuf_size -
-                       buf->padding[old_subbuf];
+               if (buf->dentry)
+                       buf->dentry->d_inode->i_size +=
+                               buf->chan->subbuf_size -
+                               buf->padding[old_subbuf];
+               else
+                       buf->early_bytes += buf->chan->subbuf_size -
+                                           buf->padding[old_subbuf];
                smp_mb();
                if (waitqueue_active(&buf->read_wait))
                        /*
@@ -1237,4 +1349,4 @@ static __init int relay_init(void)
        return 0;
 }
 
-module_init(relay_init);
+early_initcall(relay_init);
index d3c61b4ebef238c110ae3994e0d0fdc078fabfc8..f275c8eca772c4dfe6bcdda6b1253a65fefe3e83 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/res_counter.h>
 #include <linux/uaccess.h>
+#include <linux/mm.h>
 
 void res_counter_init(struct res_counter *counter)
 {
@@ -102,44 +103,37 @@ u64 res_counter_read_u64(struct res_counter *counter, int member)
        return *res_counter_member(counter, member);
 }
 
-ssize_t res_counter_write(struct res_counter *counter, int member,
-               const char __user *userbuf, size_t nbytes, loff_t *pos,
-               int (*write_strategy)(char *st_buf, unsigned long long *val))
+int res_counter_memparse_write_strategy(const char *buf,
+                                       unsigned long long *res)
 {
-       int ret;
-       char *buf, *end;
-       unsigned long flags;
-       unsigned long long tmp, *val;
-
-       buf = kmalloc(nbytes + 1, GFP_KERNEL);
-       ret = -ENOMEM;
-       if (buf == NULL)
-               goto out;
+       char *end;
+       /* FIXME - make memparse() take const char* args */
+       *res = memparse((char *)buf, &end);
+       if (*end != '\0')
+               return -EINVAL;
 
-       buf[nbytes] = '\0';
-       ret = -EFAULT;
-       if (copy_from_user(buf, userbuf, nbytes))
-               goto out_free;
+       *res = PAGE_ALIGN(*res);
+       return 0;
+}
 
-       ret = -EINVAL;
+int res_counter_write(struct res_counter *counter, int member,
+                     const char *buf, write_strategy_fn write_strategy)
+{
+       char *end;
+       unsigned long flags;
+       unsigned long long tmp, *val;
 
-       strstrip(buf);
        if (write_strategy) {
-               if (write_strategy(buf, &tmp)) {
-                       goto out_free;
-               }
+               if (write_strategy(buf, &tmp))
+                       return -EINVAL;
        } else {
                tmp = simple_strtoull(buf, &end, 10);
                if (*end != '\0')
-                       goto out_free;
+                       return -EINVAL;
        }
        spin_lock_irqsave(&counter->lock, flags);
        val = res_counter_member(counter, member);
        *val = tmp;
        spin_unlock_irqrestore(&counter->lock, flags);
-       ret = nbytes;
-out_free:
-       kfree(buf);
-out:
-       return ret;
+       return 0;
 }
index 6acf749d33369545310a94ff0fd52341d821bfd0..0236958addcbac72ca908c6be8ac74275a512ad7 100644 (file)
@@ -1867,16 +1867,24 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
 /*
  * wait_task_inactive - wait for a thread to unschedule.
  *
+ * If @match_state is nonzero, it's the @p->state value just checked and
+ * not expected to change.  If it changes, i.e. @p might have woken up,
+ * then return zero.  When we succeed in waiting for @p to be off its CPU,
+ * we return a positive number (its total switch count).  If a second call
+ * a short while later returns the same number, the caller can be sure that
+ * @p has remained unscheduled the whole time.
+ *
  * The caller must ensure that the task *will* unschedule sometime soon,
  * else this function might spin for a *long* time. This function can't
  * be called with interrupts off, or it may introduce deadlock with
  * smp_call_function() if an IPI is sent by the same process we are
  * waiting to become inactive.
  */
-void wait_task_inactive(struct task_struct *p)
+unsigned long wait_task_inactive(struct task_struct *p, long match_state)
 {
        unsigned long flags;
        int running, on_rq;
+       unsigned long ncsw;
        struct rq *rq;
 
        for (;;) {
@@ -1899,8 +1907,11 @@ void wait_task_inactive(struct task_struct *p)
                 * return false if the runqueue has changed and p
                 * is actually now running somewhere else!
                 */
-               while (task_running(rq, p))
+               while (task_running(rq, p)) {
+                       if (match_state && unlikely(p->state != match_state))
+                               return 0;
                        cpu_relax();
+               }
 
                /*
                 * Ok, time to look more closely! We need the rq
@@ -1910,8 +1921,20 @@ void wait_task_inactive(struct task_struct *p)
                rq = task_rq_lock(p, &flags);
                running = task_running(rq, p);
                on_rq = p->se.on_rq;
+               ncsw = 0;
+               if (!match_state || p->state == match_state) {
+                       ncsw = p->nivcsw + p->nvcsw;
+                       if (unlikely(!ncsw))
+                               ncsw = 1;
+               }
                task_rq_unlock(rq, &flags);
 
+               /*
+                * If it changed from the expected state, bail out now.
+                */
+               if (unlikely(!ncsw))
+                       break;
+
                /*
                 * Was it really running after all now that we
                 * checked with the proper locks actually held?
@@ -1944,6 +1967,8 @@ void wait_task_inactive(struct task_struct *p)
                 */
                break;
        }
+
+       return ncsw;
 }
 
 /***
@@ -4046,6 +4071,8 @@ void account_user_time(struct task_struct *p, cputime_t cputime)
                cpustat->nice = cputime64_add(cpustat->nice, tmp);
        else
                cpustat->user = cputime64_add(cpustat->user, tmp);
+       /* Account for user time used */
+       acct_update_integrals(p);
 }
 
 /*
@@ -6387,7 +6414,7 @@ static struct notifier_block __cpuinitdata migration_notifier = {
        .priority = 10
 };
 
-void __init migration_init(void)
+static int __init migration_init(void)
 {
        void *cpu = (void *)(long)smp_processor_id();
        int err;
@@ -6397,7 +6424,10 @@ void __init migration_init(void)
        BUG_ON(err == NOTIFY_BAD);
        migration_call(&migration_notifier, CPU_ONLINE, cpu);
        register_cpu_notifier(&migration_notifier);
+
+       return err;
 }
+early_initcall(migration_init);
 #endif
 
 #ifdef CONFIG_SMP
index f85a76363eee873e23edd0983e7427be65b4fb08..908c04f9dad02d23df66fbc55a28f5619fc10081 100644 (file)
@@ -253,7 +253,7 @@ static int do_balance_runtime(struct rt_rq *rt_rq)
 
                diff = iter->rt_runtime - iter->rt_time;
                if (diff > 0) {
-                       do_div(diff, weight);
+                       diff = div_u64((u64)diff, weight);
                        if (rt_rq->rt_runtime + diff > rt_period)
                                diff = rt_period - rt_rq->rt_runtime;
                        iter->rt_runtime -= diff;
index 6c0958e52ea7bdac212353c2b42bbd59e702ce45..954f77d7e3bc2368f405fa2ab83aaf58d6280fb3 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 #include <linux/signalfd.h>
+#include <linux/tracehook.h>
 #include <linux/capability.h>
 #include <linux/freezer.h>
 #include <linux/pid_namespace.h>
 
 static struct kmem_cache *sigqueue_cachep;
 
-static int __sig_ignored(struct task_struct *t, int sig)
+static void __user *sig_handler(struct task_struct *t, int sig)
 {
-       void __user *handler;
+       return t->sighand->action[sig - 1].sa.sa_handler;
+}
 
+static int sig_handler_ignored(void __user *handler, int sig)
+{
        /* Is it explicitly or implicitly ignored? */
-
-       handler = t->sighand->action[sig - 1].sa.sa_handler;
        return handler == SIG_IGN ||
                (handler == SIG_DFL && sig_kernel_ignore(sig));
 }
 
 static int sig_ignored(struct task_struct *t, int sig)
 {
-       /*
-        * Tracers always want to know about signals..
-        */
-       if (t->ptrace & PT_PTRACED)
-               return 0;
+       void __user *handler;
 
        /*
         * Blocked signals are never ignored, since the
@@ -66,7 +64,14 @@ static int sig_ignored(struct task_struct *t, int sig)
        if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
                return 0;
 
-       return __sig_ignored(t, sig);
+       handler = sig_handler(t, sig);
+       if (!sig_handler_ignored(handler, sig))
+               return 0;
+
+       /*
+        * Tracers may want to know about even ignored signals.
+        */
+       return !tracehook_consider_ignored_signal(t, sig, handler);
 }
 
 /*
@@ -129,7 +134,9 @@ void recalc_sigpending_and_wake(struct task_struct *t)
 
 void recalc_sigpending(void)
 {
-       if (!recalc_sigpending_tsk(current) && !freezing(current))
+       if (unlikely(tracehook_force_sigpending()))
+               set_thread_flag(TIF_SIGPENDING);
+       else if (!recalc_sigpending_tsk(current) && !freezing(current))
                clear_thread_flag(TIF_SIGPENDING);
 
 }
@@ -295,12 +302,12 @@ flush_signal_handlers(struct task_struct *t, int force_default)
 
 int unhandled_signal(struct task_struct *tsk, int sig)
 {
+       void __user *handler = tsk->sighand->action[sig-1].sa.sa_handler;
        if (is_global_init(tsk))
                return 1;
-       if (tsk->ptrace & PT_PTRACED)
+       if (handler != SIG_IGN && handler != SIG_DFL)
                return 0;
-       return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
-               (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
+       return !tracehook_consider_fatal_signal(tsk, sig, handler);
 }
 
 
@@ -338,13 +345,9 @@ unblock_all_signals(void)
        spin_unlock_irqrestore(&current->sighand->siglock, flags);
 }
 
-static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
 {
        struct sigqueue *q, *first = NULL;
-       int still_pending = 0;
-
-       if (unlikely(!sigismember(&list->signal, sig)))
-               return 0;
 
        /*
         * Collect the siginfo appropriate to this signal.  Check if
@@ -352,33 +355,30 @@ static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
        */
        list_for_each_entry(q, &list->list, list) {
                if (q->info.si_signo == sig) {
-                       if (first) {
-                               still_pending = 1;
-                               break;
-                       }
+                       if (first)
+                               goto still_pending;
                        first = q;
                }
        }
+
+       sigdelset(&list->signal, sig);
+
        if (first) {
+still_pending:
                list_del_init(&first->list);
                copy_siginfo(info, &first->info);
                __sigqueue_free(first);
-               if (!still_pending)
-                       sigdelset(&list->signal, sig);
        } else {
-
                /* Ok, it wasn't in the queue.  This must be
                   a fast-pathed signal or we must have been
                   out of queue space.  So zero out the info.
                 */
-               sigdelset(&list->signal, sig);
                info->si_signo = sig;
                info->si_errno = 0;
                info->si_code = 0;
                info->si_pid = 0;
                info->si_uid = 0;
        }
-       return 1;
 }
 
 static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
@@ -396,8 +396,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
                        }
                }
 
-               if (!collect_signal(sig, pending, info))
-                       sig = 0;
+               collect_signal(sig, pending, info);
        }
 
        return sig;
@@ -462,8 +461,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                 * is to alert stop-signal processing code when another
                 * processor has come along and cleared the flag.
                 */
-               if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
-                       tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
+               tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
        }
        if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
                /*
@@ -600,9 +598,6 @@ static int check_kill_permission(int sig, struct siginfo *info,
        return security_task_kill(t, info, sig, 0);
 }
 
-/* forward decl */
-static void do_notify_parent_cldstop(struct task_struct *tsk, int why);
-
 /*
  * Handle magic process-wide effects of stop/continue signals. Unlike
  * the signal actions, these happen immediately at signal-generation
@@ -765,7 +760,8 @@ static void complete_signal(int sig, struct task_struct *p, int group)
        if (sig_fatal(p, sig) &&
            !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
            !sigismember(&t->real_blocked, sig) &&
-           (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) {
+           (sig == SIGKILL ||
+            !tracehook_consider_fatal_signal(t, sig, SIG_DFL))) {
                /*
                 * This signal will be fatal to the whole group.
                 */
@@ -1125,7 +1121,7 @@ EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);
  * is probably wrong.  Should make it like BSD or SYSV.
  */
 
-static int kill_something_info(int sig, struct siginfo *info, int pid)
+static int kill_something_info(int sig, struct siginfo *info, pid_t pid)
 {
        int ret;
 
@@ -1237,17 +1233,6 @@ int kill_pid(struct pid *pid, int sig, int priv)
 }
 EXPORT_SYMBOL(kill_pid);
 
-int
-kill_proc(pid_t pid, int sig, int priv)
-{
-       int ret;
-
-       rcu_read_lock();
-       ret = kill_pid_info(sig, __si_special(priv), find_pid(pid));
-       rcu_read_unlock();
-       return ret;
-}
-
 /*
  * These functions support sending signals using preallocated sigqueue
  * structures.  This is needed "because realtime applications cannot
@@ -1343,9 +1328,11 @@ static inline void __wake_up_parent(struct task_struct *p,
 /*
  * Let a parent know about the death of a child.
  * For a stopped/continued status change, use do_notify_parent_cldstop instead.
+ *
+ * Returns -1 if our parent ignored us and so we've switched to
+ * self-reaping, or else @sig.
  */
-
-void do_notify_parent(struct task_struct *tsk, int sig)
+int do_notify_parent(struct task_struct *tsk, int sig)
 {
        struct siginfo info;
        unsigned long flags;
@@ -1379,10 +1366,9 @@ void do_notify_parent(struct task_struct *tsk, int sig)
 
        info.si_uid = tsk->uid;
 
-       /* FIXME: find out whether or not this is supposed to be c*time. */
-       info.si_utime = cputime_to_jiffies(cputime_add(tsk->utime,
+       info.si_utime = cputime_to_clock_t(cputime_add(tsk->utime,
                                                       tsk->signal->utime));
-       info.si_stime = cputime_to_jiffies(cputime_add(tsk->stime,
+       info.si_stime = cputime_to_clock_t(cputime_add(tsk->stime,
                                                       tsk->signal->stime));
 
        info.si_status = tsk->exit_code & 0x7f;
@@ -1417,12 +1403,14 @@ void do_notify_parent(struct task_struct *tsk, int sig)
                 */
                tsk->exit_signal = -1;
                if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN)
-                       sig = 0;
+                       sig = -1;
        }
        if (valid_signal(sig) && sig > 0)
                __group_send_sig_info(sig, &info, tsk->parent);
        __wake_up_parent(tsk, tsk->parent);
        spin_unlock_irqrestore(&psig->siglock, flags);
+
+       return sig;
 }
 
 static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
@@ -1450,9 +1438,8 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
 
        info.si_uid = tsk->uid;
 
-       /* FIXME: find out whether or not this is supposed to be c*time. */
-       info.si_utime = cputime_to_jiffies(tsk->utime);
-       info.si_stime = cputime_to_jiffies(tsk->stime);
+       info.si_utime = cputime_to_clock_t(tsk->utime);
+       info.si_stime = cputime_to_clock_t(tsk->stime);
 
        info.si_code = why;
        switch (why) {
@@ -1491,10 +1478,10 @@ static inline int may_ptrace_stop(void)
         * is a deadlock situation, and pointless because our tracer
         * is dead so don't allow us to stop.
         * If SIGKILL was already sent before the caller unlocked
-        * ->siglock we must see ->core_waiters != 0. Otherwise it
+        * ->siglock we must see ->core_state != NULL. Otherwise it
         * is safe to enter schedule().
         */
-       if (unlikely(current->mm->core_waiters) &&
+       if (unlikely(current->mm->core_state) &&
            unlikely(current->mm == current->parent->mm))
                return 0;
 
@@ -1507,9 +1494,8 @@ static inline int may_ptrace_stop(void)
  */
 static int sigkill_pending(struct task_struct *tsk)
 {
-       return ((sigismember(&tsk->pending.signal, SIGKILL) ||
-                sigismember(&tsk->signal->shared_pending.signal, SIGKILL)) &&
-               !unlikely(sigismember(&tsk->blocked, SIGKILL)));
+       return  sigismember(&tsk->pending.signal, SIGKILL) ||
+               sigismember(&tsk->signal->shared_pending.signal, SIGKILL);
 }
 
 /*
@@ -1525,8 +1511,6 @@ static int sigkill_pending(struct task_struct *tsk)
  */
 static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)
 {
-       int killed = 0;
-
        if (arch_ptrace_stop_needed(exit_code, info)) {
                /*
                 * The arch code has something special to do before a
@@ -1542,7 +1526,8 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)
                spin_unlock_irq(&current->sighand->siglock);
                arch_ptrace_stop(exit_code, info);
                spin_lock_irq(&current->sighand->siglock);
-               killed = sigkill_pending(current);
+               if (sigkill_pending(current))
+                       return;
        }
 
        /*
@@ -1559,7 +1544,7 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)
        __set_current_state(TASK_TRACED);
        spin_unlock_irq(&current->sighand->siglock);
        read_lock(&tasklist_lock);
-       if (!unlikely(killed) && may_ptrace_stop()) {
+       if (may_ptrace_stop()) {
                do_notify_parent_cldstop(current, CLD_TRAPPED);
                read_unlock(&tasklist_lock);
                schedule();
@@ -1623,7 +1608,7 @@ finish_stop(int stop_count)
         * a group stop in progress and we are the last to stop,
         * report to the parent.  When ptraced, every thread reports itself.
         */
-       if (stop_count == 0 || (current->ptrace & PT_PTRACED)) {
+       if (tracehook_notify_jctl(stop_count == 0, CLD_STOPPED)) {
                read_lock(&tasklist_lock);
                do_notify_parent_cldstop(current, CLD_STOPPED);
                read_unlock(&tasklist_lock);
@@ -1658,8 +1643,7 @@ static int do_signal_stop(int signr)
        } else {
                struct task_struct *t;
 
-               if (unlikely((sig->flags & (SIGNAL_STOP_DEQUEUED | SIGNAL_UNKILLABLE))
-                                        != SIGNAL_STOP_DEQUEUED) ||
+               if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) ||
                    unlikely(signal_group_exit(sig)))
                        return 0;
                /*
@@ -1760,6 +1744,9 @@ relock:
                signal->flags &= ~SIGNAL_CLD_MASK;
                spin_unlock_irq(&sighand->siglock);
 
+               if (unlikely(!tracehook_notify_jctl(1, why)))
+                       goto relock;
+
                read_lock(&tasklist_lock);
                do_notify_parent_cldstop(current->group_leader, why);
                read_unlock(&tasklist_lock);
@@ -1773,17 +1760,33 @@ relock:
                    do_signal_stop(0))
                        goto relock;
 
-               signr = dequeue_signal(current, &current->blocked, info);
-               if (!signr)
-                       break; /* will return 0 */
+               /*
+                * Tracing can induce an artifical signal and choose sigaction.
+                * The return value in @signr determines the default action,
+                * but @info->si_signo is the signal number we will report.
+                */
+               signr = tracehook_get_signal(current, regs, info, return_ka);
+               if (unlikely(signr < 0))
+                       goto relock;
+               if (unlikely(signr != 0))
+                       ka = return_ka;
+               else {
+                       signr = dequeue_signal(current, &current->blocked,
+                                              info);
 
-               if (signr != SIGKILL) {
-                       signr = ptrace_signal(signr, info, regs, cookie);
                        if (!signr)
-                               continue;
+                               break; /* will return 0 */
+
+                       if (signr != SIGKILL) {
+                               signr = ptrace_signal(signr, info,
+                                                     regs, cookie);
+                               if (!signr)
+                                       continue;
+                       }
+
+                       ka = &sighand->action[signr-1];
                }
 
-               ka = &sighand->action[signr-1];
                if (ka->sa.sa_handler == SIG_IGN) /* Do nothing.  */
                        continue;
                if (ka->sa.sa_handler != SIG_DFL) {
@@ -1831,7 +1834,7 @@ relock:
                                spin_lock_irq(&sighand->siglock);
                        }
 
-                       if (likely(do_signal_stop(signr))) {
+                       if (likely(do_signal_stop(info->si_signo))) {
                                /* It released the siglock.  */
                                goto relock;
                        }
@@ -1852,7 +1855,7 @@ relock:
 
                if (sig_kernel_coredump(signr)) {
                        if (print_fatal_signals)
-                               print_fatal_signal(regs, signr);
+                               print_fatal_signal(regs, info->si_signo);
                        /*
                         * If it was able to dump core, this kills all
                         * other threads in the group and synchronizes with
@@ -1861,13 +1864,13 @@ relock:
                         * first and our do_group_exit call below will use
                         * that value and ignore the one we pass it.
                         */
-                       do_coredump((long)signr, signr, regs);
+                       do_coredump(info->si_signo, info->si_signo, regs);
                }
 
                /*
                 * Death signals, no core dump.
                 */
-               do_group_exit(signr);
+               do_group_exit(info->si_signo);
                /* NOTREACHED */
        }
        spin_unlock_irq(&sighand->siglock);
@@ -1909,7 +1912,7 @@ void exit_signals(struct task_struct *tsk)
 out:
        spin_unlock_irq(&tsk->sighand->siglock);
 
-       if (unlikely(group_stop)) {
+       if (unlikely(group_stop) && tracehook_notify_jctl(1, CLD_STOPPED)) {
                read_lock(&tasklist_lock);
                do_notify_parent_cldstop(tsk, CLD_STOPPED);
                read_unlock(&tasklist_lock);
@@ -1920,8 +1923,6 @@ EXPORT_SYMBOL(recalc_sigpending);
 EXPORT_SYMBOL_GPL(dequeue_signal);
 EXPORT_SYMBOL(flush_signals);
 EXPORT_SYMBOL(force_sig);
-EXPORT_SYMBOL(kill_proc);
-EXPORT_SYMBOL(ptrace_notify);
 EXPORT_SYMBOL(send_sig);
 EXPORT_SYMBOL(send_sig_info);
 EXPORT_SYMBOL(sigprocmask);
@@ -2196,7 +2197,7 @@ sys_rt_sigtimedwait(const sigset_t __user *uthese,
 }
 
 asmlinkage long
-sys_kill(int pid, int sig)
+sys_kill(pid_t pid, int sig)
 {
        struct siginfo info;
 
@@ -2209,7 +2210,7 @@ sys_kill(int pid, int sig)
        return kill_something_info(sig, &info, pid);
 }
 
-static int do_tkill(int tgid, int pid, int sig)
+static int do_tkill(pid_t tgid, pid_t pid, int sig)
 {
        int error;
        struct siginfo info;
@@ -2255,7 +2256,7 @@ static int do_tkill(int tgid, int pid, int sig)
  *  exists but it's not belonging to the target process anymore. This
  *  method solves the problem of threads exiting and PIDs getting reused.
  */
-asmlinkage long sys_tgkill(int tgid, int pid, int sig)
+asmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig)
 {
        /* This is only valid for single tasks */
        if (pid <= 0 || tgid <= 0)
@@ -2268,7 +2269,7 @@ asmlinkage long sys_tgkill(int tgid, int pid, int sig)
  *  Send a signal to only one task, even if it's a CLONE_THREAD task.
  */
 asmlinkage long
-sys_tkill(int pid, int sig)
+sys_tkill(pid_t pid, int sig)
 {
        /* This is only valid for single tasks */
        if (pid <= 0)
@@ -2278,7 +2279,7 @@ sys_tkill(int pid, int sig)
 }
 
 asmlinkage long
-sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo)
+sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t __user *uinfo)
 {
        siginfo_t info;
 
@@ -2325,7 +2326,7 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
                 *   (for example, SIGCHLD), shall cause the pending signal to
                 *   be discarded, whether or not it is blocked"
                 */
-               if (__sig_ignored(t, sig)) {
+               if (sig_handler_ignored(sig_handler(t, sig), sig)) {
                        sigemptyset(&mask);
                        sigaddset(&mask, sig);
                        rm_from_queue_full(&mask, &t->signal->shared_pending);
index 462c785ca1eee80dea958541edf19786259c88e6..96fc7c0edc59d1f09ca56a500d90b0a8a212c7d7 100644 (file)
@@ -33,7 +33,7 @@ struct call_single_queue {
        spinlock_t lock;
 };
 
-void __cpuinit init_call_single_data(void)
+static int __cpuinit init_call_single_data(void)
 {
        int i;
 
@@ -43,7 +43,9 @@ void __cpuinit init_call_single_data(void)
                spin_lock_init(&q->lock);
                INIT_LIST_HEAD(&q->list);
        }
+       return 0;
 }
+early_initcall(init_call_single_data);
 
 static void csd_flag_wait(struct call_single_data *data)
 {
index 81e2fe0f983a04d1407a77e214b8f0612feedf9a..c506f266a6b90ee9d887b9eeecdd45061e74ef1f 100644 (file)
@@ -286,7 +286,7 @@ void irq_exit(void)
 #ifdef CONFIG_NO_HZ
        /* Make sure that timer wheel updates are propagated */
        if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(0);
        rcu_irq_exit();
 #endif
        preempt_enable_no_resched();
@@ -630,7 +630,7 @@ static struct notifier_block __cpuinitdata cpu_nfb = {
        .notifier_call = cpu_callback
 };
 
-__init int spawn_ksoftirqd(void)
+static __init int spawn_ksoftirqd(void)
 {
        void *cpu = (void *)(long)smp_processor_id();
        int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
@@ -640,6 +640,7 @@ __init int spawn_ksoftirqd(void)
        register_cpu_notifier(&cpu_nfb);
        return 0;
 }
+early_initcall(spawn_ksoftirqd);
 
 #ifdef CONFIG_SMP
 /*
index 7bd8d1aadd5d3693bd881791e1130b1f603f5bce..b75b492fbfcff63770bc099df2a7769fc1e26f09 100644 (file)
@@ -338,14 +338,33 @@ static struct notifier_block __cpuinitdata cpu_nfb = {
        .notifier_call = cpu_callback
 };
 
-__init void spawn_softlockup_task(void)
+static int __initdata nosoftlockup;
+
+static int __init nosoftlockup_setup(char *str)
+{
+       nosoftlockup = 1;
+       return 1;
+}
+__setup("nosoftlockup", nosoftlockup_setup);
+
+static int __init spawn_softlockup_task(void)
 {
        void *cpu = (void *)(long)smp_processor_id();
-       int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+       int err;
 
-       BUG_ON(err == NOTIFY_BAD);
+       if (nosoftlockup)
+               return 0;
+
+       err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+       if (err == NOTIFY_BAD) {
+               BUG();
+               return 1;
+       }
        cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
        register_cpu_notifier(&cpu_nfb);
 
        atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+
+       return 0;
 }
+early_initcall(spawn_softlockup_task);
index 738b411ff2d33dee86042404917640bcb2932ed5..e446c7c7d6a9230dc1205cb73dd0370568696ed0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2005 Rusty Russell rusty@rustcorp.com.au IBM Corporation.
+/* Copyright 2008, 2005 Rusty Russell rusty@rustcorp.com.au IBM Corporation.
  * GPL v2 and any later version.
  */
 #include <linux/cpu.h>
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 
-/* Since we effect priority and affinity (both of which are visible
- * to, and settable by outside processes) we do indirection via a
- * kthread. */
-
-/* Thread to stop each CPU in user context. */
+/* This controls the threads on each CPU. */
 enum stopmachine_state {
-       STOPMACHINE_WAIT,
+       /* Dummy starting state for thread. */
+       STOPMACHINE_NONE,
+       /* Awaiting everyone to be scheduled. */
        STOPMACHINE_PREPARE,
+       /* Disable interrupts. */
        STOPMACHINE_DISABLE_IRQ,
+       /* Run the function */
+       STOPMACHINE_RUN,
+       /* Exit */
        STOPMACHINE_EXIT,
 };
+static enum stopmachine_state state;
 
-static enum stopmachine_state stopmachine_state;
-static unsigned int stopmachine_num_threads;
-static atomic_t stopmachine_thread_ack;
-
-static int stopmachine(void *cpu)
-{
-       int irqs_disabled = 0;
-       int prepared = 0;
-       cpumask_of_cpu_ptr(cpumask, (int)(long)cpu);
-
-       set_cpus_allowed_ptr(current, cpumask);
-
-       /* Ack: we are alive */
-       smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
-       atomic_inc(&stopmachine_thread_ack);
-
-       /* Simple state machine */
-       while (stopmachine_state != STOPMACHINE_EXIT) {
-               if (stopmachine_state == STOPMACHINE_DISABLE_IRQ 
-                   && !irqs_disabled) {
-                       local_irq_disable();
-                       hard_irq_disable();
-                       irqs_disabled = 1;
-                       /* Ack: irqs disabled. */
-                       smp_mb(); /* Must read state first. */
-                       atomic_inc(&stopmachine_thread_ack);
-               } else if (stopmachine_state == STOPMACHINE_PREPARE
-                          && !prepared) {
-                       /* Everyone is in place, hold CPU. */
-                       preempt_disable();
-                       prepared = 1;
-                       smp_mb(); /* Must read state first. */
-                       atomic_inc(&stopmachine_thread_ack);
-               }
-               /* Yield in first stage: migration threads need to
-                * help our sisters onto their CPUs. */
-               if (!prepared && !irqs_disabled)
-                       yield();
-               cpu_relax();
-       }
-
-       /* Ack: we are exiting. */
-       smp_mb(); /* Must read state first. */
-       atomic_inc(&stopmachine_thread_ack);
-
-       if (irqs_disabled)
-               local_irq_enable();
-       if (prepared)
-               preempt_enable();
+struct stop_machine_data {
+       int (*fn)(void *);
+       void *data;
+       int fnret;
+};
 
-       return 0;
-}
+/* Like num_online_cpus(), but hotplug cpu uses us, so we need this. */
+static unsigned int num_threads;
+static atomic_t thread_ack;
+static struct completion finished;
+static DEFINE_MUTEX(lock);
 
-/* Change the thread state */
-static void stopmachine_set_state(enum stopmachine_state state)
+static void set_state(enum stopmachine_state newstate)
 {
-       atomic_set(&stopmachine_thread_ack, 0);
+       /* Reset ack counter. */
+       atomic_set(&thread_ack, num_threads);
        smp_wmb();
-       stopmachine_state = state;
-       while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads)
-               cpu_relax();
+       state = newstate;
 }
 
-static int stop_machine(void)
+/* Last one to ack a state moves to the next state. */
+static void ack_state(void)
 {
-       int i, ret = 0;
-
-       atomic_set(&stopmachine_thread_ack, 0);
-       stopmachine_num_threads = 0;
-       stopmachine_state = STOPMACHINE_WAIT;
-
-       for_each_online_cpu(i) {
-               if (i == raw_smp_processor_id())
-                       continue;
-               ret = kernel_thread(stopmachine, (void *)(long)i,CLONE_KERNEL);
-               if (ret < 0)
-                       break;
-               stopmachine_num_threads++;
-       }
-
-       /* Wait for them all to come to life. */
-       while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads) {
-               yield();
-               cpu_relax();
+       if (atomic_dec_and_test(&thread_ack)) {
+               /* If we're the last one to ack the EXIT, we're finished. */
+               if (state == STOPMACHINE_EXIT)
+                       complete(&finished);
+               else
+                       set_state(state + 1);
        }
+}
 
-       /* If some failed, kill them all. */
-       if (ret < 0) {
-               stopmachine_set_state(STOPMACHINE_EXIT);
-               return ret;
-       }
+/* This is the actual thread which stops the CPU.  It exits by itself rather
+ * than waiting for kthread_stop(), because it's easier for hotplug CPU. */
+static int stop_cpu(struct stop_machine_data *smdata)
+{
+       enum stopmachine_state curstate = STOPMACHINE_NONE;
+       int uninitialized_var(ret);
 
-       /* Now they are all started, make them hold the CPUs, ready. */
-       preempt_disable();
-       stopmachine_set_state(STOPMACHINE_PREPARE);
+       /* Simple state machine */
+       do {
+               /* Chill out and ensure we re-read stopmachine_state. */
+               cpu_relax();
+               if (state != curstate) {
+                       curstate = state;
+                       switch (curstate) {
+                       case STOPMACHINE_DISABLE_IRQ:
+                               local_irq_disable();
+                               hard_irq_disable();
+                               break;
+                       case STOPMACHINE_RUN:
+                               /* |= allows error detection if functions on
+                                * multiple CPUs. */
+                               smdata->fnret |= smdata->fn(smdata->data);
+                               break;
+                       default:
+                               break;
+                       }
+                       ack_state();
+               }
+       } while (curstate != STOPMACHINE_EXIT);
 
-       /* Make them disable irqs. */
-       local_irq_disable();
-       hard_irq_disable();
-       stopmachine_set_state(STOPMACHINE_DISABLE_IRQ);
+       local_irq_enable();
+       do_exit(0);
+}
 
+/* Callback for CPUs which aren't supposed to do anything. */
+static int chill(void *unused)
+{
        return 0;
 }
 
-static void restart_machine(void)
+int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
 {
-       stopmachine_set_state(STOPMACHINE_EXIT);
-       local_irq_enable();
-       preempt_enable_no_resched();
-}
+       int i, err;
+       struct stop_machine_data active, idle;
+       struct task_struct **threads;
+
+       active.fn = fn;
+       active.data = data;
+       active.fnret = 0;
+       idle.fn = chill;
+       idle.data = NULL;
+
+       /* This could be too big for stack on large machines. */
+       threads = kcalloc(NR_CPUS, sizeof(threads[0]), GFP_KERNEL);
+       if (!threads)
+               return -ENOMEM;
+
+       /* Set up initial state. */
+       mutex_lock(&lock);
+       init_completion(&finished);
+       num_threads = num_online_cpus();
+       set_state(STOPMACHINE_PREPARE);
 
-struct stop_machine_data {
-       int (*fn)(void *);
-       void *data;
-       struct completion done;
-};
+       for_each_online_cpu(i) {
+               struct stop_machine_data *smdata = &idle;
+               struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
 
-static int do_stop(void *_smdata)
-{
-       struct stop_machine_data *smdata = _smdata;
-       int ret;
+               if (!cpus) {
+                       if (i == first_cpu(cpu_online_map))
+                               smdata = &active;
+               } else {
+                       if (cpu_isset(i, *cpus))
+                               smdata = &active;
+               }
 
-       ret = stop_machine();
-       if (ret == 0) {
-               ret = smdata->fn(smdata->data);
-               restart_machine();
-       }
+               threads[i] = kthread_create((void *)stop_cpu, smdata, "kstop%u",
+                                           i);
+               if (IS_ERR(threads[i])) {
+                       err = PTR_ERR(threads[i]);
+                       threads[i] = NULL;
+                       goto kill_threads;
+               }
 
-       /* We're done: you can kthread_stop us now */
-       complete(&smdata->done);
+               /* Place it onto correct cpu. */
+               kthread_bind(threads[i], i);
 
-       /* Wait for kthread_stop */
-       set_current_state(TASK_INTERRUPTIBLE);
-       while (!kthread_should_stop()) {
-               schedule();
-               set_current_state(TASK_INTERRUPTIBLE);
+               /* Make it highest prio. */
+               if (sched_setscheduler_nocheck(threads[i], SCHED_FIFO, &param))
+                       BUG();
        }
-       __set_current_state(TASK_RUNNING);
-       return ret;
-}
 
-struct task_struct *__stop_machine_run(int (*fn)(void *), void *data,
-                                      unsigned int cpu)
-{
-       static DEFINE_MUTEX(stopmachine_mutex);
-       struct stop_machine_data smdata;
-       struct task_struct *p;
+       /* We've created all the threads.  Wake them all: hold this CPU so one
+        * doesn't hit this CPU until we're ready. */
+       get_cpu();
+       for_each_online_cpu(i)
+               wake_up_process(threads[i]);
 
-       smdata.fn = fn;
-       smdata.data = data;
-       init_completion(&smdata.done);
+       /* This will release the thread on our CPU. */
+       put_cpu();
+       wait_for_completion(&finished);
+       mutex_unlock(&lock);
 
-       mutex_lock(&stopmachine_mutex);
+       kfree(threads);
 
-       /* If they don't care which CPU fn runs on, bind to any online one. */
-       if (cpu == NR_CPUS)
-               cpu = raw_smp_processor_id();
+       return active.fnret;
 
-       p = kthread_create(do_stop, &smdata, "kstopmachine");
-       if (!IS_ERR(p)) {
-               struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+kill_threads:
+       for_each_online_cpu(i)
+               if (threads[i])
+                       kthread_stop(threads[i]);
+       mutex_unlock(&lock);
 
-               /* One high-prio thread per cpu.  We'll do this one. */
-               sched_setscheduler_nocheck(p, SCHED_FIFO, &param);
-               kthread_bind(p, cpu);
-               wake_up_process(p);
-               wait_for_completion(&smdata.done);
-       }
-       mutex_unlock(&stopmachine_mutex);
-       return p;
+       kfree(threads);
+       return err;
 }
 
-int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu)
+int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
 {
-       struct task_struct *p;
        int ret;
 
        /* No CPUs can come up or down during this. */
        get_online_cpus();
-       p = __stop_machine_run(fn, data, cpu);
-       if (!IS_ERR(p))
-               ret = kthread_stop(p);
-       else
-               ret = PTR_ERR(p);
+       ret = __stop_machine(fn, data, cpus);
        put_online_cpus();
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(stop_machine_run);
+EXPORT_SYMBOL_GPL(stop_machine);
index 14e97282eb6c941605913dc68c2d4e2778cbe3b6..c01858090a981634cd31b26b439fba7b360b9ca3 100644 (file)
@@ -301,26 +301,6 @@ void kernel_restart(char *cmd)
 }
 EXPORT_SYMBOL_GPL(kernel_restart);
 
-/**
- *     kernel_kexec - reboot the system
- *
- *     Move into place and start executing a preloaded standalone
- *     executable.  If nothing was preloaded return an error.
- */
-static void kernel_kexec(void)
-{
-#ifdef CONFIG_KEXEC
-       struct kimage *image;
-       image = xchg(&kexec_image, NULL);
-       if (!image)
-               return;
-       kernel_restart_prepare(NULL);
-       printk(KERN_EMERG "Starting new kernel\n");
-       machine_shutdown();
-       machine_kexec(image);
-#endif
-}
-
 static void kernel_shutdown_prepare(enum system_states state)
 {
        blocking_notifier_call_chain(&reboot_notifier_list,
@@ -425,10 +405,15 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
                kernel_restart(buffer);
                break;
 
+#ifdef CONFIG_KEXEC
        case LINUX_REBOOT_CMD_KEXEC:
-               kernel_kexec();
-               unlock_kernel();
-               return -EINVAL;
+               {
+                       int ret;
+                       ret = kernel_kexec();
+                       unlock_kernel();
+                       return ret;
+               }
+#endif
 
 #ifdef CONFIG_HIBERNATION
        case LINUX_REBOOT_CMD_SW_SUSPEND:
@@ -1343,8 +1328,6 @@ EXPORT_SYMBOL(in_egroup_p);
 
 DECLARE_RWSEM(uts_sem);
 
-EXPORT_SYMBOL(uts_sem);
-
 asmlinkage long sys_newuname(struct new_utsname __user * name)
 {
        int errno = 0;
@@ -1795,7 +1778,7 @@ int orderly_poweroff(bool force)
                goto out;
        }
 
-       info = call_usermodehelper_setup(argv[0], argv, envp);
+       info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC);
        if (info == NULL) {
                argv_free(argv);
                goto out;
index 0fea0ee12da96875bca1833e0bdf1c07163531d4..08d6e1bb99ac351f28bfe768acf49c17e04b0593 100644 (file)
@@ -31,6 +31,7 @@ cond_syscall(sys_socketpair);
 cond_syscall(sys_bind);
 cond_syscall(sys_listen);
 cond_syscall(sys_accept);
+cond_syscall(sys_paccept);
 cond_syscall(sys_connect);
 cond_syscall(sys_getsockname);
 cond_syscall(sys_getpeername);
@@ -56,6 +57,7 @@ cond_syscall(compat_sys_set_robust_list);
 cond_syscall(sys_get_robust_list);
 cond_syscall(compat_sys_get_robust_list);
 cond_syscall(sys_epoll_create);
+cond_syscall(sys_epoll_create1);
 cond_syscall(sys_epoll_ctl);
 cond_syscall(sys_epoll_wait);
 cond_syscall(sys_epoll_pwait);
@@ -95,6 +97,7 @@ cond_syscall(sys_keyctl);
 cond_syscall(compat_sys_keyctl);
 cond_syscall(compat_sys_socketcall);
 cond_syscall(sys_inotify_init);
+cond_syscall(sys_inotify_init1);
 cond_syscall(sys_inotify_add_watch);
 cond_syscall(sys_inotify_rm_watch);
 cond_syscall(sys_migrate_pages);
@@ -155,10 +158,13 @@ cond_syscall(sys_ioprio_get);
 
 /* New file descriptors */
 cond_syscall(sys_signalfd);
+cond_syscall(sys_signalfd4);
 cond_syscall(compat_sys_signalfd);
+cond_syscall(compat_sys_signalfd4);
 cond_syscall(sys_timerfd_create);
 cond_syscall(sys_timerfd_settime);
 cond_syscall(sys_timerfd_gettime);
 cond_syscall(compat_sys_timerfd_settime);
 cond_syscall(compat_sys_timerfd_gettime);
 cond_syscall(sys_eventfd);
+cond_syscall(sys_eventfd2);
index 2a7b9d88706b41072e4a8fa7cec9a61d1e1e3381..fe47133472758853b039c47ac9390e5eadd34bed 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/limits.h>
 #include <linux/dcache.h>
 #include <linux/syscalls.h>
+#include <linux/vmstat.h>
 #include <linux/nfs_fs.h>
 #include <linux/acpi.h>
 #include <linux/reboot.h>
@@ -80,7 +81,6 @@ extern int sysctl_drop_caches;
 extern int percpu_pagelist_fraction;
 extern int compat_log;
 extern int maps_protect;
-extern int sysctl_stat_interval;
 extern int latencytop_enabled;
 extern int sysctl_nr_open_min, sysctl_nr_open_max;
 #ifdef CONFIG_RCU_TORTURE_TEST
@@ -160,12 +160,13 @@ static struct ctl_table root_table[];
 static struct ctl_table_root sysctl_table_root;
 static struct ctl_table_header root_table_header = {
        .ctl_table = root_table,
-       .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.header_list),
+       .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),
        .root = &sysctl_table_root,
+       .set = &sysctl_table_root.default_set,
 };
 static struct ctl_table_root sysctl_table_root = {
        .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list),
-       .header_list = LIST_HEAD_INIT(root_table_header.ctl_entry),
+       .default_set.list = LIST_HEAD_INIT(root_table_header.ctl_entry),
 };
 
 static struct ctl_table kern_table[];
@@ -624,7 +625,7 @@ static struct ctl_table kern_table[] = {
        {
                .ctl_name       = KERN_PRINTK_RATELIMIT,
                .procname       = "printk_ratelimit",
-               .data           = &printk_ratelimit_jiffies,
+               .data           = &printk_ratelimit_state.interval,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = &proc_dointvec_jiffies,
@@ -633,7 +634,7 @@ static struct ctl_table kern_table[] = {
        {
                .ctl_name       = KERN_PRINTK_RATELIMIT_BURST,
                .procname       = "printk_ratelimit_burst",
-               .data           = &printk_ratelimit_burst,
+               .data           = &printk_ratelimit_state.burst,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
@@ -959,7 +960,7 @@ static struct ctl_table vm_table[] = {
 #ifdef CONFIG_HUGETLB_PAGE
         {
                .procname       = "nr_hugepages",
-               .data           = &max_huge_pages,
+               .data           = NULL,
                .maxlen         = sizeof(unsigned long),
                .mode           = 0644,
                .proc_handler   = &hugetlb_sysctl_handler,
@@ -985,10 +986,12 @@ static struct ctl_table vm_table[] = {
        {
                .ctl_name       = CTL_UNNUMBERED,
                .procname       = "nr_overcommit_hugepages",
-               .data           = &sysctl_overcommit_huge_pages,
-               .maxlen         = sizeof(sysctl_overcommit_huge_pages),
+               .data           = NULL,
+               .maxlen         = sizeof(unsigned long),
                .mode           = 0644,
                .proc_handler   = &hugetlb_overcommit_handler,
+               .extra1         = (void *)&hugetlb_zero,
+               .extra2         = (void *)&hugetlb_infinity,
        },
 #endif
        {
@@ -1384,6 +1387,9 @@ static void start_unregistering(struct ctl_table_header *p)
                spin_unlock(&sysctl_lock);
                wait_for_completion(&wait);
                spin_lock(&sysctl_lock);
+       } else {
+               /* anything non-NULL; we'll never dereference it */
+               p->unregistering = ERR_PTR(-EINVAL);
        }
        /*
         * do not remove from the list until nobody holds it; walking the
@@ -1392,6 +1398,32 @@ static void start_unregistering(struct ctl_table_header *p)
        list_del_init(&p->ctl_entry);
 }
 
+void sysctl_head_get(struct ctl_table_header *head)
+{
+       spin_lock(&sysctl_lock);
+       head->count++;
+       spin_unlock(&sysctl_lock);
+}
+
+void sysctl_head_put(struct ctl_table_header *head)
+{
+       spin_lock(&sysctl_lock);
+       if (!--head->count)
+               kfree(head);
+       spin_unlock(&sysctl_lock);
+}
+
+struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
+{
+       if (!head)
+               BUG();
+       spin_lock(&sysctl_lock);
+       if (!use_table(head))
+               head = ERR_PTR(-ENOENT);
+       spin_unlock(&sysctl_lock);
+       return head;
+}
+
 void sysctl_head_finish(struct ctl_table_header *head)
 {
        if (!head)
@@ -1401,14 +1433,20 @@ void sysctl_head_finish(struct ctl_table_header *head)
        spin_unlock(&sysctl_lock);
 }
 
+static struct ctl_table_set *
+lookup_header_set(struct ctl_table_root *root, struct nsproxy *namespaces)
+{
+       struct ctl_table_set *set = &root->default_set;
+       if (root->lookup)
+               set = root->lookup(root, namespaces);
+       return set;
+}
+
 static struct list_head *
 lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces)
 {
-       struct list_head *header_list;
-       header_list = &root->header_list;
-       if (root->lookup)
-               header_list = root->lookup(root, namespaces);
-       return header_list;
+       struct ctl_table_set *set = lookup_header_set(root, namespaces);
+       return &set->list;
 }
 
 struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
@@ -1478,9 +1516,9 @@ static int do_sysctl_strategy(struct ctl_table_root *root,
        int op = 0, rc;
 
        if (oldval)
-               op |= 004;
+               op |= MAY_READ;
        if (newval)
-               op |= 002;
+               op |= MAY_WRITE;
        if (sysctl_perm(root, table, op))
                return -EPERM;
 
@@ -1522,7 +1560,7 @@ repeat:
                if (n == table->ctl_name) {
                        int error;
                        if (table->child) {
-                               if (sysctl_perm(root, table, 001))
+                               if (sysctl_perm(root, table, MAY_EXEC))
                                        return -EPERM;
                                name++;
                                nlen--;
@@ -1597,7 +1635,7 @@ static int test_perm(int mode, int op)
                mode >>= 6;
        else if (in_egroup_p(0))
                mode >>= 3;
-       if ((mode & op & 0007) == op)
+       if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0)
                return 0;
        return -EACCES;
 }
@@ -1607,7 +1645,7 @@ int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
        int error;
        int mode;
 
-       error = security_sysctl(table, op);
+       error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC));
        if (error)
                return error;
 
@@ -1642,6 +1680,54 @@ static __init int sysctl_init(void)
 
 core_initcall(sysctl_init);
 
+static struct ctl_table *is_branch_in(struct ctl_table *branch,
+                                     struct ctl_table *table)
+{
+       struct ctl_table *p;
+       const char *s = branch->procname;
+
+       /* branch should have named subdirectory as its first element */
+       if (!s || !branch->child)
+               return NULL;
+
+       /* ... and nothing else */
+       if (branch[1].procname || branch[1].ctl_name)
+               return NULL;
+
+       /* table should contain subdirectory with the same name */
+       for (p = table; p->procname || p->ctl_name; p++) {
+               if (!p->child)
+                       continue;
+               if (p->procname && strcmp(p->procname, s) == 0)
+                       return p;
+       }
+       return NULL;
+}
+
+/* see if attaching q to p would be an improvement */
+static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
+{
+       struct ctl_table *to = p->ctl_table, *by = q->ctl_table;
+       struct ctl_table *next;
+       int is_better = 0;
+       int not_in_parent = !p->attached_by;
+
+       while ((next = is_branch_in(by, to)) != NULL) {
+               if (by == q->attached_by)
+                       is_better = 1;
+               if (to == p->attached_by)
+                       not_in_parent = 1;
+               by = by->child;
+               to = next->child;
+       }
+
+       if (is_better && not_in_parent) {
+               q->attached_by = by;
+               q->attached_to = to;
+               q->parent = p;
+       }
+}
+
 /**
  * __register_sysctl_paths - register a sysctl hierarchy
  * @root: List of sysctl headers to register on
@@ -1718,10 +1804,10 @@ struct ctl_table_header *__register_sysctl_paths(
        struct nsproxy *namespaces,
        const struct ctl_path *path, struct ctl_table *table)
 {
-       struct list_head *header_list;
        struct ctl_table_header *header;
        struct ctl_table *new, **prevp;
        unsigned int n, npath;
+       struct ctl_table_set *set;
 
        /* Count the path components */
        for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath)
@@ -1763,6 +1849,7 @@ struct ctl_table_header *__register_sysctl_paths(
        header->unregistering = NULL;
        header->root = root;
        sysctl_set_parent(NULL, header->ctl_table);
+       header->count = 1;
 #ifdef CONFIG_SYSCTL_SYSCALL_CHECK
        if (sysctl_check_table(namespaces, header->ctl_table)) {
                kfree(header);
@@ -1770,8 +1857,20 @@ struct ctl_table_header *__register_sysctl_paths(
        }
 #endif
        spin_lock(&sysctl_lock);
-       header_list = lookup_header_list(root, namespaces);
-       list_add_tail(&header->ctl_entry, header_list);
+       header->set = lookup_header_set(root, namespaces);
+       header->attached_by = header->ctl_table;
+       header->attached_to = root_table;
+       header->parent = &root_table_header;
+       for (set = header->set; set; set = set->parent) {
+               struct ctl_table_header *p;
+               list_for_each_entry(p, &set->list, ctl_entry) {
+                       if (p->unregistering)
+                               continue;
+                       try_attach(p, header);
+               }
+       }
+       header->parent->count++;
+       list_add_tail(&header->ctl_entry, &header->set->list);
        spin_unlock(&sysctl_lock);
 
        return header;
@@ -1826,8 +1925,37 @@ void unregister_sysctl_table(struct ctl_table_header * header)
 
        spin_lock(&sysctl_lock);
        start_unregistering(header);
+       if (!--header->parent->count) {
+               WARN_ON(1);
+               kfree(header->parent);
+       }
+       if (!--header->count)
+               kfree(header);
+       spin_unlock(&sysctl_lock);
+}
+
+int sysctl_is_seen(struct ctl_table_header *p)
+{
+       struct ctl_table_set *set = p->set;
+       int res;
+       spin_lock(&sysctl_lock);
+       if (p->unregistering)
+               res = 0;
+       else if (!set->is_seen)
+               res = 1;
+       else
+               res = set->is_seen(set);
        spin_unlock(&sysctl_lock);
-       kfree(header);
+       return res;
+}
+
+void setup_sysctl_set(struct ctl_table_set *p,
+       struct ctl_table_set *parent,
+       int (*is_seen)(struct ctl_table_set *))
+{
+       INIT_LIST_HEAD(&p->list);
+       p->parent = parent ? parent : &sysctl_table_root.default_set;
+       p->is_seen = is_seen;
 }
 
 #else /* !CONFIG_SYSCTL */
@@ -1846,6 +1974,16 @@ void unregister_sysctl_table(struct ctl_table_header * table)
 {
 }
 
+void setup_sysctl_set(struct ctl_table_set *p,
+       struct ctl_table_set *parent,
+       int (*is_seen)(struct ctl_table_set *))
+{
+}
+
+void sysctl_head_put(struct ctl_table_header *head)
+{
+}
+
 #endif /* CONFIG_SYSCTL */
 
 /*
index c09350d564f2c4d3baa5b1510ed0d42aeabdc6ba..c35da23ab8fb025f0fd0a03b54f90df3fe246cad 100644 (file)
@@ -1532,6 +1532,8 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
                        sysctl_check_leaf(namespaces, table, &fail);
                }
                sysctl_check_bin_path(table, &fail);
+               if (table->mode > 0777)
+                       set_fail(&fail, table, "bogus .mode");
                if (fail) {
                        set_fail(&fail, table, NULL);
                        error = -EINVAL;
index 06b17547f4e76869f16fedddc00f3a880fc6c364..bd6be76303cf23b4c52b757a93bf1966bdbb4f0a 100644 (file)
@@ -35,7 +35,7 @@
  */
 #define TASKSTATS_CPUMASK_MAXLEN       (100+6*NR_CPUS)
 
-static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 };
+static DEFINE_PER_CPU(__u32, taskstats_seqnum);
 static int family_registered;
 struct kmem_cache *taskstats_cache;
 
index bf43284d6855ad083319d653d1b0fbc3235dde08..80c4336f4188409a077d3f4ae4dde727f856de55 100644 (file)
@@ -196,12 +196,10 @@ static int tick_check_new_device(struct clock_event_device *newdev)
        struct tick_device *td;
        int cpu, ret = NOTIFY_OK;
        unsigned long flags;
-       cpumask_of_cpu_ptr_declare(cpumask);
 
        spin_lock_irqsave(&tick_device_lock, flags);
 
        cpu = smp_processor_id();
-       cpumask_of_cpu_ptr_next(cpumask, cpu);
        if (!cpu_isset(cpu, newdev->cpumask))
                goto out_bc;
 
@@ -209,7 +207,7 @@ static int tick_check_new_device(struct clock_event_device *newdev)
        curdev = td->evtdev;
 
        /* cpu local device ? */
-       if (!cpus_equal(newdev->cpumask, *cpumask)) {
+       if (!cpus_equal(newdev->cpumask, cpumask_of_cpu(cpu))) {
 
                /*
                 * If the cpu affinity of the device interrupt can not
@@ -222,7 +220,7 @@ static int tick_check_new_device(struct clock_event_device *newdev)
                 * If we have a cpu local device already, do not replace it
                 * by a non cpu local device
                 */
-               if (curdev && cpus_equal(curdev->cpumask, *cpumask))
+               if (curdev && cpus_equal(curdev->cpumask, cpumask_of_cpu(cpu)))
                        goto out_bc;
        }
 
@@ -254,7 +252,7 @@ static int tick_check_new_device(struct clock_event_device *newdev)
                curdev = NULL;
        }
        clockevents_exchange_device(curdev, newdev);
-       tick_setup_device(td, newdev, cpu, cpumask);
+       tick_setup_device(td, newdev, cpu, &cpumask_of_cpu(cpu));
        if (newdev->features & CLOCK_EVT_FEAT_ONESHOT)
                tick_oneshot_notify();
 
index 942fc7c85283af6592eefc8b8c4baa028bb13c1f..825b4c00fe4436a1921d4f57a6cb6d9e37510d3d 100644 (file)
@@ -195,7 +195,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
  * Called either from the idle loop or from irq_exit() when an idle period was
  * just interrupted by an interrupt which did not cause a reschedule.
  */
-void tick_nohz_stop_sched_tick(void)
+void tick_nohz_stop_sched_tick(int inidle)
 {
        unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
        struct tick_sched *ts;
@@ -224,6 +224,11 @@ void tick_nohz_stop_sched_tick(void)
        if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
                goto end;
 
+       if (!inidle && !ts->inidle)
+               goto end;
+
+       ts->inidle = 1;
+
        if (need_resched())
                goto end;
 
@@ -373,11 +378,14 @@ void tick_nohz_restart_sched_tick(void)
        local_irq_disable();
        tick_nohz_stop_idle(cpu);
 
-       if (!ts->tick_stopped) {
+       if (!ts->inidle || !ts->tick_stopped) {
+               ts->inidle = 0;
                local_irq_enable();
                return;
        }
 
+       ts->inidle = 0;
+
        rcu_exit_nohz();
 
        /* Update jiffies first */
index 4231a3dc224ac1f14460f63f195f7024980545c1..f6e3af31b403d8eaa77128712fdb594ca48be0c0 100644 (file)
@@ -587,7 +587,7 @@ static int __ftrace_modify_code(void *data)
 
 static void ftrace_run_update_code(int command)
 {
-       stop_machine_run(__ftrace_modify_code, &command, NR_CPUS);
+       stop_machine(__ftrace_modify_code, &command, NULL);
 }
 
 void ftrace_disable_daemon(void)
@@ -787,7 +787,7 @@ static int ftrace_update_code(void)
            !ftrace_enabled || !ftraced_trigger)
                return 0;
 
-       stop_machine_run(__ftrace_update_code, NULL, NR_CPUS);
+       stop_machine(__ftrace_update_code, NULL, NULL);
 
        return 1;
 }
@@ -1564,7 +1564,7 @@ static int __init ftrace_dynamic_init(void)
 
        addr = (unsigned long)ftrace_record_ip;
 
-       stop_machine_run(ftrace_dyn_arch_init, &addr, NR_CPUS);
+       stop_machine(ftrace_dyn_arch_init, &addr, NULL);
 
        /* ftrace_dyn_arch_init places the return code in addr */
        if (addr) {
index 868e121c8e385f36604271ddf93d97bb92f24dd0..8f3fb3db61c39306bdbffd36303cfed7dab02420 100644 (file)
@@ -1183,7 +1183,6 @@ static void *find_next_entry_inc(struct trace_iterator *iter)
 static void *s_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct trace_iterator *iter = m->private;
-       void *last_ent = iter->ent;
        int i = (int)*pos;
        void *ent;
 
@@ -1203,9 +1202,6 @@ static void *s_next(struct seq_file *m, void *v, loff_t *pos)
 
        iter->pos = *pos;
 
-       if (last_ent && !ent)
-               seq_puts(m, "\n\nvim:ft=help\n");
-
        return ent;
 }
 
index 421d6fe3650eded0e30ed86105de823c344beb3d..ece6cfb649fa52823f33988fd6792dad2d0d1fae 100644 (file)
@@ -253,12 +253,14 @@ void start_critical_timings(void)
        if (preempt_trace() || irq_trace())
                start_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
 }
+EXPORT_SYMBOL_GPL(start_critical_timings);
 
 void stop_critical_timings(void)
 {
        if (preempt_trace() || irq_trace())
                stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
 }
+EXPORT_SYMBOL_GPL(stop_critical_timings);
 
 #ifdef CONFIG_IRQSOFF_TRACER
 #ifdef CONFIG_PROVE_LOCKING
@@ -337,12 +339,14 @@ EXPORT_SYMBOL(trace_hardirqs_off_caller);
 #ifdef CONFIG_PREEMPT_TRACER
 void trace_preempt_on(unsigned long a0, unsigned long a1)
 {
-       stop_critical_timing(a0, a1);
+       if (preempt_trace())
+               stop_critical_timing(a0, a1);
 }
 
 void trace_preempt_off(unsigned long a0, unsigned long a1)
 {
-       start_critical_timing(a0, a1);
+       if (preempt_trace())
+               start_critical_timing(a0, a1);
 }
 #endif /* CONFIG_PREEMPT_TRACER */
 
index 3c8d61df4474adc473b107f04df43028f8efbee6..e303ccb62cdfb1284847864821d63a72694ca6af 100644 (file)
@@ -26,7 +26,8 @@ static struct task_struct     *wakeup_task;
 static int                     wakeup_cpu;
 static unsigned                        wakeup_prio = -1;
 
-static DEFINE_SPINLOCK(wakeup_lock);
+static raw_spinlock_t wakeup_lock =
+       (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
 
 static void __wakeup_reset(struct trace_array *tr);
 
@@ -56,7 +57,8 @@ wakeup_tracer_call(unsigned long ip, unsigned long parent_ip)
        if (unlikely(disabled != 1))
                goto out;
 
-       spin_lock_irqsave(&wakeup_lock, flags);
+       local_irq_save(flags);
+       __raw_spin_lock(&wakeup_lock);
 
        if (unlikely(!wakeup_task))
                goto unlock;
@@ -71,7 +73,8 @@ wakeup_tracer_call(unsigned long ip, unsigned long parent_ip)
        trace_function(tr, data, ip, parent_ip, flags);
 
  unlock:
-       spin_unlock_irqrestore(&wakeup_lock, flags);
+       __raw_spin_unlock(&wakeup_lock);
+       local_irq_restore(flags);
 
  out:
        atomic_dec(&data->disabled);
@@ -145,7 +148,8 @@ wakeup_sched_switch(void *private, void *rq, struct task_struct *prev,
        if (likely(disabled != 1))
                goto out;
 
-       spin_lock_irqsave(&wakeup_lock, flags);
+       local_irq_save(flags);
+       __raw_spin_lock(&wakeup_lock);
 
        /* We could race with grabbing wakeup_lock */
        if (unlikely(!tracer_enabled || next != wakeup_task))
@@ -174,7 +178,8 @@ wakeup_sched_switch(void *private, void *rq, struct task_struct *prev,
 
 out_unlock:
        __wakeup_reset(tr);
-       spin_unlock_irqrestore(&wakeup_lock, flags);
+       __raw_spin_unlock(&wakeup_lock);
+       local_irq_restore(flags);
 out:
        atomic_dec(&tr->data[cpu]->disabled);
 }
@@ -209,8 +214,6 @@ static void __wakeup_reset(struct trace_array *tr)
        struct trace_array_cpu *data;
        int cpu;
 
-       assert_spin_locked(&wakeup_lock);
-
        for_each_possible_cpu(cpu) {
                data = tr->data[cpu];
                tracing_reset(data);
@@ -229,9 +232,11 @@ static void wakeup_reset(struct trace_array *tr)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&wakeup_lock, flags);
+       local_irq_save(flags);
+       __raw_spin_lock(&wakeup_lock);
        __wakeup_reset(tr);
-       spin_unlock_irqrestore(&wakeup_lock, flags);
+       __raw_spin_unlock(&wakeup_lock);
+       local_irq_restore(flags);
 }
 
 static void
@@ -252,7 +257,7 @@ wakeup_check_start(struct trace_array *tr, struct task_struct *p,
                goto out;
 
        /* interrupts should be off from try_to_wake_up */
-       spin_lock(&wakeup_lock);
+       __raw_spin_lock(&wakeup_lock);
 
        /* check for races. */
        if (!tracer_enabled || p->prio >= wakeup_prio)
@@ -274,7 +279,7 @@ wakeup_check_start(struct trace_array *tr, struct task_struct *p,
                       CALLER_ADDR1, CALLER_ADDR2, flags);
 
 out_locked:
-       spin_unlock(&wakeup_lock);
+       __raw_spin_unlock(&wakeup_lock);
 out:
        atomic_dec(&tr->data[cpu]->disabled);
 }
index 63528086337c0145b6e59e4a77c9e80b40686408..bb948e52ce204bc1ec90b6bf6276a70203121de6 100644 (file)
@@ -161,7 +161,7 @@ static void timer_notify(struct pt_regs *regs, int cpu)
                __trace_special(tr, data, 2, regs->ip, 0);
 
                while (i < sample_max_depth) {
-                       frame.next_fp = 0;
+                       frame.next_fp = NULL;
                        frame.return_address = 0;
                        if (!copy_stack_frame(fp, &frame))
                                break;
@@ -213,9 +213,7 @@ static void start_stack_timers(void)
        int cpu;
 
        for_each_online_cpu(cpu) {
-               cpumask_of_cpu_ptr(new_mask, cpu);
-
-               set_cpus_allowed_ptr(current, new_mask);
+               set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
                start_stack_timer(cpu);
        }
        set_cpus_allowed_ptr(current, &saved_mask);
index 4ab1b584961b922afacc61f80750d1f0396ac0ec..8ebcd8532dfb33f80518feb2fc7e1cad1314bc31 100644 (file)
 void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
 {
        struct timespec uptime, ts;
-       s64 ac_etime;
+       u64 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, tsk->start_time);
-       /* rebase elapsed time to usec */
+       /* rebase elapsed time to usec (should never be negative) */
        ac_etime = timespec_to_ns(&ts);
        do_div(ac_etime, NSEC_PER_USEC);
        stats->ac_etime = ac_etime;
@@ -84,9 +84,9 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
 {
        struct mm_struct *mm;
 
-       /* 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;
+       /* convert pages-usec to Mbyte-usec */
+       stats->coremem = p->acct_rss_mem1 * PAGE_SIZE / MB;
+       stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE / MB;
        mm = get_task_mm(p);
        if (mm) {
                /* adjust to KB unit */
@@ -94,10 +94,10 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
                stats->hiwater_vm    = mm->hiwater_vm * PAGE_SIZE / KB;
                mmput(mm);
        }
-       stats->read_char        = p->rchar;
-       stats->write_char       = p->wchar;
-       stats->read_syscalls    = p->syscr;
-       stats->write_syscalls   = p->syscw;
+       stats->read_char        = p->ioac.rchar;
+       stats->write_char       = p->ioac.wchar;
+       stats->read_syscalls    = p->ioac.syscr;
+       stats->write_syscalls   = p->ioac.syscw;
 #ifdef CONFIG_TASK_IO_ACCOUNTING
        stats->read_bytes       = p->ioac.read_bytes;
        stats->write_bytes      = p->ioac.write_bytes;
@@ -118,12 +118,19 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
 void acct_update_integrals(struct task_struct *tsk)
 {
        if (likely(tsk->mm)) {
-               long delta = cputime_to_jiffies(
-                       cputime_sub(tsk->stime, tsk->acct_stimexpd));
+               cputime_t time, dtime;
+               struct timeval value;
+               u64 delta;
+
+               time = tsk->stime + tsk->utime;
+               dtime = cputime_sub(time, tsk->acct_timexpd);
+               jiffies_to_timeval(cputime_to_jiffies(dtime), &value);
+               delta = value.tv_sec;
+               delta = delta * USEC_PER_SEC + value.tv_usec;
 
                if (delta == 0)
                        return;
-               tsk->acct_stimexpd = tsk->stime;
+               tsk->acct_timexpd = time;
                tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
                tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
        }
@@ -135,7 +142,7 @@ void acct_update_integrals(struct task_struct *tsk)
  */
 void acct_clear_integrals(struct task_struct *tsk)
 {
-       tsk->acct_stimexpd = 0;
+       tsk->acct_timexpd = 0;
        tsk->acct_rss_mem1 = 0;
        tsk->acct_vm_mem1 = 0;
 }
index a6d36346d10ad11efc2cf0461720b34e5392ba19..ec7e4f62aaff4e71051eefb7d684e8ff4868a5ad 100644 (file)
@@ -125,7 +125,7 @@ struct cpu_workqueue_struct *get_wq_data(struct work_struct *work)
 }
 
 static void insert_work(struct cpu_workqueue_struct *cwq,
-                               struct work_struct *work, int tail)
+                       struct work_struct *work, struct list_head *head)
 {
        set_wq_data(work, cwq);
        /*
@@ -133,21 +133,17 @@ static void insert_work(struct cpu_workqueue_struct *cwq,
         * result of list_add() below, see try_to_grab_pending().
         */
        smp_wmb();
-       if (tail)
-               list_add_tail(&work->entry, &cwq->worklist);
-       else
-               list_add(&work->entry, &cwq->worklist);
+       list_add_tail(&work->entry, head);
        wake_up(&cwq->more_work);
 }
 
-/* Preempt must be disabled. */
 static void __queue_work(struct cpu_workqueue_struct *cwq,
                         struct work_struct *work)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&cwq->lock, flags);
-       insert_work(cwq, work, 1);
+       insert_work(cwq, work, &cwq->worklist);
        spin_unlock_irqrestore(&cwq->lock, flags);
 }
 
@@ -162,18 +158,40 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,
  * it can be processed by another CPU.
  */
 int queue_work(struct workqueue_struct *wq, struct work_struct *work)
+{
+       int ret;
+
+       ret = queue_work_on(get_cpu(), wq, work);
+       put_cpu();
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(queue_work);
+
+/**
+ * queue_work_on - queue work on specific cpu
+ * @cpu: CPU number to execute work on
+ * @wq: workqueue to use
+ * @work: work to queue
+ *
+ * Returns 0 if @work was already on a queue, non-zero otherwise.
+ *
+ * We queue the work to a specific CPU, the caller must ensure it
+ * can't go away.
+ */
+int
+queue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work)
 {
        int ret = 0;
 
        if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
                BUG_ON(!list_empty(&work->entry));
-               __queue_work(wq_per_cpu(wq, get_cpu()), work);
-               put_cpu();
+               __queue_work(wq_per_cpu(wq, cpu), work);
                ret = 1;
        }
        return ret;
 }
-EXPORT_SYMBOL_GPL(queue_work);
+EXPORT_SYMBOL_GPL(queue_work_on);
 
 static void delayed_work_timer_fn(unsigned long __data)
 {
@@ -337,14 +355,14 @@ static void wq_barrier_func(struct work_struct *work)
 }
 
 static void insert_wq_barrier(struct cpu_workqueue_struct *cwq,
-                                       struct wq_barrier *barr, int tail)
+                       struct wq_barrier *barr, struct list_head *head)
 {
        INIT_WORK(&barr->work, wq_barrier_func);
        __set_bit(WORK_STRUCT_PENDING, work_data_bits(&barr->work));
 
        init_completion(&barr->done);
 
-       insert_work(cwq, &barr->work, tail);
+       insert_work(cwq, &barr->work, head);
 }
 
 static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
@@ -364,7 +382,7 @@ static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
                active = 0;
                spin_lock_irq(&cwq->lock);
                if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) {
-                       insert_wq_barrier(cwq, &barr, 1);
+                       insert_wq_barrier(cwq, &barr, &cwq->worklist);
                        active = 1;
                }
                spin_unlock_irq(&cwq->lock);
@@ -402,6 +420,57 @@ void flush_workqueue(struct workqueue_struct *wq)
 }
 EXPORT_SYMBOL_GPL(flush_workqueue);
 
+/**
+ * flush_work - block until a work_struct's callback has terminated
+ * @work: the work which is to be flushed
+ *
+ * Returns false if @work has already terminated.
+ *
+ * It is expected that, prior to calling flush_work(), the caller has
+ * arranged for the work to not be requeued, otherwise it doesn't make
+ * sense to use this function.
+ */
+int flush_work(struct work_struct *work)
+{
+       struct cpu_workqueue_struct *cwq;
+       struct list_head *prev;
+       struct wq_barrier barr;
+
+       might_sleep();
+       cwq = get_wq_data(work);
+       if (!cwq)
+               return 0;
+
+       lock_acquire(&cwq->wq->lockdep_map, 0, 0, 0, 2, _THIS_IP_);
+       lock_release(&cwq->wq->lockdep_map, 1, _THIS_IP_);
+
+       prev = NULL;
+       spin_lock_irq(&cwq->lock);
+       if (!list_empty(&work->entry)) {
+               /*
+                * See the comment near try_to_grab_pending()->smp_rmb().
+                * If it was re-queued under us we are not going to wait.
+                */
+               smp_rmb();
+               if (unlikely(cwq != get_wq_data(work)))
+                       goto out;
+               prev = &work->entry;
+       } else {
+               if (cwq->current_work != work)
+                       goto out;
+               prev = &cwq->worklist;
+       }
+       insert_wq_barrier(cwq, &barr, prev->next);
+out:
+       spin_unlock_irq(&cwq->lock);
+       if (!prev)
+               return 0;
+
+       wait_for_completion(&barr.done);
+       return 1;
+}
+EXPORT_SYMBOL_GPL(flush_work);
+
 /*
  * Upon a successful return (>= 0), the caller "owns" WORK_STRUCT_PENDING bit,
  * so this work can't be re-armed in any way.
@@ -449,7 +518,7 @@ static void wait_on_cpu_work(struct cpu_workqueue_struct *cwq,
 
        spin_lock_irq(&cwq->lock);
        if (unlikely(cwq->current_work == work)) {
-               insert_wq_barrier(cwq, &barr, 0);
+               insert_wq_barrier(cwq, &barr, cwq->worklist.next);
                running = 1;
        }
        spin_unlock_irq(&cwq->lock);
@@ -553,6 +622,19 @@ int schedule_work(struct work_struct *work)
 }
 EXPORT_SYMBOL(schedule_work);
 
+/*
+ * schedule_work_on - put work task on a specific cpu
+ * @cpu: cpu to put the work task on
+ * @work: job to be done
+ *
+ * This puts a job on a specific cpu
+ */
+int schedule_work_on(int cpu, struct work_struct *work)
+{
+       return queue_work_on(cpu, keventd_wq, work);
+}
+EXPORT_SYMBOL(schedule_work_on);
+
 /**
  * schedule_delayed_work - put work task in global workqueue after delay
  * @dwork: job to be done
@@ -607,10 +689,10 @@ int schedule_on_each_cpu(work_func_t func)
                struct work_struct *work = per_cpu_ptr(works, cpu);
 
                INIT_WORK(work, func);
-               set_bit(WORK_STRUCT_PENDING, work_data_bits(work));
-               __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), work);
+               schedule_work_on(cpu, work);
        }
-       flush_workqueue(keventd_wq);
+       for_each_online_cpu(cpu)
+               flush_work(per_cpu_ptr(works, cpu));
        put_online_cpus();
        free_percpu(works);
        return 0;
@@ -747,7 +829,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
                err = create_workqueue_thread(cwq, singlethread_cpu);
                start_workqueue_thread(cwq, -1);
        } else {
-               get_online_cpus();
+               cpu_maps_update_begin();
                spin_lock(&workqueue_lock);
                list_add(&wq->list, &workqueues);
                spin_unlock(&workqueue_lock);
@@ -759,7 +841,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
                        err = create_workqueue_thread(cwq, cpu);
                        start_workqueue_thread(cwq, cpu);
                }
-               put_online_cpus();
+               cpu_maps_update_done();
        }
 
        if (err) {
@@ -773,8 +855,8 @@ EXPORT_SYMBOL_GPL(__create_workqueue_key);
 static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
 {
        /*
-        * Our caller is either destroy_workqueue() or CPU_DEAD,
-        * get_online_cpus() protects cwq->thread.
+        * Our caller is either destroy_workqueue() or CPU_POST_DEAD,
+        * cpu_add_remove_lock protects cwq->thread.
         */
        if (cwq->thread == NULL)
                return;
@@ -784,7 +866,7 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
 
        flush_cpu_workqueue(cwq);
        /*
-        * If the caller is CPU_DEAD and cwq->worklist was not empty,
+        * If the caller is CPU_POST_DEAD and cwq->worklist was not empty,
         * a concurrent flush_workqueue() can insert a barrier after us.
         * However, in that case run_workqueue() won't return and check
         * kthread_should_stop() until it flushes all work_struct's.
@@ -808,14 +890,14 @@ void destroy_workqueue(struct workqueue_struct *wq)
        const cpumask_t *cpu_map = wq_cpu_map(wq);
        int cpu;
 
-       get_online_cpus();
+       cpu_maps_update_begin();
        spin_lock(&workqueue_lock);
        list_del(&wq->list);
        spin_unlock(&workqueue_lock);
 
        for_each_cpu_mask_nr(cpu, *cpu_map)
                cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu));
-       put_online_cpus();
+       cpu_maps_update_done();
 
        free_percpu(wq->cpu_wq);
        kfree(wq);
@@ -829,6 +911,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
        unsigned int cpu = (unsigned long)hcpu;
        struct cpu_workqueue_struct *cwq;
        struct workqueue_struct *wq;
+       int ret = NOTIFY_OK;
 
        action &= ~CPU_TASKS_FROZEN;
 
@@ -836,7 +919,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
        case CPU_UP_PREPARE:
                cpu_set(cpu, cpu_populated_map);
        }
-
+undo:
        list_for_each_entry(wq, &workqueues, list) {
                cwq = per_cpu_ptr(wq->cpu_wq, cpu);
 
@@ -846,7 +929,9 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
                                break;
                        printk(KERN_ERR "workqueue [%s] for %i failed\n",
                                wq->name, cpu);
-                       return NOTIFY_BAD;
+                       action = CPU_UP_CANCELED;
+                       ret = NOTIFY_BAD;
+                       goto undo;
 
                case CPU_ONLINE:
                        start_workqueue_thread(cwq, cpu);
@@ -854,7 +939,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
 
                case CPU_UP_CANCELED:
                        start_workqueue_thread(cwq, -1);
-               case CPU_DEAD:
+               case CPU_POST_DEAD:
                        cleanup_workqueue_thread(cwq);
                        break;
                }
@@ -862,11 +947,11 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_CANCELED:
-       case CPU_DEAD:
+       case CPU_POST_DEAD:
                cpu_clear(cpu, cpu_populated_map);
        }
 
-       return NOTIFY_OK;
+       return ret;
 }
 
 void __init init_workqueues(void)
index 882c51048993010ae70049f2628deaa552645ddb..e1d4764435ed842ea1875c7739bfd668f6453fae 100644 (file)
@@ -505,6 +505,18 @@ config DEBUG_WRITECOUNT
 
          If unsure, say N.
 
+config DEBUG_MEMORY_INIT
+       bool "Debug memory initialisation" if EMBEDDED
+       default !EMBEDDED
+       help
+         Enable this for additional checks during memory initialisation.
+         The sanity checks verify aspects of the VM such as the memory model
+         and other information provided by the architecture. Verbose
+         information will be printed at KERN_DEBUG loglevel depending
+         on the mminit_loglevel= command-line option.
+
+         If unsure, say Y
+
 config DEBUG_LIST
        bool "Debug linked list manipulation"
        depends on DEBUG_KERNEL
index 818c4d4555188b509e015c198acb191e2f7a15b4..3b1f94bbe9de7415903c716753c0f96899c49938 100644 (file)
@@ -11,14 +11,14 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
         rbtree.o radix-tree.o dump_stack.o \
         idr.o int_sqrt.o extable.o prio_tree.o \
         sha1.o irq_regs.o reciprocal_div.o argv_split.o \
-        proportions.o prio_heap.o ratelimit.o
+        proportions.o prio_heap.o ratelimit.o show_mem.o
 
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
 
 lib-y  += kobject.o kref.o klist.o
 
-obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
+obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
         bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
@@ -78,6 +78,8 @@ lib-$(CONFIG_GENERIC_BUG) += bug.o
 
 obj-$(CONFIG_HAVE_LMB) += lmb.o
 
+obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o
+
 hostprogs-y    := gen_crc32table
 clean-files    := crc32table.h
 
diff --git a/lib/bcd.c b/lib/bcd.c
new file mode 100644 (file)
index 0000000..d74257f
--- /dev/null
+++ b/lib/bcd.c
@@ -0,0 +1,14 @@
+#include <linux/bcd.h>
+#include <linux/module.h>
+
+unsigned bcd2bin(unsigned char val)
+{
+       return (val & 0x0f) + (val >> 4) * 10;
+}
+EXPORT_SYMBOL(bcd2bin);
+
+unsigned char bin2bcd(unsigned val)
+{
+       return ((val / 10) << 4) + val % 10;
+}
+EXPORT_SYMBOL(bin2bcd);
index f596c08d213a0726c5f395209a3e20d730c3ea2c..f5f3ad8b62ff9844739fcdedde9389e6869e0cfc 100644 (file)
@@ -116,7 +116,7 @@ char *get_options(const char *str, int nints, int *ints)
 /**
  *     memparse - parse a string with mem suffixes into a number
  *     @ptr: Where parse begins
- *     @retptr: (output) Pointer to next char after parse completes
+ *     @retptr: (output) Optional pointer to next char after parse completes
  *
  *     Parses a string into a number.  The number stored at @ptr is
  *     potentially suffixed with %K (for kilobytes, or 1024 bytes),
@@ -126,11 +126,13 @@ char *get_options(const char *str, int nints, int *ints)
  *     megabyte, or one gigabyte, respectively.
  */
 
-unsigned long long memparse (char *ptr, char **retptr)
+unsigned long long memparse(const char *ptr, char **retptr)
 {
-       unsigned long long ret = simple_strtoull (ptr, retptr, 0);
+       char *endptr;   /* local pointer to end of parsed string */
 
-       switch (**retptr) {
+       unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
+
+       switch (*endptr) {
        case 'G':
        case 'g':
                ret <<= 10;
@@ -140,10 +142,14 @@ unsigned long long memparse (char *ptr, char **retptr)
        case 'K':
        case 'k':
                ret <<= 10;
-               (*retptr)++;
+               endptr++;
        default:
                break;
        }
+
+       if (retptr)
+               *retptr = endptr;
+
        return ret;
 }
 
index 85b18d79be89acee07e25004eac991df799f0b8a..45a6bde762d12232fab2c1f422e398625bb35e37 100644 (file)
@@ -205,9 +205,8 @@ static void debug_print_object(struct debug_obj *obj, char *msg)
 
        if (limit < 5 && obj->descr != descr_test) {
                limit++;
-               printk(KERN_ERR "ODEBUG: %s %s object type: %s\n", msg,
+               WARN(1, KERN_ERR "ODEBUG: %s %s object type: %s\n", msg,
                       obj_states[obj->state], obj->descr->name);
-               WARN_ON(1);
        }
        debug_objects_warnings++;
 }
@@ -226,15 +225,13 @@ debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state),
 
 static void debug_object_is_on_stack(void *addr, int onstack)
 {
-       void *stack = current->stack;
        int is_on_stack;
        static int limit;
 
        if (limit > 4)
                return;
 
-       is_on_stack = (addr >= stack && addr < (stack + THREAD_SIZE));
-
+       is_on_stack = object_is_on_stack(addr);
        if (is_on_stack == onstack)
                return;
 
@@ -735,26 +732,22 @@ check_results(void *addr, enum debug_obj_state state, int fixups, int warnings)
 
        obj = lookup_object(addr, db);
        if (!obj && state != ODEBUG_STATE_NONE) {
-               printk(KERN_ERR "ODEBUG: selftest object not found\n");
-               WARN_ON(1);
+               WARN(1, KERN_ERR "ODEBUG: selftest object not found\n");
                goto out;
        }
        if (obj && obj->state != state) {
-               printk(KERN_ERR "ODEBUG: selftest wrong state: %d != %d\n",
+               WARN(1, KERN_ERR "ODEBUG: selftest wrong state: %d != %d\n",
                       obj->state, state);
-               WARN_ON(1);
                goto out;
        }
        if (fixups != debug_objects_fixups) {
-               printk(KERN_ERR "ODEBUG: selftest fixups failed %d != %d\n",
+               WARN(1, KERN_ERR "ODEBUG: selftest fixups failed %d != %d\n",
                       fixups, debug_objects_fixups);
-               WARN_ON(1);
                goto out;
        }
        if (warnings != debug_objects_warnings) {
-               printk(KERN_ERR "ODEBUG: selftest warnings failed %d != %d\n",
+               WARN(1, KERN_ERR "ODEBUG: selftest warnings failed %d != %d\n",
                       warnings, debug_objects_warnings);
-               WARN_ON(1);
                goto out;
        }
        res = 0;
index 7a02e173f02773c2bc5fc3bfa763e269ef1b9f7a..e728c7fccc4de0884263cd8055aee977fe748522 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -6,6 +6,8 @@
  * Modified by George Anzinger to reuse immediately and to use
  * find bit instructions.  Also removed _irq on spinlocks.
  *
+ * Modified by Nadia Derbey to make it RCU safe.
+ *
  * Small id to pointer translation service.
  *
  * It uses a radix tree like structure as a sparse array indexed
@@ -35,7 +37,7 @@
 
 static struct kmem_cache *idr_layer_cache;
 
-static struct idr_layer *alloc_layer(struct idr *idp)
+static struct idr_layer *get_from_free_list(struct idr *idp)
 {
        struct idr_layer *p;
        unsigned long flags;
@@ -50,15 +52,28 @@ static struct idr_layer *alloc_layer(struct idr *idp)
        return(p);
 }
 
+static void idr_layer_rcu_free(struct rcu_head *head)
+{
+       struct idr_layer *layer;
+
+       layer = container_of(head, struct idr_layer, rcu_head);
+       kmem_cache_free(idr_layer_cache, layer);
+}
+
+static inline void free_layer(struct idr_layer *p)
+{
+       call_rcu(&p->rcu_head, idr_layer_rcu_free);
+}
+
 /* only called when idp->lock is held */
-static void __free_layer(struct idr *idp, struct idr_layer *p)
+static void __move_to_free_list(struct idr *idp, struct idr_layer *p)
 {
        p->ary[0] = idp->id_free;
        idp->id_free = p;
        idp->id_free_cnt++;
 }
 
-static void free_layer(struct idr *idp, struct idr_layer *p)
+static void move_to_free_list(struct idr *idp, struct idr_layer *p)
 {
        unsigned long flags;
 
@@ -66,7 +81,7 @@ static void free_layer(struct idr *idp, struct idr_layer *p)
         * Depends on the return element being zeroed.
         */
        spin_lock_irqsave(&idp->lock, flags);
-       __free_layer(idp, p);
+       __move_to_free_list(idp, p);
        spin_unlock_irqrestore(&idp->lock, flags);
 }
 
@@ -96,7 +111,7 @@ static void idr_mark_full(struct idr_layer **pa, int id)
  * @gfp_mask:  memory allocation flags
  *
  * This function should be called prior to locking and calling the
- * following function.  It preallocates enough memory to satisfy
+ * idr_get_new* functions. It preallocates enough memory to satisfy
  * the worst possible allocation.
  *
  * If the system is REALLY out of memory this function returns 0,
@@ -109,7 +124,7 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
                new = kmem_cache_alloc(idr_layer_cache, gfp_mask);
                if (new == NULL)
                        return (0);
-               free_layer(idp, new);
+               move_to_free_list(idp, new);
        }
        return 1;
 }
@@ -143,7 +158,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
                        /* if already at the top layer, we need to grow */
                        if (!(p = pa[l])) {
                                *starting_id = id;
-                               return -2;
+                               return IDR_NEED_TO_GROW;
                        }
 
                        /* If we need to go up one layer, continue the
@@ -160,16 +175,17 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
                        id = ((id >> sh) ^ n ^ m) << sh;
                }
                if ((id >= MAX_ID_BIT) || (id < 0))
-                       return -3;
+                       return IDR_NOMORE_SPACE;
                if (l == 0)
                        break;
                /*
                 * Create the layer below if it is missing.
                 */
                if (!p->ary[m]) {
-                       if (!(new = alloc_layer(idp)))
+                       new = get_from_free_list(idp);
+                       if (!new)
                                return -1;
-                       p->ary[m] = new;
+                       rcu_assign_pointer(p->ary[m], new);
                        p->count++;
                }
                pa[l--] = p;
@@ -192,7 +208,7 @@ build_up:
        p = idp->top;
        layers = idp->layers;
        if (unlikely(!p)) {
-               if (!(p = alloc_layer(idp)))
+               if (!(p = get_from_free_list(idp)))
                        return -1;
                layers = 1;
        }
@@ -204,7 +220,7 @@ build_up:
                layers++;
                if (!p->count)
                        continue;
-               if (!(new = alloc_layer(idp))) {
+               if (!(new = get_from_free_list(idp))) {
                        /*
                         * The allocation failed.  If we built part of
                         * the structure tear it down.
@@ -214,7 +230,7 @@ build_up:
                                p = p->ary[0];
                                new->ary[0] = NULL;
                                new->bitmap = new->count = 0;
-                               __free_layer(idp, new);
+                               __move_to_free_list(idp, new);
                        }
                        spin_unlock_irqrestore(&idp->lock, flags);
                        return -1;
@@ -225,10 +241,10 @@ build_up:
                        __set_bit(0, &new->bitmap);
                p = new;
        }
-       idp->top = p;
+       rcu_assign_pointer(idp->top, p);
        idp->layers = layers;
        v = sub_alloc(idp, &id, pa);
-       if (v == -2)
+       if (v == IDR_NEED_TO_GROW)
                goto build_up;
        return(v);
 }
@@ -244,7 +260,8 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
                 * Successfully found an empty slot.  Install the user
                 * pointer and mark the slot full.
                 */
-               pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr;
+               rcu_assign_pointer(pa[0]->ary[id & IDR_MASK],
+                               (struct idr_layer *)ptr);
                pa[0]->count++;
                idr_mark_full(pa, id);
        }
@@ -277,12 +294,8 @@ int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
         * This is a cheap hack until the IDR code can be fixed to
         * return proper error values.
         */
-       if (rv < 0) {
-               if (rv == -1)
-                       return -EAGAIN;
-               else /* Will be -3 */
-                       return -ENOSPC;
-       }
+       if (rv < 0)
+               return _idr_rc_to_errno(rv);
        *id = rv;
        return 0;
 }
@@ -312,12 +325,8 @@ int idr_get_new(struct idr *idp, void *ptr, int *id)
         * This is a cheap hack until the IDR code can be fixed to
         * return proper error values.
         */
-       if (rv < 0) {
-               if (rv == -1)
-                       return -EAGAIN;
-               else /* Will be -3 */
-                       return -ENOSPC;
-       }
+       if (rv < 0)
+               return _idr_rc_to_errno(rv);
        *id = rv;
        return 0;
 }
@@ -325,7 +334,8 @@ EXPORT_SYMBOL(idr_get_new);
 
 static void idr_remove_warning(int id)
 {
-       printk("idr_remove called for id=%d which is not allocated.\n", id);
+       printk(KERN_WARNING
+               "idr_remove called for id=%d which is not allocated.\n", id);
        dump_stack();
 }
 
@@ -334,6 +344,7 @@ static void sub_remove(struct idr *idp, int shift, int id)
        struct idr_layer *p = idp->top;
        struct idr_layer **pa[MAX_LEVEL];
        struct idr_layer ***paa = &pa[0];
+       struct idr_layer *to_free;
        int n;
 
        *paa = NULL;
@@ -349,13 +360,18 @@ static void sub_remove(struct idr *idp, int shift, int id)
        n = id & IDR_MASK;
        if (likely(p != NULL && test_bit(n, &p->bitmap))){
                __clear_bit(n, &p->bitmap);
-               p->ary[n] = NULL;
+               rcu_assign_pointer(p->ary[n], NULL);
+               to_free = NULL;
                while(*paa && ! --((**paa)->count)){
-                       free_layer(idp, **paa);
+                       if (to_free)
+                               free_layer(to_free);
+                       to_free = **paa;
                        **paa-- = NULL;
                }
                if (!*paa)
                        idp->layers = 0;
+               if (to_free)
+                       free_layer(to_free);
        } else
                idr_remove_warning(id);
 }
@@ -368,22 +384,34 @@ static void sub_remove(struct idr *idp, int shift, int id)
 void idr_remove(struct idr *idp, int id)
 {
        struct idr_layer *p;
+       struct idr_layer *to_free;
 
        /* Mask off upper bits we don't use for the search. */
        id &= MAX_ID_MASK;
 
        sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);
        if (idp->top && idp->top->count == 1 && (idp->layers > 1) &&
-           idp->top->ary[0]) {  // We can drop a layer
-
+           idp->top->ary[0]) {
+               /*
+                * Single child at leftmost slot: we can shrink the tree.
+                * This level is not needed anymore since when layers are
+                * inserted, they are inserted at the top of the existing
+                * tree.
+                */
+               to_free = idp->top;
                p = idp->top->ary[0];
-               idp->top->bitmap = idp->top->count = 0;
-               free_layer(idp, idp->top);
-               idp->top = p;
+               rcu_assign_pointer(idp->top, p);
                --idp->layers;
+               to_free->bitmap = to_free->count = 0;
+               free_layer(to_free);
        }
        while (idp->id_free_cnt >= IDR_FREE_MAX) {
-               p = alloc_layer(idp);
+               p = get_from_free_list(idp);
+               /*
+                * Note: we don't call the rcu callback here, since the only
+                * layers that fall into the freelist are those that have been
+                * preallocated.
+                */
                kmem_cache_free(idr_layer_cache, p);
        }
        return;
@@ -424,15 +452,13 @@ void idr_remove_all(struct idr *idp)
 
                id += 1 << n;
                while (n < fls(id)) {
-                       if (p) {
-                               memset(p, 0, sizeof *p);
-                               free_layer(idp, p);
-                       }
+                       if (p)
+                               free_layer(p);
                        n += IDR_BITS;
                        p = *--paa;
                }
        }
-       idp->top = NULL;
+       rcu_assign_pointer(idp->top, NULL);
        idp->layers = 0;
 }
 EXPORT_SYMBOL(idr_remove_all);
@@ -444,7 +470,7 @@ EXPORT_SYMBOL(idr_remove_all);
 void idr_destroy(struct idr *idp)
 {
        while (idp->id_free_cnt) {
-               struct idr_layer *p = alloc_layer(idp);
+               struct idr_layer *p = get_from_free_list(idp);
                kmem_cache_free(idr_layer_cache, p);
        }
 }
@@ -459,7 +485,8 @@ EXPORT_SYMBOL(idr_destroy);
  * return indicates that @id is not valid or you passed %NULL in
  * idr_get_new().
  *
- * The caller must serialize idr_find() vs idr_get_new() and idr_remove().
+ * This function can be called under rcu_read_lock(), given that the leaf
+ * pointers lifetimes are correctly managed.
  */
 void *idr_find(struct idr *idp, int id)
 {
@@ -467,7 +494,7 @@ void *idr_find(struct idr *idp, int id)
        struct idr_layer *p;
 
        n = idp->layers * IDR_BITS;
-       p = idp->top;
+       p = rcu_dereference(idp->top);
 
        /* Mask off upper bits we don't use for the search. */
        id &= MAX_ID_MASK;
@@ -477,7 +504,7 @@ void *idr_find(struct idr *idp, int id)
 
        while (n > 0 && p) {
                n -= IDR_BITS;
-               p = p->ary[(id >> n) & IDR_MASK];
+               p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
        }
        return((void *)p);
 }
@@ -510,7 +537,7 @@ int idr_for_each(struct idr *idp,
        struct idr_layer **paa = &pa[0];
 
        n = idp->layers * IDR_BITS;
-       p = idp->top;
+       p = rcu_dereference(idp->top);
        max = 1 << n;
 
        id = 0;
@@ -518,7 +545,7 @@ int idr_for_each(struct idr *idp,
                while (n > 0 && p) {
                        n -= IDR_BITS;
                        *paa++ = p;
-                       p = p->ary[(id >> n) & IDR_MASK];
+                       p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
                }
 
                if (p) {
@@ -548,7 +575,7 @@ EXPORT_SYMBOL(idr_for_each);
  * A -ENOENT return indicates that @id was not found.
  * A -EINVAL return indicates that @id was not within valid constraints.
  *
- * The caller must serialize vs idr_find(), idr_get_new(), and idr_remove().
+ * The caller must serialize with writers.
  */
 void *idr_replace(struct idr *idp, void *ptr, int id)
 {
@@ -574,13 +601,13 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
                return ERR_PTR(-ENOENT);
 
        old_p = p->ary[n];
-       p->ary[n] = ptr;
+       rcu_assign_pointer(p->ary[n], ptr);
 
        return old_p;
 }
 EXPORT_SYMBOL(idr_replace);
 
-static void idr_cache_ctor(struct kmem_cache *idr_layer_cache, void *idr_layer)
+static void idr_cache_ctor(void *idr_layer)
 {
        memset(idr_layer, 0, sizeof(struct idr_layer));
 }
@@ -694,12 +721,8 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
  restart:
        /* get vacant slot */
        t = idr_get_empty_slot(&ida->idr, idr_id, pa);
-       if (t < 0) {
-               if (t == -1)
-                       return -EAGAIN;
-               else /* will be -3 */
-                       return -ENOSPC;
-       }
+       if (t < 0)
+               return _idr_rc_to_errno(t);
 
        if (t * IDA_BITMAP_BITS >= MAX_ID_BIT)
                return -ENOSPC;
@@ -720,7 +743,8 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
                        return -EAGAIN;
 
                memset(bitmap, 0, sizeof(struct ida_bitmap));
-               pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap;
+               rcu_assign_pointer(pa[0]->ary[idr_id & IDR_MASK],
+                               (void *)bitmap);
                pa[0]->count++;
        }
 
@@ -749,7 +773,7 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
         * allocation.
         */
        if (ida->idr.id_free_cnt || ida->free_bitmap) {
-               struct idr_layer *p = alloc_layer(&ida->idr);
+               struct idr_layer *p = get_from_free_list(&ida->idr);
                if (p)
                        kmem_cache_free(idr_layer_cache, p);
        }
index 9762294be06257b6d6e6873dbd6b0503f21029c1..1a8e8a97812817f12460dbc880ce8fd4c53cf1cf 100644 (file)
@@ -230,6 +230,45 @@ STATIC const ush mask_bits[] = {
 #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
 #define DUMPBITS(n) {b>>=(n);k-=(n);}
 
+#ifndef NO_INFLATE_MALLOC
+/* A trivial malloc implementation, adapted from
+ *  malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ */
+
+static unsigned long malloc_ptr;
+static int malloc_count;
+
+static void *malloc(int size)
+{
+       void *p;
+
+       if (size < 0)
+               error("Malloc error");
+       if (!malloc_ptr)
+               malloc_ptr = free_mem_ptr;
+
+       malloc_ptr = (malloc_ptr + 3) & ~3;     /* Align */
+
+       p = (void *)malloc_ptr;
+       malloc_ptr += size;
+
+       if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
+               error("Out of memory");
+
+       malloc_count++;
+       return p;
+}
+
+static void free(void *where)
+{
+       malloc_count--;
+       if (!malloc_count)
+               malloc_ptr = free_mem_ptr;
+}
+#else
+#define malloc(a) kmalloc(a, GFP_KERNEL)
+#define free(a) kfree(a)
+#endif
 
 /*
    Huffman code decoding is performed using a multi-level table lookup.
@@ -1045,7 +1084,6 @@ STATIC int INIT inflate(void)
   int e;                /* last block flag */
   int r;                /* result code */
   unsigned h;           /* maximum struct huft's malloc'ed */
-  void *ptr;
 
   /* initialize window, bit buffer */
   wp = 0;
@@ -1057,12 +1095,12 @@ STATIC int INIT inflate(void)
   h = 0;
   do {
     hufts = 0;
-    gzip_mark(&ptr);
-    if ((r = inflate_block(&e)) != 0) {
-      gzip_release(&ptr);          
-      return r;
-    }
-    gzip_release(&ptr);
+#ifdef ARCH_HAS_DECOMP_WDOG
+    arch_decomp_wdog();
+#endif
+    r = inflate_block(&e);
+    if (r)
+           return r;
     if (hufts > h)
       h = hufts;
   } while (!e);
index 37a3ea4cac9f1c0a35c3e73430a5b28814f28d82..d32229385151657397709988acd392208c8d83f9 100644 (file)
@@ -40,8 +40,7 @@ static void bad_io_access(unsigned long port, const char *access)
        static int count = 10;
        if (count) {
                count--;
-               printk(KERN_ERR "Bad IO access at port %#lx (%s)\n", port, access);
-               WARN_ON(1);
+               WARN(1, KERN_ERR "Bad IO access at port %#lx (%s)\n", port, access);
        }
 }
 
index a3b8d4c3f77a5e7e466bd8f5e5591f3dcaa2c3bd..889ddce2021e26870b0b287ad0d28e7032e99028 100644 (file)
@@ -80,3 +80,11 @@ void iommu_area_free(unsigned long *map, unsigned long start, unsigned int nr)
        }
 }
 EXPORT_SYMBOL(iommu_area_free);
+
+unsigned long iommu_num_pages(unsigned long addr, unsigned long len)
+{
+       unsigned long size = roundup((addr & ~PAGE_MASK) + len, PAGE_SIZE);
+
+       return size >> PAGE_SHIFT;
+}
+EXPORT_SYMBOL(iommu_num_pages);
index 744401571ed76cbd48717f1aa1970804fc33cd9a..bd732ffebc85f36cfc30e70fa124f0566701ecba 100644 (file)
@@ -164,9 +164,8 @@ static int kobject_add_internal(struct kobject *kobj)
                return -ENOENT;
 
        if (!kobj->name || !kobj->name[0]) {
-               pr_debug("kobject: (%p): attempted to be registered with empty "
+               WARN(1, "kobject: (%p): attempted to be registered with empty "
                         "name!\n", kobj);
-               WARN_ON(1);
                return -EINVAL;
        }
 
@@ -583,12 +582,10 @@ static void kobject_release(struct kref *kref)
 void kobject_put(struct kobject *kobj)
 {
        if (kobj) {
-               if (!kobj->state_initialized) {
-                       printk(KERN_WARNING "kobject: '%s' (%p): is not "
+               if (!kobj->state_initialized)
+                       WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
                               "initialized, yet kobject_put() is being "
                               "called.\n", kobject_name(kobj), kobj);
-                       WARN_ON(1);
-               }
                kref_put(&kobj->kref, kobject_release);
        }
 }
index 9f8d599459d11011c0d9b5a7a11030af7c6e2f51..3f914725bda8ae6b278070b52258940bc4b68489 100644 (file)
@@ -285,8 +285,7 @@ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
        int len;
 
        if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
-               printk(KERN_ERR "add_uevent_var: too many keys\n");
-               WARN_ON(1);
+               WARN(1, KERN_ERR "add_uevent_var: too many keys\n");
                return -ENOMEM;
        }
 
@@ -297,8 +296,7 @@ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
        va_end(args);
 
        if (len >= (sizeof(env->buf) - env->buflen)) {
-               printk(KERN_ERR "add_uevent_var: buffer size too small\n");
-               WARN_ON(1);
+               WARN(1, KERN_ERR "add_uevent_var: buffer size too small\n");
                return -ENOMEM;
        }
 
index 4350ba9655bd182c966c1fc40909ace292c8a4a6..1a39f4e3ae1f1a93a8cb87cae13ce77b5c475d96 100644 (file)
@@ -20,18 +20,14 @@ 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 "
-                       "prev (%p), but was %p. (next=%p).\n",
-                       prev, next->prev, next);
-               BUG();
-       }
-       if (unlikely(prev->next != next)) {
-               printk(KERN_ERR "list_add corruption. prev->next should be "
-                       "next (%p), but was %p. (prev=%p).\n",
-                       next, prev->next, prev);
-               BUG();
-       }
+       WARN(next->prev != prev,
+               "list_add corruption. next->prev should be "
+               "prev (%p), but was %p. (next=%p).\n",
+               prev, next->prev, next);
+       WARN(prev->next != next,
+               "list_add corruption. prev->next should be "
+               "next (%p), but was %p. (prev=%p).\n",
+               next, prev->next, prev);
        next->prev = new;
        new->next = next;
        new->prev = prev;
@@ -39,20 +35,6 @@ void __list_add(struct list_head *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.
@@ -61,16 +43,12 @@ EXPORT_SYMBOL(list_add);
  */
 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();
-       }
+       WARN(entry->prev->next != entry,
+               "list_del corruption. prev->next should be %p, "
+               "but was %p\n", entry, entry->prev->next);
+       WARN(entry->next->prev != entry,
+               "list_del corruption. next->prev should be %p, "
+               "but was %p\n", entry, entry->next->prev);
        __list_del(entry->prev, entry->next);
        entry->next = LIST_POISON1;
        entry->prev = LIST_POISON2;
index 77f0f9b775a9c12ab2c1b42aaac31a0cf883e1d7..5dc6b29c1575f80903a3a9facc55642facbd0462 100644 (file)
@@ -138,8 +138,7 @@ match:
                                        t += 31 + *ip++;
                                }
                                m_pos = op - 1;
-                               m_pos -= le16_to_cpu(get_unaligned(
-                                       (const unsigned short *)ip)) >> 2;
+                               m_pos -= get_unaligned_le16(ip) >> 2;
                                ip += 2;
                        } else if (t >= 16) {
                                m_pos = op;
@@ -157,8 +156,7 @@ match:
                                        }
                                        t += 7 + *ip++;
                                }
-                               m_pos -= le16_to_cpu(get_unaligned(
-                                       (const unsigned short *)ip)) >> 2;
+                               m_pos -= get_unaligned_le16(ip) >> 2;
                                ip += 2;
                                if (m_pos == op)
                                        goto eof_found;
index 3074a02272f3c413b78a8c661d3d8d8ba3e47276..d6c64a824e1d70b7b3a83cde573d8fc7c16b2ada 100644 (file)
 static void plist_check_prev_next(struct list_head *t, struct list_head *p,
                                  struct list_head *n)
 {
-       if (n->prev != p || p->next != n) {
-               printk("top: %p, n: %p, p: %p\n", t, t->next, t->prev);
-               printk("prev: %p, n: %p, p: %p\n", p, p->next, p->prev);
-               printk("next: %p, n: %p, p: %p\n", n, n->next, n->prev);
-               WARN_ON(1);
-       }
+       WARN(n->prev != p || p->next != n,
+                       "top: %p, n: %p, p: %p\n"
+                       "prev: %p, n: %p, p: %p\n"
+                       "next: %p, n: %p, p: %p\n",
+                        t, t->next, t->prev,
+                       p, p->next, p->prev,
+                       n, n->next, n->prev);
 }
 
 static void plist_check_list(struct list_head *top)
index 56ec21a7f73dc09fb64dc395ee4297b04907d649..be86b32bc87482a76f847b8f6a784069be5d78e6 100644 (file)
@@ -359,18 +359,17 @@ EXPORT_SYMBOL(radix_tree_insert);
  *     Returns:  the slot corresponding to the position @index in the
  *     radix tree @root. This is useful for update-if-exists operations.
  *
- *     This function cannot be called under rcu_read_lock, it must be
- *     excluded from writers, as must the returned slot for subsequent
- *     use by radix_tree_deref_slot() and radix_tree_replace slot.
- *     Caller must hold tree write locked across slot lookup and
- *     replace.
+ *     This function can be called under rcu_read_lock iff the slot is not
+ *     modified by radix_tree_replace_slot, otherwise it must be called
+ *     exclusive from other writers. Any dereference of the slot must be done
+ *     using radix_tree_deref_slot.
  */
 void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index)
 {
        unsigned int height, shift;
        struct radix_tree_node *node, **slot;
 
-       node = root->rnode;
+       node = rcu_dereference(root->rnode);
        if (node == NULL)
                return NULL;
 
@@ -390,7 +389,7 @@ void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index)
        do {
                slot = (struct radix_tree_node **)
                        (node->slots + ((index>>shift) & RADIX_TREE_MAP_MASK));
-               node = *slot;
+               node = rcu_dereference(*slot);
                if (node == NULL)
                        return NULL;
 
@@ -667,7 +666,7 @@ unsigned long radix_tree_next_hole(struct radix_tree_root *root,
 EXPORT_SYMBOL(radix_tree_next_hole);
 
 static unsigned int
-__lookup(struct radix_tree_node *slot, void **results, unsigned long index,
+__lookup(struct radix_tree_node *slot, void ***results, unsigned long index,
        unsigned int max_items, unsigned long *next_index)
 {
        unsigned int nr_found = 0;
@@ -701,11 +700,9 @@ __lookup(struct radix_tree_node *slot, void **results, unsigned long index,
 
        /* Bottom level: grab some items */
        for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
-               struct radix_tree_node *node;
                index++;
-               node = slot->slots[i];
-               if (node) {
-                       results[nr_found++] = rcu_dereference(node);
+               if (slot->slots[i]) {
+                       results[nr_found++] = &(slot->slots[i]);
                        if (nr_found == max_items)
                                goto out;
                }
@@ -759,13 +756,22 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
 
        ret = 0;
        while (ret < max_items) {
-               unsigned int nr_found;
+               unsigned int nr_found, slots_found, i;
                unsigned long next_index;       /* Index of next search */
 
                if (cur_index > max_index)
                        break;
-               nr_found = __lookup(node, results + ret, cur_index,
+               slots_found = __lookup(node, (void ***)results + ret, cur_index,
                                        max_items - ret, &next_index);
+               nr_found = 0;
+               for (i = 0; i < slots_found; i++) {
+                       struct radix_tree_node *slot;
+                       slot = *(((void ***)results)[ret + i]);
+                       if (!slot)
+                               continue;
+                       results[ret + nr_found] = rcu_dereference(slot);
+                       nr_found++;
+               }
                ret += nr_found;
                if (next_index == 0)
                        break;
@@ -776,12 +782,71 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
 }
 EXPORT_SYMBOL(radix_tree_gang_lookup);
 
+/**
+ *     radix_tree_gang_lookup_slot - perform multiple slot lookup on radix tree
+ *     @root:          radix tree root
+ *     @results:       where the results of the lookup are placed
+ *     @first_index:   start the lookup from this key
+ *     @max_items:     place up to this many items at *results
+ *
+ *     Performs an index-ascending scan of the tree for present items.  Places
+ *     their slots at *@results and returns the number of items which were
+ *     placed at *@results.
+ *
+ *     The implementation is naive.
+ *
+ *     Like radix_tree_gang_lookup as far as RCU and locking goes. Slots must
+ *     be dereferenced with radix_tree_deref_slot, and if using only RCU
+ *     protection, radix_tree_deref_slot may fail requiring a retry.
+ */
+unsigned int
+radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
+                       unsigned long first_index, unsigned int max_items)
+{
+       unsigned long max_index;
+       struct radix_tree_node *node;
+       unsigned long cur_index = first_index;
+       unsigned int ret;
+
+       node = rcu_dereference(root->rnode);
+       if (!node)
+               return 0;
+
+       if (!radix_tree_is_indirect_ptr(node)) {
+               if (first_index > 0)
+                       return 0;
+               results[0] = (void **)&root->rnode;
+               return 1;
+       }
+       node = radix_tree_indirect_to_ptr(node);
+
+       max_index = radix_tree_maxindex(node->height);
+
+       ret = 0;
+       while (ret < max_items) {
+               unsigned int slots_found;
+               unsigned long next_index;       /* Index of next search */
+
+               if (cur_index > max_index)
+                       break;
+               slots_found = __lookup(node, results + ret, cur_index,
+                                       max_items - ret, &next_index);
+               ret += slots_found;
+               if (next_index == 0)
+                       break;
+               cur_index = next_index;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(radix_tree_gang_lookup_slot);
+
 /*
  * FIXME: the two tag_get()s here should use find_next_bit() instead of
  * open-coding the search.
  */
 static unsigned int
-__lookup_tag(struct radix_tree_node *slot, void **results, unsigned long index,
+__lookup_tag(struct radix_tree_node *slot, void ***results, unsigned long index,
        unsigned int max_items, unsigned long *next_index, unsigned int tag)
 {
        unsigned int nr_found = 0;
@@ -811,11 +876,9 @@ __lookup_tag(struct radix_tree_node *slot, void **results, unsigned long index,
                        unsigned long j = index & RADIX_TREE_MAP_MASK;
 
                        for ( ; j < RADIX_TREE_MAP_SIZE; j++) {
-                               struct radix_tree_node *node;
                                index++;
                                if (!tag_get(slot, tag, j))
                                        continue;
-                               node = slot->slots[j];
                                /*
                                 * Even though the tag was found set, we need to
                                 * recheck that we have a non-NULL node, because
@@ -826,9 +889,8 @@ __lookup_tag(struct radix_tree_node *slot, void **results, unsigned long index,
                                 * lookup ->slots[x] without a lock (ie. can't
                                 * rely on its value remaining the same).
                                 */
-                               if (node) {
-                                       node = rcu_dereference(node);
-                                       results[nr_found++] = node;
+                               if (slot->slots[j]) {
+                                       results[nr_found++] = &(slot->slots[j]);
                                        if (nr_found == max_items)
                                                goto out;
                                }
@@ -887,13 +949,22 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
 
        ret = 0;
        while (ret < max_items) {
-               unsigned int nr_found;
+               unsigned int nr_found, slots_found, i;
                unsigned long next_index;       /* Index of next search */
 
                if (cur_index > max_index)
                        break;
-               nr_found = __lookup_tag(node, results + ret, cur_index,
-                                       max_items - ret, &next_index, tag);
+               slots_found = __lookup_tag(node, (void ***)results + ret,
+                               cur_index, max_items - ret, &next_index, tag);
+               nr_found = 0;
+               for (i = 0; i < slots_found; i++) {
+                       struct radix_tree_node *slot;
+                       slot = *(((void ***)results)[ret + i]);
+                       if (!slot)
+                               continue;
+                       results[ret + nr_found] = rcu_dereference(slot);
+                       nr_found++;
+               }
                ret += nr_found;
                if (next_index == 0)
                        break;
@@ -904,6 +975,67 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
 }
 EXPORT_SYMBOL(radix_tree_gang_lookup_tag);
 
+/**
+ *     radix_tree_gang_lookup_tag_slot - perform multiple slot lookup on a
+ *                                       radix tree based on a tag
+ *     @root:          radix tree root
+ *     @results:       where the results of the lookup are placed
+ *     @first_index:   start the lookup from this key
+ *     @max_items:     place up to this many items at *results
+ *     @tag:           the tag index (< RADIX_TREE_MAX_TAGS)
+ *
+ *     Performs an index-ascending scan of the tree for present items which
+ *     have the tag indexed by @tag set.  Places the slots at *@results and
+ *     returns the number of slots which were placed at *@results.
+ */
+unsigned int
+radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results,
+               unsigned long first_index, unsigned int max_items,
+               unsigned int tag)
+{
+       struct radix_tree_node *node;
+       unsigned long max_index;
+       unsigned long cur_index = first_index;
+       unsigned int ret;
+
+       /* check the root's tag bit */
+       if (!root_tag_get(root, tag))
+               return 0;
+
+       node = rcu_dereference(root->rnode);
+       if (!node)
+               return 0;
+
+       if (!radix_tree_is_indirect_ptr(node)) {
+               if (first_index > 0)
+                       return 0;
+               results[0] = (void **)&root->rnode;
+               return 1;
+       }
+       node = radix_tree_indirect_to_ptr(node);
+
+       max_index = radix_tree_maxindex(node->height);
+
+       ret = 0;
+       while (ret < max_items) {
+               unsigned int slots_found;
+               unsigned long next_index;       /* Index of next search */
+
+               if (cur_index > max_index)
+                       break;
+               slots_found = __lookup_tag(node, results + ret,
+                               cur_index, max_items - ret, &next_index, tag);
+               ret += slots_found;
+               if (next_index == 0)
+                       break;
+               cur_index = next_index;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(radix_tree_gang_lookup_tag_slot);
+
+
 /**
  *     radix_tree_shrink    -    shrink height of a radix tree to minimal
  *     @root           radix tree root
@@ -1051,7 +1183,7 @@ int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag)
 EXPORT_SYMBOL(radix_tree_tagged);
 
 static void
-radix_tree_node_ctor(struct kmem_cache *cachep, void *node)
+radix_tree_node_ctor(void *node)
 {
        memset(node, 0, sizeof(struct radix_tree_node));
 }
index 485e3040dcd4cc7eedc1f5981fd4b8bd572572b6..26187edcc7ead6c8c14bd69f1bb77cb3ca4640b4 100644 (file)
@@ -3,6 +3,9 @@
  *
  * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com>
  *
+ * 2008-05-01 rewrite the function and use a ratelimit_state data struct as
+ * parameter. Now every user can use their own standalone ratelimit_state.
+ *
  * This file is released under the GPLv2.
  *
  */
 #include <linux/jiffies.h>
 #include <linux/module.h>
 
+static DEFINE_SPINLOCK(ratelimit_lock);
+
 /*
  * __ratelimit - rate limiting
- * @ratelimit_jiffies: minimum time in jiffies between two callbacks
- * @ratelimit_burst: number of callbacks we do before ratelimiting
+ * @rs: ratelimit_state data
  *
- * This enforces a rate limit: not more than @ratelimit_burst callbacks
- * in every ratelimit_jiffies
+ * This enforces a rate limit: not more than @rs->ratelimit_burst callbacks
+ * in every @rs->ratelimit_jiffies
  */
-int __ratelimit(int ratelimit_jiffies, int ratelimit_burst)
+int __ratelimit(struct ratelimit_state *rs)
 {
-       static DEFINE_SPINLOCK(ratelimit_lock);
-       static unsigned toks = 10 * 5 * HZ;
-       static unsigned long last_msg;
-       static int missed;
        unsigned long flags;
-       unsigned long now = jiffies;
 
-       spin_lock_irqsave(&ratelimit_lock, flags);
-       toks += now - last_msg;
-       last_msg = now;
-       if (toks > (ratelimit_burst * ratelimit_jiffies))
-               toks = ratelimit_burst * ratelimit_jiffies;
-       if (toks >= ratelimit_jiffies) {
-               int lost = missed;
-
-               missed = 0;
-               toks -= ratelimit_jiffies;
-               spin_unlock_irqrestore(&ratelimit_lock, flags);
-               if (lost)
-                       printk(KERN_WARNING "%s: %d messages suppressed\n",
-                               __func__, lost);
+       if (!rs->interval)
                return 1;
+
+       spin_lock_irqsave(&ratelimit_lock, flags);
+       if (!rs->begin)
+               rs->begin = jiffies;
+
+       if (time_is_before_jiffies(rs->begin + rs->interval)) {
+               if (rs->missed)
+                       printk(KERN_WARNING "%s: %d callbacks suppressed\n",
+                               __func__, rs->missed);
+               rs->begin = 0;
+               rs->printed = 0;
+               rs->missed = 0;
        }
-       missed++;
+       if (rs->burst && rs->burst > rs->printed)
+               goto print;
+
+       rs->missed++;
        spin_unlock_irqrestore(&ratelimit_lock, flags);
        return 0;
+
+print:
+       rs->printed++;
+       spin_unlock_irqrestore(&ratelimit_lock, flags);
+       return 1;
 }
 EXPORT_SYMBOL(__ratelimit);
diff --git a/lib/show_mem.c b/lib/show_mem.c
new file mode 100644 (file)
index 0000000..238e72a
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Generic show_mem() implementation
+ *
+ * Copyright (C) 2008 Johannes Weiner <hannes@saeurebad.de>
+ * All code subject to the GPL version 2.
+ */
+
+#include <linux/mm.h>
+#include <linux/nmi.h>
+#include <linux/quicklist.h>
+
+void show_mem(void)
+{
+       pg_data_t *pgdat;
+       unsigned long total = 0, reserved = 0, shared = 0,
+               nonshared = 0, highmem = 0;
+
+       printk(KERN_INFO "Mem-Info:\n");
+       show_free_areas();
+
+       for_each_online_pgdat(pgdat) {
+               unsigned long i, flags;
+
+               pgdat_resize_lock(pgdat, &flags);
+               for (i = 0; i < pgdat->node_spanned_pages; i++) {
+                       struct page *page;
+                       unsigned long pfn = pgdat->node_start_pfn + i;
+
+                       if (unlikely(!(i % MAX_ORDER_NR_PAGES)))
+                               touch_nmi_watchdog();
+
+                       if (!pfn_valid(pfn))
+                               continue;
+
+                       page = pfn_to_page(pfn);
+
+                       if (PageHighMem(page))
+                               highmem++;
+
+                       if (PageReserved(page))
+                               reserved++;
+                       else if (page_count(page) == 1)
+                               nonshared++;
+                       else if (page_count(page) > 1)
+                               shared += page_count(page) - 1;
+
+                       total++;
+               }
+               pgdat_resize_unlock(pgdat, &flags);
+       }
+
+       printk(KERN_INFO "%lu pages RAM\n", total);
+#ifdef CONFIG_HIGHMEM
+       printk(KERN_INFO "%lu pages HighMem\n", highmem);
+#endif
+       printk(KERN_INFO "%lu pages reserved\n", reserved);
+       printk(KERN_INFO "%lu pages shared\n", shared);
+       printk(KERN_INFO "%lu pages non-shared\n", nonshared);
+#ifdef CONFIG_QUICKLIST
+       printk(KERN_INFO "%lu pages in pagetable cache\n",
+               quicklist_total_size());
+#endif
+}
index c4381d9516f658ff62c6a2fd767310c78d80b7bc..0f8fc22ed1030a200f1fd3c203ca6789c5646ac8 100644 (file)
@@ -11,7 +11,6 @@ notrace unsigned int debug_smp_processor_id(void)
 {
        unsigned long preempt_count = preempt_count();
        int this_cpu = raw_smp_processor_id();
-       cpumask_of_cpu_ptr_declare(this_mask);
 
        if (likely(preempt_count))
                goto out;
@@ -23,9 +22,7 @@ notrace unsigned int debug_smp_processor_id(void)
         * Kernel threads bound to a single CPU can safely use
         * smp_processor_id():
         */
-       cpumask_of_cpu_ptr_next(this_mask, this_cpu);
-
-       if (cpus_equal(current->cpus_allowed, *this_mask))
+       if (cpus_equal(current->cpus_allowed, cpumask_of_cpu(this_cpu)))
                goto out;
 
        /*
index d568894df8ccd335c4acdcb47da4a7b3c4830150..977edbdbc1debada5937958f5835b1dc88c9beba 100644 (file)
@@ -492,7 +492,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                 */
                dma_addr_t handle;
                handle = swiotlb_map_single(NULL, NULL, size, DMA_FROM_DEVICE);
-               if (swiotlb_dma_mapping_error(handle))
+               if (swiotlb_dma_mapping_error(hwdev, handle))
                        return NULL;
 
                ret = bus_to_virt(handle);
@@ -824,7 +824,7 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
 }
 
 int
-swiotlb_dma_mapping_error(dma_addr_t dma_addr)
+swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
 {
        return (dma_addr == virt_to_bus(io_tlb_overflow_buffer));
 }
diff --git a/lib/syscall.c b/lib/syscall.c
new file mode 100644 (file)
index 0000000..a4f7067
--- /dev/null
@@ -0,0 +1,75 @@
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <asm/syscall.h>
+
+static int collect_syscall(struct task_struct *target, long *callno,
+                          unsigned long args[6], unsigned int maxargs,
+                          unsigned long *sp, unsigned long *pc)
+{
+       struct pt_regs *regs = task_pt_regs(target);
+       if (unlikely(!regs))
+               return -EAGAIN;
+
+       *sp = user_stack_pointer(regs);
+       *pc = instruction_pointer(regs);
+
+       *callno = syscall_get_nr(target, regs);
+       if (*callno != -1L && maxargs > 0)
+               syscall_get_arguments(target, regs, 0, maxargs, args);
+
+       return 0;
+}
+
+/**
+ * task_current_syscall - Discover what a blocked task is doing.
+ * @target:            thread to examine
+ * @callno:            filled with system call number or -1
+ * @args:              filled with @maxargs system call arguments
+ * @maxargs:           number of elements in @args to fill
+ * @sp:                        filled with user stack pointer
+ * @pc:                        filled with user PC
+ *
+ * If @target is blocked in a system call, returns zero with *@callno
+ * set to the the call's number and @args filled in with its arguments.
+ * Registers not used for system call arguments may not be available and
+ * it is not kosher to use &struct user_regset calls while the system
+ * call is still in progress.  Note we may get this result if @target
+ * has finished its system call but not yet returned to user mode, such
+ * as when it's stopped for signal handling or syscall exit tracing.
+ *
+ * If @target is blocked in the kernel during a fault or exception,
+ * returns zero with *@callno set to -1 and does not fill in @args.
+ * If so, it's now safe to examine @target using &struct user_regset
+ * get() calls as long as we're sure @target won't return to user mode.
+ *
+ * Returns -%EAGAIN if @target does not remain blocked.
+ *
+ * Returns -%EINVAL if @maxargs is too large (maximum is six).
+ */
+int task_current_syscall(struct task_struct *target, long *callno,
+                        unsigned long args[6], unsigned int maxargs,
+                        unsigned long *sp, unsigned long *pc)
+{
+       long state;
+       unsigned long ncsw;
+
+       if (unlikely(maxargs > 6))
+               return -EINVAL;
+
+       if (target == current)
+               return collect_syscall(target, callno, args, maxargs, sp, pc);
+
+       state = target->state;
+       if (unlikely(!state))
+               return -EAGAIN;
+
+       ncsw = wait_task_inactive(target, state);
+       if (unlikely(!ncsw) ||
+           unlikely(collect_syscall(target, callno, args, maxargs, sp, pc)) ||
+           unlikely(wait_task_inactive(target, state) != ncsw))
+               return -EAGAIN;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(task_current_syscall);
index c4de85285bb43cd2ab9810d42c67c8001d9adb1b..446c6588c75398ab91e9413c20363dcd076432da 100644 (file)
@@ -77,6 +77,9 @@ config FLAT_NODE_MEM_MAP
        def_bool y
        depends on !SPARSEMEM
 
+config HAVE_GET_USER_PAGES_FAST
+       bool
+
 #
 # Both the NUMA code and DISCONTIGMEM use arrays of pg_data_t's
 # to represent different areas of memory.  This variable allows
@@ -174,7 +177,7 @@ config SPLIT_PTLOCK_CPUS
 config MIGRATION
        bool "Page migration"
        def_bool y
-       depends on NUMA
+       depends on NUMA || ARCH_ENABLE_MEMORY_HOTREMOVE
        help
          Allows the migration of the physical location of pages of processes
          while the virtual addresses are not changed. This is useful for
@@ -205,3 +208,6 @@ config NR_QUICK
 config VIRT_TO_BUS
        def_bool y
        depends on !ARCH_NO_VIRT_TO_BUS
+
+config MMU_NOTIFIER
+       bool
index 18c143b3c46cd599c0822f64f503e134361b0aac..da4ccf015aea72ba4d18dc69cf47e7ac97481129 100644 (file)
@@ -11,7 +11,7 @@ obj-y                 := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
                           maccess.o page_alloc.o page-writeback.o pdflush.o \
                           readahead.o swap.o truncate.o vmscan.o \
                           prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
-                          page_isolation.o $(mmu-y)
+                          page_isolation.o mm_init.o $(mmu-y)
 
 obj-$(CONFIG_PROC_PAGE_MONITOR) += pagewalk.o
 obj-$(CONFIG_BOUNCE)   += bounce.o
@@ -25,6 +25,7 @@ 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_MMU_NOTIFIER) += mmu_notifier.o
 obj-$(CONFIG_SLAB) += slab.o
 obj-$(CONFIG_SLUB) += slub.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
index 843364594e23d1674669713b023cd6670bde8364..4297bc41bfd2aefc986d3d3957cf83e37a63cd4a 100644 (file)
  * Depopulating per-cpu data for a cpu going offline would be a typical
  * use case. You need to register a cpu hotplug handler for that purpose.
  */
-void percpu_depopulate(void *__pdata, int cpu)
+static void percpu_depopulate(void *__pdata, int cpu)
 {
        struct percpu_data *pdata = __percpu_disguise(__pdata);
 
        kfree(pdata->ptrs[cpu]);
        pdata->ptrs[cpu] = NULL;
 }
-EXPORT_SYMBOL_GPL(percpu_depopulate);
 
 /**
  * percpu_depopulate_mask - depopulate per-cpu data for some cpu's
  * @__pdata: per-cpu data to depopulate
  * @mask: depopulate per-cpu data for cpu's selected through mask bits
  */
-void __percpu_depopulate_mask(void *__pdata, cpumask_t *mask)
+static void __percpu_depopulate_mask(void *__pdata, cpumask_t *mask)
 {
        int cpu;
        for_each_cpu_mask_nr(cpu, *mask)
                percpu_depopulate(__pdata, cpu);
 }
-EXPORT_SYMBOL_GPL(__percpu_depopulate_mask);
+
+#define percpu_depopulate_mask(__pdata, mask) \
+       __percpu_depopulate_mask((__pdata), &(mask))
 
 /**
  * percpu_populate - populate per-cpu data for given cpu
@@ -51,7 +52,7 @@ EXPORT_SYMBOL_GPL(__percpu_depopulate_mask);
  * use case. You need to register a cpu hotplug handler for that purpose.
  * Per-cpu object is populated with zeroed buffer.
  */
-void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu)
+static void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu)
 {
        struct percpu_data *pdata = __percpu_disguise(__pdata);
        int node = cpu_to_node(cpu);
@@ -68,7 +69,6 @@ void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu)
                pdata->ptrs[cpu] = kzalloc(size, gfp);
        return pdata->ptrs[cpu];
 }
-EXPORT_SYMBOL_GPL(percpu_populate);
 
 /**
  * percpu_populate_mask - populate per-cpu data for more cpu's
@@ -79,8 +79,8 @@ EXPORT_SYMBOL_GPL(percpu_populate);
  *
  * Per-cpu objects are populated with zeroed buffers.
  */
-int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
-                          cpumask_t *mask)
+static int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
+                                 cpumask_t *mask)
 {
        cpumask_t populated;
        int cpu;
@@ -94,7 +94,9 @@ int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
                        cpu_set(cpu, populated);
        return 0;
 }
-EXPORT_SYMBOL_GPL(__percpu_populate_mask);
+
+#define percpu_populate_mask(__pdata, size, gfp, mask) \
+       __percpu_populate_mask((__pdata), (size), (gfp), &(mask))
 
 /**
  * percpu_alloc_mask - initial setup of per-cpu data
index 8d9f60e06f621e1d6bf614238ca86b82dcb3e840..4af15d0340adaa7bc9cded10d36302679d86f90a 100644 (file)
@@ -1,12 +1,12 @@
 /*
- *  linux/mm/bootmem.c
+ *  bootmem - A boot-time physical memory allocator and configurator
  *
  *  Copyright (C) 1999 Ingo Molnar
- *  Discontiguous memory support, Kanoj Sarcar, SGI, Nov 1999
+ *                1999 Kanoj Sarcar, SGI
+ *                2008 Johannes Weiner
  *
- *  simple boot-time physical memory area allocator and
- *  free memory collector. It's used to deal with reserved
- *  system memory and memory holes as well.
+ * Access to this subsystem has to be serialized externally (which is true
+ * for the boot process anyway).
  */
 #include <linux/init.h>
 #include <linux/pfn.h>
 
 #include "internal.h"
 
-/*
- * Access to this subsystem has to be serialized externally. (this is
- * true for the boot process anyway)
- */
 unsigned long max_low_pfn;
 unsigned long min_low_pfn;
 unsigned long max_pfn;
 
-static LIST_HEAD(bdata_list);
 #ifdef CONFIG_CRASH_DUMP
 /*
  * If we have booted due to a crash, max_pfn will be a very low value. We need
@@ -36,63 +31,72 @@ static LIST_HEAD(bdata_list);
 unsigned long saved_max_pfn;
 #endif
 
-/* return the number of _pages_ that will be allocated for the boot bitmap */
-unsigned long __init bootmem_bootmap_pages(unsigned long pages)
+bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata;
+
+static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list);
+
+static int bootmem_debug;
+
+static int __init bootmem_debug_setup(char *buf)
 {
-       unsigned long mapsize;
+       bootmem_debug = 1;
+       return 0;
+}
+early_param("bootmem_debug", bootmem_debug_setup);
 
-       mapsize = (pages+7)/8;
-       mapsize = (mapsize + ~PAGE_MASK) & PAGE_MASK;
-       mapsize >>= PAGE_SHIFT;
+#define bdebug(fmt, args...) ({                                \
+       if (unlikely(bootmem_debug))                    \
+               printk(KERN_INFO                        \
+                       "bootmem::%s " fmt,             \
+                       __FUNCTION__, ## args);         \
+})
 
-       return mapsize;
+static unsigned long __init bootmap_bytes(unsigned long pages)
+{
+       unsigned long bytes = (pages + 7) / 8;
+
+       return ALIGN(bytes, sizeof(long));
 }
 
-/*
- * link bdata in order
+/**
+ * bootmem_bootmap_pages - calculate bitmap size in pages
+ * @pages: number of pages the bitmap has to represent
  */
-static void __init link_bootmem(bootmem_data_t *bdata)
+unsigned long __init bootmem_bootmap_pages(unsigned long pages)
 {
-       bootmem_data_t *ent;
+       unsigned long bytes = bootmap_bytes(pages);
 
-       if (list_empty(&bdata_list)) {
-               list_add(&bdata->list, &bdata_list);
-               return;
-       }
-       /* insert in order */
-       list_for_each_entry(ent, &bdata_list, list) {
-               if (bdata->node_boot_start < ent->node_boot_start) {
-                       list_add_tail(&bdata->list, &ent->list);
-                       return;
-               }
-       }
-       list_add_tail(&bdata->list, &bdata_list);
+       return PAGE_ALIGN(bytes) >> PAGE_SHIFT;
 }
 
 /*
- * Given an initialised bdata, it returns the size of the boot bitmap
+ * link bdata in order
  */
-static unsigned long __init get_mapsize(bootmem_data_t *bdata)
+static void __init link_bootmem(bootmem_data_t *bdata)
 {
-       unsigned long mapsize;
-       unsigned long start = PFN_DOWN(bdata->node_boot_start);
-       unsigned long end = bdata->node_low_pfn;
+       struct list_head *iter;
 
-       mapsize = ((end - start) + 7) / 8;
-       return ALIGN(mapsize, sizeof(long));
+       list_for_each(iter, &bdata_list) {
+               bootmem_data_t *ent;
+
+               ent = list_entry(iter, bootmem_data_t, list);
+               if (bdata->node_min_pfn < ent->node_min_pfn)
+                       break;
+       }
+       list_add_tail(&bdata->list, iter);
 }
 
 /*
  * Called once to set up the allocator itself.
  */
-static unsigned long __init init_bootmem_core(pg_data_t *pgdat,
+static unsigned long __init init_bootmem_core(bootmem_data_t *bdata,
        unsigned long mapstart, unsigned long start, unsigned long end)
 {
-       bootmem_data_t *bdata = pgdat->bdata;
        unsigned long mapsize;
 
+       mminit_validate_memmodel_limits(&start, &end);
        bdata->node_bootmem_map = phys_to_virt(PFN_PHYS(mapstart));
-       bdata->node_boot_start = PFN_PHYS(start);
+       bdata->node_min_pfn = start;
        bdata->node_low_pfn = end;
        link_bootmem(bdata);
 
@@ -100,429 +104,461 @@ static unsigned long __init init_bootmem_core(pg_data_t *pgdat,
         * Initially all pages are reserved - setup_arch() has to
         * register free RAM areas explicitly.
         */
-       mapsize = get_mapsize(bdata);
+       mapsize = bootmap_bytes(end - start);
        memset(bdata->node_bootmem_map, 0xff, mapsize);
 
+       bdebug("nid=%td start=%lx map=%lx end=%lx mapsize=%lx\n",
+               bdata - bootmem_node_data, start, mapstart, end, mapsize);
+
        return mapsize;
 }
 
-/*
- * Marks a particular physical memory range as unallocatable. Usable RAM
- * might be used for boot-time allocations - or it might get added
- * to the free page pool later on.
+/**
+ * init_bootmem_node - register a node as boot memory
+ * @pgdat: node to register
+ * @freepfn: pfn where the bitmap for this node is to be placed
+ * @startpfn: first pfn on the node
+ * @endpfn: first pfn after the node
+ *
+ * Returns the number of bytes needed to hold the bitmap for this node.
  */
-static int __init can_reserve_bootmem_core(bootmem_data_t *bdata,
-                       unsigned long addr, unsigned long size, int flags)
+unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn,
+                               unsigned long startpfn, unsigned long endpfn)
 {
-       unsigned long sidx, eidx;
-       unsigned long i;
+       return init_bootmem_core(pgdat->bdata, freepfn, startpfn, endpfn);
+}
 
-       BUG_ON(!size);
+/**
+ * init_bootmem - register boot memory
+ * @start: pfn where the bitmap is to be placed
+ * @pages: number of available physical pages
+ *
+ * Returns the number of bytes needed to hold the bitmap.
+ */
+unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
+{
+       max_low_pfn = pages;
+       min_low_pfn = start;
+       return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages);
+}
 
-       /* out of range, don't hold other */
-       if (addr + size < bdata->node_boot_start ||
-               PFN_DOWN(addr) > bdata->node_low_pfn)
+static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
+{
+       int aligned;
+       struct page *page;
+       unsigned long start, end, pages, count = 0;
+
+       if (!bdata->node_bootmem_map)
                return 0;
 
+       start = bdata->node_min_pfn;
+       end = bdata->node_low_pfn;
+
        /*
-        * Round up to index to the range.
+        * If the start is aligned to the machines wordsize, we might
+        * be able to free pages in bulks of that order.
         */
-       if (addr > bdata->node_boot_start)
-               sidx= PFN_DOWN(addr - bdata->node_boot_start);
-       else
-               sidx = 0;
+       aligned = !(start & (BITS_PER_LONG - 1));
 
-       eidx = PFN_UP(addr + size - bdata->node_boot_start);
-       if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
-               eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
+       bdebug("nid=%td start=%lx end=%lx aligned=%d\n",
+               bdata - bootmem_node_data, start, end, aligned);
 
-       for (i = sidx; i < eidx; i++) {
-               if (test_bit(i, bdata->node_bootmem_map)) {
-                       if (flags & BOOTMEM_EXCLUSIVE)
-                               return -EBUSY;
-               }
-       }
+       while (start < end) {
+               unsigned long *map, idx, vec;
 
-       return 0;
+               map = bdata->node_bootmem_map;
+               idx = start - bdata->node_min_pfn;
+               vec = ~map[idx / BITS_PER_LONG];
 
-}
+               if (aligned && vec == ~0UL && start + BITS_PER_LONG < end) {
+                       int order = ilog2(BITS_PER_LONG);
 
-static void __init reserve_bootmem_core(bootmem_data_t *bdata,
-                       unsigned long addr, unsigned long size, int flags)
-{
-       unsigned long sidx, eidx;
-       unsigned long i;
-
-       BUG_ON(!size);
+                       __free_pages_bootmem(pfn_to_page(start), order);
+                       count += BITS_PER_LONG;
+               } else {
+                       unsigned long off = 0;
 
-       /* out of range */
-       if (addr + size < bdata->node_boot_start ||
-               PFN_DOWN(addr) > bdata->node_low_pfn)
-               return;
+                       while (vec && off < BITS_PER_LONG) {
+                               if (vec & 1) {
+                                       page = pfn_to_page(start + off);
+                                       __free_pages_bootmem(page, 0);
+                                       count++;
+                               }
+                               vec >>= 1;
+                               off++;
+                       }
+               }
+               start += BITS_PER_LONG;
+       }
 
-       /*
-        * Round up to index to the range.
-        */
-       if (addr > bdata->node_boot_start)
-               sidx= PFN_DOWN(addr - bdata->node_boot_start);
-       else
-               sidx = 0;
+       page = virt_to_page(bdata->node_bootmem_map);
+       pages = bdata->node_low_pfn - bdata->node_min_pfn;
+       pages = bootmem_bootmap_pages(pages);
+       count += pages;
+       while (pages--)
+               __free_pages_bootmem(page++, 0);
 
-       eidx = PFN_UP(addr + size - bdata->node_boot_start);
-       if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
-               eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
+       bdebug("nid=%td released=%lx\n", bdata - bootmem_node_data, count);
 
-       for (i = sidx; i < eidx; i++) {
-               if (test_and_set_bit(i, bdata->node_bootmem_map)) {
-#ifdef CONFIG_DEBUG_BOOTMEM
-                       printk("hm, page %08lx reserved twice.\n", i*PAGE_SIZE);
-#endif
-               }
-       }
+       return count;
 }
 
-static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
-                                    unsigned long size)
+/**
+ * free_all_bootmem_node - release a node's free pages to the buddy allocator
+ * @pgdat: node to be released
+ *
+ * Returns the number of pages actually released.
+ */
+unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
 {
-       unsigned long sidx, eidx;
-       unsigned long i;
-
-       BUG_ON(!size);
+       register_page_bootmem_info_node(pgdat);
+       return free_all_bootmem_core(pgdat->bdata);
+}
 
-       /* out range */
-       if (addr + size < bdata->node_boot_start ||
-               PFN_DOWN(addr) > bdata->node_low_pfn)
-               return;
-       /*
-        * round down end of usable mem, partially free pages are
-        * considered reserved.
-        */
+/**
+ * free_all_bootmem - release free pages to the buddy allocator
+ *
+ * Returns the number of pages actually released.
+ */
+unsigned long __init free_all_bootmem(void)
+{
+       return free_all_bootmem_core(NODE_DATA(0)->bdata);
+}
 
-       if (addr >= bdata->node_boot_start && addr < bdata->last_success)
-               bdata->last_success = addr;
+static void __init __free(bootmem_data_t *bdata,
+                       unsigned long sidx, unsigned long eidx)
+{
+       unsigned long idx;
 
-       /*
-        * Round up to index to the range.
-        */
-       if (PFN_UP(addr) > PFN_DOWN(bdata->node_boot_start))
-               sidx = PFN_UP(addr) - PFN_DOWN(bdata->node_boot_start);
-       else
-               sidx = 0;
+       bdebug("nid=%td start=%lx end=%lx\n", bdata - bootmem_node_data,
+               sidx + bdata->node_min_pfn,
+               eidx + bdata->node_min_pfn);
 
-       eidx = PFN_DOWN(addr + size - bdata->node_boot_start);
-       if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
-               eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
+       if (bdata->hint_idx > sidx)
+               bdata->hint_idx = sidx;
 
-       for (i = sidx; i < eidx; i++) {
-               if (unlikely(!test_and_clear_bit(i, bdata->node_bootmem_map)))
+       for (idx = sidx; idx < eidx; idx++)
+               if (!test_and_clear_bit(idx, bdata->node_bootmem_map))
                        BUG();
-       }
 }
 
-/*
- * We 'merge' subsequent allocations to save space. We might 'lose'
- * some fraction of a page if allocations cannot be satisfied due to
- * size constraints on boxes where there is physical RAM space
- * fragmentation - in these cases (mostly large memory boxes) this
- * is not a problem.
- *
- * On low memory boxes we get it right in 100% of the cases.
- *
- * alignment has to be a power of 2 value.
- *
- * NOTE:  This function is _not_ reentrant.
- */
-void * __init
-__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
-             unsigned long align, unsigned long goal, unsigned long limit)
+static int __init __reserve(bootmem_data_t *bdata, unsigned long sidx,
+                       unsigned long eidx, int flags)
 {
-       unsigned long areasize, preferred;
-       unsigned long i, start = 0, incr, eidx, end_pfn;
-       void *ret;
-       unsigned long node_boot_start;
-       void *node_bootmem_map;
-
-       if (!size) {
-               printk("__alloc_bootmem_core(): zero-sized request\n");
-               BUG();
-       }
-       BUG_ON(align & (align-1));
-
-       /* on nodes without memory - bootmem_map is NULL */
-       if (!bdata->node_bootmem_map)
-               return NULL;
+       unsigned long idx;
+       int exclusive = flags & BOOTMEM_EXCLUSIVE;
+
+       bdebug("nid=%td start=%lx end=%lx flags=%x\n",
+               bdata - bootmem_node_data,
+               sidx + bdata->node_min_pfn,
+               eidx + bdata->node_min_pfn,
+               flags);
+
+       for (idx = sidx; idx < eidx; idx++)
+               if (test_and_set_bit(idx, bdata->node_bootmem_map)) {
+                       if (exclusive) {
+                               __free(bdata, sidx, idx);
+                               return -EBUSY;
+                       }
+                       bdebug("silent double reserve of PFN %lx\n",
+                               idx + bdata->node_min_pfn);
+               }
+       return 0;
+}
 
-       /* bdata->node_boot_start is supposed to be (12+6)bits alignment on x86_64 ? */
-       node_boot_start = bdata->node_boot_start;
-       node_bootmem_map = bdata->node_bootmem_map;
-       if (align) {
-               node_boot_start = ALIGN(bdata->node_boot_start, align);
-               if (node_boot_start > bdata->node_boot_start)
-                       node_bootmem_map = (unsigned long *)bdata->node_bootmem_map +
-                           PFN_DOWN(node_boot_start - bdata->node_boot_start)/BITS_PER_LONG;
-       }
+static int __init mark_bootmem_node(bootmem_data_t *bdata,
+                               unsigned long start, unsigned long end,
+                               int reserve, int flags)
+{
+       unsigned long sidx, eidx;
 
-       if (limit && node_boot_start >= limit)
-               return NULL;
+       bdebug("nid=%td start=%lx end=%lx reserve=%d flags=%x\n",
+               bdata - bootmem_node_data, start, end, reserve, flags);
 
-       end_pfn = bdata->node_low_pfn;
-       limit = PFN_DOWN(limit);
-       if (limit && end_pfn > limit)
-               end_pfn = limit;
+       BUG_ON(start < bdata->node_min_pfn);
+       BUG_ON(end > bdata->node_low_pfn);
 
-       eidx = end_pfn - PFN_DOWN(node_boot_start);
+       sidx = start - bdata->node_min_pfn;
+       eidx = end - bdata->node_min_pfn;
 
-       /*
-        * We try to allocate bootmem pages above 'goal'
-        * first, then we try to allocate lower pages.
-        */
-       preferred = 0;
-       if (goal && PFN_DOWN(goal) < end_pfn) {
-               if (goal > node_boot_start)
-                       preferred = goal - node_boot_start;
-
-               if (bdata->last_success > node_boot_start &&
-                       bdata->last_success - node_boot_start >= preferred)
-                       if (!limit || (limit && limit > bdata->last_success))
-                               preferred = bdata->last_success - node_boot_start;
-       }
+       if (reserve)
+               return __reserve(bdata, sidx, eidx, flags);
+       else
+               __free(bdata, sidx, eidx);
+       return 0;
+}
 
-       preferred = PFN_DOWN(ALIGN(preferred, align));
-       areasize = (size + PAGE_SIZE-1) / PAGE_SIZE;
-       incr = align >> PAGE_SHIFT ? : 1;
+static int __init mark_bootmem(unsigned long start, unsigned long end,
+                               int reserve, int flags)
+{
+       unsigned long pos;
+       bootmem_data_t *bdata;
 
-restart_scan:
-       for (i = preferred; i < eidx;) {
-               unsigned long j;
+       pos = start;
+       list_for_each_entry(bdata, &bdata_list, list) {
+               int err;
+               unsigned long max;
 
-               i = find_next_zero_bit(node_bootmem_map, eidx, i);
-               i = ALIGN(i, incr);
-               if (i >= eidx)
-                       break;
-               if (test_bit(i, node_bootmem_map)) {
-                       i += incr;
+               if (pos < bdata->node_min_pfn ||
+                   pos >= bdata->node_low_pfn) {
+                       BUG_ON(pos != start);
                        continue;
                }
-               for (j = i + 1; j < i + areasize; ++j) {
-                       if (j >= eidx)
-                               goto fail_block;
-                       if (test_bit(j, node_bootmem_map))
-                               goto fail_block;
-               }
-               start = i;
-               goto found;
-       fail_block:
-               i = ALIGN(j, incr);
-               if (i == j)
-                       i += incr;
-       }
 
-       if (preferred > 0) {
-               preferred = 0;
-               goto restart_scan;
-       }
-       return NULL;
+               max = min(bdata->node_low_pfn, end);
 
-found:
-       bdata->last_success = PFN_PHYS(start) + node_boot_start;
-       BUG_ON(start >= eidx);
-
-       /*
-        * Is the next page of the previous allocation-end the start
-        * of this allocation's buffer? If yes then we can 'merge'
-        * the previous partial page with this allocation.
-        */
-       if (align < PAGE_SIZE &&
-           bdata->last_offset && bdata->last_pos+1 == start) {
-               unsigned long offset, remaining_size;
-               offset = ALIGN(bdata->last_offset, align);
-               BUG_ON(offset > PAGE_SIZE);
-               remaining_size = PAGE_SIZE - offset;
-               if (size < remaining_size) {
-                       areasize = 0;
-                       /* last_pos unchanged */
-                       bdata->last_offset = offset + size;
-                       ret = phys_to_virt(bdata->last_pos * PAGE_SIZE +
-                                          offset + node_boot_start);
-               } else {
-                       remaining_size = size - remaining_size;
-                       areasize = (remaining_size + PAGE_SIZE-1) / PAGE_SIZE;
-                       ret = phys_to_virt(bdata->last_pos * PAGE_SIZE +
-                                          offset + node_boot_start);
-                       bdata->last_pos = start + areasize - 1;
-                       bdata->last_offset = remaining_size;
+               err = mark_bootmem_node(bdata, pos, max, reserve, flags);
+               if (reserve && err) {
+                       mark_bootmem(start, pos, 0, 0);
+                       return err;
                }
-               bdata->last_offset &= ~PAGE_MASK;
-       } else {
-               bdata->last_pos = start + areasize - 1;
-               bdata->last_offset = size & ~PAGE_MASK;
-               ret = phys_to_virt(start * PAGE_SIZE + node_boot_start);
-       }
 
-       /*
-        * Reserve the area now:
-        */
-       for (i = start; i < start + areasize; i++)
-               if (unlikely(test_and_set_bit(i, node_bootmem_map)))
-                       BUG();
-       memset(ret, 0, size);
-       return ret;
+               if (max == end)
+                       return 0;
+               pos = bdata->node_low_pfn;
+       }
+       BUG();
 }
 
-static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
+/**
+ * free_bootmem_node - mark a page range as usable
+ * @pgdat: node the range resides on
+ * @physaddr: starting address of the range
+ * @size: size of the range in bytes
+ *
+ * Partial pages will be considered reserved and left as they are.
+ *
+ * The range must reside completely on the specified node.
+ */
+void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
+                             unsigned long size)
 {
-       struct page *page;
-       unsigned long pfn;
-       bootmem_data_t *bdata = pgdat->bdata;
-       unsigned long i, count, total = 0;
-       unsigned long idx;
-       unsigned long *map; 
-       int gofast = 0;
-
-       BUG_ON(!bdata->node_bootmem_map);
-
-       count = 0;
-       /* first extant page of the node */
-       pfn = PFN_DOWN(bdata->node_boot_start);
-       idx = bdata->node_low_pfn - pfn;
-       map = bdata->node_bootmem_map;
-       /* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */
-       if (bdata->node_boot_start == 0 ||
-           ffs(bdata->node_boot_start) - PAGE_SHIFT > ffs(BITS_PER_LONG))
-               gofast = 1;
-       for (i = 0; i < idx; ) {
-               unsigned long v = ~map[i / BITS_PER_LONG];
-
-               if (gofast && v == ~0UL) {
-                       int order;
-
-                       page = pfn_to_page(pfn);
-                       count += BITS_PER_LONG;
-                       order = ffs(BITS_PER_LONG) - 1;
-                       __free_pages_bootmem(page, order);
-                       i += BITS_PER_LONG;
-                       page += BITS_PER_LONG;
-               } else if (v) {
-                       unsigned long m;
-
-                       page = pfn_to_page(pfn);
-                       for (m = 1; m && i < idx; m<<=1, page++, i++) {
-                               if (v & m) {
-                                       count++;
-                                       __free_pages_bootmem(page, 0);
-                               }
-                       }
-               } else {
-                       i += BITS_PER_LONG;
-               }
-               pfn += BITS_PER_LONG;
-       }
-       total += count;
+       unsigned long start, end;
 
-       /*
-        * Now free the allocator bitmap itself, it's not
-        * needed anymore:
-        */
-       page = virt_to_page(bdata->node_bootmem_map);
-       count = 0;
-       idx = (get_mapsize(bdata) + PAGE_SIZE-1) >> PAGE_SHIFT;
-       for (i = 0; i < idx; i++, page++) {
-               __free_pages_bootmem(page, 0);
-               count++;
-       }
-       total += count;
-       bdata->node_bootmem_map = NULL;
+       start = PFN_UP(physaddr);
+       end = PFN_DOWN(physaddr + size);
 
-       return total;
+       mark_bootmem_node(pgdat->bdata, start, end, 0, 0);
 }
 
-unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn,
-                               unsigned long startpfn, unsigned long endpfn)
-{
-       return init_bootmem_core(pgdat, freepfn, startpfn, endpfn);
-}
-
-int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
-                                unsigned long size, int flags)
+/**
+ * free_bootmem - mark a page range as usable
+ * @addr: starting address of the range
+ * @size: size of the range in bytes
+ *
+ * Partial pages will be considered reserved and left as they are.
+ *
+ * The range must be contiguous but may span node boundaries.
+ */
+void __init free_bootmem(unsigned long addr, unsigned long size)
 {
-       int ret;
+       unsigned long start, end;
 
-       ret = can_reserve_bootmem_core(pgdat->bdata, physaddr, size, flags);
-       if (ret < 0)
-               return -ENOMEM;
-       reserve_bootmem_core(pgdat->bdata, physaddr, size, flags);
+       start = PFN_UP(addr);
+       end = PFN_DOWN(addr + size);
 
-       return 0;
+       mark_bootmem(start, end, 0, 0);
 }
 
-void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
-                             unsigned long size)
+/**
+ * reserve_bootmem_node - mark a page range as reserved
+ * @pgdat: node the range resides on
+ * @physaddr: starting address of the range
+ * @size: size of the range in bytes
+ * @flags: reservation flags (see linux/bootmem.h)
+ *
+ * Partial pages will be reserved.
+ *
+ * The range must reside completely on the specified node.
+ */
+int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
+                                unsigned long size, int flags)
 {
-       free_bootmem_core(pgdat->bdata, physaddr, size);
-}
+       unsigned long start, end;
 
-unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
-{
-       register_page_bootmem_info_node(pgdat);
-       return free_all_bootmem_core(pgdat);
-}
+       start = PFN_DOWN(physaddr);
+       end = PFN_UP(physaddr + size);
 
-unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
-{
-       max_low_pfn = pages;
-       min_low_pfn = start;
-       return init_bootmem_core(NODE_DATA(0), start, 0, pages);
+       return mark_bootmem_node(pgdat->bdata, start, end, 1, flags);
 }
 
 #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
+/**
+ * reserve_bootmem - mark a page range as usable
+ * @addr: starting address of the range
+ * @size: size of the range in bytes
+ * @flags: reservation flags (see linux/bootmem.h)
+ *
+ * Partial pages will be reserved.
+ *
+ * The range must be contiguous but may span node boundaries.
+ */
 int __init reserve_bootmem(unsigned long addr, unsigned long size,
                            int flags)
 {
-       bootmem_data_t *bdata;
-       int ret;
+       unsigned long start, end;
 
-       list_for_each_entry(bdata, &bdata_list, list) {
-               ret = can_reserve_bootmem_core(bdata, addr, size, flags);
-               if (ret < 0)
-                       return ret;
-       }
-       list_for_each_entry(bdata, &bdata_list, list)
-               reserve_bootmem_core(bdata, addr, size, flags);
+       start = PFN_DOWN(addr);
+       end = PFN_UP(addr + size);
 
-       return 0;
+       return mark_bootmem(start, end, 1, flags);
 }
 #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 
-void __init free_bootmem(unsigned long addr, unsigned long size)
+static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
+                               unsigned long size, unsigned long align,
+                               unsigned long goal, unsigned long limit)
 {
-       bootmem_data_t *bdata;
-       list_for_each_entry(bdata, &bdata_list, list)
-               free_bootmem_core(bdata, addr, size);
-}
+       unsigned long fallback = 0;
+       unsigned long min, max, start, sidx, midx, step;
 
-unsigned long __init free_all_bootmem(void)
-{
-       return free_all_bootmem_core(NODE_DATA(0));
+       BUG_ON(!size);
+       BUG_ON(align & (align - 1));
+       BUG_ON(limit && goal + size > limit);
+
+       if (!bdata->node_bootmem_map)
+               return NULL;
+
+       bdebug("nid=%td size=%lx [%lu pages] align=%lx goal=%lx limit=%lx\n",
+               bdata - bootmem_node_data, size, PAGE_ALIGN(size) >> PAGE_SHIFT,
+               align, goal, limit);
+
+       min = bdata->node_min_pfn;
+       max = bdata->node_low_pfn;
+
+       goal >>= PAGE_SHIFT;
+       limit >>= PAGE_SHIFT;
+
+       if (limit && max > limit)
+               max = limit;
+       if (max <= min)
+               return NULL;
+
+       step = max(align >> PAGE_SHIFT, 1UL);
+
+       if (goal && min < goal && goal < max)
+               start = ALIGN(goal, step);
+       else
+               start = ALIGN(min, step);
+
+       sidx = start - bdata->node_min_pfn;;
+       midx = max - bdata->node_min_pfn;
+
+       if (bdata->hint_idx > sidx) {
+               /*
+                * Handle the valid case of sidx being zero and still
+                * catch the fallback below.
+                */
+               fallback = sidx + 1;
+               sidx = ALIGN(bdata->hint_idx, step);
+       }
+
+       while (1) {
+               int merge;
+               void *region;
+               unsigned long eidx, i, start_off, end_off;
+find_block:
+               sidx = find_next_zero_bit(bdata->node_bootmem_map, midx, sidx);
+               sidx = ALIGN(sidx, step);
+               eidx = sidx + PFN_UP(size);
+
+               if (sidx >= midx || eidx > midx)
+                       break;
+
+               for (i = sidx; i < eidx; i++)
+                       if (test_bit(i, bdata->node_bootmem_map)) {
+                               sidx = ALIGN(i, step);
+                               if (sidx == i)
+                                       sidx += step;
+                               goto find_block;
+                       }
+
+               if (bdata->last_end_off &&
+                               PFN_DOWN(bdata->last_end_off) + 1 == sidx)
+                       start_off = ALIGN(bdata->last_end_off, align);
+               else
+                       start_off = PFN_PHYS(sidx);
+
+               merge = PFN_DOWN(start_off) < sidx;
+               end_off = start_off + size;
+
+               bdata->last_end_off = end_off;
+               bdata->hint_idx = PFN_UP(end_off);
+
+               /*
+                * Reserve the area now:
+                */
+               if (__reserve(bdata, PFN_DOWN(start_off) + merge,
+                               PFN_UP(end_off), BOOTMEM_EXCLUSIVE))
+                       BUG();
+
+               region = phys_to_virt(PFN_PHYS(bdata->node_min_pfn) +
+                               start_off);
+               memset(region, 0, size);
+               return region;
+       }
+
+       if (fallback) {
+               sidx = ALIGN(fallback - 1, step);
+               fallback = 0;
+               goto find_block;
+       }
+
+       return NULL;
 }
 
-void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
-                                     unsigned long goal)
+static void * __init ___alloc_bootmem_nopanic(unsigned long size,
+                                       unsigned long align,
+                                       unsigned long goal,
+                                       unsigned long limit)
 {
        bootmem_data_t *bdata;
-       void *ptr;
 
+restart:
        list_for_each_entry(bdata, &bdata_list, list) {
-               ptr = __alloc_bootmem_core(bdata, size, align, goal, 0);
-               if (ptr)
-                       return ptr;
+               void *region;
+
+               if (goal && bdata->node_low_pfn <= PFN_DOWN(goal))
+                       continue;
+               if (limit && bdata->node_min_pfn >= PFN_DOWN(limit))
+                       break;
+
+               region = alloc_bootmem_core(bdata, size, align, goal, limit);
+               if (region)
+                       return region;
+       }
+
+       if (goal) {
+               goal = 0;
+               goto restart;
        }
+
        return NULL;
 }
 
-void * __init __alloc_bootmem(unsigned long size, unsigned long align,
-                             unsigned long goal)
+/**
+ * __alloc_bootmem_nopanic - allocate boot memory without panicking
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may happen on any node in the system.
+ *
+ * Returns NULL on failure.
+ */
+void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
+                                       unsigned long goal)
 {
-       void *mem = __alloc_bootmem_nopanic(size,align,goal);
+       return ___alloc_bootmem_nopanic(size, align, goal, 0);
+}
+
+static void * __init ___alloc_bootmem(unsigned long size, unsigned long align,
+                                       unsigned long goal, unsigned long limit)
+{
+       void *mem = ___alloc_bootmem_nopanic(size, align, goal, limit);
 
        if (mem)
                return mem;
@@ -534,78 +570,135 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align,
        return NULL;
 }
 
+/**
+ * __alloc_bootmem - allocate boot memory
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may happen on any node in the system.
+ *
+ * The function panics if the request can not be satisfied.
+ */
+void * __init __alloc_bootmem(unsigned long size, unsigned long align,
+                             unsigned long goal)
+{
+       return ___alloc_bootmem(size, align, goal, 0);
+}
 
-void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
-                                  unsigned long align, unsigned long goal)
+static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata,
+                               unsigned long size, unsigned long align,
+                               unsigned long goal, unsigned long limit)
 {
        void *ptr;
 
-       ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);
+       ptr = alloc_bootmem_core(bdata, size, align, goal, limit);
        if (ptr)
                return ptr;
 
-       return __alloc_bootmem(size, align, goal);
+       return ___alloc_bootmem(size, align, goal, limit);
+}
+
+/**
+ * __alloc_bootmem_node - allocate boot memory from a specific node
+ * @pgdat: node to allocate from
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may fall back to any node in the system if the specified node
+ * can not hold the requested memory.
+ *
+ * The function panics if the request can not be satisfied.
+ */
+void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
+                                  unsigned long align, unsigned long goal)
+{
+       return ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0);
 }
 
 #ifdef CONFIG_SPARSEMEM
+/**
+ * alloc_bootmem_section - allocate boot memory from a specific section
+ * @size: size of the request in bytes
+ * @section_nr: sparse map section to allocate from
+ *
+ * Return NULL on failure.
+ */
 void * __init alloc_bootmem_section(unsigned long size,
                                    unsigned long section_nr)
 {
-       void *ptr;
-       unsigned long limit, goal, start_nr, end_nr, pfn;
-       struct pglist_data *pgdat;
+       bootmem_data_t *bdata;
+       unsigned long pfn, goal, limit;
 
        pfn = section_nr_to_pfn(section_nr);
-       goal = PFN_PHYS(pfn);
-       limit = PFN_PHYS(section_nr_to_pfn(section_nr + 1)) - 1;
-       pgdat = NODE_DATA(early_pfn_to_nid(pfn));
-       ptr = __alloc_bootmem_core(pgdat->bdata, size, SMP_CACHE_BYTES, goal,
-                                  limit);
+       goal = pfn << PAGE_SHIFT;
+       limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
+       bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
 
-       if (!ptr)
-               return NULL;
+       return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);
+}
+#endif
 
-       start_nr = pfn_to_section_nr(PFN_DOWN(__pa(ptr)));
-       end_nr = pfn_to_section_nr(PFN_DOWN(__pa(ptr) + size));
-       if (start_nr != section_nr || end_nr != section_nr) {
-               printk(KERN_WARNING "alloc_bootmem failed on section %ld.\n",
-                      section_nr);
-               free_bootmem_core(pgdat->bdata, __pa(ptr), size);
-               ptr = NULL;
-       }
+void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
+                                  unsigned long align, unsigned long goal)
+{
+       void *ptr;
 
-       return ptr;
+       ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);
+       if (ptr)
+               return ptr;
+
+       return __alloc_bootmem_nopanic(size, align, goal);
 }
-#endif
 
 #ifndef ARCH_LOW_ADDRESS_LIMIT
 #define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL
 #endif
 
+/**
+ * __alloc_bootmem_low - allocate low boot memory
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may happen on any node in the system.
+ *
+ * The function panics if the request can not be satisfied.
+ */
 void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
                                  unsigned long goal)
 {
-       bootmem_data_t *bdata;
-       void *ptr;
-
-       list_for_each_entry(bdata, &bdata_list, list) {
-               ptr = __alloc_bootmem_core(bdata, size, align, goal,
-                                               ARCH_LOW_ADDRESS_LIMIT);
-               if (ptr)
-                       return ptr;
-       }
-
-       /*
-        * Whoops, we cannot satisfy the allocation request.
-        */
-       printk(KERN_ALERT "low bootmem alloc of %lu bytes failed!\n", size);
-       panic("Out of low memory");
-       return NULL;
+       return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT);
 }
 
+/**
+ * __alloc_bootmem_low_node - allocate low boot memory from a specific node
+ * @pgdat: node to allocate from
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may fall back to any node in the system if the specified node
+ * can not hold the requested memory.
+ *
+ * The function panics if the request can not be satisfied.
+ */
 void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size,
                                       unsigned long align, unsigned long goal)
 {
-       return __alloc_bootmem_core(pgdat->bdata, size, align, goal,
-                                   ARCH_LOW_ADDRESS_LIMIT);
+       return ___alloc_bootmem_node(pgdat->bdata, size, align,
+                               goal, ARCH_LOW_ADDRESS_LIMIT);
 }
index 65d9d9e2b755e7dd7e662d4dd5cc45b19514a7ab..42bbc6909ba4852ac41506b175584ba4d00e32eb 100644 (file)
@@ -42,9 +42,6 @@
 
 #include <asm/mman.h>
 
-static ssize_t
-generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
-       loff_t offset, unsigned long nr_segs);
 
 /*
  * Shared mappings implemented 30.11.1994. It's not fully working yet,
@@ -112,13 +109,13 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 /*
  * Remove a page from the page cache and free it. Caller has to make
  * sure the page is locked and that nobody else uses it - or that usage
- * is safe.  The caller must hold a write_lock on the mapping's tree_lock.
+ * is safe.  The caller must hold the mapping's tree_lock.
  */
 void __remove_from_page_cache(struct page *page)
 {
        struct address_space *mapping = page->mapping;
 
-       mem_cgroup_uncharge_page(page);
+       mem_cgroup_uncharge_cache_page(page);
        radix_tree_delete(&mapping->page_tree, page->index);
        page->mapping = NULL;
        mapping->nrpages--;
@@ -144,9 +141,9 @@ void remove_from_page_cache(struct page *page)
 
        BUG_ON(!PageLocked(page));
 
-       write_lock_irq(&mapping->tree_lock);
+       spin_lock_irq(&mapping->tree_lock);
        __remove_from_page_cache(page);
-       write_unlock_irq(&mapping->tree_lock);
+       spin_unlock_irq(&mapping->tree_lock);
 }
 
 static int sync_page(void *word)
@@ -445,48 +442,52 @@ int filemap_write_and_wait_range(struct address_space *mapping,
 }
 
 /**
- * add_to_page_cache - add newly allocated pagecache pages
+ * add_to_page_cache_locked - add a locked page to the pagecache
  * @page:      page to add
  * @mapping:   the page's address_space
  * @offset:    page index
  * @gfp_mask:  page allocation mode
  *
- * This function is used to add newly allocated pagecache pages;
- * the page is new, so we can just run SetPageLocked() against it.
- * The other page state flags were set by rmqueue().
- *
+ * This function is used to add a page to the pagecache. It must be locked.
  * This function does not add the page to the LRU.  The caller must do that.
  */
-int add_to_page_cache(struct page *page, struct address_space *mapping,
+int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
                pgoff_t offset, gfp_t gfp_mask)
 {
-       int error = mem_cgroup_cache_charge(page, current->mm,
+       int error;
+
+       VM_BUG_ON(!PageLocked(page));
+
+       error = mem_cgroup_cache_charge(page, current->mm,
                                        gfp_mask & ~__GFP_HIGHMEM);
        if (error)
                goto out;
 
        error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
        if (error == 0) {
-               write_lock_irq(&mapping->tree_lock);
+               page_cache_get(page);
+               page->mapping = mapping;
+               page->index = offset;
+
+               spin_lock_irq(&mapping->tree_lock);
                error = radix_tree_insert(&mapping->page_tree, offset, page);
-               if (!error) {
-                       page_cache_get(page);
-                       SetPageLocked(page);
-                       page->mapping = mapping;
-                       page->index = offset;
+               if (likely(!error)) {
                        mapping->nrpages++;
                        __inc_zone_page_state(page, NR_FILE_PAGES);
-               } else
-                       mem_cgroup_uncharge_page(page);
+               } else {
+                       page->mapping = NULL;
+                       mem_cgroup_uncharge_cache_page(page);
+                       page_cache_release(page);
+               }
 
-               write_unlock_irq(&mapping->tree_lock);
+               spin_unlock_irq(&mapping->tree_lock);
                radix_tree_preload_end();
        } else
-               mem_cgroup_uncharge_page(page);
+               mem_cgroup_uncharge_cache_page(page);
 out:
        return error;
 }
-EXPORT_SYMBOL(add_to_page_cache);
+EXPORT_SYMBOL(add_to_page_cache_locked);
 
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
                                pgoff_t offset, gfp_t gfp_mask)
@@ -636,15 +637,35 @@ void __lock_page_nosync(struct page *page)
  * Is there a pagecache struct page at the given (mapping, offset) tuple?
  * If yes, increment its refcount and return it; if no, return NULL.
  */
-struct page * find_get_page(struct address_space *mapping, pgoff_t offset)
+struct page *find_get_page(struct address_space *mapping, pgoff_t offset)
 {
+       void **pagep;
        struct page *page;
 
-       read_lock_irq(&mapping->tree_lock);
-       page = radix_tree_lookup(&mapping->page_tree, offset);
-       if (page)
-               page_cache_get(page);
-       read_unlock_irq(&mapping->tree_lock);
+       rcu_read_lock();
+repeat:
+       page = NULL;
+       pagep = radix_tree_lookup_slot(&mapping->page_tree, offset);
+       if (pagep) {
+               page = radix_tree_deref_slot(pagep);
+               if (unlikely(!page || page == RADIX_TREE_RETRY))
+                       goto repeat;
+
+               if (!page_cache_get_speculative(page))
+                       goto repeat;
+
+               /*
+                * Has the page moved?
+                * This is part of the lockless pagecache protocol. See
+                * include/linux/pagemap.h for details.
+                */
+               if (unlikely(page != *pagep)) {
+                       page_cache_release(page);
+                       goto repeat;
+               }
+       }
+       rcu_read_unlock();
+
        return page;
 }
 EXPORT_SYMBOL(find_get_page);
@@ -659,32 +680,22 @@ EXPORT_SYMBOL(find_get_page);
  *
  * Returns zero if the page was not present. find_lock_page() may sleep.
  */
-struct page *find_lock_page(struct address_space *mapping,
-                               pgoff_t offset)
+struct page *find_lock_page(struct address_space *mapping, pgoff_t offset)
 {
        struct page *page;
 
 repeat:
-       read_lock_irq(&mapping->tree_lock);
-       page = radix_tree_lookup(&mapping->page_tree, offset);
+       page = find_get_page(mapping, offset);
        if (page) {
-               page_cache_get(page);
-               if (TestSetPageLocked(page)) {
-                       read_unlock_irq(&mapping->tree_lock);
-                       __lock_page(page);
-
-                       /* Has the page been truncated while we slept? */
-                       if (unlikely(page->mapping != mapping)) {
-                               unlock_page(page);
-                               page_cache_release(page);
-                               goto repeat;
-                       }
-                       VM_BUG_ON(page->index != offset);
-                       goto out;
+               lock_page(page);
+               /* Has the page been truncated? */
+               if (unlikely(page->mapping != mapping)) {
+                       unlock_page(page);
+                       page_cache_release(page);
+                       goto repeat;
                }
+               VM_BUG_ON(page->index != offset);
        }
-       read_unlock_irq(&mapping->tree_lock);
-out:
        return page;
 }
 EXPORT_SYMBOL(find_lock_page);
@@ -750,13 +761,39 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
 {
        unsigned int i;
        unsigned int ret;
+       unsigned int nr_found;
+
+       rcu_read_lock();
+restart:
+       nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
+                               (void ***)pages, start, nr_pages);
+       ret = 0;
+       for (i = 0; i < nr_found; i++) {
+               struct page *page;
+repeat:
+               page = radix_tree_deref_slot((void **)pages[i]);
+               if (unlikely(!page))
+                       continue;
+               /*
+                * this can only trigger if nr_found == 1, making livelock
+                * a non issue.
+                */
+               if (unlikely(page == RADIX_TREE_RETRY))
+                       goto restart;
 
-       read_lock_irq(&mapping->tree_lock);
-       ret = radix_tree_gang_lookup(&mapping->page_tree,
-                               (void **)pages, start, nr_pages);
-       for (i = 0; i < ret; i++)
-               page_cache_get(pages[i]);
-       read_unlock_irq(&mapping->tree_lock);
+               if (!page_cache_get_speculative(page))
+                       goto repeat;
+
+               /* Has the page moved? */
+               if (unlikely(page != *((void **)pages[i]))) {
+                       page_cache_release(page);
+                       goto repeat;
+               }
+
+               pages[ret] = page;
+               ret++;
+       }
+       rcu_read_unlock();
        return ret;
 }
 
@@ -777,19 +814,44 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
 {
        unsigned int i;
        unsigned int ret;
+       unsigned int nr_found;
+
+       rcu_read_lock();
+restart:
+       nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
+                               (void ***)pages, index, nr_pages);
+       ret = 0;
+       for (i = 0; i < nr_found; i++) {
+               struct page *page;
+repeat:
+               page = radix_tree_deref_slot((void **)pages[i]);
+               if (unlikely(!page))
+                       continue;
+               /*
+                * this can only trigger if nr_found == 1, making livelock
+                * a non issue.
+                */
+               if (unlikely(page == RADIX_TREE_RETRY))
+                       goto restart;
 
-       read_lock_irq(&mapping->tree_lock);
-       ret = radix_tree_gang_lookup(&mapping->page_tree,
-                               (void **)pages, index, nr_pages);
-       for (i = 0; i < ret; i++) {
-               if (pages[i]->mapping == NULL || pages[i]->index != index)
+               if (page->mapping == NULL || page->index != index)
                        break;
 
-               page_cache_get(pages[i]);
+               if (!page_cache_get_speculative(page))
+                       goto repeat;
+
+               /* Has the page moved? */
+               if (unlikely(page != *((void **)pages[i]))) {
+                       page_cache_release(page);
+                       goto repeat;
+               }
+
+               pages[ret] = page;
+               ret++;
                index++;
        }
-       read_unlock_irq(&mapping->tree_lock);
-       return i;
+       rcu_read_unlock();
+       return ret;
 }
 EXPORT_SYMBOL(find_get_pages_contig);
 
@@ -809,15 +871,43 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
 {
        unsigned int i;
        unsigned int ret;
+       unsigned int nr_found;
+
+       rcu_read_lock();
+restart:
+       nr_found = radix_tree_gang_lookup_tag_slot(&mapping->page_tree,
+                               (void ***)pages, *index, nr_pages, tag);
+       ret = 0;
+       for (i = 0; i < nr_found; i++) {
+               struct page *page;
+repeat:
+               page = radix_tree_deref_slot((void **)pages[i]);
+               if (unlikely(!page))
+                       continue;
+               /*
+                * this can only trigger if nr_found == 1, making livelock
+                * a non issue.
+                */
+               if (unlikely(page == RADIX_TREE_RETRY))
+                       goto restart;
+
+               if (!page_cache_get_speculative(page))
+                       goto repeat;
+
+               /* Has the page moved? */
+               if (unlikely(page != *((void **)pages[i]))) {
+                       page_cache_release(page);
+                       goto repeat;
+               }
+
+               pages[ret] = page;
+               ret++;
+       }
+       rcu_read_unlock();
 
-       read_lock_irq(&mapping->tree_lock);
-       ret = radix_tree_gang_lookup_tag(&mapping->page_tree,
-                               (void **)pages, *index, nr_pages, tag);
-       for (i = 0; i < ret; i++)
-               page_cache_get(pages[i]);
        if (ret)
                *index = pages[ret - 1]->index + 1;
-       read_unlock_irq(&mapping->tree_lock);
+
        return ret;
 }
 EXPORT_SYMBOL(find_get_pages_tag);
@@ -933,8 +1023,17 @@ find_page:
                                        ra, filp, page,
                                        index, last_index - index);
                }
-               if (!PageUptodate(page))
-                       goto page_not_up_to_date;
+               if (!PageUptodate(page)) {
+                       if (inode->i_blkbits == PAGE_CACHE_SHIFT ||
+                                       !mapping->a_ops->is_partially_uptodate)
+                               goto page_not_up_to_date;
+                       if (TestSetPageLocked(page))
+                               goto page_not_up_to_date;
+                       if (!mapping->a_ops->is_partially_uptodate(page,
+                                                               desc, offset))
+                               goto page_not_up_to_date_locked;
+                       unlock_page(page);
+               }
 page_ok:
                /*
                 * i_size must be checked after we know the page is Uptodate.
@@ -1004,6 +1103,7 @@ page_not_up_to_date:
                if (lock_page_killable(page))
                        goto readpage_eio;
 
+page_not_up_to_date_locked:
                /* Did it get truncated before we got the lock? */
                if (!page->mapping) {
                        unlock_page(page);
@@ -1200,42 +1300,41 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
 
                mapping = filp->f_mapping;
                inode = mapping->host;
-               retval = 0;
                if (!count)
                        goto out; /* skip atime */
                size = i_size_read(inode);
                if (pos < size) {
-                       retval = generic_file_direct_IO(READ, iocb,
-                                               iov, pos, nr_segs);
+                       retval = filemap_write_and_wait(mapping);
+                       if (!retval) {
+                               retval = mapping->a_ops->direct_IO(READ, iocb,
+                                                       iov, pos, nr_segs);
+                       }
                        if (retval > 0)
                                *ppos = pos + retval;
-               }
-               if (likely(retval != 0)) {
-                       file_accessed(filp);
-                       goto out;
+                       if (retval) {
+                               file_accessed(filp);
+                               goto out;
+                       }
                }
        }
 
-       retval = 0;
-       if (count) {
-               for (seg = 0; seg < nr_segs; seg++) {
-                       read_descriptor_t desc;
+       for (seg = 0; seg < nr_segs; seg++) {
+               read_descriptor_t desc;
 
-                       desc.written = 0;
-                       desc.arg.buf = iov[seg].iov_base;
-                       desc.count = iov[seg].iov_len;
-                       if (desc.count == 0)
-                               continue;
-                       desc.error = 0;
-                       do_generic_file_read(filp,ppos,&desc,file_read_actor);
-                       retval += desc.written;
-                       if (desc.error) {
-                               retval = retval ?: desc.error;
-                               break;
-                       }
-                       if (desc.count > 0)
-                               break;
+               desc.written = 0;
+               desc.arg.buf = iov[seg].iov_base;
+               desc.count = iov[seg].iov_len;
+               if (desc.count == 0)
+                       continue;
+               desc.error = 0;
+               do_generic_file_read(filp, ppos, &desc, file_read_actor);
+               retval += desc.written;
+               if (desc.error) {
+                       retval = retval ?: desc.error;
+                       break;
                }
+               if (desc.count > 0)
+                       break;
        }
 out:
        return retval;
@@ -1669,8 +1768,9 @@ static int __remove_suid(struct dentry *dentry, int kill)
        return notify_change(dentry, &newattrs);
 }
 
-int remove_suid(struct dentry *dentry)
+int file_remove_suid(struct file *file)
 {
+       struct dentry *dentry = file->f_path.dentry;
        int killsuid = should_remove_suid(dentry);
        int killpriv = security_inode_need_killpriv(dentry);
        int error = 0;
@@ -1684,7 +1784,7 @@ int remove_suid(struct dentry *dentry)
 
        return error;
 }
-EXPORT_SYMBOL(remove_suid);
+EXPORT_SYMBOL(file_remove_suid);
 
 static size_t __iovec_copy_from_user_inatomic(char *vaddr,
                        const struct iovec *iov, size_t base, size_t bytes)
@@ -2004,11 +2104,55 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
        struct address_space *mapping = file->f_mapping;
        struct inode    *inode = mapping->host;
        ssize_t         written;
+       size_t          write_len;
+       pgoff_t         end;
 
        if (count != ocount)
                *nr_segs = iov_shorten((struct iovec *)iov, *nr_segs, count);
 
-       written = generic_file_direct_IO(WRITE, iocb, iov, pos, *nr_segs);
+       /*
+        * Unmap all mmappings of the file up-front.
+        *
+        * This will cause any pte dirty bits to be propagated into the
+        * pageframes for the subsequent filemap_write_and_wait().
+        */
+       write_len = iov_length(iov, *nr_segs);
+       end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT;
+       if (mapping_mapped(mapping))
+               unmap_mapping_range(mapping, pos, write_len, 0);
+
+       written = filemap_write_and_wait(mapping);
+       if (written)
+               goto out;
+
+       /*
+        * After a write we want buffered reads to be sure to go to disk to get
+        * the new data.  We invalidate clean cached page from the region we're
+        * about to write.  We do this *before* the write so that we can return
+        * -EIO without clobbering -EIOCBQUEUED from ->direct_IO().
+        */
+       if (mapping->nrpages) {
+               written = invalidate_inode_pages2_range(mapping,
+                                       pos >> PAGE_CACHE_SHIFT, end);
+               if (written)
+                       goto out;
+       }
+
+       written = mapping->a_ops->direct_IO(WRITE, iocb, iov, pos, *nr_segs);
+
+       /*
+        * Finally, try again to invalidate clean pages which might have been
+        * cached by non-direct readahead, or faulted in by get_user_pages()
+        * if the source of the write was an mmap'ed region of the file
+        * we're writing.  Either one is a pretty crazy thing to do,
+        * so we don't support it 100%.  If this invalidation
+        * fails, tough, the write still worked...
+        */
+       if (mapping->nrpages) {
+               invalidate_inode_pages2_range(mapping,
+                                             pos >> PAGE_CACHE_SHIFT, end);
+       }
+
        if (written > 0) {
                loff_t end = pos + written;
                if (end > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
@@ -2024,6 +2168,7 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
         * i_mutex is held, which protects generic_osync_inode() from
         * livelocking.  AIO O_DIRECT ops attempt to sync metadata here.
         */
+out:
        if ((written >= 0 || written == -EIOCBQUEUED) &&
            ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
                int err = generic_osync_inode(inode, mapping, OSYNC_METADATA);
@@ -2395,7 +2540,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
        if (count == 0)
                goto out;
 
-       err = remove_suid(file->f_path.dentry);
+       err = file_remove_suid(file);
        if (err)
                goto out;
 
@@ -2511,66 +2656,6 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 }
 EXPORT_SYMBOL(generic_file_aio_write);
 
-/*
- * Called under i_mutex for writes to S_ISREG files.   Returns -EIO if something
- * went wrong during pagecache shootdown.
- */
-static ssize_t
-generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
-       loff_t offset, unsigned long nr_segs)
-{
-       struct file *file = iocb->ki_filp;
-       struct address_space *mapping = file->f_mapping;
-       ssize_t retval;
-       size_t write_len;
-       pgoff_t end = 0; /* silence gcc */
-
-       /*
-        * If it's a write, unmap all mmappings of the file up-front.  This
-        * will cause any pte dirty bits to be propagated into the pageframes
-        * for the subsequent filemap_write_and_wait().
-        */
-       if (rw == WRITE) {
-               write_len = iov_length(iov, nr_segs);
-               end = (offset + write_len - 1) >> PAGE_CACHE_SHIFT;
-               if (mapping_mapped(mapping))
-                       unmap_mapping_range(mapping, offset, write_len, 0);
-       }
-
-       retval = filemap_write_and_wait(mapping);
-       if (retval)
-               goto out;
-
-       /*
-        * After a write we want buffered reads to be sure to go to disk to get
-        * the new data.  We invalidate clean cached page from the region we're
-        * about to write.  We do this *before* the write so that we can return
-        * -EIO without clobbering -EIOCBQUEUED from ->direct_IO().
-        */
-       if (rw == WRITE && mapping->nrpages) {
-               retval = invalidate_inode_pages2_range(mapping,
-                                       offset >> PAGE_CACHE_SHIFT, end);
-               if (retval)
-                       goto out;
-       }
-
-       retval = mapping->a_ops->direct_IO(rw, iocb, iov, offset, nr_segs);
-
-       /*
-        * Finally, try again to invalidate clean pages which might have been
-        * cached by non-direct readahead, or faulted in by get_user_pages()
-        * if the source of the write was an mmap'ed region of the file
-        * we're writing.  Either one is a pretty crazy thing to do,
-        * so we don't support it 100%.  If this invalidation
-        * fails, tough, the write still worked...
-        */
-       if (rw == WRITE && mapping->nrpages) {
-               invalidate_inode_pages2_range(mapping, offset >> PAGE_CACHE_SHIFT, end);
-       }
-out:
-       return retval;
-}
-
 /**
  * try_to_release_page() - release old fs-specific metadata on a page
  *
@@ -2582,9 +2667,8 @@ out:
  * 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).
+ * this page (__GFP_IO), and whether the call may block (__GFP_WAIT & __GFP_FS).
  *
- * 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)
 {
index 3e744abcce9daa8aada1487bd42e31b769c414bf..380ab402d71160a05d82a00598e5e35efeb5f116 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/uio.h>
 #include <linux/rmap.h>
+#include <linux/mmu_notifier.h>
 #include <linux/sched.h>
 #include <asm/tlbflush.h>
 #include <asm/io.h>
@@ -188,7 +189,7 @@ __xip_unmap (struct address_space * mapping,
                if (pte) {
                        /* Nuke the page table entry. */
                        flush_cache_page(vma, address, pte_pfn(*pte));
-                       pteval = ptep_clear_flush(vma, address, pte);
+                       pteval = ptep_clear_flush_notify(vma, address, pte);
                        page_remove_rmap(page, vma);
                        dec_mm_counter(mm, file_rss);
                        BUG_ON(pte_dirty(pteval));
@@ -380,7 +381,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,
        if (count == 0)
                goto out_backing;
 
-       ret = remove_suid(filp->f_path.dentry);
+       ret = file_remove_suid(filp);
        if (ret)
                goto out_backing;
 
index 07a9c82ce1a3fa0e24da2f2da23e9416e3f1819c..7881638e4a12bd8c5489c8d08b5779b5ae5a0080 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/rmap.h>
 #include <linux/module.h>
 #include <linux/syscalls.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
@@ -214,7 +215,9 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
                spin_unlock(&mapping->i_mmap_lock);
        }
 
+       mmu_notifier_invalidate_range_start(mm, start, start + size);
        err = populate_range(mm, vma, start, size, pgoff);
+       mmu_notifier_invalidate_range_end(mm, start, start + size);
        if (!err && !(flags & MAP_NONBLOCK)) {
                if (unlikely(has_write_lock)) {
                        downgrade_write(&mm->mmap_sem);
index ab171274ef217817291667bee226b45bebe259e3..254ce2b901588f48a06f61da5692aa82b93ee0cd 100644 (file)
 #include <linux/mm.h>
 #include <linux/sysctl.h>
 #include <linux/highmem.h>
+#include <linux/mmu_notifier.h>
 #include <linux/nodemask.h>
 #include <linux/pagemap.h>
 #include <linux/mempolicy.h>
 #include <linux/cpuset.h>
 #include <linux/mutex.h>
+#include <linux/bootmem.h>
+#include <linux/sysfs.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/io.h>
 
 #include <linux/hugetlb.h>
 #include "internal.h"
 
 const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL;
-static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages;
-static unsigned long surplus_huge_pages;
-static unsigned long nr_overcommit_huge_pages;
-unsigned long max_huge_pages;
-unsigned long sysctl_overcommit_huge_pages;
-static struct list_head hugepage_freelists[MAX_NUMNODES];
-static unsigned int nr_huge_pages_node[MAX_NUMNODES];
-static unsigned int free_huge_pages_node[MAX_NUMNODES];
-static unsigned int surplus_huge_pages_node[MAX_NUMNODES];
 static gfp_t htlb_alloc_mask = GFP_HIGHUSER;
 unsigned long hugepages_treat_as_movable;
-static int hugetlb_next_nid;
+
+static int max_hstate;
+unsigned int default_hstate_idx;
+struct hstate hstates[HUGE_MAX_HSTATE];
+
+__initdata LIST_HEAD(huge_boot_pages);
+
+/* for command line parsing */
+static struct hstate * __initdata parsed_hstate;
+static unsigned long __initdata default_hstate_max_huge_pages;
+static unsigned long __initdata default_hstate_size;
+
+#define for_each_hstate(h) \
+       for ((h) = hstates; (h) < &hstates[max_hstate]; (h)++)
 
 /*
  * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
  */
 static DEFINE_SPINLOCK(hugetlb_lock);
 
-static void clear_huge_page(struct page *page, unsigned long addr)
+/*
+ * Region tracking -- allows tracking of reservations and instantiated pages
+ *                    across the pages in a mapping.
+ *
+ * The region data structures are protected by a combination of the mmap_sem
+ * and the hugetlb_instantion_mutex.  To access or modify a region the caller
+ * must either hold the mmap_sem for write, or the mmap_sem for read and
+ * the hugetlb_instantiation mutex:
+ *
+ *     down_write(&mm->mmap_sem);
+ * or
+ *     down_read(&mm->mmap_sem);
+ *     mutex_lock(&hugetlb_instantiation_mutex);
+ */
+struct file_region {
+       struct list_head link;
+       long from;
+       long to;
+};
+
+static long region_add(struct list_head *head, long f, long t)
+{
+       struct file_region *rg, *nrg, *trg;
+
+       /* Locate the region we are either in or before. */
+       list_for_each_entry(rg, head, link)
+               if (f <= rg->to)
+                       break;
+
+       /* Round our left edge to the current segment if it encloses us. */
+       if (f > rg->from)
+               f = rg->from;
+
+       /* Check for and consume any regions we now overlap with. */
+       nrg = rg;
+       list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
+               if (&rg->link == head)
+                       break;
+               if (rg->from > t)
+                       break;
+
+               /* If this area reaches higher then extend our area to
+                * include it completely.  If this is not the first area
+                * which we intend to reuse, free it. */
+               if (rg->to > t)
+                       t = rg->to;
+               if (rg != nrg) {
+                       list_del(&rg->link);
+                       kfree(rg);
+               }
+       }
+       nrg->from = f;
+       nrg->to = t;
+       return 0;
+}
+
+static long region_chg(struct list_head *head, long f, long t)
+{
+       struct file_region *rg, *nrg;
+       long chg = 0;
+
+       /* Locate the region we are before or in. */
+       list_for_each_entry(rg, head, link)
+               if (f <= rg->to)
+                       break;
+
+       /* If we are below the current region then a new region is required.
+        * Subtle, allocate a new region at the position but make it zero
+        * size such that we can guarantee to record the reservation. */
+       if (&rg->link == head || t < rg->from) {
+               nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
+               if (!nrg)
+                       return -ENOMEM;
+               nrg->from = f;
+               nrg->to   = f;
+               INIT_LIST_HEAD(&nrg->link);
+               list_add(&nrg->link, rg->link.prev);
+
+               return t - f;
+       }
+
+       /* Round our left edge to the current segment if it encloses us. */
+       if (f > rg->from)
+               f = rg->from;
+       chg = t - f;
+
+       /* Check for and consume any regions we now overlap with. */
+       list_for_each_entry(rg, rg->link.prev, link) {
+               if (&rg->link == head)
+                       break;
+               if (rg->from > t)
+                       return chg;
+
+               /* We overlap with this area, if it extends futher than
+                * us then we must extend ourselves.  Account for its
+                * existing reservation. */
+               if (rg->to > t) {
+                       chg += rg->to - t;
+                       t = rg->to;
+               }
+               chg -= rg->to - rg->from;
+       }
+       return chg;
+}
+
+static long region_truncate(struct list_head *head, long end)
+{
+       struct file_region *rg, *trg;
+       long chg = 0;
+
+       /* Locate the region we are either in or before. */
+       list_for_each_entry(rg, head, link)
+               if (end <= rg->to)
+                       break;
+       if (&rg->link == head)
+               return 0;
+
+       /* If we are in the middle of a region then adjust it. */
+       if (end > rg->from) {
+               chg = rg->to - end;
+               rg->to = end;
+               rg = list_entry(rg->link.next, typeof(*rg), link);
+       }
+
+       /* Drop any remaining regions. */
+       list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
+               if (&rg->link == head)
+                       break;
+               chg += rg->to - rg->from;
+               list_del(&rg->link);
+               kfree(rg);
+       }
+       return chg;
+}
+
+static long region_count(struct list_head *head, long f, long t)
+{
+       struct file_region *rg;
+       long chg = 0;
+
+       /* Locate each segment we overlap with, and count that overlap. */
+       list_for_each_entry(rg, head, link) {
+               int seg_from;
+               int seg_to;
+
+               if (rg->to <= f)
+                       continue;
+               if (rg->from >= t)
+                       break;
+
+               seg_from = max(rg->from, f);
+               seg_to = min(rg->to, t);
+
+               chg += seg_to - seg_from;
+       }
+
+       return chg;
+}
+
+/*
+ * Convert the address within this vma to the page offset within
+ * the mapping, in pagecache page units; huge pages here.
+ */
+static pgoff_t vma_hugecache_offset(struct hstate *h,
+                       struct vm_area_struct *vma, unsigned long address)
+{
+       return ((address - vma->vm_start) >> huge_page_shift(h)) +
+                       (vma->vm_pgoff >> huge_page_order(h));
+}
+
+/*
+ * Flags for MAP_PRIVATE reservations.  These are stored in the bottom
+ * bits of the reservation map pointer, which are always clear due to
+ * alignment.
+ */
+#define HPAGE_RESV_OWNER    (1UL << 0)
+#define HPAGE_RESV_UNMAPPED (1UL << 1)
+#define HPAGE_RESV_MASK (HPAGE_RESV_OWNER | HPAGE_RESV_UNMAPPED)
+
+/*
+ * These helpers are used to track how many pages are reserved for
+ * faults in a MAP_PRIVATE mapping. Only the process that called mmap()
+ * is guaranteed to have their future faults succeed.
+ *
+ * With the exception of reset_vma_resv_huge_pages() which is called at fork(),
+ * the reserve counters are updated with the hugetlb_lock held. It is safe
+ * to reset the VMA at fork() time as it is not in use yet and there is no
+ * chance of the global counters getting corrupted as a result of the values.
+ *
+ * The private mapping reservation is represented in a subtly different
+ * manner to a shared mapping.  A shared mapping has a region map associated
+ * with the underlying file, this region map represents the backing file
+ * pages which have ever had a reservation assigned which this persists even
+ * after the page is instantiated.  A private mapping has a region map
+ * associated with the original mmap which is attached to all VMAs which
+ * reference it, this region map represents those offsets which have consumed
+ * reservation ie. where pages have been instantiated.
+ */
+static unsigned long get_vma_private_data(struct vm_area_struct *vma)
+{
+       return (unsigned long)vma->vm_private_data;
+}
+
+static void set_vma_private_data(struct vm_area_struct *vma,
+                                                       unsigned long value)
+{
+       vma->vm_private_data = (void *)value;
+}
+
+struct resv_map {
+       struct kref refs;
+       struct list_head regions;
+};
+
+struct resv_map *resv_map_alloc(void)
+{
+       struct resv_map *resv_map = kmalloc(sizeof(*resv_map), GFP_KERNEL);
+       if (!resv_map)
+               return NULL;
+
+       kref_init(&resv_map->refs);
+       INIT_LIST_HEAD(&resv_map->regions);
+
+       return resv_map;
+}
+
+void resv_map_release(struct kref *ref)
+{
+       struct resv_map *resv_map = container_of(ref, struct resv_map, refs);
+
+       /* Clear out any active regions before we release the map. */
+       region_truncate(&resv_map->regions, 0);
+       kfree(resv_map);
+}
+
+static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
+{
+       VM_BUG_ON(!is_vm_hugetlb_page(vma));
+       if (!(vma->vm_flags & VM_SHARED))
+               return (struct resv_map *)(get_vma_private_data(vma) &
+                                                       ~HPAGE_RESV_MASK);
+       return 0;
+}
+
+static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map)
+{
+       VM_BUG_ON(!is_vm_hugetlb_page(vma));
+       VM_BUG_ON(vma->vm_flags & VM_SHARED);
+
+       set_vma_private_data(vma, (get_vma_private_data(vma) &
+                               HPAGE_RESV_MASK) | (unsigned long)map);
+}
+
+static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags)
+{
+       VM_BUG_ON(!is_vm_hugetlb_page(vma));
+       VM_BUG_ON(vma->vm_flags & VM_SHARED);
+
+       set_vma_private_data(vma, get_vma_private_data(vma) | flags);
+}
+
+static int is_vma_resv_set(struct vm_area_struct *vma, unsigned long flag)
+{
+       VM_BUG_ON(!is_vm_hugetlb_page(vma));
+
+       return (get_vma_private_data(vma) & flag) != 0;
+}
+
+/* Decrement the reserved pages in the hugepage pool by one */
+static void decrement_hugepage_resv_vma(struct hstate *h,
+                       struct vm_area_struct *vma)
+{
+       if (vma->vm_flags & VM_NORESERVE)
+               return;
+
+       if (vma->vm_flags & VM_SHARED) {
+               /* Shared mappings always use reserves */
+               h->resv_huge_pages--;
+       } else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
+               /*
+                * Only the process that called mmap() has reserves for
+                * private mappings.
+                */
+               h->resv_huge_pages--;
+       }
+}
+
+/* Reset counters to 0 and clear all HPAGE_RESV_* flags */
+void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
+{
+       VM_BUG_ON(!is_vm_hugetlb_page(vma));
+       if (!(vma->vm_flags & VM_SHARED))
+               vma->vm_private_data = (void *)0;
+}
+
+/* Returns true if the VMA has associated reserve pages */
+static int vma_has_reserves(struct vm_area_struct *vma)
+{
+       if (vma->vm_flags & VM_SHARED)
+               return 1;
+       if (is_vma_resv_set(vma, HPAGE_RESV_OWNER))
+               return 1;
+       return 0;
+}
+
+static void clear_huge_page(struct page *page,
+                       unsigned long addr, unsigned long sz)
 {
        int i;
 
        might_sleep();
-       for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); i++) {
+       for (i = 0; i < sz/PAGE_SIZE; i++) {
                cond_resched();
                clear_user_highpage(page + i, addr + i * PAGE_SIZE);
        }
@@ -55,42 +369,44 @@ static void copy_huge_page(struct page *dst, struct page *src,
                           unsigned long addr, struct vm_area_struct *vma)
 {
        int i;
+       struct hstate *h = hstate_vma(vma);
 
        might_sleep();
-       for (i = 0; i < HPAGE_SIZE/PAGE_SIZE; i++) {
+       for (i = 0; i < pages_per_huge_page(h); i++) {
                cond_resched();
                copy_user_highpage(dst + i, src + i, addr + i*PAGE_SIZE, vma);
        }
 }
 
-static void enqueue_huge_page(struct page *page)
+static void enqueue_huge_page(struct hstate *h, struct page *page)
 {
        int nid = page_to_nid(page);
-       list_add(&page->lru, &hugepage_freelists[nid]);
-       free_huge_pages++;
-       free_huge_pages_node[nid]++;
+       list_add(&page->lru, &h->hugepage_freelists[nid]);
+       h->free_huge_pages++;
+       h->free_huge_pages_node[nid]++;
 }
 
-static struct page *dequeue_huge_page(void)
+static struct page *dequeue_huge_page(struct hstate *h)
 {
        int nid;
        struct page *page = NULL;
 
        for (nid = 0; nid < MAX_NUMNODES; ++nid) {
-               if (!list_empty(&hugepage_freelists[nid])) {
-                       page = list_entry(hugepage_freelists[nid].next,
+               if (!list_empty(&h->hugepage_freelists[nid])) {
+                       page = list_entry(h->hugepage_freelists[nid].next,
                                          struct page, lru);
                        list_del(&page->lru);
-                       free_huge_pages--;
-                       free_huge_pages_node[nid]--;
+                       h->free_huge_pages--;
+                       h->free_huge_pages_node[nid]--;
                        break;
                }
        }
        return page;
 }
 
-static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma,
-                               unsigned long address)
+static struct page *dequeue_huge_page_vma(struct hstate *h,
+                               struct vm_area_struct *vma,
+                               unsigned long address, int avoid_reserve)
 {
        int nid;
        struct page *page = NULL;
@@ -101,18 +417,33 @@ static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma,
        struct zone *zone;
        struct zoneref *z;
 
+       /*
+        * A child process with MAP_PRIVATE mappings created by their parent
+        * have no page reserves. This check ensures that reservations are
+        * not "stolen". The child may still get SIGKILLed
+        */
+       if (!vma_has_reserves(vma) &&
+                       h->free_huge_pages - h->resv_huge_pages == 0)
+               return NULL;
+
+       /* If reserves cannot be used, ensure enough pages are in the pool */
+       if (avoid_reserve && h->free_huge_pages - h->resv_huge_pages == 0)
+               return NULL;
+
        for_each_zone_zonelist_nodemask(zone, z, zonelist,
                                                MAX_NR_ZONES - 1, nodemask) {
                nid = zone_to_nid(zone);
                if (cpuset_zone_allowed_softwall(zone, htlb_alloc_mask) &&
-                   !list_empty(&hugepage_freelists[nid])) {
-                       page = list_entry(hugepage_freelists[nid].next,
+                   !list_empty(&h->hugepage_freelists[nid])) {
+                       page = list_entry(h->hugepage_freelists[nid].next,
                                          struct page, lru);
                        list_del(&page->lru);
-                       free_huge_pages--;
-                       free_huge_pages_node[nid]--;
-                       if (vma && vma->vm_flags & VM_MAYSHARE)
-                               resv_huge_pages--;
+                       h->free_huge_pages--;
+                       h->free_huge_pages_node[nid]--;
+
+                       if (!avoid_reserve)
+                               decrement_hugepage_resv_vma(h, vma);
+
                        break;
                }
        }
@@ -120,12 +451,13 @@ static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma,
        return page;
 }
 
-static void update_and_free_page(struct page *page)
+static void update_and_free_page(struct hstate *h, struct page *page)
 {
        int i;
-       nr_huge_pages--;
-       nr_huge_pages_node[page_to_nid(page)]--;
-       for (i = 0; i < (HPAGE_SIZE / PAGE_SIZE); i++) {
+
+       h->nr_huge_pages--;
+       h->nr_huge_pages_node[page_to_nid(page)]--;
+       for (i = 0; i < pages_per_huge_page(h); i++) {
                page[i].flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced |
                                1 << PG_dirty | 1 << PG_active | 1 << PG_reserved |
                                1 << PG_private | 1<< PG_writeback);
@@ -133,11 +465,27 @@ static void update_and_free_page(struct page *page)
        set_compound_page_dtor(page, NULL);
        set_page_refcounted(page);
        arch_release_hugepage(page);
-       __free_pages(page, HUGETLB_PAGE_ORDER);
+       __free_pages(page, huge_page_order(h));
+}
+
+struct hstate *size_to_hstate(unsigned long size)
+{
+       struct hstate *h;
+
+       for_each_hstate(h) {
+               if (huge_page_size(h) == size)
+                       return h;
+       }
+       return NULL;
 }
 
 static void free_huge_page(struct page *page)
 {
+       /*
+        * Can't pass hstate in here because it is called from the
+        * compound page destructor.
+        */
+       struct hstate *h = page_hstate(page);
        int nid = page_to_nid(page);
        struct address_space *mapping;
 
@@ -147,12 +495,12 @@ static void free_huge_page(struct page *page)
        INIT_LIST_HEAD(&page->lru);
 
        spin_lock(&hugetlb_lock);
-       if (surplus_huge_pages_node[nid]) {
-               update_and_free_page(page);
-               surplus_huge_pages--;
-               surplus_huge_pages_node[nid]--;
+       if (h->surplus_huge_pages_node[nid] && huge_page_order(h) < MAX_ORDER) {
+               update_and_free_page(h, page);
+               h->surplus_huge_pages--;
+               h->surplus_huge_pages_node[nid]--;
        } else {
-               enqueue_huge_page(page);
+               enqueue_huge_page(h, page);
        }
        spin_unlock(&hugetlb_lock);
        if (mapping)
@@ -164,7 +512,7 @@ static void free_huge_page(struct page *page)
  * balanced by operating on them in a round-robin fashion.
  * Returns 1 if an adjustment was made.
  */
-static int adjust_pool_surplus(int delta)
+static int adjust_pool_surplus(struct hstate *h, int delta)
 {
        static int prev_nid;
        int nid = prev_nid;
@@ -177,15 +525,15 @@ static int adjust_pool_surplus(int delta)
                        nid = first_node(node_online_map);
 
                /* To shrink on this node, there must be a surplus page */
-               if (delta < 0 && !surplus_huge_pages_node[nid])
+               if (delta < 0 && !h->surplus_huge_pages_node[nid])
                        continue;
                /* Surplus cannot exceed the total number of pages */
-               if (delta > 0 && surplus_huge_pages_node[nid] >=
-                                               nr_huge_pages_node[nid])
+               if (delta > 0 && h->surplus_huge_pages_node[nid] >=
+                                               h->nr_huge_pages_node[nid])
                        continue;
 
-               surplus_huge_pages += delta;
-               surplus_huge_pages_node[nid] += delta;
+               h->surplus_huge_pages += delta;
+               h->surplus_huge_pages_node[nid] += delta;
                ret = 1;
                break;
        } while (nid != prev_nid);
@@ -194,59 +542,74 @@ static int adjust_pool_surplus(int delta)
        return ret;
 }
 
-static struct page *alloc_fresh_huge_page_node(int nid)
+static void prep_new_huge_page(struct hstate *h, struct page *page, int nid)
+{
+       set_compound_page_dtor(page, free_huge_page);
+       spin_lock(&hugetlb_lock);
+       h->nr_huge_pages++;
+       h->nr_huge_pages_node[nid]++;
+       spin_unlock(&hugetlb_lock);
+       put_page(page); /* free it into the hugepage allocator */
+}
+
+static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid)
 {
        struct page *page;
 
+       if (h->order >= MAX_ORDER)
+               return NULL;
+
        page = alloc_pages_node(nid,
                htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|
                                                __GFP_REPEAT|__GFP_NOWARN,
-               HUGETLB_PAGE_ORDER);
+               huge_page_order(h));
        if (page) {
                if (arch_prepare_hugepage(page)) {
                        __free_pages(page, HUGETLB_PAGE_ORDER);
                        return NULL;
                }
-               set_compound_page_dtor(page, free_huge_page);
-               spin_lock(&hugetlb_lock);
-               nr_huge_pages++;
-               nr_huge_pages_node[nid]++;
-               spin_unlock(&hugetlb_lock);
-               put_page(page); /* free it into the hugepage allocator */
+               prep_new_huge_page(h, page, nid);
        }
 
        return page;
 }
 
-static int alloc_fresh_huge_page(void)
+/*
+ * Use a helper variable to find the next node and then
+ * copy it back to hugetlb_next_nid afterwards:
+ * otherwise there's a window in which a racer might
+ * pass invalid nid MAX_NUMNODES to alloc_pages_node.
+ * But we don't need to use a spin_lock here: it really
+ * doesn't matter if occasionally a racer chooses the
+ * same nid as we do.  Move nid forward in the mask even
+ * if we just successfully allocated a hugepage so that
+ * the next caller gets hugepages on the next node.
+ */
+static int hstate_next_node(struct hstate *h)
+{
+       int next_nid;
+       next_nid = next_node(h->hugetlb_next_nid, node_online_map);
+       if (next_nid == MAX_NUMNODES)
+               next_nid = first_node(node_online_map);
+       h->hugetlb_next_nid = next_nid;
+       return next_nid;
+}
+
+static int alloc_fresh_huge_page(struct hstate *h)
 {
        struct page *page;
        int start_nid;
        int next_nid;
        int ret = 0;
 
-       start_nid = hugetlb_next_nid;
+       start_nid = h->hugetlb_next_nid;
 
        do {
-               page = alloc_fresh_huge_page_node(hugetlb_next_nid);
+               page = alloc_fresh_huge_page_node(h, h->hugetlb_next_nid);
                if (page)
                        ret = 1;
-               /*
-                * Use a helper variable to find the next node and then
-                * copy it back to hugetlb_next_nid afterwards:
-                * otherwise there's a window in which a racer might
-                * pass invalid nid MAX_NUMNODES to alloc_pages_node.
-                * But we don't need to use a spin_lock here: it really
-                * doesn't matter if occasionally a racer chooses the
-                * same nid as we do.  Move nid forward in the mask even
-                * if we just successfully allocated a hugepage so that
-                * the next caller gets hugepages on the next node.
-                */
-               next_nid = next_node(hugetlb_next_nid, node_online_map);
-               if (next_nid == MAX_NUMNODES)
-                       next_nid = first_node(node_online_map);
-               hugetlb_next_nid = next_nid;
-       } while (!page && hugetlb_next_nid != start_nid);
+               next_nid = hstate_next_node(h);
+       } while (!page && h->hugetlb_next_nid != start_nid);
 
        if (ret)
                count_vm_event(HTLB_BUDDY_PGALLOC);
@@ -256,12 +619,15 @@ static int alloc_fresh_huge_page(void)
        return ret;
 }
 
-static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
-                                               unsigned long address)
+static struct page *alloc_buddy_huge_page(struct hstate *h,
+                       struct vm_area_struct *vma, unsigned long address)
 {
        struct page *page;
        unsigned int nid;
 
+       if (h->order >= MAX_ORDER)
+               return NULL;
+
        /*
         * Assume we will successfully allocate the surplus page to
         * prevent racing processes from causing the surplus to exceed
@@ -286,18 +652,18 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
         * per-node value is checked there.
         */
        spin_lock(&hugetlb_lock);
-       if (surplus_huge_pages >= nr_overcommit_huge_pages) {
+       if (h->surplus_huge_pages >= h->nr_overcommit_huge_pages) {
                spin_unlock(&hugetlb_lock);
                return NULL;
        } else {
-               nr_huge_pages++;
-               surplus_huge_pages++;
+               h->nr_huge_pages++;
+               h->surplus_huge_pages++;
        }
        spin_unlock(&hugetlb_lock);
 
        page = alloc_pages(htlb_alloc_mask|__GFP_COMP|
                                        __GFP_REPEAT|__GFP_NOWARN,
-                                       HUGETLB_PAGE_ORDER);
+                                       huge_page_order(h));
 
        spin_lock(&hugetlb_lock);
        if (page) {
@@ -312,12 +678,12 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
                /*
                 * We incremented the global counters already
                 */
-               nr_huge_pages_node[nid]++;
-               surplus_huge_pages_node[nid]++;
+               h->nr_huge_pages_node[nid]++;
+               h->surplus_huge_pages_node[nid]++;
                __count_vm_event(HTLB_BUDDY_PGALLOC);
        } else {
-               nr_huge_pages--;
-               surplus_huge_pages--;
+               h->nr_huge_pages--;
+               h->surplus_huge_pages--;
                __count_vm_event(HTLB_BUDDY_PGALLOC_FAIL);
        }
        spin_unlock(&hugetlb_lock);
@@ -329,16 +695,16 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
  * Increase the hugetlb pool such that it can accomodate a reservation
  * of size 'delta'.
  */
-static int gather_surplus_pages(int delta)
+static int gather_surplus_pages(struct hstate *h, int delta)
 {
        struct list_head surplus_list;
        struct page *page, *tmp;
        int ret, i;
        int needed, allocated;
 
-       needed = (resv_huge_pages + delta) - free_huge_pages;
+       needed = (h->resv_huge_pages + delta) - h->free_huge_pages;
        if (needed <= 0) {
-               resv_huge_pages += delta;
+               h->resv_huge_pages += delta;
                return 0;
        }
 
@@ -349,7 +715,7 @@ static int gather_surplus_pages(int delta)
 retry:
        spin_unlock(&hugetlb_lock);
        for (i = 0; i < needed; i++) {
-               page = alloc_buddy_huge_page(NULL, 0);
+               page = alloc_buddy_huge_page(h, NULL, 0);
                if (!page) {
                        /*
                         * We were not able to allocate enough pages to
@@ -370,7 +736,8 @@ retry:
         * because either resv_huge_pages or free_huge_pages may have changed.
         */
        spin_lock(&hugetlb_lock);
-       needed = (resv_huge_pages + delta) - (free_huge_pages + allocated);
+       needed = (h->resv_huge_pages + delta) -
+                       (h->free_huge_pages + allocated);
        if (needed > 0)
                goto retry;
 
@@ -383,7 +750,7 @@ retry:
         * before they are reserved.
         */
        needed += allocated;
-       resv_huge_pages += delta;
+       h->resv_huge_pages += delta;
        ret = 0;
 free:
        /* Free the needed pages to the hugetlb pool */
@@ -391,7 +758,7 @@ free:
                if ((--needed) < 0)
                        break;
                list_del(&page->lru);
-               enqueue_huge_page(page);
+               enqueue_huge_page(h, page);
        }
 
        /* Free unnecessary surplus pages to the buddy allocator */
@@ -419,7 +786,8 @@ free:
  * allocated to satisfy the reservation must be explicitly freed if they were
  * never used.
  */
-static void return_unused_surplus_pages(unsigned long unused_resv_pages)
+static void return_unused_surplus_pages(struct hstate *h,
+                                       unsigned long unused_resv_pages)
 {
        static int nid = -1;
        struct page *page;
@@ -434,157 +802,269 @@ static void return_unused_surplus_pages(unsigned long unused_resv_pages)
        unsigned long remaining_iterations = num_online_nodes();
 
        /* Uncommit the reservation */
-       resv_huge_pages -= unused_resv_pages;
+       h->resv_huge_pages -= unused_resv_pages;
 
-       nr_pages = min(unused_resv_pages, surplus_huge_pages);
+       /* Cannot return gigantic pages currently */
+       if (h->order >= MAX_ORDER)
+               return;
+
+       nr_pages = min(unused_resv_pages, h->surplus_huge_pages);
 
        while (remaining_iterations-- && nr_pages) {
                nid = next_node(nid, node_online_map);
                if (nid == MAX_NUMNODES)
                        nid = first_node(node_online_map);
 
-               if (!surplus_huge_pages_node[nid])
+               if (!h->surplus_huge_pages_node[nid])
                        continue;
 
-               if (!list_empty(&hugepage_freelists[nid])) {
-                       page = list_entry(hugepage_freelists[nid].next,
+               if (!list_empty(&h->hugepage_freelists[nid])) {
+                       page = list_entry(h->hugepage_freelists[nid].next,
                                          struct page, lru);
                        list_del(&page->lru);
-                       update_and_free_page(page);
-                       free_huge_pages--;
-                       free_huge_pages_node[nid]--;
-                       surplus_huge_pages--;
-                       surplus_huge_pages_node[nid]--;
+                       update_and_free_page(h, page);
+                       h->free_huge_pages--;
+                       h->free_huge_pages_node[nid]--;
+                       h->surplus_huge_pages--;
+                       h->surplus_huge_pages_node[nid]--;
                        nr_pages--;
                        remaining_iterations = num_online_nodes();
                }
        }
 }
 
-
-static struct page *alloc_huge_page_shared(struct vm_area_struct *vma,
-                                               unsigned long addr)
+/*
+ * Determine if the huge page at addr within the vma has an associated
+ * reservation.  Where it does not we will need to logically increase
+ * reservation and actually increase quota before an allocation can occur.
+ * Where any new reservation would be required the reservation change is
+ * prepared, but not committed.  Once the page has been quota'd allocated
+ * an instantiated the change should be committed via vma_commit_reservation.
+ * No action is required on failure.
+ */
+static int vma_needs_reservation(struct hstate *h,
+                       struct vm_area_struct *vma, unsigned long addr)
 {
-       struct page *page;
+       struct address_space *mapping = vma->vm_file->f_mapping;
+       struct inode *inode = mapping->host;
 
-       spin_lock(&hugetlb_lock);
-       page = dequeue_huge_page_vma(vma, addr);
-       spin_unlock(&hugetlb_lock);
-       return page ? page : ERR_PTR(-VM_FAULT_OOM);
-}
+       if (vma->vm_flags & VM_SHARED) {
+               pgoff_t idx = vma_hugecache_offset(h, vma, addr);
+               return region_chg(&inode->i_mapping->private_list,
+                                                       idx, idx + 1);
 
-static struct page *alloc_huge_page_private(struct vm_area_struct *vma,
-                                               unsigned long addr)
-{
-       struct page *page = NULL;
+       } else if (!is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
+               return 1;
 
-       if (hugetlb_get_quota(vma->vm_file->f_mapping, 1))
-               return ERR_PTR(-VM_FAULT_SIGBUS);
+       } else  {
+               int err;
+               pgoff_t idx = vma_hugecache_offset(h, vma, addr);
+               struct resv_map *reservations = vma_resv_map(vma);
 
-       spin_lock(&hugetlb_lock);
-       if (free_huge_pages > resv_huge_pages)
-               page = dequeue_huge_page_vma(vma, addr);
-       spin_unlock(&hugetlb_lock);
-       if (!page) {
-               page = alloc_buddy_huge_page(vma, addr);
-               if (!page) {
-                       hugetlb_put_quota(vma->vm_file->f_mapping, 1);
-                       return ERR_PTR(-VM_FAULT_OOM);
-               }
+               err = region_chg(&reservations->regions, idx, idx + 1);
+               if (err < 0)
+                       return err;
+               return 0;
        }
-       return page;
 }
-
-static struct page *alloc_huge_page(struct vm_area_struct *vma,
-                                   unsigned long addr)
+static void vma_commit_reservation(struct hstate *h,
+                       struct vm_area_struct *vma, unsigned long addr)
 {
-       struct page *page;
        struct address_space *mapping = vma->vm_file->f_mapping;
+       struct inode *inode = mapping->host;
 
-       if (vma->vm_flags & VM_MAYSHARE)
-               page = alloc_huge_page_shared(vma, addr);
-       else
-               page = alloc_huge_page_private(vma, addr);
+       if (vma->vm_flags & VM_SHARED) {
+               pgoff_t idx = vma_hugecache_offset(h, vma, addr);
+               region_add(&inode->i_mapping->private_list, idx, idx + 1);
+
+       } else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
+               pgoff_t idx = vma_hugecache_offset(h, vma, addr);
+               struct resv_map *reservations = vma_resv_map(vma);
 
-       if (!IS_ERR(page)) {
-               set_page_refcounted(page);
-               set_page_private(page, (unsigned long) mapping);
+               /* Mark this page used in the map. */
+               region_add(&reservations->regions, idx, idx + 1);
        }
-       return page;
 }
 
-static int __init hugetlb_init(void)
+static struct page *alloc_huge_page(struct vm_area_struct *vma,
+                                   unsigned long addr, int avoid_reserve)
 {
-       unsigned long i;
+       struct hstate *h = hstate_vma(vma);
+       struct page *page;
+       struct address_space *mapping = vma->vm_file->f_mapping;
+       struct inode *inode = mapping->host;
+       unsigned int chg;
 
-       if (HPAGE_SHIFT == 0)
-               return 0;
+       /*
+        * Processes that did not create the mapping will have no reserves and
+        * will not have accounted against quota. Check that the quota can be
+        * made before satisfying the allocation
+        * MAP_NORESERVE mappings may also need pages and quota allocated
+        * if no reserve mapping overlaps.
+        */
+       chg = vma_needs_reservation(h, vma, addr);
+       if (chg < 0)
+               return ERR_PTR(chg);
+       if (chg)
+               if (hugetlb_get_quota(inode->i_mapping, chg))
+                       return ERR_PTR(-ENOSPC);
 
-       for (i = 0; i < MAX_NUMNODES; ++i)
-               INIT_LIST_HEAD(&hugepage_freelists[i]);
+       spin_lock(&hugetlb_lock);
+       page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve);
+       spin_unlock(&hugetlb_lock);
+
+       if (!page) {
+               page = alloc_buddy_huge_page(h, vma, addr);
+               if (!page) {
+                       hugetlb_put_quota(inode->i_mapping, chg);
+                       return ERR_PTR(-VM_FAULT_OOM);
+               }
+       }
 
-       hugetlb_next_nid = first_node(node_online_map);
+       set_page_refcounted(page);
+       set_page_private(page, (unsigned long) mapping);
 
-       for (i = 0; i < max_huge_pages; ++i) {
-               if (!alloc_fresh_huge_page())
-                       break;
+       vma_commit_reservation(h, vma, addr);
+
+       return page;
+}
+
+__attribute__((weak)) int alloc_bootmem_huge_page(struct hstate *h)
+{
+       struct huge_bootmem_page *m;
+       int nr_nodes = nodes_weight(node_online_map);
+
+       while (nr_nodes) {
+               void *addr;
+
+               addr = __alloc_bootmem_node_nopanic(
+                               NODE_DATA(h->hugetlb_next_nid),
+                               huge_page_size(h), huge_page_size(h), 0);
+
+               if (addr) {
+                       /*
+                        * Use the beginning of the huge page to store the
+                        * huge_bootmem_page struct (until gather_bootmem
+                        * puts them into the mem_map).
+                        */
+                       m = addr;
+                       if (m)
+                               goto found;
+               }
+               hstate_next_node(h);
+               nr_nodes--;
        }
-       max_huge_pages = free_huge_pages = nr_huge_pages = i;
-       printk("Total HugeTLB memory allocated, %ld\n", free_huge_pages);
        return 0;
+
+found:
+       BUG_ON((unsigned long)virt_to_phys(m) & (huge_page_size(h) - 1));
+       /* Put them into a private list first because mem_map is not up yet */
+       list_add(&m->list, &huge_boot_pages);
+       m->hstate = h;
+       return 1;
 }
-module_init(hugetlb_init);
 
-static int __init hugetlb_setup(char *s)
+/* Put bootmem huge pages into the standard lists after mem_map is up */
+static void __init gather_bootmem_prealloc(void)
 {
-       if (sscanf(s, "%lu", &max_huge_pages) <= 0)
-               max_huge_pages = 0;
-       return 1;
+       struct huge_bootmem_page *m;
+
+       list_for_each_entry(m, &huge_boot_pages, list) {
+               struct page *page = virt_to_page(m);
+               struct hstate *h = m->hstate;
+               __ClearPageReserved(page);
+               WARN_ON(page_count(page) != 1);
+               prep_compound_page(page, h->order);
+               prep_new_huge_page(h, page, page_to_nid(page));
+       }
 }
-__setup("hugepages=", hugetlb_setup);
 
-static unsigned int cpuset_mems_nr(unsigned int *array)
+static void __init hugetlb_hstate_alloc_pages(struct hstate *h)
 {
-       int node;
-       unsigned int nr = 0;
+       unsigned long i;
 
-       for_each_node_mask(node, cpuset_current_mems_allowed)
-               nr += array[node];
+       for (i = 0; i < h->max_huge_pages; ++i) {
+               if (h->order >= MAX_ORDER) {
+                       if (!alloc_bootmem_huge_page(h))
+                               break;
+               } else if (!alloc_fresh_huge_page(h))
+                       break;
+       }
+       h->max_huge_pages = i;
+}
 
-       return nr;
+static void __init hugetlb_init_hstates(void)
+{
+       struct hstate *h;
+
+       for_each_hstate(h) {
+               /* oversize hugepages were init'ed in early boot */
+               if (h->order < MAX_ORDER)
+                       hugetlb_hstate_alloc_pages(h);
+       }
+}
+
+static char * __init memfmt(char *buf, unsigned long n)
+{
+       if (n >= (1UL << 30))
+               sprintf(buf, "%lu GB", n >> 30);
+       else if (n >= (1UL << 20))
+               sprintf(buf, "%lu MB", n >> 20);
+       else
+               sprintf(buf, "%lu KB", n >> 10);
+       return buf;
+}
+
+static void __init report_hugepages(void)
+{
+       struct hstate *h;
+
+       for_each_hstate(h) {
+               char buf[32];
+               printk(KERN_INFO "HugeTLB registered %s page size, "
+                                "pre-allocated %ld pages\n",
+                       memfmt(buf, huge_page_size(h)),
+                       h->free_huge_pages);
+       }
 }
 
-#ifdef CONFIG_SYSCTL
 #ifdef CONFIG_HIGHMEM
-static void try_to_free_low(unsigned long count)
+static void try_to_free_low(struct hstate *h, unsigned long count)
 {
        int i;
 
+       if (h->order >= MAX_ORDER)
+               return;
+
        for (i = 0; i < MAX_NUMNODES; ++i) {
                struct page *page, *next;
-               list_for_each_entry_safe(page, next, &hugepage_freelists[i], lru) {
-                       if (count >= nr_huge_pages)
+               struct list_head *freel = &h->hugepage_freelists[i];
+               list_for_each_entry_safe(page, next, freel, lru) {
+                       if (count >= h->nr_huge_pages)
                                return;
                        if (PageHighMem(page))
                                continue;
                        list_del(&page->lru);
-                       update_and_free_page(page);
-                       free_huge_pages--;
-                       free_huge_pages_node[page_to_nid(page)]--;
+                       update_and_free_page(h, page);
+                       h->free_huge_pages--;
+                       h->free_huge_pages_node[page_to_nid(page)]--;
                }
        }
 }
 #else
-static inline void try_to_free_low(unsigned long count)
+static inline void try_to_free_low(struct hstate *h, unsigned long count)
 {
 }
 #endif
 
-#define persistent_huge_pages (nr_huge_pages - surplus_huge_pages)
-static unsigned long set_max_huge_pages(unsigned long count)
+#define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages)
+static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count)
 {
        unsigned long min_count, ret;
 
+       if (h->order >= MAX_ORDER)
+               return h->max_huge_pages;
+
        /*
         * Increase the pool size
         * First take pages out of surplus state.  Then make up the
@@ -597,20 +1077,19 @@ static unsigned long set_max_huge_pages(unsigned long count)
         * within all the constraints specified by the sysctls.
         */
        spin_lock(&hugetlb_lock);
-       while (surplus_huge_pages && count > persistent_huge_pages) {
-               if (!adjust_pool_surplus(-1))
+       while (h->surplus_huge_pages && count > persistent_huge_pages(h)) {
+               if (!adjust_pool_surplus(h, -1))
                        break;
        }
 
-       while (count > persistent_huge_pages) {
-               int ret;
+       while (count > persistent_huge_pages(h)) {
                /*
                 * If this allocation races such that we no longer need the
                 * page, free_huge_page will handle it by freeing the page
                 * and reducing the surplus.
                 */
                spin_unlock(&hugetlb_lock);
-               ret = alloc_fresh_huge_page();
+               ret = alloc_fresh_huge_page(h);
                spin_lock(&hugetlb_lock);
                if (!ret)
                        goto out;
@@ -632,89 +1111,454 @@ static unsigned long set_max_huge_pages(unsigned long count)
         * and won't grow the pool anywhere else. Not until one of the
         * sysctls are changed, or the surplus pages go out of use.
         */
-       min_count = resv_huge_pages + nr_huge_pages - free_huge_pages;
+       min_count = h->resv_huge_pages + h->nr_huge_pages - h->free_huge_pages;
        min_count = max(count, min_count);
-       try_to_free_low(min_count);
-       while (min_count < persistent_huge_pages) {
-               struct page *page = dequeue_huge_page();
+       try_to_free_low(h, min_count);
+       while (min_count < persistent_huge_pages(h)) {
+               struct page *page = dequeue_huge_page(h);
                if (!page)
                        break;
-               update_and_free_page(page);
+               update_and_free_page(h, page);
        }
-       while (count < persistent_huge_pages) {
-               if (!adjust_pool_surplus(1))
+       while (count < persistent_huge_pages(h)) {
+               if (!adjust_pool_surplus(h, 1))
                        break;
        }
 out:
-       ret = persistent_huge_pages;
+       ret = persistent_huge_pages(h);
+       spin_unlock(&hugetlb_lock);
+       return ret;
+}
+
+#define HSTATE_ATTR_RO(_name) \
+       static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
+
+#define HSTATE_ATTR(_name) \
+       static struct kobj_attribute _name##_attr = \
+               __ATTR(_name, 0644, _name##_show, _name##_store)
+
+static struct kobject *hugepages_kobj;
+static struct kobject *hstate_kobjs[HUGE_MAX_HSTATE];
+
+static struct hstate *kobj_to_hstate(struct kobject *kobj)
+{
+       int i;
+       for (i = 0; i < HUGE_MAX_HSTATE; i++)
+               if (hstate_kobjs[i] == kobj)
+                       return &hstates[i];
+       BUG();
+       return NULL;
+}
+
+static ssize_t nr_hugepages_show(struct kobject *kobj,
+                                       struct kobj_attribute *attr, char *buf)
+{
+       struct hstate *h = kobj_to_hstate(kobj);
+       return sprintf(buf, "%lu\n", h->nr_huge_pages);
+}
+static ssize_t nr_hugepages_store(struct kobject *kobj,
+               struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       int err;
+       unsigned long input;
+       struct hstate *h = kobj_to_hstate(kobj);
+
+       err = strict_strtoul(buf, 10, &input);
+       if (err)
+               return 0;
+
+       h->max_huge_pages = set_max_huge_pages(h, input);
+
+       return count;
+}
+HSTATE_ATTR(nr_hugepages);
+
+static ssize_t nr_overcommit_hugepages_show(struct kobject *kobj,
+                                       struct kobj_attribute *attr, char *buf)
+{
+       struct hstate *h = kobj_to_hstate(kobj);
+       return sprintf(buf, "%lu\n", h->nr_overcommit_huge_pages);
+}
+static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj,
+               struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       int err;
+       unsigned long input;
+       struct hstate *h = kobj_to_hstate(kobj);
+
+       err = strict_strtoul(buf, 10, &input);
+       if (err)
+               return 0;
+
+       spin_lock(&hugetlb_lock);
+       h->nr_overcommit_huge_pages = input;
+       spin_unlock(&hugetlb_lock);
+
+       return count;
+}
+HSTATE_ATTR(nr_overcommit_hugepages);
+
+static ssize_t free_hugepages_show(struct kobject *kobj,
+                                       struct kobj_attribute *attr, char *buf)
+{
+       struct hstate *h = kobj_to_hstate(kobj);
+       return sprintf(buf, "%lu\n", h->free_huge_pages);
+}
+HSTATE_ATTR_RO(free_hugepages);
+
+static ssize_t resv_hugepages_show(struct kobject *kobj,
+                                       struct kobj_attribute *attr, char *buf)
+{
+       struct hstate *h = kobj_to_hstate(kobj);
+       return sprintf(buf, "%lu\n", h->resv_huge_pages);
+}
+HSTATE_ATTR_RO(resv_hugepages);
+
+static ssize_t surplus_hugepages_show(struct kobject *kobj,
+                                       struct kobj_attribute *attr, char *buf)
+{
+       struct hstate *h = kobj_to_hstate(kobj);
+       return sprintf(buf, "%lu\n", h->surplus_huge_pages);
+}
+HSTATE_ATTR_RO(surplus_hugepages);
+
+static struct attribute *hstate_attrs[] = {
+       &nr_hugepages_attr.attr,
+       &nr_overcommit_hugepages_attr.attr,
+       &free_hugepages_attr.attr,
+       &resv_hugepages_attr.attr,
+       &surplus_hugepages_attr.attr,
+       NULL,
+};
+
+static struct attribute_group hstate_attr_group = {
+       .attrs = hstate_attrs,
+};
+
+static int __init hugetlb_sysfs_add_hstate(struct hstate *h)
+{
+       int retval;
+
+       hstate_kobjs[h - hstates] = kobject_create_and_add(h->name,
+                                                       hugepages_kobj);
+       if (!hstate_kobjs[h - hstates])
+               return -ENOMEM;
+
+       retval = sysfs_create_group(hstate_kobjs[h - hstates],
+                                                       &hstate_attr_group);
+       if (retval)
+               kobject_put(hstate_kobjs[h - hstates]);
+
+       return retval;
+}
+
+static void __init hugetlb_sysfs_init(void)
+{
+       struct hstate *h;
+       int err;
+
+       hugepages_kobj = kobject_create_and_add("hugepages", mm_kobj);
+       if (!hugepages_kobj)
+               return;
+
+       for_each_hstate(h) {
+               err = hugetlb_sysfs_add_hstate(h);
+               if (err)
+                       printk(KERN_ERR "Hugetlb: Unable to add hstate %s",
+                                                               h->name);
+       }
+}
+
+static void __exit hugetlb_exit(void)
+{
+       struct hstate *h;
+
+       for_each_hstate(h) {
+               kobject_put(hstate_kobjs[h - hstates]);
+       }
+
+       kobject_put(hugepages_kobj);
+}
+module_exit(hugetlb_exit);
+
+static int __init hugetlb_init(void)
+{
+       BUILD_BUG_ON(HPAGE_SHIFT == 0);
+
+       if (!size_to_hstate(default_hstate_size)) {
+               default_hstate_size = HPAGE_SIZE;
+               if (!size_to_hstate(default_hstate_size))
+                       hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
+       }
+       default_hstate_idx = size_to_hstate(default_hstate_size) - hstates;
+       if (default_hstate_max_huge_pages)
+               default_hstate.max_huge_pages = default_hstate_max_huge_pages;
+
+       hugetlb_init_hstates();
+
+       gather_bootmem_prealloc();
+
+       report_hugepages();
+
+       hugetlb_sysfs_init();
+
+       return 0;
+}
+module_init(hugetlb_init);
+
+/* Should be called on processing a hugepagesz=... option */
+void __init hugetlb_add_hstate(unsigned order)
+{
+       struct hstate *h;
+       unsigned long i;
+
+       if (size_to_hstate(PAGE_SIZE << order)) {
+               printk(KERN_WARNING "hugepagesz= specified twice, ignoring\n");
+               return;
+       }
+       BUG_ON(max_hstate >= HUGE_MAX_HSTATE);
+       BUG_ON(order == 0);
+       h = &hstates[max_hstate++];
+       h->order = order;
+       h->mask = ~((1ULL << (order + PAGE_SHIFT)) - 1);
+       h->nr_huge_pages = 0;
+       h->free_huge_pages = 0;
+       for (i = 0; i < MAX_NUMNODES; ++i)
+               INIT_LIST_HEAD(&h->hugepage_freelists[i]);
+       h->hugetlb_next_nid = first_node(node_online_map);
+       snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB",
+                                       huge_page_size(h)/1024);
+
+       parsed_hstate = h;
+}
+
+static int __init hugetlb_nrpages_setup(char *s)
+{
+       unsigned long *mhp;
+       static unsigned long *last_mhp;
+
+       /*
+        * !max_hstate means we haven't parsed a hugepagesz= parameter yet,
+        * so this hugepages= parameter goes to the "default hstate".
+        */
+       if (!max_hstate)
+               mhp = &default_hstate_max_huge_pages;
+       else
+               mhp = &parsed_hstate->max_huge_pages;
+
+       if (mhp == last_mhp) {
+               printk(KERN_WARNING "hugepages= specified twice without "
+                       "interleaving hugepagesz=, ignoring\n");
+               return 1;
+       }
+
+       if (sscanf(s, "%lu", mhp) <= 0)
+               *mhp = 0;
+
+       /*
+        * Global state is always initialized later in hugetlb_init.
+        * But we need to allocate >= MAX_ORDER hstates here early to still
+        * use the bootmem allocator.
+        */
+       if (max_hstate && parsed_hstate->order >= MAX_ORDER)
+               hugetlb_hstate_alloc_pages(parsed_hstate);
+
+       last_mhp = mhp;
+
+       return 1;
+}
+__setup("hugepages=", hugetlb_nrpages_setup);
+
+static int __init hugetlb_default_setup(char *s)
+{
+       default_hstate_size = memparse(s, &s);
+       return 1;
+}
+__setup("default_hugepagesz=", hugetlb_default_setup);
+
+static unsigned int cpuset_mems_nr(unsigned int *array)
+{
+       int node;
+       unsigned int nr = 0;
+
+       for_each_node_mask(node, cpuset_current_mems_allowed)
+               nr += array[node];
+
+       return nr;
+}
+
+#ifdef CONFIG_SYSCTL
+int hugetlb_sysctl_handler(struct ctl_table *table, int write,
+                          struct file *file, void __user *buffer,
+                          size_t *length, loff_t *ppos)
+{
+       struct hstate *h = &default_hstate;
+       unsigned long tmp;
+
+       if (!write)
+               tmp = h->max_huge_pages;
+
+       table->data = &tmp;
+       table->maxlen = sizeof(unsigned long);
+       proc_doulongvec_minmax(table, write, file, buffer, length, ppos);
+
+       if (write)
+               h->max_huge_pages = set_max_huge_pages(h, tmp);
+
+       return 0;
+}
+
+int hugetlb_treat_movable_handler(struct ctl_table *table, int write,
+                       struct file *file, void __user *buffer,
+                       size_t *length, loff_t *ppos)
+{
+       proc_dointvec(table, write, file, buffer, length, ppos);
+       if (hugepages_treat_as_movable)
+               htlb_alloc_mask = GFP_HIGHUSER_MOVABLE;
+       else
+               htlb_alloc_mask = GFP_HIGHUSER;
+       return 0;
+}
+
+int hugetlb_overcommit_handler(struct ctl_table *table, int write,
+                       struct file *file, void __user *buffer,
+                       size_t *length, loff_t *ppos)
+{
+       struct hstate *h = &default_hstate;
+       unsigned long tmp;
+
+       if (!write)
+               tmp = h->nr_overcommit_huge_pages;
+
+       table->data = &tmp;
+       table->maxlen = sizeof(unsigned long);
+       proc_doulongvec_minmax(table, write, file, buffer, length, ppos);
+
+       if (write) {
+               spin_lock(&hugetlb_lock);
+               h->nr_overcommit_huge_pages = tmp;
+               spin_unlock(&hugetlb_lock);
+       }
+
+       return 0;
+}
+
+#endif /* CONFIG_SYSCTL */
+
+int hugetlb_report_meminfo(char *buf)
+{
+       struct hstate *h = &default_hstate;
+       return sprintf(buf,
+                       "HugePages_Total: %5lu\n"
+                       "HugePages_Free:  %5lu\n"
+                       "HugePages_Rsvd:  %5lu\n"
+                       "HugePages_Surp:  %5lu\n"
+                       "Hugepagesize:    %5lu kB\n",
+                       h->nr_huge_pages,
+                       h->free_huge_pages,
+                       h->resv_huge_pages,
+                       h->surplus_huge_pages,
+                       1UL << (huge_page_order(h) + PAGE_SHIFT - 10));
+}
+
+int hugetlb_report_node_meminfo(int nid, char *buf)
+{
+       struct hstate *h = &default_hstate;
+       return sprintf(buf,
+               "Node %d HugePages_Total: %5u\n"
+               "Node %d HugePages_Free:  %5u\n"
+               "Node %d HugePages_Surp:  %5u\n",
+               nid, h->nr_huge_pages_node[nid],
+               nid, h->free_huge_pages_node[nid],
+               nid, h->surplus_huge_pages_node[nid]);
+}
+
+/* Return the number pages of memory we physically have, in PAGE_SIZE units. */
+unsigned long hugetlb_total_pages(void)
+{
+       struct hstate *h = &default_hstate;
+       return h->nr_huge_pages * pages_per_huge_page(h);
+}
+
+static int hugetlb_acct_memory(struct hstate *h, long delta)
+{
+       int ret = -ENOMEM;
+
+       spin_lock(&hugetlb_lock);
+       /*
+        * When cpuset is configured, it breaks the strict hugetlb page
+        * reservation as the accounting is done on a global variable. Such
+        * reservation is completely rubbish in the presence of cpuset because
+        * the reservation is not checked against page availability for the
+        * current cpuset. Application can still potentially OOM'ed by kernel
+        * with lack of free htlb page in cpuset that the task is in.
+        * Attempt to enforce strict accounting with cpuset is almost
+        * impossible (or too ugly) because cpuset is too fluid that
+        * task or memory node can be dynamically moved between cpusets.
+        *
+        * The change of semantics for shared hugetlb mapping with cpuset is
+        * undesirable. However, in order to preserve some of the semantics,
+        * we fall back to check against current free page availability as
+        * a best attempt and hopefully to minimize the impact of changing
+        * semantics that cpuset has.
+        */
+       if (delta > 0) {
+               if (gather_surplus_pages(h, delta) < 0)
+                       goto out;
+
+               if (delta > cpuset_mems_nr(h->free_huge_pages_node)) {
+                       return_unused_surplus_pages(h, delta);
+                       goto out;
+               }
+       }
+
+       ret = 0;
+       if (delta < 0)
+               return_unused_surplus_pages(h, (unsigned long) -delta);
+
+out:
        spin_unlock(&hugetlb_lock);
        return ret;
 }
 
-int hugetlb_sysctl_handler(struct ctl_table *table, int write,
-                          struct file *file, void __user *buffer,
-                          size_t *length, loff_t *ppos)
+static void hugetlb_vm_op_open(struct vm_area_struct *vma)
 {
-       proc_doulongvec_minmax(table, write, file, buffer, length, ppos);
-       max_huge_pages = set_max_huge_pages(max_huge_pages);
-       return 0;
-}
+       struct resv_map *reservations = vma_resv_map(vma);
 
-int hugetlb_treat_movable_handler(struct ctl_table *table, int write,
-                       struct file *file, void __user *buffer,
-                       size_t *length, loff_t *ppos)
-{
-       proc_dointvec(table, write, file, buffer, length, ppos);
-       if (hugepages_treat_as_movable)
-               htlb_alloc_mask = GFP_HIGHUSER_MOVABLE;
-       else
-               htlb_alloc_mask = GFP_HIGHUSER;
-       return 0;
+       /*
+        * This new VMA should share its siblings reservation map if present.
+        * The VMA will only ever have a valid reservation map pointer where
+        * it is being copied for another still existing VMA.  As that VMA
+        * has a reference to the reservation map it cannot dissappear until
+        * after this open call completes.  It is therefore safe to take a
+        * new reference here without additional locking.
+        */
+       if (reservations)
+               kref_get(&reservations->refs);
 }
 
-int hugetlb_overcommit_handler(struct ctl_table *table, int write,
-                       struct file *file, void __user *buffer,
-                       size_t *length, loff_t *ppos)
+static void hugetlb_vm_op_close(struct vm_area_struct *vma)
 {
-       proc_doulongvec_minmax(table, write, file, buffer, length, ppos);
-       spin_lock(&hugetlb_lock);
-       nr_overcommit_huge_pages = sysctl_overcommit_huge_pages;
-       spin_unlock(&hugetlb_lock);
-       return 0;
-}
+       struct hstate *h = hstate_vma(vma);
+       struct resv_map *reservations = vma_resv_map(vma);
+       unsigned long reserve;
+       unsigned long start;
+       unsigned long end;
 
-#endif /* CONFIG_SYSCTL */
+       if (reservations) {
+               start = vma_hugecache_offset(h, vma, vma->vm_start);
+               end = vma_hugecache_offset(h, vma, vma->vm_end);
 
-int hugetlb_report_meminfo(char *buf)
-{
-       return sprintf(buf,
-                       "HugePages_Total: %5lu\n"
-                       "HugePages_Free:  %5lu\n"
-                       "HugePages_Rsvd:  %5lu\n"
-                       "HugePages_Surp:  %5lu\n"
-                       "Hugepagesize:    %5lu kB\n",
-                       nr_huge_pages,
-                       free_huge_pages,
-                       resv_huge_pages,
-                       surplus_huge_pages,
-                       HPAGE_SIZE/1024);
-}
+               reserve = (end - start) -
+                       region_count(&reservations->regions, start, end);
 
-int hugetlb_report_node_meminfo(int nid, char *buf)
-{
-       return sprintf(buf,
-               "Node %d HugePages_Total: %5u\n"
-               "Node %d HugePages_Free:  %5u\n"
-               "Node %d HugePages_Surp:  %5u\n",
-               nid, nr_huge_pages_node[nid],
-               nid, free_huge_pages_node[nid],
-               nid, surplus_huge_pages_node[nid]);
-}
+               kref_put(&reservations->refs, resv_map_release);
 
-/* Return the number pages of memory we physically have, in PAGE_SIZE units. */
-unsigned long hugetlb_total_pages(void)
-{
-       return nr_huge_pages * (HPAGE_SIZE / PAGE_SIZE);
+               if (reserve) {
+                       hugetlb_acct_memory(h, -reserve);
+                       hugetlb_put_quota(vma->vm_file->f_mapping, reserve);
+               }
+       }
 }
 
 /*
@@ -731,6 +1575,8 @@ static int hugetlb_vm_op_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 struct vm_operations_struct hugetlb_vm_ops = {
        .fault = hugetlb_vm_op_fault,
+       .open = hugetlb_vm_op_open,
+       .close = hugetlb_vm_op_close,
 };
 
 static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
@@ -769,14 +1615,16 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
        struct page *ptepage;
        unsigned long addr;
        int cow;
+       struct hstate *h = hstate_vma(vma);
+       unsigned long sz = huge_page_size(h);
 
        cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
 
-       for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
+       for (addr = vma->vm_start; addr < vma->vm_end; addr += sz) {
                src_pte = huge_pte_offset(src, addr);
                if (!src_pte)
                        continue;
-               dst_pte = huge_pte_alloc(dst, addr);
+               dst_pte = huge_pte_alloc(dst, addr, sz);
                if (!dst_pte)
                        goto nomem;
 
@@ -804,7 +1652,7 @@ nomem:
 }
 
 void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
-                           unsigned long end)
+                           unsigned long end, struct page *ref_page)
 {
        struct mm_struct *mm = vma->vm_mm;
        unsigned long address;
@@ -812,6 +1660,9 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
        pte_t pte;
        struct page *page;
        struct page *tmp;
+       struct hstate *h = hstate_vma(vma);
+       unsigned long sz = huge_page_size(h);
+
        /*
         * A page gathering list, protected by per file i_mmap_lock. The
         * lock is used to avoid list corruption from multiple unmapping
@@ -820,11 +1671,12 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
        LIST_HEAD(page_list);
 
        WARN_ON(!is_vm_hugetlb_page(vma));
-       BUG_ON(start & ~HPAGE_MASK);
-       BUG_ON(end & ~HPAGE_MASK);
+       BUG_ON(start & ~huge_page_mask(h));
+       BUG_ON(end & ~huge_page_mask(h));
 
+       mmu_notifier_invalidate_range_start(mm, start, end);
        spin_lock(&mm->page_table_lock);
-       for (address = start; address < end; address += HPAGE_SIZE) {
+       for (address = start; address < end; address += sz) {
                ptep = huge_pte_offset(mm, address);
                if (!ptep)
                        continue;
@@ -832,6 +1684,27 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
                if (huge_pmd_unshare(mm, &address, ptep))
                        continue;
 
+               /*
+                * If a reference page is supplied, it is because a specific
+                * page is being unmapped, not a range. Ensure the page we
+                * are about to unmap is the actual page of interest.
+                */
+               if (ref_page) {
+                       pte = huge_ptep_get(ptep);
+                       if (huge_pte_none(pte))
+                               continue;
+                       page = pte_page(pte);
+                       if (page != ref_page)
+                               continue;
+
+                       /*
+                        * Mark the VMA as having unmapped its page so that
+                        * future faults in this VMA will fail rather than
+                        * looking like data was lost
+                        */
+                       set_vma_resv_flags(vma, HPAGE_RESV_UNMAPPED);
+               }
+
                pte = huge_ptep_get_and_clear(mm, address, ptep);
                if (huge_pte_none(pte))
                        continue;
@@ -843,6 +1716,7 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
        }
        spin_unlock(&mm->page_table_lock);
        flush_tlb_range(vma, start, end);
+       mmu_notifier_invalidate_range_end(mm, start, end);
        list_for_each_entry_safe(page, tmp, &page_list, lru) {
                list_del(&page->lru);
                put_page(page);
@@ -850,31 +1724,71 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
 }
 
 void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
-                         unsigned long end)
+                         unsigned long end, struct page *ref_page)
+{
+       spin_lock(&vma->vm_file->f_mapping->i_mmap_lock);
+       __unmap_hugepage_range(vma, start, end, ref_page);
+       spin_unlock(&vma->vm_file->f_mapping->i_mmap_lock);
+}
+
+/*
+ * This is called when the original mapper is failing to COW a MAP_PRIVATE
+ * mappping it owns the reserve page for. The intention is to unmap the page
+ * from other VMAs and let the children be SIGKILLed if they are faulting the
+ * same region.
+ */
+int unmap_ref_private(struct mm_struct *mm,
+                                       struct vm_area_struct *vma,
+                                       struct page *page,
+                                       unsigned long address)
 {
+       struct vm_area_struct *iter_vma;
+       struct address_space *mapping;
+       struct prio_tree_iter iter;
+       pgoff_t pgoff;
+
        /*
-        * It is undesirable to test vma->vm_file as it should be non-null
-        * for valid hugetlb area. However, vm_file will be NULL in the error
-        * cleanup path of do_mmap_pgoff. When hugetlbfs ->mmap method fails,
-        * do_mmap_pgoff() nullifies vma->vm_file before calling this function
-        * to clean up. Since no pte has actually been setup, it is safe to
-        * do nothing in this case.
+        * vm_pgoff is in PAGE_SIZE units, hence the different calculation
+        * from page cache lookup which is in HPAGE_SIZE units.
         */
-       if (vma->vm_file) {
-               spin_lock(&vma->vm_file->f_mapping->i_mmap_lock);
-               __unmap_hugepage_range(vma, start, end);
-               spin_unlock(&vma->vm_file->f_mapping->i_mmap_lock);
+       address = address & huge_page_mask(hstate_vma(vma));
+       pgoff = ((address - vma->vm_start) >> PAGE_SHIFT)
+               + (vma->vm_pgoff >> PAGE_SHIFT);
+       mapping = (struct address_space *)page_private(page);
+
+       vma_prio_tree_foreach(iter_vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
+               /* Do not unmap the current VMA */
+               if (iter_vma == vma)
+                       continue;
+
+               /*
+                * Unmap the page from other VMAs without their own reserves.
+                * They get marked to be SIGKILLed if they fault in these
+                * areas. This is because a future no-page fault on this VMA
+                * could insert a zeroed page instead of the data existing
+                * from the time of fork. This would look like data corruption
+                */
+               if (!is_vma_resv_set(iter_vma, HPAGE_RESV_OWNER))
+                       unmap_hugepage_range(iter_vma,
+                               address, address + HPAGE_SIZE,
+                               page);
        }
+
+       return 1;
 }
 
 static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
-                       unsigned long address, pte_t *ptep, pte_t pte)
+                       unsigned long address, pte_t *ptep, pte_t pte,
+                       struct page *pagecache_page)
 {
+       struct hstate *h = hstate_vma(vma);
        struct page *old_page, *new_page;
        int avoidcopy;
+       int outside_reserve = 0;
 
        old_page = pte_page(pte);
 
+retry_avoidcopy:
        /* If no-one else is actually using this page, avoid the copy
         * and just make the page writable */
        avoidcopy = (page_count(old_page) == 1);
@@ -883,11 +1797,43 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
                return 0;
        }
 
+       /*
+        * If the process that created a MAP_PRIVATE mapping is about to
+        * perform a COW due to a shared page count, attempt to satisfy
+        * the allocation without using the existing reserves. The pagecache
+        * page is used to determine if the reserve at this address was
+        * consumed or not. If reserves were used, a partial faulted mapping
+        * at the time of fork() could consume its reserves on COW instead
+        * of the full address range.
+        */
+       if (!(vma->vm_flags & VM_SHARED) &&
+                       is_vma_resv_set(vma, HPAGE_RESV_OWNER) &&
+                       old_page != pagecache_page)
+               outside_reserve = 1;
+
        page_cache_get(old_page);
-       new_page = alloc_huge_page(vma, address);
+       new_page = alloc_huge_page(vma, address, outside_reserve);
 
        if (IS_ERR(new_page)) {
                page_cache_release(old_page);
+
+               /*
+                * If a process owning a MAP_PRIVATE mapping fails to COW,
+                * it is due to references held by a child and an insufficient
+                * huge page pool. To guarantee the original mappers
+                * reliability, unmap the page from child processes. The child
+                * may get SIGKILLed if it later faults.
+                */
+               if (outside_reserve) {
+                       BUG_ON(huge_pte_none(pte));
+                       if (unmap_ref_private(mm, vma, old_page, address)) {
+                               BUG_ON(page_count(old_page) != 1);
+                               BUG_ON(huge_pte_none(pte));
+                               goto retry_avoidcopy;
+                       }
+                       WARN_ON_ONCE(1);
+               }
+
                return -PTR_ERR(new_page);
        }
 
@@ -896,7 +1842,7 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
        __SetPageUptodate(new_page);
        spin_lock(&mm->page_table_lock);
 
-       ptep = huge_pte_offset(mm, address & HPAGE_MASK);
+       ptep = huge_pte_offset(mm, address & huge_page_mask(h));
        if (likely(pte_same(huge_ptep_get(ptep), pte))) {
                /* Break COW */
                huge_ptep_clear_flush(vma, address, ptep);
@@ -910,19 +1856,44 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
        return 0;
 }
 
+/* Return the pagecache page at a given address within a VMA */
+static struct page *hugetlbfs_pagecache_page(struct hstate *h,
+                       struct vm_area_struct *vma, unsigned long address)
+{
+       struct address_space *mapping;
+       pgoff_t idx;
+
+       mapping = vma->vm_file->f_mapping;
+       idx = vma_hugecache_offset(h, vma, address);
+
+       return find_lock_page(mapping, idx);
+}
+
 static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        unsigned long address, pte_t *ptep, int write_access)
 {
+       struct hstate *h = hstate_vma(vma);
        int ret = VM_FAULT_SIGBUS;
-       unsigned long idx;
+       pgoff_t idx;
        unsigned long size;
        struct page *page;
        struct address_space *mapping;
        pte_t new_pte;
 
+       /*
+        * Currently, we are forced to kill the process in the event the
+        * original mapper has unmapped pages from the child due to a failed
+        * COW. Warn that such a situation has occured as it may not be obvious
+        */
+       if (is_vma_resv_set(vma, HPAGE_RESV_UNMAPPED)) {
+               printk(KERN_WARNING
+                       "PID %d killed due to inadequate hugepage pool\n",
+                       current->pid);
+               return ret;
+       }
+
        mapping = vma->vm_file->f_mapping;
-       idx = ((address - vma->vm_start) >> HPAGE_SHIFT)
-               + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
+       idx = vma_hugecache_offset(h, vma, address);
 
        /*
         * Use page lock to guard against racing truncation
@@ -931,15 +1902,15 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
 retry:
        page = find_lock_page(mapping, idx);
        if (!page) {
-               size = i_size_read(mapping->host) >> HPAGE_SHIFT;
+               size = i_size_read(mapping->host) >> huge_page_shift(h);
                if (idx >= size)
                        goto out;
-               page = alloc_huge_page(vma, address);
+               page = alloc_huge_page(vma, address, 0);
                if (IS_ERR(page)) {
                        ret = -PTR_ERR(page);
                        goto out;
                }
-               clear_huge_page(page, address);
+               clear_huge_page(page, address, huge_page_size(h));
                __SetPageUptodate(page);
 
                if (vma->vm_flags & VM_SHARED) {
@@ -955,14 +1926,14 @@ retry:
                        }
 
                        spin_lock(&inode->i_lock);
-                       inode->i_blocks += BLOCKS_PER_HUGEPAGE;
+                       inode->i_blocks += blocks_per_huge_page(h);
                        spin_unlock(&inode->i_lock);
                } else
                        lock_page(page);
        }
 
        spin_lock(&mm->page_table_lock);
-       size = i_size_read(mapping->host) >> HPAGE_SHIFT;
+       size = i_size_read(mapping->host) >> huge_page_shift(h);
        if (idx >= size)
                goto backout;
 
@@ -976,7 +1947,7 @@ retry:
 
        if (write_access && !(vma->vm_flags & VM_SHARED)) {
                /* Optimization, do the COW without a second fault */
-               ret = hugetlb_cow(mm, vma, address, ptep, new_pte);
+               ret = hugetlb_cow(mm, vma, address, ptep, new_pte, page);
        }
 
        spin_unlock(&mm->page_table_lock);
@@ -998,8 +1969,9 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        pte_t entry;
        int ret;
        static DEFINE_MUTEX(hugetlb_instantiation_mutex);
+       struct hstate *h = hstate_vma(vma);
 
-       ptep = huge_pte_alloc(mm, address);
+       ptep = huge_pte_alloc(mm, address, huge_page_size(h));
        if (!ptep)
                return VM_FAULT_OOM;
 
@@ -1021,14 +1993,30 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        spin_lock(&mm->page_table_lock);
        /* Check for a racing update before calling hugetlb_cow */
        if (likely(pte_same(entry, huge_ptep_get(ptep))))
-               if (write_access && !pte_write(entry))
-                       ret = hugetlb_cow(mm, vma, address, ptep, entry);
+               if (write_access && !pte_write(entry)) {
+                       struct page *page;
+                       page = hugetlbfs_pagecache_page(h, vma, address);
+                       ret = hugetlb_cow(mm, vma, address, ptep, entry, page);
+                       if (page) {
+                               unlock_page(page);
+                               put_page(page);
+                       }
+               }
        spin_unlock(&mm->page_table_lock);
        mutex_unlock(&hugetlb_instantiation_mutex);
 
        return ret;
 }
 
+/* Can be overriden by architectures */
+__attribute__((weak)) struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+              pud_t *pud, int write)
+{
+       BUG();
+       return NULL;
+}
+
 int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        struct page **pages, struct vm_area_struct **vmas,
                        unsigned long *position, int *length, int i,
@@ -1037,6 +2025,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
        unsigned long pfn_offset;
        unsigned long vaddr = *position;
        int remainder = *length;
+       struct hstate *h = hstate_vma(vma);
 
        spin_lock(&mm->page_table_lock);
        while (vaddr < vma->vm_end && remainder) {
@@ -1048,7 +2037,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                 * each hugepage.  We have to make * sure we get the
                 * first, for the page indexing below to work.
                 */
-               pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);
+               pte = huge_pte_offset(mm, vaddr & huge_page_mask(h));
 
                if (!pte || huge_pte_none(huge_ptep_get(pte)) ||
                    (write && !pte_write(huge_ptep_get(pte)))) {
@@ -1066,7 +2055,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        break;
                }
 
-               pfn_offset = (vaddr & ~HPAGE_MASK) >> PAGE_SHIFT;
+               pfn_offset = (vaddr & ~huge_page_mask(h)) >> PAGE_SHIFT;
                page = pte_page(huge_ptep_get(pte));
 same_page:
                if (pages) {
@@ -1082,7 +2071,7 @@ same_page:
                --remainder;
                ++i;
                if (vaddr < vma->vm_end && remainder &&
-                               pfn_offset < HPAGE_SIZE/PAGE_SIZE) {
+                               pfn_offset < pages_per_huge_page(h)) {
                        /*
                         * We use pfn_offset to avoid touching the pageframes
                         * of this compound page.
@@ -1104,13 +2093,14 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
        unsigned long start = address;
        pte_t *ptep;
        pte_t pte;
+       struct hstate *h = hstate_vma(vma);
 
        BUG_ON(address >= end);
        flush_cache_range(vma, address, end);
 
        spin_lock(&vma->vm_file->f_mapping->i_mmap_lock);
        spin_lock(&mm->page_table_lock);
-       for (; address < end; address += HPAGE_SIZE) {
+       for (; address < end; address += huge_page_size(h)) {
                ptep = huge_pte_offset(mm, address);
                if (!ptep)
                        continue;
@@ -1128,195 +2118,59 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
        flush_tlb_range(vma, start, end);
 }
 
-struct file_region {
-       struct list_head link;
-       long from;
-       long to;
-};
-
-static long region_add(struct list_head *head, long f, long t)
-{
-       struct file_region *rg, *nrg, *trg;
-
-       /* Locate the region we are either in or before. */
-       list_for_each_entry(rg, head, link)
-               if (f <= rg->to)
-                       break;
-
-       /* Round our left edge to the current segment if it encloses us. */
-       if (f > rg->from)
-               f = rg->from;
-
-       /* Check for and consume any regions we now overlap with. */
-       nrg = rg;
-       list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
-               if (&rg->link == head)
-                       break;
-               if (rg->from > t)
-                       break;
-
-               /* If this area reaches higher then extend our area to
-                * include it completely.  If this is not the first area
-                * which we intend to reuse, free it. */
-               if (rg->to > t)
-                       t = rg->to;
-               if (rg != nrg) {
-                       list_del(&rg->link);
-                       kfree(rg);
-               }
-       }
-       nrg->from = f;
-       nrg->to = t;
-       return 0;
-}
-
-static long region_chg(struct list_head *head, long f, long t)
-{
-       struct file_region *rg, *nrg;
-       long chg = 0;
-
-       /* Locate the region we are before or in. */
-       list_for_each_entry(rg, head, link)
-               if (f <= rg->to)
-                       break;
-
-       /* If we are below the current region then a new region is required.
-        * Subtle, allocate a new region at the position but make it zero
-        * size such that we can guarantee to record the reservation. */
-       if (&rg->link == head || t < rg->from) {
-               nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
-               if (!nrg)
-                       return -ENOMEM;
-               nrg->from = f;
-               nrg->to   = f;
-               INIT_LIST_HEAD(&nrg->link);
-               list_add(&nrg->link, rg->link.prev);
-
-               return t - f;
-       }
-
-       /* Round our left edge to the current segment if it encloses us. */
-       if (f > rg->from)
-               f = rg->from;
-       chg = t - f;
-
-       /* Check for and consume any regions we now overlap with. */
-       list_for_each_entry(rg, rg->link.prev, link) {
-               if (&rg->link == head)
-                       break;
-               if (rg->from > t)
-                       return chg;
-
-               /* We overlap with this area, if it extends futher than
-                * us then we must extend ourselves.  Account for its
-                * existing reservation. */
-               if (rg->to > t) {
-                       chg += rg->to - t;
-                       t = rg->to;
-               }
-               chg -= rg->to - rg->from;
-       }
-       return chg;
-}
-
-static long region_truncate(struct list_head *head, long end)
+int hugetlb_reserve_pages(struct inode *inode,
+                                       long from, long to,
+                                       struct vm_area_struct *vma)
 {
-       struct file_region *rg, *trg;
-       long chg = 0;
+       long ret, chg;
+       struct hstate *h = hstate_inode(inode);
 
-       /* Locate the region we are either in or before. */
-       list_for_each_entry(rg, head, link)
-               if (end <= rg->to)
-                       break;
-       if (&rg->link == head)
+       if (vma && vma->vm_flags & VM_NORESERVE)
                return 0;
 
-       /* If we are in the middle of a region then adjust it. */
-       if (end > rg->from) {
-               chg = rg->to - end;
-               rg->to = end;
-               rg = list_entry(rg->link.next, typeof(*rg), link);
-       }
-
-       /* Drop any remaining regions. */
-       list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
-               if (&rg->link == head)
-                       break;
-               chg += rg->to - rg->from;
-               list_del(&rg->link);
-               kfree(rg);
-       }
-       return chg;
-}
-
-static int hugetlb_acct_memory(long delta)
-{
-       int ret = -ENOMEM;
-
-       spin_lock(&hugetlb_lock);
        /*
-        * When cpuset is configured, it breaks the strict hugetlb page
-        * reservation as the accounting is done on a global variable. Such
-        * reservation is completely rubbish in the presence of cpuset because
-        * the reservation is not checked against page availability for the
-        * current cpuset. Application can still potentially OOM'ed by kernel
-        * with lack of free htlb page in cpuset that the task is in.
-        * Attempt to enforce strict accounting with cpuset is almost
-        * impossible (or too ugly) because cpuset is too fluid that
-        * task or memory node can be dynamically moved between cpusets.
-        *
-        * The change of semantics for shared hugetlb mapping with cpuset is
-        * undesirable. However, in order to preserve some of the semantics,
-        * we fall back to check against current free page availability as
-        * a best attempt and hopefully to minimize the impact of changing
-        * semantics that cpuset has.
+        * Shared mappings base their reservation on the number of pages that
+        * are already allocated on behalf of the file. Private mappings need
+        * to reserve the full area even if read-only as mprotect() may be
+        * called to make the mapping read-write. Assume !vma is a shm mapping
         */
-       if (delta > 0) {
-               if (gather_surplus_pages(delta) < 0)
-                       goto out;
-
-               if (delta > cpuset_mems_nr(free_huge_pages_node)) {
-                       return_unused_surplus_pages(delta);
-                       goto out;
-               }
-       }
-
-       ret = 0;
-       if (delta < 0)
-               return_unused_surplus_pages((unsigned long) -delta);
+       if (!vma || vma->vm_flags & VM_SHARED)
+               chg = region_chg(&inode->i_mapping->private_list, from, to);
+       else {
+               struct resv_map *resv_map = resv_map_alloc();
+               if (!resv_map)
+                       return -ENOMEM;
 
-out:
-       spin_unlock(&hugetlb_lock);
-       return ret;
-}
+               chg = to - from;
 
-int hugetlb_reserve_pages(struct inode *inode, long from, long to)
-{
-       long ret, chg;
+               set_vma_resv_map(vma, resv_map);
+               set_vma_resv_flags(vma, HPAGE_RESV_OWNER);
+       }
 
-       chg = region_chg(&inode->i_mapping->private_list, from, to);
        if (chg < 0)
                return chg;
 
        if (hugetlb_get_quota(inode->i_mapping, chg))
                return -ENOSPC;
-       ret = hugetlb_acct_memory(chg);
+       ret = hugetlb_acct_memory(h, chg);
        if (ret < 0) {
                hugetlb_put_quota(inode->i_mapping, chg);
                return ret;
        }
-       region_add(&inode->i_mapping->private_list, from, to);
+       if (!vma || vma->vm_flags & VM_SHARED)
+               region_add(&inode->i_mapping->private_list, from, to);
        return 0;
 }
 
 void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
 {
+       struct hstate *h = hstate_inode(inode);
        long chg = region_truncate(&inode->i_mapping->private_list, offset);
 
        spin_lock(&inode->i_lock);
-       inode->i_blocks -= BLOCKS_PER_HUGEPAGE * freed;
+       inode->i_blocks -= blocks_per_huge_page(h);
        spin_unlock(&inode->i_lock);
 
        hugetlb_put_quota(inode->i_mapping, (chg - freed));
-       hugetlb_acct_memory(-(chg - freed));
+       hugetlb_acct_memory(h, -(chg - freed));
 }
index 0034e947e4bc677c9220c267eaaa75d5d89e7760..1f43f7416972d3c4f1b07ab04898008a8ec76a81 100644 (file)
 
 #include <linux/mm.h>
 
+void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
+               unsigned long floor, unsigned long ceiling);
+
+extern void prep_compound_page(struct page *page, unsigned long order);
+
 static inline void set_page_count(struct page *page, int v)
 {
        atomic_set(&page->_count, v);
@@ -59,4 +64,60 @@ static inline unsigned long page_order(struct page *page)
 #define __paginginit __init
 #endif
 
+/* Memory initialisation debug and verification */
+enum mminit_level {
+       MMINIT_WARNING,
+       MMINIT_VERIFY,
+       MMINIT_TRACE
+};
+
+#ifdef CONFIG_DEBUG_MEMORY_INIT
+
+extern int mminit_loglevel;
+
+#define mminit_dprintk(level, prefix, fmt, arg...) \
+do { \
+       if (level < mminit_loglevel) { \
+               printk(level <= MMINIT_WARNING ? KERN_WARNING : KERN_DEBUG); \
+               printk(KERN_CONT "mminit::" prefix " " fmt, ##arg); \
+       } \
+} while (0)
+
+extern void mminit_verify_pageflags_layout(void);
+extern void mminit_verify_page_links(struct page *page,
+               enum zone_type zone, unsigned long nid, unsigned long pfn);
+extern void mminit_verify_zonelist(void);
+
+#else
+
+static inline void mminit_dprintk(enum mminit_level level,
+                               const char *prefix, const char *fmt, ...)
+{
+}
+
+static inline void mminit_verify_pageflags_layout(void)
+{
+}
+
+static inline void mminit_verify_page_links(struct page *page,
+               enum zone_type zone, unsigned long nid, unsigned long pfn)
+{
+}
+
+static inline void mminit_verify_zonelist(void)
+{
+}
+#endif /* CONFIG_DEBUG_MEMORY_INIT */
+
+/* mminit_validate_memmodel_limits is independent of CONFIG_DEBUG_MEMORY_INIT */
+#if defined(CONFIG_SPARSEMEM)
+extern void mminit_validate_memmodel_limits(unsigned long *start_pfn,
+                               unsigned long *end_pfn);
+#else
+static inline void mminit_validate_memmodel_limits(unsigned long *start_pfn,
+                               unsigned long *end_pfn)
+{
+}
+#endif /* CONFIG_SPARSEMEM */
+
 #endif
index e46451e1d9b793563b08d8ef015927b484b0be1d..fba566c513220dcf8c30133a617e5d27328a23f2 100644 (file)
@@ -35,9 +35,9 @@
 
 #include <asm/uaccess.h>
 
-struct cgroup_subsys mem_cgroup_subsys;
-static const int MEM_CGROUP_RECLAIM_RETRIES = 5;
-static struct kmem_cache *page_cgroup_cache;
+struct cgroup_subsys mem_cgroup_subsys __read_mostly;
+static struct kmem_cache *page_cgroup_cache __read_mostly;
+#define MEM_CGROUP_RECLAIM_RETRIES     5
 
 /*
  * Statistics for memory cgroup.
@@ -166,7 +166,6 @@ struct page_cgroup {
        struct list_head lru;           /* per cgroup LRU list */
        struct page *page;
        struct mem_cgroup *mem_cgroup;
-       int ref_cnt;                    /* cached, mapped, migrating */
        int flags;
 };
 #define PAGE_CGROUP_FLAG_CACHE (0x1)   /* charged as cache */
@@ -185,6 +184,7 @@ static enum zone_type page_cgroup_zid(struct page_cgroup *pc)
 enum charge_type {
        MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
        MEM_CGROUP_CHARGE_TYPE_MAPPED,
+       MEM_CGROUP_CHARGE_TYPE_FORCE,   /* used by force_empty */
 };
 
 /*
@@ -296,7 +296,7 @@ static void __mem_cgroup_remove_list(struct mem_cgroup_per_zone *mz,
                MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) -= 1;
 
        mem_cgroup_charge_statistics(pc->mem_cgroup, pc->flags, false);
-       list_del_init(&pc->lru);
+       list_del(&pc->lru);
 }
 
 static void __mem_cgroup_add_list(struct mem_cgroup_per_zone *mz,
@@ -354,6 +354,9 @@ void mem_cgroup_move_lists(struct page *page, bool active)
        struct mem_cgroup_per_zone *mz;
        unsigned long flags;
 
+       if (mem_cgroup_subsys.disabled)
+               return;
+
        /*
         * We cannot lock_page_cgroup while holding zone's lru_lock,
         * because other holders of lock_page_cgroup can be interrupted
@@ -524,7 +527,8 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
  * < 0 if the cgroup is over its limit
  */
 static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
-                               gfp_t gfp_mask, enum charge_type ctype)
+                               gfp_t gfp_mask, enum charge_type ctype,
+                               struct mem_cgroup *memcg)
 {
        struct mem_cgroup *mem;
        struct page_cgroup *pc;
@@ -532,35 +536,8 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
        unsigned long nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
        struct mem_cgroup_per_zone *mz;
 
-       if (mem_cgroup_subsys.disabled)
-               return 0;
-
-       /*
-        * Should page_cgroup's go to their own slab?
-        * One could optimize the performance of the charging routine
-        * by saving a bit in the page_flags and using it as a lock
-        * to see if the cgroup page already has a page_cgroup associated
-        * with it
-        */
-retry:
-       lock_page_cgroup(page);
-       pc = page_get_page_cgroup(page);
-       /*
-        * The page_cgroup exists and
-        * the page has already been accounted.
-        */
-       if (pc) {
-               VM_BUG_ON(pc->page != page);
-               VM_BUG_ON(pc->ref_cnt <= 0);
-
-               pc->ref_cnt++;
-               unlock_page_cgroup(page);
-               goto done;
-       }
-       unlock_page_cgroup(page);
-
-       pc = kmem_cache_zalloc(page_cgroup_cache, gfp_mask);
-       if (pc == NULL)
+       pc = kmem_cache_alloc(page_cgroup_cache, gfp_mask);
+       if (unlikely(pc == NULL))
                goto err;
 
        /*
@@ -569,16 +546,18 @@ retry:
         * thread group leader migrates. It's possible that mm is not
         * set, if so charge the init_mm (happens for pagecache usage).
         */
-       if (!mm)
-               mm = &init_mm;
-
-       rcu_read_lock();
-       mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
-       /*
-        * For every charge from the cgroup, increment reference count
-        */
-       css_get(&mem->css);
-       rcu_read_unlock();
+       if (likely(!memcg)) {
+               rcu_read_lock();
+               mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
+               /*
+                * For every charge from the cgroup, increment reference count
+                */
+               css_get(&mem->css);
+               rcu_read_unlock();
+       } else {
+               mem = memcg;
+               css_get(&memcg->css);
+       }
 
        while (res_counter_charge(&mem->res, PAGE_SIZE)) {
                if (!(gfp_mask & __GFP_WAIT))
@@ -603,25 +582,24 @@ retry:
                }
        }
 
-       pc->ref_cnt = 1;
        pc->mem_cgroup = mem;
        pc->page = page;
-       pc->flags = PAGE_CGROUP_FLAG_ACTIVE;
+       /*
+        * If a page is accounted as a page cache, insert to inactive list.
+        * If anon, insert to active list.
+        */
        if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE)
                pc->flags = PAGE_CGROUP_FLAG_CACHE;
+       else
+               pc->flags = PAGE_CGROUP_FLAG_ACTIVE;
 
        lock_page_cgroup(page);
-       if (page_get_page_cgroup(page)) {
+       if (unlikely(page_get_page_cgroup(page))) {
                unlock_page_cgroup(page);
-               /*
-                * Another charge has been added to this page already.
-                * We take lock_page_cgroup(page) again and read
-                * page->cgroup, increment refcnt.... just retry is OK.
-                */
                res_counter_uncharge(&mem->res, PAGE_SIZE);
                css_put(&mem->css);
                kmem_cache_free(page_cgroup_cache, pc);
-               goto retry;
+               goto done;
        }
        page_assign_page_cgroup(page, pc);
 
@@ -642,24 +620,65 @@ err:
 
 int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask)
 {
+       if (mem_cgroup_subsys.disabled)
+               return 0;
+
+       /*
+        * If already mapped, we don't have to account.
+        * If page cache, page->mapping has address_space.
+        * But page->mapping may have out-of-use anon_vma pointer,
+        * detecit it by PageAnon() check. newly-mapped-anon's page->mapping
+        * is NULL.
+        */
+       if (page_mapped(page) || (page->mapping && !PageAnon(page)))
+               return 0;
+       if (unlikely(!mm))
+               mm = &init_mm;
        return mem_cgroup_charge_common(page, mm, gfp_mask,
-                               MEM_CGROUP_CHARGE_TYPE_MAPPED);
+                               MEM_CGROUP_CHARGE_TYPE_MAPPED, NULL);
 }
 
 int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
                                gfp_t gfp_mask)
 {
-       if (!mm)
+       if (mem_cgroup_subsys.disabled)
+               return 0;
+
+       /*
+        * Corner case handling. This is called from add_to_page_cache()
+        * in usual. But some FS (shmem) precharges this page before calling it
+        * and call add_to_page_cache() with GFP_NOWAIT.
+        *
+        * For GFP_NOWAIT case, the page may be pre-charged before calling
+        * add_to_page_cache(). (See shmem.c) check it here and avoid to call
+        * charge twice. (It works but has to pay a bit larger cost.)
+        */
+       if (!(gfp_mask & __GFP_WAIT)) {
+               struct page_cgroup *pc;
+
+               lock_page_cgroup(page);
+               pc = page_get_page_cgroup(page);
+               if (pc) {
+                       VM_BUG_ON(pc->page != page);
+                       VM_BUG_ON(!pc->mem_cgroup);
+                       unlock_page_cgroup(page);
+                       return 0;
+               }
+               unlock_page_cgroup(page);
+       }
+
+       if (unlikely(!mm))
                mm = &init_mm;
+
        return mem_cgroup_charge_common(page, mm, gfp_mask,
-                               MEM_CGROUP_CHARGE_TYPE_CACHE);
+                               MEM_CGROUP_CHARGE_TYPE_CACHE, NULL);
 }
 
 /*
- * Uncharging is always a welcome operation, we never complain, simply
- * uncharge.
+ * uncharge if !page_mapped(page)
  */
-void mem_cgroup_uncharge_page(struct page *page)
+static void
+__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 {
        struct page_cgroup *pc;
        struct mem_cgroup *mem;
@@ -674,98 +693,151 @@ void mem_cgroup_uncharge_page(struct page *page)
         */
        lock_page_cgroup(page);
        pc = page_get_page_cgroup(page);
-       if (!pc)
+       if (unlikely(!pc))
                goto unlock;
 
        VM_BUG_ON(pc->page != page);
-       VM_BUG_ON(pc->ref_cnt <= 0);
 
-       if (--(pc->ref_cnt) == 0) {
-               mz = page_cgroup_zoneinfo(pc);
-               spin_lock_irqsave(&mz->lru_lock, flags);
-               __mem_cgroup_remove_list(mz, pc);
-               spin_unlock_irqrestore(&mz->lru_lock, flags);
+       if ((ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED)
+           && ((pc->flags & PAGE_CGROUP_FLAG_CACHE)
+               || page_mapped(page)))
+               goto unlock;
 
-               page_assign_page_cgroup(page, NULL);
-               unlock_page_cgroup(page);
+       mz = page_cgroup_zoneinfo(pc);
+       spin_lock_irqsave(&mz->lru_lock, flags);
+       __mem_cgroup_remove_list(mz, pc);
+       spin_unlock_irqrestore(&mz->lru_lock, flags);
 
-               mem = pc->mem_cgroup;
-               res_counter_uncharge(&mem->res, PAGE_SIZE);
-               css_put(&mem->css);
+       page_assign_page_cgroup(page, NULL);
+       unlock_page_cgroup(page);
 
-               kmem_cache_free(page_cgroup_cache, pc);
-               return;
-       }
+       mem = pc->mem_cgroup;
+       res_counter_uncharge(&mem->res, PAGE_SIZE);
+       css_put(&mem->css);
 
+       kmem_cache_free(page_cgroup_cache, pc);
+       return;
 unlock:
        unlock_page_cgroup(page);
 }
 
+void mem_cgroup_uncharge_page(struct page *page)
+{
+       __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_MAPPED);
+}
+
+void mem_cgroup_uncharge_cache_page(struct page *page)
+{
+       VM_BUG_ON(page_mapped(page));
+       __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE);
+}
+
 /*
- * Returns non-zero if a page (under migration) has valid page_cgroup member.
- * Refcnt of page_cgroup is incremented.
+ * Before starting migration, account against new page.
  */
-int mem_cgroup_prepare_migration(struct page *page)
+int mem_cgroup_prepare_migration(struct page *page, struct page *newpage)
 {
        struct page_cgroup *pc;
+       struct mem_cgroup *mem = NULL;
+       enum charge_type ctype = MEM_CGROUP_CHARGE_TYPE_MAPPED;
+       int ret = 0;
 
        if (mem_cgroup_subsys.disabled)
                return 0;
 
        lock_page_cgroup(page);
        pc = page_get_page_cgroup(page);
-       if (pc)
-               pc->ref_cnt++;
+       if (pc) {
+               mem = pc->mem_cgroup;
+               css_get(&mem->css);
+               if (pc->flags & PAGE_CGROUP_FLAG_CACHE)
+                       ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
+       }
        unlock_page_cgroup(page);
-       return pc != NULL;
+       if (mem) {
+               ret = mem_cgroup_charge_common(newpage, NULL, GFP_KERNEL,
+                       ctype, mem);
+               css_put(&mem->css);
+       }
+       return ret;
 }
 
-void mem_cgroup_end_migration(struct page *page)
+/* remove redundant charge if migration failed*/
+void mem_cgroup_end_migration(struct page *newpage)
 {
-       mem_cgroup_uncharge_page(page);
+       /*
+        * At success, page->mapping is not NULL.
+        * special rollback care is necessary when
+        * 1. at migration failure. (newpage->mapping is cleared in this case)
+        * 2. the newpage was moved but not remapped again because the task
+        *    exits and the newpage is obsolete. In this case, the new page
+        *    may be a swapcache. So, we just call mem_cgroup_uncharge_page()
+        *    always for avoiding mess. The  page_cgroup will be removed if
+        *    unnecessary. File cache pages is still on radix-tree. Don't
+        *    care it.
+        */
+       if (!newpage->mapping)
+               __mem_cgroup_uncharge_common(newpage,
+                                        MEM_CGROUP_CHARGE_TYPE_FORCE);
+       else if (PageAnon(newpage))
+               mem_cgroup_uncharge_page(newpage);
 }
 
 /*
- * We know both *page* and *newpage* are now not-on-LRU and PG_locked.
- * And no race with uncharge() routines because page_cgroup for *page*
- * has extra one reference by mem_cgroup_prepare_migration.
+ * A call to try to shrink memory usage under specified resource controller.
+ * This is typically used for page reclaiming for shmem for reducing side
+ * effect of page allocation from shmem, which is used by some mem_cgroup.
  */
-void mem_cgroup_page_migration(struct page *page, struct page *newpage)
+int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask)
 {
-       struct page_cgroup *pc;
-       struct mem_cgroup_per_zone *mz;
-       unsigned long flags;
+       struct mem_cgroup *mem;
+       int progress = 0;
+       int retry = MEM_CGROUP_RECLAIM_RETRIES;
 
-       lock_page_cgroup(page);
-       pc = page_get_page_cgroup(page);
-       if (!pc) {
-               unlock_page_cgroup(page);
-               return;
-       }
+       if (mem_cgroup_subsys.disabled)
+               return 0;
 
-       mz = page_cgroup_zoneinfo(pc);
-       spin_lock_irqsave(&mz->lru_lock, flags);
-       __mem_cgroup_remove_list(mz, pc);
-       spin_unlock_irqrestore(&mz->lru_lock, flags);
+       rcu_read_lock();
+       mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
+       css_get(&mem->css);
+       rcu_read_unlock();
 
-       page_assign_page_cgroup(page, NULL);
-       unlock_page_cgroup(page);
+       do {
+               progress = try_to_free_mem_cgroup_pages(mem, gfp_mask);
+       } while (!progress && --retry);
 
-       pc->page = newpage;
-       lock_page_cgroup(newpage);
-       page_assign_page_cgroup(newpage, pc);
+       css_put(&mem->css);
+       if (!retry)
+               return -ENOMEM;
+       return 0;
+}
 
-       mz = page_cgroup_zoneinfo(pc);
-       spin_lock_irqsave(&mz->lru_lock, flags);
-       __mem_cgroup_add_list(mz, pc);
-       spin_unlock_irqrestore(&mz->lru_lock, flags);
+int mem_cgroup_resize_limit(struct mem_cgroup *memcg, unsigned long long val)
+{
+
+       int retry_count = MEM_CGROUP_RECLAIM_RETRIES;
+       int progress;
+       int ret = 0;
 
-       unlock_page_cgroup(newpage);
+       while (res_counter_set_limit(&memcg->res, val)) {
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
+               if (!retry_count) {
+                       ret = -EBUSY;
+                       break;
+               }
+               progress = try_to_free_mem_cgroup_pages(memcg, GFP_KERNEL);
+               if (!progress)
+                       retry_count--;
+       }
+       return ret;
 }
 
+
 /*
  * This routine traverse page_cgroup in given list and drop them all.
- * This routine ignores page_cgroup->ref_cnt.
  * *And* this routine doesn't reclaim page itself, just removes page_cgroup.
  */
 #define FORCE_UNCHARGE_BATCH   (128)
@@ -790,12 +862,20 @@ static void mem_cgroup_force_empty_list(struct mem_cgroup *mem,
                page = pc->page;
                get_page(page);
                spin_unlock_irqrestore(&mz->lru_lock, flags);
-               mem_cgroup_uncharge_page(page);
-               put_page(page);
-               if (--count <= 0) {
-                       count = FORCE_UNCHARGE_BATCH;
+               /*
+                * Check if this page is on LRU. !LRU page can be found
+                * if it's under page migration.
+                */
+               if (PageLRU(page)) {
+                       __mem_cgroup_uncharge_common(page,
+                                       MEM_CGROUP_CHARGE_TYPE_FORCE);
+                       put_page(page);
+                       if (--count <= 0) {
+                               count = FORCE_UNCHARGE_BATCH;
+                               cond_resched();
+                       }
+               } else
                        cond_resched();
-               }
                spin_lock_irqsave(&mz->lru_lock, flags);
        }
        spin_unlock_irqrestore(&mz->lru_lock, flags);
@@ -810,9 +890,6 @@ static int mem_cgroup_force_empty(struct mem_cgroup *mem)
        int ret = -EBUSY;
        int node, zid;
 
-       if (mem_cgroup_subsys.disabled)
-               return 0;
-
        css_get(&mem->css);
        /*
         * page reclaim code (kswapd etc..) will move pages between
@@ -838,32 +915,34 @@ out:
        return ret;
 }
 
-static int mem_cgroup_write_strategy(char *buf, unsigned long long *tmp)
-{
-       *tmp = memparse(buf, &buf);
-       if (*buf != '\0')
-               return -EINVAL;
-
-       /*
-        * Round up the value to the closest page size
-        */
-       *tmp = ((*tmp + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT;
-       return 0;
-}
-
 static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
 {
        return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res,
                                    cft->private);
 }
-
-static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
-                               struct file *file, const char __user *userbuf,
-                               size_t nbytes, loff_t *ppos)
+/*
+ * The user of this function is...
+ * RES_LIMIT.
+ */
+static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
+                           const char *buffer)
 {
-       return res_counter_write(&mem_cgroup_from_cont(cont)->res,
-                               cft->private, userbuf, nbytes, ppos,
-                               mem_cgroup_write_strategy);
+       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       unsigned long long val;
+       int ret;
+
+       switch (cft->private) {
+       case RES_LIMIT:
+               /* This function does all necessary parse...reuse it */
+               ret = res_counter_memparse_write_strategy(buffer, &val);
+               if (!ret)
+                       ret = mem_cgroup_resize_limit(memcg, val);
+               break;
+       default:
+               ret = -EINVAL; /* should be BUG() ? */
+               break;
+       }
+       return ret;
 }
 
 static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
@@ -940,7 +1019,7 @@ static struct cftype mem_cgroup_files[] = {
        {
                .name = "limit_in_bytes",
                .private = RES_LIMIT,
-               .write = mem_cgroup_write,
+               .write_string = mem_cgroup_write,
                .read_u64 = mem_cgroup_read,
        },
        {
@@ -1070,8 +1149,6 @@ static void mem_cgroup_destroy(struct cgroup_subsys *ss,
 static int mem_cgroup_populate(struct cgroup_subsys *ss,
                                struct cgroup *cont)
 {
-       if (mem_cgroup_subsys.disabled)
-               return 0;
        return cgroup_add_files(cont, ss, mem_cgroup_files,
                                        ARRAY_SIZE(mem_cgroup_files));
 }
@@ -1084,9 +1161,6 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
        struct mm_struct *mm;
        struct mem_cgroup *mem, *old_mem;
 
-       if (mem_cgroup_subsys.disabled)
-               return;
-
        mm = get_task_mm(p);
        if (mm == NULL)
                return;
index 2302d228fe04f3926f8c52bf65965623f1caff05..67f0ab9077d9472f99387aa66013bd2665d58887 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/init.h>
 #include <linux/writeback.h>
 #include <linux/memcontrol.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
@@ -61,6 +62,8 @@
 #include <linux/swapops.h>
 #include <linux/elf.h>
 
+#include "internal.h"
+
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 /* use the per-pgdat data instead for discontigmem - mbligh */
 unsigned long max_mapnr;
@@ -211,7 +214,7 @@ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
  *
  * Must be called with pagetable lock held.
  */
-void free_pgd_range(struct mmu_gather **tlb,
+void free_pgd_range(struct mmu_gather *tlb,
                        unsigned long addr, unsigned long end,
                        unsigned long floor, unsigned long ceiling)
 {
@@ -262,16 +265,16 @@ void free_pgd_range(struct mmu_gather **tlb,
                return;
 
        start = addr;
-       pgd = pgd_offset((*tlb)->mm, addr);
+       pgd = pgd_offset(tlb->mm, addr);
        do {
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
                        continue;
-               free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
+               free_pud_range(tlb, pgd, addr, next, floor, ceiling);
        } while (pgd++, addr = next, addr != end);
 }
 
-void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma,
+void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *vma,
                unsigned long floor, unsigned long ceiling)
 {
        while (vma) {
@@ -372,7 +375,8 @@ static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss)
  *
  * The calling function must still handle the error.
  */
-void print_bad_pte(struct vm_area_struct *vma, pte_t pte, unsigned long vaddr)
+static void print_bad_pte(struct vm_area_struct *vma, pte_t pte,
+                         unsigned long vaddr)
 {
        printk(KERN_ERR "Bad pte = %08llx, process = %s, "
                        "vm_flags = %lx, vaddr = %lx\n",
@@ -649,6 +653,7 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
        unsigned long next;
        unsigned long addr = vma->vm_start;
        unsigned long end = vma->vm_end;
+       int ret;
 
        /*
         * Don't copy ptes where a page fault will fill them correctly.
@@ -664,17 +669,33 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
        if (is_vm_hugetlb_page(vma))
                return copy_hugetlb_page_range(dst_mm, src_mm, vma);
 
+       /*
+        * We need to invalidate the secondary MMU mappings only when
+        * there could be a permission downgrade on the ptes of the
+        * parent mm. And a permission downgrade will only happen if
+        * is_cow_mapping() returns true.
+        */
+       if (is_cow_mapping(vma->vm_flags))
+               mmu_notifier_invalidate_range_start(src_mm, addr, end);
+
+       ret = 0;
        dst_pgd = pgd_offset(dst_mm, addr);
        src_pgd = pgd_offset(src_mm, addr);
        do {
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(src_pgd))
                        continue;
-               if (copy_pud_range(dst_mm, src_mm, dst_pgd, src_pgd,
-                                               vma, addr, next))
-                       return -ENOMEM;
+               if (unlikely(copy_pud_range(dst_mm, src_mm, dst_pgd, src_pgd,
+                                           vma, addr, next))) {
+                       ret = -ENOMEM;
+                       break;
+               }
        } while (dst_pgd++, src_pgd++, addr = next, addr != end);
-       return 0;
+
+       if (is_cow_mapping(vma->vm_flags))
+               mmu_notifier_invalidate_range_end(src_mm,
+                                                 vma->vm_start, end);
+       return ret;
 }
 
 static unsigned long zap_pte_range(struct mmu_gather *tlb,
@@ -878,7 +899,9 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp,
        unsigned long start = start_addr;
        spinlock_t *i_mmap_lock = details? details->i_mmap_lock: NULL;
        int fullmm = (*tlbp)->fullmm;
+       struct mm_struct *mm = vma->vm_mm;
 
+       mmu_notifier_invalidate_range_start(mm, start_addr, end_addr);
        for ( ; vma && vma->vm_start < end_addr; vma = vma->vm_next) {
                unsigned long end;
 
@@ -899,9 +922,23 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp,
                        }
 
                        if (unlikely(is_vm_hugetlb_page(vma))) {
-                               unmap_hugepage_range(vma, start, end);
-                               zap_work -= (end - start) /
-                                               (HPAGE_SIZE / PAGE_SIZE);
+                               /*
+                                * It is undesirable to test vma->vm_file as it
+                                * should be non-null for valid hugetlb area.
+                                * However, vm_file will be NULL in the error
+                                * cleanup path of do_mmap_pgoff. When
+                                * hugetlbfs ->mmap method fails,
+                                * do_mmap_pgoff() nullifies vma->vm_file
+                                * before calling this function to clean up.
+                                * Since no pte has actually been setup, it is
+                                * safe to do nothing in this case.
+                                */
+                               if (vma->vm_file) {
+                                       unmap_hugepage_range(vma, start, end, NULL);
+                                       zap_work -= (end - start) /
+                                       pages_per_huge_page(hstate_vma(vma));
+                               }
+
                                start = end;
                        } else
                                start = unmap_page_range(*tlbp, vma,
@@ -929,6 +966,7 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp,
                }
        }
 out:
+       mmu_notifier_invalidate_range_end(mm, start_addr, end_addr);
        return start;   /* which is now the end (or restart) address */
 }
 
@@ -982,19 +1020,24 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
                goto no_page_table;
 
        pud = pud_offset(pgd, address);
-       if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+       if (pud_none(*pud))
+               goto no_page_table;
+       if (pud_huge(*pud)) {
+               BUG_ON(flags & FOLL_GET);
+               page = follow_huge_pud(mm, address, pud, flags & FOLL_WRITE);
+               goto out;
+       }
+       if (unlikely(pud_bad(*pud)))
                goto no_page_table;
-       
+
        pmd = pmd_offset(pud, address);
        if (pmd_none(*pmd))
                goto no_page_table;
-
        if (pmd_huge(*pmd)) {
                BUG_ON(flags & FOLL_GET);
                page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE);
                goto out;
        }
-
        if (unlikely(pmd_bad(*pmd)))
                goto no_page_table;
 
@@ -1058,11 +1101,9 @@ static inline int use_zero_page(struct vm_area_struct *vma)
        if (vma->vm_flags & (VM_LOCKED | VM_SHARED))
                return 0;
        /*
-        * And if we have a fault or a nopfn routine, it's not an
-        * anonymous region.
+        * And if we have a fault routine, it's not an anonymous region.
         */
-       return !vma->vm_ops ||
-               (!vma->vm_ops->fault && !vma->vm_ops->nopfn);
+       return !vma->vm_ops || !vma->vm_ops->fault;
 }
 
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
@@ -1338,6 +1379,11 @@ out:
  *
  * This function should only be called from a vm_ops->fault handler, and
  * in that case the handler should return NULL.
+ *
+ * vma cannot be a COW mapping.
+ *
+ * As this is called only for pages that do not currently exist, we
+ * do not need to flush old virtual caches or the TLB.
  */
 int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
                        unsigned long pfn)
@@ -1548,6 +1594,8 @@ static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud,
        unsigned long next;
        int err;
 
+       BUG_ON(pud_huge(*pud));
+
        pmd = pmd_alloc(mm, pud, addr);
        if (!pmd)
                return -ENOMEM;
@@ -1589,10 +1637,11 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
 {
        pgd_t *pgd;
        unsigned long next;
-       unsigned long end = addr + size;
+       unsigned long start = addr, end = addr + size;
        int err;
 
        BUG_ON(addr >= end);
+       mmu_notifier_invalidate_range_start(mm, start, end);
        pgd = pgd_offset(mm, addr);
        do {
                next = pgd_addr_end(addr, end);
@@ -1600,6 +1649,7 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
                if (err)
                        break;
        } while (pgd++, addr = next, addr != end);
+       mmu_notifier_invalidate_range_end(mm, start, end);
        return err;
 }
 EXPORT_SYMBOL_GPL(apply_to_page_range);
@@ -1812,7 +1862,7 @@ gotten:
                 * seen in the presence of one thread doing SMC and another
                 * thread doing COW.
                 */
-               ptep_clear_flush(vma, address, page_table);
+               ptep_clear_flush_notify(vma, address, page_table);
                set_pte_at(mm, address, page_table, entry);
                update_mmu_cache(vma, address, entry);
                lru_cache_add_active(new_page);
@@ -2501,59 +2551,6 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte);
 }
 
-
-/*
- * 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;
-
-       pte_unmap(page_table);
-       BUG_ON(!(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)));
-       BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags));
-
-       pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK);
-
-       BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn));
-
-       if (unlikely(pfn == NOPFN_OOM))
-               return VM_FAULT_OOM;
-       else if (unlikely(pfn == NOPFN_SIGBUS))
-               return VM_FAULT_SIGBUS;
-       else if (unlikely(pfn == NOPFN_REFAULT))
-               return 0;
-
-       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 0;
-}
-
 /*
  * Fault of a previously existing named mapping. Repopulate the pte
  * from the encoded file_pte if possible. This enables swappable
@@ -2614,9 +2611,6 @@ static inline int handle_pte_fault(struct mm_struct *mm,
                                if (likely(vma->vm_ops->fault))
                                        return do_linear_fault(mm, vma, address,
                                                pte, pmd, write_access, entry);
-                               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);
@@ -2804,6 +2798,86 @@ int in_gate_area_no_task(unsigned long addr)
 
 #endif /* __HAVE_ARCH_GATE_AREA */
 
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+static resource_size_t follow_phys(struct vm_area_struct *vma,
+                       unsigned long address, unsigned int flags,
+                       unsigned long *prot)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *ptep, pte;
+       spinlock_t *ptl;
+       resource_size_t phys_addr = 0;
+       struct mm_struct *mm = vma->vm_mm;
+
+       VM_BUG_ON(!(vma->vm_flags & (VM_IO | VM_PFNMAP)));
+
+       pgd = pgd_offset(mm, address);
+       if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+               goto no_page_table;
+
+       pud = pud_offset(pgd, address);
+       if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+               goto no_page_table;
+
+       pmd = pmd_offset(pud, address);
+       if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+               goto no_page_table;
+
+       /* We cannot handle huge page PFN maps. Luckily they don't exist. */
+       if (pmd_huge(*pmd))
+               goto no_page_table;
+
+       ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
+       if (!ptep)
+               goto out;
+
+       pte = *ptep;
+       if (!pte_present(pte))
+               goto unlock;
+       if ((flags & FOLL_WRITE) && !pte_write(pte))
+               goto unlock;
+       phys_addr = pte_pfn(pte);
+       phys_addr <<= PAGE_SHIFT; /* Shift here to avoid overflow on PAE */
+
+       *prot = pgprot_val(pte_pgprot(pte));
+
+unlock:
+       pte_unmap_unlock(ptep, ptl);
+out:
+       return phys_addr;
+no_page_table:
+       return 0;
+}
+
+int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
+                       void *buf, int len, int write)
+{
+       resource_size_t phys_addr;
+       unsigned long prot = 0;
+       void *maddr;
+       int offset = addr & (PAGE_SIZE-1);
+
+       if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+               return -EINVAL;
+
+       phys_addr = follow_phys(vma, addr, write, &prot);
+
+       if (!phys_addr)
+               return -EINVAL;
+
+       maddr = ioremap_prot(phys_addr, PAGE_SIZE, prot);
+       if (write)
+               memcpy_toio(maddr + offset, buf, len);
+       else
+               memcpy_fromio(buf, maddr + offset, len);
+       iounmap(maddr);
+
+       return len;
+}
+#endif
+
 /*
  * Access another process' address space.
  * Source/target buffer must be kernel space,
@@ -2813,7 +2887,6 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
 {
        struct mm_struct *mm;
        struct vm_area_struct *vma;
-       struct page *page;
        void *old_buf = buf;
 
        mm = get_task_mm(tsk);
@@ -2825,28 +2898,44 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
        while (len) {
                int bytes, ret, offset;
                void *maddr;
+               struct page *page = NULL;
 
                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);
+               if (ret <= 0) {
+                       /*
+                        * Check if this is a VM_IO | VM_PFNMAP VMA, which
+                        * we can access using slightly different code.
+                        */
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+                       vma = find_vma(mm, addr);
+                       if (!vma)
+                               break;
+                       if (vma->vm_ops && vma->vm_ops->access)
+                               ret = vma->vm_ops->access(vma, addr, buf,
+                                                         len, write);
+                       if (ret <= 0)
+#endif
+                               break;
+                       bytes = ret;
                } else {
-                       copy_from_user_page(vma, page, addr,
-                                           buf, maddr + offset, bytes);
+                       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);
                }
-               kunmap(page);
-               page_cache_release(page);
                len -= bytes;
                buf += bytes;
                addr += bytes;
index 833f854eabe50ad226696667db7e49d332840bb6..89fee2dcb03928594ca2da67e9b75e7c8507394b 100644 (file)
@@ -62,9 +62,9 @@ static void release_memory_resource(struct resource *res)
 
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
 #ifndef CONFIG_SPARSEMEM_VMEMMAP
-static void get_page_bootmem(unsigned long info,  struct page *page, int magic)
+static void get_page_bootmem(unsigned long info,  struct page *page, int type)
 {
-       atomic_set(&page->_mapcount, magic);
+       atomic_set(&page->_mapcount, type);
        SetPagePrivate(page);
        set_page_private(page, info);
        atomic_inc(&page->_count);
@@ -72,10 +72,10 @@ static void get_page_bootmem(unsigned long info,  struct page *page, int magic)
 
 void put_page_bootmem(struct page *page)
 {
-       int magic;
+       int type;
 
-       magic = atomic_read(&page->_mapcount);
-       BUG_ON(magic >= -1);
+       type = atomic_read(&page->_mapcount);
+       BUG_ON(type >= -1);
 
        if (atomic_dec_return(&page->_count) == 1) {
                ClearPagePrivate(page);
@@ -86,7 +86,7 @@ void put_page_bootmem(struct page *page)
 
 }
 
-void register_page_bootmem_info_section(unsigned long start_pfn)
+static void register_page_bootmem_info_section(unsigned long start_pfn)
 {
        unsigned long *usemap, mapsize, section_nr, i;
        struct mem_section *ms;
@@ -119,7 +119,7 @@ void register_page_bootmem_info_section(unsigned long start_pfn)
        mapsize = PAGE_ALIGN(usemap_size()) >> PAGE_SHIFT;
 
        for (i = 0; i < mapsize; i++, page++)
-               get_page_bootmem(section_nr, page, MIX_INFO);
+               get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
 
 }
 
@@ -429,7 +429,9 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
 
        if (need_zonelists_rebuild)
                build_all_zonelists();
-       vm_total_pages = nr_free_pagecache_pages();
+       else
+               vm_total_pages = nr_free_pagecache_pages();
+
        writeback_set_ratelimit();
 
        if (onlined_pages)
@@ -455,7 +457,7 @@ static pg_data_t *hotadd_new_pgdat(int nid, u64 start)
        /* we can use NODE_DATA(nid) from here */
 
        /* init node's zones as empty zones, we don't have any present pages.*/
-       free_area_init_node(nid, pgdat, zones_size, start_pfn, zholes_size);
+       free_area_init_node(nid, zones_size, start_pfn, zholes_size);
 
        return pgdat;
 }
@@ -520,6 +522,66 @@ error:
 EXPORT_SYMBOL_GPL(add_memory);
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
+/*
+ * A free page on the buddy free lists (not the per-cpu lists) has PageBuddy
+ * set and the size of the free page is given by page_order(). Using this,
+ * the function determines if the pageblock contains only free pages.
+ * Due to buddy contraints, a free page at least the size of a pageblock will
+ * be located at the start of the pageblock
+ */
+static inline int pageblock_free(struct page *page)
+{
+       return PageBuddy(page) && page_order(page) >= pageblock_order;
+}
+
+/* Return the start of the next active pageblock after a given page */
+static struct page *next_active_pageblock(struct page *page)
+{
+       int pageblocks_stride;
+
+       /* Ensure the starting page is pageblock-aligned */
+       BUG_ON(page_to_pfn(page) & (pageblock_nr_pages - 1));
+
+       /* Move forward by at least 1 * pageblock_nr_pages */
+       pageblocks_stride = 1;
+
+       /* If the entire pageblock is free, move to the end of free page */
+       if (pageblock_free(page))
+               pageblocks_stride += page_order(page) - pageblock_order;
+
+       return page + (pageblocks_stride * pageblock_nr_pages);
+}
+
+/* Checks if this range of memory is likely to be hot-removable. */
+int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
+{
+       int type;
+       struct page *page = pfn_to_page(start_pfn);
+       struct page *end_page = page + nr_pages;
+
+       /* Check the starting page of each pageblock within the range */
+       for (; page < end_page; page = next_active_pageblock(page)) {
+               type = get_pageblock_migratetype(page);
+
+               /*
+                * A pageblock containing MOVABLE or free pages is considered
+                * removable
+                */
+               if (type != MIGRATE_MOVABLE && !pageblock_free(page))
+                       return 0;
+
+               /*
+                * A pageblock starting with a PageReserved page is not
+                * considered removable.
+                */
+               if (PageReserved(page))
+                       return 0;
+       }
+
+       /* All pageblocks in the memory block are likely to be hot-removable */
+       return 1;
+}
+
 /*
  * Confirm all pages in a range [start, end) is belongs to the same zone.
  */
index c94e58b192c3c9913f4f4ab57860b6ac9469f839..e550bec205826bd63f46082d6c5aac7bc69aa23e 100644 (file)
@@ -1481,7 +1481,7 @@ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
 
        if (unlikely((*mpol)->mode == MPOL_INTERLEAVE)) {
                zl = node_zonelist(interleave_nid(*mpol, vma, addr,
-                                               HPAGE_SHIFT), gfp_flags);
+                               huge_page_shift(hstate_vma(vma))), gfp_flags);
        } else {
                zl = policy_zonelist(gfp_flags, *mpol);
                if ((*mpol)->mode == MPOL_BIND)
@@ -2220,9 +2220,12 @@ static void check_huge_range(struct vm_area_struct *vma,
 {
        unsigned long addr;
        struct page *page;
+       struct hstate *h = hstate_vma(vma);
+       unsigned long sz = huge_page_size(h);
 
-       for (addr = start; addr < end; addr += HPAGE_SIZE) {
-               pte_t *ptep = huge_pte_offset(vma->vm_mm, addr & HPAGE_MASK);
+       for (addr = start; addr < end; addr += sz) {
+               pte_t *ptep = huge_pte_offset(vma->vm_mm,
+                                               addr & huge_page_mask(h));
                pte_t pte;
 
                if (!ptep)
index 55bd355d170d055907c407f0c93d98dcb6e9e555..153572fb60b8debb24359e195e7a53b50f8e1c37 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/vmalloc.h>
 #include <linux/security.h>
 #include <linux/memcontrol.h>
+#include <linux/syscalls.h>
 
 #include "internal.h"
 
@@ -284,7 +285,15 @@ void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
 
        page = migration_entry_to_page(entry);
 
-       get_page(page);
+       /*
+        * Once radix-tree replacement of page migration started, page_count
+        * *must* be zero. And, we don't want to call wait_on_page_locked()
+        * against a page without get_page().
+        * So, we use get_page_unless_zero(), here. Even failed, page fault
+        * will occur again.
+        */
+       if (!get_page_unless_zero(page))
+               goto out;
        pte_unmap_unlock(ptep, ptl);
        wait_on_page_locked(page);
        put_page(page);
@@ -304,6 +313,7 @@ out:
 static int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page)
 {
+       int expected_count;
        void **pslot;
 
        if (!mapping) {
@@ -313,14 +323,20 @@ static int migrate_page_move_mapping(struct address_space *mapping,
                return 0;
        }
 
-       write_lock_irq(&mapping->tree_lock);
+       spin_lock_irq(&mapping->tree_lock);
 
        pslot = radix_tree_lookup_slot(&mapping->page_tree,
                                        page_index(page));
 
-       if (page_count(page) != 2 + !!PagePrivate(page) ||
+       expected_count = 2 + !!PagePrivate(page);
+       if (page_count(page) != expected_count ||
                        (struct page *)radix_tree_deref_slot(pslot) != page) {
-               write_unlock_irq(&mapping->tree_lock);
+               spin_unlock_irq(&mapping->tree_lock);
+               return -EAGAIN;
+       }
+
+       if (!page_freeze_refs(page, expected_count)) {
+               spin_unlock_irq(&mapping->tree_lock);
                return -EAGAIN;
        }
 
@@ -337,6 +353,7 @@ static int migrate_page_move_mapping(struct address_space *mapping,
 
        radix_tree_replace_slot(pslot, newpage);
 
+       page_unfreeze_refs(page, expected_count);
        /*
         * Drop cache reference from old page.
         * We know this isn't the last reference.
@@ -356,7 +373,9 @@ static int migrate_page_move_mapping(struct address_space *mapping,
        __dec_zone_page_state(page, NR_FILE_PAGES);
        __inc_zone_page_state(newpage, NR_FILE_PAGES);
 
-       write_unlock_irq(&mapping->tree_lock);
+       spin_unlock_irq(&mapping->tree_lock);
+       if (!PageSwapCache(newpage))
+               mem_cgroup_uncharge_cache_page(page);
 
        return 0;
 }
@@ -610,7 +629,6 @@ static int move_to_new_page(struct page *newpage, struct page *page)
                rc = fallback_migrate_page(mapping, newpage, page);
 
        if (!rc) {
-               mem_cgroup_page_migration(page, newpage);
                remove_migration_ptes(page, newpage);
        } else
                newpage->mapping = NULL;
@@ -640,6 +658,14 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
                /* page was freed from under us. So we are done. */
                goto move_newpage;
 
+       charge = mem_cgroup_prepare_migration(page, newpage);
+       if (charge == -ENOMEM) {
+               rc = -ENOMEM;
+               goto move_newpage;
+       }
+       /* prepare cgroup just returns 0 or -ENOMEM */
+       BUG_ON(charge);
+
        rc = -EAGAIN;
        if (TestSetPageLocked(page)) {
                if (!force)
@@ -691,19 +717,14 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
                goto rcu_unlock;
        }
 
-       charge = mem_cgroup_prepare_migration(page);
        /* Establish migration ptes or remove ptes */
        try_to_unmap(page, 1);
 
        if (!page_mapped(page))
                rc = move_to_new_page(newpage, page);
 
-       if (rc) {
+       if (rc)
                remove_migration_ptes(page, page);
-               if (charge)
-                       mem_cgroup_end_migration(page);
-       } else if (charge)
-               mem_cgroup_end_migration(newpage);
 rcu_unlock:
        if (rcu_locked)
                rcu_read_unlock();
@@ -724,6 +745,8 @@ unlock:
        }
 
 move_newpage:
+       if (!charge)
+               mem_cgroup_end_migration(newpage);
        /*
         * Move the new page to the LRU. If migration was not successful
         * then this will free the page.
@@ -1070,7 +1093,6 @@ out2:
        mmput(mm);
        return err;
 }
-#endif
 
 /*
  * Call migration functions in the vma_ops that may prepare
@@ -1092,3 +1114,4 @@ int migrate_vmas(struct mm_struct *mm, const nodemask_t *to,
        }
        return err;
 }
+#endif
diff --git a/mm/mm_init.c b/mm/mm_init.c
new file mode 100644 (file)
index 0000000..c6af41e
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * mm_init.c - Memory initialisation verification and debugging
+ *
+ * Copyright 2008 IBM Corporation, 2008
+ * Author Mel Gorman <mel@csn.ul.ie>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include "internal.h"
+
+#ifdef CONFIG_DEBUG_MEMORY_INIT
+int __meminitdata mminit_loglevel;
+
+/* The zonelists are simply reported, validation is manual. */
+void mminit_verify_zonelist(void)
+{
+       int nid;
+
+       if (mminit_loglevel < MMINIT_VERIFY)
+               return;
+
+       for_each_online_node(nid) {
+               pg_data_t *pgdat = NODE_DATA(nid);
+               struct zone *zone;
+               struct zoneref *z;
+               struct zonelist *zonelist;
+               int i, listid, zoneid;
+
+               BUG_ON(MAX_ZONELISTS > 2);
+               for (i = 0; i < MAX_ZONELISTS * MAX_NR_ZONES; i++) {
+
+                       /* Identify the zone and nodelist */
+                       zoneid = i % MAX_NR_ZONES;
+                       listid = i / MAX_NR_ZONES;
+                       zonelist = &pgdat->node_zonelists[listid];
+                       zone = &pgdat->node_zones[zoneid];
+                       if (!populated_zone(zone))
+                               continue;
+
+                       /* Print information about the zonelist */
+                       printk(KERN_DEBUG "mminit::zonelist %s %d:%s = ",
+                               listid > 0 ? "thisnode" : "general", nid,
+                               zone->name);
+
+                       /* Iterate the zonelist */
+                       for_each_zone_zonelist(zone, z, zonelist, zoneid) {
+#ifdef CONFIG_NUMA
+                               printk(KERN_CONT "%d:%s ",
+                                       zone->node, zone->name);
+#else
+                               printk(KERN_CONT "0:%s ", zone->name);
+#endif /* CONFIG_NUMA */
+                       }
+                       printk(KERN_CONT "\n");
+               }
+       }
+}
+
+void __init mminit_verify_pageflags_layout(void)
+{
+       int shift, width;
+       unsigned long or_mask, add_mask;
+
+       shift = 8 * sizeof(unsigned long);
+       width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH;
+       mminit_dprintk(MMINIT_TRACE, "pageflags_layout_widths",
+               "Section %d Node %d Zone %d Flags %d\n",
+               SECTIONS_WIDTH,
+               NODES_WIDTH,
+               ZONES_WIDTH,
+               NR_PAGEFLAGS);
+       mminit_dprintk(MMINIT_TRACE, "pageflags_layout_shifts",
+               "Section %d Node %d Zone %d\n",
+#ifdef SECTIONS_SHIFT
+               SECTIONS_SHIFT,
+#else
+               0,
+#endif
+               NODES_SHIFT,
+               ZONES_SHIFT);
+       mminit_dprintk(MMINIT_TRACE, "pageflags_layout_offsets",
+               "Section %lu Node %lu Zone %lu\n",
+               (unsigned long)SECTIONS_PGSHIFT,
+               (unsigned long)NODES_PGSHIFT,
+               (unsigned long)ZONES_PGSHIFT);
+       mminit_dprintk(MMINIT_TRACE, "pageflags_layout_zoneid",
+               "Zone ID: %lu -> %lu\n",
+               (unsigned long)ZONEID_PGOFF,
+               (unsigned long)(ZONEID_PGOFF + ZONEID_SHIFT));
+       mminit_dprintk(MMINIT_TRACE, "pageflags_layout_usage",
+               "location: %d -> %d unused %d -> %d flags %d -> %d\n",
+               shift, width, width, NR_PAGEFLAGS, NR_PAGEFLAGS, 0);
+#ifdef NODE_NOT_IN_PAGE_FLAGS
+       mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodeflags",
+               "Node not in page flags");
+#endif
+
+       if (SECTIONS_WIDTH) {
+               shift -= SECTIONS_WIDTH;
+               BUG_ON(shift != SECTIONS_PGSHIFT);
+       }
+       if (NODES_WIDTH) {
+               shift -= NODES_WIDTH;
+               BUG_ON(shift != NODES_PGSHIFT);
+       }
+       if (ZONES_WIDTH) {
+               shift -= ZONES_WIDTH;
+               BUG_ON(shift != ZONES_PGSHIFT);
+       }
+
+       /* Check for bitmask overlaps */
+       or_mask = (ZONES_MASK << ZONES_PGSHIFT) |
+                       (NODES_MASK << NODES_PGSHIFT) |
+                       (SECTIONS_MASK << SECTIONS_PGSHIFT);
+       add_mask = (ZONES_MASK << ZONES_PGSHIFT) +
+                       (NODES_MASK << NODES_PGSHIFT) +
+                       (SECTIONS_MASK << SECTIONS_PGSHIFT);
+       BUG_ON(or_mask != add_mask);
+}
+
+void __meminit mminit_verify_page_links(struct page *page, enum zone_type zone,
+                       unsigned long nid, unsigned long pfn)
+{
+       BUG_ON(page_to_nid(page) != nid);
+       BUG_ON(page_zonenum(page) != zone);
+       BUG_ON(page_to_pfn(page) != pfn);
+}
+
+static __init int set_mminit_loglevel(char *str)
+{
+       get_option(&str, &mminit_loglevel);
+       return 0;
+}
+early_param("mminit_loglevel", set_mminit_loglevel);
+#endif /* CONFIG_DEBUG_MEMORY_INIT */
+
+struct kobject *mm_kobj;
+EXPORT_SYMBOL_GPL(mm_kobj);
+
+static int __init mm_sysfs_init(void)
+{
+       mm_kobj = kobject_create_and_add("mm", kernel_kobj);
+       if (!mm_kobj)
+               return -ENOMEM;
+
+       return 0;
+}
+
+__initcall(mm_sysfs_init);
index 1d102b956fd88bec3ca95753909e1696799f659d..245c3d69067b7bc4c0b83ba2fa6a08df28bc7f9b 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
 #include <linux/mount.h>
 #include <linux/mempolicy.h>
 #include <linux/rmap.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/tlb.h>
 #include <asm/mmu_context.h>
 
+#include "internal.h"
+
 #ifndef arch_mmap_check
 #define arch_mmap_check(addr, len, flags)      (0)
 #endif
@@ -1108,6 +1111,9 @@ munmap_back:
        if (!may_expand_vm(mm, len >> PAGE_SHIFT))
                return -ENOMEM;
 
+       if (flags & MAP_NORESERVE)
+               vm_flags |= VM_NORESERVE;
+
        if (accountable && (!(flags & MAP_NORESERVE) ||
                            sysctl_overcommit_memory == OVERCOMMIT_NEVER)) {
                if (vm_flags & VM_SHARED) {
@@ -1763,7 +1769,7 @@ static void unmap_region(struct mm_struct *mm,
        update_hiwater_rss(mm);
        unmap_vmas(&tlb, vma, start, end, &nr_accounted, NULL);
        vm_unacct_memory(nr_accounted);
-       free_pgtables(&tlb, vma, prev? prev->vm_end: FIRST_USER_ADDRESS,
+       free_pgtables(tlb, vma, prev? prev->vm_end: FIRST_USER_ADDRESS,
                                 next? next->vm_start: 0);
        tlb_finish_mmu(tlb, start, end);
 }
@@ -1807,7 +1813,8 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
        struct mempolicy *pol;
        struct vm_area_struct *new;
 
-       if (is_vm_hugetlb_page(vma) && (addr & ~HPAGE_MASK))
+       if (is_vm_hugetlb_page(vma) && (addr &
+                                       ~(huge_page_mask(hstate_vma(vma)))))
                return -EINVAL;
 
        if (mm->map_count >= sysctl_max_map_count)
@@ -2055,6 +2062,7 @@ void exit_mmap(struct mm_struct *mm)
 
        /* mm's last user has gone, and its about to be pulled down */
        arch_exit_mmap(mm);
+       mmu_notifier_release(mm);
 
        lru_add_drain();
        flush_cache_mm(mm);
@@ -2063,7 +2071,7 @@ void exit_mmap(struct mm_struct *mm)
        /* Use -1 here to ensure all VMAs in the mm are unmapped */
        end = unmap_vmas(&tlb, vma, 0, -1, &nr_accounted, NULL);
        vm_unacct_memory(nr_accounted);
-       free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0);
+       free_pgtables(tlb, vma, FIRST_USER_ADDRESS, 0);
        tlb_finish_mmu(tlb, 0, end);
 
        /*
@@ -2262,3 +2270,161 @@ int install_special_mapping(struct mm_struct *mm,
 
        return 0;
 }
+
+static DEFINE_MUTEX(mm_all_locks_mutex);
+
+static void vm_lock_anon_vma(struct anon_vma *anon_vma)
+{
+       if (!test_bit(0, (unsigned long *) &anon_vma->head.next)) {
+               /*
+                * The LSB of head.next can't change from under us
+                * because we hold the mm_all_locks_mutex.
+                */
+               spin_lock(&anon_vma->lock);
+               /*
+                * We can safely modify head.next after taking the
+                * anon_vma->lock. If some other vma in this mm shares
+                * the same anon_vma we won't take it again.
+                *
+                * No need of atomic instructions here, head.next
+                * can't change from under us thanks to the
+                * anon_vma->lock.
+                */
+               if (__test_and_set_bit(0, (unsigned long *)
+                                      &anon_vma->head.next))
+                       BUG();
+       }
+}
+
+static void vm_lock_mapping(struct address_space *mapping)
+{
+       if (!test_bit(AS_MM_ALL_LOCKS, &mapping->flags)) {
+               /*
+                * AS_MM_ALL_LOCKS can't change from under us because
+                * we hold the mm_all_locks_mutex.
+                *
+                * Operations on ->flags have to be atomic because
+                * even if AS_MM_ALL_LOCKS is stable thanks to the
+                * mm_all_locks_mutex, there may be other cpus
+                * changing other bitflags in parallel to us.
+                */
+               if (test_and_set_bit(AS_MM_ALL_LOCKS, &mapping->flags))
+                       BUG();
+               spin_lock(&mapping->i_mmap_lock);
+       }
+}
+
+/*
+ * This operation locks against the VM for all pte/vma/mm related
+ * operations that could ever happen on a certain mm. This includes
+ * vmtruncate, try_to_unmap, and all page faults.
+ *
+ * The caller must take the mmap_sem in write mode before calling
+ * mm_take_all_locks(). The caller isn't allowed to release the
+ * mmap_sem until mm_drop_all_locks() returns.
+ *
+ * mmap_sem in write mode is required in order to block all operations
+ * that could modify pagetables and free pages without need of
+ * altering the vma layout (for example populate_range() with
+ * nonlinear vmas). It's also needed in write mode to avoid new
+ * anon_vmas to be associated with existing vmas.
+ *
+ * A single task can't take more than one mm_take_all_locks() in a row
+ * or it would deadlock.
+ *
+ * The LSB in anon_vma->head.next and the AS_MM_ALL_LOCKS bitflag in
+ * mapping->flags avoid to take the same lock twice, if more than one
+ * vma in this mm is backed by the same anon_vma or address_space.
+ *
+ * We can take all the locks in random order because the VM code
+ * taking i_mmap_lock or anon_vma->lock outside the mmap_sem never
+ * takes more than one of them in a row. Secondly we're protected
+ * against a concurrent mm_take_all_locks() by the mm_all_locks_mutex.
+ *
+ * mm_take_all_locks() and mm_drop_all_locks are expensive operations
+ * that may have to take thousand of locks.
+ *
+ * mm_take_all_locks() can fail if it's interrupted by signals.
+ */
+int mm_take_all_locks(struct mm_struct *mm)
+{
+       struct vm_area_struct *vma;
+       int ret = -EINTR;
+
+       BUG_ON(down_read_trylock(&mm->mmap_sem));
+
+       mutex_lock(&mm_all_locks_mutex);
+
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               if (signal_pending(current))
+                       goto out_unlock;
+               if (vma->anon_vma)
+                       vm_lock_anon_vma(vma->anon_vma);
+               if (vma->vm_file && vma->vm_file->f_mapping)
+                       vm_lock_mapping(vma->vm_file->f_mapping);
+       }
+       ret = 0;
+
+out_unlock:
+       if (ret)
+               mm_drop_all_locks(mm);
+
+       return ret;
+}
+
+static void vm_unlock_anon_vma(struct anon_vma *anon_vma)
+{
+       if (test_bit(0, (unsigned long *) &anon_vma->head.next)) {
+               /*
+                * The LSB of head.next can't change to 0 from under
+                * us because we hold the mm_all_locks_mutex.
+                *
+                * We must however clear the bitflag before unlocking
+                * the vma so the users using the anon_vma->head will
+                * never see our bitflag.
+                *
+                * No need of atomic instructions here, head.next
+                * can't change from under us until we release the
+                * anon_vma->lock.
+                */
+               if (!__test_and_clear_bit(0, (unsigned long *)
+                                         &anon_vma->head.next))
+                       BUG();
+               spin_unlock(&anon_vma->lock);
+       }
+}
+
+static void vm_unlock_mapping(struct address_space *mapping)
+{
+       if (test_bit(AS_MM_ALL_LOCKS, &mapping->flags)) {
+               /*
+                * AS_MM_ALL_LOCKS can't change to 0 from under us
+                * because we hold the mm_all_locks_mutex.
+                */
+               spin_unlock(&mapping->i_mmap_lock);
+               if (!test_and_clear_bit(AS_MM_ALL_LOCKS,
+                                       &mapping->flags))
+                       BUG();
+       }
+}
+
+/*
+ * The mmap_sem cannot be released by the caller until
+ * mm_drop_all_locks() returns.
+ */
+void mm_drop_all_locks(struct mm_struct *mm)
+{
+       struct vm_area_struct *vma;
+
+       BUG_ON(down_read_trylock(&mm->mmap_sem));
+       BUG_ON(!mutex_is_locked(&mm_all_locks_mutex));
+
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               if (vma->anon_vma)
+                       vm_unlock_anon_vma(vma->anon_vma);
+               if (vma->vm_file && vma->vm_file->f_mapping)
+                       vm_unlock_mapping(vma->vm_file->f_mapping);
+       }
+
+       mutex_unlock(&mm_all_locks_mutex);
+}
diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c
new file mode 100644 (file)
index 0000000..5f4ef02
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *  linux/mm/mmu_notifier.c
+ *
+ *  Copyright (C) 2008  Qumranet, Inc.
+ *  Copyright (C) 2008  SGI
+ *             Christoph Lameter <clameter@sgi.com>
+ *
+ *  This work is licensed under the terms of the GNU GPL, version 2. See
+ *  the COPYING file in the top-level directory.
+ */
+
+#include <linux/rculist.h>
+#include <linux/mmu_notifier.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/err.h>
+#include <linux/rcupdate.h>
+#include <linux/sched.h>
+
+/*
+ * This function can't run concurrently against mmu_notifier_register
+ * because mm->mm_users > 0 during mmu_notifier_register and exit_mmap
+ * runs with mm_users == 0. Other tasks may still invoke mmu notifiers
+ * in parallel despite there being no task using this mm any more,
+ * through the vmas outside of the exit_mmap context, such as with
+ * vmtruncate. This serializes against mmu_notifier_unregister with
+ * the mmu_notifier_mm->lock in addition to RCU and it serializes
+ * against the other mmu notifiers with RCU. struct mmu_notifier_mm
+ * can't go away from under us as exit_mmap holds an mm_count pin
+ * itself.
+ */
+void __mmu_notifier_release(struct mm_struct *mm)
+{
+       struct mmu_notifier *mn;
+
+       spin_lock(&mm->mmu_notifier_mm->lock);
+       while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) {
+               mn = hlist_entry(mm->mmu_notifier_mm->list.first,
+                                struct mmu_notifier,
+                                hlist);
+               /*
+                * We arrived before mmu_notifier_unregister so
+                * mmu_notifier_unregister will do nothing other than
+                * to wait ->release to finish and
+                * mmu_notifier_unregister to return.
+                */
+               hlist_del_init_rcu(&mn->hlist);
+               /*
+                * RCU here will block mmu_notifier_unregister until
+                * ->release returns.
+                */
+               rcu_read_lock();
+               spin_unlock(&mm->mmu_notifier_mm->lock);
+               /*
+                * if ->release runs before mmu_notifier_unregister it
+                * must be handled as it's the only way for the driver
+                * to flush all existing sptes and stop the driver
+                * from establishing any more sptes before all the
+                * pages in the mm are freed.
+                */
+               if (mn->ops->release)
+                       mn->ops->release(mn, mm);
+               rcu_read_unlock();
+               spin_lock(&mm->mmu_notifier_mm->lock);
+       }
+       spin_unlock(&mm->mmu_notifier_mm->lock);
+
+       /*
+        * synchronize_rcu here prevents mmu_notifier_release to
+        * return to exit_mmap (which would proceed freeing all pages
+        * in the mm) until the ->release method returns, if it was
+        * invoked by mmu_notifier_unregister.
+        *
+        * The mmu_notifier_mm can't go away from under us because one
+        * mm_count is hold by exit_mmap.
+        */
+       synchronize_rcu();
+}
+
+/*
+ * If no young bitflag is supported by the hardware, ->clear_flush_young can
+ * unmap the address and return 1 or 0 depending if the mapping previously
+ * existed or not.
+ */
+int __mmu_notifier_clear_flush_young(struct mm_struct *mm,
+                                       unsigned long address)
+{
+       struct mmu_notifier *mn;
+       struct hlist_node *n;
+       int young = 0;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
+               if (mn->ops->clear_flush_young)
+                       young |= mn->ops->clear_flush_young(mn, mm, address);
+       }
+       rcu_read_unlock();
+
+       return young;
+}
+
+void __mmu_notifier_invalidate_page(struct mm_struct *mm,
+                                         unsigned long address)
+{
+       struct mmu_notifier *mn;
+       struct hlist_node *n;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
+               if (mn->ops->invalidate_page)
+                       mn->ops->invalidate_page(mn, mm, address);
+       }
+       rcu_read_unlock();
+}
+
+void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end)
+{
+       struct mmu_notifier *mn;
+       struct hlist_node *n;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
+               if (mn->ops->invalidate_range_start)
+                       mn->ops->invalidate_range_start(mn, mm, start, end);
+       }
+       rcu_read_unlock();
+}
+
+void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end)
+{
+       struct mmu_notifier *mn;
+       struct hlist_node *n;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
+               if (mn->ops->invalidate_range_end)
+                       mn->ops->invalidate_range_end(mn, mm, start, end);
+       }
+       rcu_read_unlock();
+}
+
+static int do_mmu_notifier_register(struct mmu_notifier *mn,
+                                   struct mm_struct *mm,
+                                   int take_mmap_sem)
+{
+       struct mmu_notifier_mm *mmu_notifier_mm;
+       int ret;
+
+       BUG_ON(atomic_read(&mm->mm_users) <= 0);
+
+       ret = -ENOMEM;
+       mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL);
+       if (unlikely(!mmu_notifier_mm))
+               goto out;
+
+       if (take_mmap_sem)
+               down_write(&mm->mmap_sem);
+       ret = mm_take_all_locks(mm);
+       if (unlikely(ret))
+               goto out_cleanup;
+
+       if (!mm_has_notifiers(mm)) {
+               INIT_HLIST_HEAD(&mmu_notifier_mm->list);
+               spin_lock_init(&mmu_notifier_mm->lock);
+               mm->mmu_notifier_mm = mmu_notifier_mm;
+               mmu_notifier_mm = NULL;
+       }
+       atomic_inc(&mm->mm_count);
+
+       /*
+        * Serialize the update against mmu_notifier_unregister. A
+        * side note: mmu_notifier_release can't run concurrently with
+        * us because we hold the mm_users pin (either implicitly as
+        * current->mm or explicitly with get_task_mm() or similar).
+        * We can't race against any other mmu notifier method either
+        * thanks to mm_take_all_locks().
+        */
+       spin_lock(&mm->mmu_notifier_mm->lock);
+       hlist_add_head(&mn->hlist, &mm->mmu_notifier_mm->list);
+       spin_unlock(&mm->mmu_notifier_mm->lock);
+
+       mm_drop_all_locks(mm);
+out_cleanup:
+       if (take_mmap_sem)
+               up_write(&mm->mmap_sem);
+       /* kfree() does nothing if mmu_notifier_mm is NULL */
+       kfree(mmu_notifier_mm);
+out:
+       BUG_ON(atomic_read(&mm->mm_users) <= 0);
+       return ret;
+}
+
+/*
+ * Must not hold mmap_sem nor any other VM related lock when calling
+ * this registration function. Must also ensure mm_users can't go down
+ * to zero while this runs to avoid races with mmu_notifier_release,
+ * so mm has to be current->mm or the mm should be pinned safely such
+ * as with get_task_mm(). If the mm is not current->mm, the mm_users
+ * pin should be released by calling mmput after mmu_notifier_register
+ * returns. mmu_notifier_unregister must be always called to
+ * unregister the notifier. mm_count is automatically pinned to allow
+ * mmu_notifier_unregister to safely run at any time later, before or
+ * after exit_mmap. ->release will always be called before exit_mmap
+ * frees the pages.
+ */
+int mmu_notifier_register(struct mmu_notifier *mn, struct mm_struct *mm)
+{
+       return do_mmu_notifier_register(mn, mm, 1);
+}
+EXPORT_SYMBOL_GPL(mmu_notifier_register);
+
+/*
+ * Same as mmu_notifier_register but here the caller must hold the
+ * mmap_sem in write mode.
+ */
+int __mmu_notifier_register(struct mmu_notifier *mn, struct mm_struct *mm)
+{
+       return do_mmu_notifier_register(mn, mm, 0);
+}
+EXPORT_SYMBOL_GPL(__mmu_notifier_register);
+
+/* this is called after the last mmu_notifier_unregister() returned */
+void __mmu_notifier_mm_destroy(struct mm_struct *mm)
+{
+       BUG_ON(!hlist_empty(&mm->mmu_notifier_mm->list));
+       kfree(mm->mmu_notifier_mm);
+       mm->mmu_notifier_mm = LIST_POISON1; /* debug */
+}
+
+/*
+ * This releases the mm_count pin automatically and frees the mm
+ * structure if it was the last user of it. It serializes against
+ * running mmu notifiers with RCU and against mmu_notifier_unregister
+ * with the unregister lock + RCU. All sptes must be dropped before
+ * calling mmu_notifier_unregister. ->release or any other notifier
+ * method may be invoked concurrently with mmu_notifier_unregister,
+ * and only after mmu_notifier_unregister returned we're guaranteed
+ * that ->release or any other method can't run anymore.
+ */
+void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm)
+{
+       BUG_ON(atomic_read(&mm->mm_count) <= 0);
+
+       spin_lock(&mm->mmu_notifier_mm->lock);
+       if (!hlist_unhashed(&mn->hlist)) {
+               hlist_del_rcu(&mn->hlist);
+
+               /*
+                * RCU here will force exit_mmap to wait ->release to finish
+                * before freeing the pages.
+                */
+               rcu_read_lock();
+               spin_unlock(&mm->mmu_notifier_mm->lock);
+               /*
+                * exit_mmap will block in mmu_notifier_release to
+                * guarantee ->release is called before freeing the
+                * pages.
+                */
+               if (mn->ops->release)
+                       mn->ops->release(mn, mm);
+               rcu_read_unlock();
+       } else
+               spin_unlock(&mm->mmu_notifier_mm->lock);
+
+       /*
+        * Wait any running method to finish, of course including
+        * ->release if it was run by mmu_notifier_relase instead of us.
+        */
+       synchronize_rcu();
+
+       BUG_ON(atomic_read(&mm->mm_count) <= 0);
+
+       mmdrop(mm);
+}
+EXPORT_SYMBOL_GPL(mmu_notifier_unregister);
index 360d9cc8b38c061185d562fc40b7f032ae34d21d..fded06f923f4b939d75f745225b38b8e41e8ee08 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/syscalls.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
+#include <linux/mmu_notifier.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
@@ -153,12 +154,10 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
         * If we make a private mapping writable we increase our commit;
         * but (without finer accounting) cannot reduce our commit if we
         * make it unwritable again.
-        *
-        * FIXME? We haven't defined a VM_NORESERVE flag, so mprotecting
-        * a MAP_NORESERVE private mapping to writable will now reserve.
         */
        if (newflags & VM_WRITE) {
-               if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED))) {
+               if (!(oldflags & (VM_ACCOUNT|VM_WRITE|
+                                               VM_SHARED|VM_NORESERVE))) {
                        charged = nrpages;
                        if (security_vm_enough_memory(charged))
                                return -ENOMEM;
@@ -205,10 +204,12 @@ success:
                dirty_accountable = 1;
        }
 
+       mmu_notifier_invalidate_range_start(mm, start, end);
        if (is_vm_hugetlb_page(vma))
                hugetlb_change_protection(vma, start, end, vma->vm_page_prot);
        else
                change_protection(vma, start, end, vma->vm_page_prot, dirty_accountable);
+       mmu_notifier_invalidate_range_end(mm, start, end);
        vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
        vm_stat_account(mm, newflags, vma->vm_file, nrpages);
        return 0;
index 08e3c7f2bd15a1b2e502aeb3e9f509148cb5dfa8..1a7743923c8c42c536d79ecb64f45457b2a3f994 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/highmem.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
@@ -74,7 +75,11 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
        struct mm_struct *mm = vma->vm_mm;
        pte_t *old_pte, *new_pte, pte;
        spinlock_t *old_ptl, *new_ptl;
+       unsigned long old_start;
 
+       old_start = old_addr;
+       mmu_notifier_invalidate_range_start(vma->vm_mm,
+                                           old_start, old_end);
        if (vma->vm_file) {
                /*
                 * Subtle point from Rajesh Venkatasubramanian: before
@@ -116,6 +121,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
        pte_unmap_unlock(old_pte - 1, old_ptl);
        if (mapping)
                spin_unlock(&mapping->i_mmap_lock);
+       mmu_notifier_invalidate_range_end(vma->vm_mm, old_start, old_end);
 }
 
 #define LATENCY_LIMIT  (64 * PAGE_SIZE)
index 4462b6a3fcb984e9bd37a69ef7d377f0b5dd2367..5edccd9c9218cda91a4298d587737e88db29f2c0 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/mount.h>
@@ -745,7 +745,7 @@ static unsigned long determine_vm_flags(struct file *file,
         * it's being traced - otherwise breakpoints set in it may interfere
         * with another untraced process
         */
-       if ((flags & MAP_PRIVATE) && (current->ptrace & PT_PTRACED))
+       if ((flags & MAP_PRIVATE) && tracehook_expect_breakpoints(current))
                vm_flags &= ~VM_MAYSHARE;
 
        return vm_flags;
index 94c6d8988ab3239019ecc720b7ac0624e06016df..24de8b65fdbd1f3cd26fafe888277401125c7bc9 100644 (file)
@@ -1088,7 +1088,7 @@ int __set_page_dirty_nobuffers(struct page *page)
                if (!mapping)
                        return 1;
 
-               write_lock_irq(&mapping->tree_lock);
+               spin_lock_irq(&mapping->tree_lock);
                mapping2 = page_mapping(page);
                if (mapping2) { /* Race with truncate? */
                        BUG_ON(mapping2 != mapping);
@@ -1102,7 +1102,7 @@ int __set_page_dirty_nobuffers(struct page *page)
                        radix_tree_tag_set(&mapping->page_tree,
                                page_index(page), PAGECACHE_TAG_DIRTY);
                }
-               write_unlock_irq(&mapping->tree_lock);
+               spin_unlock_irq(&mapping->tree_lock);
                if (mapping->host) {
                        /* !PageAnon && !swapper_space */
                        __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
@@ -1258,7 +1258,7 @@ int test_clear_page_writeback(struct page *page)
                struct backing_dev_info *bdi = mapping->backing_dev_info;
                unsigned long flags;
 
-               write_lock_irqsave(&mapping->tree_lock, flags);
+               spin_lock_irqsave(&mapping->tree_lock, flags);
                ret = TestClearPageWriteback(page);
                if (ret) {
                        radix_tree_tag_clear(&mapping->page_tree,
@@ -1269,7 +1269,7 @@ int test_clear_page_writeback(struct page *page)
                                __bdi_writeout_inc(bdi);
                        }
                }
-               write_unlock_irqrestore(&mapping->tree_lock, flags);
+               spin_unlock_irqrestore(&mapping->tree_lock, flags);
        } else {
                ret = TestClearPageWriteback(page);
        }
@@ -1287,7 +1287,7 @@ int test_set_page_writeback(struct page *page)
                struct backing_dev_info *bdi = mapping->backing_dev_info;
                unsigned long flags;
 
-               write_lock_irqsave(&mapping->tree_lock, flags);
+               spin_lock_irqsave(&mapping->tree_lock, flags);
                ret = TestSetPageWriteback(page);
                if (!ret) {
                        radix_tree_tag_set(&mapping->page_tree,
@@ -1300,7 +1300,7 @@ int test_set_page_writeback(struct page *page)
                        radix_tree_tag_clear(&mapping->page_tree,
                                                page_index(page),
                                                PAGECACHE_TAG_DIRTY);
-               write_unlock_irqrestore(&mapping->tree_lock, flags);
+               spin_unlock_irqrestore(&mapping->tree_lock, flags);
        } else {
                ret = TestSetPageWriteback(page);
        }
index 79ac4afc908cff9ed4b7220e4fd9851955d73783..3cf3d05b6bd482767c71265ee3b9ad0d16ad9c7e 100644 (file)
@@ -153,9 +153,9 @@ static unsigned long __meminitdata dma_reserve;
   static unsigned long __meminitdata node_boundary_start_pfn[MAX_NUMNODES];
   static unsigned long __meminitdata node_boundary_end_pfn[MAX_NUMNODES];
 #endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
-  unsigned long __initdata required_kernelcore;
+  static unsigned long __initdata required_kernelcore;
   static unsigned long __initdata required_movablecore;
-  unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
+  static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
 
   /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
   int movable_zone;
@@ -264,7 +264,7 @@ static void free_compound_page(struct page *page)
        __free_pages_ok(page, compound_order(page));
 }
 
-static void prep_compound_page(struct page *page, unsigned long order)
+void prep_compound_page(struct page *page, unsigned long order)
 {
        int i;
        int nr_pages = 1 << order;
@@ -432,8 +432,9 @@ static inline void __free_one_page(struct page *page,
 
                buddy = __page_find_buddy(page, page_idx, order);
                if (!page_is_buddy(page, buddy, order))
-                       break;          /* Move the buddy up one level. */
+                       break;
 
+               /* Our buddy is free, merge with it and move up one order. */
                list_del(&buddy->lru);
                zone->free_area[order].nr_free--;
                rmv_page_order(buddy);
@@ -532,7 +533,7 @@ static void __free_pages_ok(struct page *page, unsigned int order)
 /*
  * permit the bootmem allocator to evade page validation on high-order frees
  */
-void __free_pages_bootmem(struct page *page, unsigned int order)
+void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
 {
        if (order == 0) {
                __ClearPageReserved(page);
@@ -673,9 +674,9 @@ static int fallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = {
  * Note that start_page and end_pages are not aligned on a pageblock
  * boundary. If alignment is required, use move_freepages_block()
  */
-int move_freepages(struct zone *zone,
-                       struct page *start_page, struct page *end_page,
-                       int migratetype)
+static int move_freepages(struct zone *zone,
+                         struct page *start_page, struct page *end_page,
+                         int migratetype)
 {
        struct page *page;
        unsigned long order;
@@ -714,7 +715,8 @@ int move_freepages(struct zone *zone,
        return pages_moved;
 }
 
-int move_freepages_block(struct zone *zone, struct page *page, int migratetype)
+static int move_freepages_block(struct zone *zone, struct page *page,
+                               int migratetype)
 {
        unsigned long start_pfn, end_pfn;
        struct page *start_page, *end_page;
@@ -1429,7 +1431,7 @@ try_next_zone:
 /*
  * This is the 'heart' of the zoned buddy allocator.
  */
-static struct page *
+struct page *
 __alloc_pages_internal(gfp_t gfp_mask, unsigned int order,
                        struct zonelist *zonelist, nodemask_t *nodemask)
 {
@@ -1632,22 +1634,7 @@ nopage:
 got_pg:
        return page;
 }
-
-struct page *
-__alloc_pages(gfp_t gfp_mask, unsigned int order,
-               struct zonelist *zonelist)
-{
-       return __alloc_pages_internal(gfp_mask, order, zonelist, NULL);
-}
-
-struct page *
-__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
-               struct zonelist *zonelist, nodemask_t *nodemask)
-{
-       return __alloc_pages_internal(gfp_mask, order, zonelist, nodemask);
-}
-
-EXPORT_SYMBOL(__alloc_pages);
+EXPORT_SYMBOL(__alloc_pages_internal);
 
 /*
  * Common helper functions.
@@ -1711,6 +1698,59 @@ void free_pages(unsigned long addr, unsigned int order)
 
 EXPORT_SYMBOL(free_pages);
 
+/**
+ * alloc_pages_exact - allocate an exact number physically-contiguous pages.
+ * @size: the number of bytes to allocate
+ * @gfp_mask: GFP flags for the allocation
+ *
+ * This function is similar to alloc_pages(), except that it allocates the
+ * minimum number of pages to satisfy the request.  alloc_pages() can only
+ * allocate memory in power-of-two pages.
+ *
+ * This function is also limited by MAX_ORDER.
+ *
+ * Memory allocated by this function must be released by free_pages_exact().
+ */
+void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
+{
+       unsigned int order = get_order(size);
+       unsigned long addr;
+
+       addr = __get_free_pages(gfp_mask, order);
+       if (addr) {
+               unsigned long alloc_end = addr + (PAGE_SIZE << order);
+               unsigned long used = addr + PAGE_ALIGN(size);
+
+               split_page(virt_to_page(addr), order);
+               while (used < alloc_end) {
+                       free_page(used);
+                       used += PAGE_SIZE;
+               }
+       }
+
+       return (void *)addr;
+}
+EXPORT_SYMBOL(alloc_pages_exact);
+
+/**
+ * free_pages_exact - release memory allocated via alloc_pages_exact()
+ * @virt: the value returned by alloc_pages_exact.
+ * @size: size of allocation, same value as passed to alloc_pages_exact().
+ *
+ * Release the memory allocated by a previous call to alloc_pages_exact.
+ */
+void free_pages_exact(void *virt, size_t size)
+{
+       unsigned long addr = (unsigned long)virt;
+       unsigned long end = addr + PAGE_ALIGN(size);
+
+       while (addr < end) {
+               free_page(addr);
+               addr += PAGE_SIZE;
+       }
+}
+EXPORT_SYMBOL(free_pages_exact);
+
 static unsigned int nr_free_zone_pages(int offset)
 {
        struct zoneref *z;
@@ -2332,7 +2372,7 @@ static void build_zonelist_cache(pg_data_t *pgdat)
 
 #endif /* CONFIG_NUMA */
 
-/* return values int ....just for stop_machine_run() */
+/* return values int ....just for stop_machine() */
 static int __build_all_zonelists(void *dummy)
 {
        int nid;
@@ -2352,11 +2392,12 @@ void build_all_zonelists(void)
 
        if (system_state == SYSTEM_BOOTING) {
                __build_all_zonelists(NULL);
+               mminit_verify_zonelist();
                cpuset_init_current_mems_allowed();
        } else {
                /* we have to stop all cpus to guarantee there is no user
                   of zonelist */
-               stop_machine_run(__build_all_zonelists, NULL, NR_CPUS);
+               stop_machine(__build_all_zonelists, NULL, NULL);
                /* cpuset refresh routine should be here */
        }
        vm_total_pages = nr_free_pagecache_pages();
@@ -2534,6 +2575,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                }
                page = pfn_to_page(pfn);
                set_page_links(page, zone, nid, pfn);
+               mminit_verify_page_links(page, zone, nid, pfn);
                init_page_count(page);
                reset_page_mapcount(page);
                SetPageReserved(page);
@@ -2611,7 +2653,7 @@ static int zone_batchsize(struct zone *zone)
        return batch;
 }
 
-inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
+static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
 {
        struct per_cpu_pages *pcp;
 
@@ -2836,6 +2878,12 @@ __meminit int init_currently_empty_zone(struct zone *zone,
 
        zone->zone_start_pfn = zone_start_pfn;
 
+       mminit_dprintk(MMINIT_TRACE, "memmap_init",
+                       "Initialising map node %d zone %lu pfns %lu -> %lu\n",
+                       pgdat->node_id,
+                       (unsigned long)zone_idx(zone),
+                       zone_start_pfn, (zone_start_pfn + size));
+
        zone_init_free_lists(zone);
 
        return 0;
@@ -2975,7 +3023,8 @@ void __init sparse_memory_present_with_active_regions(int nid)
 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",
+       mminit_dprintk(MMINIT_TRACE, "zoneboundary",
+                       "Entering push_node_boundaries(%u, %lu, %lu)\n",
                        nid, start_pfn, end_pfn);
 
        /* Initialise the boundary for this node if necessary */
@@ -2993,7 +3042,8 @@ void __init push_node_boundaries(unsigned int nid,
 static void __meminit 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",
+       mminit_dprintk(MMINIT_TRACE, "zoneboundary",
+                       "Entering account_node_boundary(%u, %lu, %lu)\n",
                        nid, *start_pfn, *end_pfn);
 
        /* Return if boundary information has not been provided */
@@ -3050,7 +3100,7 @@ void __meminit get_pfn_range_for_nid(unsigned int nid,
  * assumption is made that zones within a node are ordered in monotonic
  * increasing memory addresses so that the "highest" populated zone is used
  */
-void __init find_usable_zone_for_movable(void)
+static void __init find_usable_zone_for_movable(void)
 {
        int zone_index;
        for (zone_index = MAX_NR_ZONES - 1; zone_index >= 0; zone_index--) {
@@ -3076,7 +3126,7 @@ void __init find_usable_zone_for_movable(void)
  * highest usable zone for ZONE_MOVABLE. This preserves the assumption that
  * zones within a node are in order of monotonic increases memory addresses
  */
-void __meminit adjust_zone_range_for_zone_movable(int nid,
+static void __meminit adjust_zone_range_for_zone_movable(int nid,
                                        unsigned long zone_type,
                                        unsigned long node_start_pfn,
                                        unsigned long node_end_pfn,
@@ -3137,7 +3187,7 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
  * Return the number of holes in a range on a node. If nid is MAX_NUMNODES,
  * then all holes in the requested range will be accounted for.
  */
-unsigned long __meminit __absent_pages_in_range(int nid,
+static unsigned long __meminit __absent_pages_in_range(int nid,
                                unsigned long range_start_pfn,
                                unsigned long range_end_pfn)
 {
@@ -3368,8 +3418,8 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                        PAGE_ALIGN(size * sizeof(struct page)) >> PAGE_SHIFT;
                if (realsize >= memmap_pages) {
                        realsize -= memmap_pages;
-                       printk(KERN_DEBUG
-                               "  %s zone: %lu pages used for memmap\n",
+                       mminit_dprintk(MMINIT_TRACE, "memmap_init",
+                               "%s zone: %lu pages used for memmap\n",
                                zone_names[j], memmap_pages);
                } else
                        printk(KERN_WARNING
@@ -3379,7 +3429,8 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                /* Account for reserved pages */
                if (j == 0 && realsize > dma_reserve) {
                        realsize -= dma_reserve;
-                       printk(KERN_DEBUG "  %s zone: %lu pages reserved\n",
+                       mminit_dprintk(MMINIT_TRACE, "memmap_init",
+                                       "%s zone: %lu pages reserved\n",
                                        zone_names[0], dma_reserve);
                }
 
@@ -3464,10 +3515,11 @@ static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)
 #endif /* CONFIG_FLAT_NODE_MEM_MAP */
 }
 
-void __paginginit free_area_init_node(int nid, struct pglist_data *pgdat,
-               unsigned long *zones_size, unsigned long node_start_pfn,
-               unsigned long *zholes_size)
+void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
+               unsigned long node_start_pfn, unsigned long *zholes_size)
 {
+       pg_data_t *pgdat = NODE_DATA(nid);
+
        pgdat->node_id = nid;
        pgdat->node_start_pfn = node_start_pfn;
        calculate_node_totalpages(pgdat, zones_size, zholes_size);
@@ -3520,10 +3572,13 @@ void __init add_active_range(unsigned int nid, unsigned long start_pfn,
 {
        int i;
 
-       printk(KERN_DEBUG "Entering add_active_range(%d, %#lx, %#lx) "
-                         "%d entries of %d used\n",
-                         nid, start_pfn, end_pfn,
-                         nr_nodemap_entries, MAX_ACTIVE_REGIONS);
+       mminit_dprintk(MMINIT_TRACE, "memory_register",
+                       "Entering add_active_range(%d, %#lx, %#lx) "
+                       "%d entries of %d used\n",
+                       nid, start_pfn, end_pfn,
+                       nr_nodemap_entries, MAX_ACTIVE_REGIONS);
+
+       mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
 
        /* Merge with existing active regions if possible */
        for (i = 0; i < nr_nodemap_entries; i++) {
@@ -3669,7 +3724,7 @@ static void __init sort_node_map(void)
 }
 
 /* Find the lowest pfn for a node */
-unsigned long __init find_min_pfn_for_node(int nid)
+static unsigned long __init find_min_pfn_for_node(int nid)
 {
        int i;
        unsigned long min_pfn = ULONG_MAX;
@@ -3741,7 +3796,7 @@ static unsigned long __init early_calculate_totalpages(void)
  * memory. When they don't, some nodes will have more kernelcore than
  * others
  */
-void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
+static void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
 {
        int i, nid;
        unsigned long usable_startpfn;
@@ -3957,10 +4012,11 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
                                                early_node_map[i].end_pfn);
 
        /* Initialise every node */
+       mminit_verify_pageflags_layout();
        setup_nr_node_ids();
        for_each_online_node(nid) {
                pg_data_t *pgdat = NODE_DATA(nid);
-               free_area_init_node(nid, pgdat, NULL,
+               free_area_init_node(nid, NULL,
                                find_min_pfn_for_node(nid), NULL);
 
                /* Any memory on that node */
@@ -4025,15 +4081,13 @@ void __init set_dma_reserve(unsigned long 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 };
-
+struct pglist_data contig_page_data = { .bdata = &bootmem_node_data[0] };
 EXPORT_SYMBOL(contig_page_data);
 #endif
 
 void __init free_area_init(unsigned long *zones_size)
 {
-       free_area_init_node(0, NODE_DATA(0), zones_size,
+       free_area_init_node(0, zones_size,
                        __pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL);
 }
 
index 9d834aa4b9795264d87eef283c2492a99d67597b..0cbe0c60c6bff39d60f0f3994258de7931d6dd4d 100644 (file)
@@ -130,7 +130,7 @@ static int __pdflush(struct pdflush_work *my_work)
                 * Thread creation: For how long have there been zero
                 * available threads?
                 */
-               if (jiffies - last_empty_jifs > 1 * HZ) {
+               if (time_after(jiffies, last_empty_jifs + 1 * HZ)) {
                        /* unlocked list_empty() test is OK here */
                        if (list_empty(&pdflush_list)) {
                                /* unlocked test is OK here */
@@ -151,7 +151,7 @@ static int __pdflush(struct pdflush_work *my_work)
                if (nr_pdflush_threads <= MIN_PDFLUSH_THREADS)
                        continue;
                pdf = list_entry(pdflush_list.prev, struct pdflush_work, list);
-               if (jiffies - pdf->when_i_went_to_sleep > 1 * HZ) {
+               if (time_after(jiffies, pdf->when_i_went_to_sleep + 1 * HZ)) {
                        /* Limit exit rate */
                        pdf->when_i_went_to_sleep = jiffies;
                        break;                                  /* exeunt */
index d8723a5f6496d05af23445e6ae862754e9d41214..77e8ddf945e9a725d4b675923124f4eafd0924e2 100644 (file)
@@ -382,9 +382,9 @@ ondemand_readahead(struct address_space *mapping,
        if (hit_readahead_marker) {
                pgoff_t start;
 
-               read_lock_irq(&mapping->tree_lock);
-               start = radix_tree_next_hole(&mapping->page_tree, offset, max+1);
-               read_unlock_irq(&mapping->tree_lock);
+               rcu_read_lock();
+               start = radix_tree_next_hole(&mapping->page_tree, offset,max+1);
+               rcu_read_unlock();
 
                if (!start || start - offset > max)
                        return 0;
index bf0a5b7cfb8e7a97369271ed235a714bd11dfd12..99bc3f9cd796f34a58ec1d61798c27c583a0eaf3 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -49,6 +49,7 @@
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/memcontrol.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/tlbflush.h>
 
@@ -138,7 +139,7 @@ void anon_vma_unlink(struct vm_area_struct *vma)
                anon_vma_free(anon_vma);
 }
 
-static void anon_vma_ctor(struct kmem_cache *cachep, void *data)
+static void anon_vma_ctor(void *data)
 {
        struct anon_vma *anon_vma = data;
 
@@ -287,7 +288,7 @@ static int page_referenced_one(struct page *page,
        if (vma->vm_flags & VM_LOCKED) {
                referenced++;
                *mapcount = 1;  /* break early from loop */
-       } else if (ptep_clear_flush_young(vma, address, pte))
+       } else if (ptep_clear_flush_young_notify(vma, address, pte))
                referenced++;
 
        /* Pretend the page is referenced if the task has the
@@ -457,7 +458,7 @@ static int page_mkclean_one(struct page *page, struct vm_area_struct *vma)
                pte_t entry;
 
                flush_cache_page(vma, address, pte_pfn(*pte));
-               entry = ptep_clear_flush(vma, address, pte);
+               entry = ptep_clear_flush_notify(vma, address, pte);
                entry = pte_wrprotect(entry);
                entry = pte_mkclean(entry);
                set_pte_at(mm, address, pte, entry);
@@ -576,14 +577,8 @@ void page_add_anon_rmap(struct page *page,
        VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end);
        if (atomic_inc_and_test(&page->_mapcount))
                __page_set_anon_rmap(page, vma, address);
-       else {
+       else
                __page_check_anon_rmap(page, vma, address);
-               /*
-                * We unconditionally charged during prepare, we uncharge here
-                * This takes care of balancing the reference counts
-                */
-               mem_cgroup_uncharge_page(page);
-       }
 }
 
 /**
@@ -614,12 +609,6 @@ void page_add_file_rmap(struct page *page)
 {
        if (atomic_inc_and_test(&page->_mapcount))
                __inc_zone_page_state(page, NR_FILE_MAPPED);
-       else
-               /*
-                * We unconditionally charged during prepare, we uncharge here
-                * This takes care of balancing the reference counts
-                */
-               mem_cgroup_uncharge_page(page);
 }
 
 #ifdef CONFIG_DEBUG_VM
@@ -717,14 +706,14 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
         * skipped over this mm) then we should reactivate it.
         */
        if (!migration && ((vma->vm_flags & VM_LOCKED) ||
-                       (ptep_clear_flush_young(vma, address, pte)))) {
+                       (ptep_clear_flush_young_notify(vma, address, pte)))) {
                ret = SWAP_FAIL;
                goto out_unmap;
        }
 
        /* Nuke the page table entry. */
        flush_cache_page(vma, address, page_to_pfn(page));
-       pteval = ptep_clear_flush(vma, address, pte);
+       pteval = ptep_clear_flush_notify(vma, address, pte);
 
        /* Move the dirty bit to the physical page now the pte is gone. */
        if (pte_dirty(pteval))
@@ -849,12 +838,12 @@ static void try_to_unmap_cluster(unsigned long cursor,
                page = vm_normal_page(vma, address, *pte);
                BUG_ON(!page || PageAnon(page));
 
-               if (ptep_clear_flush_young(vma, address, pte))
+               if (ptep_clear_flush_young_notify(vma, address, pte))
                        continue;
 
                /* Nuke the page table entry. */
                flush_cache_page(vma, address, pte_pfn(*pte));
-               pteval = ptep_clear_flush(vma, address, pte);
+               pteval = ptep_clear_flush_notify(vma, address, pte);
 
                /* If nonlinear, store the file page offset in the pte. */
                if (page->index != linear_page_index(vma, address))
index e2a6ae1a44e9a5e8b5e6594d11f76b11a02ea49f..c1e5a3b4f7583087d4f2558f96b1992bc2508696 100644 (file)
@@ -922,20 +922,26 @@ found:
        error = 1;
        if (!inode)
                goto out;
-       /* Precharge page while we can wait, compensate afterwards */
+       /* Precharge page using GFP_KERNEL while we can wait */
        error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
        if (error)
                goto out;
        error = radix_tree_preload(GFP_KERNEL);
-       if (error)
-               goto uncharge;
+       if (error) {
+               mem_cgroup_uncharge_cache_page(page);
+               goto out;
+       }
        error = 1;
 
        spin_lock(&info->lock);
        ptr = shmem_swp_entry(info, idx, NULL);
-       if (ptr && ptr->val == entry.val)
-               error = add_to_page_cache(page, inode->i_mapping,
+       if (ptr && ptr->val == entry.val) {
+               error = add_to_page_cache_locked(page, inode->i_mapping,
                                                idx, GFP_NOWAIT);
+               /* does mem_cgroup_uncharge_cache_page on error */
+       } else  /* we must compensate for our precharge above */
+               mem_cgroup_uncharge_cache_page(page);
+
        if (error == -EEXIST) {
                struct page *filepage = find_get_page(inode->i_mapping, idx);
                error = 1;
@@ -961,8 +967,6 @@ found:
                shmem_swp_unmap(ptr);
        spin_unlock(&info->lock);
        radix_tree_preload_end();
-uncharge:
-       mem_cgroup_uncharge_page(page);
 out:
        unlock_page(page);
        page_cache_release(page);
@@ -1297,8 +1301,8 @@ repeat:
                        SetPageUptodate(filepage);
                        set_page_dirty(filepage);
                        swap_free(swap);
-               } else if (!(error = add_to_page_cache(
-                               swappage, mapping, idx, GFP_NOWAIT))) {
+               } else if (!(error = add_to_page_cache_locked(swappage, mapping,
+                                       idx, GFP_NOWAIT))) {
                        info->flags |= SHMEM_PAGEIN;
                        shmem_swp_set(info, entry, 0);
                        shmem_swp_unmap(entry);
@@ -1311,17 +1315,14 @@ repeat:
                        shmem_swp_unmap(entry);
                        spin_unlock(&info->lock);
                        unlock_page(swappage);
+                       page_cache_release(swappage);
                        if (error == -ENOMEM) {
                                /* allow reclaim from this memory cgroup */
-                               error = mem_cgroup_cache_charge(swappage,
-                                       current->mm, gfp & ~__GFP_HIGHMEM);
-                               if (error) {
-                                       page_cache_release(swappage);
+                               error = mem_cgroup_shrink_usage(current->mm,
+                                                               gfp);
+                               if (error)
                                        goto failed;
-                               }
-                               mem_cgroup_uncharge_page(swappage);
                        }
-                       page_cache_release(swappage);
                        goto repeat;
                }
        } else if (sgp == SGP_READ && !filepage) {
@@ -1358,6 +1359,8 @@ repeat:
                }
 
                if (!filepage) {
+                       int ret;
+
                        spin_unlock(&info->lock);
                        filepage = shmem_alloc_page(gfp, info, idx);
                        if (!filepage) {
@@ -1386,10 +1389,18 @@ repeat:
                                swap = *entry;
                                shmem_swp_unmap(entry);
                        }
-                       if (error || swap.val || 0 != add_to_page_cache_lru(
-                                       filepage, mapping, idx, GFP_NOWAIT)) {
+                       ret = error || swap.val;
+                       if (ret)
+                               mem_cgroup_uncharge_cache_page(filepage);
+                       else
+                               ret = add_to_page_cache_lru(filepage, mapping,
+                                               idx, GFP_NOWAIT);
+                       /*
+                        * At add_to_page_cache_lru() failure, uncharge will
+                        * be done automatically.
+                        */
+                       if (ret) {
                                spin_unlock(&info->lock);
-                               mem_cgroup_uncharge_page(filepage);
                                page_cache_release(filepage);
                                shmem_unacct_blocks(info->flags, 1);
                                shmem_free_blocks(inode, 1);
@@ -1398,7 +1409,6 @@ repeat:
                                        goto failed;
                                goto repeat;
                        }
-                       mem_cgroup_uncharge_page(filepage);
                        info->flags |= SHMEM_PAGEIN;
                }
 
@@ -1503,7 +1513,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
                inode->i_blocks = 0;
-               inode->i_mapping->a_ops = &shmem_aops;
                inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inode->i_generation = get_seconds();
@@ -1518,6 +1527,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
                        init_special_inode(inode, mode, dev);
                        break;
                case S_IFREG:
+                       inode->i_mapping->a_ops = &shmem_aops;
                        inode->i_op = &shmem_inode_operations;
                        inode->i_fop = &shmem_file_operations;
                        mpol_shared_policy_init(&info->policy,
@@ -1690,26 +1700,38 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
        file_accessed(filp);
 }
 
-static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
+static ssize_t shmem_file_aio_read(struct kiocb *iocb,
+               const struct iovec *iov, unsigned long nr_segs, loff_t pos)
 {
-       read_descriptor_t desc;
+       struct file *filp = iocb->ki_filp;
+       ssize_t retval;
+       unsigned long seg;
+       size_t count;
+       loff_t *ppos = &iocb->ki_pos;
 
-       if ((ssize_t) count < 0)
-               return -EINVAL;
-       if (!access_ok(VERIFY_WRITE, buf, count))
-               return -EFAULT;
-       if (!count)
-               return 0;
+       retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
+       if (retval)
+               return retval;
 
-       desc.written = 0;
-       desc.count = count;
-       desc.arg.buf = buf;
-       desc.error = 0;
+       for (seg = 0; seg < nr_segs; seg++) {
+               read_descriptor_t desc;
 
-       do_shmem_file_read(filp, ppos, &desc, file_read_actor);
-       if (desc.written)
-               return desc.written;
-       return desc.error;
+               desc.written = 0;
+               desc.arg.buf = iov[seg].iov_base;
+               desc.count = iov[seg].iov_len;
+               if (desc.count == 0)
+                       continue;
+               desc.error = 0;
+               do_shmem_file_read(filp, ppos, &desc, file_read_actor);
+               retval += desc.written;
+               if (desc.error) {
+                       retval = retval ?: desc.error;
+                       break;
+               }
+               if (desc.count > 0)
+                       break;
+       }
+       return retval;
 }
 
 static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -1907,6 +1929,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
                        return error;
                }
                unlock_page(page);
+               inode->i_mapping->a_ops = &shmem_aops;
                inode->i_op = &shmem_symlink_inode_operations;
                kaddr = kmap_atomic(page, KM_USER0);
                memcpy(kaddr, symname, len);
@@ -2330,7 +2353,7 @@ static void shmem_destroy_inode(struct inode *inode)
        kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct shmem_inode_info *p = (struct shmem_inode_info *) foo;
 
@@ -2369,8 +2392,9 @@ static const struct file_operations shmem_file_operations = {
        .mmap           = shmem_mmap,
 #ifdef CONFIG_TMPFS
        .llseek         = generic_file_llseek,
-       .read           = shmem_file_read,
+       .read           = do_sync_read,
        .write          = do_sync_write,
+       .aio_read       = shmem_file_aio_read,
        .aio_write      = generic_file_aio_write,
        .fsync          = simple_sync_file,
        .splice_read    = generic_file_splice_read,
index f5664c5b9eb1433425501486562c3c6bb98b2237..8e5aadd7dcd6aef09f581d3ff925072cc494b0c0 100644 (file)
@@ -191,7 +191,7 @@ shmem_check_acl(struct inode *inode, int mask)
  * shmem_permission  -  permission() inode operation
  */
 int
-shmem_permission(struct inode *inode, int mask, struct nameidata *nd)
+shmem_permission(struct inode *inode, int mask)
 {
        return generic_permission(inode, mask, shmem_check_acl);
 }
index 052e7d64537eb61e71c780ff4a6ca653dff0750e..918f04f7fef1a3b8a19bd4fdbbb1f407fecec90d 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -406,7 +406,7 @@ struct kmem_cache {
        unsigned int dflags;            /* dynamic flags */
 
        /* constructor func */
-       void (*ctor)(struct kmem_cache *, void *);
+       void (*ctor)(void *obj);
 
 /* 5) cache creation/removal */
        const char *name;
@@ -2137,8 +2137,7 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep)
  */
 struct kmem_cache *
 kmem_cache_create (const char *name, size_t size, size_t align,
-       unsigned long flags,
-       void (*ctor)(struct kmem_cache *, void *))
+       unsigned long flags, void (*ctor)(void *))
 {
        size_t left_over, slab_size, ralign;
        struct kmem_cache *cachep = NULL, *pc;
@@ -2653,7 +2652,7 @@ static void cache_init_objs(struct kmem_cache *cachep,
                 * They must also be threaded.
                 */
                if (cachep->ctor && !(cachep->flags & SLAB_POISON))
-                       cachep->ctor(cachep, objp + obj_offset(cachep));
+                       cachep->ctor(objp + obj_offset(cachep));
 
                if (cachep->flags & SLAB_RED_ZONE) {
                        if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
@@ -2669,7 +2668,7 @@ static void cache_init_objs(struct kmem_cache *cachep,
                                         cachep->buffer_size / PAGE_SIZE, 0);
 #else
                if (cachep->ctor)
-                       cachep->ctor(cachep, objp);
+                       cachep->ctor(objp);
 #endif
                slab_bufctl(slabp)[i] = i + 1;
        }
@@ -3093,7 +3092,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
 #endif
        objp += obj_offset(cachep);
        if (cachep->ctor && cachep->flags & SLAB_POISON)
-               cachep->ctor(cachep, objp);
+               cachep->ctor(objp);
 #if ARCH_SLAB_MINALIGN
        if ((u32)objp & (ARCH_SLAB_MINALIGN-1)) {
                printk(KERN_ERR "0x%p: not aligned to ARCH_SLAB_MINALIGN=%d\n",
index a3ad6671adf179daa38dae11a3963e5323ce0c91..d8fbd4d1bfa7e6fee9d538929349a0efd4740ca8 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -130,17 +130,17 @@ static LIST_HEAD(free_slob_large);
  */
 static inline int slob_page(struct slob_page *sp)
 {
-       return test_bit(PG_active, &sp->flags);
+       return PageSlobPage((struct page *)sp);
 }
 
 static inline void set_slob_page(struct slob_page *sp)
 {
-       __set_bit(PG_active, &sp->flags);
+       __SetPageSlobPage((struct page *)sp);
 }
 
 static inline void clear_slob_page(struct slob_page *sp)
 {
-       __clear_bit(PG_active, &sp->flags);
+       __ClearPageSlobPage((struct page *)sp);
 }
 
 /*
@@ -148,19 +148,19 @@ static inline void clear_slob_page(struct slob_page *sp)
  */
 static inline int slob_page_free(struct slob_page *sp)
 {
-       return test_bit(PG_private, &sp->flags);
+       return PageSlobFree((struct page *)sp);
 }
 
 static void set_slob_page_free(struct slob_page *sp, struct list_head *list)
 {
        list_add(&sp->list, list);
-       __set_bit(PG_private, &sp->flags);
+       __SetPageSlobFree((struct page *)sp);
 }
 
 static inline void clear_slob_page_free(struct slob_page *sp)
 {
        list_del(&sp->list);
-       __clear_bit(PG_private, &sp->flags);
+       __ClearPageSlobFree((struct page *)sp);
 }
 
 #define SLOB_UNIT sizeof(slob_t)
@@ -525,12 +525,11 @@ struct kmem_cache {
        unsigned int size, align;
        unsigned long flags;
        const char *name;
-       void (*ctor)(struct kmem_cache *, void *);
+       void (*ctor)(void *);
 };
 
 struct kmem_cache *kmem_cache_create(const char *name, size_t size,
-       size_t align, unsigned long flags,
-       void (*ctor)(struct kmem_cache *, void *))
+       size_t align, unsigned long flags, void (*ctor)(void *))
 {
        struct kmem_cache *c;
 
@@ -575,7 +574,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
                b = slob_new_page(flags, get_order(c->size), node);
 
        if (c->ctor)
-               c->ctor(c, b);
+               c->ctor(b);
 
        return b;
 }
index 6d4a49c1ff2fc27bef0616c03016394d551fc5be..b7e2cd5d82dbd34577962e56d436dd94bd455b64 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
  *                     the fast path and disables lockless freelists.
  */
 
-#define FROZEN (1 << PG_active)
-
 #ifdef CONFIG_SLUB_DEBUG
-#define SLABDEBUG (1 << PG_error)
+#define SLABDEBUG 1
 #else
 #define SLABDEBUG 0
 #endif
 
-static inline int SlabFrozen(struct page *page)
-{
-       return page->flags & FROZEN;
-}
-
-static inline void SetSlabFrozen(struct page *page)
-{
-       page->flags |= FROZEN;
-}
-
-static inline void ClearSlabFrozen(struct page *page)
-{
-       page->flags &= ~FROZEN;
-}
-
-static inline int SlabDebug(struct page *page)
-{
-       return page->flags & SLABDEBUG;
-}
-
-static inline void SetSlabDebug(struct page *page)
-{
-       page->flags |= SLABDEBUG;
-}
-
-static inline void ClearSlabDebug(struct page *page)
-{
-       page->flags &= ~SLABDEBUG;
-}
-
 /*
  * Issues still to be resolved:
  *
@@ -971,7 +939,7 @@ static int free_debug_processing(struct kmem_cache *s, struct page *page,
        }
 
        /* Special debug activities for freeing objects */
-       if (!SlabFrozen(page) && !page->freelist)
+       if (!PageSlubFrozen(page) && !page->freelist)
                remove_full(s, page);
        if (s->flags & SLAB_STORE_USER)
                set_track(s, object, TRACK_FREE, addr);
@@ -1044,7 +1012,7 @@ __setup("slub_debug", setup_slub_debug);
 
 static unsigned long kmem_cache_flags(unsigned long objsize,
        unsigned long flags, const char *name,
-       void (*ctor)(struct kmem_cache *, void *))
+       void (*ctor)(void *))
 {
        /*
         * Enable debugging if selected on the kernel commandline.
@@ -1072,7 +1040,7 @@ static inline int check_object(struct kmem_cache *s, struct page *page,
 static inline void add_full(struct kmem_cache_node *n, struct page *page) {}
 static inline unsigned long kmem_cache_flags(unsigned long objsize,
        unsigned long flags, const char *name,
-       void (*ctor)(struct kmem_cache *, void *))
+       void (*ctor)(void *))
 {
        return flags;
 }
@@ -1135,7 +1103,7 @@ static void setup_object(struct kmem_cache *s, struct page *page,
 {
        setup_object_debug(s, page, object);
        if (unlikely(s->ctor))
-               s->ctor(s, object);
+               s->ctor(object);
 }
 
 static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
@@ -1157,7 +1125,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
        page->flags |= 1 << PG_slab;
        if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
                        SLAB_STORE_USER | SLAB_TRACE))
-               SetSlabDebug(page);
+               __SetPageSlubDebug(page);
 
        start = page_address(page);
 
@@ -1184,14 +1152,14 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
        int order = compound_order(page);
        int pages = 1 << order;
 
-       if (unlikely(SlabDebug(page))) {
+       if (unlikely(SLABDEBUG && PageSlubDebug(page))) {
                void *p;
 
                slab_pad_check(s, page);
                for_each_object(p, s, page_address(page),
                                                page->objects)
                        check_object(s, page, p, 0);
-               ClearSlabDebug(page);
+               __ClearPageSlubDebug(page);
        }
 
        mod_zone_page_state(page_zone(page),
@@ -1288,7 +1256,7 @@ static inline int lock_and_freeze_slab(struct kmem_cache_node *n,
        if (slab_trylock(page)) {
                list_del(&page->lru);
                n->nr_partial--;
-               SetSlabFrozen(page);
+               __SetPageSlubFrozen(page);
                return 1;
        }
        return 0;
@@ -1398,7 +1366,7 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
        struct kmem_cache_node *n = get_node(s, page_to_nid(page));
        struct kmem_cache_cpu *c = get_cpu_slab(s, smp_processor_id());
 
-       ClearSlabFrozen(page);
+       __ClearPageSlubFrozen(page);
        if (page->inuse) {
 
                if (page->freelist) {
@@ -1406,7 +1374,8 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
                        stat(c, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD);
                } else {
                        stat(c, DEACTIVATE_FULL);
-                       if (SlabDebug(page) && (s->flags & SLAB_STORE_USER))
+                       if (SLABDEBUG && PageSlubDebug(page) &&
+                                               (s->flags & SLAB_STORE_USER))
                                add_full(n, page);
                }
                slab_unlock(page);
@@ -1551,7 +1520,7 @@ load_freelist:
        object = c->page->freelist;
        if (unlikely(!object))
                goto another_slab;
-       if (unlikely(SlabDebug(c->page)))
+       if (unlikely(SLABDEBUG && PageSlubDebug(c->page)))
                goto debug;
 
        c->freelist = object[c->offset];
@@ -1588,7 +1557,7 @@ new_slab:
                if (c->page)
                        flush_slab(s, c);
                slab_lock(new);
-               SetSlabFrozen(new);
+               __SetPageSlubFrozen(new);
                c->page = new;
                goto load_freelist;
        }
@@ -1674,7 +1643,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
        stat(c, FREE_SLOWPATH);
        slab_lock(page);
 
-       if (unlikely(SlabDebug(page)))
+       if (unlikely(SLABDEBUG && PageSlubDebug(page)))
                goto debug;
 
 checks_ok:
@@ -1682,7 +1651,7 @@ checks_ok:
        page->freelist = object;
        page->inuse--;
 
-       if (unlikely(SlabFrozen(page))) {
+       if (unlikely(PageSlubFrozen(page))) {
                stat(c, FREE_FROZEN);
                goto out_unlock;
        }
@@ -2317,7 +2286,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
 static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
                const char *name, size_t size,
                size_t align, unsigned long flags,
-               void (*ctor)(struct kmem_cache *, void *))
+               void (*ctor)(void *))
 {
        memset(s, 0, kmem_size);
        s->name = name;
@@ -3073,7 +3042,7 @@ static int slab_unmergeable(struct kmem_cache *s)
 
 static struct kmem_cache *find_mergeable(size_t size,
                size_t align, unsigned long flags, const char *name,
-               void (*ctor)(struct kmem_cache *, void *))
+               void (*ctor)(void *))
 {
        struct kmem_cache *s;
 
@@ -3113,8 +3082,7 @@ static struct kmem_cache *find_mergeable(size_t size,
 }
 
 struct kmem_cache *kmem_cache_create(const char *name, size_t size,
-               size_t align, unsigned long flags,
-               void (*ctor)(struct kmem_cache *, void *))
+               size_t align, unsigned long flags, void (*ctor)(void *))
 {
        struct kmem_cache *s;
 
@@ -3317,12 +3285,12 @@ static void validate_slab_slab(struct kmem_cache *s, struct page *page,
                        s->name, page);
 
        if (s->flags & DEBUG_DEFAULT_FLAGS) {
-               if (!SlabDebug(page))
-                       printk(KERN_ERR "SLUB %s: SlabDebug not set "
+               if (!PageSlubDebug(page))
+                       printk(KERN_ERR "SLUB %s: SlubDebug not set "
                                "on slab 0x%p\n", s->name, page);
        } else {
-               if (SlabDebug(page))
-                       printk(KERN_ERR "SLUB %s: SlabDebug set on "
+               if (PageSlubDebug(page))
+                       printk(KERN_ERR "SLUB %s: SlubDebug set on "
                                "slab 0x%p\n", s->name, page);
        }
 }
index 36511c7b5e2c797067ccb539646f580aa8ec1012..5d9dbbb9d39e34759e2a858049901927f379f6a3 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/dma.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
+#include "internal.h"
 
 /*
  * Permanent SPARSEMEM data:
@@ -147,22 +148,41 @@ static inline int sparse_early_nid(struct mem_section *section)
        return (section->section_mem_map >> SECTION_NID_SHIFT);
 }
 
-/* Record a memory area against a node. */
-void __init memory_present(int nid, unsigned long start, unsigned long end)
+/* Validate the physical addressing limitations of the model */
+void __meminit mminit_validate_memmodel_limits(unsigned long *start_pfn,
+                                               unsigned long *end_pfn)
 {
-       unsigned long max_arch_pfn = 1UL << (MAX_PHYSMEM_BITS-PAGE_SHIFT);
-       unsigned long pfn;
+       unsigned long max_sparsemem_pfn = 1UL << (MAX_PHYSMEM_BITS-PAGE_SHIFT);
 
        /*
         * Sanity checks - do not allow an architecture to pass
         * in larger pfns than the maximum scope of sparsemem:
         */
-       if (start >= max_arch_pfn)
-               return;
-       if (end >= max_arch_pfn)
-               end = max_arch_pfn;
+       if (*start_pfn > max_sparsemem_pfn) {
+               mminit_dprintk(MMINIT_WARNING, "pfnvalidation",
+                       "Start of range %lu -> %lu exceeds SPARSEMEM max %lu\n",
+                       *start_pfn, *end_pfn, max_sparsemem_pfn);
+               WARN_ON_ONCE(1);
+               *start_pfn = max_sparsemem_pfn;
+               *end_pfn = max_sparsemem_pfn;
+       }
+
+       if (*end_pfn > max_sparsemem_pfn) {
+               mminit_dprintk(MMINIT_WARNING, "pfnvalidation",
+                       "End of range %lu -> %lu exceeds SPARSEMEM max %lu\n",
+                       *start_pfn, *end_pfn, max_sparsemem_pfn);
+               WARN_ON_ONCE(1);
+               *end_pfn = max_sparsemem_pfn;
+       }
+}
+
+/* Record a memory area against a node. */
+void __init memory_present(int nid, unsigned long start, unsigned long end)
+{
+       unsigned long pfn;
 
        start &= PAGE_SECTION_MASK;
+       mminit_validate_memmodel_limits(&start, &end);
        for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
                unsigned long section = pfn_to_section_nr(pfn);
                struct mem_section *ms;
@@ -187,6 +207,7 @@ unsigned long __init node_memmap_size_bytes(int nid, unsigned long start_pfn,
        unsigned long pfn;
        unsigned long nr_pages = 0;
 
+       mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
        for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
                if (nid != early_pfn_to_nid(pfn))
                        continue;
@@ -248,16 +269,92 @@ static unsigned long *__kmalloc_section_usemap(void)
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+static unsigned long * __init
+sparse_early_usemap_alloc_pgdat_section(struct pglist_data *pgdat)
+{
+       unsigned long section_nr;
+
+       /*
+        * A page may contain usemaps for other sections preventing the
+        * page being freed and making a section unremovable while
+        * other sections referencing the usemap retmain active. Similarly,
+        * a pgdat can prevent a section being removed. If section A
+        * contains a pgdat and section B contains the usemap, both
+        * sections become inter-dependent. This allocates usemaps
+        * from the same section as the pgdat where possible to avoid
+        * this problem.
+        */
+       section_nr = pfn_to_section_nr(__pa(pgdat) >> PAGE_SHIFT);
+       return alloc_bootmem_section(usemap_size(), section_nr);
+}
+
+static void __init check_usemap_section_nr(int nid, unsigned long *usemap)
+{
+       unsigned long usemap_snr, pgdat_snr;
+       static unsigned long old_usemap_snr = NR_MEM_SECTIONS;
+       static unsigned long old_pgdat_snr = NR_MEM_SECTIONS;
+       struct pglist_data *pgdat = NODE_DATA(nid);
+       int usemap_nid;
+
+       usemap_snr = pfn_to_section_nr(__pa(usemap) >> PAGE_SHIFT);
+       pgdat_snr = pfn_to_section_nr(__pa(pgdat) >> PAGE_SHIFT);
+       if (usemap_snr == pgdat_snr)
+               return;
+
+       if (old_usemap_snr == usemap_snr && old_pgdat_snr == pgdat_snr)
+               /* skip redundant message */
+               return;
+
+       old_usemap_snr = usemap_snr;
+       old_pgdat_snr = pgdat_snr;
+
+       usemap_nid = sparse_early_nid(__nr_to_section(usemap_snr));
+       if (usemap_nid != nid) {
+               printk(KERN_INFO
+                      "node %d must be removed before remove section %ld\n",
+                      nid, usemap_snr);
+               return;
+       }
+       /*
+        * There is a circular dependency.
+        * Some platforms allow un-removable section because they will just
+        * gather other removable sections for dynamic partitioning.
+        * Just notify un-removable section's number here.
+        */
+       printk(KERN_INFO "Section %ld and %ld (node %d)", usemap_snr,
+              pgdat_snr, nid);
+       printk(KERN_CONT
+              " have a circular dependency on usemap and pgdat allocations\n");
+}
+#else
+static unsigned long * __init
+sparse_early_usemap_alloc_pgdat_section(struct pglist_data *pgdat)
+{
+       return NULL;
+}
+
+static void __init check_usemap_section_nr(int nid, unsigned long *usemap)
+{
+}
+#endif /* CONFIG_MEMORY_HOTREMOVE */
+
 static unsigned long *__init sparse_early_usemap_alloc(unsigned long pnum)
 {
        unsigned long *usemap;
        struct mem_section *ms = __nr_to_section(pnum);
        int nid = sparse_early_nid(ms);
 
-       usemap = alloc_bootmem_node(NODE_DATA(nid), usemap_size());
+       usemap = sparse_early_usemap_alloc_pgdat_section(NODE_DATA(nid));
        if (usemap)
                return usemap;
 
+       usemap = alloc_bootmem_node(NODE_DATA(nid), usemap_size());
+       if (usemap) {
+               check_usemap_section_nr(nid, usemap);
+               return usemap;
+       }
+
        /* Stupid: suppress gcc warning for SPARSEMEM && !NUMA */
        nid = 0;
 
@@ -280,7 +377,7 @@ struct page __init *sparse_mem_map_populate(unsigned long pnum, int nid)
 }
 #endif /* !CONFIG_SPARSEMEM_VMEMMAP */
 
-struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
+static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
 {
        struct page *map;
        struct mem_section *ms = __nr_to_section(pnum);
index 45c9f25a8a3be7e2dccc6a6f807e0eaeade1e697..dd89234ee51fa230f893f6f55d9039dd01693955 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -34,9 +34,9 @@
 /* How many pages do we try to swap or page in/out together? */
 int page_cluster;
 
-static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs) = { 0, };
-static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs) = { 0, };
-static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs) = { 0, };
+static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs);
+static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs);
+static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs);
 
 /*
  * This path almost never happens for VM activity - pages are normally
@@ -493,7 +493,7 @@ EXPORT_SYMBOL(pagevec_lookup_tag);
  */
 #define ACCT_THRESHOLD max(16, NR_CPUS * 2)
 
-static DEFINE_PER_CPU(long, committed_space) = 0;
+static DEFINE_PER_CPU(long, committed_space);
 
 void vm_acct_memory(long pages)
 {
index d8aadaf2a0baa5e87aff579039323585add00952..b8035b0551297f6ca7c2e09239d454e4707f5320 100644 (file)
@@ -39,7 +39,7 @@ static struct backing_dev_info swap_backing_dev_info = {
 
 struct address_space swapper_space = {
        .page_tree      = RADIX_TREE_INIT(GFP_ATOMIC|__GFP_NOWARN),
-       .tree_lock      = __RW_LOCK_UNLOCKED(swapper_space.tree_lock),
+       .tree_lock      = __SPIN_LOCK_UNLOCKED(swapper_space.tree_lock),
        .a_ops          = &swap_aops,
        .i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear),
        .backing_dev_info = &swap_backing_dev_info,
@@ -56,7 +56,8 @@ static struct {
 
 void show_swap_cache_info(void)
 {
-       printk("Swap cache: add %lu, delete %lu, find %lu/%lu\n",
+       printk("%lu pages in swap cache\n", total_swapcache_pages);
+       printk("Swap cache stats: add %lu, delete %lu, find %lu/%lu\n",
                swap_cache_info.add_total, swap_cache_info.del_total,
                swap_cache_info.find_success, swap_cache_info.find_total);
        printk("Free swap  = %lukB\n", nr_swap_pages << (PAGE_SHIFT - 10));
@@ -64,7 +65,7 @@ void show_swap_cache_info(void)
 }
 
 /*
- * add_to_swap_cache resembles add_to_page_cache on swapper_space,
+ * add_to_swap_cache resembles add_to_page_cache_locked on swapper_space,
  * but sets SwapCache flag and private instead of mapping and index.
  */
 int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp_mask)
@@ -76,19 +77,26 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp_mask)
        BUG_ON(PagePrivate(page));
        error = radix_tree_preload(gfp_mask);
        if (!error) {
-               write_lock_irq(&swapper_space.tree_lock);
+               page_cache_get(page);
+               SetPageSwapCache(page);
+               set_page_private(page, entry.val);
+
+               spin_lock_irq(&swapper_space.tree_lock);
                error = radix_tree_insert(&swapper_space.page_tree,
                                                entry.val, page);
-               if (!error) {
-                       page_cache_get(page);
-                       SetPageSwapCache(page);
-                       set_page_private(page, entry.val);
+               if (likely(!error)) {
                        total_swapcache_pages++;
                        __inc_zone_page_state(page, NR_FILE_PAGES);
                        INC_CACHE_INFO(add_total);
                }
-               write_unlock_irq(&swapper_space.tree_lock);
+               spin_unlock_irq(&swapper_space.tree_lock);
                radix_tree_preload_end();
+
+               if (unlikely(error)) {
+                       set_page_private(page, 0UL);
+                       ClearPageSwapCache(page);
+                       page_cache_release(page);
+               }
        }
        return error;
 }
@@ -175,9 +183,9 @@ void delete_from_swap_cache(struct page *page)
 
        entry.val = page_private(page);
 
-       write_lock_irq(&swapper_space.tree_lock);
+       spin_lock_irq(&swapper_space.tree_lock);
        __delete_from_swap_cache(page);
-       write_unlock_irq(&swapper_space.tree_lock);
+       spin_unlock_irq(&swapper_space.tree_lock);
 
        swap_free(entry);
        page_cache_release(page);
index bd1bb59203065621e561900b125c017bfe65054d..6beb6251e99d78dcd7de0dae4347bc10dfd2e2d4 100644 (file)
 #include <asm/tlbflush.h>
 #include <linux/swapops.h>
 
-DEFINE_SPINLOCK(swap_lock);
-unsigned int nr_swapfiles;
+static DEFINE_SPINLOCK(swap_lock);
+static unsigned int nr_swapfiles;
 long total_swap_pages;
 static int swap_overflow;
+static int least_priority;
 
 static const char Bad_file[] = "Bad swap file entry ";
 static const char Unused_file[] = "Unused swap file entry ";
 static const char Bad_offset[] = "Bad swap offset entry ";
 static const char Unused_offset[] = "Unused swap offset entry ";
 
-struct swap_list_t swap_list = {-1, -1};
+static struct swap_list_t swap_list = {-1, -1};
 
 static struct swap_info_struct swap_info[MAX_SWAPFILES];
 
@@ -368,13 +369,13 @@ int remove_exclusive_swap_page(struct page *page)
        retval = 0;
        if (p->swap_map[swp_offset(entry)] == 1) {
                /* Recheck the page count with the swapcache lock held.. */
-               write_lock_irq(&swapper_space.tree_lock);
+               spin_lock_irq(&swapper_space.tree_lock);
                if ((page_count(page) == 2) && !PageWriteback(page)) {
                        __delete_from_swap_cache(page);
                        SetPageDirty(page);
                        retval = 1;
                }
-               write_unlock_irq(&swapper_space.tree_lock);
+               spin_unlock_irq(&swapper_space.tree_lock);
        }
        spin_unlock(&swap_lock);
 
@@ -1260,6 +1261,11 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
                /* just pick something that's safe... */
                swap_list.next = swap_list.head;
        }
+       if (p->prio < 0) {
+               for (i = p->next; i >= 0; i = swap_info[i].next)
+                       swap_info[i].prio = p->prio--;
+               least_priority++;
+       }
        nr_swap_pages -= p->pages;
        total_swap_pages -= p->pages;
        p->flags &= ~SWP_WRITEOK;
@@ -1272,9 +1278,14 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
        if (err) {
                /* re-insert swap space back into swap_list */
                spin_lock(&swap_lock);
-               for (prev = -1, i = swap_list.head; i >= 0; prev = i, i = swap_info[i].next)
+               if (p->prio < 0)
+                       p->prio = --least_priority;
+               prev = -1;
+               for (i = swap_list.head; i >= 0; i = swap_info[i].next) {
                        if (p->prio >= swap_info[i].prio)
                                break;
+                       prev = i;
+               }
                p->next = i;
                if (prev < 0)
                        swap_list.head = swap_list.next = p - swap_info;
@@ -1447,7 +1458,6 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
        unsigned int type;
        int i, prev;
        int error;
-       static int least_priority;
        union swap_header *swap_header = NULL;
        int swap_header_version;
        unsigned int nr_good_pages = 0;
@@ -1455,7 +1465,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
        sector_t span;
        unsigned long maxpages = 1;
        int swapfilesize;
-       unsigned short *swap_map;
+       unsigned short *swap_map = NULL;
        struct page *page = NULL;
        struct inode *inode = NULL;
        int did_down = 0;
@@ -1474,22 +1484,10 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
        }
        if (type >= nr_swapfiles)
                nr_swapfiles = type+1;
+       memset(p, 0, sizeof(*p));
        INIT_LIST_HEAD(&p->extent_list);
        p->flags = SWP_USED;
-       p->swap_file = NULL;
-       p->old_block_size = 0;
-       p->swap_map = NULL;
-       p->lowest_bit = 0;
-       p->highest_bit = 0;
-       p->cluster_nr = 0;
-       p->inuse_pages = 0;
        p->next = -1;
-       if (swap_flags & SWAP_FLAG_PREFER) {
-               p->prio =
-                 (swap_flags & SWAP_FLAG_PRIO_MASK)>>SWAP_FLAG_PRIO_SHIFT;
-       } else {
-               p->prio = --least_priority;
-       }
        spin_unlock(&swap_lock);
        name = getname(specialfile);
        error = PTR_ERR(name);
@@ -1632,19 +1630,20 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
                        goto bad_swap;
 
                /* OK, set up the swap map and apply the bad block list */
-               if (!(p->swap_map = vmalloc(maxpages * sizeof(short)))) {
+               swap_map = vmalloc(maxpages * sizeof(short));
+               if (!swap_map) {
                        error = -ENOMEM;
                        goto bad_swap;
                }
 
                error = 0;
-               memset(p->swap_map, 0, maxpages * sizeof(short));
+               memset(swap_map, 0, maxpages * sizeof(short));
                for (i = 0; i < swap_header->info.nr_badpages; i++) {
                        int page_nr = swap_header->info.badpages[i];
                        if (page_nr <= 0 || page_nr >= swap_header->info.last_page)
                                error = -EINVAL;
                        else
-                               p->swap_map[page_nr] = SWAP_MAP_BAD;
+                               swap_map[page_nr] = SWAP_MAP_BAD;
                }
                nr_good_pages = swap_header->info.last_page -
                                swap_header->info.nr_badpages -
@@ -1654,7 +1653,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
        }
 
        if (nr_good_pages) {
-               p->swap_map[0] = SWAP_MAP_BAD;
+               swap_map[0] = SWAP_MAP_BAD;
                p->max = maxpages;
                p->pages = nr_good_pages;
                nr_extents = setup_swap_extents(p, &span);
@@ -1672,6 +1671,12 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
 
        mutex_lock(&swapon_mutex);
        spin_lock(&swap_lock);
+       if (swap_flags & SWAP_FLAG_PREFER)
+               p->prio =
+                 (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT;
+       else
+               p->prio = --least_priority;
+       p->swap_map = swap_map;
        p->flags = SWP_ACTIVE;
        nr_swap_pages += nr_good_pages;
        total_swap_pages += nr_good_pages;
@@ -1707,12 +1712,8 @@ bad_swap:
        destroy_swap_extents(p);
 bad_swap_2:
        spin_lock(&swap_lock);
-       swap_map = p->swap_map;
        p->swap_file = NULL;
-       p->swap_map = NULL;
        p->flags = 0;
-       if (!(swap_flags & SWAP_FLAG_PREFER))
-               ++least_priority;
        spin_unlock(&swap_lock);
        vfree(swap_map);
        if (swap_file)
index b8961cb6341401e27f9debffc5832154525fadcb..e68443d7456702767d1b4c6213d5bb006f048b67 100644 (file)
@@ -349,18 +349,18 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
        if (PagePrivate(page) && !try_to_release_page(page, GFP_KERNEL))
                return 0;
 
-       write_lock_irq(&mapping->tree_lock);
+       spin_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);
+       spin_unlock_irq(&mapping->tree_lock);
        ClearPageUptodate(page);
        page_cache_release(page);       /* pagecache ref */
        return 1;
 failed:
-       write_unlock_irq(&mapping->tree_lock);
+       spin_unlock_irq(&mapping->tree_lock);
        return 0;
 }
 
index 8f18683825bcd0e3b95b4fe1754befb3e0b0268c..9341ca77bd88240741afbcbabed9019f247a7531 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -1,7 +1,9 @@
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 
 /**
@@ -68,25 +70,22 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp)
 EXPORT_SYMBOL(kmemdup);
 
 /**
- * krealloc - reallocate memory. The contents will remain unchanged.
+ * __krealloc - like krealloc() but don't free @p.
  * @p: object to reallocate memory for.
  * @new_size: how many bytes of memory are required.
  * @flags: the type of memory to allocate.
  *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
+ * This function is like krealloc() except it never frees the originally
+ * allocated buffer. Use this if you don't want to free the buffer immediately
+ * like, for example, with RCU.
  */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
+void *__krealloc(const void *p, size_t new_size, gfp_t flags)
 {
        void *ret;
        size_t ks = 0;
 
-       if (unlikely(!new_size)) {
-               kfree(p);
+       if (unlikely(!new_size))
                return ZERO_SIZE_PTR;
-       }
 
        if (p)
                ks = ksize(p);
@@ -95,10 +94,37 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags)
                return (void *)p;
 
        ret = kmalloc_track_caller(new_size, flags);
-       if (ret && p) {
+       if (ret && p)
                memcpy(ret, p, ks);
+
+       return ret;
+}
+EXPORT_SYMBOL(__krealloc);
+
+/**
+ * krealloc - reallocate memory. The contents will remain unchanged.
+ * @p: object to reallocate memory for.
+ * @new_size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ *
+ * The contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.  If @p is %NULL, krealloc()
+ * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * %NULL pointer, the object pointed to is freed.
+ */
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+       void *ret;
+
+       if (unlikely(!new_size)) {
                kfree(p);
+               return ZERO_SIZE_PTR;
        }
+
+       ret = __krealloc(p, new_size, flags);
+       if (ret && p != ret)
+               kfree(p);
+
        return ret;
 }
 EXPORT_SYMBOL(krealloc);
@@ -136,3 +162,12 @@ char *strndup_user(const char __user *s, long n)
        return p;
 }
 EXPORT_SYMBOL(strndup_user);
+
+#ifndef HAVE_ARCH_PICK_MMAP_LAYOUT
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+       mm->mmap_base = TASK_UNMAPPED_BASE;
+       mm->get_unmapped_area = arch_get_unmapped_area;
+       mm->unmap_area = arch_unmap_area;
+}
+#endif
index 6e45b0f3d1256e0bdc3a3caffa74597cf96a5138..85b9a0d2c877402ee6c06e97fd9084919ed8485b 100644 (file)
@@ -381,16 +381,14 @@ static void __vunmap(const void *addr, int deallocate_pages)
                return;
 
        if ((PAGE_SIZE-1) & (unsigned long)addr) {
-               printk(KERN_ERR "Trying to vfree() bad address (%p)\n", addr);
-               WARN_ON(1);
+               WARN(1, KERN_ERR "Trying to vfree() bad address (%p)\n", addr);
                return;
        }
 
        area = remove_vm_area(addr);
        if (unlikely(!area)) {
-               printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n",
+               WARN(1, KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n",
                                addr);
-               WARN_ON(1);
                return;
        }
 
@@ -931,6 +929,25 @@ static void s_stop(struct seq_file *m, void *p)
        read_unlock(&vmlist_lock);
 }
 
+static void show_numa_info(struct seq_file *m, struct vm_struct *v)
+{
+       if (NUMA_BUILD) {
+               unsigned int nr, *counters = m->private;
+
+               if (!counters)
+                       return;
+
+               memset(counters, 0, nr_node_ids * sizeof(unsigned int));
+
+               for (nr = 0; nr < v->nr_pages; nr++)
+                       counters[page_to_nid(v->pages[nr])]++;
+
+               for_each_node_state(nr, N_HIGH_MEMORY)
+                       if (counters[nr])
+                               seq_printf(m, " N%u=%u", nr, counters[nr]);
+       }
+}
+
 static int s_show(struct seq_file *m, void *p)
 {
        struct vm_struct *v = p;
@@ -967,6 +984,7 @@ static int s_show(struct seq_file *m, void *p)
        if (v->flags & VM_VPAGES)
                seq_printf(m, " vpages");
 
+       show_numa_info(m, v);
        seq_putc(m, '\n');
        return 0;
 }
index 967d30ccd92b8f3a453951104a761986b6d88a6a..8f71761bc4b756e755f2717b8ac850c644c5dd22 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 #include <linux/memcontrol.h>
+#include <linux/delayacct.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -390,17 +391,15 @@ static pageout_t pageout(struct page *page, struct address_space *mapping,
 }
 
 /*
- * Attempt to detach a locked page from its ->mapping.  If it is dirty or if
- * someone else has a ref on the page, abort and return 0.  If it was
- * successfully detached, return 1.  Assumes the caller has a single ref on
- * this page.
+ * Same as remove_mapping, but if the page is removed from the mapping, it
+ * gets returned with a refcount of 0.
  */
-int remove_mapping(struct address_space *mapping, struct page *page)
+static int __remove_mapping(struct address_space *mapping, struct page *page)
 {
        BUG_ON(!PageLocked(page));
        BUG_ON(mapping != page_mapping(page));
 
-       write_lock_irq(&mapping->tree_lock);
+       spin_lock_irq(&mapping->tree_lock);
        /*
         * The non racy check for a busy page.
         *
@@ -426,28 +425,48 @@ int remove_mapping(struct address_space *mapping, struct page *page)
         * 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))
+       if (!page_freeze_refs(page, 2))
                goto cannot_free;
-       smp_rmb();
-       if (unlikely(PageDirty(page)))
+       /* note: atomic_cmpxchg in page_freeze_refs provides the smp_rmb */
+       if (unlikely(PageDirty(page))) {
+               page_unfreeze_refs(page, 2);
                goto cannot_free;
+       }
 
        if (PageSwapCache(page)) {
                swp_entry_t swap = { .val = page_private(page) };
                __delete_from_swap_cache(page);
-               write_unlock_irq(&mapping->tree_lock);
+               spin_unlock_irq(&mapping->tree_lock);
                swap_free(swap);
-               __put_page(page);       /* The pagecache ref */
-               return 1;
+       } else {
+               __remove_from_page_cache(page);
+               spin_unlock_irq(&mapping->tree_lock);
        }
 
-       __remove_from_page_cache(page);
-       write_unlock_irq(&mapping->tree_lock);
-       __put_page(page);
        return 1;
 
 cannot_free:
-       write_unlock_irq(&mapping->tree_lock);
+       spin_unlock_irq(&mapping->tree_lock);
+       return 0;
+}
+
+/*
+ * Attempt to detach a locked page from its ->mapping.  If it is dirty or if
+ * someone else has a ref on the page, abort and return 0.  If it was
+ * successfully detached, return 1.  Assumes the caller has a single ref on
+ * this page.
+ */
+int remove_mapping(struct address_space *mapping, struct page *page)
+{
+       if (__remove_mapping(mapping, page)) {
+               /*
+                * Unfreezing the refcount with 1 rather than 2 effectively
+                * drops the pagecache ref for us without requiring another
+                * atomic operation.
+                */
+               page_unfreeze_refs(page, 1);
+               return 1;
+       }
        return 0;
 }
 
@@ -597,18 +616,34 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                if (PagePrivate(page)) {
                        if (!try_to_release_page(page, sc->gfp_mask))
                                goto activate_locked;
-                       if (!mapping && page_count(page) == 1)
-                               goto free_it;
+                       if (!mapping && page_count(page) == 1) {
+                               unlock_page(page);
+                               if (put_page_testzero(page))
+                                       goto free_it;
+                               else {
+                                       /*
+                                        * rare race with speculative reference.
+                                        * the speculative reference will free
+                                        * this page shortly, so we may
+                                        * increment nr_reclaimed here (and
+                                        * leave it off the LRU).
+                                        */
+                                       nr_reclaimed++;
+                                       continue;
+                               }
+                       }
                }
 
-               if (!mapping || !remove_mapping(mapping, page))
+               if (!mapping || !__remove_mapping(mapping, page))
                        goto keep_locked;
 
-free_it:
                unlock_page(page);
+free_it:
                nr_reclaimed++;
-               if (!pagevec_add(&freed_pvec, page))
-                       __pagevec_release_nonlru(&freed_pvec);
+               if (!pagevec_add(&freed_pvec, page)) {
+                       __pagevec_free(&freed_pvec);
+                       pagevec_reinit(&freed_pvec);
+               }
                continue;
 
 activate_locked:
@@ -622,7 +657,7 @@ keep:
        }
        list_splice(&ret_pages, page_list);
        if (pagevec_count(&freed_pvec))
-               __pagevec_release_nonlru(&freed_pvec);
+               __pagevec_free(&freed_pvec);
        count_vm_events(PGACTIVATE, pgactivate);
        return nr_reclaimed;
 }
@@ -1316,6 +1351,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
        struct zone *zone;
        enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask);
 
+       delayacct_freepages_start();
+
        if (scan_global_lru(sc))
                count_vm_event(ALLOCSTALL);
        /*
@@ -1396,6 +1433,8 @@ out:
        } else
                mem_cgroup_record_reclaim_priority(sc->mem_cgroup, priority);
 
+       delayacct_freepages_end();
+
        return ret;
 }
 
index c3d4a781802f24c48a61864c9d40f1c94134cbc8..b0d08e667ecec2105356fa12bd3a6c77ce2c7e3d 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
+#include <linux/vmstat.h>
 #include <linux/sched.h>
 
 #ifdef CONFIG_VM_EVENT_COUNTERS
index ea46439314468e78f5a20539de38e123dc4cd5a9..b3cfe5a14fcaee0cfb56401286574d1a2e94a74b 100644 (file)
@@ -31,11 +31,9 @@ static struct llc_sap *snap_sap;
  */
 static struct datalink_proto *find_snap_client(unsigned char *desc)
 {
-       struct list_head *entry;
        struct datalink_proto *proto = NULL, *p;
 
-       list_for_each_rcu(entry, &snap_list) {
-               p = list_entry(entry, struct datalink_proto, node);
+       list_for_each_entry_rcu(p, &snap_list, node) {
                if (!memcmp(p->type, desc, 5)) {
                        proto = p;
                        break;
index 4507f744f44e527cc140b6b5601e556c10bfd361..cdf137af7adc87d580280fbbce9b3c2d64b9dc82 100644 (file)
@@ -1285,7 +1285,7 @@ static int p9_socket_open(struct p9_trans *trans, struct socket *csocket)
        int fd, ret;
 
        csocket->sk->sk_allocation = GFP_NOIO;
-       fd = sock_map_fd(csocket);
+       fd = sock_map_fd(csocket, 0);
        if (fd < 0) {
                P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
                return fd;
index 07b5b82c5eabae0e2be2158b7fb738bd95668e3c..0c850427a85b437e4e82e80b6c5f7f5bc52e06d0 100644 (file)
@@ -959,7 +959,7 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + skb_shinfo(skb)->frags[i].size;
                if ((copy = end - offset) > 0) {
@@ -986,7 +986,7 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
                for (; list; list = list->next) {
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        if ((copy = end - offset) > 0) {
index 690bc3ab186c67cee4ba7844bc19b32ba2c2aafb..1a58af51a2e24a374d2d558e65e8206a5c96f329 100644 (file)
@@ -93,28 +93,20 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
 
 static int __init ebtable_filter_init(void)
 {
-       int i, j, ret;
+       int ret;
 
        ret = ebt_register_table(&frame_filter);
        if (ret < 0)
                return ret;
-       for (i = 0; i < ARRAY_SIZE(ebt_ops_filter); i++)
-               if ((ret = nf_register_hook(&ebt_ops_filter[i])) < 0)
-                       goto cleanup;
-       return ret;
-cleanup:
-       for (j = 0; j < i; j++)
-               nf_unregister_hook(&ebt_ops_filter[j]);
-       ebt_unregister_table(&frame_filter);
+       ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
+       if (ret < 0)
+               ebt_unregister_table(&frame_filter);
        return ret;
 }
 
 static void __exit ebtable_filter_fini(void)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ebt_ops_filter); i++)
-               nf_unregister_hook(&ebt_ops_filter[i]);
+       nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
        ebt_unregister_table(&frame_filter);
 }
 
index 5b495fe2d0b6bb6326d583766c28af7ff272ff93..f60c1e78e57537541e9e1d2ddbd186ff4e681df5 100644 (file)
@@ -100,28 +100,20 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
 
 static int __init ebtable_nat_init(void)
 {
-       int i, ret, j;
+       int ret;
 
        ret = ebt_register_table(&frame_nat);
        if (ret < 0)
                return ret;
-       for (i = 0; i < ARRAY_SIZE(ebt_ops_nat); i++)
-               if ((ret = nf_register_hook(&ebt_ops_nat[i])) < 0)
-                       goto cleanup;
-       return ret;
-cleanup:
-       for (j = 0; j < i; j++)
-               nf_unregister_hook(&ebt_ops_nat[j]);
-       ebt_unregister_table(&frame_nat);
+       ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
+       if (ret < 0)
+               ebt_unregister_table(&frame_nat);
        return ret;
 }
 
 static void __exit ebtable_nat_fini(void)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ebt_ops_nat); i++)
-               nf_unregister_hook(&ebt_ops_nat[i]);
+       nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
        ebt_unregister_table(&frame_nat);
 }
 
index 6e1b03b51933cf897fc7c24cf1fa4d561b0e6243..67fb6a3834a3a538221b347c309842cda1816521 100644 (file)
@@ -722,9 +722,10 @@ EXPORT_SYMBOL(compat_mc_getsockopt);
 
 /* Argument list sizes for compat_sys_socketcall */
 #define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+static unsigned char nas[19]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
                                AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-                               AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+                               AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
+                               AL(6)};
 #undef AL
 
 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags)
@@ -737,13 +738,52 @@ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, uns
        return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
+asmlinkage long compat_sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
+                                  int __user *upeer_addrlen,
+                                  const compat_sigset_t __user *sigmask,
+                                  compat_size_t sigsetsize, int flags)
+{
+       compat_sigset_t ss32;
+       sigset_t ksigmask, sigsaved;
+       int ret;
+
+       if (sigmask) {
+               if (sigsetsize != sizeof(compat_sigset_t))
+                       return -EINVAL;
+               if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+                       return -EFAULT;
+               sigset_from_compat(&ksigmask, &ss32);
+
+               sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+               sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+       }
+
+       ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
+
+       if (ret == -ERESTARTNOHAND) {
+               /*
+                * Don't restore the signal mask yet. Let do_signal() deliver
+                * the signal on the way back to userspace, before the signal
+                * mask is restored.
+                */
+               if (sigmask) {
+                       memcpy(&current->saved_sigmask, &sigsaved,
+                              sizeof(sigsaved));
+                       set_restore_sigmask();
+               }
+       } else if (sigmask)
+               sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+       return ret;
+}
+
 asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
 {
        int ret;
        u32 a[6];
        u32 a0, a1;
 
-       if (call < SYS_SOCKET || call > SYS_RECVMSG)
+       if (call < SYS_SOCKET || call > SYS_PACCEPT)
                return -EINVAL;
        if (copy_from_user(a, args, nas[call]))
                return -EFAULT;
@@ -764,7 +804,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
                ret = sys_listen(a0, a1);
                break;
        case SYS_ACCEPT:
-               ret = sys_accept(a0, compat_ptr(a1), compat_ptr(a[2]));
+               ret = do_accept(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
                break;
        case SYS_GETSOCKNAME:
                ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
@@ -804,6 +844,10 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
        case SYS_RECVMSG:
                ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
                break;
+       case SYS_PACCEPT:
+               ret = compat_sys_paccept(a0, compat_ptr(a1), compat_ptr(a[2]),
+                                        compat_ptr(a[3]), a[4], a[5]);
+               break;
        default:
                ret = -EINVAL;
                break;
index 8a28fc93b72424bafe31a63e336ca4ead747dc89..dd61dcad60199a9ae29242f0c240e4bf4160df77 100644 (file)
@@ -285,7 +285,7 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + skb_shinfo(skb)->frags[i].size;
                if ((copy = end - offset) > 0) {
@@ -315,7 +315,7 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
                for (; list; list = list->next) {
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        if ((copy = end - offset) > 0) {
@@ -366,7 +366,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + skb_shinfo(skb)->frags[i].size;
                if ((copy = end - offset) > 0) {
@@ -402,7 +402,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
                for (; list; list=list->next) {
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        if ((copy = end - offset) > 0) {
index 7463a2150b092b85630bd278de12e2ce0c7632af..8d13a9b9f1df66a51daf0aefe71a6a854ea47095 100644 (file)
@@ -1341,9 +1341,6 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 
 void __netif_schedule(struct Qdisc *q)
 {
-       if (WARN_ON_ONCE(q == &noop_qdisc))
-               return;
-
        if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) {
                struct softnet_data *sd;
                unsigned long flags;
@@ -1976,7 +1973,7 @@ static void net_tx_action(struct softirq_action *h)
                        struct sk_buff *skb = clist;
                        clist = clist->next;
 
-                       BUG_TRAP(!atomic_read(&skb->users));
+                       WARN_ON(atomic_read(&skb->users));
                        __kfree_skb(skb);
                }
        }
@@ -3850,7 +3847,7 @@ static void rollback_registered(struct net_device *dev)
                dev->uninit(dev);
 
        /* Notifier chain MUST detach us from master device. */
-       BUG_TRAP(!dev->master);
+       WARN_ON(dev->master);
 
        /* Remove entries from kobject tree */
        netdev_unregister_kobject(dev);
@@ -4172,9 +4169,9 @@ void netdev_run_todo(void)
 
                /* paranoia */
                BUG_ON(atomic_read(&dev->refcnt));
-               BUG_TRAP(!dev->ip_ptr);
-               BUG_TRAP(!dev->ip6_ptr);
-               BUG_TRAP(!dev->dn_ptr);
+               WARN_ON(dev->ip_ptr);
+               WARN_ON(dev->ip6_ptr);
+               WARN_ON(dev->dn_ptr);
 
                if (dev->destructor)
                        dev->destructor(dev);
index 2d3035d3abd7a923eef8849f0b31590ee418bdd4..7552495aff7aef090d99654312d5365afa421e95 100644 (file)
@@ -123,7 +123,7 @@ void reqsk_queue_destroy(struct request_sock_queue *queue)
                }
        }
 
-       BUG_TRAP(lopt->qlen == 0);
+       WARN_ON(lopt->qlen != 0);
        if (lopt_size > PAGE_SIZE)
                vfree(lopt);
        else
index e4115672b6cfb1094de109c3fd56db796fc3741b..4e0c922741897eb1ad158880ea9cb96f692894fe 100644 (file)
@@ -1200,7 +1200,7 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + skb_shinfo(skb)->frags[i].size;
                if ((copy = end - offset) > 0) {
@@ -1229,7 +1229,7 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
                for (; list; list = list->next) {
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        if ((copy = end - offset) > 0) {
@@ -1475,7 +1475,7 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
                skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + frag->size;
                if ((copy = end - offset) > 0) {
@@ -1503,7 +1503,7 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
                for (; list; list = list->next) {
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        if ((copy = end - offset) > 0) {
@@ -1552,7 +1552,7 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset,
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + skb_shinfo(skb)->frags[i].size;
                if ((copy = end - offset) > 0) {
@@ -1581,7 +1581,7 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset,
                for (; list; list = list->next) {
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        if ((copy = end - offset) > 0) {
@@ -1629,7 +1629,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + skb_shinfo(skb)->frags[i].size;
                if ((copy = end - offset) > 0) {
@@ -1662,7 +1662,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
                        __wsum csum2;
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        if ((copy = end - offset) > 0) {
@@ -2373,7 +2373,7 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + skb_shinfo(skb)->frags[i].size;
                if ((copy = end - offset) > 0) {
@@ -2397,7 +2397,7 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
                for (; list; list = list->next) {
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        if ((copy = end - offset) > 0) {
index 10a64d57078cc684e07d9d821845ed2de41de41b..91f8bbc93526523a2eaca207359951117712c577 100644 (file)
@@ -180,7 +180,7 @@ static const char *af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_ASH"   , "clock-AF_ECONET"   , "clock-AF_ATMSVC"   ,
   "clock-21"       , "clock-AF_SNA"      , "clock-AF_IRDA"     ,
   "clock-AF_PPPOX" , "clock-AF_WANPIPE"  , "clock-AF_LLC"      ,
-  "clock-27"       , "clock-28"          , "clock-29"          ,
+  "clock-27"       , "clock-28"          , "clock-AF_CAN"      ,
   "clock-AF_TIPC"  , "clock-AF_BLUETOOTH", "clock-AF_IUCV"     ,
   "clock-AF_RXRPC" , "clock-AF_MAX"
 };
index 4a0ad152c9c4492c35fc3abc6ac21bf4580abb20..a6b3437ff082d9cf98b59bb754b409817f3b4597 100644 (file)
@@ -192,13 +192,13 @@ void sk_stream_kill_queues(struct sock *sk)
        __skb_queue_purge(&sk->sk_error_queue);
 
        /* Next, the write queue. */
-       BUG_TRAP(skb_queue_empty(&sk->sk_write_queue));
+       WARN_ON(!skb_queue_empty(&sk->sk_write_queue));
 
        /* Account for returned memory. */
        sk_mem_reclaim(sk);
 
-       BUG_TRAP(!sk->sk_wmem_queued);
-       BUG_TRAP(!sk->sk_forward_alloc);
+       WARN_ON(sk->sk_wmem_queued);
+       WARN_ON(sk->sk_forward_alloc);
 
        /* It is _impossible_ for the backlog to contain anything
         * when we get here.  All user references to this socket
index a570e2af22cb78d0994d41d19e83a29a5e7c5527..f686467ff12ba085f12b140f340a639699a7e049 100644 (file)
@@ -67,7 +67,7 @@ static struct ctl_table net_core_table[] = {
        {
                .ctl_name       = NET_CORE_MSG_COST,
                .procname       = "message_cost",
-               .data           = &net_msg_cost,
+               .data           = &net_ratelimit_state.interval,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = &proc_dointvec_jiffies,
@@ -76,7 +76,7 @@ static struct ctl_table net_core_table[] = {
        {
                .ctl_name       = NET_CORE_MSG_BURST,
                .procname       = "message_burst",
-               .data           = &net_msg_burst,
+               .data           = &net_ratelimit_state.burst,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
index 8c6b706963ff01b02c87a54f2c70103e7f7f8f29..164b090d5ac3d5fed2b1d84753d11101f8a790f0 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <linux/dmaengine.h>
 #include <linux/socket.h>
-#include <linux/rtnetlink.h> /* for BUG_TRAP */
 #include <net/tcp.h>
 #include <net/netdma.h>
 
@@ -72,7 +71,7 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + skb_shinfo(skb)->frags[i].size;
                copy = end - offset;
@@ -101,7 +100,7 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
                for (; list; list = list->next) {
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        copy = end - offset;
index 8031eb59054e057f4556f0cf4f4d251020f57b0d..72e0ebe964a08d03be218b8c17aa061818579f2f 100644 (file)
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-int net_msg_cost __read_mostly = 5*HZ;
-int net_msg_burst __read_mostly = 10;
 int net_msg_warn __read_mostly = 1;
 EXPORT_SYMBOL(net_msg_warn);
 
+DEFINE_RATELIMIT_STATE(net_ratelimit_state, 5 * HZ, 10);
 /*
  * All net warning printk()s should be guarded by this function.
  */
 int net_ratelimit(void)
 {
-       return __printk_ratelimit(net_msg_cost, net_msg_burst);
+       return __ratelimit(&net_ratelimit_state);
 }
 EXPORT_SYMBOL(net_ratelimit);
 
index 32617e0576cb04e240d654f13c2cbecb64d9230a..1c2e3ec2eb57331cd7d6945d543d47446fc31ac0 100644 (file)
@@ -164,7 +164,7 @@ static inline bool dccp_loss_free(const u64 s1, const u64 s2, const u64 ndp)
 {
        s64 delta = dccp_delta_seqno(s1, s2);
 
-       BUG_TRAP(delta >= 0);
+       WARN_ON(delta < 0);
        return (u64)delta <= ndp + 1;
 }
 
@@ -226,7 +226,7 @@ static inline void dccp_csum_outgoing(struct sk_buff *skb)
 
 extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
 
-extern int  dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
+extern int  dccp_retransmit_skb(struct sock *sk);
 
 extern void dccp_send_ack(struct sock *sk);
 extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk);
index 08392ed86c25403ea574c1e2b39786b8488e4625..df2f110df94a4bf2ccc1dcecb1d588fea65ff778 100644 (file)
@@ -413,7 +413,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
 
                /* Stop the REQUEST timer */
                inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
-               BUG_TRAP(sk->sk_send_head != NULL);
+               WARN_ON(sk->sk_send_head == NULL);
                __kfree_skb(sk->sk_send_head);
                sk->sk_send_head = NULL;
 
index 2622ace17c467d528efbc41de9705a5b4d4ec49e..882c5c4de69e69ef390f73059fba96b3cad23799 100644 (file)
@@ -196,8 +196,8 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
 static void dccp_v4_err(struct sk_buff *skb, u32 info)
 {
        const struct iphdr *iph = (struct iphdr *)skb->data;
-       const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data +
-                                                       (iph->ihl << 2));
+       const u8 offset = iph->ihl << 2;
+       const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
        struct dccp_sock *dp;
        struct inet_sock *inet;
        const int type = icmp_hdr(skb)->type;
@@ -207,7 +207,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
        int err;
        struct net *net = dev_net(skb->dev);
 
-       if (skb->len < (iph->ihl << 2) + 8) {
+       if (skb->len < offset + sizeof(*dh) ||
+           skb->len < offset + __dccp_basic_hdr_len(dh)) {
                ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
                return;
        }
@@ -238,7 +239,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
        dp = dccp_sk(sk);
        seq = dccp_hdr_seq(dh);
        if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
-           !between48(seq, dp->dccps_swl, dp->dccps_swh)) {
+           !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
                NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
                goto out;
        }
@@ -283,7 +284,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
                 * ICMPs are not backlogged, hence we cannot get an established
                 * socket here.
                 */
-               BUG_TRAP(!req->sk);
+               WARN_ON(req->sk);
 
                if (seq != dccp_rsk(req)->dreq_iss) {
                        NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
index b74e8b2cbe55938fe79873097ac17ae16111aba3..5e1ee0da2c40cab9c7f44ffd431e4df4455e08f5 100644 (file)
@@ -89,12 +89,19 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 {
        struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
        const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
+       struct dccp_sock *dp;
        struct ipv6_pinfo *np;
        struct sock *sk;
        int err;
        __u64 seq;
        struct net *net = dev_net(skb->dev);
 
+       if (skb->len < offset + sizeof(*dh) ||
+           skb->len < offset + __dccp_basic_hdr_len(dh)) {
+               ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
+               return;
+       }
+
        sk = inet6_lookup(net, &dccp_hashinfo,
                        &hdr->daddr, dh->dccph_dport,
                        &hdr->saddr, dh->dccph_sport, inet6_iif(skb));
@@ -116,6 +123,14 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        if (sk->sk_state == DCCP_CLOSED)
                goto out;
 
+       dp = dccp_sk(sk);
+       seq = dccp_hdr_seq(dh);
+       if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
+           !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
+               NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
+               goto out;
+       }
+
        np = inet6_sk(sk);
 
        if (type == ICMPV6_PKT_TOOBIG) {
@@ -168,7 +183,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        icmpv6_err_convert(type, code, &err);
 
-       seq = dccp_hdr_seq(dh);
        /* Might be for an request_sock */
        switch (sk->sk_state) {
                struct request_sock *req, **prev;
@@ -186,7 +200,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                 * ICMPs are not backlogged, hence we cannot get an established
                 * socket here.
                 */
-               BUG_TRAP(req->sk == NULL);
+               WARN_ON(req->sk != NULL);
 
                if (seq != dccp_rsk(req)->dreq_iss) {
                        NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
index fe20068c5d8e581add6c25a543d046f3fd49071d..d06945c7d3dfc3e1201a00840516a457e9773303 100644 (file)
@@ -53,8 +53,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
                                          dccp_packet_hdr_len(dcb->dccpd_type);
                int err, set_ack = 1;
                u64 ackno = dp->dccps_gsr;
-
-               dccp_inc_seqno(&dp->dccps_gss);
+               /*
+                * Increment GSS here already in case the option code needs it.
+                * Update GSS for real only if option processing below succeeds.
+                */
+               dcb->dccpd_seq = ADD48(dp->dccps_gss, 1);
 
                switch (dcb->dccpd_type) {
                case DCCP_PKT_DATA:
@@ -66,6 +69,9 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
 
                case DCCP_PKT_REQUEST:
                        set_ack = 0;
+                       /* Use ISS on the first (non-retransmitted) Request. */
+                       if (icsk->icsk_retransmits == 0)
+                               dcb->dccpd_seq = dp->dccps_iss;
                        /* fall through */
 
                case DCCP_PKT_SYNC:
@@ -84,8 +90,6 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
                        break;
                }
 
-               dcb->dccpd_seq = dp->dccps_gss;
-
                if (dccp_insert_options(sk, skb)) {
                        kfree_skb(skb);
                        return -EPROTO;
@@ -103,7 +107,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
                /* XXX For now we're using only 48 bits sequence numbers */
                dh->dccph_x     = 1;
 
-               dp->dccps_awh = dp->dccps_gss;
+               dccp_update_gss(sk, dcb->dccpd_seq);
                dccp_hdr_set_seq(dh, dp->dccps_gss);
                if (set_ack)
                        dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno);
@@ -112,6 +116,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
                case DCCP_PKT_REQUEST:
                        dccp_hdr_request(skb)->dccph_req_service =
                                                        dp->dccps_service;
+                       /*
+                        * Limit Ack window to ISS <= P.ackno <= GSS, so that
+                        * only Responses to Requests we sent are considered.
+                        */
+                       dp->dccps_awl = dp->dccps_iss;
                        break;
                case DCCP_PKT_RESET:
                        dccp_hdr_reset(skb)->dccph_reset_code =
@@ -284,14 +293,26 @@ void dccp_write_xmit(struct sock *sk, int block)
        }
 }
 
-int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+/**
+ * dccp_retransmit_skb  -  Retransmit Request, Close, or CloseReq packets
+ * There are only four retransmittable packet types in DCCP:
+ * - Request  in client-REQUEST  state (sec. 8.1.1),
+ * - CloseReq in server-CLOSEREQ state (sec. 8.3),
+ * - Close    in   node-CLOSING  state (sec. 8.3),
+ * - Acks in client-PARTOPEN state (sec. 8.1.5, handled by dccp_delack_timer()).
+ * This function expects sk->sk_send_head to contain the original skb.
+ */
+int dccp_retransmit_skb(struct sock *sk)
 {
+       WARN_ON(sk->sk_send_head == NULL);
+
        if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
                return -EHOSTUNREACH; /* Routing failure or similar. */
 
-       return dccp_transmit_skb(sk, (skb_cloned(skb) ?
-                                     pskb_copy(skb, GFP_ATOMIC):
-                                     skb_clone(skb, GFP_ATOMIC)));
+       /* this count is used to distinguish original and retransmitted skb */
+       inet_csk(sk)->icsk_retransmits++;
+
+       return dccp_transmit_skb(sk, skb_clone(sk->sk_send_head, GFP_ATOMIC));
 }
 
 struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
@@ -437,19 +458,7 @@ static inline void dccp_connect_init(struct sock *sk)
 
        dccp_sync_mss(sk, dst_mtu(dst));
 
-       /*
-        * SWL and AWL are initially adjusted so that they are not less than
-        * the initial Sequence Numbers received and sent, respectively:
-        *      SWL := max(GSR + 1 - floor(W/4), ISR),
-        *      AWL := max(GSS - W' + 1, ISS).
-        * These adjustments MUST be applied only at the beginning of the
-        * connection.
-        */
-       dccp_update_gss(sk, dp->dccps_iss);
-       dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
-
-       /* S.GAR - greatest valid acknowledgement number received on a non-Sync;
-        *         initialized to S.ISS (sec. 8.5)                            */
+       /* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */
        dp->dccps_gar = dp->dccps_iss;
 
        icsk->icsk_retransmits = 0;
index a0b56009611f149da6e172998e104cd62b740984..b622d9744856a9e8320f812cb9e9d85699f1a6a0 100644 (file)
@@ -327,7 +327,7 @@ int dccp_disconnect(struct sock *sk, int flags)
        inet_csk_delack_init(sk);
        __sk_dst_reset(sk);
 
-       BUG_TRAP(!inet->num || icsk->icsk_bind_hash);
+       WARN_ON(inet->num && !icsk->icsk_bind_hash);
 
        sk->sk_error_report(sk);
        return err;
@@ -981,7 +981,7 @@ adjudge_to_death:
         */
        local_bh_disable();
        bh_lock_sock(sk);
-       BUG_TRAP(!sock_owned_by_user(sk));
+       WARN_ON(sock_owned_by_user(sk));
 
        /* Have we already been destroyed by a softirq or backlog? */
        if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED)
index 3608d5342ca22335bf474fcaac15d9ebb10f83a7..54b3c7e9e016737eab1614fde3b22afa67456345 100644 (file)
@@ -98,22 +98,12 @@ static void dccp_retransmit_timer(struct sock *sk)
                goto backoff;
        }
 
-       /*
-        * sk->sk_send_head has to have one skb with
-        * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
-        * packet types. The only packets eligible for retransmission are:
-        *      -- Requests in client-REQUEST  state (sec. 8.1.1)
-        *      -- Acks     in client-PARTOPEN state (sec. 8.1.5)
-        *      -- CloseReq in server-CLOSEREQ state (sec. 8.3)
-        *      -- Close    in   node-CLOSING  state (sec. 8.3)                */
-       BUG_TRAP(sk->sk_send_head != NULL);
-
        /*
         * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
         * sent, no need to retransmit, this sock is dead.
         */
        if (dccp_write_timeout(sk))
-               goto out;
+               return;
 
        /*
         * We want to know the number of packets retransmitted, not the
@@ -122,30 +112,28 @@ static void dccp_retransmit_timer(struct sock *sk)
        if (icsk->icsk_retransmits == 0)
                DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS);
 
-       if (dccp_retransmit_skb(sk, sk->sk_send_head) < 0) {
+       if (dccp_retransmit_skb(sk) != 0) {
                /*
                 * Retransmission failed because of local congestion,
                 * do not backoff.
                 */
-               if (icsk->icsk_retransmits == 0)
+               if (--icsk->icsk_retransmits == 0)
                        icsk->icsk_retransmits = 1;
                inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
                                          min(icsk->icsk_rto,
                                              TCP_RESOURCE_PROBE_INTERVAL),
                                          DCCP_RTO_MAX);
-               goto out;
+               return;
        }
 
 backoff:
        icsk->icsk_backoff++;
-       icsk->icsk_retransmits++;
 
        icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
        inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
                                  DCCP_RTO_MAX);
        if (icsk->icsk_retransmits > sysctl_dccp_retries1)
                __sk_dst_reset(sk);
-out:;
 }
 
 static void dccp_write_timer(unsigned long data)
index 4670683b4688d67b9cd99ae165cfb8c86d5217a8..591ea23639ca859edcf085da1a2204aa5ef22c6c 100644 (file)
@@ -356,10 +356,8 @@ config INET_ESP
 
 config INET_IPCOMP
        tristate "IP: IPComp transformation"
-       select XFRM
        select INET_XFRM_TUNNEL
-       select CRYPTO
-       select CRYPTO_DEFLATE
+       select XFRM_IPCOMP
        ---help---
          Support for IP Payload Compression Protocol (IPComp) (RFC3173),
          typically needed for IPsec.
index dd919d84285ffc8874fe659e96c24c76e56501f5..8a3ac1fa71a976e8c8f4c4f2dfd9fa87af2f9a99 100644 (file)
@@ -148,10 +148,10 @@ void inet_sock_destruct(struct sock *sk)
                return;
        }
 
-       BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
-       BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
-       BUG_TRAP(!sk->sk_wmem_queued);
-       BUG_TRAP(!sk->sk_forward_alloc);
+       WARN_ON(atomic_read(&sk->sk_rmem_alloc));
+       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+       WARN_ON(sk->sk_wmem_queued);
+       WARN_ON(sk->sk_forward_alloc);
 
        kfree(inet->opt);
        dst_release(sk->sk_dst_cache);
@@ -264,7 +264,6 @@ static inline int inet_netns_ok(struct net *net, int protocol)
 static int inet_create(struct net *net, struct socket *sock, int protocol)
 {
        struct sock *sk;
-       struct list_head *p;
        struct inet_protosw *answer;
        struct inet_sock *inet;
        struct proto *answer_prot;
@@ -281,13 +280,12 @@ static int inet_create(struct net *net, struct socket *sock, int protocol)
        sock->state = SS_UNCONNECTED;
 
        /* Look for the requested type/protocol pair. */
-       answer = NULL;
 lookup_protocol:
        err = -ESOCKTNOSUPPORT;
        rcu_read_lock();
-       list_for_each_rcu(p, &inetsw[sock->type]) {
-               answer = list_entry(p, struct inet_protosw, list);
+       list_for_each_entry_rcu(answer, &inetsw[sock->type], list) {
 
+               err = 0;
                /* Check the non-wild match. */
                if (protocol == answer->protocol) {
                        if (protocol != IPPROTO_IP)
@@ -302,10 +300,9 @@ lookup_protocol:
                                break;
                }
                err = -EPROTONOSUPPORT;
-               answer = NULL;
        }
 
-       if (unlikely(answer == NULL)) {
+       if (unlikely(err)) {
                if (try_loading_module < 2) {
                        rcu_read_unlock();
                        /*
@@ -341,7 +338,7 @@ lookup_protocol:
        answer_flags = answer->flags;
        rcu_read_unlock();
 
-       BUG_TRAP(answer_prot->slab != NULL);
+       WARN_ON(answer_prot->slab == NULL);
 
        err = -ENOBUFS;
        sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot);
@@ -661,8 +658,8 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags)
 
        lock_sock(sk2);
 
-       BUG_TRAP((1 << sk2->sk_state) &
-                (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE));
+       WARN_ON(!((1 << sk2->sk_state) &
+                 (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE)));
 
        sock_graft(sk2, newsock);
 
@@ -1442,6 +1439,10 @@ static int __init inet_init(void)
 
        (void)sock_register(&inet_family_ops);
 
+#ifdef CONFIG_SYSCTL
+       ip_static_sysctl_init();
+#endif
+
        /*
         *      Add all the base protocols.
         */
index 2e667e2f90df2e3c97845e7eee59cabd180c55de..91d3d96805d03aef392e0f514b1bd1750a9757d4 100644 (file)
@@ -138,8 +138,8 @@ void in_dev_finish_destroy(struct in_device *idev)
 {
        struct net_device *dev = idev->dev;
 
-       BUG_TRAP(!idev->ifa_list);
-       BUG_TRAP(!idev->mc_list);
+       WARN_ON(idev->ifa_list);
+       WARN_ON(idev->mc_list);
 #ifdef NET_REFCNT_DEBUG
        printk(KERN_DEBUG "in_dev_finish_destroy: %p=%s\n",
               idev, dev ? dev->name : "NIL");
@@ -399,7 +399,7 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
        }
        ipv4_devconf_setall(in_dev);
        if (ifa->ifa_dev != in_dev) {
-               BUG_TRAP(!ifa->ifa_dev);
+               WARN_ON(ifa->ifa_dev);
                in_dev_hold(in_dev);
                ifa->ifa_dev = in_dev;
        }
index bb81c958b7447ecc1f7cee2b898ab727756cb927..0c1ae68ee84bb24a08b73d6798ceb66db63bd176 100644 (file)
@@ -167,7 +167,7 @@ tb_not_found:
 success:
        if (!inet_csk(sk)->icsk_bind_hash)
                inet_bind_hash(sk, tb, snum);
-       BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb);
+       WARN_ON(inet_csk(sk)->icsk_bind_hash != tb);
        ret = 0;
 
 fail_unlock:
@@ -260,7 +260,7 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err)
        }
 
        newsk = reqsk_queue_get_child(&icsk->icsk_accept_queue, sk);
-       BUG_TRAP(newsk->sk_state != TCP_SYN_RECV);
+       WARN_ON(newsk->sk_state == TCP_SYN_RECV);
 out:
        release_sock(sk);
        return newsk;
@@ -386,7 +386,7 @@ struct request_sock *inet_csk_search_req(const struct sock *sk,
                    ireq->rmt_addr == raddr &&
                    ireq->loc_addr == laddr &&
                    AF_INET_FAMILY(req->rsk_ops->family)) {
-                       BUG_TRAP(!req->sk);
+                       WARN_ON(req->sk);
                        *prevp = prev;
                        break;
                }
@@ -539,14 +539,14 @@ EXPORT_SYMBOL_GPL(inet_csk_clone);
  */
 void inet_csk_destroy_sock(struct sock *sk)
 {
-       BUG_TRAP(sk->sk_state == TCP_CLOSE);
-       BUG_TRAP(sock_flag(sk, SOCK_DEAD));
+       WARN_ON(sk->sk_state != TCP_CLOSE);
+       WARN_ON(!sock_flag(sk, SOCK_DEAD));
 
        /* It cannot be in hash table! */
-       BUG_TRAP(sk_unhashed(sk));
+       WARN_ON(!sk_unhashed(sk));
 
        /* If it has not 0 inet_sk(sk)->num, it must be bound */
-       BUG_TRAP(!inet_sk(sk)->num || inet_csk(sk)->icsk_bind_hash);
+       WARN_ON(inet_sk(sk)->num && !inet_csk(sk)->icsk_bind_hash);
 
        sk->sk_prot->destroy(sk);
 
@@ -629,7 +629,7 @@ void inet_csk_listen_stop(struct sock *sk)
 
                local_bh_disable();
                bh_lock_sock(child);
-               BUG_TRAP(!sock_owned_by_user(child));
+               WARN_ON(sock_owned_by_user(child));
                sock_hold(child);
 
                sk->sk_prot->disconnect(child, O_NONBLOCK);
@@ -647,7 +647,7 @@ void inet_csk_listen_stop(struct sock *sk)
                sk_acceptq_removed(sk);
                __reqsk_free(req);
        }
-       BUG_TRAP(!sk->sk_ack_backlog);
+       WARN_ON(sk->sk_ack_backlog);
 }
 
 EXPORT_SYMBOL_GPL(inet_csk_listen_stop);
index 0546a0bc97ea37bdc1b9bef0c22d6b82ec190abf..6c52e08f786e6f574e71c589ddbb86b26f2f43a0 100644 (file)
@@ -134,8 +134,8 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
        struct sk_buff *fp;
        struct netns_frags *nf;
 
-       BUG_TRAP(q->last_in & INET_FRAG_COMPLETE);
-       BUG_TRAP(del_timer(&q->timer) == 0);
+       WARN_ON(!(q->last_in & INET_FRAG_COMPLETE));
+       WARN_ON(del_timer(&q->timer) != 0);
 
        /* Release all fragment data. */
        fp = q->fragments;
index 115f53722d2058d8847a53139ddf2fd635960e7d..44981906fb913e7afbb4f7e03cd0192b9fdcda12 100644 (file)
@@ -305,7 +305,7 @@ unique:
        inet->num = lport;
        inet->sport = htons(lport);
        sk->sk_hash = hash;
-       BUG_TRAP(sk_unhashed(sk));
+       WARN_ON(!sk_unhashed(sk));
        __sk_add_node(sk, &head->chain);
        sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
        write_unlock(lock);
@@ -342,7 +342,7 @@ void __inet_hash_nolisten(struct sock *sk)
        rwlock_t *lock;
        struct inet_ehash_bucket *head;
 
-       BUG_TRAP(sk_unhashed(sk));
+       WARN_ON(!sk_unhashed(sk));
 
        sk->sk_hash = inet_sk_ehashfn(sk);
        head = inet_ehash_bucket(hashinfo, sk->sk_hash);
@@ -367,7 +367,7 @@ static void __inet_hash(struct sock *sk)
                return;
        }
 
-       BUG_TRAP(sk_unhashed(sk));
+       WARN_ON(!sk_unhashed(sk));
        list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
        lock = &hashinfo->lhash_lock;
 
@@ -450,7 +450,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
                         */
                        inet_bind_bucket_for_each(tb, node, &head->chain) {
                                if (tb->ib_net == net && tb->port == port) {
-                                       BUG_TRAP(!hlist_empty(&tb->owners));
+                                       WARN_ON(hlist_empty(&tb->owners));
                                        if (tb->fastreuse >= 0)
                                                goto next_port;
                                        if (!check_established(death_row, sk,
index 75c2def8f9a0cbcd04a0a324e28cde2e756bb480..d985bd613d25d3895f3b7d32fee5f571062d52be 100644 (file)
@@ -86,7 +86,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
                        hashinfo->bhash_size)];
        spin_lock(&bhead->lock);
        tw->tw_tb = icsk->icsk_bind_hash;
-       BUG_TRAP(icsk->icsk_bind_hash);
+       WARN_ON(!icsk->icsk_bind_hash);
        inet_twsk_add_bind_node(tw, &tw->tw_tb->owners);
        spin_unlock(&bhead->lock);
 
index 38d38f058018ddf55b7a17257576cf9310c4af3b..2152d222b954b3eca22bba260e30a5a551316da0 100644 (file)
@@ -488,8 +488,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
                qp->q.fragments = head;
        }
 
-       BUG_TRAP(head != NULL);
-       BUG_TRAP(FRAG_CB(head)->offset == 0);
+       WARN_ON(head == NULL);
+       WARN_ON(FRAG_CB(head)->offset != 0);
 
        /* Allocate a new buffer for the datagram. */
        ihlen = ip_hdrlen(head);
index 465544f6281afbab2990bc561f946f60ae4615aa..d533a89e08de14d2e7417b41dddcb99d8e9c881b 100644 (file)
@@ -118,7 +118,7 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb)
        __skb_pull(newskb, skb_network_offset(newskb));
        newskb->pkt_type = PACKET_LOOPBACK;
        newskb->ip_summed = CHECKSUM_UNNECESSARY;
-       BUG_TRAP(newskb->dst);
+       WARN_ON(!newskb->dst);
        netif_rx(newskb);
        return 0;
 }
index a75807b971b3e1b452d6b272ab3b8077afebd4d1..38ccb6dfb02e1c755f8ec03f6d793ec16121784f 100644 (file)
  *   - Adaptive compression.
  */
 #include <linux/module.h>
-#include <linux/crypto.h>
 #include <linux/err.h>
-#include <linux/pfkeyv2.h>
-#include <linux/percpu.h>
-#include <linux/smp.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
 #include <linux/rtnetlink.h>
-#include <linux/mutex.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/icmp.h>
 #include <net/ipcomp.h>
 #include <net/protocol.h>
-
-struct ipcomp_tfms {
-       struct list_head list;
-       struct crypto_comp **tfms;
-       int users;
-};
-
-static DEFINE_MUTEX(ipcomp_resource_mutex);
-static void **ipcomp_scratches;
-static int ipcomp_scratch_users;
-static LIST_HEAD(ipcomp_tfms_list);
-
-static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
-{
-       struct ipcomp_data *ipcd = x->data;
-       const int plen = skb->len;
-       int dlen = IPCOMP_SCRATCH_SIZE;
-       const u8 *start = skb->data;
-       const int cpu = get_cpu();
-       u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
-       struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
-       int err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
-
-       if (err)
-               goto out;
-
-       if (dlen < (plen + sizeof(struct ip_comp_hdr))) {
-               err = -EINVAL;
-               goto out;
-       }
-
-       err = pskb_expand_head(skb, 0, dlen - plen, GFP_ATOMIC);
-       if (err)
-               goto out;
-
-       skb->truesize += dlen - plen;
-       __skb_put(skb, dlen - plen);
-       skb_copy_to_linear_data(skb, scratch, dlen);
-out:
-       put_cpu();
-       return err;
-}
-
-static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
-{
-       int nexthdr;
-       int err = -ENOMEM;
-       struct ip_comp_hdr *ipch;
-
-       if (skb_linearize_cow(skb))
-               goto out;
-
-       skb->ip_summed = CHECKSUM_NONE;
-
-       /* Remove ipcomp header and decompress original payload */
-       ipch = (void *)skb->data;
-       nexthdr = ipch->nexthdr;
-
-       skb->transport_header = skb->network_header + sizeof(*ipch);
-       __skb_pull(skb, sizeof(*ipch));
-       err = ipcomp_decompress(x, skb);
-       if (err)
-               goto out;
-
-       err = nexthdr;
-
-out:
-       return err;
-}
-
-static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
-{
-       struct ipcomp_data *ipcd = x->data;
-       const int plen = skb->len;
-       int dlen = IPCOMP_SCRATCH_SIZE;
-       u8 *start = skb->data;
-       const int cpu = get_cpu();
-       u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
-       struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
-       int err;
-
-       local_bh_disable();
-       err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
-       local_bh_enable();
-       if (err)
-               goto out;
-
-       if ((dlen + sizeof(struct ip_comp_hdr)) >= plen) {
-               err = -EMSGSIZE;
-               goto out;
-       }
-
-       memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
-       put_cpu();
-
-       pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
-       return 0;
-
-out:
-       put_cpu();
-       return err;
-}
-
-static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-       int err;
-       struct ip_comp_hdr *ipch;
-       struct ipcomp_data *ipcd = x->data;
-
-       if (skb->len < ipcd->threshold) {
-               /* Don't bother compressing */
-               goto out_ok;
-       }
-
-       if (skb_linearize_cow(skb))
-               goto out_ok;
-
-       err = ipcomp_compress(x, skb);
-
-       if (err) {
-               goto out_ok;
-       }
-
-       /* Install ipcomp header, convert into ipcomp datagram. */
-       ipch = ip_comp_hdr(skb);
-       ipch->nexthdr = *skb_mac_header(skb);
-       ipch->flags = 0;
-       ipch->cpi = htons((u16 )ntohl(x->id.spi));
-       *skb_mac_header(skb) = IPPROTO_COMP;
-out_ok:
-       skb_push(skb, -skb_network_offset(skb));
-       return 0;
-}
+#include <net/sock.h>
 
 static void ipcomp4_err(struct sk_buff *skb, u32 info)
 {
@@ -241,155 +102,9 @@ out:
        return err;
 }
 
-static void ipcomp_free_scratches(void)
-{
-       int i;
-       void **scratches;
-
-       if (--ipcomp_scratch_users)
-               return;
-
-       scratches = ipcomp_scratches;
-       if (!scratches)
-               return;
-
-       for_each_possible_cpu(i)
-               vfree(*per_cpu_ptr(scratches, i));
-
-       free_percpu(scratches);
-}
-
-static void **ipcomp_alloc_scratches(void)
-{
-       int i;
-       void **scratches;
-
-       if (ipcomp_scratch_users++)
-               return ipcomp_scratches;
-
-       scratches = alloc_percpu(void *);
-       if (!scratches)
-               return NULL;
-
-       ipcomp_scratches = scratches;
-
-       for_each_possible_cpu(i) {
-               void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
-               if (!scratch)
-                       return NULL;
-               *per_cpu_ptr(scratches, i) = scratch;
-       }
-
-       return scratches;
-}
-
-static void ipcomp_free_tfms(struct crypto_comp **tfms)
-{
-       struct ipcomp_tfms *pos;
-       int cpu;
-
-       list_for_each_entry(pos, &ipcomp_tfms_list, list) {
-               if (pos->tfms == tfms)
-                       break;
-       }
-
-       BUG_TRAP(pos);
-
-       if (--pos->users)
-               return;
-
-       list_del(&pos->list);
-       kfree(pos);
-
-       if (!tfms)
-               return;
-
-       for_each_possible_cpu(cpu) {
-               struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu);
-               crypto_free_comp(tfm);
-       }
-       free_percpu(tfms);
-}
-
-static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name)
-{
-       struct ipcomp_tfms *pos;
-       struct crypto_comp **tfms;
-       int cpu;
-
-       /* This can be any valid CPU ID so we don't need locking. */
-       cpu = raw_smp_processor_id();
-
-       list_for_each_entry(pos, &ipcomp_tfms_list, list) {
-               struct crypto_comp *tfm;
-
-               tfms = pos->tfms;
-               tfm = *per_cpu_ptr(tfms, cpu);
-
-               if (!strcmp(crypto_comp_name(tfm), alg_name)) {
-                       pos->users++;
-                       return tfms;
-               }
-       }
-
-       pos = kmalloc(sizeof(*pos), GFP_KERNEL);
-       if (!pos)
-               return NULL;
-
-       pos->users = 1;
-       INIT_LIST_HEAD(&pos->list);
-       list_add(&pos->list, &ipcomp_tfms_list);
-
-       pos->tfms = tfms = alloc_percpu(struct crypto_comp *);
-       if (!tfms)
-               goto error;
-
-       for_each_possible_cpu(cpu) {
-               struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
-                                                           CRYPTO_ALG_ASYNC);
-               if (IS_ERR(tfm))
-                       goto error;
-               *per_cpu_ptr(tfms, cpu) = tfm;
-       }
-
-       return tfms;
-
-error:
-       ipcomp_free_tfms(tfms);
-       return NULL;
-}
-
-static void ipcomp_free_data(struct ipcomp_data *ipcd)
+static int ipcomp4_init_state(struct xfrm_state *x)
 {
-       if (ipcd->tfms)
-               ipcomp_free_tfms(ipcd->tfms);
-       ipcomp_free_scratches();
-}
-
-static void ipcomp_destroy(struct xfrm_state *x)
-{
-       struct ipcomp_data *ipcd = x->data;
-       if (!ipcd)
-               return;
-       xfrm_state_delete_tunnel(x);
-       mutex_lock(&ipcomp_resource_mutex);
-       ipcomp_free_data(ipcd);
-       mutex_unlock(&ipcomp_resource_mutex);
-       kfree(ipcd);
-}
-
-static int ipcomp_init_state(struct xfrm_state *x)
-{
-       int err;
-       struct ipcomp_data *ipcd;
-       struct xfrm_algo_desc *calg_desc;
-
-       err = -EINVAL;
-       if (!x->calg)
-               goto out;
-
-       if (x->encap)
-               goto out;
+       int err = -EINVAL;
 
        x->props.header_len = 0;
        switch (x->props.mode) {
@@ -402,40 +117,22 @@ static int ipcomp_init_state(struct xfrm_state *x)
                goto out;
        }
 
-       err = -ENOMEM;
-       ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
-       if (!ipcd)
+       err = ipcomp_init_state(x);
+       if (err)
                goto out;
 
-       mutex_lock(&ipcomp_resource_mutex);
-       if (!ipcomp_alloc_scratches())
-               goto error;
-
-       ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name);
-       if (!ipcd->tfms)
-               goto error;
-       mutex_unlock(&ipcomp_resource_mutex);
-
        if (x->props.mode == XFRM_MODE_TUNNEL) {
                err = ipcomp_tunnel_attach(x);
                if (err)
                        goto error_tunnel;
        }
 
-       calg_desc = xfrm_calg_get_byname(x->calg->alg_name, 0);
-       BUG_ON(!calg_desc);
-       ipcd->threshold = calg_desc->uinfo.comp.threshold;
-       x->data = ipcd;
        err = 0;
 out:
        return err;
 
 error_tunnel:
-       mutex_lock(&ipcomp_resource_mutex);
-error:
-       ipcomp_free_data(ipcd);
-       mutex_unlock(&ipcomp_resource_mutex);
-       kfree(ipcd);
+       ipcomp_destroy(x);
        goto out;
 }
 
@@ -443,7 +140,7 @@ static const struct xfrm_type ipcomp_type = {
        .description    = "IPCOMP4",
        .owner          = THIS_MODULE,
        .proto          = IPPROTO_COMP,
-       .init_state     = ipcomp_init_state,
+       .init_state     = ipcomp4_init_state,
        .destructor     = ipcomp_destroy,
        .input          = ipcomp_input,
        .output         = ipcomp_output
@@ -481,7 +178,7 @@ module_init(ipcomp4_init);
 module_exit(ipcomp4_fini);
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173");
+MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp/IPv4) - RFC3173");
 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
 
 MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_COMP);
index f23e60c93ef973ab43a6010cfe395d5e2897155e..90eb7cb47e7723fb57e035e447e3ff182dd46d77 100644 (file)
@@ -369,7 +369,7 @@ config IP_NF_SECURITY
        tristate "Security table"
        depends on IP_NF_IPTABLES
        depends on SECURITY
-       default m if NETFILTER_ADVANCED=n
+       depends on NETFILTER_ADVANCED
        help
          This option adds a `security' table to iptables, for use
          with Mandatory Access Control (MAC) policy.
index 3be4d07e7ed9880a17d78a5476e240a1d1d40bf0..082f5dd3156c609b324af20330c7875b58ddfbb1 100644 (file)
@@ -55,32 +55,53 @@ static struct xt_table packet_filter = {
 };
 
 /* The work comes in here from netfilter.c */
-static unsigned int arpt_hook(unsigned int hook,
-                             struct sk_buff *skb,
-                             const struct net_device *in,
-                             const struct net_device *out,
-                             int (*okfn)(struct sk_buff *))
+static unsigned int arpt_in_hook(unsigned int hook,
+                                struct sk_buff *skb,
+                                const struct net_device *in,
+                                const struct net_device *out,
+                                int (*okfn)(struct sk_buff *))
 {
-       return arpt_do_table(skb, hook, in, out, init_net.ipv4.arptable_filter);
+       return arpt_do_table(skb, hook, in, out,
+                            dev_net(in)->ipv4.arptable_filter);
+}
+
+static unsigned int arpt_out_hook(unsigned int hook,
+                                 struct sk_buff *skb,
+                                 const struct net_device *in,
+                                 const struct net_device *out,
+                                 int (*okfn)(struct sk_buff *))
+{
+       return arpt_do_table(skb, hook, in, out,
+                            dev_net(out)->ipv4.arptable_filter);
+}
+
+static unsigned int arpt_forward_hook(unsigned int hook,
+                                     struct sk_buff *skb,
+                                     const struct net_device *in,
+                                     const struct net_device *out,
+                                     int (*okfn)(struct sk_buff *))
+{
+       return arpt_do_table(skb, hook, in, out,
+                            dev_net(in)->ipv4.arptable_filter);
 }
 
 static struct nf_hook_ops arpt_ops[] __read_mostly = {
        {
-               .hook           = arpt_hook,
+               .hook           = arpt_in_hook,
                .owner          = THIS_MODULE,
                .pf             = NF_ARP,
                .hooknum        = NF_ARP_IN,
                .priority       = NF_IP_PRI_FILTER,
        },
        {
-               .hook           = arpt_hook,
+               .hook           = arpt_out_hook,
                .owner          = THIS_MODULE,
                .pf             = NF_ARP,
                .hooknum        = NF_ARP_OUT,
                .priority       = NF_IP_PRI_FILTER,
        },
        {
-               .hook           = arpt_hook,
+               .hook           = arpt_forward_hook,
                .owner          = THIS_MODULE,
                .pf             = NF_ARP,
                .hooknum        = NF_ARP_FORWARD,
index 2b472ac2263a612a3d6776764abd1410e1a7ed01..db6d312128e1f3623d78a579bca55dc9c7d125fb 100644 (file)
@@ -32,7 +32,7 @@ static struct
        struct ipt_replace repl;
        struct ipt_standard entries[3];
        struct ipt_error term;
-} initial_table __initdata = {
+} initial_table __net_initdata = {
        .repl = {
                .name = "security",
                .valid_hooks = SECURITY_VALID_HOOKS,
index e4ab0ac94f9225f4ac9f6d2f12d4ece0c1383400..380d6474cf661d91fb45ef88699c526b23dabd01 100644 (file)
@@ -1502,7 +1502,7 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
                                    rth->fl.iif != 0 ||
                                    dst_metric_locked(&rth->u.dst, RTAX_MTU) ||
                                    !net_eq(dev_net(rth->u.dst.dev), net) ||
-                                   !rt_is_expired(rth))
+                                   rt_is_expired(rth))
                                        continue;
 
                                if (new_mtu < 68 || new_mtu >= old_mtu) {
@@ -2914,7 +2914,7 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
        return 0;
 }
 
-ctl_table ipv4_route_table[] = {
+static ctl_table ipv4_route_table[] = {
        {
                .ctl_name       = NET_IPV4_ROUTE_GC_THRESH,
                .procname       = "gc_thresh",
@@ -3216,6 +3216,15 @@ int __init ip_rt_init(void)
        return rc;
 }
 
+/*
+ * We really need to sanitize the damn ipv4 init order, then all
+ * this nonsense will go away.
+ */
+void __init ip_static_sysctl_init(void)
+{
+       register_sysctl_paths(ipv4_route_path, ipv4_route_table);
+}
+
 EXPORT_SYMBOL(__ip_select_ident);
 EXPORT_SYMBOL(ip_route_input);
 EXPORT_SYMBOL(ip_route_output_key);
index 51bc24d3b8a71580a097ff13df9a4781f10b0575..9d38005abbace6956bf3a5493aaacf58d7a9d90b 100644 (file)
@@ -299,6 +299,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
        ireq->rmt_port          = th->source;
        ireq->loc_addr          = ip_hdr(skb)->daddr;
        ireq->rmt_addr          = ip_hdr(skb)->saddr;
+       ireq->ecn_ok            = 0;
        ireq->snd_wscale        = tcp_opt.snd_wscale;
        ireq->rcv_wscale        = tcp_opt.rcv_wscale;
        ireq->sack_ok           = tcp_opt.sack_ok;
index 14ef202a2254f21a57e4c7e5dfdd666e8ef65e63..770d827f5ab87a75ff6fcaa19a83f3fd7b7f112c 100644 (file)
@@ -401,13 +401,6 @@ static struct ctl_table ipv4_table[] = {
                .proc_handler   = &ipv4_local_port_range,
                .strategy       = &ipv4_sysctl_local_port_range,
        },
-       {
-               .ctl_name       = NET_IPV4_ROUTE,
-               .procname       = "route",
-               .maxlen         = 0,
-               .mode           = 0555,
-               .child          = ipv4_route_table
-       },
 #ifdef CONFIG_IP_MULTICAST
        {
                .ctl_name       = NET_IPV4_IGMP_MAX_MEMBERSHIPS,
index 0b491bf03db48e275e0b4ad2978d80e9ffd92d57..1ab341e5d3e0f70383fdfa460b0ee9071b282df7 100644 (file)
@@ -1096,7 +1096,7 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied)
 #if TCP_DEBUG
        struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
 
-       BUG_TRAP(!skb || before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq));
+       WARN_ON(skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq));
 #endif
 
        if (inet_csk_ack_scheduled(sk)) {
@@ -1358,7 +1358,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                                goto found_ok_skb;
                        if (tcp_hdr(skb)->fin)
                                goto found_fin_ok;
-                       BUG_TRAP(flags & MSG_PEEK);
+                       WARN_ON(!(flags & MSG_PEEK));
                        skb = skb->next;
                } while (skb != (struct sk_buff *)&sk->sk_receive_queue);
 
@@ -1421,8 +1421,8 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
                        tp->ucopy.len = len;
 
-                       BUG_TRAP(tp->copied_seq == tp->rcv_nxt ||
-                                (flags & (MSG_PEEK | MSG_TRUNC)));
+                       WARN_ON(tp->copied_seq != tp->rcv_nxt &&
+                               !(flags & (MSG_PEEK | MSG_TRUNC)));
 
                        /* Ugly... If prequeue is not empty, we have to
                         * process it before releasing socket, otherwise
@@ -1844,7 +1844,7 @@ adjudge_to_death:
         */
        local_bh_disable();
        bh_lock_sock(sk);
-       BUG_TRAP(!sock_owned_by_user(sk));
+       WARN_ON(sock_owned_by_user(sk));
 
        /* Have we already been destroyed by a softirq or backlog? */
        if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE)
@@ -1973,7 +1973,7 @@ int tcp_disconnect(struct sock *sk, int flags)
        memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
        __sk_dst_reset(sk);
 
-       BUG_TRAP(!inet->num || icsk->icsk_bind_hash);
+       WARN_ON(inet->num && !icsk->icsk_bind_hash);
 
        sk->sk_error_report(sk);
        return err;
index 1f5e6049883e245e5042601456d1c38f5fd21ed9..67ccce2a96bd0d7d506bc7bca08a7ac29c38fea6 100644 (file)
@@ -1629,10 +1629,10 @@ advance_sp:
 out:
 
 #if FASTRETRANS_DEBUG > 0
-       BUG_TRAP((int)tp->sacked_out >= 0);
-       BUG_TRAP((int)tp->lost_out >= 0);
-       BUG_TRAP((int)tp->retrans_out >= 0);
-       BUG_TRAP((int)tcp_packets_in_flight(tp) >= 0);
+       WARN_ON((int)tp->sacked_out < 0);
+       WARN_ON((int)tp->lost_out < 0);
+       WARN_ON((int)tp->retrans_out < 0);
+       WARN_ON((int)tcp_packets_in_flight(tp) < 0);
 #endif
        return flag;
 }
@@ -2181,7 +2181,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets)
        int err;
        unsigned int mss;
 
-       BUG_TRAP(packets <= tp->packets_out);
+       WARN_ON(packets > tp->packets_out);
        if (tp->lost_skb_hint) {
                skb = tp->lost_skb_hint;
                cnt = tp->lost_cnt_hint;
@@ -2610,7 +2610,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag)
        /* E. Check state exit conditions. State can be terminated
         *    when high_seq is ACKed. */
        if (icsk->icsk_ca_state == TCP_CA_Open) {
-               BUG_TRAP(tp->retrans_out == 0);
+               WARN_ON(tp->retrans_out != 0);
                tp->retrans_stamp = 0;
        } else if (!before(tp->snd_una, tp->high_seq)) {
                switch (icsk->icsk_ca_state) {
@@ -2972,9 +2972,9 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets)
        }
 
 #if FASTRETRANS_DEBUG > 0
-       BUG_TRAP((int)tp->sacked_out >= 0);
-       BUG_TRAP((int)tp->lost_out >= 0);
-       BUG_TRAP((int)tp->retrans_out >= 0);
+       WARN_ON((int)tp->sacked_out < 0);
+       WARN_ON((int)tp->lost_out < 0);
+       WARN_ON((int)tp->retrans_out < 0);
        if (!tp->packets_out && tcp_is_sack(tp)) {
                icsk = inet_csk(sk);
                if (tp->lost_out) {
@@ -3292,6 +3292,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
         * log. Something worked...
         */
        sk->sk_err_soft = 0;
+       icsk->icsk_probes_out = 0;
        tp->rcv_tstamp = tcp_time_stamp;
        prior_packets = tp->packets_out;
        if (!prior_packets)
@@ -3324,8 +3325,6 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
        return 1;
 
 no_queue:
-       icsk->icsk_probes_out = 0;
-
        /* If this ack opens up a zero window, clear backoff.  It was
         * being used to time the probes, and is probably far higher than
         * it needs to be for normal retransmission.
@@ -3878,7 +3877,7 @@ static void tcp_sack_remove(struct tcp_sock *tp)
                        int i;
 
                        /* RCV.NXT must cover all the block! */
-                       BUG_TRAP(!before(tp->rcv_nxt, sp->end_seq));
+                       WARN_ON(before(tp->rcv_nxt, sp->end_seq));
 
                        /* Zap this SACK, by moving forward any other SACKS. */
                        for (i=this_sack+1; i < num_sacks; i++)
index a82df6307567e61675720a9bc6f5f03dcecbdb4b..a2b06d0cc26b70075a6cd649db7cb7c19451f76c 100644 (file)
@@ -418,7 +418,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
                /* ICMPs are not backlogged, hence we cannot get
                   an established socket here.
                 */
-               BUG_TRAP(!req->sk);
+               WARN_ON(req->sk);
 
                if (seq != tcp_rsk(req)->snt_isn) {
                        NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
index 328e0cf42b3c6e164c09da5d54b29566ff5c1480..5ab6ba19c3ce8547076f9fefbdf83c60f3c01c44 100644 (file)
@@ -287,7 +287,7 @@ static void tcp_retransmit_timer(struct sock *sk)
        if (!tp->packets_out)
                goto out;
 
-       BUG_TRAP(!tcp_write_queue_empty(sk));
+       WARN_ON(tcp_write_queue_empty(sk));
 
        if (!tp->snd_wnd && !sock_flag(sk, SOCK_DEAD) &&
            !((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))) {
index 42814a2ec9d73f0249b53386e997104cde4dee64..ec992159b5f8b0e08c60d680de92da155c1abbc6 100644 (file)
@@ -96,10 +96,8 @@ config INET6_ESP
 
 config INET6_IPCOMP
        tristate "IPv6: IPComp transformation"
-       select XFRM
        select INET6_XFRM_TUNNEL
-       select CRYPTO
-       select CRYPTO_DEFLATE
+       select XFRM_IPCOMP
        ---help---
          Support for IP Payload Compression Protocol (IPComp) (RFC3173),
          typically needed for IPsec.
index 74d543d504a1d6fcfbe859235e70bd05418b4364..a7842c54f58a0905201751a9d32a7e270875aaf4 100644 (file)
@@ -313,8 +313,10 @@ static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
 void in6_dev_finish_destroy(struct inet6_dev *idev)
 {
        struct net_device *dev = idev->dev;
-       BUG_TRAP(idev->addr_list==NULL);
-       BUG_TRAP(idev->mc_list==NULL);
+
+       WARN_ON(idev->addr_list != NULL);
+       WARN_ON(idev->mc_list != NULL);
+
 #ifdef NET_REFCNT_DEBUG
        printk(KERN_DEBUG "in6_dev_finish_destroy: %s\n", dev ? dev->name : "NIL");
 #endif
@@ -517,8 +519,9 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
 
 void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
 {
-       BUG_TRAP(ifp->if_next==NULL);
-       BUG_TRAP(ifp->lst_next==NULL);
+       WARN_ON(ifp->if_next != NULL);
+       WARN_ON(ifp->lst_next != NULL);
+
 #ifdef NET_REFCNT_DEBUG
        printk(KERN_DEBUG "inet6_ifa_finish_destroy\n");
 #endif
index 3d828bc4b1cf97cbfcbd1df9e76c5b357b37a9c4..95055f8c3f35eb18d17f4848fe0ae72ed648bbc2 100644 (file)
@@ -83,7 +83,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol)
        struct inet_sock *inet;
        struct ipv6_pinfo *np;
        struct sock *sk;
-       struct list_head *p;
        struct inet_protosw *answer;
        struct proto *answer_prot;
        unsigned char answer_flags;
@@ -97,13 +96,12 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol)
                build_ehash_secret();
 
        /* Look for the requested type/protocol pair. */
-       answer = NULL;
 lookup_protocol:
        err = -ESOCKTNOSUPPORT;
        rcu_read_lock();
-       list_for_each_rcu(p, &inetsw6[sock->type]) {
-               answer = list_entry(p, struct inet_protosw, list);
+       list_for_each_entry_rcu(answer, &inetsw6[sock->type], list) {
 
+               err = 0;
                /* Check the non-wild match. */
                if (protocol == answer->protocol) {
                        if (protocol != IPPROTO_IP)
@@ -118,10 +116,9 @@ lookup_protocol:
                                break;
                }
                err = -EPROTONOSUPPORT;
-               answer = NULL;
        }
 
-       if (!answer) {
+       if (err) {
                if (try_loading_module < 2) {
                        rcu_read_unlock();
                        /*
@@ -153,7 +150,7 @@ lookup_protocol:
        answer_flags = answer->flags;
        rcu_read_unlock();
 
-       BUG_TRAP(answer_prot->slab != NULL);
+       WARN_ON(answer_prot->slab == NULL);
 
        err = -ENOBUFS;
        sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot);
@@ -937,6 +934,11 @@ static int __init inet6_init(void)
        if (err)
                goto out_unregister_sock;
 
+#ifdef CONFIG_SYSCTL
+       err = ipv6_static_sysctl_register();
+       if (err)
+               goto static_sysctl_fail;
+#endif
        /*
         *      ipngwg API draft makes clear that the correct semantics
         *      for TCP and UDP is to consider one TCP and UDP instance
@@ -1061,6 +1063,10 @@ ipmr_fail:
 icmp_fail:
        unregister_pernet_subsys(&inet6_net_ops);
 register_pernet_fail:
+#ifdef CONFIG_SYSCTL
+       ipv6_static_sysctl_unregister();
+static_sysctl_fail:
+#endif
        cleanup_ipv6_mibs();
 out_unregister_sock:
        sock_unregister(PF_INET6);
@@ -1116,6 +1122,9 @@ static void __exit inet6_exit(void)
        rawv6_exit();
 
        unregister_pernet_subsys(&inet6_net_ops);
+#ifdef CONFIG_SYSCTL
+       ipv6_static_sysctl_unregister();
+#endif
        cleanup_ipv6_mibs();
        proto_unregister(&rawv6_prot);
        proto_unregister(&udplitev6_prot);
index 87801cc1b2f88405b363ebb11b25d58c1d16eea5..16d43f20b32f83c5994cb4d1479c6393c5ae0961 100644 (file)
@@ -98,7 +98,7 @@ struct request_sock *inet6_csk_search_req(const struct sock *sk,
                    ipv6_addr_equal(&treq->rmt_addr, raddr) &&
                    ipv6_addr_equal(&treq->loc_addr, laddr) &&
                    (!treq->iif || treq->iif == iif)) {
-                       BUG_TRAP(req->sk == NULL);
+                       WARN_ON(req->sk != NULL);
                        *prevp = prev;
                        return req;
                }
index 00a8a5f9380c3d454419c75074a5eccf3c2bc4f7..1646a565825513421332b02411f00aa863f9c261 100644 (file)
@@ -28,7 +28,7 @@ void __inet6_hash(struct sock *sk)
        struct hlist_head *list;
        rwlock_t *lock;
 
-       BUG_TRAP(sk_unhashed(sk));
+       WARN_ON(!sk_unhashed(sk));
 
        if (sk->sk_state == TCP_LISTEN) {
                list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
@@ -202,7 +202,7 @@ unique:
         * in hash table socket with a funny identity. */
        inet->num = lport;
        inet->sport = htons(lport);
-       BUG_TRAP(sk_unhashed(sk));
+       WARN_ON(!sk_unhashed(sk));
        __sk_add_node(sk, &head->chain);
        sk->sk_hash = hash;
        sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
index 08ea2de28d63c358eeec0a3b59469914dd3fca4b..52dddc25d3e6e6c96a83fd7ccd6ade53b9160fa0 100644 (file)
@@ -287,7 +287,7 @@ static int fib6_dump_node(struct fib6_walker_t *w)
                        w->leaf = rt;
                        return 1;
                }
-               BUG_TRAP(res!=0);
+               WARN_ON(res == 0);
        }
        w->leaf = NULL;
        return 0;
@@ -778,7 +778,7 @@ out:
                        pn->leaf = fib6_find_prefix(info->nl_net, pn);
 #if RT6_DEBUG >= 2
                        if (!pn->leaf) {
-                               BUG_TRAP(pn->leaf != NULL);
+                               WARN_ON(pn->leaf == NULL);
                                pn->leaf = info->nl_net->ipv6.ip6_null_entry;
                        }
 #endif
@@ -942,7 +942,7 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
 
 #ifdef CONFIG_IPV6_SUBTREES
        if (src_len) {
-               BUG_TRAP(saddr!=NULL);
+               WARN_ON(saddr == NULL);
                if (fn && fn->subtree)
                        fn = fib6_locate_1(fn->subtree, saddr, src_len,
                                           offsetof(struct rt6_info, rt6i_src));
@@ -996,9 +996,9 @@ static struct fib6_node *fib6_repair_tree(struct net *net,
                RT6_TRACE("fixing tree: plen=%d iter=%d\n", fn->fn_bit, iter);
                iter++;
 
-               BUG_TRAP(!(fn->fn_flags&RTN_RTINFO));
-               BUG_TRAP(!(fn->fn_flags&RTN_TL_ROOT));
-               BUG_TRAP(fn->leaf==NULL);
+               WARN_ON(fn->fn_flags & RTN_RTINFO);
+               WARN_ON(fn->fn_flags & RTN_TL_ROOT);
+               WARN_ON(fn->leaf != NULL);
 
                children = 0;
                child = NULL;
@@ -1014,7 +1014,7 @@ static struct fib6_node *fib6_repair_tree(struct net *net,
                        fn->leaf = fib6_find_prefix(net, fn);
 #if RT6_DEBUG >= 2
                        if (fn->leaf==NULL) {
-                               BUG_TRAP(fn->leaf);
+                               WARN_ON(!fn->leaf);
                                fn->leaf = net->ipv6.ip6_null_entry;
                        }
 #endif
@@ -1025,16 +1025,17 @@ static struct fib6_node *fib6_repair_tree(struct net *net,
                pn = fn->parent;
 #ifdef CONFIG_IPV6_SUBTREES
                if (FIB6_SUBTREE(pn) == fn) {
-                       BUG_TRAP(fn->fn_flags&RTN_ROOT);
+                       WARN_ON(!(fn->fn_flags & RTN_ROOT));
                        FIB6_SUBTREE(pn) = NULL;
                        nstate = FWS_L;
                } else {
-                       BUG_TRAP(!(fn->fn_flags&RTN_ROOT));
+                       WARN_ON(fn->fn_flags & RTN_ROOT);
 #endif
                        if (pn->right == fn) pn->right = child;
                        else if (pn->left == fn) pn->left = child;
 #if RT6_DEBUG >= 2
-                       else BUG_TRAP(0);
+                       else
+                               WARN_ON(1);
 #endif
                        if (child)
                                child->parent = pn;
@@ -1154,14 +1155,14 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
 
 #if RT6_DEBUG >= 2
        if (rt->u.dst.obsolete>0) {
-               BUG_TRAP(fn==NULL);
+               WARN_ON(fn != NULL);
                return -ENOENT;
        }
 #endif
        if (fn == NULL || rt == net->ipv6.ip6_null_entry)
                return -ENOENT;
 
-       BUG_TRAP(fn->fn_flags&RTN_RTINFO);
+       WARN_ON(!(fn->fn_flags & RTN_RTINFO));
 
        if (!(rt->rt6i_flags&RTF_CACHE)) {
                struct fib6_node *pn = fn;
@@ -1266,7 +1267,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w)
                        w->node = pn;
 #ifdef CONFIG_IPV6_SUBTREES
                        if (FIB6_SUBTREE(pn) == fn) {
-                               BUG_TRAP(fn->fn_flags&RTN_ROOT);
+                               WARN_ON(!(fn->fn_flags & RTN_ROOT));
                                w->state = FWS_L;
                                continue;
                        }
@@ -1281,7 +1282,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w)
                                continue;
                        }
 #if RT6_DEBUG >= 2
-                       BUG_TRAP(0);
+                       WARN_ON(1);
 #endif
                }
        }
@@ -1323,7 +1324,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
                        }
                        return 0;
                }
-               BUG_TRAP(res==0);
+               WARN_ON(res != 0);
        }
        w->leaf = rt;
        return 0;
index 6407c64ea4a5c08f1e6260b04e70a4cc142fb3e0..6811901e6b1ec94c0e3084de16c7b8c408bb0503 100644 (file)
@@ -116,7 +116,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
        __skb_pull(newskb, skb_network_offset(newskb));
        newskb->pkt_type = PACKET_LOOPBACK;
        newskb->ip_summed = CHECKSUM_UNNECESSARY;
-       BUG_TRAP(newskb->dst);
+       WARN_ON(!newskb->dst);
 
        netif_rx(newskb);
        return 0;
index ee6de425ce6b8c28873c8fdd0148b19c584f6d7f..4545e4306862b104217aa5189eac1d4b64c1b43e 100644 (file)
 #include <linux/icmpv6.h>
 #include <linux/mutex.h>
 
-struct ipcomp6_tfms {
-       struct list_head list;
-       struct crypto_comp **tfms;
-       int users;
-};
-
-static DEFINE_MUTEX(ipcomp6_resource_mutex);
-static void **ipcomp6_scratches;
-static int ipcomp6_scratch_users;
-static LIST_HEAD(ipcomp6_tfms_list);
-
-static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
-{
-       int nexthdr;
-       int err = -ENOMEM;
-       struct ip_comp_hdr *ipch;
-       int plen, dlen;
-       struct ipcomp_data *ipcd = x->data;
-       u8 *start, *scratch;
-       struct crypto_comp *tfm;
-       int cpu;
-
-       if (skb_linearize_cow(skb))
-               goto out;
-
-       skb->ip_summed = CHECKSUM_NONE;
-
-       /* Remove ipcomp header and decompress original payload */
-       ipch = (void *)skb->data;
-       nexthdr = ipch->nexthdr;
-
-       skb->transport_header = skb->network_header + sizeof(*ipch);
-       __skb_pull(skb, sizeof(*ipch));
-
-       /* decompression */
-       plen = skb->len;
-       dlen = IPCOMP_SCRATCH_SIZE;
-       start = skb->data;
-
-       cpu = get_cpu();
-       scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
-       tfm = *per_cpu_ptr(ipcd->tfms, cpu);
-
-       err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
-       if (err)
-               goto out_put_cpu;
-
-       if (dlen < (plen + sizeof(*ipch))) {
-               err = -EINVAL;
-               goto out_put_cpu;
-       }
-
-       err = pskb_expand_head(skb, 0, dlen - plen, GFP_ATOMIC);
-       if (err) {
-               goto out_put_cpu;
-       }
-
-       skb->truesize += dlen - plen;
-       __skb_put(skb, dlen - plen);
-       skb_copy_to_linear_data(skb, scratch, dlen);
-       err = nexthdr;
-
-out_put_cpu:
-       put_cpu();
-out:
-       return err;
-}
-
-static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
-{
-       int err;
-       struct ip_comp_hdr *ipch;
-       struct ipcomp_data *ipcd = x->data;
-       int plen, dlen;
-       u8 *start, *scratch;
-       struct crypto_comp *tfm;
-       int cpu;
-
-       /* check whether datagram len is larger than threshold */
-       if (skb->len < ipcd->threshold) {
-               goto out_ok;
-       }
-
-       if (skb_linearize_cow(skb))
-               goto out_ok;
-
-       /* compression */
-       plen = skb->len;
-       dlen = IPCOMP_SCRATCH_SIZE;
-       start = skb->data;
-
-       cpu = get_cpu();
-       scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
-       tfm = *per_cpu_ptr(ipcd->tfms, cpu);
-
-       local_bh_disable();
-       err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
-       local_bh_enable();
-       if (err || (dlen + sizeof(*ipch)) >= plen) {
-               put_cpu();
-               goto out_ok;
-       }
-       memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
-       put_cpu();
-       pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
-
-       /* insert ipcomp header and replace datagram */
-       ipch = ip_comp_hdr(skb);
-       ipch->nexthdr = *skb_mac_header(skb);
-       ipch->flags = 0;
-       ipch->cpi = htons((u16 )ntohl(x->id.spi));
-       *skb_mac_header(skb) = IPPROTO_COMP;
-
-out_ok:
-       skb_push(skb, -skb_network_offset(skb));
-
-       return 0;
-}
-
 static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                                int type, int code, int offset, __be32 info)
 {
@@ -251,160 +132,9 @@ out:
        return err;
 }
 
-static void ipcomp6_free_scratches(void)
-{
-       int i;
-       void **scratches;
-
-       if (--ipcomp6_scratch_users)
-               return;
-
-       scratches = ipcomp6_scratches;
-       if (!scratches)
-               return;
-
-       for_each_possible_cpu(i) {
-               void *scratch = *per_cpu_ptr(scratches, i);
-
-               vfree(scratch);
-       }
-
-       free_percpu(scratches);
-}
-
-static void **ipcomp6_alloc_scratches(void)
-{
-       int i;
-       void **scratches;
-
-       if (ipcomp6_scratch_users++)
-               return ipcomp6_scratches;
-
-       scratches = alloc_percpu(void *);
-       if (!scratches)
-               return NULL;
-
-       ipcomp6_scratches = scratches;
-
-       for_each_possible_cpu(i) {
-               void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
-               if (!scratch)
-                       return NULL;
-               *per_cpu_ptr(scratches, i) = scratch;
-       }
-
-       return scratches;
-}
-
-static void ipcomp6_free_tfms(struct crypto_comp **tfms)
-{
-       struct ipcomp6_tfms *pos;
-       int cpu;
-
-       list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
-               if (pos->tfms == tfms)
-                       break;
-       }
-
-       BUG_TRAP(pos);
-
-       if (--pos->users)
-               return;
-
-       list_del(&pos->list);
-       kfree(pos);
-
-       if (!tfms)
-               return;
-
-       for_each_possible_cpu(cpu) {
-               struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu);
-               crypto_free_comp(tfm);
-       }
-       free_percpu(tfms);
-}
-
-static struct crypto_comp **ipcomp6_alloc_tfms(const char *alg_name)
-{
-       struct ipcomp6_tfms *pos;
-       struct crypto_comp **tfms;
-       int cpu;
-
-       /* This can be any valid CPU ID so we don't need locking. */
-       cpu = raw_smp_processor_id();
-
-       list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
-               struct crypto_comp *tfm;
-
-               tfms = pos->tfms;
-               tfm = *per_cpu_ptr(tfms, cpu);
-
-               if (!strcmp(crypto_comp_name(tfm), alg_name)) {
-                       pos->users++;
-                       return tfms;
-               }
-       }
-
-       pos = kmalloc(sizeof(*pos), GFP_KERNEL);
-       if (!pos)
-               return NULL;
-
-       pos->users = 1;
-       INIT_LIST_HEAD(&pos->list);
-       list_add(&pos->list, &ipcomp6_tfms_list);
-
-       pos->tfms = tfms = alloc_percpu(struct crypto_comp *);
-       if (!tfms)
-               goto error;
-
-       for_each_possible_cpu(cpu) {
-               struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
-                                                           CRYPTO_ALG_ASYNC);
-               if (IS_ERR(tfm))
-                       goto error;
-               *per_cpu_ptr(tfms, cpu) = tfm;
-       }
-
-       return tfms;
-
-error:
-       ipcomp6_free_tfms(tfms);
-       return NULL;
-}
-
-static void ipcomp6_free_data(struct ipcomp_data *ipcd)
-{
-       if (ipcd->tfms)
-               ipcomp6_free_tfms(ipcd->tfms);
-       ipcomp6_free_scratches();
-}
-
-static void ipcomp6_destroy(struct xfrm_state *x)
-{
-       struct ipcomp_data *ipcd = x->data;
-       if (!ipcd)
-               return;
-       xfrm_state_delete_tunnel(x);
-       mutex_lock(&ipcomp6_resource_mutex);
-       ipcomp6_free_data(ipcd);
-       mutex_unlock(&ipcomp6_resource_mutex);
-       kfree(ipcd);
-
-       xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
-}
-
 static int ipcomp6_init_state(struct xfrm_state *x)
 {
-       int err;
-       struct ipcomp_data *ipcd;
-       struct xfrm_algo_desc *calg_desc;
-
-       err = -EINVAL;
-       if (!x->calg)
-               goto out;
-
-       if (x->encap)
-               goto out;
+       int err = -EINVAL;
 
        x->props.header_len = 0;
        switch (x->props.mode) {
@@ -417,39 +147,21 @@ static int ipcomp6_init_state(struct xfrm_state *x)
                goto out;
        }
 
-       err = -ENOMEM;
-       ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
-       if (!ipcd)
+       err = ipcomp_init_state(x);
+       if (err)
                goto out;
 
-       mutex_lock(&ipcomp6_resource_mutex);
-       if (!ipcomp6_alloc_scratches())
-               goto error;
-
-       ipcd->tfms = ipcomp6_alloc_tfms(x->calg->alg_name);
-       if (!ipcd->tfms)
-               goto error;
-       mutex_unlock(&ipcomp6_resource_mutex);
-
        if (x->props.mode == XFRM_MODE_TUNNEL) {
                err = ipcomp6_tunnel_attach(x);
                if (err)
                        goto error_tunnel;
        }
 
-       calg_desc = xfrm_calg_get_byname(x->calg->alg_name, 0);
-       BUG_ON(!calg_desc);
-       ipcd->threshold = calg_desc->uinfo.comp.threshold;
-       x->data = ipcd;
        err = 0;
 out:
        return err;
 error_tunnel:
-       mutex_lock(&ipcomp6_resource_mutex);
-error:
-       ipcomp6_free_data(ipcd);
-       mutex_unlock(&ipcomp6_resource_mutex);
-       kfree(ipcd);
+       ipcomp_destroy(x);
 
        goto out;
 }
@@ -460,9 +172,9 @@ static const struct xfrm_type ipcomp6_type =
        .owner          = THIS_MODULE,
        .proto          = IPPROTO_COMP,
        .init_state     = ipcomp6_init_state,
-       .destructor     = ipcomp6_destroy,
-       .input          = ipcomp6_input,
-       .output         = ipcomp6_output,
+       .destructor     = ipcomp_destroy,
+       .input          = ipcomp_input,
+       .output         = ipcomp_output,
        .hdr_offset     = xfrm6_find_1stfragopt,
 };
 
index ad1cc5bbf977a9d766a78a065277d7aa457f7806..31295c8f619688099477dd5e230c61f8199d51da 100644 (file)
@@ -164,8 +164,8 @@ static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb)
                        calc_padlen(sizeof(*dstopt), 6));
 
        hao->type = IPV6_TLV_HAO;
+       BUILD_BUG_ON(sizeof(*hao) != 18);
        hao->length = sizeof(*hao) - 2;
-       BUG_TRAP(hao->length == 16);
 
        len = ((char *)hao - (char *)dstopt) + sizeof(*hao);
 
@@ -174,7 +174,7 @@ static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb)
        memcpy(&iph->saddr, x->coaddr, sizeof(iph->saddr));
        spin_unlock_bh(&x->lock);
 
-       BUG_TRAP(len == x->props.header_len);
+       WARN_ON(len != x->props.header_len);
        dstopt->hdrlen = (x->props.header_len >> 3) - 1;
 
        return 0;
@@ -317,7 +317,7 @@ static int mip6_destopt_init_state(struct xfrm_state *x)
        x->props.header_len = sizeof(struct ipv6_destopt_hdr) +
                calc_padlen(sizeof(struct ipv6_destopt_hdr), 6) +
                sizeof(struct ipv6_destopt_hao);
-       BUG_TRAP(x->props.header_len == 24);
+       WARN_ON(x->props.header_len != 24);
 
        return 0;
 }
@@ -380,7 +380,7 @@ static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb)
        rt2->rt_hdr.segments_left = 1;
        memset(&rt2->reserved, 0, sizeof(rt2->reserved));
 
-       BUG_TRAP(rt2->rt_hdr.hdrlen == 2);
+       WARN_ON(rt2->rt_hdr.hdrlen != 2);
 
        memcpy(&rt2->addr, &iph->daddr, sizeof(rt2->addr));
        spin_lock_bh(&x->lock);
index 689dec899c57d441ad362fa720d35e2c055e0978..0cfcce7b18d8105b46aab7d9f45f4fa9eb1c8364 100644 (file)
@@ -213,7 +213,7 @@ config IP6_NF_SECURITY
        tristate "Security table"
        depends on IP6_NF_IPTABLES
        depends on SECURITY
-       default m if NETFILTER_ADVANCED=n
+       depends on NETFILTER_ADVANCED
        help
          This option adds a `security' table to iptables, for use
          with Mandatory Access Control (MAC) policy.
index a07abee30497ad25dc8eeee9a98715d9deedb176..6e7131036bc6bf7603daa7401ff418fb836368c0 100644 (file)
@@ -31,7 +31,7 @@ static struct
        struct ip6t_replace repl;
        struct ip6t_standard entries[3];
        struct ip6t_error term;
-} initial_table __initdata = {
+} initial_table __net_initdata = {
        .repl = {
                .name = "security",
                .valid_hooks = SECURITY_VALID_HOOKS,
index cf20bc4fd60db346eab94b35ec3b84ee255dd265..52d06dd4b8176f01a4e0b796e38d1fedf5c8c7c8 100644 (file)
@@ -416,8 +416,8 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
 
        fq_kill(fq);
 
-       BUG_TRAP(head != NULL);
-       BUG_TRAP(NFCT_FRAG6_CB(head)->offset == 0);
+       WARN_ON(head == NULL);
+       WARN_ON(NFCT_FRAG6_CB(head)->offset != 0);
 
        /* Unfragmented part is taken from the first segment. */
        payload_len = ((head->data - skb_network_header(head)) -
index 6ab957ec2dd6d4a64bee43cc20d754e7e85ca579..89184b576e2377f1190c69a36476d320e263c265 100644 (file)
@@ -473,8 +473,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
                fq->q.fragments = head;
        }
 
-       BUG_TRAP(head != NULL);
-       BUG_TRAP(FRAG6_CB(head)->offset == 0);
+       WARN_ON(head == NULL);
+       WARN_ON(FRAG6_CB(head)->offset != 0);
 
        /* Unfragmented part is taken from the first segment. */
        payload_len = ((head->data - skb_network_header(head)) -
index 6a68eeb7bbf8ba76b5834d5960991aad4a3021da..a46badd1082d9c55a2388dd3e31d2882db68df06 100644 (file)
@@ -223,6 +223,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 
        req->expires = 0UL;
        req->retrans = 0;
+       ireq->ecn_ok            = 0;
        ireq->snd_wscale        = tcp_opt.snd_wscale;
        ireq->rcv_wscale        = tcp_opt.rcv_wscale;
        ireq->sack_ok           = tcp_opt.sack_ok;
index 5c99274558bf40412b738c4c71484c2a082e7029..e6dfaeac6be3f9a646b832a57938b7b5832da53b 100644 (file)
@@ -150,3 +150,19 @@ void ipv6_sysctl_unregister(void)
        unregister_net_sysctl_table(ip6_header);
        unregister_pernet_subsys(&ipv6_sysctl_net_ops);
 }
+
+static struct ctl_table_header *ip6_base;
+
+int ipv6_static_sysctl_register(void)
+{
+       static struct ctl_table empty[1];
+       ip6_base = register_net_sysctl_rotable(net_ipv6_ctl_path, empty);
+       if (ip6_base == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+void ipv6_static_sysctl_unregister(void)
+{
+       unregister_net_sysctl_table(ip6_base);
+}
index ae45f98350143e524798fa6ef4b8014c07685dc1..cff778b23a7feca249b9edab81c9d6afdee8597b 100644 (file)
@@ -421,7 +421,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                /* ICMPs are not backlogged, hence we cannot get
                 * an established socket here.
                 */
-               BUG_TRAP(req->sk == NULL);
+               WARN_ON(req->sk != NULL);
 
                if (seq != tcp_rsk(req)->snt_isn) {
                        NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
index f0fc46c8038d0632bca9fb3b031af5b908f1ff2d..d628df97e02ed5b81002e725bdda6f200649fc08 100644 (file)
@@ -96,8 +96,8 @@ static void pfkey_sock_destruct(struct sock *sk)
                return;
        }
 
-       BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
-       BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
+       WARN_ON(atomic_read(&sk->sk_rmem_alloc));
+       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
 
        atomic_dec(&pfkey_socks_nr);
 }
index 3469bc71a385eacb66b2099c334833469ec889cf..4b2c769d555fce4d6131b08f5aac6d53b3a48be6 100644 (file)
@@ -95,7 +95,7 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
        newlen = newoff + t->len;
        rcu_read_unlock();
 
-       new = krealloc(ct->ext, newlen, gfp);
+       new = __krealloc(ct->ext, newlen, gfp);
        if (!new)
                return NULL;
 
@@ -115,10 +115,10 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
                ct->ext = new;
        }
 
-       ct->ext->offset[id] = newoff;
-       ct->ext->len = newlen;
-       memset((void *)ct->ext + newoff, 0, newlen - newoff);
-       return (void *)ct->ext + newoff;
+       new->offset[id] = newoff;
+       new->len = newlen;
+       memset((void *)new + newoff, 0, newlen - newoff);
+       return (void *)new + newoff;
 }
 EXPORT_SYMBOL(__nf_ct_ext_add);
 
index 98bfe277eab22ef15ac39cd08185f0f63cc8030e..b0eacc0007cc39b1c19ccf0c38800e0e50a8d608 100644 (file)
@@ -158,9 +158,10 @@ static void netlink_sock_destruct(struct sock *sk)
                printk(KERN_ERR "Freeing alive netlink socket %p\n", sk);
                return;
        }
-       BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
-       BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
-       BUG_TRAP(!nlk_sk(sk)->groups);
+
+       WARN_ON(atomic_read(&sk->sk_rmem_alloc));
+       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+       WARN_ON(nlk_sk(sk)->groups);
 }
 
 /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on
index d56cae112dc83b4223b28924f508b426a02c0594..c718e7e3f7dea66facd1483b0b27dd5b4ef974bc 100644 (file)
@@ -260,8 +260,8 @@ static inline struct packet_sock *pkt_sk(struct sock *sk)
 
 static void packet_sock_destruct(struct sock *sk)
 {
-       BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
-       BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
+       WARN_ON(atomic_read(&sk->sk_rmem_alloc));
+       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
 
        if (!sock_flag(sk, SOCK_DEAD)) {
                printk("Attempt to release alive packet socket: %p\n", sk);
index 4b2682feeedcbcf61d2b1e9fb729ad9cfff9abc1..32e489118bebcc7462316456cf9a4e8dffeaae31 100644 (file)
@@ -660,9 +660,9 @@ static void rxrpc_sock_destructor(struct sock *sk)
 
        rxrpc_purge_queue(&sk->sk_receive_queue);
 
-       BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
-       BUG_TRAP(sk_unhashed(sk));
-       BUG_TRAP(!sk->sk_socket);
+       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+       WARN_ON(!sk_unhashed(sk));
+       WARN_ON(sk->sk_socket);
 
        if (!sock_flag(sk, SOCK_DEAD)) {
                printk("Attempt to release alive rxrpc socket: %p\n", sk);
index 74e662cbb2c5b7a61a1c0815a358899c6abc694a..d308c19aa3f9be6d6087aecfa27dcc55dead6eed 100644 (file)
@@ -41,7 +41,7 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
                        return;
                }
        }
-       BUG_TRAP(0);
+       WARN_ON(1);
 }
 EXPORT_SYMBOL(tcf_hash_destroy);
 
index 32c3f9d9fb7ad89d06e3b45fc5c664936e9b56ad..38015b49394755d06cd1cfa56306ea358c968a49 100644 (file)
@@ -116,7 +116,7 @@ static void tcf_police_destroy(struct tcf_police *p)
                        return;
                }
        }
-       BUG_TRAP(0);
+       WARN_ON(1);
 }
 
 static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
index 527db2559dd28163173d4ee875be430d31cc7f1f..246f9065ce34b0ad8f7b176807dea7d50221b087 100644 (file)
@@ -345,7 +345,7 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode* key)
                        }
                }
        }
-       BUG_TRAP(0);
+       WARN_ON(1);
        return 0;
 }
 
@@ -368,7 +368,7 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
        struct tc_u_common *tp_c = tp->data;
        struct tc_u_hnode **hn;
 
-       BUG_TRAP(!ht->refcnt);
+       WARN_ON(ht->refcnt);
 
        u32_clear_hnode(tp, ht);
 
@@ -380,7 +380,7 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
                }
        }
 
-       BUG_TRAP(0);
+       WARN_ON(1);
        return -ENOENT;
 }
 
@@ -389,7 +389,7 @@ static void u32_destroy(struct tcf_proto *tp)
        struct tc_u_common *tp_c = tp->data;
        struct tc_u_hnode *root_ht = xchg(&tp->root, NULL);
 
-       BUG_TRAP(root_ht != NULL);
+       WARN_ON(root_ht == NULL);
 
        if (root_ht && --root_ht->refcnt == 0)
                u32_destroy_hnode(tp, root_ht);
@@ -407,7 +407,7 @@ static void u32_destroy(struct tcf_proto *tp)
                while ((ht = tp_c->hlist) != NULL) {
                        tp_c->hlist = ht->next;
 
-                       BUG_TRAP(ht->refcnt == 0);
+                       WARN_ON(ht->refcnt != 0);
 
                        kfree(ht);
                }
index 04faa835be173bf703cd899038f8ba3c0c686130..6b517b9dac5be93fb959e008b678904bf1c467a0 100644 (file)
@@ -162,7 +162,7 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
        qdisc_destroy(flow->q);
        tcf_destroy_chain(&flow->filter_list);
        if (flow->sock) {
-               pr_debug("atm_tc_put: f_count %d\n",
+               pr_debug("atm_tc_put: f_count %ld\n",
                        file_count(flow->sock->file));
                flow->vcc->pop = flow->old_pop;
                sockfd_put(flow->sock);
@@ -259,7 +259,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
        sock = sockfd_lookup(fd, &error);
        if (!sock)
                return error;   /* f_count++ */
-       pr_debug("atm_tc_change: f_count %d\n", file_count(sock->file));
+       pr_debug("atm_tc_change: f_count %ld\n", file_count(sock->file));
        if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) {
                error = -EPROTOTYPE;
                goto err_out;
index f1d2f8ec8b4cde95e206ff184627ae9b8bdcf55b..14954bf4a6836c8fe21731072af228d23f85b33e 100644 (file)
@@ -1175,7 +1175,7 @@ static void cbq_unlink_class(struct cbq_class *this)
                                this->tparent->children = NULL;
                }
        } else {
-               BUG_TRAP(this->sibling == this);
+               WARN_ON(this->sibling != this);
        }
 }
 
@@ -1699,7 +1699,7 @@ static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
 {
        struct cbq_sched_data *q = qdisc_priv(sch);
 
-       BUG_TRAP(!cl->filters);
+       WARN_ON(cl->filters);
 
        tcf_destroy_chain(&cl->filter_list);
        qdisc_destroy(cl->q);
index 4ac7e3a8c253b0e7754ac77071a6c7348a514841..fd2a6cadb1155429fff6de7aa4045ef00899deb9 100644 (file)
@@ -736,9 +736,9 @@ static void shutdown_scheduler_queue(struct net_device *dev,
                dev_queue->qdisc = qdisc_default;
                dev_queue->qdisc_sleeping = qdisc_default;
 
-               spin_lock(root_lock);
+               spin_lock_bh(root_lock);
                qdisc_destroy(qdisc);
-               spin_unlock(root_lock);
+               spin_unlock_bh(root_lock);
        }
 }
 
@@ -746,5 +746,5 @@ void dev_shutdown(struct net_device *dev)
 {
        netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc);
        shutdown_scheduler_queue(dev, &dev->rx_queue, NULL);
-       BUG_TRAP(!timer_pending(&dev->watchdog_timer));
+       WARN_ON(timer_pending(&dev->watchdog_timer));
 }
index 30c999c61b01f1ab771fb3bb75984b7595fbaee4..75a40951c4f24edc68684462980e74dfd7123214 100644 (file)
@@ -524,7 +524,7 @@ htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
  */
 static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
 {
-       BUG_TRAP(!cl->level && cl->un.leaf.q && cl->un.leaf.q->q.qlen);
+       WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen);
 
        if (!cl->prio_activity) {
                cl->prio_activity = 1 << (cl->un.leaf.aprio = cl->un.leaf.prio);
@@ -542,7 +542,7 @@ static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
  */
 static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
 {
-       BUG_TRAP(cl->prio_activity);
+       WARN_ON(!cl->prio_activity);
 
        htb_deactivate_prios(q, cl);
        cl->prio_activity = 0;
@@ -757,7 +757,7 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
                u32 *pid;
        } stk[TC_HTB_MAXDEPTH], *sp = stk;
 
-       BUG_TRAP(tree->rb_node);
+       WARN_ON(!tree->rb_node);
        sp->root = tree->rb_node;
        sp->pptr = pptr;
        sp->pid = pid;
@@ -777,7 +777,7 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
                                *sp->pptr = (*sp->pptr)->rb_left;
                        if (sp > stk) {
                                sp--;
-                               BUG_TRAP(*sp->pptr);
+                               WARN_ON(!*sp->pptr);
                                if (!*sp->pptr)
                                        return NULL;
                                htb_next_rb_node(sp->pptr);
@@ -792,7 +792,7 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
                        sp->pid = cl->un.inner.last_ptr_id + prio;
                }
        }
-       BUG_TRAP(0);
+       WARN_ON(1);
        return NULL;
 }
 
@@ -810,7 +810,7 @@ static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
 
        do {
 next:
-               BUG_TRAP(cl);
+               WARN_ON(!cl);
                if (!cl)
                        return NULL;
 
@@ -1185,7 +1185,7 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
 {
        struct htb_class *parent = cl->parent;
 
-       BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity);
+       WARN_ON(cl->level || !cl->un.leaf.q || cl->prio_activity);
 
        if (parent->cmode != HTB_CAN_SEND)
                htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
@@ -1205,7 +1205,7 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
 static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
 {
        if (!cl->level) {
-               BUG_TRAP(cl->un.leaf.q);
+               WARN_ON(!cl->un.leaf.q);
                qdisc_destroy(cl->un.leaf.q);
        }
        gen_kill_estimator(&cl->bstats, &cl->rate_est);
index ec2a0a33fd780e8c8185c74cbbcf453dbebeb99a..8472b8b349c464ac8a900d6b23241ce59efc5397 100644 (file)
@@ -464,7 +464,7 @@ static void sctp_association_destroy(struct sctp_association *asoc)
                spin_unlock_bh(&sctp_assocs_id_lock);
        }
 
-       BUG_TRAP(!atomic_read(&asoc->rmem_alloc));
+       WARN_ON(atomic_read(&asoc->rmem_alloc));
 
        if (asoc->base.malloced) {
                kfree(asoc);
index 79bece16aede7959948010158733bfaa21187df6..dbb79adf8f3c0bab606f7141e96ae96dd29b3e4c 100644 (file)
@@ -3910,7 +3910,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
                goto out;
 
        /* Map the socket to an unused fd that can be returned to the user.  */
-       retval = sock_map_fd(newsock);
+       retval = sock_map_fd(newsock, 0);
        if (retval < 0) {
                sock_release(newsock);
                goto out;
index 1ba57d88898184160c8fd3c918eba73f3cd77d00..8ef8ba81b9e2048c93363f4a2f98f73b7778cdce 100644 (file)
 #include <linux/file.h>
 #include <linux/net.h>
 #include <linux/interrupt.h>
+#include <linux/thread_info.h>
 #include <linux/rcupdate.h>
 #include <linux/netdevice.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/mutex.h>
+#include <linux/thread_info.h>
 #include <linux/wanrouter.h>
 #include <linux/if_bridge.h>
 #include <linux/if_frad.h>
@@ -263,7 +265,7 @@ static void sock_destroy_inode(struct inode *inode)
                        container_of(inode, struct socket_alloc, vfs_inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
 {
        struct socket_alloc *ei = (struct socket_alloc *)foo;
 
@@ -349,11 +351,11 @@ static struct dentry_operations sockfs_dentry_operations = {
  *     but we take care of internal coherence yet.
  */
 
-static int sock_alloc_fd(struct file **filep)
+static int sock_alloc_fd(struct file **filep, int flags)
 {
        int fd;
 
-       fd = get_unused_fd();
+       fd = get_unused_fd_flags(flags);
        if (likely(fd >= 0)) {
                struct file *file = get_empty_filp();
 
@@ -367,7 +369,7 @@ static int sock_alloc_fd(struct file **filep)
        return fd;
 }
 
-static int sock_attach_fd(struct socket *sock, struct file *file)
+static int sock_attach_fd(struct socket *sock, struct file *file, int flags)
 {
        struct dentry *dentry;
        struct qstr name = { .name = "" };
@@ -389,20 +391,20 @@ static int sock_attach_fd(struct socket *sock, struct file *file)
        init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,
                  &socket_file_ops);
        SOCK_INODE(sock)->i_fop = &socket_file_ops;
-       file->f_flags = O_RDWR;
+       file->f_flags = O_RDWR | (flags & O_NONBLOCK);
        file->f_pos = 0;
        file->private_data = sock;
 
        return 0;
 }
 
-int sock_map_fd(struct socket *sock)
+int sock_map_fd(struct socket *sock, int flags)
 {
        struct file *newfile;
-       int fd = sock_alloc_fd(&newfile);
+       int fd = sock_alloc_fd(&newfile, flags);
 
        if (likely(fd >= 0)) {
-               int err = sock_attach_fd(sock, newfile);
+               int err = sock_attach_fd(sock, newfile, flags);
 
                if (unlikely(err < 0)) {
                        put_filp(newfile);
@@ -1218,12 +1220,27 @@ asmlinkage long sys_socket(int family, int type, int protocol)
 {
        int retval;
        struct socket *sock;
+       int flags;
+
+       /* Check the SOCK_* constants for consistency.  */
+       BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
+       BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
+       BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
+       BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
+
+       flags = type & ~SOCK_TYPE_MASK;
+       if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+               return -EINVAL;
+       type &= SOCK_TYPE_MASK;
+
+       if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
+               flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
 
        retval = sock_create(family, type, protocol, &sock);
        if (retval < 0)
                goto out;
 
-       retval = sock_map_fd(sock);
+       retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
        if (retval < 0)
                goto out_release;
 
@@ -1246,6 +1263,15 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
        struct socket *sock1, *sock2;
        int fd1, fd2, err;
        struct file *newfile1, *newfile2;
+       int flags;
+
+       flags = type & ~SOCK_TYPE_MASK;
+       if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+               return -EINVAL;
+       type &= SOCK_TYPE_MASK;
+
+       if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
+               flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
 
        /*
         * Obtain the first socket and check if the underlying protocol
@@ -1264,13 +1290,13 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
        if (err < 0)
                goto out_release_both;
 
-       fd1 = sock_alloc_fd(&newfile1);
+       fd1 = sock_alloc_fd(&newfile1, flags & O_CLOEXEC);
        if (unlikely(fd1 < 0)) {
                err = fd1;
                goto out_release_both;
        }
 
-       fd2 = sock_alloc_fd(&newfile2);
+       fd2 = sock_alloc_fd(&newfile2, flags & O_CLOEXEC);
        if (unlikely(fd2 < 0)) {
                err = fd2;
                put_filp(newfile1);
@@ -1278,12 +1304,12 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
                goto out_release_both;
        }
 
-       err = sock_attach_fd(sock1, newfile1);
+       err = sock_attach_fd(sock1, newfile1, flags & O_NONBLOCK);
        if (unlikely(err < 0)) {
                goto out_fd2;
        }
 
-       err = sock_attach_fd(sock2, newfile2);
+       err = sock_attach_fd(sock2, newfile2, flags & O_NONBLOCK);
        if (unlikely(err < 0)) {
                fput(newfile1);
                goto out_fd1;
@@ -1401,14 +1427,20 @@ asmlinkage long sys_listen(int fd, int backlog)
  *     clean when we restucture accept also.
  */
 
-asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
-                          int __user *upeer_addrlen)
+long do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
+              int __user *upeer_addrlen, int flags)
 {
        struct socket *sock, *newsock;
        struct file *newfile;
        int err, len, newfd, fput_needed;
        struct sockaddr_storage address;
 
+       if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+               return -EINVAL;
+
+       if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
+               flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
+
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
@@ -1426,14 +1458,14 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
         */
        __module_get(newsock->ops->owner);
 
-       newfd = sock_alloc_fd(&newfile);
+       newfd = sock_alloc_fd(&newfile, flags & O_CLOEXEC);
        if (unlikely(newfd < 0)) {
                err = newfd;
                sock_release(newsock);
                goto out_put;
        }
 
-       err = sock_attach_fd(newsock, newfile);
+       err = sock_attach_fd(newsock, newfile, flags & O_NONBLOCK);
        if (err < 0)
                goto out_fd_simple;
 
@@ -1479,6 +1511,66 @@ out_fd:
        goto out_put;
 }
 
+#ifdef HAVE_SET_RESTORE_SIGMASK
+asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
+                           int __user *upeer_addrlen,
+                           const sigset_t __user *sigmask,
+                           size_t sigsetsize, int flags)
+{
+       sigset_t ksigmask, sigsaved;
+       int ret;
+
+       if (sigmask) {
+               /* XXX: Don't preclude handling different sized sigset_t's.  */
+               if (sigsetsize != sizeof(sigset_t))
+                       return -EINVAL;
+               if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+                       return -EFAULT;
+
+               sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+               sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+        }
+
+       ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
+
+       if (ret < 0 && signal_pending(current)) {
+               /*
+                * Don't restore the signal mask yet. Let do_signal() deliver
+                * the signal on the way back to userspace, before the signal
+                * mask is restored.
+                */
+               if (sigmask) {
+                       memcpy(&current->saved_sigmask, &sigsaved,
+                              sizeof(sigsaved));
+                       set_restore_sigmask();
+               }
+       } else if (sigmask)
+               sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+       return ret;
+}
+#else
+asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
+                           int __user *upeer_addrlen,
+                           const sigset_t __user *sigmask,
+                           size_t sigsetsize, int flags)
+{
+       /* The platform does not support restoring the signal mask in the
+        * return path.  So we do not allow using paccept() with a signal
+        * mask.  */
+       if (sigmask)
+               return -EINVAL;
+
+       return do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
+}
+#endif
+
+asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
+                          int __user *upeer_addrlen)
+{
+       return do_accept(fd, upeer_sockaddr, upeer_addrlen, 0);
+}
+
 /*
  *     Attempt to connect to a socket with the server address.  The address
  *     is in user space so we verify it is OK and move it to kernel space.
@@ -1999,10 +2091,11 @@ out:
 
 /* Argument list sizes for sys_socketcall */
 #define AL(x) ((x) * sizeof(unsigned long))
-static const unsigned char nargs[18]={
+static const unsigned char nargs[19]={
        AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
        AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-       AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)
+       AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
+       AL(6)
 };
 
 #undef AL
@@ -2021,7 +2114,7 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
        unsigned long a0, a1;
        int err;
 
-       if (call < 1 || call > SYS_RECVMSG)
+       if (call < 1 || call > SYS_PACCEPT)
                return -EINVAL;
 
        /* copy_from_user should be SMP safe. */
@@ -2050,8 +2143,8 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
                break;
        case SYS_ACCEPT:
                err =
-                   sys_accept(a0, (struct sockaddr __user *)a1,
-                              (int __user *)a[2]);
+                   do_accept(a0, (struct sockaddr __user *)a1,
+                             (int __user *)a[2], 0);
                break;
        case SYS_GETSOCKNAME:
                err =
@@ -2098,6 +2191,13 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
        case SYS_RECVMSG:
                err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
                break;
+       case SYS_PACCEPT:
+               err =
+                   sys_paccept(a0, (struct sockaddr __user *)a1,
+                               (int __user *)a[2],
+                               (const sigset_t __user *) a[3],
+                               a[4], a[5]);
+               break;
        default:
                err = -EINVAL;
                break;
index 5a9b0e7828cd6ca89f3f5bedfd18399b1ff0eb3a..23a2b8f6dc495094ec7c8de5a48c06bad2c3d4b8 100644 (file)
@@ -897,7 +897,7 @@ static struct file_system_type rpc_pipe_fs_type = {
 };
 
 static void
-init_once(struct kmem_cache * cachep, void *foo)
+init_once(void *foo)
 {
        struct rpc_inode *rpci = (struct rpc_inode *) foo;
 
index 835d274130838361212a8ffcbae3d4767af0cf57..5a32cb7c4bb486267a03d15892adc7ce5db93c93 100644 (file)
@@ -310,8 +310,7 @@ svc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx)
        switch (m->mode) {
        case SVC_POOL_PERCPU:
        {
-               cpumask_of_cpu_ptr(cpumask, node);
-               set_cpus_allowed_ptr(task, cpumask);
+               set_cpus_allowed_ptr(task, &cpumask_of_cpu(node));
                break;
        }
        case SVC_POOL_PERNODE:
index a19b22b452a37c1a814d5464842afbc96fa6bc37..84d328329d98575d624557fa75a7e159436ece85 100644 (file)
@@ -169,7 +169,8 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
                                          (void *)
                                          vec->sge[xdr_sge_no].iov_base + sge_off,
                                          sge_bytes, DMA_TO_DEVICE);
-               if (dma_mapping_error(sge[sge_no].addr))
+               if (dma_mapping_error(xprt->sc_cm_id->device->dma_device,
+                                       sge[sge_no].addr))
                        goto err;
                sge_off = 0;
                sge_no++;
index 007c1a6708ee4652dd97a9f21c45f407b75327f0..972201cd5fa76791be3d558252d3efb5b009f92e 100644 (file)
 #include <linux/if_tr.h>
 #endif
 
-static struct list_head *
+static struct ctl_table_set *
 net_ctl_header_lookup(struct ctl_table_root *root, struct nsproxy *namespaces)
 {
-       return &namespaces->net_ns->sysctl_table_headers;
+       return &namespaces->net_ns->sysctls;
 }
 
-static struct ctl_table_root net_sysctl_root = {
-       .lookup = net_ctl_header_lookup,
-};
+static int is_seen(struct ctl_table_set *set)
+{
+       return &current->nsproxy->net_ns->sysctls == set;
+}
 
-static LIST_HEAD(net_sysctl_ro_tables);
-static struct list_head *net_ctl_ro_header_lookup(struct ctl_table_root *root,
-               struct nsproxy *namespaces)
+/* Return standard mode bits for table entry. */
+static int net_ctl_permissions(struct ctl_table_root *root,
+                              struct nsproxy *nsproxy,
+                              struct ctl_table *table)
 {
-       return &net_sysctl_ro_tables;
+       /* Allow network administrator to have same access as root. */
+       if (capable(CAP_NET_ADMIN)) {
+               int mode = (table->mode >> 6) & 7;
+               return (mode << 6) | (mode << 3) | mode;
+       }
+       return table->mode;
 }
 
+static struct ctl_table_root net_sysctl_root = {
+       .lookup = net_ctl_header_lookup,
+       .permissions = net_ctl_permissions,
+};
+
 static int net_ctl_ro_header_perms(struct ctl_table_root *root,
                struct nsproxy *namespaces, struct ctl_table *table)
 {
@@ -56,19 +68,20 @@ static int net_ctl_ro_header_perms(struct ctl_table_root *root,
 }
 
 static struct ctl_table_root net_sysctl_ro_root = {
-       .lookup = net_ctl_ro_header_lookup,
        .permissions = net_ctl_ro_header_perms,
 };
 
 static int sysctl_net_init(struct net *net)
 {
-       INIT_LIST_HEAD(&net->sysctl_table_headers);
+       setup_sysctl_set(&net->sysctls,
+                        &net_sysctl_ro_root.default_set,
+                        is_seen);
        return 0;
 }
 
 static void sysctl_net_exit(struct net *net)
 {
-       WARN_ON(!list_empty(&net->sysctl_table_headers));
+       WARN_ON(!list_empty(&net->sysctls.list));
        return;
 }
 
@@ -84,6 +97,7 @@ static __init int sysctl_init(void)
        if (ret)
                goto out;
        register_sysctl_root(&net_sysctl_root);
+       setup_sysctl_set(&net_sysctl_ro_root.default_set, NULL, NULL);
        register_sysctl_root(&net_sysctl_ro_root);
 out:
        return ret;
index 70ceb1604ad83278359dc30b313dd43b5ac481c4..015606b54d9b28325aad62a71ea4fc160b686cd8 100644 (file)
@@ -227,7 +227,7 @@ static void __unix_remove_socket(struct sock *sk)
 
 static void __unix_insert_socket(struct hlist_head *list, struct sock *sk)
 {
-       BUG_TRAP(sk_unhashed(sk));
+       WARN_ON(!sk_unhashed(sk));
        sk_add_node(sk, list);
 }
 
@@ -350,9 +350,9 @@ static void unix_sock_destructor(struct sock *sk)
 
        skb_queue_purge(&sk->sk_receive_queue);
 
-       BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
-       BUG_TRAP(sk_unhashed(sk));
-       BUG_TRAP(!sk->sk_socket);
+       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+       WARN_ON(!sk_unhashed(sk));
+       WARN_ON(sk->sk_socket);
        if (!sock_flag(sk, SOCK_DEAD)) {
                printk("Attempt to release alive unix socket: %p\n", sk);
                return;
@@ -603,7 +603,7 @@ static struct sock * unix_create1(struct net *net, struct socket *sock)
        u->dentry = NULL;
        u->mnt    = NULL;
        spin_lock_init(&u->lock);
-       atomic_set(&u->inflight, 0);
+       atomic_long_set(&u->inflight, 0);
        INIT_LIST_HEAD(&u->link);
        mutex_init(&u->readlock); /* single task reading lock */
        init_waitqueue_head(&u->peer_wait);
index ebdff3d877a1e3201f69af1ae60e92d58df7177a..2a27b84f740bc836a8c4d3debb5031209bf8441d 100644 (file)
@@ -127,7 +127,7 @@ void unix_inflight(struct file *fp)
        if(s) {
                struct unix_sock *u = unix_sk(s);
                spin_lock(&unix_gc_lock);
-               if (atomic_inc_return(&u->inflight) == 1) {
+               if (atomic_long_inc_return(&u->inflight) == 1) {
                        BUG_ON(!list_empty(&u->link));
                        list_add_tail(&u->link, &gc_inflight_list);
                } else {
@@ -145,7 +145,7 @@ void unix_notinflight(struct file *fp)
                struct unix_sock *u = unix_sk(s);
                spin_lock(&unix_gc_lock);
                BUG_ON(list_empty(&u->link));
-               if (atomic_dec_and_test(&u->inflight))
+               if (atomic_long_dec_and_test(&u->inflight))
                        list_del_init(&u->link);
                unix_tot_inflight--;
                spin_unlock(&unix_gc_lock);
@@ -237,17 +237,17 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
 
 static void dec_inflight(struct unix_sock *usk)
 {
-       atomic_dec(&usk->inflight);
+       atomic_long_dec(&usk->inflight);
 }
 
 static void inc_inflight(struct unix_sock *usk)
 {
-       atomic_inc(&usk->inflight);
+       atomic_long_inc(&usk->inflight);
 }
 
 static void inc_inflight_move_tail(struct unix_sock *u)
 {
-       atomic_inc(&u->inflight);
+       atomic_long_inc(&u->inflight);
        /*
         * If this is still a candidate, move it to the end of the
         * list, so that it's checked even if it was already passed
@@ -288,11 +288,11 @@ void unix_gc(void)
         * before the detach without atomicity guarantees.
         */
        list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
-               int total_refs;
-               int inflight_refs;
+               long total_refs;
+               long inflight_refs;
 
                total_refs = file_count(u->sk.sk_socket->file);
-               inflight_refs = atomic_read(&u->inflight);
+               inflight_refs = atomic_long_read(&u->inflight);
 
                BUG_ON(inflight_refs < 1);
                BUG_ON(total_refs < inflight_refs);
@@ -324,7 +324,7 @@ void unix_gc(void)
                /* Move cursor to after the current position. */
                list_move(&cursor, &u->link);
 
-               if (atomic_read(&u->inflight) > 0) {
+               if (atomic_long_read(&u->inflight) > 0) {
                        list_move_tail(&u->link, &gc_inflight_list);
                        u->gc_candidate = 0;
                        scan_children(&u->sk, inc_inflight_move_tail, NULL);
index 9201ef8ad90eb2143a652b769ee4215e54eaa72c..6d081674515f0a7112580d1328c52bceda0386e5 100644 (file)
@@ -46,6 +46,12 @@ config XFRM_STATISTICS
 
          If unsure, say N.
 
+config XFRM_IPCOMP
+       tristate
+       select XFRM
+       select CRYPTO
+       select CRYPTO_DEFLATE
+
 config NET_KEY
        tristate "PF_KEY sockets"
        select XFRM
index 332cfb0ff566af1e59433e989c1c545929f24e81..0f439a72ccab4fa8129a0e0c9868241fae4ad610 100644 (file)
@@ -6,4 +6,5 @@ obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
                      xfrm_input.o xfrm_output.o xfrm_algo.o
 obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
 obj-$(CONFIG_XFRM_USER) += xfrm_user.o
+obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o
 
index 23a2cc04b8cdb5f4a9f215643bfc1df130800322..96036cf2216d09c7dea7907c31c73c3b42f5b7cf 100644 (file)
@@ -718,7 +718,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;
 
-               BUG_TRAP(start <= offset + len);
+               WARN_ON(start > offset + len);
 
                end = start + skb_shinfo(skb)->frags[i].size;
                if ((copy = end - offset) > 0) {
@@ -748,7 +748,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
                for (; list; list = list->next) {
                        int end;
 
-                       BUG_TRAP(start <= offset + len);
+                       WARN_ON(start > offset + len);
 
                        end = start + list->len;
                        if ((copy = end - offset) > 0) {
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
new file mode 100644 (file)
index 0000000..c609a4b
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * IP Payload Compression Protocol (IPComp) - RFC3173.
+ *
+ * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2003-2008 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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.
+ *
+ * Todo:
+ *   - Tunable compression parameters.
+ *   - Compression stats.
+ *   - Adaptive compression.
+ */
+
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/percpu.h>
+#include <linux/smp.h>
+#include <linux/vmalloc.h>
+#include <net/ip.h>
+#include <net/ipcomp.h>
+#include <net/xfrm.h>
+
+struct ipcomp_tfms {
+       struct list_head list;
+       struct crypto_comp **tfms;
+       int users;
+};
+
+static DEFINE_MUTEX(ipcomp_resource_mutex);
+static void **ipcomp_scratches;
+static int ipcomp_scratch_users;
+static LIST_HEAD(ipcomp_tfms_list);
+
+static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
+{
+       struct ipcomp_data *ipcd = x->data;
+       const int plen = skb->len;
+       int dlen = IPCOMP_SCRATCH_SIZE;
+       const u8 *start = skb->data;
+       const int cpu = get_cpu();
+       u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+       struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+       int err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
+       int len;
+
+       if (err)
+               goto out;
+
+       if (dlen < (plen + sizeof(struct ip_comp_hdr))) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       len = dlen - plen;
+       if (len > skb_tailroom(skb))
+               len = skb_tailroom(skb);
+
+       skb->truesize += len;
+       __skb_put(skb, len);
+
+       len += plen;
+       skb_copy_to_linear_data(skb, scratch, len);
+
+       while ((scratch += len, dlen -= len) > 0) {
+               skb_frag_t *frag;
+
+               err = -EMSGSIZE;
+               if (WARN_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS))
+                       goto out;
+
+               frag = skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
+               frag->page = alloc_page(GFP_ATOMIC);
+
+               err = -ENOMEM;
+               if (!frag->page)
+                       goto out;
+
+               len = PAGE_SIZE;
+               if (dlen < len)
+                       len = dlen;
+
+               memcpy(page_address(frag->page), scratch, len);
+
+               frag->page_offset = 0;
+               frag->size = len;
+               skb->truesize += len;
+               skb->data_len += len;
+               skb->len += len;
+
+               skb_shinfo(skb)->nr_frags++;
+       }
+
+       err = 0;
+
+out:
+       put_cpu();
+       return err;
+}
+
+int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int nexthdr;
+       int err = -ENOMEM;
+       struct ip_comp_hdr *ipch;
+
+       if (skb_linearize_cow(skb))
+               goto out;
+
+       skb->ip_summed = CHECKSUM_NONE;
+
+       /* Remove ipcomp header and decompress original payload */
+       ipch = (void *)skb->data;
+       nexthdr = ipch->nexthdr;
+
+       skb->transport_header = skb->network_header + sizeof(*ipch);
+       __skb_pull(skb, sizeof(*ipch));
+       err = ipcomp_decompress(x, skb);
+       if (err)
+               goto out;
+
+       err = nexthdr;
+
+out:
+       return err;
+}
+EXPORT_SYMBOL_GPL(ipcomp_input);
+
+static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
+{
+       struct ipcomp_data *ipcd = x->data;
+       const int plen = skb->len;
+       int dlen = IPCOMP_SCRATCH_SIZE;
+       u8 *start = skb->data;
+       const int cpu = get_cpu();
+       u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+       struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+       int err;
+
+       local_bh_disable();
+       err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
+       local_bh_enable();
+       if (err)
+               goto out;
+
+       if ((dlen + sizeof(struct ip_comp_hdr)) >= plen) {
+               err = -EMSGSIZE;
+               goto out;
+       }
+
+       memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
+       put_cpu();
+
+       pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
+       return 0;
+
+out:
+       put_cpu();
+       return err;
+}
+
+int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int err;
+       struct ip_comp_hdr *ipch;
+       struct ipcomp_data *ipcd = x->data;
+
+       if (skb->len < ipcd->threshold) {
+               /* Don't bother compressing */
+               goto out_ok;
+       }
+
+       if (skb_linearize_cow(skb))
+               goto out_ok;
+
+       err = ipcomp_compress(x, skb);
+
+       if (err) {
+               goto out_ok;
+       }
+
+       /* Install ipcomp header, convert into ipcomp datagram. */
+       ipch = ip_comp_hdr(skb);
+       ipch->nexthdr = *skb_mac_header(skb);
+       ipch->flags = 0;
+       ipch->cpi = htons((u16 )ntohl(x->id.spi));
+       *skb_mac_header(skb) = IPPROTO_COMP;
+out_ok:
+       skb_push(skb, -skb_network_offset(skb));
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ipcomp_output);
+
+static void ipcomp_free_scratches(void)
+{
+       int i;
+       void **scratches;
+
+       if (--ipcomp_scratch_users)
+               return;
+
+       scratches = ipcomp_scratches;
+       if (!scratches)
+               return;
+
+       for_each_possible_cpu(i)
+               vfree(*per_cpu_ptr(scratches, i));
+
+       free_percpu(scratches);
+}
+
+static void **ipcomp_alloc_scratches(void)
+{
+       int i;
+       void **scratches;
+
+       if (ipcomp_scratch_users++)
+               return ipcomp_scratches;
+
+       scratches = alloc_percpu(void *);
+       if (!scratches)
+               return NULL;
+
+       ipcomp_scratches = scratches;
+
+       for_each_possible_cpu(i) {
+               void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
+               if (!scratch)
+                       return NULL;
+               *per_cpu_ptr(scratches, i) = scratch;
+       }
+
+       return scratches;
+}
+
+static void ipcomp_free_tfms(struct crypto_comp **tfms)
+{
+       struct ipcomp_tfms *pos;
+       int cpu;
+
+       list_for_each_entry(pos, &ipcomp_tfms_list, list) {
+               if (pos->tfms == tfms)
+                       break;
+       }
+
+       WARN_ON(!pos);
+
+       if (--pos->users)
+               return;
+
+       list_del(&pos->list);
+       kfree(pos);
+
+       if (!tfms)
+               return;
+
+       for_each_possible_cpu(cpu) {
+               struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu);
+               crypto_free_comp(tfm);
+       }
+       free_percpu(tfms);
+}
+
+static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name)
+{
+       struct ipcomp_tfms *pos;
+       struct crypto_comp **tfms;
+       int cpu;
+
+       /* This can be any valid CPU ID so we don't need locking. */
+       cpu = raw_smp_processor_id();
+
+       list_for_each_entry(pos, &ipcomp_tfms_list, list) {
+               struct crypto_comp *tfm;
+
+               tfms = pos->tfms;
+               tfm = *per_cpu_ptr(tfms, cpu);
+
+               if (!strcmp(crypto_comp_name(tfm), alg_name)) {
+                       pos->users++;
+                       return tfms;
+               }
+       }
+
+       pos = kmalloc(sizeof(*pos), GFP_KERNEL);
+       if (!pos)
+               return NULL;
+
+       pos->users = 1;
+       INIT_LIST_HEAD(&pos->list);
+       list_add(&pos->list, &ipcomp_tfms_list);
+
+       pos->tfms = tfms = alloc_percpu(struct crypto_comp *);
+       if (!tfms)
+               goto error;
+
+       for_each_possible_cpu(cpu) {
+               struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
+                                                           CRYPTO_ALG_ASYNC);
+               if (IS_ERR(tfm))
+                       goto error;
+               *per_cpu_ptr(tfms, cpu) = tfm;
+       }
+
+       return tfms;
+
+error:
+       ipcomp_free_tfms(tfms);
+       return NULL;
+}
+
+static void ipcomp_free_data(struct ipcomp_data *ipcd)
+{
+       if (ipcd->tfms)
+               ipcomp_free_tfms(ipcd->tfms);
+       ipcomp_free_scratches();
+}
+
+void ipcomp_destroy(struct xfrm_state *x)
+{
+       struct ipcomp_data *ipcd = x->data;
+       if (!ipcd)
+               return;
+       xfrm_state_delete_tunnel(x);
+       mutex_lock(&ipcomp_resource_mutex);
+       ipcomp_free_data(ipcd);
+       mutex_unlock(&ipcomp_resource_mutex);
+       kfree(ipcd);
+}
+EXPORT_SYMBOL_GPL(ipcomp_destroy);
+
+int ipcomp_init_state(struct xfrm_state *x)
+{
+       int err;
+       struct ipcomp_data *ipcd;
+       struct xfrm_algo_desc *calg_desc;
+
+       err = -EINVAL;
+       if (!x->calg)
+               goto out;
+
+       if (x->encap)
+               goto out;
+
+       err = -ENOMEM;
+       ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
+       if (!ipcd)
+               goto out;
+
+       mutex_lock(&ipcomp_resource_mutex);
+       if (!ipcomp_alloc_scratches())
+               goto error;
+
+       ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name);
+       if (!ipcd->tfms)
+               goto error;
+       mutex_unlock(&ipcomp_resource_mutex);
+
+       calg_desc = xfrm_calg_get_byname(x->calg->alg_name, 0);
+       BUG_ON(!calg_desc);
+       ipcd->threshold = calg_desc->uinfo.comp.threshold;
+       x->data = ipcd;
+       err = 0;
+out:
+       return err;
+
+error:
+       ipcomp_free_data(ipcd);
+       mutex_unlock(&ipcomp_resource_mutex);
+       kfree(ipcd);
+       goto out;
+}
+EXPORT_SYMBOL_GPL(ipcomp_init_state);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173");
+MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
index 72fddafd891a0b3f3be603804e6c5727a56a5b3d..4c6914ef7d92df5830baba92363108e502217c3f 100644 (file)
@@ -538,7 +538,7 @@ EXPORT_SYMBOL(xfrm_state_alloc);
 
 void __xfrm_state_destroy(struct xfrm_state *x)
 {
-       BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
+       WARN_ON(x->km.state != XFRM_STATE_DEAD);
 
        spin_lock_bh(&xfrm_state_lock);
        list_del(&x->all);
index c972c0f54ce0aba88771ef2a727b425ad50abd83..f63a663de1589106a05897270b56709e5400034a 100644 (file)
@@ -17,14 +17,15 @@ include $(srctree)/$(obj)/Makefile
 
 include scripts/Makefile.host
 
-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-m))
-
+mod-fw := $(fw-shipped-m)
 # If CONFIG_FIRMWARE_IN_KERNEL isn't set, then install the 
 # firmware for in-kernel drivers too.
 ifndef CONFIG_FIRMWARE_IN_KERNEL
-mod-fw += $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-y))
+mod-fw += $(fw-shipped-y)
 endif
 
+installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw))
+
 installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all))
 installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/.
 
@@ -49,7 +50,8 @@ PHONY +=  __fw_install __fw_modinst FORCE
 .PHONY: $(PHONY)
 
 __fw_install: $(installed-fw)
-__fw_modinst: $(mod-fw)
+__fw_modinst: $(installed-mod-fw)
+__fw_modbuild: $(addprefix $(obj)/,$(mod-fw))
 
 FORCE:
 
index 53dae3eb3d1f0334fb0043759598e6117ab4b3ba..612dc13ddd85fcda58d327ea688746f887ad02db 100644 (file)
 # ==========================================================================
 # Installing headers
 #
-# header-y files will be installed verbatim
-# unifdef-y are the files where unifdef will be run before installing files
-# objhdr-y are generated files that will be installed verbatim
+# header-y  - list files to be installed. They are preprocessed
+#             to remove __KERNEL__ section of the file
+# unifdef-y - Same as header-y. Obsolete
+# objhdr-y  - Same as header-y but for generated files
 #
 # ==========================================================================
 
-UNIFDEF := scripts/unifdef -U__KERNEL__
-
-# Eliminate the contents of (and inclusions of) compiler.h
-HDRSED  := sed         -e "s/ inline / __inline__ /g" \
-               -e "s/[[:space:]]__user[[:space:]]\{1,\}/ /g" \
-               -e "s/(__user[[:space:]]\{1,\}/ (/g" \
-               -e "s/[[:space:]]__force[[:space:]]\{1,\}/ /g" \
-               -e "s/(__force[[:space:]]\{1,\}/ (/g" \
-               -e "s/[[:space:]]__iomem[[:space:]]\{1,\}/ /g" \
-               -e "s/(__iomem[[:space:]]\{1,\}/ (/g" \
-               -e "s/[[:space:]]__attribute_const__[[:space:]]\{1,\}/\ /g" \
-               -e "s/[[:space:]]__attribute_const__$$//" \
-               -e "/^\#include <linux\/compiler.h>/d"
-
+# called may set destination dir (when installing to asm/)
 _dst := $(if $(dst),$(dst),$(obj))
 
-ifeq (,$(patsubst include/asm/%,,$(obj)/))
-# For producing the generated stuff in include/asm for biarch builds, include
-# both sets of Kbuild files; we'll generate anything which is mentioned in
-# _either_ arch, and recurse into subdirectories which are mentioned in either
-# arch. Since some directories may exist in one but not the other, we must
-# use $(wildcard...). 
-GENASM := 1
-archasm           := $(subst include/asm,asm-$(ARCH),$(obj))
-altarchasm := $(subst include/asm,asm-$(ALTARCH),$(obj))
-KBUILDFILES := $(wildcard $(srctree)/include/$(archasm)/Kbuild $(srctree)/include/$(altarchasm)/Kbuild)
-else
-KBUILDFILES := $(srctree)/$(obj)/Kbuild
-endif
+kbuild-file := $(srctree)/$(obj)/Kbuild
+include $(kbuild-file)
 
-include $(KBUILDFILES)
+include scripts/Kbuild.include
 
-include scripts/Kbuild.include 
+install       := $(INSTALL_HDR_PATH)/$(_dst)
 
-# If this is include/asm-$(ARCH) and there's no $(ALTARCH), then
-# override $(_dst) so that we install to include/asm directly.
-# Unless $(BIASMDIR) is set, in which case we're probably doing
-# a 'headers_install_all' build and we should keep the -$(ARCH)
-# in the directory name.
-ifeq ($(obj)$(ALTARCH),include/asm-$(ARCH)$(BIASMDIR))
-     _dst := include/asm
-endif
+header-y      := $(sort $(header-y) $(unifdef-y))
+subdirs       := $(patsubst %/,%,$(filter %/, $(header-y)))
+header-y      := $(filter-out %/, $(header-y))
 
-header-y       := $(sort $(header-y))
-unifdef-y      := $(sort $(unifdef-y))
-subdir-y       := $(patsubst %/,%,$(filter %/, $(header-y)))
-header-y       := $(filter-out %/, $(header-y))
-header-y       := $(filter-out $(unifdef-y),$(header-y))
+# files used to track state of install/check
+install-file  := $(install)/.install
+check-file    := $(install)/.check
 
-# stamp files for header checks
-check-y                := $(patsubst %,.check.%,$(header-y) $(unifdef-y) $(objhdr-y))
+# all headers files for this dir
+all-files     := $(header-y) $(objhdr-y)
+input-files   := $(addprefix $(srctree)/$(obj)/,$(header-y)) \
+                 $(addprefix $(objtree)/$(obj)/,$(objhdr-y))
+output-files  := $(addprefix $(install)/, $(all-files))
 
 # Work out what needs to be removed
-oldheaders     := $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$(wildcard $(INSTALL_HDR_PATH)/$(_dst)/*.h))
-unwanted       := $(filter-out $(header-y) $(unifdef-y) $(objhdr-y),$(oldheaders))
+oldheaders    := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h))
+unwanted      := $(filter-out $(all-files),$(oldheaders))
 
-oldcheckstamps := $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$(wildcard $(INSTALL_HDR_PATH)/$(_dst)/.check.*.h))
-unwanted       += $(filter-out $(check-y),$(oldcheckstamps))
+# Prefix unwanted with full paths to $(INSTALL_HDR_PATH)
+unwanted-file := $(addprefix $(install)/, $(unwanted))
 
-# Prefix them all with full paths to $(INSTALL_HDR_PATH)
-header-y       := $(patsubst %,$(INSTALL_HDR_PATH)/$(_dst)/%,$(header-y))
-unifdef-y      := $(patsubst %,$(INSTALL_HDR_PATH)/$(_dst)/%,$(unifdef-y))
-objhdr-y       := $(patsubst %,$(INSTALL_HDR_PATH)/$(_dst)/%,$(objhdr-y))
-check-y        := $(patsubst %,$(INSTALL_HDR_PATH)/$(_dst)/%,$(check-y))
+printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
 
+quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
+                            file$(if $(word 2, $(all-files)),s))
+      cmd_install = \
+        $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \
+        $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \
+        touch $@
 
-ifdef ALTARCH
-ifeq ($(obj),include/asm-$(ARCH))
-altarch-y      := altarch-dir
-endif
-endif
+quiet_cmd_remove = REMOVE  $(unwanted)
+      cmd_remove = rm -f $(unwanted-file)
 
-# Make the definitions visible for recursive make invocations
-export ALTARCH
-export ARCHDEF
-export ALTARCHDEF
-
-quiet_cmd_o_hdr_install   = INSTALL $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_o_hdr_install   = cp $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,$(objtree)/$(obj)/%,$@) \
-                           $(INSTALL_HDR_PATH)/$(_dst)
-
-quiet_cmd_headers_install = INSTALL $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_headers_install = $(HDRSED) $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,$(srctree)/$(obj)/%,$@) \
-                           > $@
-
-quiet_cmd_unifdef        = UNIFDEF $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_unifdef        = $(UNIFDEF) $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,$(srctree)/$(obj)/%,$@) \
-                                  | $(HDRSED) > $@ || :
-
-quiet_cmd_check                  = CHECK   $(patsubst $(INSTALL_HDR_PATH)/$(_dst)/.check.%,$(_dst)/%,$@)
-      cmd_check                  = $(CONFIG_SHELL) $(srctree)/scripts/hdrcheck.sh \
-                              $(INSTALL_HDR_PATH)/include $(subst /.check.,/,$@) $@
-
-quiet_cmd_remove         = REMOVE  $(_dst)/$@
-      cmd_remove         = rm -f $(INSTALL_HDR_PATH)/$(_dst)/$@
-
-quiet_cmd_mkdir                  = MKDIR   $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_mkdir                  = mkdir -p $@
-
-quiet_cmd_gen            = GEN     $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
-      cmd_gen            = \
-FNAME=$(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$@);                  \
-STUBDEF=__ASM_STUB_`echo $$FNAME | tr a-z.- A-Z__`;                    \
-(echo "/* File autogenerated by 'make headers_install' */" ;           \
-echo "\#ifndef $$STUBDEF" ;                                            \
-echo "\#define $$STUBDEF" ;                                            \
-echo "\# if $(ARCHDEF)" ;                                              \
-if [ -r $(subst /$(_dst)/,/include/$(archasm)/,$@) ]; then             \
-       echo "\#  include <$(archasm)/$$FNAME>" ;                       \
-else                                                                   \
-       echo "\#  error $(archasm)/$$FNAME does not exist in"           \
-                       "the $(ARCH) architecture" ;                    \
-fi ;                                                                   \
-echo "\# elif $(ALTARCHDEF)" ;                                         \
-if [ -r $(subst /$(_dst)/,/include/$(altarchasm)/,$@) ]; then          \
-       echo "\#  include <$(altarchasm)/$$FNAME>" ;                    \
-else                                                                   \
-       echo "\#  error $(altarchasm)/$$FNAME does not exist in"        \
-                       "the $(ALTARCH) architecture" ;                 \
-fi ;                                                                   \
-echo "\# else" ;                                                       \
-echo "\#  warning This machine appears to be"                          \
-                "neither $(ARCH) nor $(ALTARCH)." ;                    \
-echo "\# endif" ;                                                      \
-echo "\#endif /* $$STUBDEF */" ;                                       \
-) > $@
-
-.PHONY: __headersinst __headerscheck
-
-ifdef HDRCHECK
-__headerscheck: $(subdir-y) $(check-y)
-       @true
-
-$(check-y) : $(INSTALL_HDR_PATH)/$(_dst)/.check.%.h : $(INSTALL_HDR_PATH)/$(_dst)/%.h 
-       $(call cmd,check)
-
-# Other dependencies for $(check-y)
-include /dev/null $(wildcard $(check-y))
-
-# ... but leave $(check-y) as .PHONY for now until those deps are actually correct.
-.PHONY: $(check-y)
+quiet_cmd_check = CHECK   $(printdir) ($(words $(all-files)) files)
+      cmd_check = $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH) \
+                  $(addprefix $(install)/, $(all-files));           \
+                 touch $@
 
-else
-# Rules for installing headers
-__headersinst: $(subdir-y) $(header-y) $(unifdef-y) $(altarch-y) $(objhdr-y)
-       @true
+PHONY += __headersinst __headerscheck
 
-$(objhdr-y) $(subdir-y) $(header-y) $(unifdef-y): | $(INSTALL_HDR_PATH)/$(_dst) $(unwanted)
-
-$(INSTALL_HDR_PATH)/$(_dst):
-       $(call cmd,mkdir)
-
-.PHONY: $(unwanted)
-$(unwanted):
-       $(call cmd,remove)
+ifndef HDRCHECK
+# Rules for installing headers
+__headersinst: $(subdirs) $(install-file)
+       @:
 
-ifdef GENASM
-$(objhdr-y) $(header-y) $(unifdef-y): $(KBUILDFILES)
-       $(call cmd,gen)
+targets += $(install-file)
+$(install-file): scripts/headers_install.pl $(input-files) FORCE
+       $(if $(unwanted),$(call cmd,remove),)
+       $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@)))
+       $(call if_changed,install)
 
 else
-$(objhdr-y) :          $(INSTALL_HDR_PATH)/$(_dst)/%.h: $(objtree)/$(obj)/%.h $(KBUILDFILES)
-       $(call cmd,o_hdr_install)
+__headerscheck: $(subdirs) $(check-file)
+       @:
 
-$(header-y) :          $(INSTALL_HDR_PATH)/$(_dst)/%.h: $(srctree)/$(obj)/%.h $(KBUILDFILES)
-       $(call cmd,headers_install)
+targets += $(check-file)
+$(check-file): scripts/headers_check.pl $(output-files) FORCE
+       $(call if_changed,check)
 
-$(unifdef-y) :         $(INSTALL_HDR_PATH)/$(_dst)/%.h: $(srctree)/$(obj)/%.h $(KBUILDFILES)
-       $(call cmd,unifdef)
-endif
 endif
 
-hdrinst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
+# Recursion
+hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
+.PHONY: $(subdirs)
+$(subdirs):
+       $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@
 
-.PHONY: altarch-dir
-# All the files in the normal arch dir must be created first, since we test
-# for their existence.
-altarch-dir: $(subdir-y) $(header-y) $(unifdef-y) $(objhdr-y)
-       $(Q)$(MAKE) $(hdrinst)=include/asm-$(ALTARCH) dst=include/asm-$(ALTARCH)
-       $(Q)$(MAKE) $(hdrinst)=include/asm dst=include/asm$(BIASMDIR)
+targets := $(wildcard $(sort $(targets)))
+cmd_files := $(wildcard \
+             $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
 
-# Recursion
-.PHONY: $(subdir-y)
-$(subdir-y):
-       $(Q)$(MAKE) $(hdrinst)=$(obj)/$@ dst=$(_dst)/$@ rel=../$(rel)
+ifneq ($(cmd_files),)
+       include $(cmd_files)
+endif
+
+.PHONY: $(PHONY)
+PHONY += FORCE
+FORCE: ;
index 6971bf078d1338ff3f7c7f2b5b72b7f874c94fbc..bc6779398229757a94a44a4d3ef4a70dbf618a49 100755 (executable)
@@ -9,7 +9,7 @@ use strict;
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.19';
+my $V = '0.21';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -17,7 +17,6 @@ my $quiet = 0;
 my $tree = 1;
 my $chk_signoff = 1;
 my $chk_patch = 1;
-my $tst_type = 0;
 my $tst_only;
 my $emacs = 0;
 my $terse = 0;
@@ -44,7 +43,6 @@ GetOptions(
        'summary-file!' => \$summary_file,
 
        'debug=s'       => \%debug,
-       'test-type!'    => \$tst_type,
        'test-only=s'   => \$tst_only,
 ) or exit;
 
@@ -67,6 +65,7 @@ if ($#ARGV < 0) {
 
 my $dbg_values = 0;
 my $dbg_possible = 0;
+my $dbg_type = 0;
 for my $key (keys %debug) {
        eval "\${dbg_$key} = '$debug{$key}';"
 }
@@ -169,24 +168,23 @@ our @modifierList = (
 );
 
 sub build_types {
-       my $mods = "(?:  \n" . join("|\n  ", @modifierList) . "\n)";
-       my $all = "(?:  \n" . join("|\n  ", @typeList) . "\n)";
+       my $mods = "(?x:  \n" . join("|\n  ", @modifierList) . "\n)";
+       my $all = "(?x:  \n" . join("|\n  ", @typeList) . "\n)";
+       $Modifier       = qr{(?:$Attribute|$Sparse|$mods)};
        $NonptrType     = qr{
-                       (?:const\s+)?
-                       (?:$mods\s+)?
+                       (?:$Modifier\s+|const\s+)*
                        (?:
                                (?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)|
                                (?:${all}\b)
                        )
-                       (?:\s+$Sparse|\s+const)*
+                       (?:\s+$Modifier|\s+const)*
                  }x;
        $Type   = qr{
                        $NonptrType
                        (?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
-                       (?:\s+$Inline|\s+$Sparse|\s+$Attribute|\s+$mods)*
+                       (?:\s+$Inline|\s+$Modifier)*
                  }x;
        $Declare        = qr{(?:$Storage\s+)?$Type};
-       $Modifier       = qr{(?:$Attribute|$Sparse|$mods)};
 }
 build_types();
 
@@ -470,7 +468,9 @@ sub ctx_statement_block {
                }
                $off++;
        }
+       # We are truly at the end, so shuffle to the next line.
        if ($off == $len) {
+               $loff = $len + 1;
                $line++;
                $remain--;
        }
@@ -631,7 +631,7 @@ sub ctx_locate_comment {
        my ($first_line, $end_line) = @_;
 
        # Catch a comment on the end of the line itself.
-       my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*$@);
+       my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
        return $current_comment if (defined $current_comment);
 
        # Look through the context and try and figure out if there is a
@@ -689,17 +689,20 @@ sub cat_vet {
 my $av_preprocessor = 0;
 my $av_pending;
 my @av_paren_type;
+my $av_pend_colon;
 
 sub annotate_reset {
        $av_preprocessor = 0;
        $av_pending = '_';
        @av_paren_type = ('E');
+       $av_pend_colon = 'O';
 }
 
 sub annotate_values {
        my ($stream, $type) = @_;
 
        my $res;
+       my $var = '_' x length($stream);
        my $cur = $stream;
 
        print "$stream\n" if ($dbg_values > 1);
@@ -715,10 +718,14 @@ sub annotate_values {
                                $av_preprocessor = 0;
                        }
 
-               } elsif ($cur =~ /^($Type)/) {
+               } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) {
                        print "DECLARE($1)\n" if ($dbg_values > 1);
                        $type = 'T';
 
+               } elsif ($cur =~ /^($Modifier)\s*/) {
+                       print "MODIFIER($1)\n" if ($dbg_values > 1);
+                       $type = 'T';
+
                } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
                        print "DEFINE($1,$2)\n" if ($dbg_values > 1);
                        $av_preprocessor = 1;
@@ -780,7 +787,12 @@ sub annotate_values {
                        $av_pending = 'N';
                        $type = 'N';
 
-               } elsif ($cur =~/^(return|case|else)/o) {
+               } elsif ($cur =~/^(case)/o) {
+                       print "CASE($1)\n" if ($dbg_values > 1);
+                       $av_pend_colon = 'C';
+                       $type = 'N';
+
+               } elsif ($cur =~/^(return|else|goto)/o) {
                        print "KEYWORD($1)\n" if ($dbg_values > 1);
                        $type = 'N';
 
@@ -800,10 +812,20 @@ sub annotate_values {
                                print "PAREN('$1')\n" if ($dbg_values > 1);
                        }
 
-               } elsif ($cur =~ /^($Ident)\(/o) {
+               } elsif ($cur =~ /^($Ident)\s*\(/o) {
                        print "FUNC($1)\n" if ($dbg_values > 1);
+                       $type = 'V';
                        $av_pending = 'V';
 
+               } elsif ($cur =~ /^($Ident\s*):/) {
+                       if ($type eq 'E') {
+                               $av_pend_colon = 'L';
+                       } elsif ($type eq 'T') {
+                               $av_pend_colon = 'B';
+                       }
+                       print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
+                       $type = 'V';
+
                } elsif ($cur =~ /^($Ident|$Constant)/o) {
                        print "IDENT($1)\n" if ($dbg_values > 1);
                        $type = 'V';
@@ -815,11 +837,40 @@ sub annotate_values {
                } elsif ($cur =~/^(;|{|})/) {
                        print "END($1)\n" if ($dbg_values > 1);
                        $type = 'E';
+                       $av_pend_colon = 'O';
+
+               } elsif ($cur =~ /^(\?)/o) {
+                       print "QUESTION($1)\n" if ($dbg_values > 1);
+                       $type = 'N';
 
-               } elsif ($cur =~ /^(;|\?|:|\[)/o) {
+               } elsif ($cur =~ /^(:)/o) {
+                       print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
+
+                       substr($var, length($res), 1, $av_pend_colon);
+                       if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
+                               $type = 'E';
+                       } else {
+                               $type = 'N';
+                       }
+                       $av_pend_colon = 'O';
+
+               } elsif ($cur =~ /^(;|\[)/o) {
                        print "CLOSE($1)\n" if ($dbg_values > 1);
                        $type = 'N';
 
+               } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&(?!\&))/o) {
+                       my $variant;
+
+                       print "OPV($1)\n" if ($dbg_values > 1);
+                       if ($type eq 'V') {
+                               $variant = 'B';
+                       } else {
+                               $variant = 'U';
+                       }
+
+                       substr($var, length($res), 1, $variant);
+                       $type = 'N';
+
                } elsif ($cur =~ /^($Operators)/o) {
                        print "OP($1)\n" if ($dbg_values > 1);
                        if ($1 ne '++' && $1 ne '--') {
@@ -835,17 +886,17 @@ sub annotate_values {
                }
        }
 
-       return $res;
+       return ($res, $var);
 }
 
 sub possible {
        my ($possible, $line) = @_;
 
        print "CHECK<$possible> ($line)\n" if ($dbg_possible > 1);
-       if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ &&
+       if ($possible !~ /^(?:$Modifier|$Storage|$Type|DEFINE_\S+)$/ &&
            $possible ne 'goto' && $possible ne 'return' &&
            $possible ne 'case' && $possible ne 'else' &&
-           $possible ne 'asm' &&
+           $possible ne 'asm' && $possible ne '__asm__' &&
            $possible !~ /^(typedef|struct|enum)\b/) {
                # Check for modifiers.
                $possible =~ s/\s*$Storage\s*//g;
@@ -854,8 +905,10 @@ sub possible {
 
                } elsif ($possible =~ /\s/) {
                        $possible =~ s/\s*$Type\s*//g;
-                       warn "MODIFIER: $possible ($line)\n" if ($dbg_possible);
-                       push(@modifierList, $possible);
+                       for my $modifier (split(' ', $possible)) {
+                               warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
+                               push(@modifierList, $modifier);
+                       }
 
                } else {
                        warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
@@ -1135,7 +1188,9 @@ sub process {
                }
 #80 column limit
                if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
-                   $rawline !~ /^.\s*\*\s*\@$Ident\s/ && $length > 80)
+                   $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
+                   $line !~ /^\+\s*printk\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&
+                   $length > 80)
                {
                        WARN("line over 80 characters\n" . $herecurr);
                }
@@ -1162,10 +1217,10 @@ sub process {
                }
 
 # Check for potential 'bare' types
-               my ($stat, $cond);
+               my ($stat, $cond, $line_nr_next, $remain_next);
                if ($realcnt && $line =~ /.\s*\S/) {
-                       ($stat, $cond) = ctx_statement_block($linenr,
-                                                               $realcnt, 0);
+                       ($stat, $cond, $line_nr_next, $remain_next) =
+                               ctx_statement_block($linenr, $realcnt, 0);
                        $stat =~ s/\n./\n /g;
                        $cond =~ s/\n./\n /g;
 
@@ -1179,7 +1234,7 @@ sub process {
                        } elsif ($s =~ /^.\s*$Ident\s*\(/s) {
 
                        # declarations always start with types
-                       } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))\s*(?:;|=|,|\()/s) {
+                       } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) {
                                my $type = $1;
                                $type =~ s/\s+/ /g;
                                possible($type, "A:" . $s);
@@ -1239,6 +1294,10 @@ sub process {
                                ERROR("switch and case should be at the same indent\n$hereline$err");
                        }
                }
+               if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
+                   $line !~ /\G(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$/g) {
+                       ERROR("trailing statements should be on next line\n" . $herecurr);
+               }
 
 # if/while/etc brace do not go on next line, unless defining a do while loop,
 # or if that brace on the next line is for something else
@@ -1246,17 +1305,22 @@ sub process {
                        my $pre_ctx = "$1$2";
 
                        my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
-                       my $ctx_ln = $linenr + $#ctx + 1;
                        my $ctx_cnt = $realcnt - $#ctx - 1;
                        my $ctx = join("\n", @ctx);
 
-                       ##warn "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
+                       my $ctx_ln = $linenr;
+                       my $ctx_skip = $realcnt;
 
-                       # Skip over any removed lines in the context following statement.
-                       while (defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^-/) {
+                       while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt &&
+                                       defined $lines[$ctx_ln - 1] &&
+                                       $lines[$ctx_ln - 1] =~ /^-/)) {
+                               ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
+                               $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/);
                                $ctx_ln++;
                        }
-                       ##warn "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
+
+                       #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
+                       #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
 
                        if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
                                ERROR("that open brace { should be on the previous line\n" .
@@ -1276,12 +1340,14 @@ sub process {
 
                # Track the 'values' across context and added lines.
                my $opline = $line; $opline =~ s/^./ /;
-               my $curr_values = annotate_values($opline . "\n", $prev_values);
+               my ($curr_values, $curr_vars) =
+                               annotate_values($opline . "\n", $prev_values);
                $curr_values = $prev_values . $curr_values;
                if ($dbg_values) {
                        my $outline = $opline; $outline =~ s/\t/ /g;
                        print "$linenr > .$outline\n";
                        print "$linenr > $curr_values\n";
+                       print "$linenr >  $curr_vars\n";
                }
                $prev_values = substr($curr_values, -1);
 
@@ -1289,8 +1355,12 @@ sub process {
                if ($line=~/^[^\+]/) {next;}
 
 # TEST: allow direct testing of the type matcher.
-               if ($tst_type && $line =~ /^.$Declare$/) {
-                       ERROR("TEST: is type $Declare\n" . $herecurr);
+               if ($dbg_type) {
+                       if ($line =~ /^.\s*$Declare\s*$/) {
+                               ERROR("TEST: is type\n" . $herecurr);
+                       } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
+                               ERROR("TEST: is not type ($1 is)\n". $herecurr);
+                       }
                        next;
                }
 
@@ -1365,11 +1435,11 @@ sub process {
                        ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
                                $herecurr);
 
-               } elsif ($line =~ m{$NonptrType(\*+)(?:\s+(?:$Attribute|$Sparse))?\s+[A-Za-z\d_]+}) {
+               } elsif ($line =~ m{\b$NonptrType(\*+)(?:\s+(?:$Attribute|$Sparse))?\s+[A-Za-z\d_]+}) {
                        ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
                                $herecurr);
 
-               } elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+(?:$Attribute|$Sparse))\s+[A-Za-z\d_]+}) {
+               } elsif ($line =~ m{\b$NonptrType\s+(\*+)(?!\s+(?:$Attribute|$Sparse))\s+[A-Za-z\d_]+}) {
                        ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
                                $herecurr);
                }
@@ -1421,6 +1491,17 @@ sub process {
                        ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
                }
 
+# check for spacing round square brackets; allowed:
+#  1. with a type on the left -- int [] a;
+#  2. at the beginning of a line for slice initialisers -- [0..10] = 5,
+               while ($line =~ /(.*?\s)\[/g) {
+                       my ($where, $prefix) = ($-[1], $1);
+                       if ($prefix !~ /$Type\s+$/ &&
+                           ($where != 0 || $prefix !~ /^.\s+$/)) {
+                               ERROR("space prohibited before open square bracket '['\n" . $herecurr);
+                       }
+               }
+
 # check for spaces between functions and their parentheses.
                while ($line =~ /($Ident)\s+\(/g) {
                        my $name = $1;
@@ -1457,7 +1538,8 @@ sub process {
                                <<=|>>=|<=|>=|==|!=|
                                \+=|-=|\*=|\/=|%=|\^=|\|=|&=|
                                =>|->|<<|>>|<|>|=|!|~|
-                               &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
+                               &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
+                               \?|:
                        }x;
                        my @elements = split(/($ops|;)/, $opline);
                        my $off = 0;
@@ -1504,22 +1586,11 @@ sub process {
                                my $ptr = substr($blank, 0, $off) . "^";
                                my $hereptr = "$hereline$ptr\n";
 
-                               # Classify operators into binary, unary, or
-                               # definitions (* only) where they have more
-                               # than one mode.
+                               # Pull out the value of this operator.
                                my $op_type = substr($curr_values, $off + 1, 1);
-                               my $op_left = substr($curr_values, $off, 1);
-                               my $is_unary;
-                               if ($op_type eq 'T') {
-                                       $is_unary = 2;
-                               } elsif ($op_left eq 'V') {
-                                       $is_unary = 0;
-                               } else {
-                                       $is_unary = 1;
-                               }
-                               #if ($op eq '-' || $op eq '&' || $op eq '*') {
-                               #       print "UNARY: <$op_left$op_type $is_unary $a:$op:$c> <$ca:$op:$cc> <$unary_ctx>\n";
-                               #}
+
+                               # Get the full operator variant.
+                               my $opv = $op . substr($curr_vars, $off, 1);
 
                                # Ignore operators passed as parameters.
                                if ($op_type ne 'V' &&
@@ -1538,8 +1609,10 @@ sub process {
                                # // is a comment
                                } elsif ($op eq '//') {
 
-                               # -> should have no spaces
-                               } elsif ($op eq '->') {
+                               # No spaces for:
+                               #   ->
+                               #   :   when part of a bitfield
+                               } elsif ($op eq '->' || $opv eq ':B') {
                                        if ($ctx =~ /Wx.|.xW/) {
                                                ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
                                        }
@@ -1551,18 +1624,19 @@ sub process {
                                        }
 
                                # '*' as part of a type definition -- reported already.
-                               } elsif ($op eq '*' && $is_unary == 2) {
+                               } elsif ($opv eq '*_') {
                                        #warn "'*' is part of type\n";
 
                                # unary operators should have a space before and
                                # none after.  May be left adjacent to another
                                # unary operator, or a cast
                                } elsif ($op eq '!' || $op eq '~' ||
-                                        ($is_unary && ($op eq '*' || $op eq '-' || $op eq '&'))) {
+                                        $opv eq '*U' || $opv eq '-U' ||
+                                        $opv eq '&U') {
                                        if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
                                                ERROR("space required before that '$op' $at\n" . $hereptr);
                                        }
-                                       if ($op  eq '*' && $cc =~/\s*const\b/) {
+                                       if ($op eq '*' && $cc =~/\s*const\b/) {
                                                # A unary '*' may be const
 
                                        } elsif ($ctx =~ /.xW/) {
@@ -1595,11 +1669,33 @@ sub process {
                                                        $hereptr);
                                        }
 
+                               # A colon needs no spaces before when it is
+                               # terminating a case value or a label.
+                               } elsif ($opv eq ':C' || $opv eq ':L') {
+                                       if ($ctx =~ /Wx./) {
+                                               ERROR("space prohibited before that '$op' $at\n" . $hereptr);
+                                       }
+
                                # All the others need spaces both sides.
                                } elsif ($ctx !~ /[EWC]x[CWE]/) {
+                                       my $ok = 0;
+
                                        # Ignore email addresses <foo@bar>
-                                       if (!($op eq '<' && $cb =~ /$;\S+\@\S+>/) &&
-                                           !($op eq '>' && $cb =~ /<\S+\@\S+$;/)) {
+                                       if (($op eq '<' &&
+                                            $cc =~ /^\S+\@\S+>/) ||
+                                           ($op eq '>' &&
+                                            $ca =~ /<\S+\@\S+$/))
+                                       {
+                                               $ok = 1;
+                                       }
+
+                                       # Ignore ?:
+                                       if (($opv eq ':O' && $ca =~ /\?$/) ||
+                                           ($op eq '?' && $cc =~ /^:/)) {
+                                               $ok = 1;
+                                       }
+
+                                       if ($ok == 0) {
                                                ERROR("spaces required around that '$op' $at\n" . $hereptr);
                                        }
                                }
@@ -1670,6 +1766,7 @@ sub process {
                        my $value = $2;
 
                        # Flatten any parentheses and braces
+                       $value =~ s/\)\(/\) \(/g;
                        while ($value =~ s/\([^\(\)]*\)/1/) {
                        }
 
@@ -1686,8 +1783,9 @@ sub process {
                        ERROR("space required before the open parenthesis '('\n" . $herecurr);
                }
 
-# Check for illegal assignment in if conditional.
-               if ($line =~ /\bif\s*\(/) {
+# Check for illegal assignment in if conditional -- and check for trailing
+# statements after the conditional.
+               if ($line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
                        my ($s, $c) = ($stat, $cond);
 
                        if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/) {
@@ -1699,13 +1797,63 @@ sub process {
                        substr($s, 0, length($c), '');
                        $s =~ s/\n.*//g;
                        $s =~ s/$;//g;  # Remove any comments
-                       if (length($c) && $s !~ /^\s*({|;|)\s*\\*\s*$/ &&
-                           $c !~ /^.\s*\#\s*if/)
+                       if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
+                           $c !~ /}\s*while\s*/)
                        {
                                ERROR("trailing statements should be on next line\n" . $herecurr);
                        }
                }
 
+# Check relative indent for conditionals and blocks.
+               if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
+                       my ($s, $c) = ($stat, $cond);
+
+                       substr($s, 0, length($c), '');
+
+                       # Make sure we remove the line prefixes as we have
+                       # none on the first line, and are going to readd them
+                       # where necessary.
+                       $s =~ s/\n./\n/gs;
+
+                       # We want to check the first line inside the block
+                       # starting at the end of the conditional, so remove:
+                       #  1) any blank line termination
+                       #  2) any opening brace { on end of the line
+                       #  3) any do (...) {
+                       my $continuation = 0;
+                       my $check = 0;
+                       $s =~ s/^.*\bdo\b//;
+                       $s =~ s/^\s*{//;
+                       if ($s =~ s/^\s*\\//) {
+                               $continuation = 1;
+                       }
+                       if ($s =~ s/^\s*\n//) {
+                               $check = 1;
+                       }
+
+                       # Also ignore a loop construct at the end of a
+                       # preprocessor statement.
+                       if (($prevline =~ /^.\s*#\s*define\s/ ||
+                           $prevline =~ /\\\s*$/) && $continuation == 0) {
+                               $check = 0;
+                       }
+
+                       # Ignore the current line if its is a preprocessor
+                       # line.
+                       if ($s =~ /^\s*#\s*/) {
+                               $check = 0;
+                       }
+
+                       my (undef, $sindent) = line_stats("+" . $s);
+
+                       ##print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s>\n";
+
+                       if ($check && (($sindent % 8) != 0 ||
+                           ($sindent <= $indent && $s ne ''))) {
+                               WARN("suspect code indent for conditional statements\n" . $herecurr);
+                       }
+               }
+
 # Check for bitwise tests written as boolean
                if ($line =~ /
                        (?:
@@ -1777,7 +1925,8 @@ sub process {
 # multi-statement macros should be enclosed in a do while loop, grab the
 # first statement and ensure its the whole macro if its not enclosed
 # in a known good container
-               if ($line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
+               if ($realfile !~ m@/vmlinux.lds.h$@ &&
+                   $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
                        my $ln = $linenr;
                        my $cnt = $realcnt;
                        my ($off, $dstat, $dcond, $rest);
@@ -1791,30 +1940,26 @@ sub process {
                                $lines[$ln - 1] =~ /^(?:-|..*\\$)/)
                        {
                                $ctx .= $rawlines[$ln - 1] . "\n";
+                               $cnt-- if ($lines[$ln - 1] !~ /^-/);
                                $ln++;
-                               $cnt--;
                        }
                        $ctx .= $rawlines[$ln - 1];
 
                        ($dstat, $dcond, $ln, $cnt, $off) =
                                ctx_statement_block($linenr, $ln - $linenr + 1, 0);
                        #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
-                       #print "LINE<$lines[$ln]> len<" . length($lines[$ln]) . "\n";
+                       #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
 
                        # Extract the remainder of the define (if any) and
                        # rip off surrounding spaces, and trailing \'s.
                        $rest = '';
-                       if (defined $lines[$ln - 1] &&
-                           $off > length($lines[$ln - 1]))
-                       {
-                               $ln++;
-                               $cnt--;
-                               $off = 0;
-                       }
-                       while ($cnt > 0) {
-                               $rest .= substr($lines[$ln - 1], $off) . "\n";
+                       while ($off != 0 || ($cnt > 0 && $rest =~ /(?:^|\\)\s*$/)) {
+                               #print "ADDING $off <" . substr($lines[$ln - 1], $off) . ">\n";
+                               if ($off != 0 || $lines[$ln - 1] !~ /^-/) {
+                                       $rest .= substr($lines[$ln - 1], $off) . "\n";
+                                       $cnt--;
+                               }
                                $ln++;
-                               $cnt--;
                                $off = 0;
                        }
                        $rest =~ s/\\\n.//g;
@@ -1827,6 +1972,7 @@ sub process {
                        } else {
                                $dstat =~ s/^.\s*\#\s*define\s+$Ident\s*//;
                        }
+                       $dstat =~ s/$;//g;
                        $dstat =~ s/\\\n.//g;
                        $dstat =~ s/^\s*//s;
                        $dstat =~ s/\s*$//s;
@@ -1845,6 +1991,7 @@ sub process {
                                DEFINE_PER_CPU|
                                __typeof__\(
                        }x;
+                       #print "REST<$rest>\n";
                        if ($rest ne '') {
                                if ($rest !~ /while\s*\(/ &&
                                    $dstat !~ /$exceptions/)
@@ -2001,7 +2148,14 @@ sub process {
                if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
                        my $expr = $1;
                        if ($line =~ /\bkfree\(\Q$expr\E\);/) {
-                               WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
+                               WARN("kfree(NULL) is safe this check is probably not required\n" . $hereprev);
+                       }
+               }
+# check for needless usb_free_urb() checks
+               if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
+                       my $expr = $1;
+                       if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) {
+                               WARN("usb_free_urb(NULL) is safe this check is probably not required\n" . $hereprev);
                        }
                }
 
@@ -2106,6 +2260,10 @@ sub process {
                if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
                        WARN("consider using strict_$1 in preference to simple_$1\n" . $herecurr);
                }
+# check for __initcall(), use device_initcall() explicitly please
+               if ($line =~ /^.\s*__initcall\s*\(/) {
+                       WARN("please use device_initcall() instead of __initcall()\n" . $herecurr);
+               }
 
 # use of NR_CPUS is usually wrong
 # ignore definitions of NR_CPUS and usage to define arrays as likely right
index 340ad6920511aa08a52f5360c54836c682e2deed..3eca62566d6b4468412c9ff2afdbb3b5675dc7b6 100755 (executable)
 # $& (whole re) matches the complete objdump line with the stack growth
 # $1 (first bracket) matches the size of the stack growth
 #
+# $dre is similar, but for dynamic stack redutions:
+# $& (whole re) matches the complete objdump line with the stack growth
+# $1 (first bracket) matches the dynamic amount of the stack growth
+#
 # use anything else and feel the pain ;)
-my (@stack, $re, $x, $xs);
+my (@stack, $re, $dre, $x, $xs);
 {
        my $arch = shift;
        if ($arch eq "") {
                $arch = `uname -m`;
+               chomp($arch);
        }
 
        $x      = "[0-9a-f]";   # hex character
@@ -46,9 +51,11 @@ my (@stack, $re, $x, $xs);
        } elsif ($arch =~ /^i[3456]86$/) {
                #c0105234:       81 ec ac 05 00 00       sub    $0x5ac,%esp
                $re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%esp$/o;
+               $dre = qr/^.*[as][du][db]    (%.*),\%esp$/o;
        } elsif ($arch eq 'x86_64') {
                #    2f60:      48 81 ec e8 05 00 00    sub    $0x5e8,%rsp
                $re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%rsp$/o;
+               $dre = qr/^.*[as][du][db]    (\%.*),\%rsp$/o;
        } elsif ($arch eq 'ia64') {
                #e0000000044011fc:       01 0f fc 8c     adds r12=-384,r12
                $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o;
@@ -85,7 +92,7 @@ my (@stack, $re, $x, $xs);
                #   0:   00 e8 38 01     LINK 0x4e0;
                $re = qr/.*[[:space:]]LINK[[:space:]]*(0x$x{1,8})/o;
        } else {
-               print("wrong or unknown architecture\n");
+               print("wrong or unknown architecture \"$arch\"\n");
                exit
        }
 }
@@ -141,6 +148,22 @@ while (my $line = <STDIN>) {
                next if ($size < 100);
                push @stack, "$intro$size\n";
        }
+       elsif (defined $dre && $line =~ m/$dre/) {
+               my $size = "Dynamic ($1)";
+
+               next if $line !~ m/^($xs*)/;
+               my $addr = $1;
+               $addr =~ s/ /0/g;
+               $addr = "0x$addr";
+
+               my $intro = "$addr $func [$file]:";
+               my $padlen = 56 - length($intro);
+               while ($padlen > 0) {
+                       $intro .= '     ';
+                       $padlen -= 8;
+               }
+               push @stack, "$intro$size\n";
+       }
 }
 
 print sort bysize @stack;
diff --git a/scripts/diffconfig b/scripts/diffconfig
new file mode 100755 (executable)
index 0000000..b91f3e3
--- /dev/null
@@ -0,0 +1,129 @@
+#!/usr/bin/python
+#
+# diffconfig - a tool to compare .config files.
+#
+# originally written in 2006 by Matt Mackall
+#  (at least, this was in his bloatwatch source code)
+# last worked on 2008 by Tim Bird
+#
+
+import sys, os
+
+def usage():
+    print """Usage: diffconfig [-h] [-m] [<config1> <config2>]
+
+Diffconfig is a simple utility for comparing two .config files.
+Using standard diff to compare .config files often includes extraneous and
+distracting information.  This utility produces sorted output with only the
+changes in configuration values between the two files.
+
+Added and removed items are shown with a leading plus or minus, respectively.
+Changed items show the old and new values on a single line.
+
+If -m is specified, then output will be in "merge" style, which has the
+changed and new values in kernel config option format.
+
+If no config files are specified, .config and .config.old are used.
+
+Example usage:
+ $ diffconfig .config config-with-some-changes
+-EXT2_FS_XATTR  n
+-EXT2_FS_XIP  n
+ CRAMFS  n -> y
+ EXT2_FS  y -> n
+ LOG_BUF_SHIFT  14 -> 16
+ PRINTK_TIME  n -> y
+"""
+    sys.exit(0)
+
+# returns a dictionary of name/value pairs for config items in the file
+def readconfig(config_file):
+    d = {}
+    for line in config_file:
+        line = line[:-1]
+        if line[:7] == "CONFIG_":
+            name, val = line[7:].split("=", 1)
+            d[name] = val
+        if line[-11:] == " is not set":
+            d[line[9:-11]] = "n"
+    return d
+
+def print_config(op, config, value, new_value):
+    global merge_style
+
+    if merge_style:
+        if new_value:
+            if new_value=="n":
+                print "# CONFIG_%s is not set" % config
+            else:
+                print "CONFIG_%s=%s" % (config, new_value)
+    else:
+        if op=="-":
+            print "-%s %s" % (config, value)
+        elif op=="+":
+            print "+%s %s" % (config, new_value)
+        else:
+            print " %s %s -> %s" % (config, value, new_value)
+
+def main():
+    global merge_style
+
+    # parse command line args
+    if ("-h" in sys.argv or "--help" in sys.argv):
+       usage()
+
+    merge_style = 0
+    if "-m" in sys.argv:
+        merge_style = 1
+        sys.argv.remove("-m")
+
+    argc = len(sys.argv)
+    if not (argc==1 or argc == 3):
+        print "Error: incorrect number of arguments or unrecognized option"
+        usage()
+
+    if argc == 1:
+        # if no filenames given, assume .config and .config.old
+        build_dir=""
+        if os.environ.has_key("KBUILD_OUTPUT"):
+            build_dir = os.environ["KBUILD_OUTPUT"]+"/"
+
+        configa_filename = build_dir + ".config.old"
+        configb_filename = build_dir + ".config"
+    else:
+        configa_filename = sys.argv[1]
+        configb_filename = sys.argv[2]
+
+    a = readconfig(file(configa_filename))
+    b = readconfig(file(configb_filename))
+
+    # print items in a but not b (accumulate, sort and print)
+    old = []
+    for config in a:
+        if config not in b:
+            old.append(config)
+    old.sort()
+    for config in old:
+        print_config("-", config, a[config], None)
+        del a[config]
+
+    # print items that changed (accumulate, sort, and print)
+    changed = []
+    for config in a:
+        if a[config] != b[config]:
+            changed.append(config)
+        else:
+            del b[config]
+    changed.sort()
+    for config in changed:
+        print_config("->", config, a[config], b[config])
+        del b[config]
+
+    # now print items in b but not in a
+    # (items from b that were in a were removed above)
+    new = b.keys()
+    new.sort()
+    for config in new:
+        print_config("+", config, None, b[config])
+
+main()
index dca5e0dd09bf1fdc57b525f23befeba074e41c10..4f8a3007e45706117a74fe316a28c28c7e46486f 100644 (file)
@@ -520,8 +520,7 @@ int main(int argc, char **argv)
                        genksyms_usage();
                        return 1;
                }
-       if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0)
-           || (strcmp(arch, "blackfin") == 0))
+       if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0))
                mod_prefix = "_";
        {
                extern int yydebug;
diff --git a/scripts/hdrcheck.sh b/scripts/hdrcheck.sh
deleted file mode 100755 (executable)
index 3159858..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-for FILE in `grep '^[ \t]*#[ \t]*include[ \t]*<' $2 | cut -f2 -d\< | cut -f1 -d\> | egrep ^linux\|^asm` ; do
-    if [ ! -r $1/$FILE ]; then
-       echo $2 requires $FILE, which does not exist in exported headers
-       exit 1
-    fi
-done
-# FIXME: List dependencies into $3
-touch $3
diff --git a/scripts/headers.sh b/scripts/headers.sh
new file mode 100755 (executable)
index 0000000..d33426f
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+# Run headers_$1 command for all suitable architectures
+
+# Stop on error
+set -e
+
+do_command()
+{
+       if [ -f ${srctree}/arch/$2/include/asm/Kbuild ]; then
+               make ARCH=$2 KBUILD_HEADERS=$1 headers_$1
+       elif [ -f ${srctree}/include/asm-$2/Kbuild ]; then
+               make ARCH=$2 KBUILD_HEADERS=$1 headers_$1
+       else
+               printf "Ignoring arch: %s\n" ${arch}
+       fi
+}
+
+# Do not try this architecture
+drop="generic um ppc sparc64 cris"
+
+archs=$(ls ${srctree}/arch)
+
+for arch in ${archs}; do
+       case ${arch} in
+       um)        # no userspace export
+               ;;
+       ppc)       # headers exported by powerpc
+               ;;
+       sparc64)   # headers exported by sparc
+               ;;
+       cris)      # headers export are known broken
+               ;;
+       *)
+               if [ -d ${srctree}/arch/${arch} ]; then
+                       do_command $1 ${arch}
+               fi
+               ;;
+       esac
+done
+
+
diff --git a/scripts/headers_check.pl b/scripts/headers_check.pl
new file mode 100644 (file)
index 0000000..15d53a6
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+#
+# headers_check.pl execute a number of trivial consistency checks
+#
+# Usage: headers_check.pl dir [files...]
+# dir:   dir to look for included files
+# arch:  architecture
+# files: list of files to check
+#
+# The script reads the supplied files line by line and:
+#
+# 1) for each include statement it checks if the
+#    included file actually exists.
+#    Only include files located in asm* and linux* are checked.
+#    The rest are assumed to be system include files.
+#
+# 2) TODO: check for leaked CONFIG_ symbols
+
+use strict;
+use warnings;
+
+my ($dir, $arch, @files) = @ARGV;
+
+my $ret = 0;
+my $line;
+my $lineno = 0;
+my $filename;
+
+foreach my $file (@files) {
+       $filename = $file;
+       open(my $fh, '<', "$filename") or die "$filename: $!\n";
+       $lineno = 0;
+       while ($line = <$fh>) {
+               $lineno++;
+               check_include();
+       }
+       close $fh;
+}
+exit $ret;
+
+sub check_include
+{
+       if ($line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/) {
+               my $inc = $1;
+               my $found;
+               $found = stat($dir . "/" . $inc);
+               if (!$found) {
+                       $inc =~ s#asm/#asm-$arch/#;
+                       $found = stat($dir . "/" . $inc);
+               }
+               if (!$found) {
+                       printf STDERR "$filename:$lineno: included file '$inc' is not exported\n";
+                       $ret = 1;
+               }
+       }
+}
diff --git a/scripts/headers_install.pl b/scripts/headers_install.pl
new file mode 100644 (file)
index 0000000..68591cd
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+#
+# headers_install prepare the listed header files for use in
+# user space and copy the files to their destination.
+#
+# Usage: headers_install.pl readdir installdir arch [files...]
+# readdir:    dir to open files
+# installdir: dir to install the files
+# arch:       current architecture
+#             arch is used to force a reinstallation when the arch
+#             changes because kbuild then detect a command line change.
+# files:      list of files to check
+#
+# Step in preparation for users space:
+# 1) Drop all use of compiler.h definitions
+# 2) Drop include of compiler.h
+# 3) Drop all sections defined out by __KERNEL__ (using unifdef)
+
+use strict;
+use warnings;
+
+my ($readdir, $installdir, $arch, @files) = @ARGV;
+
+my $unifdef = "scripts/unifdef -U__KERNEL__";
+
+foreach my $file (@files) {
+       my $tmpfile = "$installdir/$file.tmp";
+       open(my $infile, '<', "$readdir/$file")
+               or die "$readdir/$file: $!\n";
+       open(my $outfile, '>', "$tmpfile") or die "$tmpfile: $!\n";
+       while (my $line = <$infile>) {
+               $line =~ s/([\s(])__user\s/$1/g;
+               $line =~ s/([\s(])__force\s/$1/g;
+               $line =~ s/([\s(])__iomem\s/$1/g;
+               $line =~ s/\s__attribute_const__\s/ /g;
+               $line =~ s/\s__attribute_const__$//g;
+               $line =~ s/^#include <linux\/compiler.h>//;
+               printf $outfile "%s", $line;
+       }
+       close $outfile;
+       close $infile;
+       system $unifdef . " $tmpfile > $installdir/$file";
+       unlink $tmpfile;
+}
+exit 0;
index fda63136ae6809512c6d84ab5c11d1497eee3bc5..9fba838c7069c4cb71d3fbd9c109e0f951c5e340 100644 (file)
@@ -76,7 +76,6 @@ static void check_stdin(void)
 static int conf_askvalue(struct symbol *sym, const char *def)
 {
        enum symbol_type type = sym_get_type(sym);
-       tristate val;
 
        if (!sym_has_value(sym))
                printf(_("(NEW) "));
@@ -92,15 +91,6 @@ static int conf_askvalue(struct symbol *sym, const char *def)
        }
 
        switch (input_mode) {
-       case set_no:
-       case set_mod:
-       case set_yes:
-       case set_random:
-               if (sym_has_value(sym)) {
-                       printf("%s\n", def);
-                       return 0;
-               }
-               break;
        case ask_new:
        case ask_silent:
                if (sym_has_value(sym)) {
@@ -112,9 +102,6 @@ static int conf_askvalue(struct symbol *sym, const char *def)
                fflush(stdout);
                fgets(line, 128, stdin);
                return 1;
-       case set_default:
-               printf("%s\n", def);
-               return 1;
        default:
                break;
        }
@@ -128,52 +115,6 @@ static int conf_askvalue(struct symbol *sym, const char *def)
        default:
                ;
        }
-       switch (input_mode) {
-       case set_yes:
-               if (sym_tristate_within_range(sym, yes)) {
-                       line[0] = 'y';
-                       line[1] = '\n';
-                       line[2] = 0;
-                       break;
-               }
-       case set_mod:
-               if (type == S_TRISTATE) {
-                       if (sym_tristate_within_range(sym, mod)) {
-                               line[0] = 'm';
-                               line[1] = '\n';
-                               line[2] = 0;
-                               break;
-                       }
-               } else {
-                       if (sym_tristate_within_range(sym, yes)) {
-                               line[0] = 'y';
-                               line[1] = '\n';
-                               line[2] = 0;
-                               break;
-                       }
-               }
-       case set_no:
-               if (sym_tristate_within_range(sym, no)) {
-                       line[0] = 'n';
-                       line[1] = '\n';
-                       line[2] = 0;
-                       break;
-               }
-       case set_random:
-               do {
-                       val = (tristate)(rand() % 3);
-               } while (!sym_tristate_within_range(sym, val));
-               switch (val) {
-               case no: line[0] = 'n'; break;
-               case mod: line[0] = 'm'; break;
-               case yes: line[0] = 'y'; break;
-               }
-               line[1] = '\n';
-               line[2] = 0;
-               break;
-       default:
-               break;
-       }
        printf("%s", line);
        return 1;
 }
@@ -374,15 +315,7 @@ static int conf_choice(struct menu *menu)
                        else
                                continue;
                        break;
-               case set_random:
-                       if (is_new)
-                               def = (rand() % cnt) + 1;
-               case set_default:
-               case set_yes:
-               case set_mod:
-               case set_no:
-                       cnt = def;
-                       printf("%d\n", cnt);
+               default:
                        break;
                }
 
@@ -494,6 +427,43 @@ static void check_conf(struct menu *menu)
                check_conf(child);
 }
 
+static void conf_do_update(void)
+{
+       /* Update until a loop caused no more changes */
+       do {
+               conf_cnt = 0;
+               check_conf(&rootmenu);
+       } while (conf_cnt);
+}
+
+static int conf_silent_update(void)
+{
+       const char *name;
+
+       if (conf_get_changed()) {
+               name = getenv("KCONFIG_NOSILENTUPDATE");
+               if (name && *name) {
+                       fprintf(stderr,
+                       _("\n*** Kernel configuration requires explicit update.\n\n"));
+                       return 1;
+               }
+               conf_do_update();
+       }
+       return 0;
+}
+
+static int conf_update(void)
+{
+       rootEntry = &rootmenu;
+       conf(&rootmenu);
+       if (input_mode == ask_all) {
+               input_mode = ask_silent;
+               valid_stdin = 1;
+       }
+       conf_do_update();
+       return 0;
+}
+
 int main(int ac, char **av)
 {
        int opt;
@@ -599,36 +569,43 @@ int main(int ac, char **av)
        default:
                break;
        }
+       switch (input_mode) {
+       case set_no:
+               conf_set_all_new_symbols(def_no);
+               break;
+       case set_yes:
+               conf_set_all_new_symbols(def_yes);
+               break;
+       case set_mod:
+               conf_set_all_new_symbols(def_mod);
+               break;
+       case set_random:
+               conf_set_all_new_symbols(def_random);
+               break;
+       case set_default:
+               conf_set_all_new_symbols(def_default);
+               break;
+       case ask_silent:
+       case ask_new:
+               if (conf_silent_update())
+                       exit(1);
+               break;
+       case ask_all:
+               if (conf_update())
+                       exit(1);
+               break;
+       }
 
-       if (input_mode != ask_silent) {
-               rootEntry = &rootmenu;
-               conf(&rootmenu);
-               if (input_mode == ask_all) {
-                       input_mode = ask_silent;
-                       valid_stdin = 1;
-               }
-       } else if (conf_get_changed()) {
-               name = getenv("KCONFIG_NOSILENTUPDATE");
-               if (name && *name) {
-                       fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
-                       return 1;
-               }
-       } else
-               goto skip_check;
-
-       do {
-               conf_cnt = 0;
-               check_conf(&rootmenu);
-       } while (conf_cnt);
-       if (conf_write(NULL)) {
+       if (conf_get_changed() && conf_write(NULL)) {
                fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
-               return 1;
+               exit(1);
        }
-skip_check:
+       /* ask_silent is used during the build so we shall update autoconf.
+        * All other commands are only used to generate a config.
+        */
        if (input_mode == ask_silent && conf_write_autoconf()) {
                fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
                return 1;
        }
-
        return 0;
 }
index ee5fe943d58db0eda374b91a8181e5991d8cf23b..07597611cc504deca5098cdd7638ace892cd4441 100644 (file)
@@ -812,3 +812,73 @@ void conf_set_changed_callback(void (*fn)(void))
 {
        conf_changed_callback = fn;
 }
+
+
+void conf_set_all_new_symbols(enum conf_def_mode mode)
+{
+       struct symbol *sym, *csym;
+       struct property *prop;
+       struct expr *e;
+       int i, cnt, def;
+
+       for_all_symbols(i, sym) {
+               if (sym_has_value(sym))
+                       continue;
+               switch (sym_get_type(sym)) {
+               case S_BOOLEAN:
+               case S_TRISTATE:
+                       switch (mode) {
+                       case def_yes:
+                               sym->def[S_DEF_USER].tri = yes;
+                               break;
+                       case def_mod:
+                               sym->def[S_DEF_USER].tri = mod;
+                               break;
+                       case def_no:
+                               sym->def[S_DEF_USER].tri = no;
+                               break;
+                       case def_random:
+                               sym->def[S_DEF_USER].tri = (tristate)(rand() % 3);
+                               break;
+                       default:
+                               continue;
+                       }
+                       if (!sym_is_choice(sym) || mode != def_random)
+                               sym->flags |= SYMBOL_DEF_USER;
+                       break;
+               default:
+                       break;
+               }
+
+       }
+
+       if (modules_sym)
+               sym_calc_value(modules_sym);
+
+       if (mode != def_random)
+               return;
+
+       for_all_symbols(i, csym) {
+               if (sym_has_value(csym) || !sym_is_choice(csym))
+                       continue;
+
+               sym_calc_value(csym);
+               prop = sym_get_choice_prop(csym);
+               def = -1;
+               while (1) {
+                       cnt = 0;
+                       expr_list_for_each_sym(prop->expr, e, sym) {
+                               if (sym->visible == no)
+                                       continue;
+                               if (def == cnt++) {
+                                       csym->def[S_DEF_USER].val = sym;
+                                       break;
+                               }
+                       }
+                       if (def >= 0 || cnt < 2)
+                               break;
+                       def = (rand() % cnt) + 1;
+               }
+               csym->flags |= SYMBOL_DEF_USER;
+       }
+}
index 96521cb087ec388587d4737c375c42862f4b5a24..4a9af6f7886b8f1362fc593009f3e36374a5e3bd 100644 (file)
@@ -42,6 +42,14 @@ extern "C" {
 #define TF_PARAM       0x0002
 #define TF_OPTION      0x0004
 
+enum conf_def_mode {
+       def_default,
+       def_yes,
+       def_mod,
+       def_no,
+       def_random
+};
+
 #define T_OPT_MODULES          1
 #define T_OPT_DEFCONFIG_LIST   2
 #define T_OPT_ENV              3
@@ -69,6 +77,7 @@ const char *conf_get_configname(void);
 char *conf_get_default_confname(void);
 void sym_set_change_count(int count);
 void sym_add_change_count(int count);
+void conf_set_all_new_symbols(enum conf_def_mode mode);
 
 /* kconfig_load.c */
 void kconfig_load(void);
index 88e3934a8b8c86f6e5962ac64acb36ab7d0c08dd..d8f77e26081c230a3bc489f5c773950cab3b10d3 100755 (executable)
@@ -1643,6 +1643,7 @@ sub dump_function($$) {
     $prototype =~ s/^__always_inline +//;
     $prototype =~ s/^noinline +//;
     $prototype =~ s/__devinit +//;
+    $prototype =~ s/__init +//;
     $prototype =~ s/^#define\s+//; #ak added
     $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
 
index 1fcaf3284a6a2990128f2589b5856cec3997097c..4fa1f3ad251340833a3b5d4b094dbc0c05557068 100644 (file)
@@ -623,7 +623,7 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
        return 1;
 }
 
-/* Ignore any prefix, eg. v850 prepends _ */
+/* Ignore any prefix, eg. some architectures prepend _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
        const char *match;
index db3881f14c2d911d7bbf5d2b98d67a30e771b2fe..6a96d47bd1e6e8cdb9ded3b0f0551fdf621dade9 100644 (file)
@@ -55,7 +55,7 @@ main(int argc, char **argv)
        else
                exit(1);
 
-       if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)
+       if ((strcmp(argv[1], "h8300") == 0)
            || (strcmp(argv[1], "blackfin") == 0))
                printf("#define MODULE_SYMBOL_PREFIX \"_\"\n");
        else
index 1c1bdaf7348a61fc3606165cb1cc5c6725831e05..83b75126c9f7b5c57a92c8f996dc94e6c61d6680 100755 (executable)
@@ -12,7 +12,9 @@ cd "${1:-.}" || usage
 if head=`git rev-parse --verify HEAD 2>/dev/null`; then
        # Do we have an untagged version?
        if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then
-               git describe | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+               if tag=`git describe 2>/dev/null`; then
+                       echo $tag | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+               fi
        fi
 
        # Are there uncommitted changes?
index 62ed4717d334f3f10de514aa4b9e088f4b2ca827..559293922a479eabf188b70e963d5264f9032799 100644 (file)
@@ -74,8 +74,7 @@ config SECURITY_NETWORK_XFRM
          If you are unsure how to answer this question, answer N.
 
 config SECURITY_FILE_CAPABILITIES
-       bool "File POSIX Capabilities (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       bool "File POSIX Capabilities"
        default n
        help
          This enables filesystem capabilities, allowing you to give
index 5b01c0b02422b28a1809ba7be383e1b93e76159f..63d10da515a5b01e9cf36a2f7b2a49e82b10d199 100644 (file)
@@ -211,8 +211,7 @@ static int cap_inode_follow_link(struct dentry *dentry,
        return 0;
 }
 
-static int cap_inode_permission(struct inode *inode, int mask,
-                               struct nameidata *nd)
+static int cap_inode_permission(struct inode *inode, int mask)
 {
        return 0;
 }
index 0b6537a3672d8822baf4b10627f142e9afc1102b..4afbece37a086af337be9f3b8566a11843092ee3 100644 (file)
@@ -162,8 +162,7 @@ void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
 
 static inline void bprm_clear_caps(struct linux_binprm *bprm)
 {
-       cap_clear(bprm->cap_inheritable);
-       cap_clear(bprm->cap_permitted);
+       cap_clear(bprm->cap_post_exec_permitted);
        bprm->cap_effective = false;
 }
 
@@ -198,6 +197,7 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
 {
        __u32 magic_etc;
        unsigned tocopy, i;
+       int ret;
 
        if (size < sizeof(magic_etc))
                return -EINVAL;
@@ -225,19 +225,40 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
                bprm->cap_effective = false;
        }
 
-       for (i = 0; i < tocopy; ++i) {
-               bprm->cap_permitted.cap[i] =
-                       le32_to_cpu(caps->data[i].permitted);
-               bprm->cap_inheritable.cap[i] =
-                       le32_to_cpu(caps->data[i].inheritable);
-       }
-       while (i < VFS_CAP_U32) {
-               bprm->cap_permitted.cap[i] = 0;
-               bprm->cap_inheritable.cap[i] = 0;
-               i++;
+       ret = 0;
+
+       CAP_FOR_EACH_U32(i) {
+               __u32 value_cpu;
+
+               if (i >= tocopy) {
+                       /*
+                        * Legacy capability sets have no upper bits
+                        */
+                       bprm->cap_post_exec_permitted.cap[i] = 0;
+                       continue;
+               }
+               /*
+                * pP' = (X & fP) | (pI & fI)
+                */
+               value_cpu = le32_to_cpu(caps->data[i].permitted);
+               bprm->cap_post_exec_permitted.cap[i] =
+                       (current->cap_bset.cap[i] & value_cpu) |
+                       (current->cap_inheritable.cap[i] &
+                               le32_to_cpu(caps->data[i].inheritable));
+               if (value_cpu & ~bprm->cap_post_exec_permitted.cap[i]) {
+                       /*
+                        * insufficient to execute correctly
+                        */
+                       ret = -EPERM;
+               }
        }
 
-       return 0;
+       /*
+        * For legacy apps, with no internal support for recognizing they
+        * do not have enough capabilities, we return an error if they are
+        * missing some "forced" (aka file-permitted) capabilities.
+        */
+       return bprm->cap_effective ? ret : 0;
 }
 
 /* Locate any VFS capabilities: */
@@ -269,9 +290,9 @@ static int get_file_caps(struct linux_binprm *bprm)
                goto out;
 
        rc = cap_from_disk(&vcaps, bprm, rc);
-       if (rc)
+       if (rc == -EINVAL)
                printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
-                       __func__, rc, bprm->filename);
+                      __func__, rc, bprm->filename);
 
 out:
        dput(dentry);
@@ -304,25 +325,24 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
        int ret;
 
        ret = get_file_caps(bprm);
-       if (ret)
-               printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
-                       __func__, ret, bprm->filename);
-
-       /*  To support inheritance of root-permissions and suid-root
-        *  executables under compatibility mode, we raise all three
-        *  capability sets for the file.
-        *
-        *  If only the real uid is 0, we only raise the inheritable
-        *  and permitted sets of the executable file.
-        */
 
-       if (!issecure (SECURE_NOROOT)) {
+       if (!issecure(SECURE_NOROOT)) {
+               /*
+                * To support inheritance of root-permissions and suid-root
+                * executables under compatibility mode, we override the
+                * capability sets for the file.
+                *
+                * If only the real uid is 0, we do not set the effective
+                * bit.
+                */
                if (bprm->e_uid == 0 || current->uid == 0) {
-                       cap_set_full (bprm->cap_inheritable);
-                       cap_set_full (bprm->cap_permitted);
+                       /* pP' = (cap_bset & ~0) | (pI & ~0) */
+                       bprm->cap_post_exec_permitted = cap_combine(
+                               current->cap_bset, current->cap_inheritable
+                               );
+                       bprm->cap_effective = (bprm->e_uid == 0);
+                       ret = 0;
                }
-               if (bprm->e_uid == 0)
-                       bprm->cap_effective = true;
        }
 
        return ret;
@@ -330,17 +350,9 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
 
 void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
 {
-       /* Derived from fs/exec.c:compute_creds. */
-       kernel_cap_t new_permitted, working;
-
-       new_permitted = cap_intersect(bprm->cap_permitted,
-                                current->cap_bset);
-       working = cap_intersect(bprm->cap_inheritable,
-                                current->cap_inheritable);
-       new_permitted = cap_combine(new_permitted, working);
-
        if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
-           !cap_issubset (new_permitted, current->cap_permitted)) {
+           !cap_issubset(bprm->cap_post_exec_permitted,
+                         current->cap_permitted)) {
                set_dumpable(current->mm, suid_dumpable);
                current->pdeath_signal = 0;
 
@@ -350,9 +362,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
                                bprm->e_gid = current->gid;
                        }
                        if (cap_limit_ptraced_target()) {
-                               new_permitted =
-                                       cap_intersect(new_permitted,
-                                                     current->cap_permitted);
+                               bprm->cap_post_exec_permitted = cap_intersect(
+                                       bprm->cap_post_exec_permitted,
+                                       current->cap_permitted);
                        }
                }
        }
@@ -364,9 +376,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
         * in the init_task struct. Thus we skip the usual
         * capability rules */
        if (!is_global_init(current)) {
-               current->cap_permitted = new_permitted;
+               current->cap_permitted = bprm->cap_post_exec_permitted;
                if (bprm->cap_effective)
-                       current->cap_effective = new_permitted;
+                       current->cap_effective = bprm->cap_post_exec_permitted;
                else
                        cap_clear(current->cap_effective);
        }
@@ -381,9 +393,7 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
        if (current->uid != 0) {
                if (bprm->cap_effective)
                        return 1;
-               if (!cap_isclear(bprm->cap_permitted))
-                       return 1;
-               if (!cap_isclear(bprm->cap_inheritable))
+               if (!cap_isclear(bprm->cap_post_exec_permitted))
                        return 1;
        }
 
index ddd92cec78ed81c44bcfc4d9c530662a179381f2..7bd296cca041aaa7e62a3f923182ff7ac2adf5ef 100644 (file)
@@ -41,6 +41,7 @@ struct dev_whitelist_item {
        short type;
        short access;
        struct list_head list;
+       struct rcu_head rcu;
 };
 
 struct dev_cgroup {
@@ -59,6 +60,11 @@ static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup)
        return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id));
 }
 
+static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
+{
+       return css_to_devcgroup(task_subsys_state(task, devices_subsys_id));
+}
+
 struct cgroup_subsys devices_subsys;
 
 static int devcgroup_can_attach(struct cgroup_subsys *ss,
@@ -128,11 +134,19 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
        }
 
        if (whcopy != NULL)
-               list_add_tail(&whcopy->list, &dev_cgroup->whitelist);
+               list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist);
        spin_unlock(&dev_cgroup->lock);
        return 0;
 }
 
+static void whitelist_item_free(struct rcu_head *rcu)
+{
+       struct dev_whitelist_item *item;
+
+       item = container_of(rcu, struct dev_whitelist_item, rcu);
+       kfree(item);
+}
+
 /*
  * called under cgroup_lock()
  * since the list is visible to other tasks, we need the spinlock also
@@ -156,8 +170,8 @@ static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
 remove:
                walk->access &= ~wh->access;
                if (!walk->access) {
-                       list_del(&walk->list);
-                       kfree(walk);
+                       list_del_rcu(&walk->list);
+                       call_rcu(&walk->rcu, whitelist_item_free);
                }
        }
        spin_unlock(&dev_cgroup->lock);
@@ -188,7 +202,7 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
                }
                wh->minor = wh->major = ~0;
                wh->type = DEV_ALL;
-               wh->access = ACC_MKNOD | ACC_READ | ACC_WRITE;
+               wh->access = ACC_MASK;
                list_add(&wh->list, &dev_cgroup->whitelist);
        } else {
                parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
@@ -250,11 +264,10 @@ static char type_to_char(short type)
 
 static void set_majmin(char *str, unsigned m)
 {
-       memset(str, 0, MAJMINLEN);
        if (m == ~0)
-               sprintf(str, "*");
+               strcpy(str, "*");
        else
-               snprintf(str, MAJMINLEN, "%u", m);
+               sprintf(str, "%u", m);
 }
 
 static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
@@ -264,15 +277,15 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
        struct dev_whitelist_item *wh;
        char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
 
-       spin_lock(&devcgroup->lock);
-       list_for_each_entry(wh, &devcgroup->whitelist, list) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(wh, &devcgroup->whitelist, list) {
                set_access(acc, wh->access);
                set_majmin(maj, wh->major);
                set_majmin(min, wh->minor);
                seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
                           maj, min, acc);
        }
-       spin_unlock(&devcgroup->lock);
+       rcu_read_unlock();
 
        return 0;
 }
@@ -312,10 +325,10 @@ static int may_access_whitelist(struct dev_cgroup *c,
  * when adding a new allow rule to a device whitelist, the rule
  * must be allowed in the parent device
  */
-static int parent_has_perm(struct cgroup *childcg,
+static int parent_has_perm(struct dev_cgroup *childcg,
                                  struct dev_whitelist_item *wh)
 {
-       struct cgroup *pcg = childcg->parent;
+       struct cgroup *pcg = childcg->css.cgroup->parent;
        struct dev_cgroup *parent;
        int ret;
 
@@ -341,39 +354,19 @@ static int parent_has_perm(struct cgroup *childcg,
  * new access is only allowed if you're in the top-level cgroup, or your
  * parent cgroup has the access you're asking for.
  */
-static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
-                               struct file *file, const char __user *userbuf,
-                               size_t nbytes, loff_t *ppos)
+static int devcgroup_update_access(struct dev_cgroup *devcgroup,
+                                  int filetype, const char *buffer)
 {
-       struct cgroup *cur_cgroup;
-       struct dev_cgroup *devcgroup, *cur_devcgroup;
-       int filetype = cft->private;
-       char *buffer, *b;
+       struct dev_cgroup *cur_devcgroup;
+       const char *b;
+       char *endp;
        int retval = 0, count;
        struct dev_whitelist_item wh;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       devcgroup = cgroup_to_devcgroup(cgroup);
-       cur_cgroup = task_cgroup(current, devices_subsys.subsys_id);
-       cur_devcgroup = cgroup_to_devcgroup(cur_cgroup);
-
-       buffer = kmalloc(nbytes+1, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       if (copy_from_user(buffer, userbuf, nbytes)) {
-               retval = -EFAULT;
-               goto out1;
-       }
-       buffer[nbytes] = 0;     /* nul-terminate */
-
-       cgroup_lock();
-       if (cgroup_is_removed(cgroup)) {
-               retval = -ENODEV;
-               goto out2;
-       }
+       cur_devcgroup = task_devcgroup(current);
 
        memset(&wh, 0, sizeof(wh));
        b = buffer;
@@ -392,32 +385,23 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
                wh.type = DEV_CHAR;
                break;
        default:
-               retval = -EINVAL;
-               goto out2;
+               return -EINVAL;
        }
        b++;
-       if (!isspace(*b)) {
-               retval = -EINVAL;
-               goto out2;
-       }
+       if (!isspace(*b))
+               return -EINVAL;
        b++;
        if (*b == '*') {
                wh.major = ~0;
                b++;
        } else if (isdigit(*b)) {
-               wh.major = 0;
-               while (isdigit(*b)) {
-                       wh.major = wh.major*10+(*b-'0');
-                       b++;
-               }
+               wh.major = simple_strtoul(b, &endp, 10);
+               b = endp;
        } else {
-               retval = -EINVAL;
-               goto out2;
-       }
-       if (*b != ':') {
-               retval = -EINVAL;
-               goto out2;
+               return -EINVAL;
        }
+       if (*b != ':')
+               return -EINVAL;
        b++;
 
        /* read minor */
@@ -425,19 +409,13 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
                wh.minor = ~0;
                b++;
        } else if (isdigit(*b)) {
-               wh.minor = 0;
-               while (isdigit(*b)) {
-                       wh.minor = wh.minor*10+(*b-'0');
-                       b++;
-               }
+               wh.minor = simple_strtoul(b, &endp, 10);
+               b = endp;
        } else {
-               retval = -EINVAL;
-               goto out2;
-       }
-       if (!isspace(*b)) {
-               retval = -EINVAL;
-               goto out2;
+               return -EINVAL;
        }
+       if (!isspace(*b))
+               return -EINVAL;
        for (b++, count = 0; count < 3; count++, b++) {
                switch (*b) {
                case 'r':
@@ -454,8 +432,7 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
                        count = 3;
                        break;
                default:
-                       retval = -EINVAL;
-                       goto out2;
+                       return -EINVAL;
                }
        }
 
@@ -463,38 +440,39 @@ handle:
        retval = 0;
        switch (filetype) {
        case DEVCG_ALLOW:
-               if (!parent_has_perm(cgroup, &wh))
-                       retval = -EPERM;
-               else
-                       retval = dev_whitelist_add(devcgroup, &wh);
-               break;
+               if (!parent_has_perm(devcgroup, &wh))
+                       return -EPERM;
+               return dev_whitelist_add(devcgroup, &wh);
        case DEVCG_DENY:
                dev_whitelist_rm(devcgroup, &wh);
                break;
        default:
-               retval = -EINVAL;
-               goto out2;
+               return -EINVAL;
        }
+       return 0;
+}
 
-       if (retval == 0)
-               retval = nbytes;
-
-out2:
+static int devcgroup_access_write(struct cgroup *cgrp, struct cftype *cft,
+                                 const char *buffer)
+{
+       int retval;
+       if (!cgroup_lock_live_group(cgrp))
+               return -ENODEV;
+       retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp),
+                                        cft->private, buffer);
        cgroup_unlock();
-out1:
-       kfree(buffer);
        return retval;
 }
 
 static struct cftype dev_cgroup_files[] = {
        {
                .name = "allow",
-               .write  = devcgroup_access_write,
+               .write_string  = devcgroup_access_write,
                .private = DEVCG_ALLOW,
        },
        {
                .name = "deny",
-               .write = devcgroup_access_write,
+               .write_string = devcgroup_access_write,
                .private = DEVCG_DENY,
        },
        {
@@ -535,8 +513,8 @@ int devcgroup_inode_permission(struct inode *inode, int mask)
        if (!dev_cgroup)
                return 0;
 
-       spin_lock(&dev_cgroup->lock);
-       list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) {
                if (wh->type & DEV_ALL)
                        goto acc_check;
                if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode))
@@ -552,10 +530,10 @@ acc_check:
                        continue;
                if ((mask & MAY_READ) && !(wh->access & ACC_READ))
                        continue;
-               spin_unlock(&dev_cgroup->lock);
+               rcu_read_unlock();
                return 0;
        }
-       spin_unlock(&dev_cgroup->lock);
+       rcu_read_unlock();
 
        return -EPERM;
 }
@@ -570,7 +548,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
        if (!dev_cgroup)
                return 0;
 
-       spin_lock(&dev_cgroup->lock);
+       rcu_read_lock();
        list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
                if (wh->type & DEV_ALL)
                        goto acc_check;
@@ -585,9 +563,9 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
 acc_check:
                if (!(wh->access & ACC_MKNOD))
                        continue;
-               spin_unlock(&dev_cgroup->lock);
+               rcu_read_unlock();
                return 0;
        }
-       spin_unlock(&dev_cgroup->lock);
+       rcu_read_unlock();
        return -EPERM;
 }
index 59f23b5918b38c01028263798cebd1ca304b171d..ff7068727757639149501937043766d2199a8228 100644 (file)
@@ -429,11 +429,11 @@ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
        return security_ops->inode_follow_link(dentry, nd);
 }
 
-int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
+int security_inode_permission(struct inode *inode, int mask)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
-       return security_ops->inode_permission(inode, mask, nd);
+       return security_ops->inode_permission(inode, mask);
 }
 
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
@@ -442,6 +442,7 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
                return 0;
        return security_ops->inode_setattr(dentry, attr);
 }
+EXPORT_SYMBOL_GPL(security_inode_setattr);
 
 int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
 {
index 63f131fc42e4e2e2eaedbe5f89d52ea3fe5fe000..40d06c533f89fb574efd68507142fbe9b770d9f7 100644 (file)
@@ -25,7 +25,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/security.h>
@@ -1971,22 +1971,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
        return __vm_enough_memory(mm, pages, cap_sys_admin);
 }
 
-/**
- * task_tracer_task - return the task that is tracing the given task
- * @task:              task to consider
- *
- * Returns NULL if noone is tracing @task, or the &struct task_struct
- * pointer to its tracer.
- *
- * Must be called under rcu_read_lock().
- */
-static struct task_struct *task_tracer_task(struct task_struct *task)
-{
-       if (task->ptrace & PT_PTRACED)
-               return rcu_dereference(task->parent);
-       return NULL;
-}
-
 /* binprm security operations */
 
 static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -2238,7 +2222,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
                        u32 ptsid = 0;
 
                        rcu_read_lock();
-                       tracer = task_tracer_task(current);
+                       tracer = tracehook_tracer_task(current);
                        if (likely(tracer != NULL)) {
                                sec = tracer->security;
                                ptsid = sec->sid;
@@ -2640,12 +2624,11 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
        return dentry_has_perm(current, NULL, dentry, FILE__READ);
 }
 
-static int selinux_inode_permission(struct inode *inode, int mask,
-                                   struct nameidata *nd)
+static int selinux_inode_permission(struct inode *inode, int mask)
 {
        int rc;
 
-       rc = secondary_ops->inode_permission(inode, mask, nd);
+       rc = secondary_ops->inode_permission(inode, mask);
        if (rc)
                return rc;
 
@@ -5247,7 +5230,7 @@ static int selinux_setprocattr(struct task_struct *p,
                   Otherwise, leave SID unchanged and fail. */
                task_lock(p);
                rcu_read_lock();
-               tracer = task_tracer_task(p);
+               tracer = tracehook_tracer_task(p);
                if (tracer != NULL) {
                        struct task_security_struct *ptsec = tracer->security;
                        u32 ptsid = ptsec->sid;
@@ -5670,27 +5653,20 @@ static struct nf_hook_ops selinux_ipv6_ops[] = {
 static int __init selinux_nf_ip_init(void)
 {
        int err = 0;
-       u32 iter;
 
        if (!selinux_enabled)
                goto out;
 
        printk(KERN_DEBUG "SELinux:  Registering netfilter hooks\n");
 
-       for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
-               err = nf_register_hook(&selinux_ipv4_ops[iter]);
-               if (err)
-                       panic("SELinux: nf_register_hook for IPv4: error %d\n",
-                             err);
-       }
+       err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
+       if (err)
+               panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-       for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
-               err = nf_register_hook(&selinux_ipv6_ops[iter]);
-               if (err)
-                       panic("SELinux: nf_register_hook for IPv6: error %d\n",
-                             err);
-       }
+       err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
+       if (err)
+               panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
 #endif /* IPV6 */
 
 out:
@@ -5702,15 +5678,11 @@ __initcall(selinux_nf_ip_init);
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 static void selinux_nf_ip_exit(void)
 {
-       u32 iter;
-
        printk(KERN_DEBUG "SELinux:  Unregistering netfilter hooks\n");
 
-       for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
-               nf_unregister_hook(&selinux_ipv4_ops[iter]);
+       nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-       for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
-               nf_unregister_hook(&selinux_ipv6_ops[iter]);
+       nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
 #endif /* IPV6 */
 }
 #endif
index ee5a51cbc5ebdd537997978760093f11994a59cc..1b40e558f98329a718a76c7a4b4458380a63057e 100644 (file)
@@ -522,8 +522,7 @@ static int smack_inode_rename(struct inode *old_inode,
  *
  * Returns 0 if access is permitted, -EACCES otherwise
  */
-static int smack_inode_permission(struct inode *inode, int mask,
-                                 struct nameidata *nd)
+static int smack_inode_permission(struct inode *inode, int mask)
 {
        /*
         * No permission to check. Existence test. Yup, it's there.
index cb5ead3e202df5512317aeba7e5c281d993f8fae..c67773ad9298076e701ea161b5f7c9ce3560da1e 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/init.h>
 #include <linux/time.h>
+#include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <sound/core.h>
index 87e3aefeddc39bf73f2b16465b71f5dc95d16795..83e90057270ead89f272ffe34fd6c3515a2b8a28 100644 (file)
@@ -189,9 +189,7 @@ void snd_tea575x_init(struct snd_tea575x *tea)
        }
 
        memset(&tea->vd, 0, sizeof(tea->vd));
-       tea->vd.owner = tea->card->module;
        strcpy(tea->vd.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio");
-       tea->vd.type = VID_TYPE_TUNER;
        tea->vd.release = snd_tea575x_release;
        video_set_drvdata(&tea->vd, tea);
        tea->vd.fops = &tea->fops;
index dbe63db4bfd654cfb656aee997d873353374c02b..4d4b8ddc26bac1711e51b772212497cdfe0f2ddf 100644 (file)
@@ -325,6 +325,7 @@ static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
 static int __devinit snd_card_cs4232_pnp(int dev, struct snd_card_cs4236 *acard,
                                         struct pnp_dev *pdev)
 {
+       acard->wss = pdev;
        if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0)
                return -EBUSY;
        cport[dev] = -1;
index 41c047e665ec7d62c6f85c25dbf45ce1441e901f..0797ca441a372d719de70bad9c7df9b96db458f6 100644 (file)
@@ -68,7 +68,9 @@ MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)},"
 static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
 static char *id = SNDRV_DEFAULT_STR1;          /* ID for this card */
 //static int enable = SNDRV_DEFAULT_ENABLE1;   /* Enable this card */
+#ifdef CONFIG_PNP
 static int isapnp = 1;                 /* Enable ISA PnP detection */
+#endif
 static long port = SNDRV_DEFAULT_PORT1;        /* 0x530,0xe80,0xf40,0x604 */
 static long mpu_port = SNDRV_DEFAULT_PORT1;    /* 0x300,0x310,0x320,0x330 */
 static long fm_port = SNDRV_DEFAULT_PORT1;     /* 0x388 */
@@ -85,8 +87,10 @@ module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard.");
 //module_param(enable, bool, 0444);
 //MODULE_PARM_DESC(enable, "Enable opti9xx soundcard.");
+#ifdef CONFIG_PNP
 module_param(isapnp, bool, 0444);
 MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
+#endif
 module_param(port, long, 0444);
 MODULE_PARM_DESC(port, "WSS port # for opti9xx driver.");
 module_param(mpu_port, long, 0444);
@@ -688,7 +692,7 @@ static void snd_card_opti9xx_free(struct snd_card *card)
        if (chip) {
 #ifdef OPTi93X
                struct snd_cs4231 *codec = chip->codec;
-               if (codec->irq > 0) {
+               if (codec && codec->irq > 0) {
                        disable_irq(codec->irq);
                        free_irq(codec->irq, codec);
                }
index 33940139844bf3893ab5487e711a728682c1c096..d4fafb6eec6caec2286999a541221d715b1f81db 100644 (file)
@@ -35,47 +35,6 @@ config SOUND_AU1550_AC97
        tristate "Au1550/Au1200 AC97 Sound"
        depends on SOC_AU1550 || SOC_AU1200
 
-config SOUND_TRIDENT
-       tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"
-       depends on PCI
-       ---help---
-         Say Y or M if you have a PCI sound card utilizing the Trident
-         4DWave-DX/NX chipset or your mother board chipset has SiS 7018
-         or ALi 5451 built-in. The SiS 7018 PCI Audio Core is embedded
-         in SiS960 Super South Bridge and SiS540/630 Single Chipset.
-         The ALi 5451 PCI Audio Core is embedded in ALi M1535, M1535D,
-         M1535+ or M1535D+ South Bridge.
-
-         Use lspci -n to find out if your sound card or chipset uses
-         Trident 4DWave or SiS 7018. PCI ID 1023:2000 or 1023:2001 stands
-         for Trident 4Dwave. PCI ID 1039:7018 stands for SiS7018. PCI ID
-         10B9:5451 stands for ALi5451.
-
-         This driver supports S/PDIF in/out (record/playback) for ALi 5451
-         embedded in ALi M1535+ and M1535D+. Note that they aren't all
-         enabled by default; you can enable them by saying Y to "/proc file
-         system support" and "Sysctl support", and after the /proc file
-         system has been mounted, executing the command
-
-               command                 what is enabled
-
-         echo 0>/proc/ALi5451  pcm out is also set to S/PDIF out. (Default).
-
-         echo 1>/proc/ALi5451  use S/PDIF out to output pcm data.
-
-         echo 2>/proc/ALi5451  use S/PDIF out to output non-pcm data.
-         (AC3...).
-
-         echo 3>/proc/ALi5451  record from Ac97 in(MIC, Line in...).
-         (Default).
-
-         echo 4>/proc/ALi5451  no matter Ac97 settings, record from S/PDIF
-         in.
-
-
-         This driver differs slightly from OSS/Free, so PLEASE READ the
-         comments at the top of <file:sound/oss/trident.c>.
-
 config SOUND_MSNDCLAS
        tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
        depends on (m || !STANDALONE) && ISA
index 1f86299fae409a297154737002f4466782cc597f..c611514f7ff104ec3289d960d9108d5391fc91c9 100644 (file)
@@ -29,11 +29,8 @@ obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
 obj-$(CONFIG_SOUND_MSNDPIN)    += msnd.o msnd_pinnacle.o
 obj-$(CONFIG_SOUND_VWSND)      += vwsnd.o
 obj-$(CONFIG_SOUND_AU1550_AC97)        += au1550_ac97.o ac97_codec.o
-obj-$(CONFIG_SOUND_TRIDENT)    += trident.o ac97_codec.o
 obj-$(CONFIG_SOUND_BCM_CS4297A)        += swarm_cs4297a.o
 
-obj-$(CONFIG_SOUND_WM97XX)     += ac97_plugin_wm97xx.o
-
 obj-$(CONFIG_DMASOUND)         += dmasound/
 
 # Declare multi-part drivers.
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
deleted file mode 100644 (file)
index f43f91e..0000000
+++ /dev/null
@@ -1,4654 +0,0 @@
-/*
- *     OSS driver for Linux 2.[46].x for
- *
- *     Trident 4D-Wave
- *     SiS 7018
- *     ALi 5451
- *     Tvia/IGST CyberPro 5050
- *
- *     Driver: Alan Cox <alan@redhat.com>
- *
- *  Built from:
- *     Low level code: <audio@tridentmicro.com> from ALSA
- *     Framework: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *     Extended by: Zach Brown <zab@redhat.com>
- *
- *  Hacked up by:
- *     Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
- *     Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support
- *     Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support
- *     Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support
- *     Peter Wächtler <pwaechtler@loewe-komp.de> CyberPro5050 support
- *      Muli Ben-Yehuda <mulix@mulix.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.
- *
- *  History
- *  v0.14.10j
- *     January 3 2004 Eugene Teo <eugeneteo@eugeneteo.net>
- *     minor cleanup to use pr_debug instead of TRDBG since it is already
- *     defined in linux/kernel.h.
- *  v0.14.10i
- *      December 29 2003 Muli Ben-Yehuda <mulix@mulix.org>
- *      major cleanup for 2.6, fix a few error patch buglets
- *      with returning without properly cleaning up first,
- *      get rid of lock_kernel().
- *  v0.14.10h
- *     Sept 10 2002 Pascal Schmidt <der.eremit@email.de>
- *     added support for ALi 5451 joystick port
- *  v0.14.10g
- *     Sept 05 2002 Alan Cox <alan@redhat.com>
- *     adapt to new pci joystick attachment interface
- *  v0.14.10f
- *      July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      patch from Eric Lemar (via Ian Soboroff): in suspend and resume,
- *      fix wrong cast from pci_dev* to struct trident_card*.
- *  v0.14.10e
- *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      rewrite the DMA buffer allocation/deallcoation functions, to make it
- *      modular and fix a bug where we would call free_pages on memory
- *      obtained with pci_alloc_consistent. Also remove unnecessary #ifdef
- *      CONFIG_PROC_FS and various other cleanups.
- *  v0.14.10d
- *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming
- *      my syslog with hundreds of messages.
- *  v0.14.10c
- *      July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle
- *      and the coding style used in the rest of the file.
- *  v0.14.10b
- *      June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      add a missing unlock_set_fmt, remove a superflous lock/unlock pair
- *      with nothing in between.
- *  v0.14.10a
- *      June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns
- *      per line, use 'do {} while (0)' in statement macros.
- *  v0.14.10
- *      June 6 2002 Lei Hu <Lei_hu@ali.com.tw>
- *      rewrite the part to read/write registers of audio codec for Ali5451
- *  v0.14.9e
- *      January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport
- *      support to avoid resource conflict with pcigame.c
- *  v0.14.9d
- *     October 8 2001 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- *     use set_current_state, properly release resources on failure in
- *     trident_probe, get rid of check_region
- *  v0.14.9c
- *     August 10 2001 Peter Wächtler <pwaechtler@loewe-komp.de>
- *     added support for Tvia (formerly Integraphics/IGST) CyberPro5050
- *     this chip is often found in settop boxes (combined video+audio)
- *  v0.14.9b
- *     Switch to static inline not extern inline (gcc 3)
- *  v0.14.9a
- *     Aug 6 2001 Alan Cox
- *     0.14.9 crashed on rmmod due to a timer/bh left running. Simplified
- *     the existing logic (the BH doesn't help as ac97 is lock_irqsave)
- *     and used del_timer_sync to clean up
- *     Fixed a problem where the ALi change broke my generic card
- *  v0.14.9
- *     Jul 10 2001 Matt Wu
- *     Add H/W Volume Control
- *  v0.14.8a
- *     July 7 2001 Alan Cox
- *     Moved Matt Wu's ac97 register cache into the card structure
- *  v0.14.8
- *     Apr 30 2001 Matt Wu
- *     Set EBUF1 and EBUF2 to still mode
- *     Add dc97/ac97 reset function
- *     Fix power management: ali_restore_regs
- *  unreleased
- *     Mar 09 2001 Matt Wu
- *     Add cache for ac97 access
- *  v0.14.7
- *     Feb 06 2001 Matt Wu
- *     Fix ac97 initialization
- *     Fix bug: an extra tail will be played when playing
- *     Jan 05 2001 Matt Wu
- *     Implement multi-channels and S/PDIF in support for ALi 1535+
- *  v0.14.6
- *     Nov 1 2000 Ching-Ling Lee
- *     Fix the bug of memory leak when switching 5.1-channels to 2 channels.
- *     Add lock protection into dynamic changing format of data.
- *     Oct 18 2000 Ching-Ling Lee
- *     5.1-channels support for ALi
- *     June 28 2000 Ching-Ling Lee
- *     S/PDIF out/in(playback/record) support for ALi 1535+, using /proc to be selected by user
- *     Simple Power Management support for ALi
- *  v0.14.5 May 23 2000 Ollie Lho
- *     Misc bug fix from the Net
- *  v0.14.4 May 20 2000 Aaron Holtzman
- *     Fix kfree'd memory access in release
- *     Fix race in open while looking for a free virtual channel slot
- *     remove open_wait wq (which appears to be unused)
- *  v0.14.3 May 10 2000 Ollie Lho
- *     fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU
- *  v0.14.2 Mar 29 2000 Ching-Ling Lee
- *     Add clear to silence advance in trident_update_ptr
- *     fix invalid data of the end of the sound
- *  v0.14.1 Mar 24 2000 Ching-Ling Lee
- *     ALi 5451 support added, playback and recording O.K.
- *     ALi 5451 originally developed and structured based on sonicvibes, and
- *     suggested to merge into this file by Alan Cox.
- *  v0.14 Mar 15 2000 Ollie Lho
- *     5.1 channel output support with channel binding. What's the Matrix ?
- *  v0.13.1 Mar 10 2000 Ollie Lho
- *     few minor bugs on dual codec support, needs more testing
- *  v0.13 Mar 03 2000 Ollie Lho
- *     new pci_* for 2.4 kernel, back ported to 2.2
- *  v0.12 Feb 23 2000 Ollie Lho
- *     Preliminary Recording support
- *  v0.11.2 Feb 19 2000 Ollie Lho
- *     removed incomplete full-dulplex support
- *  v0.11.1 Jan 28 2000 Ollie Lho
- *     small bug in setting sample rate for 4d-nx (reported by Aaron)
- *  v0.11 Jan 27 2000 Ollie Lho
- *     DMA bug, scheduler latency, second try
- *  v0.10 Jan 24 2000 Ollie Lho
- *     DMA bug fixed, found kernel scheduling problem
- *  v0.09 Jan 20 2000 Ollie Lho
- *     Clean up of channel register access routine (prepare for channel binding)
- *  v0.08 Jan 14 2000 Ollie Lho
- *     Isolation of AC97 codec code
- *  v0.07 Jan 13 2000 Ollie Lho
- *     Get rid of ugly old low level access routines (e.g. CHRegs.lp****)
- *  v0.06 Jan 11 2000 Ollie Lho
- *     Preliminary support for dual (more ?) AC97 codecs
- *  v0.05 Jan 08 2000 Luca Montecchiani <m.luca@iname.com>
- *     adapt to 2.3.x new __setup/__init call
- *  v0.04 Dec 31 1999 Ollie Lho
- *     Multiple Open, using Middle Loop Interrupt to smooth playback
- *  v0.03 Dec 24 1999 Ollie Lho
- *     mem leak in prog_dmabuf and dealloc_dmabuf removed
- *  v0.02 Dec 15 1999 Ollie Lho
- *     SiS 7018 support added, playback O.K.
- *  v0.01 Alan Cox et. al.
- *     Initial Release in kernel 2.3.30, does not work
- *
- *  ToDo
- *     Clean up of low level channel register access code. (done)
- *     Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done)
- *     Dual AC97 codecs support (done)
- *     Recording support (done)
- *     Mmap support
- *     "Channel Binding" ioctl extension (done)
- *     new pci device driver interface for 2.4 kernel (done)
- *
- *     Lock order (high->low)
- *             lock    -       hardware lock
- *             open_mutex -    guard opens
- *             sem     -       guard dmabuf, write re-entry etc
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/spinlock.h>
-#include <linux/ac97_codec.h>
-#include <linux/bitops.h>
-#include <linux/proc_fs.h>
-#include <linux/interrupt.h>
-#include <linux/pm.h>
-#include <linux/gameport.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC)
-#include <asm/hwrpb.h>
-#endif
-
-#include "trident.h"
-
-#define DRIVER_VERSION "0.14.10j-2.6"
-
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-#define SUPPORT_JOYSTICK 1
-#endif
-
-/* magic numbers to protect our data structures */
-#define TRIDENT_CARD_MAGIC     0x5072696E      /* "Prin" */
-#define TRIDENT_STATE_MAGIC    0x63657373      /* "cess" */
-
-#define TRIDENT_DMA_MASK       0x3fffffff      /* DMA buffer mask for pci_alloc_consist */
-#define ALI_DMA_MASK           0x7fffffff      /* ALI Tridents have 31-bit DMA. Wow. */
-
-#define NR_HW_CH               32
-
-/* maximum number of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only
-   have 2 SDATA_IN lines (currently) */
-#define NR_AC97                2
-
-/* minor number of /dev/swmodem (temporary, experimental) */
-#define SND_DEV_SWMODEM        7
-
-static const unsigned ali_multi_channels_5_1[] = {
-       /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL, */
-       ALI_CENTER_CHANNEL,
-       ALI_LEF_CHANNEL,
-       ALI_SURR_LEFT_CHANNEL,
-       ALI_SURR_RIGHT_CHANNEL
-};
-
-static const unsigned sample_size[] = { 1, 2, 2, 4 };
-static const unsigned sample_shift[] = { 0, 1, 1, 2 };
-
-static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %s\n";
-
-enum {
-       TRIDENT_4D_DX = 0,
-       TRIDENT_4D_NX,
-       SIS_7018,
-       ALI_5451,
-       CYBER5050
-};
-
-static char *card_names[] = {
-       "Trident 4DWave DX",
-       "Trident 4DWave NX",
-       "SiS 7018 PCI Audio",
-       "ALi Audio Accelerator",
-       "Tvia/IGST CyberPro 5050"
-};
-
-static struct pci_device_id trident_pci_tbl[] = {
-       {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
-               PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TRIDENT_4D_DX},
-       {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
-               0, 0, TRIDENT_4D_NX},
-       {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, SIS_7018},
-       {PCI_DEVICE(PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451), 0, 0, ALI_5451},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050),
-               0, 0, CYBER5050},
-       {0,}
-};
-
-MODULE_DEVICE_TABLE(pci, trident_pci_tbl);
-
-/* "software" or virtual channel, an instance of opened /dev/dsp */
-struct trident_state {
-       unsigned int magic;
-       struct trident_card *card;      /* Card info */
-
-       /* file mode */
-       mode_t open_mode;
-
-       /* virtual channel number */
-       int virt;
-
-       struct dmabuf {
-               /* wave sample stuff */
-               unsigned int rate;
-               unsigned char fmt, enable;
-
-               /* hardware channel */
-               struct trident_channel *channel;
-
-               /* OSS buffer management stuff */
-               void *rawbuf;
-               dma_addr_t dma_handle;
-               unsigned buforder;
-               unsigned numfrag;
-               unsigned fragshift;
-
-               /* our buffer acts like a circular ring */
-               unsigned hwptr; /* where dma last started, updated by update_ptr */
-               unsigned swptr; /* where driver last clear/filled, updated by read/write */
-               int count;      /* bytes to be comsumed or been generated by dma machine */
-               unsigned total_bytes;   /* total bytes dmaed by hardware */
-
-               unsigned error; /* number of over/underruns */
-                /* put process on wait queue when no more space in buffer */
-               wait_queue_head_t wait;
-
-               /* redundant, but makes calculations easier */
-               unsigned fragsize;
-               unsigned dmasize;
-               unsigned fragsamples;
-
-               /* OSS stuff */
-               unsigned mapped:1;
-               unsigned ready:1;
-               unsigned endcleared:1;
-               unsigned update_flag;
-               unsigned ossfragshift;
-               int ossmaxfrags;
-               unsigned subdivision;
-
-       } dmabuf;
-
-       /* 5.1 channels */
-       struct trident_state *other_states[4];
-       int multi_channels_adjust_count;
-       unsigned chans_num;
-       unsigned long fmt_flag;
-       /* Guard against mmap/write/read races */
-       struct mutex sem;
-
-};
-
-/* hardware channels */
-struct trident_channel {
-       int num; /* channel number */
-       u32 lba; /* Loop Begine Address, where dma buffer starts */
-       u32 eso; /* End Sample Offset, wehre dma buffer ends */
-                /* (in the unit of samples) */
-       u32 delta; /* delta value, sample rate / 48k for playback, */
-                  /* 48k/sample rate for recording */
-       u16 attribute; /* control where PCM data go and come  */
-       u16 fm_vol;
-       u32 control; /* signed/unsigned, 8/16 bits, mono/stereo */
-};
-
-struct trident_pcm_bank_address {
-       u32 start;
-       u32 stop;
-       u32 aint;
-       u32 aint_en;
-};
-
-static struct trident_pcm_bank_address bank_a_addrs = {
-       T4D_START_A,
-       T4D_STOP_A,
-       T4D_AINT_A,
-       T4D_AINTEN_A
-};
-
-static struct trident_pcm_bank_address bank_b_addrs = {
-       T4D_START_B,
-       T4D_STOP_B,
-       T4D_AINT_B,
-       T4D_AINTEN_B
-};
-
-struct trident_pcm_bank {
-       /* register addresses to control bank operations */
-       struct trident_pcm_bank_address *addresses;
-       /* each bank has 32 channels */
-       u32 bitmap;             /* channel allocation bitmap */
-       struct trident_channel channels[32];
-};
-
-struct trident_card {
-       unsigned int magic;
-
-       /* We keep trident cards in a linked list */
-       struct trident_card *next;
-
-       /* single open lock mechanism, only used for recording */
-       struct mutex open_mutex;
-
-       /* The trident has a certain amount of cross channel interaction
-          so we use a single per card lock */
-       spinlock_t lock;
-
-       /* PCI device stuff */
-       struct pci_dev *pci_dev;
-       u16 pci_id;
-       u8 revision;
-
-       /* soundcore stuff */
-       int dev_audio;
-
-       /* structures for abstraction of hardware facilities, codecs, */
-       /* banks and channels */
-       struct ac97_codec *ac97_codec[NR_AC97];
-       struct trident_pcm_bank banks[NR_BANKS];
-       struct trident_state *states[NR_HW_CH];
-
-       /* hardware resources */
-       unsigned long iobase;
-       u32 irq;
-
-       /* Function support */
-       struct trident_channel *(*alloc_pcm_channel) (struct trident_card *);
-       struct trident_channel *(*alloc_rec_pcm_channel) (struct trident_card *);
-       void (*free_pcm_channel) (struct trident_card *, unsigned int chan);
-       void (*address_interrupt) (struct trident_card *);
-
-       /* Added by Matt Wu 01-05-2001 for spdif in */
-       int multi_channel_use_count;
-       int rec_channel_use_count;
-       u16 mixer_regs[64][NR_AC97];    /* Made card local by Alan */
-       int mixer_regs_ready;
-
-       /* Added for hardware volume control */
-       int hwvolctl;
-       struct timer_list timer;
-
-       /* Game port support */
-       struct gameport *gameport;
-};
-
-enum dmabuf_mode {
-       DM_PLAYBACK = 0,
-       DM_RECORD
-};
-
-/* table to map from CHANNELMASK to channel attribute for SiS 7018 */
-static u16 mask2attr[] = {
-       PCM_LR, PCM_LR, SURR_LR, CENTER_LFE,
-       HSET, MIC, MODEM_LINE1, MODEM_LINE2,
-       I2S_LR, SPDIF_LR
-};
-
-/* table to map from channel attribute to CHANNELMASK for SiS 7018 */
-static int attr2mask[] = {
-       DSP_BIND_MODEM1, DSP_BIND_MODEM2, DSP_BIND_FRONT, DSP_BIND_HANDSET,
-       DSP_BIND_I2S, DSP_BIND_CENTER_LFE, DSP_BIND_SURR, DSP_BIND_SPDIF
-};
-
-/* Added by Matt Wu 01-05-2001 for spdif in */
-static int ali_close_multi_channels(void);
-static void ali_delay(struct trident_card *card, int interval);
-static void ali_detect_spdif_rate(struct trident_card *card);
-
-static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val);
-static u16 ali_ac97_read(struct ac97_codec *codec, u8 reg);
-
-static struct trident_card *devs;
-
-static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val);
-static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg);
-
-static int trident_open_mixdev(struct inode *inode, struct file *file);
-static int trident_ioctl_mixdev(struct inode *inode, struct file *file,
-                               unsigned int cmd, unsigned long arg);
-
-static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val);
-static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg);
-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_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);
-static void ali_setup_spdif_in(struct trident_card *card);
-static void ali_disable_spdif_in(struct trident_card *card);
-static void ali_disable_special_channel(struct trident_card *card, int ch);
-static void ali_setup_spdif_out(struct trident_card *card, int flag);
-static int ali_write_5_1(struct trident_state *state,
-                        const char __user *buffer,
-                        int cnt_for_multi_channel, unsigned int *copy_count,
-                        unsigned int *state_cnt);
-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);
-
-#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count)  do { \
-        (dma_ptr) += (offset);   \
-       (buffer) += (offset);     \
-        (cnt) -= (offset);       \
-       (copy_count) += (offset); \
-} while (0)
-
-static inline int lock_set_fmt(struct trident_state* state)
-{
-       if (test_and_set_bit(0, &state->fmt_flag))
-               return -EFAULT;
-
-       return 0;
-}
-
-static inline void unlock_set_fmt(struct trident_state* state)
-{
-       clear_bit(0, &state->fmt_flag);
-}
-
-static int
-trident_enable_loop_interrupts(struct trident_card *card)
-{
-       u32 global_control;
-
-       global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR));
-
-       switch (card->pci_id) {
-       case PCI_DEVICE_ID_SI_7018:
-               global_control |= (ENDLP_IE | MIDLP_IE | BANK_B_EN);
-               break;
-       case PCI_DEVICE_ID_ALI_5451:
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
-       case PCI_DEVICE_ID_INTERG_5050:
-               global_control |= (ENDLP_IE | MIDLP_IE);
-               break;
-       default:
-               return 0;
-       }
-
-       outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));
-
-       pr_debug("trident: Enable Loop Interrupts, globctl = 0x%08X\n",
-                inl(TRID_REG(card, T4D_LFO_GC_CIR)));
-
-       return 1;
-}
-
-static int
-trident_disable_loop_interrupts(struct trident_card *card)
-{
-       u32 global_control;
-
-       global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR));
-       global_control &= ~(ENDLP_IE | MIDLP_IE);
-       outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));
-
-       pr_debug("trident: Disabled Loop Interrupts, globctl = 0x%08X\n",
-                global_control);
-
-       return 1;
-}
-
-static void
-trident_enable_voice_irq(struct trident_card *card, unsigned int channel)
-{
-       unsigned int mask = 1 << (channel & 0x1f);
-       struct trident_pcm_bank *bank = &card->banks[channel >> 5];
-       u32 reg, addr = bank->addresses->aint_en;
-
-       reg = inl(TRID_REG(card, addr));
-       reg |= mask;
-       outl(reg, TRID_REG(card, addr));
-
-#ifdef DEBUG
-       reg = inl(TRID_REG(card, addr));
-       pr_debug("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",
-                channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A",
-                reg, addr);
-#endif /* DEBUG */
-}
-
-static void
-trident_disable_voice_irq(struct trident_card *card, unsigned int channel)
-{
-       unsigned int mask = 1 << (channel & 0x1f);
-       struct trident_pcm_bank *bank = &card->banks[channel >> 5];
-       u32 reg, addr = bank->addresses->aint_en;
-
-       reg = inl(TRID_REG(card, addr));
-       reg &= ~mask;
-       outl(reg, TRID_REG(card, addr));
-
-       /* Ack the channel in case the interrupt was set before we disable it. */
-       outl(mask, TRID_REG(card, bank->addresses->aint));
-
-#ifdef DEBUG
-       reg = inl(TRID_REG(card, addr));
-       pr_debug("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",
-                channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A",
-                reg, addr);
-#endif /* DEBUG */
-}
-
-static void
-trident_start_voice(struct trident_card *card, unsigned int channel)
-{
-       unsigned int mask = 1 << (channel & 0x1f);
-       struct trident_pcm_bank *bank = &card->banks[channel >> 5];
-       u32 addr = bank->addresses->start;
-
-#ifdef DEBUG
-       u32 reg;
-#endif /* DEBUG */
-
-       outl(mask, TRID_REG(card, addr));
-
-#ifdef DEBUG
-       reg = inl(TRID_REG(card, addr));
-       pr_debug("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n",
-                channel, addr == T4D_START_B ? "START_B" : "START_A",
-                reg, addr);
-#endif /* DEBUG */
-}
-
-static void
-trident_stop_voice(struct trident_card *card, unsigned int channel)
-{
-       unsigned int mask = 1 << (channel & 0x1f);
-       struct trident_pcm_bank *bank = &card->banks[channel >> 5];
-       u32 addr = bank->addresses->stop;
-
-#ifdef DEBUG
-       u32 reg;
-#endif /* DEBUG */
-
-       outl(mask, TRID_REG(card, addr));
-
-#ifdef DEBUG
-       reg = inl(TRID_REG(card, addr));
-       pr_debug("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n",
-                channel, addr == T4D_STOP_B ? "STOP_B" : "STOP_A",
-                reg, addr);
-#endif /* DEBUG */
-}
-
-static u32
-trident_get_interrupt_mask(struct trident_card *card, unsigned int channel)
-{
-       struct trident_pcm_bank *bank = &card->banks[channel];
-       u32 addr = bank->addresses->aint;
-       return inl(TRID_REG(card, addr));
-}
-
-static int
-trident_check_channel_interrupt(struct trident_card *card, unsigned int channel)
-{
-       unsigned int mask = 1 << (channel & 0x1f);
-       u32 reg = trident_get_interrupt_mask(card, channel >> 5);
-
-#ifdef DEBUG
-       if (reg & mask)
-               pr_debug("trident: channel %d has interrupt, %s = 0x%08x\n",
-                        channel, reg == T4D_AINT_B ? "AINT_B" : "AINT_A",
-                        reg);
-#endif /* DEBUG */
-       return (reg & mask) ? 1 : 0;
-}
-
-static void
-trident_ack_channel_interrupt(struct trident_card *card, unsigned int channel)
-{
-       unsigned int mask = 1 << (channel & 0x1f);
-       struct trident_pcm_bank *bank = &card->banks[channel >> 5];
-       u32 reg, addr = bank->addresses->aint;
-
-       reg = inl(TRID_REG(card, addr));
-       reg &= mask;
-       outl(reg, TRID_REG(card, addr));
-
-#ifdef DEBUG
-       reg = inl(TRID_REG(card, T4D_AINT_B));
-       pr_debug("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n",
-                channel, reg);
-#endif /* DEBUG */
-}
-
-static struct trident_channel *
-trident_alloc_pcm_channel(struct trident_card *card)
-{
-       struct trident_pcm_bank *bank;
-       int idx;
-
-       bank = &card->banks[BANK_B];
-
-       for (idx = 31; idx >= 0; idx--) {
-               if (!(bank->bitmap & (1 << idx))) {
-                       struct trident_channel *channel = &bank->channels[idx];
-                       bank->bitmap |= 1 << idx;
-                       channel->num = idx + 32;
-                       return channel;
-               }
-       }
-
-       /* no more free channels available */
-       printk(KERN_ERR "trident: no more channels available on Bank B.\n");
-       return NULL;
-}
-
-static void
-trident_free_pcm_channel(struct trident_card *card, unsigned int channel)
-{
-       int bank;
-       unsigned char b;
-
-       if (channel < 31 || channel > 63)
-               return;
-
-       if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX ||
-           card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) {
-               b = inb(TRID_REG(card, T4D_REC_CH));
-               if ((b & ~0x80) == channel)
-                       outb(0x0, TRID_REG(card, T4D_REC_CH));
-       }
-
-       bank = channel >> 5;
-       channel = channel & 0x1f;
-
-       card->banks[bank].bitmap &= ~(1 << (channel));
-}
-
-static struct trident_channel *
-cyber_alloc_pcm_channel(struct trident_card *card)
-{
-       struct trident_pcm_bank *bank;
-       int idx;
-
-       /* The cyberpro 5050 has only 32 voices and one bank */
-       /* .. at least they are not documented (if you want to call that
-        * crap documentation), perhaps broken ? */
-
-       bank = &card->banks[BANK_A];
-
-       for (idx = 31; idx >= 0; idx--) {
-               if (!(bank->bitmap & (1 << idx))) {
-                       struct trident_channel *channel = &bank->channels[idx];
-                       bank->bitmap |= 1 << idx;
-                       channel->num = idx;
-                       return channel;
-               }
-       }
-
-       /* no more free channels available */
-       printk(KERN_ERR "cyberpro5050: no more channels available on Bank A.\n");
-       return NULL;
-}
-
-static void
-cyber_free_pcm_channel(struct trident_card *card, unsigned int channel)
-{
-       if (channel > 31)
-               return;
-       card->banks[BANK_A].bitmap &= ~(1 << (channel));
-}
-
-static inline void
-cyber_outidx(int port, int idx, int data)
-{
-       outb(idx, port);
-       outb(data, port + 1);
-}
-
-static inline int
-cyber_inidx(int port, int idx)
-{
-       outb(idx, port);
-       return inb(port + 1);
-}
-
-static int
-cyber_init_ritual(struct trident_card *card)
-{
-       /* some black magic, taken from SDK samples */
-       /* remove this and nothing will work */
-       int portDat;
-       int ret = 0;
-       unsigned long flags;
-
-       /*
-        *      Keep interrupts off for the configure - we don't want to
-        *      clash with another cyberpro config event
-        */
-
-       spin_lock_irqsave(&card->lock, flags);
-       portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);
-       /* enable, if it was disabled */
-       if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) {
-               printk(KERN_INFO "cyberpro5050: enabling audio controller\n");
-               cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE,
-                            portDat | CYBER_BMSK_AUENZ_ENABLE);
-               /* check again if hardware is enabled now */
-               portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);
-       }
-       if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) {
-               printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n");
-               ret = -1;
-       } else {
-               cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE,
-                            CYBER_BMSK_AUDIO_INT_ENABLE);
-               cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x01);
-               cyber_outidx(CYBER_PORT_AUDIO, 0xba, 0x20);
-               cyber_outidx(CYBER_PORT_AUDIO, 0xbb, 0x08);
-               cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x02);
-               cyber_outidx(CYBER_PORT_AUDIO, 0xb3, 0x06);
-               cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x00);
-       }
-       spin_unlock_irqrestore(&card->lock, flags);
-       return ret;
-}
-
-/*  called with spin lock held */
-
-static int
-trident_load_channel_registers(struct trident_card *card, u32 * data,
-                              unsigned int channel)
-{
-       int i;
-
-       if (channel > 63)
-               return 0;
-
-       /* select hardware channel to write */
-       outb(channel, TRID_REG(card, T4D_LFO_GC_CIR));
-
-       /* Output the channel registers, but don't write register
-          three to an ALI chip. */
-       for (i = 0; i < CHANNEL_REGS; i++) {
-               if (i == 3 && card->pci_id == PCI_DEVICE_ID_ALI_5451)
-                       continue;
-               outl(data[i], TRID_REG(card, CHANNEL_START + 4 * i));
-       }
-       if (card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
-           card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
-               outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1));
-               outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2));
-       }
-       return 1;
-}
-
-/* called with spin lock held */
-static int
-trident_write_voice_regs(struct trident_state *state)
-{
-       unsigned int data[CHANNEL_REGS + 1];
-       struct trident_channel *channel;
-
-       channel = state->dmabuf.channel;
-
-       data[1] = channel->lba;
-       data[4] = channel->control;
-
-       switch (state->card->pci_id) {
-       case PCI_DEVICE_ID_ALI_5451:
-               data[0] = 0;    /* Current Sample Offset */
-               data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
-               data[3] = 0;
-               break;
-       case PCI_DEVICE_ID_SI_7018:
-       case PCI_DEVICE_ID_INTERG_5050:
-               data[0] = 0;    /* Current Sample Offset */
-               data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
-               data[3] = (channel->attribute << 16) | (channel->fm_vol & 0xffff);
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
-               data[0] = 0;    /* Current Sample Offset */
-               data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
-               data[3] = channel->fm_vol & 0xffff;
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
-               data[0] = (channel->delta << 24);
-               data[2] = ((channel->delta << 16) & 0xff000000) |
-                       (channel->eso & 0x00ffffff);
-               data[3] = channel->fm_vol & 0xffff;
-               break;
-       default:
-               return 0;
-       }
-
-       return trident_load_channel_registers(state->card, data, channel->num);
-}
-
-static int
-compute_rate_play(u32 rate)
-{
-       int delta;
-       /* We special case 44100 and 8000 since rounding with the equation
-          does not give us an accurate enough value. For 11025 and 22050
-          the equation gives us the best answer. All other frequencies will
-          also use the equation. JDW */
-       if (rate == 44100)
-               delta = 0xeb3;
-       else if (rate == 8000)
-               delta = 0x2ab;
-       else if (rate == 48000)
-               delta = 0x1000;
-       else
-               delta = (((rate << 12) + rate) / 48000) & 0x0000ffff;
-       return delta;
-}
-
-static int
-compute_rate_rec(u32 rate)
-{
-       int delta;
-
-       if (rate == 44100)
-               delta = 0x116a;
-       else if (rate == 8000)
-               delta = 0x6000;
-       else if (rate == 48000)
-               delta = 0x1000;
-       else
-               delta = ((48000 << 12) / rate) & 0x0000ffff;
-
-       return delta;
-}
-
-/* set playback sample rate */
-static unsigned int
-trident_set_dac_rate(struct trident_state *state, unsigned int rate)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-
-       if (rate > 48000)
-               rate = 48000;
-       if (rate < 4000)
-               rate = 4000;
-
-       dmabuf->rate = rate;
-       dmabuf->channel->delta = compute_rate_play(rate);
-
-       trident_write_voice_regs(state);
-
-       pr_debug("trident: called trident_set_dac_rate : rate = %d\n", rate);
-
-       return rate;
-}
-
-/* set recording sample rate */
-static unsigned int
-trident_set_adc_rate(struct trident_state *state, unsigned int rate)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-
-       if (rate > 48000)
-               rate = 48000;
-       if (rate < 4000)
-               rate = 4000;
-
-       dmabuf->rate = rate;
-       dmabuf->channel->delta = compute_rate_rec(rate);
-
-       trident_write_voice_regs(state);
-
-       pr_debug("trident: called trident_set_adc_rate : rate = %d\n", rate);
-
-       return rate;
-}
-
-/* prepare channel attributes for playback */
-static void
-trident_play_setup(struct trident_state *state)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       struct trident_channel *channel = dmabuf->channel;
-
-       channel->lba = dmabuf->dma_handle;
-       channel->delta = compute_rate_play(dmabuf->rate);
-
-       channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt];
-       channel->eso -= 1;
-
-       if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) {
-               channel->attribute = 0;
-               if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-                       if ((channel->num == ALI_SPDIF_IN_CHANNEL) ||
-                           (channel->num == ALI_PCM_IN_CHANNEL))
-                               ali_disable_special_channel(state->card, channel->num);
-                       else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL))
-                                 & ALI_SPDIF_OUT_CH_ENABLE)
-                                && (channel->num == ALI_SPDIF_OUT_CHANNEL)) {
-                               ali_set_spdif_out_rate(state->card,
-                                                      state->dmabuf.rate);
-                               state->dmabuf.channel->delta = 0x1000;
-                       }
-               }
-       }
-
-       channel->fm_vol = 0x0;
-
-       channel->control = CHANNEL_LOOP;
-       if (dmabuf->fmt & TRIDENT_FMT_16BIT) {
-               /* 16-bits */
-               channel->control |= CHANNEL_16BITS;
-               /* signed */
-               channel->control |= CHANNEL_SIGNED;
-       }
-       if (dmabuf->fmt & TRIDENT_FMT_STEREO)
-               /* stereo */
-               channel->control |= CHANNEL_STEREO;
-
-       pr_debug("trident: trident_play_setup, LBA = 0x%08x, Delta = 0x%08x, "
-                "ESO = 0x%08x, Control = 0x%08x\n", channel->lba,
-                channel->delta, channel->eso, channel->control);
-
-       trident_write_voice_regs(state);
-}
-
-/* prepare channel attributes for recording */
-static void
-trident_rec_setup(struct trident_state *state)
-{
-       u16 w;
-       u8 bval;
-
-       struct trident_card *card = state->card;
-       struct dmabuf *dmabuf = &state->dmabuf;
-       struct trident_channel *channel = dmabuf->channel;
-       unsigned int rate;
-
-       /* Enable AC-97 ADC (capture) */
-       switch (card->pci_id) {
-       case PCI_DEVICE_ID_ALI_5451:
-               ali_enable_special_channel(state);
-               break;
-       case PCI_DEVICE_ID_SI_7018:
-               /* for 7018, the ac97 is always in playback/record (duplex) mode */
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
-               w = inb(TRID_REG(card, DX_ACR2_AC97_COM_STAT));
-               outb(w | 0x48, TRID_REG(card, DX_ACR2_AC97_COM_STAT));
-               /* enable and set record channel */
-               outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH));
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
-               w = inw(TRID_REG(card, T4D_MISCINT));
-               outw(w | 0x1000, TRID_REG(card, T4D_MISCINT));
-               /* enable and set record channel */
-               outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH));
-               break;
-       case PCI_DEVICE_ID_INTERG_5050:
-               /* don't know yet, using special channel 22 in GC1(0xd4)? */
-               break;
-       default:
-               return;
-       }
-
-       channel->lba = dmabuf->dma_handle;
-       channel->delta = compute_rate_rec(dmabuf->rate);
-       if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) &&
-           (channel->num == ALI_SPDIF_IN_CHANNEL)) {
-               rate = ali_get_spdif_in_rate(card);
-               if (rate == 0) {
-                       printk(KERN_WARNING "trident: ALi 5451 "
-                              "S/PDIF input setup error!\n");
-                       rate = 48000;
-               }
-               bval = inb(TRID_REG(card, ALI_SPDIF_CTRL));
-               if (bval & 0x10) {
-                       outb(bval, TRID_REG(card, ALI_SPDIF_CTRL));
-                       printk(KERN_WARNING "trident: cleared ALi "
-                              "5451 S/PDIF parity error flag.\n");
-               }
-
-               if (rate != 48000)
-                       channel->delta = ((rate << 12) / dmabuf->rate) & 0x0000ffff;
-       }
-
-       channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt];
-       channel->eso -= 1;
-
-       if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) {
-               channel->attribute = 0;
-       }
-
-       channel->fm_vol = 0x0;
-
-       channel->control = CHANNEL_LOOP;
-       if (dmabuf->fmt & TRIDENT_FMT_16BIT) {
-               /* 16-bits */
-               channel->control |= CHANNEL_16BITS;
-               /* signed */
-               channel->control |= CHANNEL_SIGNED;
-       }
-       if (dmabuf->fmt & TRIDENT_FMT_STEREO)
-               /* stereo */
-               channel->control |= CHANNEL_STEREO;
-
-       pr_debug("trident: trident_rec_setup, LBA = 0x%08x, Delat = 0x%08x, "
-                "ESO = 0x%08x, Control = 0x%08x\n", channel->lba,
-                channel->delta, channel->eso, channel->control);
-
-       trident_write_voice_regs(state);
-}
-
-/* get current playback/recording dma buffer pointer (byte offset from LBA),
-   called with spinlock held! */
-static inline unsigned
-trident_get_dma_addr(struct trident_state *state)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       u32 cso;
-
-       if (!dmabuf->enable)
-               return 0;
-
-       outb(dmabuf->channel->num, TRID_REG(state->card, T4D_LFO_GC_CIR));
-
-       switch (state->card->pci_id) {
-       case PCI_DEVICE_ID_ALI_5451:
-       case PCI_DEVICE_ID_SI_7018:
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
-       case PCI_DEVICE_ID_INTERG_5050:
-               /* 16 bits ESO, CSO for 7018 and DX */
-               cso = inw(TRID_REG(state->card, CH_DX_CSO_ALPHA_FMS + 2));
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
-               /* 24 bits ESO, CSO for NX */
-               cso = inl(TRID_REG(state->card, CH_NX_DELTA_CSO)) & 0x00ffffff;
-               break;
-       default:
-               return 0;
-       }
-
-       pr_debug("trident: trident_get_dma_addr: chip reported channel: %d, "
-                "cso = 0x%04x\n", dmabuf->channel->num, cso);
-
-       /* ESO and CSO are in units of Samples, convert to byte offset */
-       cso <<= sample_shift[dmabuf->fmt];
-
-       return (cso % dmabuf->dmasize);
-}
-
-/* Stop recording (lock held) */
-static inline void
-__stop_adc(struct trident_state *state)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned int chan_num = dmabuf->channel->num;
-       struct trident_card *card = state->card;
-
-       dmabuf->enable &= ~ADC_RUNNING;
-       trident_stop_voice(card, chan_num);
-       trident_disable_voice_irq(card, chan_num);
-}
-
-static void
-stop_adc(struct trident_state *state)
-{
-       struct trident_card *card = state->card;
-       unsigned long flags;
-
-       spin_lock_irqsave(&card->lock, flags);
-       __stop_adc(state);
-       spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static void
-start_adc(struct trident_state *state)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned int chan_num = dmabuf->channel->num;
-       struct trident_card *card = state->card;
-       unsigned long flags;
-
-       spin_lock_irqsave(&card->lock, flags);
-       if ((dmabuf->mapped ||
-            dmabuf->count < (signed) dmabuf->dmasize) &&
-           dmabuf->ready) {
-               dmabuf->enable |= ADC_RUNNING;
-               trident_enable_voice_irq(card, chan_num);
-               trident_start_voice(card, chan_num);
-       }
-       spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/* stop playback (lock held) */
-static inline void
-__stop_dac(struct trident_state *state)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned int chan_num = dmabuf->channel->num;
-       struct trident_card *card = state->card;
-
-       dmabuf->enable &= ~DAC_RUNNING;
-       trident_stop_voice(card, chan_num);
-       if (state->chans_num == 6) {
-               trident_stop_voice(card, state->other_states[0]->
-                                  dmabuf.channel->num);
-               trident_stop_voice(card, state->other_states[1]->
-                                  dmabuf.channel->num);
-               trident_stop_voice(card, state->other_states[2]->
-                                  dmabuf.channel->num);
-               trident_stop_voice(card, state->other_states[3]->
-                                  dmabuf.channel->num);
-       }
-       trident_disable_voice_irq(card, chan_num);
-}
-
-static void
-stop_dac(struct trident_state *state)
-{
-       struct trident_card *card = state->card;
-       unsigned long flags;
-
-       spin_lock_irqsave(&card->lock, flags);
-       __stop_dac(state);
-       spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static void
-start_dac(struct trident_state *state)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned int chan_num = dmabuf->channel->num;
-       struct trident_card *card = state->card;
-       unsigned long flags;
-
-       spin_lock_irqsave(&card->lock, flags);
-       if ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) {
-               dmabuf->enable |= DAC_RUNNING;
-               trident_enable_voice_irq(card, chan_num);
-               trident_start_voice(card, chan_num);
-               if (state->chans_num == 6) {
-                       trident_start_voice(card, state->other_states[0]->
-                                           dmabuf.channel->num);
-                       trident_start_voice(card, state->other_states[1]->
-                                           dmabuf.channel->num);
-                       trident_start_voice(card, state->other_states[2]->
-                                           dmabuf.channel->num);
-                       trident_start_voice(card, state->other_states[3]->
-                                           dmabuf.channel->num);
-               }
-       }
-       spin_unlock_irqrestore(&card->lock, flags);
-}
-
-#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
-#define DMABUF_MINORDER 1
-
-/* alloc a DMA buffer of with a buffer of this order */
-static int
-alloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev, int order)
-{
-       void *rawbuf = NULL;
-       struct page *page, *pend;
-
-       if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,
-                                           &dmabuf->dma_handle)))
-               return -ENOMEM;
-
-       pr_debug("trident: allocated %ld (order = %d) bytes at %p\n",
-                PAGE_SIZE << order, order, rawbuf);
-
-       dmabuf->ready = dmabuf->mapped = 0;
-       dmabuf->rawbuf = rawbuf;
-       dmabuf->buforder = order;
-
-       /* now mark the pages as reserved; otherwise */
-       /* remap_pfn_range doesn't do what we want */
-       pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
-       for (page = virt_to_page(rawbuf); page <= pend; page++)
-               SetPageReserved(page);
-
-       return 0;
-}
-
-/* allocate the main DMA buffer, playback and recording buffer should be */
-/* allocated separately */
-static int
-alloc_main_dmabuf(struct trident_state *state)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       int order;
-       int ret = -ENOMEM;
-
-       /* alloc as big a chunk as we can, FIXME: is this necessary ?? */
-       for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) {
-               if (!(ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order)))
-                       return 0;
-               /* else try again */
-       }
-       return ret;
-}
-
-/* deallocate a DMA buffer */
-static void
-dealloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev)
-{
-       struct page *page, *pend;
-
-       if (dmabuf->rawbuf) {
-               /* undo marking the pages as reserved */
-               pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
-               for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
-                       ClearPageReserved(page);
-               pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder,
-                                   dmabuf->rawbuf, dmabuf->dma_handle);
-               dmabuf->rawbuf = NULL;
-       }
-       dmabuf->mapped = dmabuf->ready = 0;
-}
-
-static int
-prog_dmabuf(struct trident_state *state, enum dmabuf_mode rec)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned bytepersec;
-       struct trident_state *s = state;
-       unsigned bufsize, dma_nums;
-       unsigned long flags;
-       int ret, i, order;
-
-       if ((ret = lock_set_fmt(state)) < 0)
-               return ret;
-
-       if (state->chans_num == 6)
-               dma_nums = 5;
-       else
-               dma_nums = 1;
-
-       for (i = 0; i < dma_nums; i++) {
-               if (i > 0) {
-                       s = state->other_states[i - 1];
-                       dmabuf = &s->dmabuf;
-                       dmabuf->fmt = state->dmabuf.fmt;
-                       dmabuf->rate = state->dmabuf.rate;
-               }
-
-               spin_lock_irqsave(&s->card->lock, flags);
-               dmabuf->hwptr = dmabuf->swptr = dmabuf->total_bytes = 0;
-               dmabuf->count = dmabuf->error = 0;
-               spin_unlock_irqrestore(&s->card->lock, flags);
-
-               /* allocate DMA buffer if not allocated yet */
-               if (!dmabuf->rawbuf) {
-                       if (i == 0) {
-                               if ((ret = alloc_main_dmabuf(state))) {
-                                       unlock_set_fmt(state);
-                                       return ret;
-                               }
-                       } else {
-                               ret = -ENOMEM;
-                               order = state->dmabuf.buforder - 1;
-                               if (order >= DMABUF_MINORDER) {
-                                       ret = alloc_dmabuf(dmabuf,
-                                                          state->card->pci_dev,
-                                                          order);
-                               }
-                               if (ret) {
-                                       /* release the main DMA buffer */
-                                       dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
-                                       /* release the auxiliary DMA buffers */
-                                       for (i -= 2; i >= 0; i--)
-                                               dealloc_dmabuf(&state->other_states[i]->dmabuf,
-                                                              state->card->pci_dev);
-                                       unlock_set_fmt(state);
-                                       return ret;
-                               }
-                       }
-               }
-               /* FIXME: figure out all this OSS fragment stuff */
-               bytepersec = dmabuf->rate << sample_shift[dmabuf->fmt];
-               bufsize = PAGE_SIZE << dmabuf->buforder;
-               if (dmabuf->ossfragshift) {
-                       if ((1000 << dmabuf->ossfragshift) < bytepersec)
-                               dmabuf->fragshift = ld2(bytepersec / 1000);
-                       else
-                               dmabuf->fragshift = dmabuf->ossfragshift;
-               } else {
-                       /* lets hand out reasonable big ass buffers by default */
-                       dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT - 2);
-               }
-               dmabuf->numfrag = bufsize >> dmabuf->fragshift;
-               while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) {
-                       dmabuf->fragshift--;
-                       dmabuf->numfrag = bufsize >> dmabuf->fragshift;
-               }
-               dmabuf->fragsize = 1 << dmabuf->fragshift;
-               if (dmabuf->ossmaxfrags >= 4 && dmabuf->ossmaxfrags < dmabuf->numfrag)
-                       dmabuf->numfrag = dmabuf->ossmaxfrags;
-               dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt];
-               dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
-
-               memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80,
-                      dmabuf->dmasize);
-
-               spin_lock_irqsave(&s->card->lock, flags);
-               if (rec == DM_RECORD)
-                       trident_rec_setup(s);
-               else /* DM_PLAYBACK */
-                       trident_play_setup(s);
-
-               spin_unlock_irqrestore(&s->card->lock, flags);
-
-               /* set the ready flag for the dma buffer */
-               dmabuf->ready = 1;
-
-               pr_debug("trident: prog_dmabuf(%d), sample rate = %d, "
-                        "format = %d, numfrag = %d, fragsize = %d "
-                        "dmasize = %d\n", dmabuf->channel->num,
-                        dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
-                        dmabuf->fragsize, dmabuf->dmasize);
-       }
-       unlock_set_fmt(state);
-       return 0;
-}
-
-
-static inline int prog_dmabuf_record(struct trident_state* state)
-{
-       return prog_dmabuf(state, DM_RECORD);
-}
-
-static inline int prog_dmabuf_playback(struct trident_state* state)
-{
-       return prog_dmabuf(state, DM_PLAYBACK);
-}
-
-/* we are doing quantum mechanics here, the buffer can only be empty, half or full filled i.e.
-   |------------|------------|   or   |xxxxxxxxxxxx|------------|   or   |xxxxxxxxxxxx|xxxxxxxxxxxx|
-   but we almost always get this
-   |xxxxxx------|------------|   or   |xxxxxxxxxxxx|xxxxx-------|
-   so we have to clear the tail space to "silence"
-   |xxxxxx000000|------------|   or   |xxxxxxxxxxxx|xxxxxx000000|
-*/
-static void
-trident_clear_tail(struct trident_state *state)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned swptr;
-       unsigned char silence = (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80;
-       unsigned int len;
-       unsigned long flags;
-
-       spin_lock_irqsave(&state->card->lock, flags);
-       swptr = dmabuf->swptr;
-       spin_unlock_irqrestore(&state->card->lock, flags);
-
-       if (swptr == 0 || swptr == dmabuf->dmasize / 2 ||
-           swptr == dmabuf->dmasize)
-               return;
-
-       if (swptr < dmabuf->dmasize / 2)
-               len = dmabuf->dmasize / 2 - swptr;
-       else
-               len = dmabuf->dmasize - swptr;
-
-       memset(dmabuf->rawbuf + swptr, silence, len);
-       if (state->card->pci_id != PCI_DEVICE_ID_ALI_5451) {
-               spin_lock_irqsave(&state->card->lock, flags);
-               dmabuf->swptr += len;
-               dmabuf->count += len;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-       }
-
-       /* restart the dma machine in case it is halted */
-       start_dac(state);
-}
-
-static int
-drain_dac(struct trident_state *state, int nonblock)
-{
-       DECLARE_WAITQUEUE(wait, current);
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned long flags;
-       unsigned long tmo;
-       int count;
-       unsigned long diff = 0;
-
-       if (dmabuf->mapped || !dmabuf->ready)
-               return 0;
-
-       add_wait_queue(&dmabuf->wait, &wait);
-       for (;;) {
-               /* It seems that we have to set the current state to TASK_INTERRUPTIBLE
-                  every time to make the process really go to sleep */
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               spin_lock_irqsave(&state->card->lock, flags);
-               count = dmabuf->count;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-
-               if (count <= 0)
-                       break;
-
-               if (signal_pending(current))
-                       break;
-
-               if (nonblock) {
-                       remove_wait_queue(&dmabuf->wait, &wait);
-                       set_current_state(TASK_RUNNING);
-                       return -EBUSY;
-               }
-
-               /* No matter how much data is left in the buffer, we have to wait until
-                  CSO == ESO/2 or CSO == ESO when address engine interrupts */
-               if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
-                   state->card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
-                       diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize;
-                       diff = diff % (dmabuf->dmasize);
-                       tmo = (diff * HZ) / dmabuf->rate;
-               } else {
-                       tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
-               }
-               tmo >>= sample_shift[dmabuf->fmt];
-               if (!schedule_timeout(tmo ? tmo : 1) && tmo) {
-                       break;
-               }
-       }
-       remove_wait_queue(&dmabuf->wait, &wait);
-       set_current_state(TASK_RUNNING);
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       return 0;
-}
-
-/* update buffer manangement pointers, especially, */
-/* dmabuf->count and dmabuf->hwptr */
-static void
-trident_update_ptr(struct trident_state *state)
-{
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned hwptr, swptr;
-       int clear_cnt = 0;
-       int diff;
-       unsigned char silence;
-       unsigned half_dmasize;
-
-       /* update hardware pointer */
-       hwptr = trident_get_dma_addr(state);
-       diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-       dmabuf->hwptr = hwptr;
-       dmabuf->total_bytes += diff;
-
-       /* error handling and process wake up for ADC */
-       if (dmabuf->enable == ADC_RUNNING) {
-               if (dmabuf->mapped) {
-                       dmabuf->count -= diff;
-                       if (dmabuf->count >= (signed) dmabuf->fragsize)
-                               wake_up(&dmabuf->wait);
-               } else {
-                       dmabuf->count += diff;
-
-                       if (dmabuf->count < 0 ||
-                           dmabuf->count > dmabuf->dmasize) {
-                               /* buffer underrun or buffer overrun, */
-                               /* we have no way to recover it here, just */
-                               /* stop the machine and let the process */
-                               /* force hwptr and swptr to sync */
-                               __stop_adc(state);
-                               dmabuf->error++;
-                       }
-                       if (dmabuf->count < (signed) dmabuf->dmasize / 2)
-                               wake_up(&dmabuf->wait);
-               }
-       }
-
-       /* error handling and process wake up for DAC */
-       if (dmabuf->enable == DAC_RUNNING) {
-               if (dmabuf->mapped) {
-                       dmabuf->count += diff;
-                       if (dmabuf->count >= (signed) dmabuf->fragsize)
-                               wake_up(&dmabuf->wait);
-               } else {
-                       dmabuf->count -= diff;
-
-                       if (dmabuf->count < 0 ||
-                           dmabuf->count > dmabuf->dmasize) {
-                               /* buffer underrun or buffer overrun, we have no way to recover
-                                  it here, just stop the machine and let the process force hwptr
-                                  and swptr to sync */
-                               __stop_dac(state);
-                               dmabuf->error++;
-                       } else if (!dmabuf->endcleared) {
-                               swptr = dmabuf->swptr;
-                               silence = (dmabuf->fmt & TRIDENT_FMT_16BIT ? 0 : 0x80);
-                               if (dmabuf->update_flag & ALI_ADDRESS_INT_UPDATE) {
-                                       /* We must clear end data of 1/2 dmabuf if needed.
-                                          According to 1/2 algorithm of Address Engine Interrupt,
-                                          check the validation of the data of half dmasize. */
-                                       half_dmasize = dmabuf->dmasize / 2;
-                                       if ((diff = hwptr - half_dmasize) < 0)
-                                               diff = hwptr;
-                                       if ((dmabuf->count + diff) < half_dmasize) {
-                                               //there is invalid data in the end of half buffer
-                                               if ((clear_cnt = half_dmasize - swptr) < 0)
-                                                       clear_cnt += half_dmasize;
-                                               //clear the invalid data
-                                               memset(dmabuf->rawbuf + swptr, silence, clear_cnt);
-                                               if (state->chans_num == 6) {
-                                                       clear_cnt = clear_cnt / 2;
-                                                       swptr = swptr / 2;
-                                                       memset(state->other_states[0]->dmabuf.rawbuf + swptr,
-                                                              silence, clear_cnt);
-                                                       memset(state->other_states[1]->dmabuf.rawbuf + swptr,
-                                                              silence, clear_cnt);
-                                                       memset(state->other_states[2]->dmabuf.rawbuf + swptr,
-                                                              silence, clear_cnt);
-                                                       memset(state->other_states[3]->dmabuf.rawbuf + swptr,
-                                                              silence, clear_cnt);
-                                               }
-                                               dmabuf->endcleared = 1;
-                                       }
-                               } else if (dmabuf->count < (signed) dmabuf->fragsize) {
-                                       clear_cnt = dmabuf->fragsize;
-                                       if ((swptr + clear_cnt) > dmabuf->dmasize)
-                                               clear_cnt = dmabuf->dmasize - swptr;
-                                       memset(dmabuf->rawbuf + swptr, silence, clear_cnt);
-                                       if (state->chans_num == 6) {
-                                               clear_cnt = clear_cnt / 2;
-                                               swptr = swptr / 2;
-                                               memset(state->other_states[0]->dmabuf.rawbuf + swptr,
-                                                      silence, clear_cnt);
-                                               memset(state->other_states[1]->dmabuf.rawbuf + swptr,
-                                                      silence, clear_cnt);
-                                               memset(state->other_states[2]->dmabuf.rawbuf + swptr,
-                                                      silence, clear_cnt);
-                                               memset(state->other_states[3]->dmabuf.rawbuf + swptr,
-                                                      silence, clear_cnt);
-                                       }
-                                       dmabuf->endcleared = 1;
-                               }
-                       }
-                       /* trident_update_ptr is called by interrupt handler or by process via
-                          ioctl/poll, we only wake up the waiting process when we have more
-                          than 1/2 buffer free (always true for interrupt handler) */
-                       if (dmabuf->count < (signed) dmabuf->dmasize / 2)
-                               wake_up(&dmabuf->wait);
-               }
-       }
-       dmabuf->update_flag &= ~ALI_ADDRESS_INT_UPDATE;
-}
-
-static void
-trident_address_interrupt(struct trident_card *card)
-{
-       int i;
-       struct trident_state *state;
-       unsigned int channel;
-
-       /* Update the pointers for all channels we are running. */
-       /* FIXME: should read interrupt status only once */
-       for (i = 0; i < NR_HW_CH; i++) {
-               channel = 63 - i;
-               if (trident_check_channel_interrupt(card, channel)) {
-                       trident_ack_channel_interrupt(card, channel);
-                       if ((state = card->states[i]) != NULL) {
-                               trident_update_ptr(state);
-                       } else {
-                               printk(KERN_WARNING "trident: spurious channel "
-                                      "irq %d.\n", channel);
-                               trident_stop_voice(card, channel);
-                               trident_disable_voice_irq(card, channel);
-                       }
-               }
-       }
-}
-
-static void
-ali_hwvol_control(struct trident_card *card, int opt)
-{
-       u16 dwTemp, volume[2], mute, diff, *pVol[2];
-
-       dwTemp = ali_ac97_read(card->ac97_codec[0], 0x02);
-       mute = dwTemp & 0x8000;
-       volume[0] = dwTemp & 0x001f;
-       volume[1] = (dwTemp & 0x1f00) >> 8;
-       if (volume[0] < volume[1]) {
-               pVol[0] = &volume[0];
-               pVol[1] = &volume[1];
-       } else {
-               pVol[1] = &volume[0];
-               pVol[0] = &volume[1];
-       }
-       diff = *(pVol[1]) - *(pVol[0]);
-
-       if (opt == 1) {         // MUTE
-               dwTemp ^= 0x8000;
-               ali_ac97_write(card->ac97_codec[0],
-                              0x02, dwTemp);
-       } else if (opt == 2) {  // Down
-               if (mute)
-                       return;
-               if (*(pVol[1]) < 0x001f) {
-                       (*pVol[1])++;
-                       *(pVol[0]) = *(pVol[1]) - diff;
-               }
-               dwTemp &= 0xe0e0;
-               dwTemp |= (volume[0]) | (volume[1] << 8);
-               ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
-               card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
-                       (((32 - volume[1]) * 25 / 8) << 8);
-       } else if (opt == 4) {  // Up
-               if (mute)
-                       return;
-               if (*(pVol[0]) > 0) {
-                       (*pVol[0])--;
-                       *(pVol[1]) = *(pVol[0]) + diff;
-               }
-               dwTemp &= 0xe0e0;
-               dwTemp |= (volume[0]) | (volume[1] << 8);
-               ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
-               card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
-                       (((32 - volume[1]) * 25 / 8) << 8);
-       } else {
-               /* Nothing needs doing */
-       }
-}
-
-/*
- *     Re-enable reporting of vol change after 0.1 seconds
- */
-
-static void
-ali_timeout(unsigned long ptr)
-{
-       struct trident_card *card = (struct trident_card *) ptr;
-       u16 temp = 0;
-
-       /* Enable GPIO IRQ (MISCINT bit 18h) */
-       temp = inw(TRID_REG(card, T4D_MISCINT + 2));
-       temp |= 0x0004;
-       outw(temp, TRID_REG(card, T4D_MISCINT + 2));
-}
-
-/*
- *     Set up the timer to clear the vol change notification
- */
-
-static void
-ali_set_timer(struct trident_card *card)
-{
-       /* Add Timer Routine to Enable GPIO IRQ */
-       del_timer(&card->timer);        /* Never queue twice */
-       card->timer.function = ali_timeout;
-       card->timer.data = (unsigned long) card;
-       card->timer.expires = jiffies + HZ / 10;
-       add_timer(&card->timer);
-}
-
-/*
- *     Process a GPIO event
- */
-
-static void
-ali_queue_task(struct trident_card *card, int opt)
-{
-       u16 temp;
-
-       /* Disable GPIO IRQ (MISCINT bit 18h) */
-       temp = inw(TRID_REG(card, T4D_MISCINT + 2));
-       temp &= (u16) (~0x0004);
-       outw(temp, TRID_REG(card, T4D_MISCINT + 2));
-
-       /* Adjust the volume */
-       ali_hwvol_control(card, opt);
-
-       /* Set the timer for 1/10th sec */
-       ali_set_timer(card);
-}
-
-static void
-cyber_address_interrupt(struct trident_card *card)
-{
-       int i, irq_status;
-       struct trident_state *state;
-       unsigned int channel;
-
-       /* Update the pointers for all channels we are running. */
-       /* FIXED: read interrupt status only once */
-       irq_status = inl(TRID_REG(card, T4D_AINT_A));
-
-       pr_debug("cyber_address_interrupt: irq_status 0x%X\n", irq_status);
-
-       for (i = 0; i < NR_HW_CH; i++) {
-               channel = 31 - i;
-               if (irq_status & (1 << channel)) {
-                       /* clear bit by writing a 1, zeroes are ignored */
-                       outl((1 << channel), TRID_REG(card, T4D_AINT_A));
-
-                       pr_debug("cyber_interrupt: channel %d\n", channel);
-
-                       if ((state = card->states[i]) != NULL) {
-                               trident_update_ptr(state);
-                       } else {
-                               printk(KERN_WARNING "cyber5050: spurious "
-                                      "channel irq %d.\n", channel);
-                               trident_stop_voice(card, channel);
-                               trident_disable_voice_irq(card, channel);
-                       }
-               }
-       }
-}
-
-static irqreturn_t
-trident_interrupt(int irq, void *dev_id)
-{
-       struct trident_card *card = (struct trident_card *) dev_id;
-       u32 event;
-       u32 gpio;
-
-       spin_lock(&card->lock);
-       event = inl(TRID_REG(card, T4D_MISCINT));
-
-       pr_debug("trident: trident_interrupt called, MISCINT = 0x%08x\n",
-                event);
-
-       if (event & ADDRESS_IRQ) {
-               card->address_interrupt(card);
-       }
-
-       if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-               /* GPIO IRQ (H/W Volume Control) */
-               event = inl(TRID_REG(card, T4D_MISCINT));
-               if (event & (1 << 25)) {
-                       gpio = inl(TRID_REG(card, ALI_GPIO));
-                       if (!timer_pending(&card->timer))
-                               ali_queue_task(card, gpio & 0x07);
-               }
-               event = inl(TRID_REG(card, T4D_MISCINT));
-               outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
-                    TRID_REG(card, T4D_MISCINT));
-               spin_unlock(&card->lock);
-               return IRQ_HANDLED;
-       }
-
-       /* manually clear interrupt status, bad hardware design, blame T^2 */
-       outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
-            TRID_REG(card, T4D_MISCINT));
-       spin_unlock(&card->lock);
-       return IRQ_HANDLED;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting */
-/* to be copied to the user's buffer.  it is filled by the dma machine and */
-/* drained by this loop. */
-static ssize_t
-trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
-{
-       struct trident_state *state = (struct trident_state *)file->private_data;
-       struct dmabuf *dmabuf = &state->dmabuf;
-       ssize_t ret = 0;
-       unsigned long flags;
-       unsigned swptr;
-       int cnt;
-
-       pr_debug("trident: trident_read called, count = %zd\n", count);
-
-       VALIDATE_STATE(state);
-
-       if (dmabuf->mapped)
-               return -ENXIO;
-       if (!access_ok(VERIFY_WRITE, buffer, count))
-               return -EFAULT;
-
-       mutex_lock(&state->sem);
-       if (!dmabuf->ready && (ret = prog_dmabuf_record(state)))
-               goto out;
-
-       while (count > 0) {
-               spin_lock_irqsave(&state->card->lock, flags);
-               if (dmabuf->count > (signed) dmabuf->dmasize) {
-                       /* buffer overrun, we are recovering from */
-                       /* sleep_on_timeout, resync hwptr and swptr, */
-                       /* make process flush the buffer */
-                       dmabuf->count = dmabuf->dmasize;
-                       dmabuf->swptr = dmabuf->hwptr;
-               }
-               swptr = dmabuf->swptr;
-               cnt = dmabuf->dmasize - swptr;
-               if (dmabuf->count < cnt)
-                       cnt = dmabuf->count;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-
-               if (cnt > count)
-                       cnt = count;
-               if (cnt <= 0) {
-                       unsigned long tmo;
-                       /* buffer is empty, start the dma machine and */
-                       /* wait for data to be recorded */
-                       start_adc(state);
-                       if (file->f_flags & O_NONBLOCK) {
-                               if (!ret)
-                                       ret = -EAGAIN;
-                               goto out;
-                       }
-
-                       mutex_unlock(&state->sem);
-                       /* No matter how much space left in the buffer, */
-                       /* we have to wait until CSO == ESO/2 or CSO == ESO */
-                       /* when address engine interrupts */
-                       tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
-                       tmo >>= sample_shift[dmabuf->fmt];
-                       /* There are two situations when sleep_on_timeout returns, one is when
-                          the interrupt is serviced correctly and the process is waked up by
-                          ISR ON TIME. Another is when timeout is expired, which means that
-                          either interrupt is NOT serviced correctly (pending interrupt) or it
-                          is TOO LATE for the process to be scheduled to run (scheduler latency)
-                          which results in a (potential) buffer overrun. And worse, there is
-                          NOTHING we can do to prevent it. */
-                       if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
-                               pr_debug(KERN_ERR "trident: recording schedule timeout, "
-                                        "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
-                                        dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
-                                        dmabuf->hwptr, dmabuf->swptr);
-
-                               /* a buffer overrun, we delay the recovery until next time the
-                                  while loop begin and we REALLY have space to record */
-                       }
-                       if (signal_pending(current)) {
-                               if (!ret)
-                                       ret = -ERESTARTSYS;
-                               goto out;
-                       }
-                       mutex_lock(&state->sem);
-                       if (dmabuf->mapped) {
-                               if (!ret)
-                                       ret = -ENXIO;
-                               goto out;
-                       }
-                       continue;
-               }
-
-               if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
-                       if (!ret)
-                               ret = -EFAULT;
-                       goto out;
-               }
-
-               swptr = (swptr + cnt) % dmabuf->dmasize;
-
-               spin_lock_irqsave(&state->card->lock, flags);
-               dmabuf->swptr = swptr;
-               dmabuf->count -= cnt;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-
-               count -= cnt;
-               buffer += cnt;
-               ret += cnt;
-               start_adc(state);
-       }
-out:
-       mutex_unlock(&state->sem);
-       return ret;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to
-   the soundcard.  it is drained by the dma machine and filled by this loop. */
-
-static ssize_t
-trident_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
-{
-       struct trident_state *state = (struct trident_state *)file->private_data;
-       struct dmabuf *dmabuf = &state->dmabuf;
-       ssize_t ret;
-       unsigned long flags;
-       unsigned swptr;
-       int cnt;
-       unsigned int state_cnt;
-       unsigned int copy_count;
-       int lret; /* for lock_set_fmt */
-
-       pr_debug("trident: trident_write called, count = %zd\n", count);
-
-       VALIDATE_STATE(state);
-
-       /*
-        *      Guard against an mmap or ioctl while writing
-        */
-
-       mutex_lock(&state->sem);
-
-       if (dmabuf->mapped) {
-               ret = -ENXIO;
-               goto out;
-       }
-       if (!dmabuf->ready && (ret = prog_dmabuf_playback(state)))
-               goto out;
-
-       if (!access_ok(VERIFY_READ, buffer, count)) {
-               ret = -EFAULT;
-               goto out;
-       }
-
-       ret = 0;
-
-       while (count > 0) {
-               spin_lock_irqsave(&state->card->lock, flags);
-               if (dmabuf->count < 0) {
-                       /* buffer underrun, we are recovering from */
-                       /* sleep_on_timeout, resync hwptr and swptr */
-                       dmabuf->count = 0;
-                       dmabuf->swptr = dmabuf->hwptr;
-               }
-               swptr = dmabuf->swptr;
-               cnt = dmabuf->dmasize - swptr;
-               if (dmabuf->count + cnt > dmabuf->dmasize)
-                       cnt = dmabuf->dmasize - dmabuf->count;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-
-               if (cnt > count)
-                       cnt = count;
-               if (cnt <= 0) {
-                       unsigned long tmo;
-                       /* buffer is full, start the dma machine and */
-                       /* wait for data to be played */
-                       start_dac(state);
-                       if (file->f_flags & O_NONBLOCK) {
-                               if (!ret)
-                                       ret = -EAGAIN;
-                               goto out;
-                       }
-                       /* No matter how much data left in the buffer, */
-                       /* we have to wait until CSO == ESO/2 or CSO == ESO */
-                       /* when address engine interrupts */
-                       lock_set_fmt(state);
-                       tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
-                       tmo >>= sample_shift[dmabuf->fmt];
-                       unlock_set_fmt(state);
-                       mutex_unlock(&state->sem);
-
-                       /* There are two situations when sleep_on_timeout */
-                       /* returns, one is when the interrupt is serviced */
-                       /* correctly and the process is waked up by ISR */
-                       /* ON TIME. Another is when timeout is expired, which */
-                       /* means that either interrupt is NOT serviced */
-                       /* correctly (pending interrupt) or it is TOO LATE */
-                       /* for the process to be scheduled to run */
-                       /* (scheduler latency) which results in a (potential) */
-                       /* buffer underrun. And worse, there is NOTHING we */
-                       /* can do to prevent it. */
-                       if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
-                               pr_debug(KERN_ERR "trident: playback schedule "
-                                        "timeout, dmasz %u fragsz %u count %i "
-                                        "hwptr %u swptr %u\n", dmabuf->dmasize,
-                                        dmabuf->fragsize, dmabuf->count,
-                                        dmabuf->hwptr, dmabuf->swptr);
-
-                               /* a buffer underrun, we delay the recovery */
-                               /* until next time the while loop begin and */
-                               /* we REALLY have data to play */
-                       }
-                       if (signal_pending(current)) {
-                               if (!ret)
-                                       ret = -ERESTARTSYS;
-                               goto out_nolock;
-                       }
-                       mutex_lock(&state->sem);
-                       if (dmabuf->mapped) {
-                               if (!ret)
-                                       ret = -ENXIO;
-                               goto out;
-                       }
-                       continue;
-               }
-               if ((lret = lock_set_fmt(state)) < 0) {
-                       ret = lret;
-                       goto out;
-               }
-
-               if (state->chans_num == 6) {
-                       copy_count = 0;
-                       state_cnt = 0;
-                       if (ali_write_5_1(state, buffer, cnt, &copy_count,
-                                         &state_cnt) == -EFAULT) {
-                               if (state_cnt) {
-                                       swptr = (swptr + state_cnt) % dmabuf->dmasize;
-                                       spin_lock_irqsave(&state->card->lock, flags);
-                                       dmabuf->swptr = swptr;
-                                       dmabuf->count += state_cnt;
-                                       dmabuf->endcleared = 0;
-                                       spin_unlock_irqrestore(&state->card->lock, flags);
-                               }
-                               ret += copy_count;
-                               if (!ret)
-                                       ret = -EFAULT;
-                               unlock_set_fmt(state);
-                               goto out;
-                       }
-               } else {
-                       if (copy_from_user(dmabuf->rawbuf + swptr,
-                                          buffer, cnt)) {
-                               if (!ret)
-                                       ret = -EFAULT;
-                               unlock_set_fmt(state);
-                               goto out;
-                       }
-                       state_cnt = cnt;
-               }
-               unlock_set_fmt(state);
-
-               swptr = (swptr + state_cnt) % dmabuf->dmasize;
-
-               spin_lock_irqsave(&state->card->lock, flags);
-               dmabuf->swptr = swptr;
-               dmabuf->count += state_cnt;
-               dmabuf->endcleared = 0;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-
-               count -= cnt;
-               buffer += cnt;
-               ret += cnt;
-               start_dac(state);
-       }
-out:
-       mutex_unlock(&state->sem);
-out_nolock:
-       return ret;
-}
-
-/* No kernel lock - we have our own spinlock */
-static unsigned int
-trident_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct trident_state *state = (struct trident_state *)file->private_data;
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned long flags;
-       unsigned int mask = 0;
-
-       VALIDATE_STATE(state);
-
-       /*
-        *      Guard against a parallel poll and write causing multiple
-        *      prog_dmabuf events
-        */
-
-       mutex_lock(&state->sem);
-
-       if (file->f_mode & FMODE_WRITE) {
-               if (!dmabuf->ready && prog_dmabuf_playback(state)) {
-                       mutex_unlock(&state->sem);
-                       return 0;
-               }
-               poll_wait(file, &dmabuf->wait, wait);
-       }
-       if (file->f_mode & FMODE_READ) {
-               if (!dmabuf->ready && prog_dmabuf_record(state)) {
-                       mutex_unlock(&state->sem);
-                       return 0;
-               }
-               poll_wait(file, &dmabuf->wait, wait);
-       }
-
-       mutex_unlock(&state->sem);
-
-       spin_lock_irqsave(&state->card->lock, flags);
-       trident_update_ptr(state);
-       if (file->f_mode & FMODE_READ) {
-               if (dmabuf->count >= (signed) dmabuf->fragsize)
-                       mask |= POLLIN | POLLRDNORM;
-       }
-       if (file->f_mode & FMODE_WRITE) {
-               if (dmabuf->mapped) {
-                       if (dmabuf->count >= (signed) dmabuf->fragsize)
-                               mask |= POLLOUT | POLLWRNORM;
-               } else {
-                       if ((signed) dmabuf->dmasize >= dmabuf->count +
-                           (signed) dmabuf->fragsize)
-                               mask |= POLLOUT | POLLWRNORM;
-               }
-       }
-       spin_unlock_irqrestore(&state->card->lock, flags);
-
-       return mask;
-}
-
-static int
-trident_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct trident_state *state = (struct trident_state *)file->private_data;
-       struct dmabuf *dmabuf = &state->dmabuf;
-       int ret = -EINVAL;
-       unsigned long size;
-
-       VALIDATE_STATE(state);
-
-       /*
-        *      Lock against poll read write or mmap creating buffers. Also lock
-        *      a read or write against an mmap.
-        */
-
-       mutex_lock(&state->sem);
-
-       if (vma->vm_flags & VM_WRITE) {
-               if ((ret = prog_dmabuf_playback(state)) != 0)
-                       goto out;
-       } else if (vma->vm_flags & VM_READ) {
-               if ((ret = prog_dmabuf_record(state)) != 0)
-                       goto out;
-       } else
-               goto out;
-
-       ret = -EINVAL;
-       if (vma->vm_pgoff != 0)
-               goto out;
-       size = vma->vm_end - vma->vm_start;
-       if (size > (PAGE_SIZE << dmabuf->buforder))
-               goto out;
-       ret = -EAGAIN;
-       if (remap_pfn_range(vma, vma->vm_start,
-                            virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
-                            size, vma->vm_page_prot))
-               goto out;
-       dmabuf->mapped = 1;
-       ret = 0;
-out:
-       mutex_unlock(&state->sem);
-       return ret;
-}
-
-static int
-trident_ioctl(struct inode *inode, struct file *file,
-             unsigned int cmd, unsigned long arg)
-{
-       struct trident_state *state = (struct trident_state *)file->private_data;
-       struct dmabuf *dmabuf = &state->dmabuf;
-       unsigned long flags;
-       audio_buf_info abinfo;
-       count_info cinfo;
-       int val, mapped, ret = 0;
-       struct trident_card *card = state->card;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-
-       VALIDATE_STATE(state);
-
-
-       mapped = ((file->f_mode & (FMODE_WRITE | FMODE_READ)) && dmabuf->mapped);
-
-       pr_debug("trident: trident_ioctl, command = %2d, arg = 0x%08x\n",
-                _IOC_NR(cmd), arg ? *p : 0);
-
-       switch (cmd) {
-       case OSS_GETVERSION:
-               ret = put_user(SOUND_VERSION, p);
-               break;
-
-       case SNDCTL_DSP_RESET:
-               /* FIXME: spin_lock ? */
-               if (file->f_mode & FMODE_WRITE) {
-                       stop_dac(state);
-                       synchronize_irq(card->irq);
-                       dmabuf->ready = 0;
-                       dmabuf->swptr = dmabuf->hwptr = 0;
-                       dmabuf->count = dmabuf->total_bytes = 0;
-               }
-               if (file->f_mode & FMODE_READ) {
-                       stop_adc(state);
-                       synchronize_irq(card->irq);
-                       dmabuf->ready = 0;
-                       dmabuf->swptr = dmabuf->hwptr = 0;
-                       dmabuf->count = dmabuf->total_bytes = 0;
-               }
-               break;
-
-       case SNDCTL_DSP_SYNC:
-               if (file->f_mode & FMODE_WRITE)
-                       ret = drain_dac(state, file->f_flags & O_NONBLOCK);
-               break;
-
-       case SNDCTL_DSP_SPEED:  /* set smaple rate */
-               if (get_user(val, p)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               if (val >= 0) {
-                       if (file->f_mode & FMODE_WRITE) {
-                               stop_dac(state);
-                               dmabuf->ready = 0;
-                               spin_lock_irqsave(&state->card->lock, flags);
-                               trident_set_dac_rate(state, val);
-                               spin_unlock_irqrestore(&state->card->lock, flags);
-                       }
-                       if (file->f_mode & FMODE_READ) {
-                               stop_adc(state);
-                               dmabuf->ready = 0;
-                               spin_lock_irqsave(&state->card->lock, flags);
-                               trident_set_adc_rate(state, val);
-                               spin_unlock_irqrestore(&state->card->lock, flags);
-                       }
-               }
-               ret = put_user(dmabuf->rate, p);
-               break;
-
-       case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
-               if (get_user(val, p)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               if ((ret = lock_set_fmt(state)) < 0)
-                       return ret;
-
-               if (file->f_mode & FMODE_WRITE) {
-                       stop_dac(state);
-                       dmabuf->ready = 0;
-                       if (val)
-                               dmabuf->fmt |= TRIDENT_FMT_STEREO;
-                       else
-                               dmabuf->fmt &= ~TRIDENT_FMT_STEREO;
-               }
-               if (file->f_mode & FMODE_READ) {
-                       stop_adc(state);
-                       dmabuf->ready = 0;
-                       if (val)
-                               dmabuf->fmt |= TRIDENT_FMT_STEREO;
-                       else
-                               dmabuf->fmt &= ~TRIDENT_FMT_STEREO;
-               }
-               unlock_set_fmt(state);
-               break;
-
-       case SNDCTL_DSP_GETBLKSIZE:
-               if (file->f_mode & FMODE_WRITE) {
-                       if ((val = prog_dmabuf_playback(state)))
-                               ret = val;
-                       else
-                               ret = put_user(dmabuf->fragsize, p);
-                       break;
-               }
-               if (file->f_mode & FMODE_READ) {
-                       if ((val = prog_dmabuf_record(state)))
-                               ret = val;
-                       else
-                               ret = put_user(dmabuf->fragsize, p);
-                       break;
-               }
-               /* neither READ nor WRITE? is this even possible? */
-               ret = -EINVAL;
-               break;
-
-
-       case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */
-               ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
-                              AFMT_U8, p);
-               break;
-
-       case SNDCTL_DSP_SETFMT: /* Select sample format */
-               if (get_user(val, p)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               if ((ret = lock_set_fmt(state)) < 0)
-                       return ret;
-
-               if (val != AFMT_QUERY) {
-                       if (file->f_mode & FMODE_WRITE) {
-                               stop_dac(state);
-                               dmabuf->ready = 0;
-                               if (val == AFMT_S16_LE)
-                                       dmabuf->fmt |= TRIDENT_FMT_16BIT;
-                               else
-                                       dmabuf->fmt &= ~TRIDENT_FMT_16BIT;
-                       }
-                       if (file->f_mode & FMODE_READ) {
-                               stop_adc(state);
-                               dmabuf->ready = 0;
-                               if (val == AFMT_S16_LE)
-                                       dmabuf->fmt |= TRIDENT_FMT_16BIT;
-                               else
-                                       dmabuf->fmt &= ~TRIDENT_FMT_16BIT;
-                       }
-               }
-               unlock_set_fmt(state);
-               ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
-                              AFMT_U8, p);
-               break;
-
-       case SNDCTL_DSP_CHANNELS:
-               if (get_user(val, p)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               if (val != 0) {
-                       if ((ret = lock_set_fmt(state)) < 0)
-                               return ret;
-
-                       if (file->f_mode & FMODE_WRITE) {
-                               stop_dac(state);
-                               dmabuf->ready = 0;
-
-                               //prevent from memory leak
-                               if ((state->chans_num > 2) && (state->chans_num != val)) {
-                                       ali_free_other_states_resources(state);
-                                       state->chans_num = 1;
-                               }
-
-                               if (val >= 2) {
-
-                                       dmabuf->fmt |= TRIDENT_FMT_STEREO;
-                                       if ((val == 6) && (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)) {
-                                               if (card->rec_channel_use_count > 0) {
-                                                       printk(KERN_ERR "trident: Record is "
-                                                              "working on the card!\n");
-                                                       ret = -EBUSY;
-                                                       unlock_set_fmt(state);
-                                                       break;
-                                               }
-
-                                               ret = ali_setup_multi_channels(state->card, 6);
-                                               if (ret < 0) {
-                                                       unlock_set_fmt(state);
-                                                       break;
-                                               }
-                                               mutex_lock(&state->card->open_mutex);
-                                               ret = ali_allocate_other_states_resources(state, 6);
-                                               if (ret < 0) {
-                                                       mutex_unlock(&state->card->open_mutex);
-                                                       unlock_set_fmt(state);
-                                                       break;
-                                               }
-                                               state->card->multi_channel_use_count++;
-                                               mutex_unlock(&state->card->open_mutex);
-                                       } else
-                                               val = 2;        /*yield to 2-channels */
-                               } else
-                                       dmabuf->fmt &= ~TRIDENT_FMT_STEREO;
-                               state->chans_num = val;
-                       }
-                       if (file->f_mode & FMODE_READ) {
-                               stop_adc(state);
-                               dmabuf->ready = 0;
-                               if (val >= 2) {
-                                       if (!((file->f_mode & FMODE_WRITE) &&
-                                             (val == 6)))
-                                               val = 2;
-                                       dmabuf->fmt |= TRIDENT_FMT_STEREO;
-                               } else
-                                       dmabuf->fmt &= ~TRIDENT_FMT_STEREO;
-                               state->chans_num = val;
-                       }
-                       unlock_set_fmt(state);
-               }
-               ret = put_user(val, p);
-               break;
-
-       case SNDCTL_DSP_POST:
-               /* Cause the working fragment to be output */
-               break;
-
-       case SNDCTL_DSP_SUBDIVIDE:
-               if (dmabuf->subdivision) {
-                       ret = -EINVAL;
-                       break;
-               }
-               if (get_user(val, p)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               if (val != 1 && val != 2 && val != 4) {
-                       ret = -EINVAL;
-                       break;
-               }
-               dmabuf->subdivision = val;
-               break;
-
-       case SNDCTL_DSP_SETFRAGMENT:
-               if (get_user(val, p)) {
-                       ret = -EFAULT;
-                       break;
-               }
-
-               dmabuf->ossfragshift = val & 0xffff;
-               dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
-               if (dmabuf->ossfragshift < 4)
-                       dmabuf->ossfragshift = 4;
-               if (dmabuf->ossfragshift > 15)
-                       dmabuf->ossfragshift = 15;
-               if (dmabuf->ossmaxfrags < 4)
-                       dmabuf->ossmaxfrags = 4;
-
-               break;
-
-       case SNDCTL_DSP_GETOSPACE:
-               if (!(file->f_mode & FMODE_WRITE)) {
-                       ret = -EINVAL;
-                       break;
-               }
-               if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) {
-                       ret = val;
-                       break;
-               }
-               spin_lock_irqsave(&state->card->lock, flags);
-               trident_update_ptr(state);
-               abinfo.fragsize = dmabuf->fragsize;
-               abinfo.bytes = dmabuf->dmasize - dmabuf->count;
-               abinfo.fragstotal = dmabuf->numfrag;
-               abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
-                       -EFAULT : 0;
-               break;
-
-       case SNDCTL_DSP_GETISPACE:
-               if (!(file->f_mode & FMODE_READ)) {
-                       ret = -EINVAL;
-                       break;
-               }
-               if (!dmabuf->ready && (val = prog_dmabuf_record(state)) != 0) {
-                       ret = val;
-                       break;
-               }
-               spin_lock_irqsave(&state->card->lock, flags);
-               trident_update_ptr(state);
-               abinfo.fragsize = dmabuf->fragsize;
-               abinfo.bytes = dmabuf->count;
-               abinfo.fragstotal = dmabuf->numfrag;
-               abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
-                       -EFAULT : 0;
-               break;
-
-       case SNDCTL_DSP_NONBLOCK:
-               file->f_flags |= O_NONBLOCK;
-               break;
-
-       case SNDCTL_DSP_GETCAPS:
-               ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER |
-                              DSP_CAP_MMAP | DSP_CAP_BIND, p);
-               break;
-
-       case SNDCTL_DSP_GETTRIGGER:
-               val = 0;
-               if ((file->f_mode & FMODE_READ) && dmabuf->enable)
-                       val |= PCM_ENABLE_INPUT;
-               if ((file->f_mode & FMODE_WRITE) && dmabuf->enable)
-                       val |= PCM_ENABLE_OUTPUT;
-               ret = put_user(val, p);
-               break;
-
-       case SNDCTL_DSP_SETTRIGGER:
-               if (get_user(val, p)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               if (file->f_mode & FMODE_READ) {
-                       if (val & PCM_ENABLE_INPUT) {
-                               if (!dmabuf->ready &&
-                                   (ret = prog_dmabuf_record(state)))
-                                       break;
-                               start_adc(state);
-                       } else
-                               stop_adc(state);
-               }
-               if (file->f_mode & FMODE_WRITE) {
-                       if (val & PCM_ENABLE_OUTPUT) {
-                               if (!dmabuf->ready &&
-                                   (ret = prog_dmabuf_playback(state)))
-                                       break;
-                               start_dac(state);
-                       } else
-                               stop_dac(state);
-               }
-               break;
-
-       case SNDCTL_DSP_GETIPTR:
-               if (!(file->f_mode & FMODE_READ)) {
-                       ret = -EINVAL;
-                       break;
-               }
-               if (!dmabuf->ready && (val = prog_dmabuf_record(state))
-                   != 0) {
-                       ret = val;
-                       break;
-               }
-               spin_lock_irqsave(&state->card->lock, flags);
-               trident_update_ptr(state);
-               cinfo.bytes = dmabuf->total_bytes;
-               cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
-               cinfo.ptr = dmabuf->hwptr;
-               if (dmabuf->mapped)
-                       dmabuf->count &= dmabuf->fragsize - 1;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
-                       -EFAULT : 0;
-               break;
-
-       case SNDCTL_DSP_GETOPTR:
-               if (!(file->f_mode & FMODE_WRITE)) {
-                       ret = -EINVAL;
-                       break;
-               }
-               if (!dmabuf->ready && (val = prog_dmabuf_playback(state))
-                   != 0) {
-                       ret = val;
-                       break;
-               }
-
-               spin_lock_irqsave(&state->card->lock, flags);
-               trident_update_ptr(state);
-               cinfo.bytes = dmabuf->total_bytes;
-               cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
-               cinfo.ptr = dmabuf->hwptr;
-               if (dmabuf->mapped)
-                       dmabuf->count &= dmabuf->fragsize - 1;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
-                       -EFAULT : 0;
-               break;
-
-       case SNDCTL_DSP_SETDUPLEX:
-               ret = -EINVAL;
-               break;
-
-       case SNDCTL_DSP_GETODELAY:
-               if (!(file->f_mode & FMODE_WRITE)) {
-                       ret = -EINVAL;
-                       break;
-               }
-               if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) {
-                       ret = val;
-                       break;
-               }
-               spin_lock_irqsave(&state->card->lock, flags);
-               trident_update_ptr(state);
-               val = dmabuf->count;
-               spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = put_user(val, p);
-               break;
-
-       case SOUND_PCM_READ_RATE:
-               ret = put_user(dmabuf->rate, p);
-               break;
-
-       case SOUND_PCM_READ_CHANNELS:
-               ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
-                              p);
-               break;
-
-       case SOUND_PCM_READ_BITS:
-               ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
-                              AFMT_U8, p);
-               break;
-
-       case SNDCTL_DSP_GETCHANNELMASK:
-               ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR |
-                              DSP_BIND_CENTER_LFE,  p);
-               break;
-
-       case SNDCTL_DSP_BIND_CHANNEL:
-               if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               if (get_user(val, p)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               if (val == DSP_BIND_QUERY) {
-                       val = dmabuf->channel->attribute | 0x3c00;
-                       val = attr2mask[val >> 8];
-               } else {
-                       dmabuf->ready = 0;
-                       if (file->f_mode & FMODE_READ)
-                               dmabuf->channel->attribute = (CHANNEL_REC |
-                                                             SRC_ENABLE);
-                       if (file->f_mode & FMODE_WRITE)
-                               dmabuf->channel->attribute = (CHANNEL_SPC_PB |
-                                                             SRC_ENABLE);
-                       dmabuf->channel->attribute |= mask2attr[ffs(val)];
-               }
-               ret = put_user(val, p);
-               break;
-
-       case SNDCTL_DSP_MAPINBUF:
-       case SNDCTL_DSP_MAPOUTBUF:
-       case SNDCTL_DSP_SETSYNCRO:
-       case SOUND_PCM_WRITE_FILTER:
-       case SOUND_PCM_READ_FILTER:
-       default:
-               ret = -EINVAL;
-               break;
-
-       }
-       return ret;
-}
-
-static int
-trident_open(struct inode *inode, struct file *file)
-{
-       int i = 0;
-       int minor = iminor(inode);
-       struct trident_card *card = devs;
-       struct trident_state *state = NULL;
-       struct dmabuf *dmabuf = NULL;
-       unsigned long flags;
-
-       /* Added by Matt Wu 01-05-2001 */
-       /* TODO: there's some redundacy here wrt the check below */
-       /* for multi_use_count > 0. Should we return -EBUSY or find */
-       /* a different card? for now, don't break current behaviour */
-       /* -- mulix */
-       if (file->f_mode & FMODE_READ) {
-               if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-                       if (card->multi_channel_use_count > 0)
-                               return -EBUSY;
-               }
-       }
-
-       /* find an available virtual channel (instance of /dev/dsp) */
-       while (card != NULL) {
-               mutex_lock(&card->open_mutex);
-               if (file->f_mode & FMODE_READ) {
-                       /* Skip opens on cards that are in 6 channel mode */
-                       if (card->multi_channel_use_count > 0) {
-                               mutex_unlock(&card->open_mutex);
-                               card = card->next;
-                               continue;
-                       }
-               }
-               for (i = 0; i < NR_HW_CH; i++) {
-                       if (card->states[i] == NULL) {
-                               state = card->states[i] = kzalloc(sizeof(*state), GFP_KERNEL);
-                               if (state == NULL) {
-                                       mutex_unlock(&card->open_mutex);
-                                       return -ENOMEM;
-                               }
-                               mutex_init(&state->sem);
-                               dmabuf = &state->dmabuf;
-                               goto found_virt;
-                       }
-               }
-               mutex_unlock(&card->open_mutex);
-               card = card->next;
-       }
-       /* no more virtual channel avaiable */
-       if (!state) {
-               return -ENODEV;
-       }
-      found_virt:
-       /* found a free virtual channel, allocate hardware channels */
-       if (file->f_mode & FMODE_READ)
-               dmabuf->channel = card->alloc_rec_pcm_channel(card);
-       else
-               dmabuf->channel = card->alloc_pcm_channel(card);
-
-       if (dmabuf->channel == NULL) {
-               kfree(card->states[i]);
-               card->states[i] = NULL;
-               return -ENODEV;
-       }
-
-       /* initialize the virtual channel */
-       state->virt = i;
-       state->card = card;
-       state->magic = TRIDENT_STATE_MAGIC;
-       init_waitqueue_head(&dmabuf->wait);
-       file->private_data = state;
-
-       /* set default sample format. According to OSS Programmer's */
-       /* Guide  /dev/dsp should be default to unsigned 8-bits, mono, */
-       /* with sample rate 8kHz and /dev/dspW will accept 16-bits sample */
-       if (file->f_mode & FMODE_WRITE) {
-               dmabuf->fmt &= ~TRIDENT_FMT_MASK;
-               if ((minor & 0x0f) == SND_DEV_DSP16)
-                       dmabuf->fmt |= TRIDENT_FMT_16BIT;
-               dmabuf->ossfragshift = 0;
-               dmabuf->ossmaxfrags = 0;
-               dmabuf->subdivision = 0;
-               if (card->pci_id == PCI_DEVICE_ID_SI_7018) {
-                       /* set default channel attribute to normal playback */
-                       dmabuf->channel->attribute = CHANNEL_PB;
-               }
-               spin_lock_irqsave(&card->lock, flags);
-               trident_set_dac_rate(state, 8000);
-               spin_unlock_irqrestore(&card->lock, flags);
-       }
-
-       if (file->f_mode & FMODE_READ) {
-               /* FIXME: Trident 4d can only record in signed 16-bits stereo, */
-               /* 48kHz sample, to be dealed with in trident_set_adc_rate() ?? */
-               dmabuf->fmt &= ~TRIDENT_FMT_MASK;
-               if ((minor & 0x0f) == SND_DEV_DSP16)
-                       dmabuf->fmt |= TRIDENT_FMT_16BIT;
-               dmabuf->ossfragshift = 0;
-               dmabuf->ossmaxfrags = 0;
-               dmabuf->subdivision = 0;
-               if (card->pci_id == PCI_DEVICE_ID_SI_7018) {
-                       /* set default channel attribute to 0x8a80, record from
-                          PCM L/R FIFO and mono = (left + right + 1)/2 */
-                       dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR |
-                                                     MONO_MIX);
-               }
-               spin_lock_irqsave(&card->lock, flags);
-               trident_set_adc_rate(state, 8000);
-               spin_unlock_irqrestore(&card->lock, flags);
-
-               /* Added by Matt Wu 01-05-2001 */
-               if (card->pci_id == PCI_DEVICE_ID_ALI_5451)
-                       card->rec_channel_use_count++;
-       }
-
-       state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
-       mutex_unlock(&card->open_mutex);
-
-       pr_debug("trident: open virtual channel %d, hard channel %d\n",
-                state->virt, dmabuf->channel->num);
-
-       return nonseekable_open(inode, file);
-}
-
-static int
-trident_release(struct inode *inode, struct file *file)
-{
-       struct trident_state *state = (struct trident_state *)file->private_data;
-       struct trident_card *card;
-       struct dmabuf *dmabuf;
-
-       VALIDATE_STATE(state);
-
-       card = state->card;
-       dmabuf = &state->dmabuf;
-
-       if (file->f_mode & FMODE_WRITE) {
-               trident_clear_tail(state);
-               drain_dac(state, file->f_flags & O_NONBLOCK);
-       }
-
-       pr_debug("trident: closing virtual channel %d, hard channel %d\n",
-                state->virt, dmabuf->channel->num);
-
-       /* stop DMA state machine and free DMA buffers/channels */
-       mutex_lock(&card->open_mutex);
-
-       if (file->f_mode & FMODE_WRITE) {
-               stop_dac(state);
-               dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
-               state->card->free_pcm_channel(state->card, dmabuf->channel->num);
-
-               /* Added by Matt Wu */
-               if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-                       if (state->chans_num > 2) {
-                               if (card->multi_channel_use_count-- < 0)
-                                       card->multi_channel_use_count = 0;
-                               if (card->multi_channel_use_count == 0)
-                                       ali_close_multi_channels();
-                               ali_free_other_states_resources(state);
-                       }
-               }
-       }
-       if (file->f_mode & FMODE_READ) {
-               stop_adc(state);
-               dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
-               state->card->free_pcm_channel(state->card, dmabuf->channel->num);
-
-               /* Added by Matt Wu */
-               if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-                       if (card->rec_channel_use_count-- < 0)
-                               card->rec_channel_use_count = 0;
-               }
-       }
-
-       card->states[state->virt] = NULL;
-       kfree(state);
-
-       /* we're covered by the open_mutex */
-       mutex_unlock(&card->open_mutex);
-
-       return 0;
-}
-
-static const struct file_operations trident_audio_fops = {
-       .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .read = trident_read,
-       .write = trident_write,
-       .poll = trident_poll,
-       .ioctl = trident_ioctl,
-       .mmap = trident_mmap,
-       .open = trident_open,
-       .release = trident_release,
-};
-
-/* trident specific AC97 functions */
-/* Write AC97 codec registers */
-static void
-trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val)
-{
-       struct trident_card *card = (struct trident_card *)codec->private_data;
-       unsigned int address, mask, busy;
-       unsigned short count = 0xffff;
-       unsigned long flags;
-       u32 data;
-
-       data = ((u32) val) << 16;
-
-       switch (card->pci_id) {
-       default:
-       case PCI_DEVICE_ID_SI_7018:
-               address = SI_AC97_WRITE;
-               mask = SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY;
-               if (codec->id)
-                       mask |= SI_AC97_SECONDARY;
-               busy = SI_AC97_BUSY_WRITE;
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
-               address = DX_ACR0_AC97_W;
-               mask = busy = DX_AC97_BUSY_WRITE;
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
-               address = NX_ACR1_AC97_W;
-               mask = NX_AC97_BUSY_WRITE;
-               if (codec->id)
-                       mask |= NX_AC97_WRITE_SECONDARY;
-               busy = NX_AC97_BUSY_WRITE;
-               break;
-       case PCI_DEVICE_ID_INTERG_5050:
-               address = SI_AC97_WRITE;
-               mask = busy = SI_AC97_BUSY_WRITE;
-               if (codec->id)
-                       mask |= SI_AC97_SECONDARY;
-               break;
-       }
-
-       spin_lock_irqsave(&card->lock, flags);
-       do {
-               if ((inw(TRID_REG(card, address)) & busy) == 0)
-                       break;
-       } while (--count);
-
-       data |= (mask | (reg & AC97_REG_ADDR));
-
-       if (count == 0) {
-               printk(KERN_ERR "trident: AC97 CODEC write timed out.\n");
-               spin_unlock_irqrestore(&card->lock, flags);
-               return;
-       }
-
-       outl(data, TRID_REG(card, address));
-       spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/* Read AC97 codec registers */
-static u16
-trident_ac97_get(struct ac97_codec *codec, u8 reg)
-{
-       struct trident_card *card = (struct trident_card *)codec->private_data;
-       unsigned int address, mask, busy;
-       unsigned short count = 0xffff;
-       unsigned long flags;
-       u32 data;
-
-       switch (card->pci_id) {
-       default:
-       case PCI_DEVICE_ID_SI_7018:
-               address = SI_AC97_READ;
-               mask = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY;
-               if (codec->id)
-                       mask |= SI_AC97_SECONDARY;
-               busy = SI_AC97_BUSY_READ;
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
-               address = DX_ACR1_AC97_R;
-               mask = busy = DX_AC97_BUSY_READ;
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
-               if (codec->id)
-                       address = NX_ACR3_AC97_R_SECONDARY;
-               else
-                       address = NX_ACR2_AC97_R_PRIMARY;
-               mask = NX_AC97_BUSY_READ;
-               busy = NX_AC97_BUSY_READ | NX_AC97_BUSY_DATA;
-               break;
-       case PCI_DEVICE_ID_INTERG_5050:
-               address = SI_AC97_READ;
-               mask = busy = SI_AC97_BUSY_READ;
-               if (codec->id)
-                       mask |= SI_AC97_SECONDARY;
-               break;
-       }
-
-       data = (mask | (reg & AC97_REG_ADDR));
-
-       spin_lock_irqsave(&card->lock, flags);
-       outl(data, TRID_REG(card, address));
-       do {
-               data = inl(TRID_REG(card, address));
-               if ((data & busy) == 0)
-                       break;
-       } while (--count);
-       spin_unlock_irqrestore(&card->lock, flags);
-
-       if (count == 0) {
-               printk(KERN_ERR "trident: AC97 CODEC read timed out.\n");
-               data = 0;
-       }
-       return ((u16) (data >> 16));
-}
-
-/* rewrite ac97 read and write mixer register by hulei for ALI*/
-static int
-acquirecodecaccess(struct trident_card *card)
-{
-       u16 wsemamask = 0x6000; /* bit 14..13 */
-       u16 wsemabits;
-       u16 wcontrol;
-       int block = 0;
-       int ncount = 25;
-       while (1) {
-               wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
-               wsemabits = wcontrol & wsemamask;
-
-               if (wsemabits == 0x4000)
-                       return 1;       /* 0x4000 is audio ,then success */
-               if (ncount-- < 0)
-                       break;
-               if (wsemabits == 0) {
-                     unlock:
-                       outl(((u32) (wcontrol & 0x1eff) | 0x00004000),
-                            TRID_REG(card, ALI_AC97_WRITE));
-                       continue;
-               }
-               udelay(20);
-       }
-       if (!block) {
-               pr_debug("accesscodecsemaphore: try unlock\n");
-               block = 1;
-               goto unlock;
-       }
-       return 0;
-}
-
-static void
-releasecodecaccess(struct trident_card *card)
-{
-       unsigned long wcontrol;
-       wcontrol = inl(TRID_REG(card, ALI_AC97_WRITE));
-       outl((wcontrol & 0xffff1eff), TRID_REG(card, ALI_AC97_WRITE));
-}
-
-static int
-waitforstimertick(struct trident_card *card)
-{
-       unsigned long chk1, chk2;
-       unsigned int wcount = 0xffff;
-       chk1 = inl(TRID_REG(card, ALI_STIMER));
-
-       while (1) {
-               chk2 = inl(TRID_REG(card, ALI_STIMER));
-               if ((wcount > 0) && chk1 != chk2)
-                       return 1;
-               if (wcount <= 0)
-                       break;
-               udelay(50);
-       }
-       return 0;
-}
-
-/* Read AC97 codec registers for ALi*/
-static u16
-ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
-{
-       unsigned int address, mask;
-       unsigned int ncount;
-       unsigned long aud_reg;
-       u32 data;
-       u16 wcontrol;
-       unsigned long flags;
-
-       BUG_ON(!card);
-
-       address = ALI_AC97_READ;
-       if (card->revision == ALI_5451_V02) {
-               address = ALI_AC97_WRITE;
-       }
-       mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY;
-       if (secondary)
-               mask |= ALI_AC97_SECONDARY;
-
-       spin_lock_irqsave(&card->lock, flags);
-
-       if (!acquirecodecaccess(card))
-               printk(KERN_ERR "access codec fail\n");
-
-       wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
-       wcontrol &= 0xfe00;
-       wcontrol |= (0x8000 | reg);
-       outw(wcontrol, TRID_REG(card, ALI_AC97_WRITE));
-
-       data = (mask | (reg & AC97_REG_ADDR));
-
-       if (!waitforstimertick(card)) {
-               printk(KERN_ERR "ali_ac97_read: BIT_CLOCK is dead\n");
-               goto releasecodec;
-       }
-
-       udelay(20);
-
-       ncount = 10;
-
-       while (1) {
-               if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ)
-                   != 0)
-                       break;
-               if (ncount <= 0)
-                       break;
-               if (ncount-- == 1) {
-                       pr_debug("ali_ac97_read :try clear busy flag\n");
-                       aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE));
-                       outl((aud_reg & 0xffff7fff),
-                            TRID_REG(card, ALI_AC97_WRITE));
-               }
-               udelay(10);
-       }
-
-       data = inl(TRID_REG(card, address));
-
-       spin_unlock_irqrestore(&card->lock, flags);
-
-       return ((u16) (data >> 16));
-
-      releasecodec:
-       releasecodecaccess(card);
-       spin_unlock_irqrestore(&card->lock, flags);
-       printk(KERN_ERR "ali_ac97_read: AC97 CODEC read timed out.\n");
-       return 0;
-}
-
-/* Write AC97 codec registers for hulei*/
-static void
-ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
-{
-       unsigned int address, mask;
-       unsigned int ncount;
-       u32 data;
-       u16 wcontrol;
-       unsigned long flags;
-
-       data = ((u32) val) << 16;
-
-       BUG_ON(!card);
-
-       address = ALI_AC97_WRITE;
-       mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
-       if (secondary)
-               mask |= ALI_AC97_SECONDARY;
-       if (card->revision == ALI_5451_V02)
-               mask |= ALI_AC97_WRITE_MIXER_REGISTER;
-
-       spin_lock_irqsave(&card->lock, flags);
-       if (!acquirecodecaccess(card))
-               printk(KERN_ERR "ali_ac97_write: access codec fail\n");
-
-       wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
-       wcontrol &= 0xff00;
-       wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */
-                                   /* ali1535+ write */
-       outl((data | wcontrol), TRID_REG(card, ALI_AC97_WRITE));
-
-       if (!waitforstimertick(card)) {
-               printk(KERN_ERR "BIT_CLOCK is dead\n");
-               goto releasecodec;
-       }
-
-       ncount = 10;
-       while (1) {
-               wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
-               if (!(wcontrol & 0x8000))
-                       break;
-               if (ncount <= 0)
-                       break;
-               if (ncount-- == 1) {
-                       pr_debug("ali_ac97_set :try clear busy flag!!\n");
-                       outw(wcontrol & 0x7fff,
-                            TRID_REG(card, ALI_AC97_WRITE));
-               }
-               udelay(10);
-       }
-
-      releasecodec:
-       releasecodecaccess(card);
-       spin_unlock_irqrestore(&card->lock, flags);
-       return;
-}
-
-static void
-ali_enable_special_channel(struct trident_state *stat)
-{
-       struct trident_card *card = stat->card;
-       unsigned long s_channels;
-
-       s_channels = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
-       s_channels |= (1 << stat->dmabuf.channel->num);
-       outl(s_channels, TRID_REG(card, ALI_GLOBAL_CONTROL));
-}
-
-static u16
-ali_ac97_read(struct ac97_codec *codec, u8 reg)
-{
-       int id;
-       u16 data;
-       struct trident_card *card = NULL;
-
-       /* Added by Matt Wu */
-       BUG_ON(!codec);
-
-       card = (struct trident_card *) codec->private_data;
-
-       if (!card->mixer_regs_ready)
-               return ali_ac97_get(card, codec->id, reg);
-
-       /*
-        *      FIXME: need to stop this caching some registers
-        */
-       if (codec->id)
-               id = 1;
-       else
-               id = 0;
-
-       data = card->mixer_regs[reg / 2][id];
-       return data;
-}
-
-static void
-ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
-{
-       int id;
-       struct trident_card *card;
-
-       /*  Added by Matt Wu */
-       BUG_ON(!codec);
-
-       card = (struct trident_card *) codec->private_data;
-
-       if (!card->mixer_regs_ready) {
-               ali_ac97_set(card, codec->id, reg, val);
-               return;
-       }
-
-       if (codec->id)
-               id = 1;
-       else
-               id = 0;
-
-       card->mixer_regs[reg / 2][id] = val;
-       ali_ac97_set(card, codec->id, reg, val);
-}
-
-/*
-flag:  ALI_SPDIF_OUT_TO_SPDIF_OUT
-       ALI_PCM_TO_SPDIF_OUT
-*/
-
-static void
-ali_setup_spdif_out(struct trident_card *card, int flag)
-{
-       unsigned long spdif;
-       unsigned char ch;
-
-       char temp;
-       struct pci_dev *pci_dev = NULL;
-
-       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);
-       temp |= 0x40;
-       pci_write_config_byte(pci_dev, 0x61, temp);
-       pci_read_config_byte(pci_dev, 0x7d, &temp);
-       temp |= 0x01;
-       pci_write_config_byte(pci_dev, 0x7d, temp);
-       pci_read_config_byte(pci_dev, 0x7e, &temp);
-       temp &= (~0x20);
-       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));
-       outb(ch & ALI_SPDIF_OUT_CH_STATUS, TRID_REG(card, ALI_SPDIF_CTRL));
-
-       if (flag & ALI_SPDIF_OUT_TO_SPDIF_OUT) {
-               spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL));
-               spdif |= ALI_SPDIF_OUT_CH_ENABLE;
-               spdif &= ALI_SPDIF_OUT_SEL_SPDIF;
-               outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
-               spdif = inw(TRID_REG(card, ALI_SPDIF_CS));
-               if (flag & ALI_SPDIF_OUT_NON_PCM)
-                       spdif |= 0x0002;
-               else
-                       spdif &= (~0x0002);
-               outw(spdif, TRID_REG(card, ALI_SPDIF_CS));
-       } else {
-               spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL));
-               spdif |= ALI_SPDIF_OUT_SEL_PCM;
-               outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
-       }
-}
-
-static void
-ali_disable_special_channel(struct trident_card *card, int ch)
-{
-       unsigned long sc;
-
-       sc = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
-       sc &= ~(1 << ch);
-       outl(sc, TRID_REG(card, ALI_GLOBAL_CONTROL));
-}
-
-static void
-ali_disable_spdif_in(struct trident_card *card)
-{
-       unsigned long spdif;
-
-       spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
-       spdif &= (~ALI_SPDIF_IN_SUPPORT);
-       outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
-
-       ali_disable_special_channel(card, ALI_SPDIF_IN_CHANNEL);
-}
-
-static void
-ali_setup_spdif_in(struct trident_card *card)
-{
-       unsigned long spdif;
-
-       //Set SPDIF IN Supported
-       spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
-       spdif |= ALI_SPDIF_IN_SUPPORT;
-       outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
-
-       //Set SPDIF IN Rec
-       spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
-       spdif |= ALI_SPDIF_IN_CH_ENABLE;
-       outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
-
-       spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL));
-       spdif |= ALI_SPDIF_IN_CH_STATUS;
-       outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL));
-/*
-       spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL));
-       spdif |= ALI_SPDIF_IN_FUNC_ENABLE;
-       outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL));
-*/
-}
-
-static void
-ali_delay(struct trident_card *card, int interval)
-{
-       unsigned long begintimer, currenttimer;
-
-       begintimer = inl(TRID_REG(card, ALI_STIMER));
-       currenttimer = inl(TRID_REG(card, ALI_STIMER));
-
-       while (currenttimer < begintimer + interval)
-               currenttimer = inl(TRID_REG(card, ALI_STIMER));
-}
-
-static void
-ali_detect_spdif_rate(struct trident_card *card)
-{
-       u16 wval = 0;
-       u16 count = 0;
-       u8 bval = 0, R1 = 0, R2 = 0;
-
-       bval = inb(TRID_REG(card, ALI_SPDIF_CTRL));
-       bval |= 0x02;
-       outb(bval, TRID_REG(card, ALI_SPDIF_CTRL));
-
-       bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1));
-       bval |= 0x1F;
-       outb(bval, TRID_REG(card, ALI_SPDIF_CTRL + 1));
-
-       while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) &&
-              count <= 50000) {
-               count++;
-
-               ali_delay(card, 6);
-
-               bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1));
-               R1 = bval & 0x1F;
-       }
-
-       if (count > 50000) {
-               printk(KERN_WARNING "trident: Error in "
-                      "ali_detect_spdif_rate!\n");
-               return;
-       }
-
-       count = 0;
-
-       while (count <= 50000) {
-               count++;
-
-               ali_delay(card, 6);
-
-               bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1));
-               R2 = bval & 0x1F;
-
-               if (R2 != R1)
-                       R1 = R2;
-               else
-                       break;
-       }
-
-       if (count > 50000) {
-               printk(KERN_WARNING "trident: Error in "
-                      "ali_detect_spdif_rate!\n");
-               return;
-       }
-
-       switch (R2) {
-       case 0x0b:
-       case 0x0c:
-       case 0x0d:
-       case 0x0e:
-               wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2));
-               wval &= 0xE0F0;
-               wval |= (u16) 0x09 << 8 | (u16) 0x05;
-               outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2));
-
-               bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0;
-               outb(bval | 0x02, TRID_REG(card, ALI_SPDIF_CS + 3));
-               break;
-
-       case 0x12:
-               wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2));
-               wval &= 0xE0F0;
-               wval |= (u16) 0x0E << 8 | (u16) 0x08;
-               outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2));
-
-               bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0;
-               outb(bval | 0x03, TRID_REG(card, ALI_SPDIF_CS + 3));
-               break;
-
-       default:
-               break;
-       }
-
-}
-
-static unsigned int
-ali_get_spdif_in_rate(struct trident_card *card)
-{
-       u32 dwRate = 0;
-       u8 bval = 0;
-
-       ali_detect_spdif_rate(card);
-
-       bval = inb(TRID_REG(card, ALI_SPDIF_CTRL));
-       bval &= 0x7F;
-       bval |= 0x40;
-       outb(bval, TRID_REG(card, ALI_SPDIF_CTRL));
-
-       bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3));
-       bval &= 0x0F;
-
-       switch (bval) {
-       case 0:
-               dwRate = 44100;
-               break;
-       case 1:
-               dwRate = 48000;
-               break;
-       case 2:
-               dwRate = 32000;
-               break;
-       default:
-               // Error occurs
-               break;
-       }
-
-       return dwRate;
-
-}
-
-static int
-ali_close_multi_channels(void)
-{
-       char temp = 0;
-       struct pci_dev *pci_dev = NULL;
-
-       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_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, 0xB8, &temp);
-       temp &= ~0x20;
-       pci_write_config_byte(pci_dev, 0xB8, temp);
-
-       pci_dev_put(pci_dev);
-
-       return 0;
-}
-
-static int
-ali_setup_multi_channels(struct trident_card *card, int chan_nums)
-{
-       unsigned long dwValue;
-       char temp = 0;
-       struct pci_dev *pci_dev = NULL;
-
-       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_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));
-               mdelay(4);
-               dwValue = inl(TRID_REG(card, ALI_SCTRL));
-               if (dwValue & 0x2000000) {
-                       ali_ac97_write(card->ac97_codec[0], 0x02, 8080);
-                       ali_ac97_write(card->ac97_codec[0], 0x36, 0);
-                       ali_ac97_write(card->ac97_codec[0], 0x38, 0);
-                       /*
-                        *      On a board with a single codec you won't get the
-                        *      surround. On other boards configure it.
-                        */
-                       if (card->ac97_codec[1] != NULL) {
-                               ali_ac97_write(card->ac97_codec[1], 0x36, 0);
-                               ali_ac97_write(card->ac97_codec[1], 0x38, 0);
-                               ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606);
-                               ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303);
-                               ali_ac97_write(card->ac97_codec[1], 0x74, 0x3);
-                       }
-                       return 1;
-               }
-       }
-       return -EINVAL;
-}
-
-static void
-ali_free_pcm_channel(struct trident_card *card, unsigned int channel)
-{
-       int bank;
-
-       if (channel > 31)
-               return;
-
-       bank = channel >> 5;
-       channel = channel & 0x1f;
-
-       card->banks[bank].bitmap &= ~(1 << (channel));
-}
-
-static int
-ali_allocate_other_states_resources(struct trident_state *state, int chan_nums)
-{
-       struct trident_card *card = state->card;
-       struct trident_state *s;
-       int i, state_count = 0;
-       struct trident_pcm_bank *bank;
-       struct trident_channel *channel;
-       unsigned long num;
-
-       bank = &card->banks[BANK_A];
-
-       if (chan_nums != 6)
-               return 0;
-
-       for (i = 0; (i < ALI_CHANNELS) && (state_count != 4); i++) {
-               if (card->states[i])
-                       continue;
-
-               num = ali_multi_channels_5_1[state_count];
-               if (!(bank->bitmap & (1 << num))) {
-                       bank->bitmap |= 1 << num;
-                       channel = &bank->channels[num];
-                       channel->num = num;
-               } else {
-                       state_count--;
-                       for (; state_count >= 0; state_count--) {
-                               kfree(state->other_states[state_count]);
-                               num = ali_multi_channels_5_1[state_count];
-                                       ali_free_pcm_channel(card, num);
-                       }
-                       return -EBUSY;
-               }
-               s = card->states[i] = kzalloc(sizeof(*state), GFP_KERNEL);
-               if (!s) {
-                       num = ali_multi_channels_5_1[state_count];
-                       ali_free_pcm_channel(card, num);
-                       state_count--;
-                       for (; state_count >= 0; state_count--) {
-                               num = ali_multi_channels_5_1[state_count];
-                               ali_free_pcm_channel(card, num);
-                               kfree(state->other_states[state_count]);
-                       }
-                       return -ENOMEM;
-               }
-
-               s->dmabuf.channel = channel;
-               s->dmabuf.ossfragshift = s->dmabuf.ossmaxfrags =
-                       s->dmabuf.subdivision = 0;
-               init_waitqueue_head(&s->dmabuf.wait);
-               s->magic = card->magic;
-               s->card = card;
-               s->virt = i;
-               ali_enable_special_channel(s);
-               state->other_states[state_count++] = s;
-       }
-
-       if (state_count != 4) {
-               state_count--;
-               for (; state_count >= 0; state_count--) {
-                       kfree(state->other_states[state_count]);
-                       num = ali_multi_channels_5_1[state_count];
-                       ali_free_pcm_channel(card, num);
-               }
-               return -EBUSY;
-       }
-       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)
-{
-       unsigned long flags;
-       int i, j;
-
-       spin_lock_irqsave(&card->lock, flags);
-
-       ali_registers.global_regs[0x2c] = inl(TRID_REG(card, T4D_MISCINT));
-       //ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A));
-       ali_registers.global_regs[0x21] = inl(TRID_REG(card, T4D_STOP_A));
-
-       //disable all IRQ bits
-       outl(ALI_DISABLE_ALL_IRQ, TRID_REG(card, T4D_MISCINT));
-
-       for (i = 1; i < ALI_MIXER_REGS; i++)
-               ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0],
-                                                           i * 2);
-
-       for (i = 0; i < ALI_GLOBAL_REGS; i++) {
-               if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A))
-                       continue;
-               ali_registers.global_regs[i] = inl(TRID_REG(card, i * 4));
-       }
-
-       for (i = 0; i < ALI_CHANNELS; i++) {
-               outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
-               for (j = 0; j < ALI_CHANNEL_REGS; j++)
-                       ali_registers.channel_regs[i][j] = inl(TRID_REG(card,
-                                                                       j * 4 + 0xe0));
-       }
-
-       //Stop all HW channel
-       outl(ALI_STOP_ALL_CHANNELS, TRID_REG(card, T4D_STOP_A));
-
-       spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static void
-ali_restore_regs(struct trident_card *card)
-{
-       unsigned long flags;
-       int i, j;
-
-       spin_lock_irqsave(&card->lock, flags);
-
-       for (i = 1; i < ALI_MIXER_REGS; i++)
-               ali_ac97_write(card->ac97_codec[0], i * 2,
-                              ali_registers.mixer_regs[i]);
-
-       for (i = 0; i < ALI_CHANNELS; i++) {
-               outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
-               for (j = 0; j < ALI_CHANNEL_REGS; j++)
-                       outl(ali_registers.channel_regs[i][j],
-                            TRID_REG(card, j * 4 + 0xe0));
-       }
-
-       for (i = 0; i < ALI_GLOBAL_REGS; i++) {
-               if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) ||
-                   (i * 4 == T4D_START_A))
-                       continue;
-               outl(ali_registers.global_regs[i], TRID_REG(card, i * 4));
-       }
-
-       //start HW channel
-       outl(ali_registers.global_regs[0x20], TRID_REG(card, T4D_START_A));
-       //restore IRQ enable bits
-       outl(ali_registers.global_regs[0x2c], TRID_REG(card, T4D_MISCINT));
-
-       spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static int
-trident_suspend(struct pci_dev *dev, pm_message_t unused)
-{
-       struct trident_card *card = pci_get_drvdata(dev);
-
-       if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-               ali_save_regs(card);
-       }
-       return 0;
-}
-
-static int
-trident_resume(struct pci_dev *dev)
-{
-       struct trident_card *card = pci_get_drvdata(dev);
-
-       if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-               ali_restore_regs(card);
-       }
-       return 0;
-}
-#endif
-
-static struct trident_channel *
-ali_alloc_pcm_channel(struct trident_card *card)
-{
-       struct trident_pcm_bank *bank;
-       int idx;
-
-       bank = &card->banks[BANK_A];
-
-       if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) &
-           (ALI_SPDIF_OUT_CH_ENABLE)) {
-               idx = ALI_SPDIF_OUT_CHANNEL;
-               if (!(bank->bitmap & (1 << idx))) {
-                       struct trident_channel *channel = &bank->channels[idx];
-                       bank->bitmap |= 1 << idx;
-                       channel->num = idx;
-                       return channel;
-               }
-       }
-
-       for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST;
-            idx++) {
-               if (!(bank->bitmap & (1 << idx))) {
-                       struct trident_channel *channel = &bank->channels[idx];
-                       bank->bitmap |= 1 << idx;
-                       channel->num = idx;
-                       return channel;
-               }
-       }
-
-       /* no more free channels avaliable */
-#if 0
-       printk(KERN_ERR "ali: no more channels available on Bank A.\n");
-#endif /* 0 */
-       return NULL;
-}
-
-static struct trident_channel *
-ali_alloc_rec_pcm_channel(struct trident_card *card)
-{
-       struct trident_pcm_bank *bank;
-       int idx;
-
-       if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_IN_SUPPORT)
-               idx = ALI_SPDIF_IN_CHANNEL;
-       else
-               idx = ALI_PCM_IN_CHANNEL;
-
-       bank = &card->banks[BANK_A];
-
-       if (!(bank->bitmap & (1 << idx))) {
-               struct trident_channel *channel = &bank->channels[idx];
-               bank->bitmap |= 1 << idx;
-               channel->num = idx;
-               return channel;
-       }
-
-       /* no free recordable channels avaliable */
-#if 0
-       printk(KERN_ERR "ali: no recordable channels available on Bank A.\n");
-#endif /* 0 */
-       return NULL;
-}
-
-static void
-ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate)
-{
-       unsigned char ch_st_sel;
-       unsigned short status_rate;
-
-       switch (rate) {
-       case 44100:
-               status_rate = 0;
-               break;
-       case 32000:
-               status_rate = 0x300;
-               break;
-       case 48000:
-       default:
-               status_rate = 0x200;
-               break;
-       }
-
-       /* select spdif_out */
-       ch_st_sel = inb(TRID_REG(card, ALI_SPDIF_CTRL)) & ALI_SPDIF_OUT_CH_STATUS;
-
-       ch_st_sel |= 0x80;      /* select right */
-       outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
-       outb(status_rate | 0x20, TRID_REG(card, ALI_SPDIF_CS + 2));
-
-       ch_st_sel &= (~0x80);   /* select left */
-       outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
-       outw(status_rate | 0x10, TRID_REG(card, ALI_SPDIF_CS + 2));
-}
-
-static void
-ali_address_interrupt(struct trident_card *card)
-{
-       int i, channel;
-       struct trident_state *state;
-       u32 mask, channel_mask;
-
-       mask = trident_get_interrupt_mask(card, 0);
-       for (i = 0; i < NR_HW_CH; i++) {
-               if ((state = card->states[i]) == NULL)
-                       continue;
-               channel = state->dmabuf.channel->num;
-               if ((channel_mask = 1 << channel) & mask) {
-                       mask &= ~channel_mask;
-                       trident_ack_channel_interrupt(card, channel);
-                       udelay(100);
-                       state->dmabuf.update_flag |= ALI_ADDRESS_INT_UPDATE;
-                       trident_update_ptr(state);
-               }
-       }
-       if (mask) {
-               for (i = 0; i < NR_HW_CH; i++) {
-                       if (mask & (1 << i)) {
-                               printk("ali: spurious channel irq %d.\n", i);
-                               trident_ack_channel_interrupt(card, i);
-                               trident_stop_voice(card, i);
-                               trident_disable_voice_irq(card, i);
-                       }
-               }
-       }
-}
-
-/* Updating the values of counters of other_states' DMAs without lock
-protection is no harm because all DMAs of multi-channels and interrupt
-depend on a master state's DMA, and changing the counters of the master
-state DMA is protected by a spinlock.
-*/
-static int
-ali_write_5_1(struct trident_state *state, const char __user *buf,
-             int cnt_for_multi_channel, unsigned int *copy_count,
-             unsigned int *state_cnt)
-{
-
-       struct dmabuf *dmabuf = &state->dmabuf;
-       struct dmabuf *dmabuf_temp;
-       const char __user *buffer = buf;
-       unsigned swptr, other_dma_nums, sample_s;
-       unsigned int i, loop;
-
-       other_dma_nums = 4;
-       sample_s = sample_size[dmabuf->fmt] >> 1;
-       swptr = dmabuf->swptr;
-
-       if ((i = state->multi_channels_adjust_count) > 0) {
-               if (i == 1) {
-                       if (copy_from_user(dmabuf->rawbuf + swptr,
-                                          buffer, sample_s))
-                               return -EFAULT;
-                       seek_offset(swptr, buffer, cnt_for_multi_channel,
-                                   sample_s, *copy_count);
-                       i--;
-                       (*state_cnt) += sample_s;
-                       state->multi_channels_adjust_count++;
-               } else
-                       i = i - (state->chans_num - other_dma_nums);
-               for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) {
-                       dmabuf_temp = &state->other_states[i]->dmabuf;
-                       if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
-                                          buffer, sample_s))
-                               return -EFAULT;
-                       seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
-                                   sample_s, *copy_count);
-               }
-               if (cnt_for_multi_channel == 0)
-                       state->multi_channels_adjust_count += i;
-       }
-       if (cnt_for_multi_channel > 0) {
-               loop = cnt_for_multi_channel / (state->chans_num * sample_s);
-               for (i = 0; i < loop; i++) {
-                       if (copy_from_user(dmabuf->rawbuf + swptr, buffer,
-                                          sample_s * 2))
-                               return -EFAULT;
-                       seek_offset(swptr, buffer, cnt_for_multi_channel,
-                                   sample_s * 2, *copy_count);
-                       (*state_cnt) += (sample_s * 2);
-
-                       dmabuf_temp = &state->other_states[0]->dmabuf;
-                       if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
-                                          buffer, sample_s))
-                               return -EFAULT;
-                       seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
-                                   sample_s, *copy_count);
-
-                       dmabuf_temp = &state->other_states[1]->dmabuf;
-                       if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
-                                          buffer, sample_s))
-                               return -EFAULT;
-                       seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
-                                   sample_s, *copy_count);
-
-                       dmabuf_temp = &state->other_states[2]->dmabuf;
-                       if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
-                                          buffer, sample_s))
-                               return -EFAULT;
-                       seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
-                                   sample_s, *copy_count);
-
-                       dmabuf_temp = &state->other_states[3]->dmabuf;
-                       if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
-                                          buffer, sample_s))
-                               return -EFAULT;
-                       seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
-                                   sample_s, *copy_count);
-               }
-
-               if (cnt_for_multi_channel > 0) {
-                       state->multi_channels_adjust_count = cnt_for_multi_channel / sample_s;
-
-                       if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s))
-                               return -EFAULT;
-                       seek_offset(swptr, buffer, cnt_for_multi_channel,
-                                   sample_s, *copy_count);
-                       (*state_cnt) += sample_s;
-
-                       if (cnt_for_multi_channel > 0) {
-                               if (copy_from_user(dmabuf->rawbuf + swptr,
-                                                  buffer, sample_s))
-                                       return -EFAULT;
-                               seek_offset(swptr, buffer, cnt_for_multi_channel,
-                                           sample_s, *copy_count);
-                               (*state_cnt) += sample_s;
-
-                               if (cnt_for_multi_channel > 0) {
-                                       int diff = state->chans_num - other_dma_nums;
-                                       loop = state->multi_channels_adjust_count - diff;
-                                       for (i = 0; i < loop; i++) {
-                                               dmabuf_temp = &state->other_states[i]->dmabuf;
-                                               if (copy_from_user(dmabuf_temp->rawbuf +
-                                                                  dmabuf_temp->swptr,
-                                                                  buffer, sample_s))
-                                                       return -EFAULT;
-                                               seek_offset(dmabuf_temp->swptr, buffer,
-                                                           cnt_for_multi_channel,
-                                                           sample_s, *copy_count);
-                                       }
-                               }
-                       }
-               } else
-                       state->multi_channels_adjust_count = 0;
-       }
-       for (i = 0; i < other_dma_nums; i++) {
-               dmabuf_temp = &state->other_states[i]->dmabuf;
-               dmabuf_temp->swptr = dmabuf_temp->swptr % dmabuf_temp->dmasize;
-       }
-       return *state_cnt;
-}
-
-static void
-ali_free_other_states_resources(struct trident_state *state)
-{
-       int i;
-       struct trident_card *card = state->card;
-       struct trident_state *s;
-       unsigned other_states_count;
-
-       other_states_count = state->chans_num - 2; /* except PCM L/R channels */
-       for (i = 0; i < other_states_count; i++) {
-               s = state->other_states[i];
-               dealloc_dmabuf(&s->dmabuf, card->pci_dev);
-               ali_disable_special_channel(s->card, s->dmabuf.channel->num);
-               state->card->free_pcm_channel(s->card, s->dmabuf.channel->num);
-               card->states[s->virt] = NULL;
-               kfree(s);
-       }
-}
-
-static struct proc_dir_entry *res;
-
-static int
-ali_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
-{
-       struct trident_card *card = (struct trident_card *) data;
-       unsigned long flags;
-       char c;
-
-       if (count < 0)
-               return -EINVAL;
-       if (count == 0)
-               return 0;
-       if (get_user(c, buffer))
-               return -EFAULT;
-
-       spin_lock_irqsave(&card->lock, flags);
-       switch (c) {
-       case '0':
-               ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
-               ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
-               break;
-       case '1':
-               ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
-                                   ALI_SPDIF_OUT_PCM);
-               break;
-       case '2':
-               ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
-                                   ALI_SPDIF_OUT_NON_PCM);
-               break;
-       case '3':
-               ali_disable_spdif_in(card);     //default
-               break;
-       case '4':
-               ali_setup_spdif_in(card);
-               break;
-       }
-       spin_unlock_irqrestore(&card->lock, flags);
-
-       return count;
-}
-
-/* OSS /dev/mixer file operation methods */
-static int
-trident_open_mixdev(struct inode *inode, struct file *file)
-{
-       int i = 0;
-       int minor = iminor(inode);
-       struct trident_card *card = devs;
-
-       for (card = devs; card != NULL; card = card->next)
-               for (i = 0; i < NR_AC97; i++)
-                       if (card->ac97_codec[i] != NULL &&
-                           card->ac97_codec[i]->dev_mixer == minor)
-                               goto match;
-
-       if (!card) {
-               return -ENODEV;
-       }
-      match:
-       file->private_data = card->ac97_codec[i];
-
-       return nonseekable_open(inode, file);
-}
-
-static int
-trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
-                    unsigned long arg)
-{
-       struct ac97_codec *codec = (struct ac97_codec *) file->private_data;
-
-       return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static const struct file_operations trident_mixer_fops = {
-       .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .ioctl = trident_ioctl_mixdev,
-       .open = trident_open_mixdev,
-};
-
-static int
-ali_reset_5451(struct trident_card *card)
-{
-       struct pci_dev *pci_dev = NULL;
-       unsigned int dwVal;
-       unsigned short wCount, wReg;
-
-       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_dword(pci_dev, 0x7c, &dwVal);
-       pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);
-       udelay(5000);
-       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)
-               return -1;
-
-       pci_read_config_dword(pci_dev, 0x44, &dwVal);
-       pci_write_config_dword(pci_dev, 0x44, dwVal | 0x000c0000);
-       udelay(500);
-       pci_read_config_dword(pci_dev, 0x44, &dwVal);
-       pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff);
-       udelay(5000);
-
-       /* TODO: recognize if we have a PM capable codec and only do this */
-       /* if the codec is PM capable */
-       wCount = 2000;
-       while (wCount--) {
-               wReg = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
-               if ((wReg & 0x000f) == 0x000f)
-                       return 0;
-               udelay(5000);
-       }
-       /* This is non fatal if you have a non PM capable codec.. */
-       return 0;
-}
-
-/* AC97 codec initialisation. */
-static int __devinit
-trident_ac97_init(struct trident_card *card)
-{
-       int num_ac97 = 0;
-       unsigned long ready_2nd = 0;
-       struct ac97_codec *codec;
-       int i = 0;
-
-       /* initialize controller side of AC link, and find out if secondary codes
-          really exist */
-       switch (card->pci_id) {
-       case PCI_DEVICE_ID_ALI_5451:
-               if (ali_reset_5451(card)) {
-                       printk(KERN_ERR "trident_ac97_init: error "
-                              "resetting 5451.\n");
-                       return -1;
-               }
-               outl(0x80000001, TRID_REG(card, ALI_GLOBAL_CONTROL));
-               outl(0x00000000, TRID_REG(card, T4D_AINTEN_A));
-               outl(0xffffffff, TRID_REG(card, T4D_AINT_A));
-               outl(0x00000000, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
-               outb(0x10, TRID_REG(card, ALI_MPUR2));
-               ready_2nd = inl(TRID_REG(card, ALI_SCTRL));
-               ready_2nd &= 0x3fff;
-               outl(ready_2nd | PCMOUT | 0x8000, TRID_REG(card, ALI_SCTRL));
-               ready_2nd = inl(TRID_REG(card, ALI_SCTRL));
-               ready_2nd &= SI_AC97_SECONDARY_READY;
-               if (card->revision < ALI_5451_V02)
-                       ready_2nd = 0;
-               break;
-       case PCI_DEVICE_ID_SI_7018:
-               /* disable AC97 GPIO interrupt */
-               outl(0x00, TRID_REG(card, SI_AC97_GPIO));
-               /* when power up the AC link is in cold reset mode so stop it */
-               outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID,
-                    TRID_REG(card, SI_SERIAL_INTF_CTRL));
-               /* it take a long time to recover from a cold reset */
-               /* (especially when you have more than one codec) */
-               udelay(2000);
-               ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
-               ready_2nd &= SI_AC97_SECONDARY_READY;
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
-               /* playback on */
-               outl(DX_AC97_PLAYBACK, TRID_REG(card, DX_ACR2_AC97_COM_STAT));
-               break;
-       case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
-               /* enable AC97 Output Slot 3,4 (PCM Left/Right Playback) */
-               outl(NX_AC97_PCM_OUTPUT, TRID_REG(card, NX_ACR0_AC97_COM_STAT));
-               ready_2nd = inl(TRID_REG(card, NX_ACR0_AC97_COM_STAT));
-               ready_2nd &= NX_AC97_SECONDARY_READY;
-               break;
-       case PCI_DEVICE_ID_INTERG_5050:
-               /* disable AC97 GPIO interrupt */
-               outl(0x00, TRID_REG(card, SI_AC97_GPIO));
-               /* when power up, the AC link is in cold reset mode, so stop it */
-               outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT,
-                    TRID_REG(card, SI_SERIAL_INTF_CTRL));
-               /* it take a long time to recover from a cold reset (especially */
-               /* when you have more than one codec) */
-               udelay(2000);
-               ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
-               ready_2nd &= SI_AC97_SECONDARY_READY;
-               break;
-       }
-
-       for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
-               if ((codec = ac97_alloc_codec()) == NULL)
-                       return -ENOMEM;
-
-               /* initialize some basic codec information, other fields */
-               /* will be filled in ac97_probe_codec */
-               codec->private_data = card;
-               codec->id = num_ac97;
-
-               if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-                       codec->codec_read = ali_ac97_read;
-                       codec->codec_write = ali_ac97_write;
-               } else {
-                       codec->codec_read = trident_ac97_get;
-                       codec->codec_write = trident_ac97_set;
-               }
-
-               if (ac97_probe_codec(codec) == 0)
-                       break;
-
-               codec->dev_mixer = register_sound_mixer(&trident_mixer_fops, -1);
-               if (codec->dev_mixer < 0) {
-                       printk(KERN_ERR "trident: couldn't register mixer!\n");
-                       ac97_release_codec(codec);
-                       break;
-               }
-
-               card->ac97_codec[num_ac97] = codec;
-
-               /* if there is no secondary codec at all, don't probe any more */
-               if (!ready_2nd)
-                       break;
-       }
-
-       if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-               for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
-                       if (card->ac97_codec[num_ac97] == NULL)
-                               break;
-                       for (i = 0; i < 64; i++) {
-                               u16 reg = ali_ac97_get(card, num_ac97, i * 2);
-                               card->mixer_regs[i][num_ac97] = reg;
-                       }
-               }
-       }
-       return num_ac97 + 1;
-}
-
-#ifdef SUPPORT_JOYSTICK
-/* Gameport functions for the cards ADC gameport */
-
-static unsigned char trident_game_read(struct gameport *gameport)
-{
-       struct trident_card *card = gameport->port_data;
-
-       return inb(TRID_REG(card, T4D_GAME_LEG));
-}
-
-static void trident_game_trigger(struct gameport *gameport)
-{
-       struct trident_card *card = gameport->port_data;
-
-       outb(0xff, TRID_REG(card, T4D_GAME_LEG));
-}
-
-static int trident_game_cooked_read(struct gameport *gameport,
-                                   int *axes, int *buttons)
-{
-       struct trident_card *card = gameport->port_data;
-       int i;
-
-       *buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf;
-
-       for (i = 0; i < 4; i++) {
-               axes[i] = inw(TRID_REG(card, T4D_GAME_AXD) + i * sizeof (u16));
-               if (axes[i] == 0xffff)
-                       axes[i] = -1;
-       }
-
-       return 0;
-}
-
-static int trident_game_open(struct gameport *gameport, int mode)
-{
-       struct trident_card *card = gameport->port_data;
-
-       switch (mode) {
-       case GAMEPORT_MODE_COOKED:
-               outb(0x80, TRID_REG(card, T4D_GAME_CR));
-               msleep(20);
-               return 0;
-       case GAMEPORT_MODE_RAW:
-               outb(0x00, TRID_REG(card, T4D_GAME_CR));
-               return 0;
-       default:
-               return -1;
-       }
-
-       return 0;
-}
-
-static int __devinit trident_register_gameport(struct trident_card *card)
-{
-       struct gameport *gp;
-
-       card->gameport = gp = gameport_allocate_port();
-       if (!gp) {
-               printk(KERN_ERR "trident: can not allocate memory for gameport\n");
-               return -ENOMEM;
-       }
-
-       gameport_set_name(gp, "Trident 4DWave");
-       gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev));
-       gp->read = trident_game_read;
-       gp->trigger = trident_game_trigger;
-       gp->cooked_read = trident_game_cooked_read;
-       gp->open = trident_game_open;
-       gp->fuzz = 64;
-       gp->port_data = card;
-
-       gameport_register_port(gp);
-
-       return 0;
-}
-
-static inline void trident_unregister_gameport(struct trident_card *card)
-{
-       if (card->gameport)
-               gameport_unregister_port(card->gameport);
-}
-
-#else
-static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; }
-static inline void trident_unregister_gameport(struct trident_card *card) { }
-#endif /* SUPPORT_JOYSTICK */
-
-/* install the driver, we do not allocate hardware channel nor DMA buffer */
-/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */
-/* open/read/write/ioctl/mmap) */
-static int __devinit
-trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
-{
-       unsigned long iobase;
-       struct trident_card *card;
-       u8 bits;
-       u8 revision;
-       int i = 0;
-       u16 temp;
-       struct pci_dev *pci_dev_m1533 = NULL;
-       int rc = -ENODEV;
-       u64 dma_mask;
-
-       if (pci_enable_device(pci_dev))
-               goto out;
-
-       if (pci_dev->device == PCI_DEVICE_ID_ALI_5451)
-               dma_mask = ALI_DMA_MASK;
-       else
-               dma_mask = TRIDENT_DMA_MASK;
-       if (pci_set_dma_mask(pci_dev, dma_mask)) {
-               printk(KERN_ERR "trident: architecture does not support"
-                      " %s PCI busmaster DMA\n",
-                      pci_dev->device == PCI_DEVICE_ID_ALI_5451 ?
-                      "32-bit" : "30-bit");
-               goto out;
-       }
-       pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
-
-       if (pci_id->device == PCI_DEVICE_ID_INTERG_5050)
-               iobase = pci_resource_start(pci_dev, 1);
-       else
-               iobase = pci_resource_start(pci_dev, 0);
-
-       if (!request_region(iobase, 256, card_names[pci_id->driver_data])) {
-               printk(KERN_ERR "trident: can't allocate I/O space at "
-                      "0x%4.4lx\n", iobase);
-               goto out;
-       }
-
-       rc = -ENOMEM;
-       if ((card = kzalloc(sizeof(*card), GFP_KERNEL)) == NULL) {
-               printk(KERN_ERR "trident: out of memory\n");
-               goto out_release_region;
-       }
-
-       init_timer(&card->timer);
-       card->iobase = iobase;
-       card->pci_dev = pci_dev_get(pci_dev);
-       card->pci_id = pci_id->device;
-       card->revision = revision;
-       card->irq = pci_dev->irq;
-       card->next = devs;
-       card->magic = TRIDENT_CARD_MAGIC;
-       card->banks[BANK_A].addresses = &bank_a_addrs;
-       card->banks[BANK_A].bitmap = 0UL;
-       card->banks[BANK_B].addresses = &bank_b_addrs;
-       card->banks[BANK_B].bitmap = 0UL;
-
-       mutex_init(&card->open_mutex);
-       spin_lock_init(&card->lock);
-       init_timer(&card->timer);
-
-       devs = card;
-
-       pci_set_master(pci_dev);
-
-       printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
-              card_names[pci_id->driver_data], card->iobase, card->irq);
-
-       if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-               /* ALi channel Management */
-               card->alloc_pcm_channel = ali_alloc_pcm_channel;
-               card->alloc_rec_pcm_channel = ali_alloc_rec_pcm_channel;
-               card->free_pcm_channel = ali_free_pcm_channel;
-
-               card->address_interrupt = ali_address_interrupt;
-
-               /* Added by Matt Wu 01-05-2001 for spdif in */
-               card->multi_channel_use_count = 0;
-               card->rec_channel_use_count = 0;
-
-               /* ALi SPDIF OUT function */
-               if (card->revision == ALI_5451_V02) {
-                       ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
-                       res = create_proc_entry("ALi5451", 0, NULL);
-                       if (res) {
-                               res->write_proc = ali_write_proc;
-                               res->data = card;
-                       }
-               }
-
-               /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
-               card->hwvolctl = 0;
-               pci_dev_m1533 = pci_get_device(PCI_VENDOR_ID_AL,
-                                              PCI_DEVICE_ID_AL_M1533,
-                                              pci_dev_m1533);
-               rc = -ENODEV;
-               if (pci_dev_m1533 == NULL)
-                       goto out_proc_fs;
-               pci_read_config_byte(pci_dev_m1533, 0x63, &bits);
-               if (bits & (1 << 5))
-                       card->hwvolctl = 1;
-               if (card->hwvolctl) {
-                       /* Clear m1533 pci cfg 78h bit 30 to zero, which makes
-                          GPIO11/12/13 work as ACGP_UP/DOWN/MUTE. */
-                       pci_read_config_byte(pci_dev_m1533, 0x7b, &bits);
-                       bits &= 0xbf;   /*clear bit 6 */
-                       pci_write_config_byte(pci_dev_m1533, 0x7b, bits);
-               }
-               pci_dev_put(pci_dev_m1533);
-
-       } else if (card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
-               card->alloc_pcm_channel = cyber_alloc_pcm_channel;
-               card->alloc_rec_pcm_channel = cyber_alloc_pcm_channel;
-               card->free_pcm_channel = cyber_free_pcm_channel;
-               card->address_interrupt = cyber_address_interrupt;
-               cyber_init_ritual(card);
-       } else {
-               card->alloc_pcm_channel = trident_alloc_pcm_channel;
-               card->alloc_rec_pcm_channel = trident_alloc_pcm_channel;
-               card->free_pcm_channel = trident_free_pcm_channel;
-               card->address_interrupt = trident_address_interrupt;
-       }
-
-       /* claim our irq */
-       rc = -ENODEV;
-       if (request_irq(card->irq, &trident_interrupt, IRQF_SHARED,
-                       card_names[pci_id->driver_data], card)) {
-               printk(KERN_ERR "trident: unable to allocate irq %d\n",
-                      card->irq);
-               goto out_proc_fs;
-       }
-       /* register /dev/dsp */
-       if ((card->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0) {
-               printk(KERN_ERR "trident: couldn't register DSP device!\n");
-               goto out_free_irq;
-       }
-       card->mixer_regs_ready = 0;
-       /* initialize AC97 codec and register /dev/mixer */
-       if (trident_ac97_init(card) <= 0) {
-               /* unregister audio devices */
-               for (i = 0; i < NR_AC97; i++) {
-                       if (card->ac97_codec[i] != NULL) {
-                               struct ac97_codec* codec = card->ac97_codec[i];
-                               unregister_sound_mixer(codec->dev_mixer);
-                               ac97_release_codec(codec);
-                       }
-               }
-               goto out_unregister_sound_dsp;
-       }
-       card->mixer_regs_ready = 1;
-       outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
-
-       if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-               /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
-               if (card->hwvolctl) {
-                       /* Enable GPIO IRQ (MISCINT bit 18h) */
-                       temp = inw(TRID_REG(card, T4D_MISCINT + 2));
-                       temp |= 0x0004;
-                       outw(temp, TRID_REG(card, T4D_MISCINT + 2));
-
-                       /* Enable H/W Volume Control GLOVAL CONTROL bit 0 */
-                       temp = inw(TRID_REG(card, ALI_GLOBAL_CONTROL));
-                       temp |= 0x0001;
-                       outw(temp, TRID_REG(card, ALI_GLOBAL_CONTROL));
-
-               }
-               if (card->revision == ALI_5451_V02)
-                       ali_close_multi_channels();
-               /* edited by HMSEO for GT sound */
-#if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC)
-               {
-                       u16 ac97_data;
-                       extern struct hwrpb_struct *hwrpb;
-
-                       if ((hwrpb->sys_type) == 201) {
-                               printk(KERN_INFO "trident: Running on Alpha system "
-                                      "type Nautilus\n");
-                               ac97_data = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
-                               ali_ac97_set(card, 0, AC97_POWER_CONTROL,
-                                            ac97_data | ALI_EAPD_POWER_DOWN);
-                       }
-               }
-#endif                         /* CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC */
-               /* edited by HMSEO for GT sound */
-       }
-       rc = 0;
-       pci_set_drvdata(pci_dev, card);
-
-       /* Enable Address Engine Interrupts */
-       trident_enable_loop_interrupts(card);
-
-       /* Register gameport */
-       trident_register_gameport(card);
-
-out:
-       return rc;
-
-out_unregister_sound_dsp:
-       unregister_sound_dsp(card->dev_audio);
-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;
-       }
-       kfree(card);
-       devs = NULL;
-out_release_region:
-       release_region(iobase, 256);
-       return rc;
-}
-
-static void __devexit
-trident_remove(struct pci_dev *pci_dev)
-{
-       int i;
-       struct trident_card *card = pci_get_drvdata(pci_dev);
-
-       /*
-        *      Kill running timers before unload. We can't have them
-        *      going off after rmmod!
-        */
-       if (card->hwvolctl)
-               del_timer_sync(&card->timer);
-
-       /* ALi S/PDIF and Power Management */
-       if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-               ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
-               ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
-               ali_disable_spdif_in(card);
-               remove_proc_entry("ALi5451", NULL);
-       }
-
-       /* Unregister gameport */
-       trident_unregister_gameport(card);
-
-       /* Kill interrupts, and SP/DIF */
-       trident_disable_loop_interrupts(card);
-
-       /* free hardware resources */
-       free_irq(card->irq, card);
-       release_region(card->iobase, 256);
-
-       /* unregister audio devices */
-       for (i = 0; i < NR_AC97; i++)
-               if (card->ac97_codec[i] != NULL) {
-                       unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
-                       ac97_release_codec(card->ac97_codec[i]);
-               }
-       unregister_sound_dsp(card->dev_audio);
-
-       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");
-MODULE_DESCRIPTION("Trident 4DWave/SiS 7018/ALi 5451 and Tvia/IGST CyberPro5050 PCI "
-                  "Audio Driver");
-MODULE_LICENSE("GPL");
-
-#define TRIDENT_MODULE_NAME "trident"
-
-static struct pci_driver trident_pci_driver = {
-       .name = TRIDENT_MODULE_NAME,
-       .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
-trident_init_module(void)
-{
-       printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro "
-              "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " "
-              __DATE__ "\n");
-
-       return pci_register_driver(&trident_pci_driver);
-}
-
-static void __exit
-trident_cleanup_module(void)
-{
-       pci_unregister_driver(&trident_pci_driver);
-}
-
-module_init(trident_init_module);
-module_exit(trident_cleanup_module);
diff --git a/sound/oss/trident.h b/sound/oss/trident.h
deleted file mode 100644 (file)
index ff30a1d..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-#ifndef __TRID4DWAVE_H
-#define __TRID4DWAVE_H
-
-/*
- *  audio@tridentmicro.com
- *  Fri Feb 19 15:55:28 MST 1999
- *  Definitions for Trident 4DWave DX/NX chips
- *
- *
- *   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.
- *
- */
-
-/* PCI vendor and device ID */ 
-#ifndef PCI_VENDOR_ID_TRIDENT
-#define PCI_VENDOR_ID_TRIDENT          0x1023
-#endif
-
-#ifndef PCI_VENDOR_ID_SI
-#define PCI_VENDOR_ID_SI                       0x1039
-#endif
-
-#ifndef PCI_VENDOR_ID_ALI
-#define PCI_VENDOR_ID_ALI                      0x10b9
-#endif
-
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_DX
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX        0x2000
-#endif
-
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_NX
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX        0x2001
-#endif
-
-#ifndef PCI_DEVICE_ID_SI_7018
-#define PCI_DEVICE_ID_SI_7018          0x7018
-#endif
-
-#ifndef PCI_DEVICE_ID_ALI_5451
-#define PCI_DEVICE_ID_ALI_5451         0x5451
-#endif
-
-#ifndef PCI_DEVICE_ID_ALI_1533
-#define PCI_DEVICE_ID_ALI_1533         0x1533
-#endif
-
-#define CHANNEL_REGS   5
-#define CHANNEL_START  0xe0   // The first bytes of the contiguous register space.
-
-#define BANK_A                 0
-#define BANK_B                 1
-#define NR_BANKS               2
-
-#define TRIDENT_FMT_STEREO     0x01
-#define TRIDENT_FMT_16BIT      0x02
-#define TRIDENT_FMT_MASK       0x03
-
-#define DAC_RUNNING    0x01
-#define ADC_RUNNING    0x02
-
-/* Register Addresses */
-
-/* operational registers common to DX, NX, 7018 */
-enum trident_op_registers {
-       T4D_GAME_CR     = 0x30, T4D_GAME_LEG    = 0x31,
-       T4D_GAME_AXD    = 0x34,
-       T4D_REC_CH      = 0x70,
-       T4D_START_A     = 0x80, T4D_STOP_A      = 0x84,
-       T4D_DLY_A       = 0x88, T4D_SIGN_CSO_A  = 0x8c,
-       T4D_CSPF_A      = 0x90, T4D_CEBC_A      = 0x94,
-       T4D_AINT_A      = 0x98, T4D_EINT_A      = 0x9c,
-       T4D_LFO_GC_CIR  = 0xa0, T4D_AINTEN_A    = 0xa4,
-       T4D_MUSICVOL_WAVEVOL = 0xa8, T4D_SBDELTA_DELTA_R = 0xac,
-       T4D_MISCINT     = 0xb0, T4D_START_B     = 0xb4,
-       T4D_STOP_B      = 0xb8, T4D_CSPF_B      = 0xbc,
-       T4D_SBBL_SBCL   = 0xc0, T4D_SBCTRL_SBE2R_SBDD    = 0xc4,
-       T4D_STIMER      = 0xc8, T4D_LFO_B_I2S_DELTA      = 0xcc,
-       T4D_AINT_B      = 0xd8, T4D_AINTEN_B    = 0xdc,
-       ALI_MPUR2       = 0x22, ALI_GPIO        = 0x7c,
-       ALI_EBUF1 = 0xf4,
-       ALI_EBUF2 = 0xf8
-};
-
-enum ali_op_registers {
-       ALI_SCTRL               = 0x48,
-       ALI_GLOBAL_CONTROL      = 0xd4,
-       ALI_STIMER              = 0xc8,
-       ALI_SPDIF_CS            = 0x70,
-       ALI_SPDIF_CTRL          = 0x74
-};
-
-enum ali_registers_number {
-       ALI_GLOBAL_REGS         = 56,
-       ALI_CHANNEL_REGS        = 8,
-       ALI_MIXER_REGS          = 20
-};
-
-enum ali_sctrl_control_bit {
-       ALI_SPDIF_OUT_ENABLE    = 0x20
-};
-
-enum ali_global_control_bit {
-       ALI_SPDIF_OUT_SEL_PCM   = 0x00000400,
-       ALI_SPDIF_IN_SUPPORT    = 0x00000800,
-       ALI_SPDIF_OUT_CH_ENABLE = 0x00008000,
-       ALI_SPDIF_IN_CH_ENABLE  = 0x00080000,
-       ALI_PCM_IN_DISABLE      = 0x7fffffff,
-       ALI_PCM_IN_ENABLE       = 0x80000000,
-       ALI_SPDIF_IN_CH_DISABLE = 0xfff7ffff,
-       ALI_SPDIF_OUT_CH_DISABLE = 0xffff7fff,
-       ALI_SPDIF_OUT_SEL_SPDIF = 0xfffffbff
-       
-};
-
-enum ali_spdif_control_bit {
-       ALI_SPDIF_IN_FUNC_ENABLE        = 0x02,
-       ALI_SPDIF_IN_CH_STATUS          = 0x40,
-       ALI_SPDIF_OUT_CH_STATUS         = 0xbf
-       
-};
-
-enum ali_control_all {
-       ALI_DISABLE_ALL_IRQ     = 0,
-       ALI_CHANNELS            = 32,
-       ALI_STOP_ALL_CHANNELS   = 0xffffffff,
-       ALI_MULTI_CHANNELS_START_STOP   = 0x07800000
-};
-
-enum ali_EMOD_control_bit {
-       ALI_EMOD_DEC    = 0x00000000,
-       ALI_EMOD_INC    = 0x10000000,
-       ALI_EMOD_Delay  = 0x20000000,
-       ALI_EMOD_Still  = 0x30000000
-};
-
-enum ali_pcm_in_channel_num {
-       ALI_NORMAL_CHANNEL      = 0,
-       ALI_SPDIF_OUT_CHANNEL   = 15,
-       ALI_SPDIF_IN_CHANNEL    = 19,
-       ALI_LEF_CHANNEL         = 23,
-       ALI_CENTER_CHANNEL      = 24,
-       ALI_SURR_RIGHT_CHANNEL  = 25,
-       ALI_SURR_LEFT_CHANNEL   = 26,
-       ALI_PCM_IN_CHANNEL      = 31
-};
-
-enum ali_pcm_out_channel_num {
-       ALI_PCM_OUT_CHANNEL_FIRST = 0,
-       ALI_PCM_OUT_CHANNEL_LAST = 31
-};
-
-enum ali_ac97_power_control_bit {
-       ALI_EAPD_POWER_DOWN     = 0x8000
-};
-
-enum ali_update_ptr_flags {
-       ALI_ADDRESS_INT_UPDATE  = 0x01
-};
-
-enum ali_revision {
-       ALI_5451_V02    = 0x02
-};
-
-enum ali_spdif_out_control {
-       ALI_PCM_TO_SPDIF_OUT            = 0,
-       ALI_SPDIF_OUT_TO_SPDIF_OUT      = 1,
-       ALI_SPDIF_OUT_PCM               = 0,
-       ALI_SPDIF_OUT_NON_PCM           = 2
-};
-
-/* S/PDIF Operational Registers for 4D-NX */
-enum nx_spdif_registers {
-       NX_SPCTRL_SPCSO = 0x24, NX_SPLBA = 0x28,
-       NX_SPESO        = 0x2c, NX_SPCSTATUS = 0x64
-};
-
-/* OP registers to access each hardware channel */
-enum channel_registers {
-       CH_DX_CSO_ALPHA_FMS = 0xe0, CH_DX_ESO_DELTA = 0xe8,
-       CH_DX_FMC_RVOL_CVOL = 0xec,
-       CH_NX_DELTA_CSO     = 0xe0, CH_NX_DELTA_ESO = 0xe8,
-       CH_NX_ALPHA_FMS_FMC_RVOL_CVOL = 0xec,
-       CH_LBA              = 0xe4,
-       CH_GVSEL_PAN_VOL_CTRL_EC      = 0xf0
-};
-
-/* registers to read/write/control AC97 codec */
-enum dx_ac97_registers {
-       DX_ACR0_AC97_W        = 0x40, DX_ACR1_AC97_R = 0x44,
-       DX_ACR2_AC97_COM_STAT = 0x48
-};
-
-enum nx_ac97_registers {
-       NX_ACR0_AC97_COM_STAT  = 0x40, NX_ACR1_AC97_W           = 0x44,
-       NX_ACR2_AC97_R_PRIMARY = 0x48, NX_ACR3_AC97_R_SECONDARY = 0x4c
-};
-
-enum si_ac97_registers {
-       SI_AC97_WRITE       = 0x40, SI_AC97_READ = 0x44,
-       SI_SERIAL_INTF_CTRL = 0x48, SI_AC97_GPIO = 0x4c
-};
-
-enum ali_ac97_registers {
-       ALI_AC97_WRITE       = 0x40, ALI_AC97_READ = 0x44
-};
-
-/* Bit mask for operational registers */
-#define AC97_REG_ADDR      0x000000ff
-
-enum ali_ac97_bits {
-       ALI_AC97_BUSY_WRITE = 0x8000, ALI_AC97_BUSY_READ = 0x8000,
-       ALI_AC97_WRITE_ACTION = 0x8000, ALI_AC97_READ_ACTION = 0x8000,
-       ALI_AC97_AUDIO_BUSY = 0x4000, ALI_AC97_SECONDARY  = 0x0080,
-       ALI_AC97_READ_MIXER_REGISTER = 0xfeff,
-       ALI_AC97_WRITE_MIXER_REGISTER = 0x0100
-};
-
-enum sis7018_ac97_bits {
-       SI_AC97_BUSY_WRITE = 0x8000, SI_AC97_BUSY_READ = 0x8000,
-       SI_AC97_AUDIO_BUSY = 0x4000, SI_AC97_MODEM_BUSY = 0x2000,
-       SI_AC97_SECONDARY  = 0x0080
-};
-
-enum trident_dx_ac97_bits {
-       DX_AC97_BUSY_WRITE = 0x8000, DX_AC97_BUSY_READ = 0x8000,
-       DX_AC97_READY      = 0x0010, DX_AC97_RECORD    = 0x0008,
-       DX_AC97_PLAYBACK   = 0x0002
-};
-
-enum trident_nx_ac97_bits {
-       /* ACR1-3 */
-       NX_AC97_BUSY_WRITE = 0x0800, NX_AC97_BUSY_READ = 0x0800,
-       NX_AC97_BUSY_DATA  = 0x0400, NX_AC97_WRITE_SECONDARY = 0x0100,
-       /* ACR0 */
-       NX_AC97_SECONDARY_READY = 0x0040, NX_AC97_SECONDARY_RECORD = 0x0020,
-       NX_AC97_SURROUND_OUTPUT = 0x0010,
-       NX_AC97_PRIMARY_READY   = 0x0008, NX_AC97_PRIMARY_RECORD   = 0x0004,
-       NX_AC97_PCM_OUTPUT      = 0x0002,
-       NX_AC97_WARM_RESET      = 0x0001
-};
-
-enum serial_intf_ctrl_bits {
-       WARM_REST   = 0x00000001, COLD_RESET  = 0x00000002,
-       I2S_CLOCK   = 0x00000004, PCM_SEC_AC97= 0x00000008,
-       AC97_DBL_RATE = 0x00000010, SPDIF_EN  = 0x00000020,
-       I2S_OUTPUT_EN = 0x00000040, I2S_INPUT_EN = 0x00000080,
-       PCMIN       = 0x00000100, LINE1IN     = 0x00000200,
-       MICIN       = 0x00000400, LINE2IN     = 0x00000800,
-       HEAD_SET_IN = 0x00001000, GPIOIN      = 0x00002000,
-       /* 7018 spec says id = 01 but the demo board routed to 10 
-          SECONDARY_ID= 0x00004000, */
-       SECONDARY_ID= 0x00004000,
-       PCMOUT      = 0x00010000, SURROUT     = 0x00020000,
-       CENTEROUT   = 0x00040000, LFEOUT      = 0x00080000,
-       LINE1OUT    = 0x00100000, LINE2OUT    = 0x00200000,
-       GPIOOUT     = 0x00400000,
-       SI_AC97_PRIMARY_READY   = 0x01000000,
-       SI_AC97_SECONDARY_READY = 0x02000000,
-};
-
-enum global_control_bits {
-       CHANNLE_IDX = 0x0000003f, PB_RESET    = 0x00000100,
-       PAUSE_ENG   = 0x00000200,
-       OVERRUN_IE  = 0x00000400, UNDERRUN_IE = 0x00000800,
-       ENDLP_IE    = 0x00001000, MIDLP_IE    = 0x00002000,
-       ETOG_IE     = 0x00004000,
-       EDROP_IE    = 0x00008000, BANK_B_EN   = 0x00010000
-};
-
-enum channel_control_bits {
-       CHANNEL_LOOP   = 0x00001000, CHANNEL_SIGNED = 0x00002000,
-       CHANNEL_STEREO = 0x00004000, CHANNEL_16BITS = 0x00008000,
-};
-
-enum channel_attribute {
-       /* playback/record select */
-       CHANNEL_PB     = 0x0000, CHANNEL_SPC_PB = 0x4000,
-       CHANNEL_REC    = 0x8000, CHANNEL_REC_PB = 0xc000,
-       /* playback destination/record source select */
-       MODEM_LINE1    = 0x0000, MODEM_LINE2    = 0x0400,
-       PCM_LR         = 0x0800, HSET           = 0x0c00,
-       I2S_LR         = 0x1000, CENTER_LFE     = 0x1400,
-       SURR_LR        = 0x1800, SPDIF_LR       = 0x1c00,
-       MIC            = 0x1400,
-       /* mist stuff */
-       MONO_LEFT      = 0x0000, MONO_RIGHT     = 0x0100,
-       MONO_MIX       = 0x0200, SRC_ENABLE     = 0x0080,
-};
-
-enum miscint_bits {
-       PB_UNDERRUN_IRO = 0x00000001, REC_OVERRUN_IRQ = 0x00000002,
-       SB_IRQ          = 0x00000004, MPU401_IRQ      = 0x00000008,
-       OPL3_IRQ        = 0x00000010, ADDRESS_IRQ     = 0x00000020,
-       ENVELOPE_IRQ    = 0x00000040, ST_IRQ          = 0x00000080,
-       PB_UNDERRUN     = 0x00000100, REC_OVERRUN     = 0x00000200,
-       MIXER_UNDERFLOW = 0x00000400, MIXER_OVERFLOW  = 0x00000800,
-       ST_TARGET_REACHED = 0x00008000, PB_24K_MODE   = 0x00010000, 
-       ST_IRQ_EN       = 0x00800000, ACGPIO_IRQ      = 0x01000000
-};
-
-#define TRID_REG( trident, x ) ( (trident) -> iobase + (x) )
-
-#define                CYBER_PORT_AUDIO                0x3CE
-#define                CYBER_IDX_AUDIO_ENABLE          0x7B
-#define                CYBER_BMSK_AUDIO_INT_ENABLE     0x09
-#define                CYBER_BMSK_AUENZ                0x01
-#define                CYBER_BMSK_AUENZ_ENABLE         0x00
-#define                CYBER_IDX_IRQ_ENABLE            0x12
-      
-#define VALIDATE_MAGIC(FOO,MAG)                                \
-({                                                     \
-       if (!(FOO) || (FOO)->magic != MAG) {            \
-               printk(invalid_magic,__func__); \
-               return -ENXIO;                          \
-       }                                               \
-})
-
-#define VALIDATE_STATE(a) VALIDATE_MAGIC(a,TRIDENT_STATE_MAGIC)
-#define VALIDATE_CARD(a) VALIDATE_MAGIC(a,TRIDENT_CARD_MAGIC)
-
-static inline unsigned ld2(unsigned int x)
-{
-       unsigned r = 0;
-       
-       if (x >= 0x10000) {
-               x >>= 16;
-               r += 16;
-       }
-       if (x >= 0x100) {
-               x >>= 8;
-               r += 8;
-       }
-       if (x >= 0x10) {
-               x >>= 4;
-               r += 4;
-       }
-       if (x >= 4) {
-               x >>= 2;
-               r += 2;
-       }
-       if (x >= 2)
-               r++;
-       return r;
-}
-
-#endif /* __TRID4DWAVE_H */
index 07364c00768a4dd90f8eceeb338d899955a17685..8c49a00a5e3919d835b3f5d3a6fe0569eafda80d 100644 (file)
@@ -161,6 +161,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
 { 0x50534304, 0xffffffff, "UCB1400",           patch_ucb1400,  NULL },
 { 0x53494c20, 0xffffffe0, "Si3036,8",          mpatch_si3036,  mpatch_si3036, AC97_MODEM_PATCH },
 { 0x54524102, 0xffffffff, "TR28022",           NULL,           NULL },
+{ 0x54524103, 0xffffffff, "TR28023",           NULL,           NULL },
 { 0x54524106, 0xffffffff, "TR28026",           NULL,           NULL },
 { 0x54524108, 0xffffffff, "TR28028",           patch_tritech_tr28028,  NULL }, // added by xin jin [07/09/99]
 { 0x54524123, 0xffffffff, "TR28602",           NULL,           NULL }, // only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
@@ -169,7 +170,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
 { 0x56494170, 0xffffffff, "VIA1617A",          patch_vt1617a,  NULL }, // modified VT1616 with S/PDIF
 { 0x56494182, 0xffffffff, "VIA1618",           NULL,           NULL },
 { 0x57454301, 0xffffffff, "W83971D",           NULL,           NULL },
-{ 0x574d4c00, 0xffffffff, "WM9701A",           NULL,           NULL },
+{ 0x574d4c00, 0xffffffff, "WM9701,WM9701A",    NULL,           NULL },
 { 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
 { 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q",   patch_wolfson04, NULL},
 { 0x574d4C05, 0xffffffff, "WM9705,WM9710",     patch_wolfson05, NULL},
index 0746e9ccc20b1572ec1cae300b0178c1ad6f90e9..f4fbc795ee8140853305d4297e0818a48e01dd87 100644 (file)
@@ -3381,8 +3381,8 @@ static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
 }
 
 /* create a virtual master control and add slaves */
-int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
-                        const unsigned int *tlv, const char **slaves)
+static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
+                               const unsigned int *tlv, const char **slaves)
 {
        struct snd_kcontrol *kctl;
        const char **s;
index 7e3e8942d0733f01fa3b9d5363878f2f9bf2f665..974e05122f005f6d23d70fb1f593a94c017b0081 100644 (file)
@@ -94,7 +94,7 @@ enum azf_freq_t {
   AZF_FREQ(48000),
   AZF_FREQ(66200),
 #undef AZF_FREQ
-} AZF_FREQUENCIES;
+};
 
 /** recording area (see also: playback bit flag definitions) **/
 #define IDX_IO_REC_FLAGS       0x20 /* ??, PU:0x0000 */
@@ -210,7 +210,7 @@ enum azf_freq_t {
 
 enum {
        AZF_GAME_LEGACY_IO_PORT = 0x200
-} AZF_GAME_CONFIGS;
+};
 
 #define IDX_GAME_LEGACY_COMPATIBLE     0x00
        /* in some operation mode, writing anything to this port
index fbf1124f7c79d1609f594fdb786e0ec0e0b676ac..9bf95367c882b4fbe80558f254aa2b45456f9646 100644 (file)
@@ -522,7 +522,7 @@ static unsigned int snd_es1371_wait_src_ready(struct ensoniq * ensoniq)
                        return r;
                cond_resched();
        }
-       snd_printk(KERN_ERR "wait source ready timeout 0x%lx [0x%x]\n",
+       snd_printk(KERN_ERR "wait src ready timeout 0x%lx [0x%x]\n",
                   ES_REG(ensoniq, 1371_SMPRATE), r);
        return 0;
 }
@@ -1629,6 +1629,7 @@ static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
        memset(&ac97, 0, sizeof(ac97));
        ac97.private_data = ensoniq;
        ac97.private_free = snd_ensoniq_mixer_free_ac97;
+       ac97.pci = ensoniq->pci;
        ac97.scaps = AC97_SCAP_AUDIO;
        if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0)
                return err;
index 16715a68ba5e59c362b5ea3d3db252b4f022523d..ef9f072b47fcc65749729d22fa8e1390c1f8a8de 100644 (file)
@@ -1047,9 +1047,13 @@ static int azx_setup_periods(struct azx *chip,
        pos_adj = bdl_pos_adj[chip->dev_index];
        if (pos_adj > 0) {
                struct snd_pcm_runtime *runtime = substream->runtime;
+               int pos_align = pos_adj;
                pos_adj = (pos_adj * runtime->rate + 47999) / 48000;
                if (!pos_adj)
-                       pos_adj = 1;
+                       pos_adj = pos_align;
+               else
+                       pos_adj = ((pos_adj + pos_align - 1) / pos_align) *
+                               pos_align;
                pos_adj = frames_to_bytes(runtime, pos_adj);
                if (pos_adj >= period_bytes) {
                        snd_printk(KERN_WARNING "Too big adjustment %d\n",
index 2807bc840d26973f695d6be66c55b6bb5ac58717..add4e87e0b203a6ff8d9a52705158622550d6d79 100644 (file)
@@ -122,6 +122,8 @@ enum {
 /* ALC269 models */
 enum {
        ALC269_BASIC,
+       ALC269_ASUS_EEEPC_P703,
+       ALC269_ASUS_EEEPC_P901,
        ALC269_AUTO,
        ALC269_MODEL_LAST /* last tag */
 };
@@ -7905,6 +7907,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
+       SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), 
        SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */
        SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
        SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
@@ -10946,7 +10949,23 @@ static int patch_alc268(struct hda_codec *codec)
 
 static hda_nid_t alc269_adc_nids[1] = {
        /* ADC1 */
-       0x07,
+       0x08,
+};
+
+static struct hda_input_mux alc269_eeepc_dmic_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "i-Mic", 0x5 },
+               { "e-Mic", 0x0 },
+       },
+};
+
+static struct hda_input_mux alc269_eeepc_amic_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "i-Mic", 0x1 },
+               { "e-Mic", 0x0 },
+       },
 };
 
 #define alc269_modes           alc260_modes
@@ -10968,10 +10987,27 @@ static struct snd_kcontrol_new alc269_base_mixer[] = {
        { } /* end */
 };
 
+/* bind volumes of both NID 0x0c and 0x0d */
+static struct hda_bind_ctls alc269_epc_bind_vol = {
+       .ops = &snd_hda_bind_vol,
+       .values = {
+               HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
+               0
+       },
+};
+
+static struct snd_kcontrol_new alc269_eeepc_mixer[] = {
+       HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       HDA_BIND_VOL("LineOut Playback Volume", &alc269_epc_bind_vol),
+       HDA_CODEC_MUTE("LineOut Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       { } /* end */
+};
+
 /* capture mixer elements */
 static struct snd_kcontrol_new alc269_capture_mixer[] = {
-       HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                /* The multiple "Capture Source" controls confuse alsamixer
@@ -10987,6 +11023,13 @@ static struct snd_kcontrol_new alc269_capture_mixer[] = {
        { } /* end */
 };
 
+/* capture mixer elements */
+static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
+       HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+       { } /* end */
+};
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -10994,7 +11037,7 @@ static struct hda_verb alc269_init_verbs[] = {
        /*
         * Unmute ADC0 and set the default input to mic-in
         */
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 
        /* Mute input amps (PCBeep, Line In, Mic 1 & Mic 2) of the
         * analog-loopback mixer widget
@@ -11057,6 +11100,98 @@ static struct hda_verb alc269_init_verbs[] = {
        { }
 };
 
+static struct hda_verb alc269_eeepc_dmic_init_verbs[] = {
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
+       {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
+       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {}
+};
+
+static struct hda_verb alc269_eeepc_amic_init_verbs[] = {
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {}
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc269_speaker_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+       unsigned int bits;
+
+       present = snd_hda_codec_read(codec, 0x15, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+       bits = present ? AMP_IN_MUTE(0) : 0;
+       snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
+                                AMP_IN_MUTE(0), bits);
+       snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
+                                AMP_IN_MUTE(0), bits);
+}
+
+static void alc269_eeepc_dmic_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_codec_read(codec, 0x18, 0, AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_CONNECT_SEL,
+                           present ? 0 : 5);
+}
+
+static void alc269_eeepc_amic_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_codec_read(codec, 0x18, 0, AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           present ? AMP_IN_UNMUTE(0) : AMP_IN_MUTE(0));
+       snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           present ? AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1));
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc269_eeepc_dmic_unsol_event(struct hda_codec *codec,
+                                         unsigned int res)
+{
+       if ((res >> 26) == ALC880_HP_EVENT)
+               alc269_speaker_automute(codec);
+
+       if ((res >> 26) == ALC880_MIC_EVENT)
+               alc269_eeepc_dmic_automute(codec);
+}
+
+static void alc269_eeepc_dmic_inithook(struct hda_codec *codec)
+{
+       alc269_speaker_automute(codec);
+       alc269_eeepc_dmic_automute(codec);
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc269_eeepc_amic_unsol_event(struct hda_codec *codec,
+                                         unsigned int res)
+{
+       if ((res >> 26) == ALC880_HP_EVENT)
+               alc269_speaker_automute(codec);
+
+       if ((res >> 26) == ALC880_MIC_EVENT)
+               alc269_eeepc_amic_automute(codec);
+}
+
+static void alc269_eeepc_amic_inithook(struct hda_codec *codec)
+{
+       alc269_speaker_automute(codec);
+       alc269_eeepc_amic_automute(codec);
+}
+
 /* add playback controls from the parsed DAC table */
 static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec,
                                             const struct auto_pin_cfg *cfg)
@@ -11188,6 +11323,9 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        if (err < 0)
                return err;
 
+       spec->mixers[spec->num_mixers] = alc269_capture_mixer;
+       spec->num_mixers++;
+
        return 1;
 }
 
@@ -11215,12 +11353,16 @@ static const char *alc269_models[ALC269_MODEL_LAST] = {
 };
 
 static struct snd_pci_quirk alc269_cfg_tbl[] = {
+       SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
+                     ALC269_ASUS_EEEPC_P703),
+       SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
+                     ALC269_ASUS_EEEPC_P901),
        {}
 };
 
 static struct alc_config_preset alc269_presets[] = {
        [ALC269_BASIC] = {
-               .mixers = { alc269_base_mixer },
+               .mixers = { alc269_base_mixer, alc269_capture_mixer },
                .init_verbs = { alc269_init_verbs },
                .num_dacs = ARRAY_SIZE(alc269_dac_nids),
                .dac_nids = alc269_dac_nids,
@@ -11229,6 +11371,32 @@ static struct alc_config_preset alc269_presets[] = {
                .channel_mode = alc269_modes,
                .input_mux = &alc269_capture_source,
        },
+       [ALC269_ASUS_EEEPC_P703] = {
+               .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer },
+               .init_verbs = { alc269_init_verbs,
+                               alc269_eeepc_amic_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc269_dac_nids),
+               .dac_nids = alc269_dac_nids,
+               .hp_nid = 0x03,
+               .num_channel_mode = ARRAY_SIZE(alc269_modes),
+               .channel_mode = alc269_modes,
+               .input_mux = &alc269_eeepc_amic_capture_source,
+               .unsol_event = alc269_eeepc_amic_unsol_event,
+               .init_hook = alc269_eeepc_amic_inithook,
+       },
+       [ALC269_ASUS_EEEPC_P901] = {
+               .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer},
+               .init_verbs = { alc269_init_verbs,
+                               alc269_eeepc_dmic_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc269_dac_nids),
+               .dac_nids = alc269_dac_nids,
+               .hp_nid = 0x03,
+               .num_channel_mode = ARRAY_SIZE(alc269_modes),
+               .channel_mode = alc269_modes,
+               .input_mux = &alc269_eeepc_dmic_capture_source,
+               .unsol_event = alc269_eeepc_dmic_unsol_event,
+               .init_hook = alc269_eeepc_dmic_inithook,
+       },
 };
 
 static int patch_alc269(struct hda_codec *codec)
@@ -11282,8 +11450,6 @@ static int patch_alc269(struct hda_codec *codec)
 
        spec->adc_nids = alc269_adc_nids;
        spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
-       spec->mixers[spec->num_mixers] = alc269_capture_mixer;
-       spec->num_mixers++;
 
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC269_AUTO)
@@ -12994,6 +13160,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
        SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
        SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
+       SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC861VD_LENOVO),
        SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
        SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
        SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
index 08cb77f51880a31265c46cf66691715cfbf5dd55..7fdafcb0015d8e9030c13c27b9d060c16ff9b39d 100644 (file)
@@ -94,6 +94,9 @@ enum {
        STAC_INTEL_MAC_V3,
        STAC_INTEL_MAC_V4,
        STAC_INTEL_MAC_V5,
+       STAC_INTEL_MAC_AUTO, /* This model is selected if no module parameter
+                             * is given, one of the above models will be
+                             * chosen according to the subsystem id. */
        /* for backward compatibility */
        STAC_MACMINI,
        STAC_MACBOOK,
@@ -1483,6 +1486,7 @@ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
        [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs,
        [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs,
        [STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs,
+       [STAC_INTEL_MAC_AUTO] = intel_mac_v3_pin_configs,
        /* for backward compatibility */
        [STAC_MACMINI] = intel_mac_v3_pin_configs,
        [STAC_MACBOOK] = intel_mac_v5_pin_configs,
@@ -1505,6 +1509,7 @@ static const char *stac922x_models[STAC_922X_MODELS] = {
        [STAC_INTEL_MAC_V3] = "intel-mac-v3",
        [STAC_INTEL_MAC_V4] = "intel-mac-v4",
        [STAC_INTEL_MAC_V5] = "intel-mac-v5",
+       [STAC_INTEL_MAC_AUTO] = "intel-mac-auto",
        /* for backward compatibility */
        [STAC_MACMINI]  = "macmini",
        [STAC_MACBOOK]  = "macbook",
@@ -1576,9 +1581,9 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707,
                      "Intel D945P", STAC_D945GTP5),
        /* other systems  */
-       /* Apple Mac Mini (early 2006) */
+       /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */
        SND_PCI_QUIRK(0x8384, 0x7680,
-                     "Mac Mini", STAC_INTEL_MAC_V3),
+                     "Mac", STAC_INTEL_MAC_AUTO),
        /* Dell systems  */
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a7,
                      "unknown Dell", STAC_922X_DELL_D81),
@@ -3725,7 +3730,7 @@ static int patch_stac922x(struct hda_codec *codec)
        spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
                                                        stac922x_models,
                                                        stac922x_cfg_tbl);
-       if (spec->board_config == STAC_INTEL_MAC_V3) {
+       if (spec->board_config == STAC_INTEL_MAC_AUTO) {
                spec->gpio_mask = spec->gpio_dir = 0x03;
                spec->gpio_data = 0x03;
                /* Intel Macs have all same PCI SSID, so we need to check
@@ -3757,6 +3762,9 @@ static int patch_stac922x(struct hda_codec *codec)
                case 0x106b2200:
                        spec->board_config = STAC_INTEL_MAC_V5;
                        break;
+               default:
+                       spec->board_config = STAC_INTEL_MAC_V3;
+                       break;
                }
        }
 
index ba4b5c199f21b9fa97aa62cf0f6166309e00a901..9384702c7ebd7c09f0df6d4e25f9161ac854cc37 100644 (file)
@@ -231,7 +231,7 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
 
        /* if both TX and RX are idle, disable PSC */
        stat = au_readl(I2S_STAT(pscdata));
-       if (!(stat & (PSC_I2SSTAT_RB | PSC_I2SSTAT_RB))) {
+       if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) {
                au_writel(0, I2S_CFG(pscdata));
                au_sync();
                au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
index 9fc8edd82225cfe98dfbcb6aabadddf48eb1e9c5..1fb7f9a7aecd63dfa6ae6c71414e3702047a5c5a 100644 (file)
@@ -427,20 +427,20 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"HPOUTR", NULL, "Headphone PGA"},
        {"Headphone PGA", NULL, "Right HP Mixer"},
 
-       /* mono hp mixer */
-       {"Mono HP Mixer", NULL, "Left HP Mixer"},
-       {"Mono HP Mixer", NULL, "Right HP Mixer"},
+       /* mono mixer */
+       {"Mono Mixer", NULL, "Left HP Mixer"},
+       {"Mono Mixer", NULL, "Right HP Mixer"},
 
        /* Out3 Mux */
        {"Out3 Mux", "Left", "Left HP Mixer"},
        {"Out3 Mux", "Mono", "Phone Mixer"},
-       {"Out3 Mux", "Left + Right", "Mono HP Mixer"},
+       {"Out3 Mux", "Left + Right", "Mono Mixer"},
        {"Out 3 PGA", NULL, "Out3 Mux"},
        {"OUT3", NULL, "Out 3 PGA"},
 
        /* speaker Mux */
        {"Speaker Mux", "Speaker Mix", "Speaker Mixer"},
-       {"Speaker Mux", "Headphone Mix", "Mono HP Mixer"},
+       {"Speaker Mux", "Headphone Mix", "Mono Mixer"},
        {"Speaker PGA", NULL, "Speaker Mux"},
        {"LOUT2", NULL, "Speaker PGA"},
        {"ROUT2", NULL, "Speaker PGA"},
index 2c87061c2a6b4d7b9c35d7479d782462a0d8b3c1..820347c9ae4bbc5d5281e981e94f0cd27d2e28ae 100644 (file)
@@ -523,24 +523,6 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
                                continue;
                        }
 
-                       /* programmable gain/attenuation */
-                       if (w->id == snd_soc_dapm_pga) {
-                               int on;
-                               in = is_connected_input_ep(w);
-                               dapm_clear_walk(w->codec);
-                               out = is_connected_output_ep(w);
-                               dapm_clear_walk(w->codec);
-                               w->power = on = (out != 0 && in != 0) ? 1 : 0;
-
-                               if (!on)
-                                       dapm_set_pga(w, on); /* lower volume to reduce pops */
-                               dapm_update_bits(w);
-                               if (on)
-                                       dapm_set_pga(w, on); /* restore volume from zero */
-
-                               continue;
-                       }
-
                        /* pre and post event widgets */
                        if (w->id == snd_soc_dapm_pre) {
                                if (!w->event)
@@ -586,45 +568,56 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
                        power_change = (w->power == power) ? 0: 1;
                        w->power = power;
 
+                       if (!power_change)
+                               continue;
+
                        /* call any power change event handlers */
-                       if (power_change) {
-                               if (w->event) {
-                                       pr_debug("power %s event for %s flags %x\n",
-                                                w->power ? "on" : "off", w->name, w->event_flags);
-                                       if (power) {
-                                               /* power up event */
-                                               if (w->event_flags & SND_SOC_DAPM_PRE_PMU) {
-                                                       ret = w->event(w,
-                                                               NULL, SND_SOC_DAPM_PRE_PMU);
-                                                       if (ret < 0)
-                                                               return ret;
-                                               }
-                                               dapm_update_bits(w);
-                                               if (w->event_flags & SND_SOC_DAPM_POST_PMU){
-                                                       ret = w->event(w,
-                                                               NULL, SND_SOC_DAPM_POST_PMU);
-                                                       if (ret < 0)
-                                                               return ret;
-                                               }
-                                       } else {
-                                               /* power down event */
-                                               if (w->event_flags & SND_SOC_DAPM_PRE_PMD) {
-                                                       ret = w->event(w,
-                                                               NULL, SND_SOC_DAPM_PRE_PMD);
-                                                       if (ret < 0)
-                                                               return ret;
-                                               }
-                                               dapm_update_bits(w);
-                                               if (w->event_flags & SND_SOC_DAPM_POST_PMD) {
-                                                       ret = w->event(w,
-                                                               NULL, SND_SOC_DAPM_POST_PMD);
-                                                       if (ret < 0)
-                                                               return ret;
-                                               }
-                                       }
-                               } else
-                                       /* no event handler */
-                                       dapm_update_bits(w);
+                       if (w->event)
+                               pr_debug("power %s event for %s flags %x\n",
+                                        w->power ? "on" : "off",
+                                        w->name, w->event_flags);
+
+                       /* power up pre event */
+                       if (power && w->event &&
+                           (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
+                               ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
+                               if (ret < 0)
+                                       return ret;
+                       }
+
+                       /* power down pre event */
+                       if (!power && w->event &&
+                           (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
+                               ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
+                               if (ret < 0)
+                                       return ret;
+                       }
+
+                       /* Lower PGA volume to reduce pops */
+                       if (w->id == snd_soc_dapm_pga && !power)
+                               dapm_set_pga(w, power);
+
+                       dapm_update_bits(w);
+
+                       /* Raise PGA volume to reduce pops */
+                       if (w->id == snd_soc_dapm_pga && power)
+                               dapm_set_pga(w, power);
+
+                       /* power up post event */
+                       if (power && w->event &&
+                           (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
+                               ret = w->event(w,
+                                              NULL, SND_SOC_DAPM_POST_PMU);
+                               if (ret < 0)
+                                       return ret;
+                       }
+
+                       /* power down post event */
+                       if (!power && w->event &&
+                           (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
+                               ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
+                               if (ret < 0)
+                                       return ret;
                        }
                }
        }
index 904d7b7bd7800bf12152af6c96387e0a8dc882a1..a845890b680062365930b89a63ba4536c0fa6670 100644 (file)
@@ -902,7 +902,7 @@ static const struct file_operations kvm_vcpu_fops = {
  */
 static int create_vcpu_fd(struct kvm_vcpu *vcpu)
 {
-       int fd = anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu);
+       int fd = anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0);
        if (fd < 0)
                kvm_put_kvm(vcpu->kvm);
        return fd;
@@ -1261,7 +1261,7 @@ static int kvm_dev_ioctl_create_vm(void)
        kvm = kvm_create_vm();
        if (IS_ERR(kvm))
                return PTR_ERR(kvm);
-       fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm);
+       fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, 0);
        if (fd < 0)
                kvm_put_kvm(kvm);